From bc300bb3de57e3e0a9606c42d966f3ed26954fc3 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 29 Oct 2025 15:07:53 +0300 Subject: [PATCH] ... --- asibfm700/asibfm700_netserver.cpp | 39 ++- asibfm700/asibfm700_netserver.h | 60 ++++- mcc/mcc_generic_mount.h | 76 +++++- mcc/mcc_generics.h | 40 ++- mcc/mcc_netserver.h | 419 +++++++++++++++++++++--------- mcc/mcc_netserver_proto.h | 40 ++- 6 files changed, 508 insertions(+), 166 deletions(-) diff --git a/asibfm700/asibfm700_netserver.cpp b/asibfm700/asibfm700_netserver.cpp index 0306a6c..d10a9b2 100644 --- a/asibfm700/asibfm700_netserver.cpp +++ b/asibfm700/asibfm700_netserver.cpp @@ -6,10 +6,47 @@ namespace asibfm700 template Asibfm700MountNetServer::Asibfm700MountNetServer(asio::io_context& ctx, + Asibfm700Mount& mount, std::shared_ptr logger, const R& pattern_range) - : _base_t(ctx, [this](std::string_view msg) { return handleMessage(msg); }, std::move(logger), pattern_range) + : base_t(ctx, mount, std::move(logger), pattern_range) { + // to avoid possible compiler optimization (one needs to catch 'mount' strictly by reference) + auto* mount_ptr = &mount; + + base_t::_handleMessageFunc = [base_hndl_func = std::move(base_t::_handleMessageFunc), mount_ptr, + this](std::string_view command) { + using mount_error_t = typename Asibfm700Mount::error_t; + std::error_code err{}; + + Asibfm700NetMessage input_msg; + Asibfm700NetMessage output_msg; + + auto ec = parseMessage(command, input_msg); + + if (ec) { + output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec); + } else { + if (input_msg.withKey(ASIBFM700_COMMPROTO_KEYWORD_METEO_STR)) { + // what is operation type (set or get)? + if (input_msg.paramSize()) { // set operation + auto vp = input_msg.paramValue(0); + if (vp) { + mount_ptr->updateMeteoERFA(vp.value()); + } else { + output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, vp.error()); + } + } else { // get operation + output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, + ASIBFM700_COMMPROTO_KEYWORD_METEO_STR, mount_ptr->getStateERFA().meteo); + } + } else { + output_msg = base_t::handleMessage(input_msg, mount_ptr); + } + } + + return output_msg.byteRepr(); + }; } } // namespace asibfm700 diff --git a/asibfm700/asibfm700_netserver.h b/asibfm700/asibfm700_netserver.h index 2ee085c..61fbd20 100644 --- a/asibfm700/asibfm700_netserver.h +++ b/asibfm700/asibfm700_netserver.h @@ -4,6 +4,7 @@ #include #include "asibfm700_common.h" +#include "asibfm700_mount.h" namespace asibfm700 { @@ -57,11 +58,59 @@ struct Asibfm700NetMessageValidKeywords { }; template -class Asibfm700MountNetMessage : public mcc::network::MccNetMessage +class Asibfm700NetMessage : public mcc::network::MccNetMessage { protected: using base_t = mcc::network::MccNetMessage; + class serializer_t : public base_t::DefaultSerializer + { + public: + template + void operator()(const T& value, OR& bytes) + { + if constexpr (std::same_as) { + // serialize just like a vector + std::vector meteo{value.temperature, value.humidity, value.pressure}; + base_t::operator()(meteo, bytes); + } else { + base_t::operator()(value, bytes); + } + } + } _serializer; + + + class deserializer_t : public base_t::DefaultDeserializer + { + public: + template + std::error_code operator()(IR&& bytes, VT& value) + { + if constexpr (std::same_as) { + // deserialize just like a vector + + std::vector v; + auto ec = base_t::operator()(std::forward(bytes), v); + if (ec) { + return ec; + } + + if (v.size() < 3) { + return std::make_error_code(std::errc::invalid_argument); + } + + value.temperature = v[0]; + value.humidity = v[1]; + value.pressure = v[2]; + + return {}; + } else { + return base_t::operator()(std::forward(bytes), value); + } + } + } _deserializer; + + public: using base_t::base_t; @@ -69,7 +118,7 @@ public: template std::expected paramValue(size_t idx) { - return paramValue(idx, _defaultDeserilizer); + return paramValue(idx, _deserializer); } @@ -78,19 +127,20 @@ public: std::error_code construct(KT&& key, PTs&&... params) requires mcc::traits::mcc_output_char_range { - return construct(_defaultSerializer, std::forward(key), std::forward(params)...); + return construct(_serializer, std::forward(key), std::forward(params)...); } }; -class Asibfm700MountNetServer : public mcc::network::MccGenericNetworkServer +class Asibfm700MountNetServer : public mcc::network::MccGenericMountNetworkServer { - using _base_t = mcc::network::MccGenericNetworkServer; + using base_t = mcc::network::MccGenericMountNetworkServer; public: template Asibfm700MountNetServer(asio::io_context& ctx, + Asibfm700Mount& mount, std::shared_ptr logger, const R& pattern_range = Asibfm700Logger::LOGGER_DEFAULT_FORMAT); diff --git a/mcc/mcc_generic_mount.h b/mcc/mcc_generic_mount.h index 76efa62..a6be0ce 100644 --- a/mcc/mcc_generic_mount.h +++ b/mcc/mcc_generic_mount.h @@ -19,7 +19,8 @@ enum class MccGenericMountErrorCode : int { ERROR_HW_STOP, ERROR_HW_GETSTATE, ERROR_SET_TARGET, - ERROR_MOUNT_SLEW + ERROR_MOUNT_SLEW, + ERROR_MOUNT_TRACK }; enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT }; @@ -152,6 +153,9 @@ public: using typename SlewModelT::slewing_params_t; using typename TrackModelT::tracking_params_t; + + enum class mount_status_t : int { IDLE, INITIALIZATION, STOPPED, SLEWING, ADJUSTING, TRACKING, ERROR }; + MccGenericMount(HardwareT hardware, TelemetryT telemetry, PZoneContT pzone_cont, @@ -163,8 +167,10 @@ public: PZoneContT(std::move(pzone_cont)), SlewModelT(std::move(slew_model)), TrackModelT(std::move(track_model)), - LoggerT(std::move(logger)) + LoggerT(std::move(logger)), + _mountStatus(new mount_status_t) { + *_mountStatus = mount_status_t::IDLE; } MccGenericMount(MccGenericMount&&) = default; @@ -173,7 +179,10 @@ public: MccGenericMount& operator=(MccGenericMount&&) = default; MccGenericMount& operator=(const MccGenericMount&) = delete; - virtual ~MccGenericMount() = default; + virtual ~MccGenericMount() + { + stopMount(); + }; error_t stopMount() { @@ -184,11 +193,15 @@ public: auto hw_err = this->hardwareStop(); if (hw_err) { + *_mountStatus = mount_status_t::ERROR; + return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); } logInfo("Stop command was sent"); + *_mountStatus = mount_status_t::STOPPED; + return MccGenericMountErrorCode::ERROR_OK; } @@ -196,13 +209,19 @@ public: { logInfo("Start generic mount initialization ..."); + *_mountStatus = mount_status_t::INITIALIZATION; + auto hw_err = this->hardwareInit(); if (hw_err) { + *_mountStatus = mount_status_t::ERROR; + return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); } logInfo("Generic mount initialization was performed"); + *_mountStatus = mount_status_t::IDLE; + return MccGenericMountErrorCode::ERROR_OK; } @@ -231,17 +250,66 @@ public: // re-implements SlewModelT::slewToTarget to fetch input target coordinates from intermediate buffer error_t slewToTarget(bool slew_and_stop = false) { + *_mountStatus = mount_status_t::SLEWING; + auto err = TelemetryT::setPointingTarget(_enteredTargetCoordiniates); if (err) { + *_mountStatus = mount_status_t::ERROR; + return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_SET_TARGET); } + if (slew_and_stop) { + *_mountStatus = mount_status_t::IDLE; + } + return mcc_deduce_error_code(SlewModelT::slewToTarget(slew_and_stop), MccGenericMountErrorCode::ERROR_MOUNT_SLEW); } + error_t trackTarget() + { + auto err = TrackModelT::traclTarget(); + if (err) { + *_mountStatus = mount_status_t::ERROR; + + return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_MOUNT_TRACK); + } + + *_mountStatus = mount_status_t::TRACKING; + + return MccGenericMountErrorCode::ERROR_OK; + } + + + error_t stopSlewing() + { + *_mountStatus = mount_status_t::IDLE; + + SlewModelT::stopSlewing(); + + return MccGenericMountErrorCode::ERROR_OK; + } + + error_t stopTracking() + { + *_mountStatus = mount_status_t::IDLE; + + TrackModelT::stopTracking(); + + return MccGenericMountErrorCode::ERROR_OK; + } + + + MccGenericMount::mount_status_t mountStatus() const + { + return _mountStatus.get(); + } + protected: - MccCelestialPoint _enteredTargetCoordiniates; + MccCelestialPoint _enteredTargetCoordiniates{}; + + std::unique_ptr> _mountStatus; }; diff --git a/mcc/mcc_generics.h b/mcc/mcc_generics.h index c99c39a..356b961 100644 --- a/mcc/mcc_generics.h +++ b/mcc/mcc_generics.h @@ -975,7 +975,7 @@ concept mcc_all_controls_c = mcc_position_controls_c && mcc_telemetry_c && // 2) prohibited zones related methods // 3) slewing and tracking, stop and init mount methods template -concept mcc_generic_mount_c = mcc_telemetry_c && mcc_pzone_container_c && requires(T t) { +concept mcc_generic_mount_c = mcc_telemetry_c && mcc_pzone_container_c && requires(T t, const T t_const) { // requires mcc_error_c; // slew mount to target (it is assumed that the target coordinates are determined in the telemetry data) @@ -996,6 +996,42 @@ concept mcc_generic_mount_c = mcc_telemetry_c && mcc_pzone_container_c && // init mount { t.initMount() }; + + // + // minimal set of mount status mnemonic constants + // + requires requires(typename T::mount_status_t type) { + requires std::formattable< + std::conditional_t, + std::underlying_type_t, typename T::mount_status_t>, + char>; + + []() { + // mount initialization + static constexpr auto v1 = T::mount_status_t::INITIALIZATION; + + // IDLE + static constexpr auto v2 = T::mount_status_t::IDLE; + + // mount is in state after the stopMount() method invoking + static constexpr auto v3 = T::mount_status_t::STOPPED; + + // mount is slewing (move to given celestial point) + static constexpr auto v4 = T::mount_status_t::SLEWING; + + // mount is adjusting its position in the end of slewing + // (adjusting actual mount position to align with target celestial point at the end of slewing process) + static constexpr auto v5 = T::mount_status_t::ADJUSTING; + + // mount is tracking + static constexpr auto v6 = T::mount_status_t::TRACKING; + + // an error occured while mount operation + static constexpr auto v7 = T::mount_status_t::ERROR; + }(); + }; + + { t_const.mountStatus() } -> std::same_as; }; @@ -1011,6 +1047,4 @@ concept mcc_generic_fsm_mount_c = mcc_generic_mount_c && std::derived_from concept mcc_generic_fsm_log_mount_c = mcc_generic_mount_c && mcc_logger_c && std::derived_from; - - } // namespace mcc diff --git a/mcc/mcc_netserver.h b/mcc/mcc_netserver.h index 0b0f775..695bc9a 100644 --- a/mcc/mcc_netserver.h +++ b/mcc/mcc_netserver.h @@ -899,154 +899,317 @@ public: MccGenericMountNetworkServer(asio::io_context& ctx, MountT& mount, LoggerCtorArgsTs&&... log_args) : 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; + // to avoid possible compiler optimization (one needs to catch 'mount' strictly by reference) + auto* mount_ptr = &mount; + + base_t::_handleMessageFunc = [mount_ptr, this](std::string_view command) { + using mount_error_t = typename MountT::error_t; mount_error_t m_err; MccNetMessage input_msg; MccNetMessage output_msg; - std::error_code err{}; - - if (auto ec = parseMessage(command, input_msg)) { + auto ec = parseMessage(command, input_msg); + if (ec) { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec); } else { - if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange! - 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, command); - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) { - this->restart(); - output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) { - m_err = mount.initMount(); - if (m_err) { - err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT); - } - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) { - m_err = mount.stopMount(); - if (m_err) { - err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP); - } - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) { - m_err = mount.slewToTarget(false); - if (m_err) { - err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW); - } - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) { - m_err = mount.slewToTarget(true); - if (m_err) { - err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE); - } - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) { - m_err = mount.trackTarget(); - if (m_err) { - err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_TRACK); - } - } 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) { - if (m_err) { - err = mcc_deduce_error_code( - m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET); - } - } 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, - _coordFormat, _coordPrec, 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, - _coordFormat, _coordPrec, cp); - } - } - } else { - err = std::make_error_code(std::errc::invalid_argument); - } - - 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); - // } + output_msg = handleMessage(input_msg, mount_ptr); } return output_msg.byteRepr(); + + // std::error_code err{}; + + // if (auto ec = parseMessage(command, input_msg)) { + // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec); + // } else { + // if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange! + // 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, command); + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) { + // this->restart(); + // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command); + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) { + // m_err = mount_ptr->initMount(); + // if (m_err) { + // err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT); + // } + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) { + // m_err = mount_ptr->stopMount(); + // if (m_err) { + // err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP); + // } + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) { + // m_err = mount_ptr->slewToTarget(false); + // if (m_err) { + // err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW); + // } + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) { + // m_err = mount_ptr->slewToTarget(true); + // if (m_err) { + // err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE); + // } + // } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) { + // m_err = mount_ptr->trackTarget(); + // if (m_err) { + // err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_TRACK); + // } + // } 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_ptr->setPointingTarget(vc.value()); + // if (m_err) { + // if (m_err) { + // err = mcc_deduce_error_code( + // m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET); + // } + // } 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_ptr, 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_ptr, true, cp); + // if (!err) { + // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, + // MCC_COMMPROTO_KEYWORD_TARGET_STR, + // _coordFormat, _coordPrec, 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_ptr, 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_ptr, false, cp); + // if (!err) { + // output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, + // MCC_COMMPROTO_KEYWORD_MOUNT_STR, + // _coordFormat, _coordPrec, cp); + // } + // } + // } else { + // err = std::make_error_code(std::errc::invalid_argument); + // } + + // 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.byteRepr(); }; } virtual ~MccGenericMountNetworkServer() {} protected: - // MccNetMessageCoordFormat _coordFormat{MccNetMessageCoordFormat::CFMT_SGM}; // ouput coordinates format - // MccNetMessageCoordPrec _coordPrec{2, 1}; - MccCoordinateSerializer::SerializedCoordFormat _coordFormat{ MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM}; MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{2, 1}; + + template + RESULT_MSG_T handleMessage(const INPUT_MSG_T& input_msg, MountT* mount_ptr) + requires( + std::derived_from> && + std::derived_from>) + { + using mount_error_t = typename MountT::error_t; + mount_error_t m_err; + + RESULT_MSG_T output_msg; + + std::error_code err{}; + + if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange! + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR)) { // ??!!! + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) { + this->restart(); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STATUS_STR)) { + auto st = mount_ptr->status(); // according to mcc_generic_mount_c 'st' is formattable + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_STATUS_STR, st); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) { + m_err = mount_ptr->initMount(); + if (m_err) { + err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT); + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_INIT_STR); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) { + m_err = mount_ptr->stopMount(); + if (m_err) { + err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP); + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_STOP_STR); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) { + m_err = mount_ptr->slewToTarget(false); + if (m_err) { + err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW); + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SLEW_STR); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) { + m_err = mount_ptr->slewToTarget(true); + if (m_err) { + err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE); + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOVE_STR); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) { + m_err = mount_ptr->trackTarget(); + if (m_err) { + err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_TRACK); + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TRACK_STR); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) { + auto v = input_msg.template paramValue(0); + if (v) { + _coordFormat = v.value(); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } else { + err = v.error(); + } + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDPREC_STR)) { + auto v = input_msg.template paramValue(0); + if (v) { + _coordPrec = v.value(); + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } 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.template paramValue(0); // is it set operation? + if (vc) { // coordinates are given - set operation + auto m_err = mount_ptr->setPointingTarget(vc.value()); + if (m_err) { + if (m_err) { + err = mcc_deduce_error_code(m_err, + MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET); + } + } else { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); + } + } else { + auto vp = input_msg.template paramValue(0); + if (vp) { // coordinate pair kind is given + cp.pair_kind = vp.value(); + err = coordsFromTelemetryData(*mount_ptr, 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_ptr, true, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, + _coordFormat, _coordPrec, 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.template paramValue(0); + if (vp) { // coordinate pair kind is given + cp.pair_kind = vp.value(); + err = coordsFromTelemetryData(*mount_ptr, 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_ptr, false, cp); + if (!err) { + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR, + _coordFormat, _coordPrec, cp); + } + } + } else { + err = std::make_error_code(std::errc::invalid_argument); + } + + if (err) { // send error description + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, err); + } + + + return output_msg; + } + + template std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg) { diff --git a/mcc/mcc_netserver_proto.h b/mcc/mcc_netserver_proto.h index 2827ed9..ef68b40 100644 --- a/mcc/mcc_netserver_proto.h +++ b/mcc/mcc_netserver_proto.h @@ -493,18 +493,6 @@ 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 corresponding 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 @@ -537,7 +525,7 @@ protected: if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) { return std::make_error_code(std::errc::invalid_argument); } - } else if constexpr (std::same_as) { + } else if constexpr (std::same_as) { std::string v; auto ec = (*this)(std::forward(bytes), v); if (ec) { @@ -545,13 +533,13 @@ protected: } if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR) == 0) { - value = MccNetMessageCoordFormat::CFMT_SGM; + value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM; } else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) { - value = MccNetMessageCoordFormat::CFMT_DEGREES; + value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_DEGREES; } else { return std::make_error_code(std::errc::invalid_argument); } - } else if constexpr (std::same_as) { + } else if constexpr (std::same_as) { std::vector v; auto ec = (*this)(std::forward(bytes), v); if (ec) { @@ -683,8 +671,10 @@ public: // fromCharRange(msg); // } + virtual ~MccNetMessage() = default; + template - constexpr bool withKey(const KT& key) + constexpr bool withKey(const KT& key) const { if constexpr (std::is_pointer_v>) { return withKey(std::string_view{key}); @@ -719,7 +709,7 @@ public: } template - R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) + R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) const requires(traits::mcc_view_or_output_char_range || traits::mcc_range_of_char_range) { if (start_idx >= _params.size()) { @@ -758,13 +748,13 @@ public: } } - std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) + std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits::max()) const { return params(start_idx, Nelemes); } template - R param(size_t idx) + R param(size_t idx) const { if (idx >= _params.size()) { return {}; @@ -780,7 +770,7 @@ public: } } - std::string_view param(size_t idx) + std::string_view param(size_t idx) const { if (idx >= _params.size()) { return {}; @@ -791,7 +781,7 @@ public: template - std::expected paramValue(size_t idx, DeserFuncT&& deser_func) + std::expected paramValue(size_t idx, DeserFuncT&& deser_func) const { if (idx >= _params.size()) { return std::unexpected{std::make_error_code(std::errc::argument_out_of_domain)}; @@ -808,9 +798,9 @@ public: } template - std::expected paramValue(size_t idx) + std::expected paramValue(size_t idx) const { - return paramValue(idx, _defaultDeserilizer); + return paramValue(idx, _defaultDeserializer); } @@ -948,7 +938,7 @@ protected: BYTEREPR_T _msgBuffer{}; - inline static DefaultDeserializer _defaultDeserilizer{}; + inline static DefaultDeserializer _defaultDeserializer{}; DefaultSerializer _defaultSerializer{};