This commit is contained in:
2026-02-11 18:22:06 +03:00
parent 652fbd0890
commit 4e08d985c9
8 changed files with 244 additions and 136 deletions

View File

@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.14)
set(QT_CREATOR_SKIP_MAINTENANCE_TOOL_PROVIDER ON)
# ******* MOUNT CONTROL COMPONENTS ******* # ******* MOUNT CONTROL COMPONENTS *******
project(mcc LANGUAGES C CXX Fortran VERSION 0.1) project(mcc LANGUAGES C CXX Fortran VERSION 0.1)
@@ -48,6 +50,7 @@ if(USE_SPDLOG)
find_package(spdlog CONFIG) find_package(spdlog CONFIG)
if(NOT ${spdlog_FOUND}) if(NOT ${spdlog_FOUND})
message(STATUS "\tfetch spdlog-lib ...")
FetchContent_Declare( FetchContent_Declare(
spdlog spdlog
GIT_REPOSITORY "https://github.com/gabime/spdlog.git" GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
@@ -59,7 +62,7 @@ if(USE_SPDLOG)
"-DSPDLOG_USE_STD_FORMAT=ON -DSPDLOG_FMT_EXTERNAL=OFF" "-DSPDLOG_USE_STD_FORMAT=ON -DSPDLOG_FMT_EXTERNAL=OFF"
OVERRIDE_FIND_PACKAGE OVERRIDE_FIND_PACKAGE
) )
find_package(spdlog CONFIG) find_package(spdlog REQUIRED CONFIG)
endif() endif()
endif() endif()
@@ -171,7 +174,7 @@ if(USE_ASIO)
execute_process( execute_process(
WORKING_DIRECTORY ${asiolib_project_SOURCE_DIR}/asio 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") 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) target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ASIOLIB)
endif() endif()
if(USE_SPDLOG)
target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog)
endif()
if(BUILD_TESTS) if(BUILD_TESTS)
add_executable(mcc_telemetry_test tests/mcc_telemetry_test.cpp) add_executable(mcc_telemetry_test tests/mcc_telemetry_test.cpp)
target_link_libraries(mcc_telemetry_test PRIVATE ${PROJECT_NAME}) target_link_libraries(mcc_telemetry_test PRIVATE ${PROJECT_NAME})

View File

@@ -968,10 +968,11 @@ concept mcc_movement_controls_c = requires(T t) {
template <typename T> template <typename T>
concept mcc_mount_status_c = requires { concept mcc_mount_status_c = requires {
[]() { []() {
[[maybe_unused]] static constexpr std::array arr = { [[maybe_unused]]
T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE, T::MOUNT_STATUS_INITIALIZATION, static constexpr std::array arr = {T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE,
T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_STOPPED, T::MOUNT_STATUS_SLEWING, T::MOUNT_STATUS_INITIALIZATION, T::MOUNT_STATUS_STOPPED,
T::MOUNT_STATUS_ADJUSTING, T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING}; T::MOUNT_STATUS_SLEWING, T::MOUNT_STATUS_ADJUSTING,
T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING};
}; // to ensure mount status is compile-time constants }; // to ensure mount status is compile-time constants
}; };

View File

@@ -370,14 +370,36 @@ struct MccDeserializer<VT> : MccDeserializerBase {
}; };
template <>
struct MccDeserializer<MccCoordPairKind> : MccDeserializerBase {
static constexpr std::string_view deserializerName{"MCC-COORDPAIR-DESERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
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 <> template <>
struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase { struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"}; static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t> template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_input_char_range auto const& input, error_t operator ()(
MccSerializedAngleFormatPrec& value, traits::mcc_input_char_range auto const& input,
ParamsT const& params = mcc_serialization_params_t{}) MccSerializedAngleFormatPrec& value,
ParamsT const& params = mcc_serialization_params_t{})
{ {
// valid format: hour_prec[<params.elem_delim>deg_prec<params.elem_delim>decimals] // valid format: hour_prec[<params.elem_delim>deg_prec<params.elem_delim>decimals]
@@ -408,16 +430,17 @@ struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
template <> template <>
struct MccDeserializer<MccSerializedCoordPairFormat> : MccDeserializerBase { struct MccDeserializer<MccSerializedCoordPairFormat> : MccDeserializerBase {
static constexpr std::string_view deserializerName{"MCC-COORD-PAIR-FORMAT-DESERIALIZER"}; static constexpr std::string_view deserializerName{"MCC-COORDPAIR-FORMAT-DESERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t> template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_input_char_range auto const& input, error_t operator ()(
MccSerializedCoordPairFormat& value, traits::mcc_input_char_range auto const& input,
ParamsT const& params = mcc_serialization_params_t{}) MccSerializedCoordPairFormat& value,
ParamsT const& params = mcc_serialization_params_t{})
{ {
value = MccSerializedCoordPairFormatStrToValue(input); value = MccSerializedCoordPairFormatStrToValue(input);
if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN){ if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN) {
return MccDeserializerErrorCode::ERROR_OK; return MccDeserializerErrorCode::ERROR_OK;
} else { } else {
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;

View File

@@ -37,7 +37,7 @@
#include "mcc_generics.h" #include "mcc_concepts.h"
#include "mcc_netserver_endpoint.h" #include "mcc_netserver_endpoint.h"
#include "mcc_netserver_proto.h" #include "mcc_netserver_proto.h"
#include "mcc_traits.h" #include "mcc_traits.h"
@@ -52,9 +52,10 @@ enum class MccGenericMountNetworkServerErrorCode : int {
ERROR_MOUNT_STOP, ERROR_MOUNT_STOP,
ERROR_MOUNT_SET_TARGET, ERROR_MOUNT_SET_TARGET,
ERROR_MOUNT_GET_TELEMETRY, ERROR_MOUNT_GET_TELEMETRY,
ERROR_MOUNT_COORD_TRANSFORM,
ERROR_MOUNT_SLEW, ERROR_MOUNT_SLEW,
ERROR_MOUNT_MOVE, ERROR_MOUNT_MOVE,
ERROR_MOUNT_TRACK ERROR_MOUNT_TRACK,
}; };
struct MccGenericMountNetworkServerErrorCategory : std::error_category { struct MccGenericMountNetworkServerErrorCategory : std::error_category {
@@ -78,6 +79,8 @@ struct MccGenericMountNetworkServerErrorCategory : std::error_category {
return "mount set target error"; return "mount set target error";
case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY: case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY:
return "mount get telemetry error"; return "mount get telemetry error";
case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_COORD_TRANSFORM:
return "coordinate transformation error";
case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW: case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW:
return "mount slewing error"; return "mount slewing error";
case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE: case MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE:
@@ -977,9 +980,9 @@ public:
} }
protected: protected:
MccCoordinateSerializer::SerializedCoordFormat _coordFormat{ MccSerializedCoordPairFormat _coordFormat{MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG};
MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM}; MccSerializedAngleFormatPrec _coordPrec{2, 1, 7};
MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{2, 1};
std::function<void()> _stopMountFunc{}; std::function<void()> _stopMountFunc{};
@@ -1041,44 +1044,51 @@ protected:
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TRACK_STR); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TRACK_STR);
} }
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) { } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) {
auto v = input_msg.template paramValue<MccCoordinateSerializer::SerializedCoordFormat>(0); if (input_msg.paramSize()) { // set operation
if (v) { auto v = input_msg.template paramValue<MccSerializedCoordPairFormat>(0);
_coordFormat = v.value(); if (v) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); _coordFormat = v.value();
} else { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
err = v.error(); } 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)) { } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDPREC_STR)) {
auto v = input_msg.template paramValue<MccCoordinateSerializer::SexagesimalCoordPrec>(0); if (input_msg.paramSize()) { // set operation
if (v) { auto v = input_msg.template paramValue<MccSerializedAngleFormatPrec>(0);
_coordPrec = v.value(); if (v) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); _coordPrec = v.value();
} else { output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
err = v.error(); } 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)) { } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TARGET_STR)) {
// by default return ICRS coordinates impl::MccCoordPairKind pair_kind = impl::MccCoordPairKind::COORDS_KIND_UNKNOWN;
MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; impl::MccSkyPoint sp;
auto sz = input_msg.paramSize(); auto sz = input_msg.paramSize();
if (sz) { // set or get operation if (sz) { // set or get operation
auto vp = input_msg.template paramValue<MccCoordPairKind>(0); // is it get operation? auto vp = input_msg.template paramValue<impl::MccCoordPairKind>(0); // is it get operation?
if (vp) { // coordinate pair kind is given, it is get operation if (vp) { // coordinate pair kind is given, it is get operation
cp.pair_kind = vp.value(); pair_kind = vp.value();
err = coordsFromTelemetryData(*mount_ptr, true, cp); err = coordsFromTelemetryData(mount_ptr, true, pair_kind, sp);
if (!err) { if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, 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 } else { // here a celestial point must be given
auto vc = input_msg.template paramValue<MccCelestialPoint>(0); auto vc = input_msg.template paramValue<impl::MccSkyPoint>(0);
if (vc) { // set operation if (vc) { // set operation
auto m_err = mount_ptr->setPointingTarget(vc.value()); auto m_err = mount_ptr->setPointingTarget(vc.value());
if (m_err) { if (m_err) {
if (m_err) { err = mcc_deduce_err(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET);
err = mcc_deduce_error_code(
m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET);
}
} else { } else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
} }
@@ -1087,42 +1097,38 @@ protected:
} }
} }
} else { // get operation } else { // get operation
err = coordsFromTelemetryData(*mount_ptr, true, cp); err = coordsFromTelemetryData(mount_ptr, true, pair_kind, sp);
if (!err) { if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, 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)) { } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOUNT_STR)) {
// by default return ICRS coordinates impl::MccCoordPairKind pair_kind = impl::MccCoordPairKind::COORDS_KIND_UNKNOWN;
MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; impl::MccSkyPoint sp;
if (input_msg.paramSize()) { // ccordinate pair kind is given if (input_msg.paramSize()) { // ccordinate pair kind is given
auto vp = input_msg.template paramValue<MccCoordPairKind>(0); auto vp = input_msg.template paramValue<impl::MccCoordPairKind>(0);
if (vp) { // coordinate pair kind is given if (vp) { // coordinate pair kind is given
cp.pair_kind = vp.value(); 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);
}
} else { // invalid command!!! } else { // invalid command!!!
err = vp.error(); err = vp.error();
} }
}
} else { if (!err) {
err = coordsFromTelemetryData(*mount_ptr, false, cp); err = coordsFromTelemetryData(mount_ptr, false, pair_kind, sp);
if (!err) { if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR, 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); } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TELEMETRY_STR)) {
auto t_err = mount_ptr->waitForTelemetryData(&tdata); typename MountT::telemetry_data_t tdata;
auto t_err = mount_ptr->telemetryData(&tdata);
if (t_err) { if (t_err) {
err = mcc_deduce_error_code(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY); err = mcc_deduce_error_code(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY);
} else { } else {
@@ -1166,79 +1172,90 @@ protected:
} }
std::error_code coordsFromTelemetryData(mcc_generic_mount_c auto& mount, template <mcc_generic_mount_c MountT>
std::error_code coordsFromTelemetryData(MountT* mount,
bool target, // true - target coordinates, false - mount coordinates 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) { 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 = [&]<mcc_coord_pair_c T>(T& cp) {
cp.setEpoch(tdata.mountPos.epoch());
switch (cp.pair_kind) { if (target) {
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS: 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) { if (target) {
cp.X = tdata.target.RA_ICRS; // WARNING: STILL NOT IMPLEMENTED!!!
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 { } else {
cp.X = tdata.RA_APP; sp.from(tdata.hwState.XY);
cp.Y = tdata.DEC_APP;
} }
break; return MccGenericMountNetworkServerErrorCode::ERROR_OK;
case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP: } break;
case impl::MccCoordPairKind::COORDS_KIND_UNKNOWN: { // interpretated as no transformation
if (target) { if (target) {
cp.X = tdata.target.HA; sp = tdata.targetPos;
cp.Y = tdata.target.DEC_APP;
} else { } else {
cp.X = tdata.HA; sp = tdata.mountPos;
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: default:
return std::make_error_code(std::errc::invalid_argument); return std::make_error_code(std::errc::invalid_argument);
} }
return {}; return MccGenericMountNetworkServerErrorCode::ERROR_OK;
} }
}; };

View File

@@ -10,9 +10,9 @@
#include <string_view> #include <string_view>
#include "mcc_utils.h"
#include "mcc_serializer.h"
#include "mcc_deserializer.h" #include "mcc_deserializer.h"
#include "mcc_serializer.h"
#include "mcc_utils.h"
namespace mcc::network namespace mcc::network
{ {
@@ -251,10 +251,8 @@ template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
class MccNetMessage class MccNetMessage
{ {
protected: protected:
// just a wrapper class to hold MccSerializer<T> specializations // just a wrapper class to hold MccSerializer<T> specializations
struct DefaultSerializer struct DefaultSerializer {
{
template <traits::mcc_output_char_range OR, typename T> template <traits::mcc_output_char_range OR, typename T>
auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const
{ {
@@ -403,7 +401,13 @@ public:
template <typename T, typename DeserFuncT> template <typename T, typename DeserFuncT>
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const
{ {
static_assert(std::invocable<DeserFuncT, typename decltype(_params)::value_type const&, T&, impl::mcc_serialization_params_t const&>, "INVALID DESERIALIZTION FUNCTION!"); static_assert(std::invocable<DeserFuncT, typename decltype(_params)::value_type const&, T&,
impl::mcc_serialization_params_t const&>,
"INVALID DESERIALIZATION FUNCTION!");
static_assert(std::same_as<std::invoke_result_t<DeserFuncT, typename decltype(_params)::value_type const&, T&,
impl::mcc_serialization_params_t const&>,
std::error_code>,
"INVALID DESERIALIZATION FUNCTION!");
if (idx >= _params.size()) { if (idx >= _params.size()) {
return std::unexpected{std::make_error_code(std::errc::value_too_large)}; return std::unexpected{std::make_error_code(std::errc::value_too_large)};
@@ -422,7 +426,8 @@ public:
template <typename T> template <typename T>
std::expected<T, std::error_code> paramValue(size_t idx) const std::expected<T, std::error_code> paramValue(size_t idx) const
{ {
return paramValue<T>(idx, impl::MccDeserializer<T>{}); // use one of specialization of MccDeserializer templated class return paramValue<T>(
idx, impl::MccDeserializer<T>{}); // use one of specialization of MccDeserializer templated class
} }
@@ -562,13 +567,12 @@ protected:
DefaultSerializer _defaultSerializer{}; 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 <typename SerFuncT, typename T, typename... Ts> template <typename SerFuncT, typename T, typename... Ts>
void convertFunc(SerFuncT&& ser_func, std::vector<size_t>& idx, const T& par, const Ts&... pars) void convertFunc(SerFuncT&& ser_func, std::vector<size_t>& idx, const T& par, const Ts&... pars)
requires(!std::same_as<std::remove_cvref_t<SerFuncT>, std::vector<size_t>>)
{ {
if constexpr (std::same_as<T, MccSerializedCoordPairFormat>) { if constexpr (std::same_as<T, MccSerializedCoordPairFormat>) {
_serializationParams.coordpair_format = par; _serializationParams.coordpair_format = par;
} else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) { } else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) {
@@ -576,8 +580,6 @@ protected:
} else { } else {
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end())); idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
// convertFunc(std::forward<SerFuncT>(ser_func), idx, par);
std::forward<SerFuncT>(ser_func)(_msgBuffer, par, _serializationParams); std::forward<SerFuncT>(ser_func)(_msgBuffer, par, _serializationParams);
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end())); idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));

View File

@@ -64,7 +64,7 @@ static constexpr MccSerializedAngleFormat MccSerializedAngleFormatStrToValue(R&&
enum class MccSerializedCoordPairFormat { enum class MccSerializedCoordPairFormat {
MCC_SERIALIZED_FORMAT_DEGREES, // both angles are in degrees as floating-point number 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_SXGM_DEGDEG, // both angles are in sexagesimal degrees
MCC_SERIALIZED_FORMAT_UNKNOWN MCC_SERIALIZED_FORMAT_UNKNOWN
}; };

View File

@@ -228,7 +228,9 @@ struct MccSerializer<VT> : MccSerializerBase {
VT const& value, VT const& value,
ParamsT const& params = mcc_serialization_params_t{}) 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<std::chrono::milliseconds>(value);
std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(tp));
return MccSerializerErrorCode::ERROR_OK; return MccSerializerErrorCode::ERROR_OK;
} }
@@ -249,9 +251,14 @@ struct MccSerializer<VT> : MccSerializerBase {
std::string sgm; std::string sgm;
switch (params.angle_format) { switch (params.angle_format) {
case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES: case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES: {
v *= MCC_RADS_TO_DEGRESS; v *= MCC_RADS_TO_DEGRESS;
return MccSerializer<double>{}(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<double>{}(output, v, params);
case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS: case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS:
if (params.norm_sxgm) { if (params.norm_sxgm) {
sgm = utils::rad2sxg<true>(v, false, params.angle_prec.deg_prec); sgm = utils::rad2sxg<true>(v, false, params.angle_prec.deg_prec);
@@ -716,6 +723,53 @@ struct MccSerializer<VT> : MccSerializerBase {
}; };
template <>
struct MccSerializer<MccSerializedCoordPairFormat> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-COORDPAIR-FORMAT-SERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
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<MccSerializedAngleFormatPrec> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-ANGLE-FORMAT-PREC-SERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
MccSerializedAngleFormatPrec const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
auto err = MccSerializer<decltype(value.hour_prec)>{}(output, value.hour_prec, params);
if (!err) {
auto err = MccSerializer<decltype(value.deg_prec)>{}(output, value.deg_prec, params);
if (!err) {
auto err = MccSerializer<decltype(value.decimals)>{}(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<MccSerializer<MccAngle>>, "!!!"); static_assert(mcc_serializer_c<MccSerializer<MccAngle>>, "!!!");
} // namespace mcc::impl } // namespace mcc::impl

View File

@@ -1,5 +1,5 @@
#include <print>
#include <list> #include <list>
#include <print>
#include <mcc_netserver_proto.h> #include <mcc_netserver_proto.h>
@@ -24,7 +24,7 @@ int main()
msg2_t msg2("ACK", 12.43298042, "EEE", std::chrono::seconds(10), vd); msg2_t msg2("ACK", 12.43298042, "EEE", std::chrono::seconds(10), vd);
// msg2_t msg2("ACK"); // 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.key = <{}>", msg2.keyword());
std::println("msg.par[1] = <{}>", msg2.param(1)); std::println("msg.par[1] = <{}>", msg2.param(1));
std::println("msg.par[2] = <{}>", msg2.param(2)); 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}); 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()); std::println("msg2.bytes = <{}>", msg2.byteRepr());
auto spt_d = msg2.paramValue<mcc::impl::MccSkyPoint>(1); auto spt_d = msg2.paramValue<mcc::impl::MccSkyPoint>(1);
if (spt_d){ if (spt_d) {
std::println("msg2.parvalue(1).epoch() = {}", spt_d->epoch().MJD()+mcc::MCC_MJD_ZERO); 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 { } else {
std::println("cannot deserialize MccSkyPoint value!"); 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; return 0;
} }