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)
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})

View File

@@ -968,10 +968,11 @@ concept mcc_movement_controls_c = requires(T t) {
template <typename T>
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
};

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 <>
struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"};
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
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[<params.elem_delim>deg_prec<params.elem_delim>decimals]
@@ -408,16 +430,17 @@ struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
template <>
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>
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;

View File

@@ -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<void()> _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<MccCoordinateSerializer::SerializedCoordFormat>(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<MccSerializedCoordPairFormat>(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<MccCoordinateSerializer::SexagesimalCoordPrec>(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<MccSerializedAngleFormatPrec>(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<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
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<MccCelestialPoint>(0);
auto vc = input_msg.template paramValue<impl::MccSkyPoint>(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<MccCoordPairKind>(0);
auto vp = input_msg.template paramValue<impl::MccCoordPairKind>(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 <mcc_generic_mount_c MountT>
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 = [&]<mcc_coord_pair_c T>(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;
}
};

View File

@@ -10,9 +10,9 @@
#include <string_view>
#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 <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
class MccNetMessage
{
protected:
// just a wrapper class to hold MccSerializer<T> specializations
struct DefaultSerializer
{
struct DefaultSerializer {
template <traits::mcc_output_char_range OR, typename T>
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>
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()) {
return std::unexpected{std::make_error_code(std::errc::value_too_large)};
@@ -422,7 +426,8 @@ public:
template <typename T>
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{};
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>
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>) {
_serializationParams.coordpair_format = par;
} else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) {
@@ -576,8 +580,6 @@ protected:
} else {
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);
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));

View File

@@ -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
};

View File

@@ -228,7 +228,9 @@ struct MccSerializer<VT> : 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<std::chrono::milliseconds>(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<VT> : 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<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:
if (params.norm_sxgm) {
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>>, "!!!");
} // namespace mcc::impl

View File

@@ -1,5 +1,5 @@
#include <print>
#include <list>
#include <print>
#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");
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<mcc::impl::MccSkyPoint>(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;
}