From bdfc5dbc1c5a7c11188cb7f9b60dafc37a25349a Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Sun, 26 Oct 2025 02:22:39 +0300 Subject: [PATCH] ... --- mcc/mcc_defaults.h | 302 +++++++++++++++++++++++++++++--------- mcc/tests/netmsg_test.cpp | 17 +++ 2 files changed, 250 insertions(+), 69 deletions(-) diff --git a/mcc/mcc_defaults.h b/mcc/mcc_defaults.h index ce2158e..669e886 100644 --- a/mcc/mcc_defaults.h +++ b/mcc/mcc_defaults.h @@ -501,6 +501,7 @@ struct MccPositionControls : CCTE_T, HARDWARE_T, PCM_T { static_assert(mcc_julday_c, ""); static_assert(mcc_celestial_point_c, ""); +static_assert(mcc_pointing_target_coord_c>, ""); static_assert(mcc_telemetry_data_c, ""); @@ -569,6 +570,30 @@ protected: return {}; } + + template + std::error_code parseHourRepr(const IR& bytes, double& ang_value) + { + std::optional ang; + ang = mcc::utils::parsAngleString(bytes, true); + if (ang) { + ang_value = MccAngle(ang.value(), MccDegreeTag{}); + } else { + return std::make_error_code(std::errc::invalid_argument); + } + } + + template + std::error_code parseDegreeRepr(const IR& bytes, double& ang_value) + { + std::optional ang; + ang = mcc::utils::parsAngleString(bytes); + if (ang) { + ang_value = MccAngle(ang.value(), MccDegreeTag{}); + } else { + return std::make_error_code(std::errc::invalid_argument); + } + } }; // base class @@ -774,12 +799,15 @@ public: pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{}); mcc_copy_celestial_point(pt, &value); + + return {}; } }; class MccEqtHrzCoordsSerializer : public MccCoordinateSerializer { +public: template void operator()(const T& value, OR& bytes) { @@ -826,85 +854,221 @@ class MccEqtHrzCoordsSerializer : public MccCoordinateSerializer class MccEqtHrzCoordsDeserializer : public MccCoordinateDeserializer { +public: template std::error_code operator()(IR&& bytes, T& value) { + // valid format: RA, DEC, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point + // in the case of sexagesimal input the X,Y coordinates will be interpretated + // according to value.pair_kind field + auto els = splitToElements(std::forward(bytes)); + if (els.size() < 10) { + return std::make_error_code(std::errc::invalid_argument); + } + + MccEqtHrzCoords pt; + pt.pair_kind = MccCoordStrToPairKind(els[8]); + if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) { + return std::make_error_code(std::errc::invalid_argument); + } + + auto err = parseTimePoint(els[9], pt); + if (err) { + return err; + } + + err = parseHourRepr(els[0], pt.RA_APP); + if (err) { + return err; + } + + err = parseDegreeRepr(els[1], pt.DEC_APP); + if (err) { + return err; + } + + err = parseHourRepr(els[2], pt.HA); + if (err) { + return err; + } + + err = parseDegreeRepr(els[4], pt.AZ); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], pt.ZD); + if (err) { + return err; + } + + err = parseDegreeRepr(els[6], pt.ALT); + if (err) { + return err; + } + + switch (value.pair_kind) { + case MccCoordPairKind::COORDS_KIND_RADEC_ICRS: + case MccCoordPairKind::COORDS_KIND_RADEC_APP: + case MccCoordPairKind::COORDS_KIND_HADEC_APP: + err = parseHourRepr(els[7], pt.X); + break; + default: + err = parseDegreeRepr(els[7], pt.X); + } + if (err) { + return err; + } + + err = parseDegreeRepr(els[8], pt.Y); + if (err) { + return err; + } + + mcc_copy_eqt_hrz_coord(pt, &value); + + return {}; } }; -/**/ +class MccPointingTargetSerializer : public MccCoordinateSerializer +{ +public: + template + void operator()(const T& value, OR& bytes) + { + // output format: RA_ICRS, DEC_ICRS, RA_APP, DEC_APP, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point + // in the case of sexagesimal output X,Y coordinates will be interpretated + // according to value.pair_kind field -static constexpr char MccCoordinateXFmt = 'x'; -static constexpr char MccCoordinateYFmt = 'y'; -static constexpr char MccCoordinateRA_ICRSFmt = 'R'; -static constexpr char MccCoordinateDEC_ICRSFmt = 'D'; -static constexpr char MccCoordinateRA_APPFmt = 'r'; -static constexpr char MccCoordinateDEC_APPFmt = 'd'; -static constexpr char MccCoordinateHAFmt = 'h'; -static constexpr char MccCoordinateAZFmt = 'a'; -static constexpr char MccCoordinateZDFmt = 'z'; -static constexpr char MccCoordinateALTFmt = 'A'; -static constexpr char MccCoordinateTMFmt = 't'; // time point -static constexpr char MccCoordinatePKFmt = 'p'; // pair kind + if (_currentFormat == SerializedCoordFormat::CFMT_DEGREES) { + toDegrees(bytes, value.RA_ICRS, value.DEC_ICRS); + } else if (_currentFormat == SerializedCoordFormat::CFMT_SGM) { + toSexagesimalHour(bytes, value.RA_ICRS); + std::format_to(std::back_inserter(bytes), "{}", _delimiter); + toSexagesimalDeg(bytes, value.DEC_APP); + } + + std::format_to(std::back_inserter(bytes), "{}", _delimiter); + + MccEqtHrzCoordsSerializer{}(value, bytes); + } +}; + +class MccPointingTargetDeserializer : public MccCoordinateDeserializer +{ +public: + template + std::error_code operator()(IR&& bytes, T& value) + { + // valid format: RA_ICRS, DEC_ICRS, RA_APP, DEC_APP, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point + // in the case of sexagesimal input the X,Y coordinates will be interpretated + // according to value.pair_kind field + + auto els = splitToElements(std::forward(bytes)); + if (els.size() < 12) { + return std::make_error_code(std::errc::invalid_argument); + } + + MccPointingTarget pt; + auto err = parseHourRepr(els[0], pt.RA_ICRS); + if (err) { + return err; + } + + err = parseDegreeRepr(els[1], pt.DEC_ICRS); + if (err) { + return err; + } + + err = MccEqtHrzCoordsDeserializer{}(std::string_view{els[2].begin(), els[11].end()}, pt); + if (err) { + return err; + } + + mcc_copy_pointing_target_coord(pt, &value); + + return {}; + } +}; + + +class MccTelemetryDataSerializer : public MccCoordinateSerializer +{ +public: + template + void operator()(const T& value, OR& bytes) + { + // output format: , speedX, speedY, pcmX, pcmY, refCorr, + + MccEqtHrzCoordsSerializer{}(value, bytes); + std::format_to(std::back_inserter(bytes), "{}", _delimiter); + + toDegrees(bytes, value.speedX, value.speedY, value.pcmX, value.pcmY, value.refCorr); + std::format_to(std::back_inserter(bytes), "{}", _delimiter); + + MccPointingTargetSerializer{}(value.target, bytes); + } +}; + + +class MccTelemetryDataDeserializer : public MccCoordinateDeserializer +{ +public: + template + std::error_code operator()(IR&& bytes, T& value) + { + // valid format: , speedX, speedY, pcmX, pcmY, refCorr, + + auto els = splitToElements(std::forward(bytes)); + if (els.size() < 12) { + return std::make_error_code(std::errc::invalid_argument); + } + + MccTelemetryData tdata; + auto err = MccEqtHrzCoordsDeserializer{}(std::string_view{els[0].begin(), els[11].end()}, tdata); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], tdata.speedX); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], tdata.speedY); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], tdata.pcmX); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], tdata.pcmY); + if (err) { + return err; + } + + err = parseDegreeRepr(els[5], tdata.refCorr); + if (err) { + return err; + } + + err = MccPointingTargetDeserializer{}(std::string_view{els[0].begin(), els[11].end()}, tdata.target); + if (err) { + return err; + } + + mcc_copy_telemetry_data(tdata, &value); + + return {}; + } +}; } // namespace mcc - - -template -struct std::formatter { - std::vector fmt_order; - - template - constexpr ParseContext::iterator parse(ParseContext& ctx) - { - bool do_fmt = false; - - for (auto it = ctx.begin(); it != ctx.end(); ++it) { - if (*it == '%' && !do_fmt) { - do_fmt = true; - continue; - } else { - throw std::format_error("Invalid format argument for celestial point"); - } - - switch (*it) { - case mcc::MccCoordinateXFmt: - case mcc::MccCoordinateYFmt: - case mcc::MccCoordinateRA_ICRSFmt: - case mcc::MccCoordinateDEC_ICRSFmt: - case mcc::MccCoordinateRA_APPFmt: - case mcc::MccCoordinateDEC_APPFmt: - case mcc::MccCoordinateHAFmt: - case mcc::MccCoordinateAZFmt: - case mcc::MccCoordinateZDFmt: - case mcc::MccCoordinateALTFmt: - case mcc::MccCoordinateTMFmt: - case mcc::MccCoordinatePKFmt: - fmt_order.push_back(*it); - do_fmt = false; - break; - default: - throw std::format_error("Invalid format argument for celestial point"); - } - } - } - - template - FmtContext::iterator format(mcc::mcc_celestial_point_c auto cp, FmtContext& ctx) const - { - std::ostringstream out; - - if (fmt_order.empty()) { - return ctx.out(); - } - - for (auto& el : fmt_order) { - } - - return std::ranges::copy(std::move(out).str(), ctx.out()).out; - } -}; diff --git a/mcc/tests/netmsg_test.cpp b/mcc/tests/netmsg_test.cpp index 87c03a5..87e6b0f 100644 --- a/mcc/tests/netmsg_test.cpp +++ b/mcc/tests/netmsg_test.cpp @@ -70,6 +70,23 @@ int main() std::cout << "\n\n\n"; + mcc::MccCelestialPointSerializer cpser; + mcc::MccCelestialPointDeserializer cpdser; + + std::string s; + cpser(cpt, s); + std::cout << "Serialized: " << s << "\n"; + + auto err = cpdser(s, cpt); + if (err) { + std::cout << "deserialization error: " << err.message() << "\n"; + } else { + std::cout << "Deserialized: tp = " << cpt.time_point << "; kind = " << mcc::MccCoordPairKindToStr(cpt.pair_kind) + << "\n"; + } + + std::cout << "\n\n\n"; + mcc::MccCelestialCoordEpoch cep; std::cout << "UTC: " << cep.UTC() << "\n";