From 80ec2382ea1dcadb49a784bb328186896df39e95 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 22 Oct 2025 23:52:14 +0300 Subject: [PATCH] ... --- mcc/mcc_angle.h | 13 ++- mcc/mcc_defaults.h | 8 +- mcc/mcc_netserver.h | 192 ++++++++++++++++++++++++++++++++++++-- mcc/mcc_netserver_proto.h | 86 +++++++++++++---- mcc/tests/netmsg_test.cpp | 2 +- 5 files changed, 266 insertions(+), 35 deletions(-) diff --git a/mcc/mcc_angle.h b/mcc/mcc_angle.h index c6caa25..c383866 100644 --- a/mcc/mcc_angle.h +++ b/mcc/mcc_angle.h @@ -504,6 +504,11 @@ class MccAngleLON : public MccAngle using MccAngle::MccAngle; }; +class MccAngleUnknown : public MccAngle +{ + using MccAngle::MccAngle; +}; + enum class MccCoordKind : size_t { COORDS_KIND_GENERIC = traits::mcc_type_hash, @@ -518,7 +523,8 @@ enum class MccCoordKind : size_t { COORDS_KIND_X = traits::mcc_type_hash, COORDS_KIND_Y = traits::mcc_type_hash, COORDS_KIND_LAT = traits::mcc_type_hash, - COORDS_KIND_LON = traits::mcc_type_hash + COORDS_KIND_LON = traits::mcc_type_hash, + COORDS_KIND_UKNOWN = traits::mcc_type_hash }; enum class MccCoordPairKind : size_t { @@ -529,7 +535,8 @@ enum class MccCoordPairKind : size_t { COORDS_KIND_AZZD = traits::mcc_type_pair_hash(), COORDS_KIND_AZALT = traits::mcc_type_pair_hash(), COORDS_KIND_XY = traits::mcc_type_pair_hash(), - COORDS_KIND_LATLON = traits::mcc_type_pair_hash() + COORDS_KIND_LATLON = traits::mcc_type_pair_hash(), + COORDS_KIND_UNKNOWN = traits::mcc_type_pair_hash() }; @@ -587,7 +594,7 @@ static constexpr MccCoordPairKind MccCoordStrToPairKind(R&& spair) : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_XY_STR) ? MccCoordPairKind::COORDS_KIND_XY : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_LATLON_STR) ? MccCoordPairKind::COORDS_KIND_LATLON : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_GENERIC_STR) ? MccCoordPairKind::COORDS_KIND_GENERIC - : MccCoordPairKind::COORDS_KIND_GENERIC; + : MccCoordPairKind::COORDS_KIND_UNKNOWN; } diff --git a/mcc/mcc_defaults.h b/mcc/mcc_defaults.h index dccb662..2e1eb92 100644 --- a/mcc/mcc_defaults.h +++ b/mcc/mcc_defaults.h @@ -96,7 +96,7 @@ public: return ep; } - MccCelestialCoordEpoch() : _MJD(J2000_MJD), _UTC(J2000_UTC), _JEpoch(2000.0) {} + MccCelestialCoordEpoch() : _UTC(J2000_UTC), _MJD(J2000_MJD), _JEpoch(2000.0) {} template bool fromCharRange(IR&& str) @@ -196,7 +196,7 @@ public: template friend MccCelestialCoordEpoch operator+(const MccCelestialCoordEpoch& lhs, const DT& dt) { - MccCelestialCoordEpoch ep; + MccCelestialCoordEpoch ep = lhs; ep += dt; return ep; @@ -210,7 +210,7 @@ public: template friend MccCelestialCoordEpoch operator-(const MccCelestialCoordEpoch& lhs, const DT& dt) { - MccCelestialCoordEpoch ep; + MccCelestialCoordEpoch ep = lhs; ep -= dt; return ep; @@ -330,7 +330,7 @@ protected: jd += 2400001.0; double s = 0.5, cs = 0.0; - double v[] = {f1, f2}; + // double v[] = {f1, f2}; auto lmd = [&](double v) { // double x = v; diff --git a/mcc/mcc_netserver.h b/mcc/mcc_netserver.h index 8256c42..aaa346f 100644 --- a/mcc/mcc_netserver.h +++ b/mcc/mcc_netserver.h @@ -826,26 +826,125 @@ public: : base_t(ctx, {}, std::forward(log_args)...) { base_t::_handleMessageFunc = [mount = std::move(mount), this](std::string_view command) { + using mount_error_t = decltype(mount)::error_t; + mount_error_t m_err; + MccNetMessage input_msg; MccNetMessage> output_msg; + std::error_code err{}; + if (auto ec = parseMessage(command, input_msg)) { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec); } else { - bool imsg_ok = true; if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange! - output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR)) { // ??!!! - output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) { this->restart(); - output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, - MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) { + m_err = mount.initMount(); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) { + m_err = mount.stopMount(); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) { + m_err = mount.slewToTarget(false); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) { + m_err = mount.slewToTarget(true); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) { + m_err = mount.trackTarget(); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) { + auto v = input_msg.paramValue(0); + if (v) { + _coordFormat = v.value(); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + } else { + err = v.error(); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDPREC_STR)) { + auto v = input_msg.paramValue(0); + if (v) { + _coordPrec = v.value(); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + } else { + err = v.error(); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TARGET_STR)) { + // by default return ICRS coordinates + MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; + + auto sz = input_msg.paramSize(); + if (sz) { // set or get operation + auto vc = input_msg.paramValue(0); // is it set operation? + if (vc) { // coordinates are given - set operation + auto m_err = mount.setPointingTarget(vc.value()); + if (m_err) { + // !!!!!!!!!!!!! + err = m_err; + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + } + } else { + auto vp = input_msg.paramValue(0); + if (vp) { // coordinate pair kind is given + cp.pair_kind = vp.value(); + err = coordsFromTelemetryData(mount, true, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, + MCC_COMMPROTO_KEYWORD_TARGET_STR, cp); + } + } else { // invalid command!!! + err = vp.error(); + } + } + } else { // get operation + err = coordsFromTelemetryData(mount, true, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, + cp); + } + } + + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOUNT_STR)) { + // by default return ICRS coordinates + MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; + + if (input_msg.paramSize()) { // ccordinate pair kind is given + auto vp = input_msg.paramValue(0); + if (vp) { // coordinate pair kind is given + cp.pair_kind = vp.value(); + err = coordsFromTelemetryData(mount, false, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, + MCC_COMMPROTO_KEYWORD_MOUNT_STR, cp); + } + } else { // invalid command!!! + err = vp.error(); + } + + } else { + err = coordsFromTelemetryData(mount, false, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR, + cp); + } + } + } else { + err = std::make_error_code(std::errc::invalid_argument); } - if (imsg_ok) { // send ACK - // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg); + if (m_err) { + // ?????!!!!!! + err = m_err; } + + if (err) { // send error description + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, err); + } + // else { // send ACK with copy of the input message + // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + // } } return output_msg; @@ -855,6 +954,9 @@ public: virtual ~MccGenericMountNetworkServer() {} protected: + MccNetMessageCoordFormat _coordFormat{MccNetMessageCoordFormat::CFMT_SGM}; // ouput coordinates format + MccNetMessageCoordPrec _coordPrec{2, 1}; + template std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg) { @@ -862,6 +964,82 @@ protected: return ec; } + + + std::error_code coordsFromTelemetryData(mcc_generic_mount_c auto& mount, + bool target, // true - target coordinates, false - mount coordinates + mcc_celestial_point_c auto& cp) + { + MccTelemetryData tdata; + + auto t_err = mount.telemetryData(&tdata); + if (t_err) { + // ??!!!! + return t_err; + } + + mcc_tp2tp(tdata.target.time_point, cp.time_point); + + switch (cp.pair_kind) { + case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS: + if (target) { + cp.X = tdata.target.RA_ICRS; + cp.Y = tdata.target.DEC_ICRS; + mcc_tp2tp(MccCelestialCoordEpoch::J2000_UTC, cp.time_point); + } // ??!!! + break; + case mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP: + if (target) { + cp.X = tdata.target.RA_APP; + cp.Y = tdata.target.DEC_APP; + } else { + cp.X = tdata.RA_APP; + cp.Y = tdata.DEC_APP; + } + + break; + case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP: + if (target) { + cp.X = tdata.target.HA; + cp.Y = tdata.target.DEC_APP; + } else { + cp.X = tdata.HA; + cp.Y = tdata.DEC_APP; + } + break; + case mcc::MccCoordPairKind::COORDS_KIND_AZZD: + if (target) { + cp.X = tdata.target.AZ; + cp.Y = tdata.target.ZD; + } else { + cp.X = tdata.AZ; + cp.Y = tdata.ZD; + } + break; + case mcc::MccCoordPairKind::COORDS_KIND_AZALT: + if (target) { + cp.X = tdata.target.AZ; + cp.Y = tdata.target.ALT; + } else { + cp.X = tdata.AZ; + cp.Y = tdata.ALT; + } + break; + case mcc::MccCoordPairKind::COORDS_KIND_XY: + if (target) { + cp.X = tdata.target.X; + cp.Y = tdata.target.Y; + } else { + cp.X = tdata.X; + cp.Y = tdata.Y; + } + break; + default: + return std::make_error_code(std::errc::invalid_argument); + } + + return {}; + } }; } // namespace mcc::network diff --git a/mcc/mcc_netserver_proto.h b/mcc/mcc_netserver_proto.h index cf0637a..246aa22 100644 --- a/mcc/mcc_netserver_proto.h +++ b/mcc/mcc_netserver_proto.h @@ -156,7 +156,7 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FI // arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT) // precision must be given as non-negative integer number // e.g. -// "COORDPREC 2 1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9) +// "COORDPREC 2,1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9) // static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC"; @@ -492,23 +492,25 @@ static_assert(mcc_netmsg_valid_keys_c, ""); template concept mcc_netmessage_c = requires(T t) { T(); }; + +/* helper types to format serialized celestial coordinates */ +/* it can be used as inputs in "construct" method or corresponded constructor */ + +// format of output (serialized) coordinates +enum class MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM }; + +// precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds) +struct MccNetMessageCoordPrec { + uint8_t hour_prec = 2; + uint8_t deg_prec = 1; +}; + + template class MccNetMessage { public: - /* helper types to format serialized celestial coordinates */ - /* it can be used as inputs in "construct" method or corresponded constructor */ - - // format of output (serialized) coordinates - enum MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM }; - - // precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds) - struct MccNetMessageCoordPrec { - uint8_t hour_prec = 2; - uint8_t deg_prec = 1; - }; - protected: class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer { @@ -599,6 +601,46 @@ protected: pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{}); mcc_copy_celestial_point(pt, &value); + } else if constexpr (std::same_as) { + value = MccCoordStrToPairKind(bytes); + if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) { + return std::make_error_code(std::errc::invalid_argument); + } + } else if constexpr (std::same_as) { + std::string v; + auto ec = (*this)(std::forward(bytes), v); + if (ec) { + return ec; + } + + if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR) == 0) { + value = MccNetMessageCoordFormat::CFMT_SGM; + } else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) { + value = MccNetMessageCoordFormat::CFMT_DEGREES; + } else { + return std::make_error_code(std::errc::invalid_argument); + } + } else if constexpr (std::same_as) { + std::vector v; + auto ec = (*this)(std::forward(bytes), v); + if (ec) { + return ec; + } + + auto hprec = v[0]; + value.hour_prec = hprec > 0 ? (hprec < std::numeric_limits::max() + ? hprec + : std::numeric_limits::max()) + : 2; + if (v.size() == 1) { + value.deg_prec = 1; + } else { + auto dprec = v[1]; + value.deg_prec = dprec > 0 ? dprec < std::numeric_limits::max() + ? dprec + : std::numeric_limits::max() + : 1; + } } else { return base_t::operator()(std::forward(bytes), value); } @@ -610,7 +652,7 @@ protected: class DefaultSerializer { - MccNetMessageCoordFormat _currentCoordFormat = MccNetMessage::CFMT_SGM; + MccNetMessageCoordFormat _currentCoordFormat = MccNetMessageCoordFormat::CFMT_SGM; MccNetMessageCoordPrec _currentCoordPrec{2, 1}; public: @@ -635,12 +677,12 @@ protected: std::ranges::copy(std::string(value), std::back_inserter(bytes)); } else if constexpr (traits::mcc_char_range) { std::ranges::copy(std::string(value.begin(), value.end()), std::back_inserter(bytes)); - } else if constexpr (std::same_as) { - std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes)); + // } else if constexpr (std::same_as) { + // std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes)); } else if constexpr (traits::mcc_time_duration_c) { (*this)(value.count(), bytes); } else if constexpr (mcc_celestial_point_c) { - if (_currentCoordFormat == MccNetMessage::CFMT_DEGREES) { + if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) { std::format_to(std::back_inserter(bytes), "{}{}{}", MccAngle(value.X).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccAngle(value.Y).degrees()); } else { @@ -683,7 +725,6 @@ protected: std::format_to(std::back_inserter(bytes), "{}{}{}{}{}", value.value(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.message(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.category().name()); - } else if constexpr (std::same_as) { } else if constexpr (std::formattable) { std::format_to(std::back_inserter(bytes), "{}", value); } else { @@ -751,8 +792,13 @@ public: } + size_t paramSize() const + { + return _params.size(); + } + template - R params(size_t start_idx, size_t Nelemes = std::numeric_limits::max()) + R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) requires(traits::mcc_view_or_output_char_range || traits::mcc_range_of_char_range) { if (start_idx >= _params.size()) { @@ -791,7 +837,7 @@ public: } } - std::string_view params(size_t start_idx, size_t Nelemes = std::numeric_limits::max()) + std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) { return params(start_idx, Nelemes); } diff --git a/mcc/tests/netmsg_test.cpp b/mcc/tests/netmsg_test.cpp index bee75b2..87c03a5 100644 --- a/mcc/tests/netmsg_test.cpp +++ b/mcc/tests/netmsg_test.cpp @@ -60,7 +60,7 @@ int main() .Y = mcc::MccAngle(67.9827148715, mcc::mcc_degrees)}; // msg2.construct("ACK", "MOUNT", msg2_t::CFMT_DEGREES, msg2_t::MccNetMessageCoordPrec{2, 3}, cpt); - msg2.construct("ACK", "MOUNT", msg2_t::MccNetMessageCoordPrec{2, 3}, cpt); + msg2.construct("ACK", "MOUNT", mcc::network::MccNetMessageCoordPrec{2, 3}, cpt); std::cout << "MSG2: " << msg2.byteRepr() << "\n"; auto cpt1 = msg2.paramValue(1); if (cpt1) {