From 4e08d985c93778aa2f2261acb56fce48c2eb9586 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 11 Feb 2026 18:22:06 +0300 Subject: [PATCH] ... --- CMakeLists.txt | 11 +- mcc_concepts.h | 9 +- mcc_deserializer.h | 39 +++++-- mcc_netserver.h | 219 ++++++++++++++++++++----------------- mcc_netserver_proto.h | 26 +++-- mcc_serialization_common.h | 2 +- mcc_serializer.h | 60 +++++++++- tests/mcc_netmsg_test.cpp | 14 ++- 8 files changed, 244 insertions(+), 136 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index beaa3ac..66326a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.14) +set(QT_CREATOR_SKIP_MAINTENANCE_TOOL_PROVIDER ON) + # ******* MOUNT CONTROL COMPONENTS ******* project(mcc LANGUAGES C CXX Fortran VERSION 0.1) @@ -48,6 +50,7 @@ if(USE_SPDLOG) find_package(spdlog CONFIG) if(NOT ${spdlog_FOUND}) + message(STATUS "\tfetch spdlog-lib ...") FetchContent_Declare( spdlog GIT_REPOSITORY "https://github.com/gabime/spdlog.git" @@ -59,7 +62,7 @@ if(USE_SPDLOG) "-DSPDLOG_USE_STD_FORMAT=ON -DSPDLOG_FMT_EXTERNAL=OFF" OVERRIDE_FIND_PACKAGE ) - find_package(spdlog CONFIG) + find_package(spdlog REQUIRED CONFIG) endif() endif() @@ -171,7 +174,7 @@ if(USE_ASIO) execute_process( WORKING_DIRECTORY ${asiolib_project_SOURCE_DIR}/asio - COMMAND ./configure --prefix=${asiolib_project_SOURCE_DIR} + COMMAND ./configure --prefix=${asiolib_project_SOURCE_DIR}/asio ) set(ENV{PKG_CONFIG_PATH} "${asiolib_project_SOURCE_DIR}/asio") @@ -250,6 +253,10 @@ if(USE_ASIO) target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ASIOLIB) endif() +if(USE_SPDLOG) + target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog) +endif() + if(BUILD_TESTS) add_executable(mcc_telemetry_test tests/mcc_telemetry_test.cpp) target_link_libraries(mcc_telemetry_test PRIVATE ${PROJECT_NAME}) diff --git a/mcc_concepts.h b/mcc_concepts.h index 26e91ef..249133c 100644 --- a/mcc_concepts.h +++ b/mcc_concepts.h @@ -968,10 +968,11 @@ concept mcc_movement_controls_c = requires(T t) { template concept mcc_mount_status_c = requires { []() { - [[maybe_unused]] static constexpr std::array arr = { - T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE, T::MOUNT_STATUS_INITIALIZATION, - T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_STOPPED, T::MOUNT_STATUS_SLEWING, - T::MOUNT_STATUS_ADJUSTING, T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING}; + [[maybe_unused]] + static constexpr std::array arr = {T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE, + T::MOUNT_STATUS_INITIALIZATION, T::MOUNT_STATUS_STOPPED, + T::MOUNT_STATUS_SLEWING, T::MOUNT_STATUS_ADJUSTING, + T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING}; }; // to ensure mount status is compile-time constants }; diff --git a/mcc_deserializer.h b/mcc_deserializer.h index ea1fa28..c372c7e 100644 --- a/mcc_deserializer.h +++ b/mcc_deserializer.h @@ -370,14 +370,36 @@ struct MccDeserializer : MccDeserializerBase { }; +template <> +struct MccDeserializer : MccDeserializerBase { + static constexpr std::string_view deserializerName{"MCC-COORDPAIR-DESERIALIZER"}; + + template + error_t operator ()( + traits::mcc_input_char_range auto const& input, + MccCoordPairKind& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + value = MccCoordStrToPairKind(input); + + if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) { + return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; + } + + return MccDeserializerErrorCode::ERROR_OK; + } +}; + + template <> struct MccDeserializer : MccDeserializerBase { static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"}; template - error_t operator()(traits::mcc_input_char_range auto const& input, - MccSerializedAngleFormatPrec& value, - ParamsT const& params = mcc_serialization_params_t{}) + error_t operator ()( + traits::mcc_input_char_range auto const& input, + MccSerializedAngleFormatPrec& value, + ParamsT const& params = mcc_serialization_params_t{}) { // valid format: hour_prec[deg_precdecimals] @@ -408,16 +430,17 @@ struct MccDeserializer : MccDeserializerBase { template <> struct MccDeserializer : MccDeserializerBase { - static constexpr std::string_view deserializerName{"MCC-COORD-PAIR-FORMAT-DESERIALIZER"}; + static constexpr std::string_view deserializerName{"MCC-COORDPAIR-FORMAT-DESERIALIZER"}; template - error_t operator()(traits::mcc_input_char_range auto const& input, - MccSerializedCoordPairFormat& value, - ParamsT const& params = mcc_serialization_params_t{}) + error_t operator ()( + traits::mcc_input_char_range auto const& input, + MccSerializedCoordPairFormat& value, + ParamsT const& params = mcc_serialization_params_t{}) { value = MccSerializedCoordPairFormatStrToValue(input); - if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN){ + if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN) { return MccDeserializerErrorCode::ERROR_OK; } else { return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; diff --git a/mcc_netserver.h b/mcc_netserver.h index daffd78..c46213f 100644 --- a/mcc_netserver.h +++ b/mcc_netserver.h @@ -37,7 +37,7 @@ -#include "mcc_generics.h" +#include "mcc_concepts.h" #include "mcc_netserver_endpoint.h" #include "mcc_netserver_proto.h" #include "mcc_traits.h" @@ -52,9 +52,10 @@ enum class MccGenericMountNetworkServerErrorCode : int { ERROR_MOUNT_STOP, ERROR_MOUNT_SET_TARGET, ERROR_MOUNT_GET_TELEMETRY, + ERROR_MOUNT_COORD_TRANSFORM, ERROR_MOUNT_SLEW, ERROR_MOUNT_MOVE, - ERROR_MOUNT_TRACK + ERROR_MOUNT_TRACK, }; struct MccGenericMountNetworkServerErrorCategory : std::error_category { @@ -78,6 +79,8 @@ struct MccGenericMountNetworkServerErrorCategory : std::error_category { return "mount set target error"; case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY: return "mount get telemetry error"; + case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_COORD_TRANSFORM: + return "coordinate transformation error"; case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW: return "mount slewing error"; case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE: @@ -977,9 +980,9 @@ public: } protected: - MccCoordinateSerializer::SerializedCoordFormat _coordFormat{ - MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM}; - MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{2, 1}; + MccSerializedCoordPairFormat _coordFormat{MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG}; + MccSerializedAngleFormatPrec _coordPrec{2, 1, 7}; + std::function _stopMountFunc{}; @@ -1041,44 +1044,51 @@ protected: 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(); + if (input_msg.paramSize()) { // set operation + 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 { // get operation + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_COORDFMT_STR, + _coordFormat); } } 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(); + if (input_msg.paramSize()) { // set operation + 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 { // get operation + output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_COORDPREC_STR, + _coordPrec); } } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TARGET_STR)) { - // by default return ICRS coordinates - MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; + impl::MccCoordPairKind pair_kind = impl::MccCoordPairKind::COORDS_KIND_UNKNOWN; + impl::MccSkyPoint sp; auto sz = input_msg.paramSize(); if (sz) { // set or get operation - auto vp = input_msg.template paramValue(0); // is it get operation? + auto vp = input_msg.template paramValue(0); // is it get operation? if (vp) { // coordinate pair kind is given, it is get operation - cp.pair_kind = vp.value(); - err = coordsFromTelemetryData(*mount_ptr, true, cp); + pair_kind = vp.value(); + err = coordsFromTelemetryData(mount_ptr, true, pair_kind, sp); if (!err) { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, - _coordFormat, _coordPrec, cp); + _coordFormat, _coordPrec, sp); } } else { // here a celestial point must be given - auto vc = input_msg.template paramValue(0); + auto vc = input_msg.template paramValue(0); if (vc) { // 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); - } + err = mcc_deduce_err(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET); } else { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); } @@ -1087,42 +1097,38 @@ protected: } } } else { // get operation - err = coordsFromTelemetryData(*mount_ptr, true, cp); + err = coordsFromTelemetryData(mount_ptr, true, pair_kind, sp); if (!err) { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, - _coordFormat, _coordPrec, cp); + _coordFormat, _coordPrec, sp); } } } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOUNT_STR)) { - // by default return ICRS coordinates - MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; + impl::MccCoordPairKind pair_kind = impl::MccCoordPairKind::COORDS_KIND_UNKNOWN; + impl::MccSkyPoint sp; if (input_msg.paramSize()) { // ccordinate pair kind is given - auto vp = input_msg.template paramValue(0); + 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, - _coordFormat, _coordPrec, cp); - } + pair_kind = vp.value(); } else { // invalid command!!! err = vp.error(); } + } - } else { - err = coordsFromTelemetryData(*mount_ptr, false, cp); + if (!err) { + err = coordsFromTelemetryData(mount_ptr, false, pair_kind, sp); if (!err) { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR, - _coordFormat, _coordPrec, cp); + _coordFormat, _coordPrec, sp); } } - } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TELEMETRY_STR)) { - MccTelemetryData tdata; - // auto t_err = mount_ptr->telemetryData(&tdata); - auto t_err = mount_ptr->waitForTelemetryData(&tdata); + } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TELEMETRY_STR)) { + typename MountT::telemetry_data_t tdata; + + auto t_err = mount_ptr->telemetryData(&tdata); if (t_err) { err = mcc_deduce_error_code(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY); } else { @@ -1166,79 +1172,90 @@ protected: } - std::error_code coordsFromTelemetryData(mcc_generic_mount_c auto& mount, + template + std::error_code coordsFromTelemetryData(MountT* mount, bool target, // true - target coordinates, false - mount coordinates - mcc_celestial_point_c auto& cp) + impl::MccCoordPairKind pair_kind, + mcc_skypoint_c auto& sp) { - MccTelemetryData tdata; + typename MountT::telemetry_data_t tdata; - auto t_err = mount.waitForTelemetryData(&tdata); - // auto t_err = mount.telemetryData(&tdata); + auto t_err = mount->telemetryData(&tdata); if (t_err) { - return mcc_deduce_error_code(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY); + return mcc_deduce_err(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY); } - mcc_tp2tp(tdata.target.time_point, cp.time_point); + auto get_coords = [&](T& cp) { + cp.setEpoch(tdata.mountPos.epoch()); - switch (cp.pair_kind) { - case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS: + if (target) { + auto err = tdata.targetPos.to(cp); + if (err) { + return mcc_deduced_err(err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_COORD_TRANSFORM); + } + } else { + auto err = tdata.mountPos.to(cp); + if (err) { + return mcc_deduced_err(err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_COORD_TRANSFORM); + } + } + + sp.from(cp); + + return MccGenericMountNetworkServerErrorCode::ERROR_OK; + }; + + switch (pair_kind) { + case impl::MccCoordPairKind::COORDS_KIND_RADEC_ICRS: { + impl::MccSkyRADEC_ICRS cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_RADEC_OBS: { + impl::MccSkyRADEC_OBS cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_HADEC_OBS: { + impl::MccSkyHADEC_OBS cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_RADEC_APP: { + impl::MccSkyRADEC_APP cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_HADEC_APP: { + impl::MccSkyHADEC_APP cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_AZZD: { + impl::MccSkyAZZD cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_AZALT: { + impl::MccSkyAZALT cp; + return get_coords(cp); + } break; + case impl::MccCoordPairKind::COORDS_KIND_XY: // interpretated as encoder coordinates + case impl::MccCoordPairKind::COORDS_KIND_GENERIC: { // interpretated as encoder coordinates 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; + // WARNING: STILL NOT IMPLEMENTED!!! } else { - cp.X = tdata.RA_APP; - cp.Y = tdata.DEC_APP; + sp.from(tdata.hwState.XY); } - break; - case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP: + return MccGenericMountNetworkServerErrorCode::ERROR_OK; + } break; + case impl::MccCoordPairKind::COORDS_KIND_UNKNOWN: { // interpretated as no transformation if (target) { - cp.X = tdata.target.HA; - cp.Y = tdata.target.DEC_APP; + sp = tdata.targetPos; } else { - cp.X = tdata.HA; - cp.Y = tdata.DEC_APP; + sp = tdata.mountPos; } - 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 {}; + return MccGenericMountNetworkServerErrorCode::ERROR_OK; } }; diff --git a/mcc_netserver_proto.h b/mcc_netserver_proto.h index 12dfe1d..f2709cd 100644 --- a/mcc_netserver_proto.h +++ b/mcc_netserver_proto.h @@ -10,9 +10,9 @@ #include -#include "mcc_utils.h" -#include "mcc_serializer.h" #include "mcc_deserializer.h" +#include "mcc_serializer.h" +#include "mcc_utils.h" namespace mcc::network { @@ -251,10 +251,8 @@ template specializations - struct DefaultSerializer - { + struct DefaultSerializer { template auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const { @@ -403,7 +401,13 @@ public: template std::expected paramValue(size_t idx, DeserFuncT&& deser_func) const { - static_assert(std::invocable, "INVALID DESERIALIZTION FUNCTION!"); + static_assert(std::invocable, + "INVALID DESERIALIZATION FUNCTION!"); + static_assert(std::same_as, + std::error_code>, + "INVALID DESERIALIZATION FUNCTION!"); if (idx >= _params.size()) { return std::unexpected{std::make_error_code(std::errc::value_too_large)}; @@ -422,7 +426,8 @@ public: template std::expected paramValue(size_t idx) const { - return paramValue(idx, impl::MccDeserializer{}); // use one of specialization of MccDeserializer templated class + return paramValue( + idx, impl::MccDeserializer{}); // use one of specialization of MccDeserializer templated class } @@ -562,13 +567,12 @@ protected: DefaultSerializer _defaultSerializer{}; - impl::mcc_serialization_params_t _serializationParams{.seq_delim{MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ}, .elem_delim{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ}}; + impl::mcc_serialization_params_t _serializationParams{.seq_delim{MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ}, + .elem_delim{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ}}; template void convertFunc(SerFuncT&& ser_func, std::vector& idx, const T& par, const Ts&... pars) - requires(!std::same_as, std::vector>) { - if constexpr (std::same_as) { _serializationParams.coordpair_format = par; } else if constexpr (std::same_as) { @@ -576,8 +580,6 @@ protected: } else { idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end())); - // convertFunc(std::forward(ser_func), idx, par); - std::forward(ser_func)(_msgBuffer, par, _serializationParams); idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end())); diff --git a/mcc_serialization_common.h b/mcc_serialization_common.h index 29da0f5..972e6b9 100644 --- a/mcc_serialization_common.h +++ b/mcc_serialization_common.h @@ -64,7 +64,7 @@ static constexpr MccSerializedAngleFormat MccSerializedAngleFormatStrToValue(R&& enum class MccSerializedCoordPairFormat { MCC_SERIALIZED_FORMAT_DEGREES, // both angles are in degrees as floating-point number - MCC_SERIALIZED_FORMAT_SXGM_HOURDEG, // X is in hour and Y is in degree sexagesimal representation + MCC_SERIALIZED_FORMAT_SXGM_HOURDEG, // X is in hour (if RA or HA) and Y is in degree sexagesimal representation MCC_SERIALIZED_FORMAT_SXGM_DEGDEG, // both angles are in sexagesimal degrees MCC_SERIALIZED_FORMAT_UNKNOWN }; diff --git a/mcc_serializer.h b/mcc_serializer.h index 021d13f..73132d4 100644 --- a/mcc_serializer.h +++ b/mcc_serializer.h @@ -228,7 +228,9 @@ struct MccSerializer : MccSerializerBase { VT const& value, ParamsT const& params = mcc_serialization_params_t{}) { - std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(value)); + // std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(value)); + auto tp = std::chrono::round(value); + std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(tp)); return MccSerializerErrorCode::ERROR_OK; } @@ -249,9 +251,14 @@ struct MccSerializer : MccSerializerBase { std::string sgm; switch (params.angle_format) { - case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES: + case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES: { v *= MCC_RADS_TO_DEGRESS; - return MccSerializer{}(output, v, params); + std::string_view fmt = "{:." + std::to_string(params.angle_prec.decimals) + "f}"; + std::vformat_to(std::back_inserter(output), fmt, std::make_format_args(v)); + + return MccSerializerErrorCode::ERROR_OK; + } + // return MccSerializer{}(output, v, params); case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS: if (params.norm_sxgm) { sgm = utils::rad2sxg(v, false, params.angle_prec.deg_prec); @@ -716,6 +723,53 @@ struct MccSerializer : MccSerializerBase { }; + +template <> +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-COORDPAIR-FORMAT-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, + MccSerializedCoordPairFormat const& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + std::ranges::copy(MccSerializedCoordPairFormatToStr(value), std::back_inserter(output)); + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +template <> +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-ANGLE-FORMAT-PREC-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, + MccSerializedAngleFormatPrec const& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + auto err = MccSerializer{}(output, value.hour_prec, params); + if (!err) { + auto err = MccSerializer{}(output, value.deg_prec, params); + if (!err) { + auto err = MccSerializer{}(output, value.decimals, params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + } else { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + } else { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + + static_assert(mcc_serializer_c>, "!!!"); } // namespace mcc::impl diff --git a/tests/mcc_netmsg_test.cpp b/tests/mcc_netmsg_test.cpp index f06a691..e463abc 100644 --- a/tests/mcc_netmsg_test.cpp +++ b/tests/mcc_netmsg_test.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include @@ -24,7 +24,7 @@ int main() msg2_t msg2("ACK", 12.43298042, "EEE", std::chrono::seconds(10), vd); // msg2_t msg2("ACK"); - std::println("msg.bytes = <{}>",msg2.byteRepr()); + std::println("msg.bytes = <{}>", msg2.byteRepr()); std::println("msg.key = <{}>", msg2.keyword()); std::println("msg.par[1] = <{}>", msg2.param(1)); std::println("msg.par[2] = <{}>", msg2.param(2)); @@ -58,16 +58,20 @@ int main() mcc::impl::MccSkyPoint spt(mcc::impl::MccSkyRADEC_APP{"10:00:00.0"_hms, 12.098687_degs}); - msg2.construct("ACK", "MOUNT", spt); + msg2.construct("ACK", "MOUNT", mcc::MccSerializedAngleFormatPrec{3, 2}, spt); std::println("msg2.bytes = <{}>", msg2.byteRepr()); auto spt_d = msg2.paramValue(1); - if (spt_d){ - std::println("msg2.parvalue(1).epoch() = {}", spt_d->epoch().MJD()+mcc::MCC_MJD_ZERO); + if (spt_d) { + std::println("msg2.parvalue(1).pairKind() = {}", MccCoordPairKindToStr(spt_d->pairKind())); + std::println("msg2.parvalue(1).epoch() = {}", spt_d->epoch().MJD() + mcc::MCC_MJD_ZERO); } else { std::println("cannot deserialize MccSkyPoint value!"); } + msg2.construct("ACK", "MOUNT", mcc::MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES, spt); + std::println("msg2.bytes = <{}>", msg2.byteRepr()); + return 0; }