This commit is contained in:
Timur A. Fatkhullin 2025-10-22 23:52:14 +03:00
parent 42a4349c76
commit 80ec2382ea
5 changed files with 266 additions and 35 deletions

View File

@ -504,6 +504,11 @@ class MccAngleLON : public MccAngle
using MccAngle::MccAngle; using MccAngle::MccAngle;
}; };
class MccAngleUnknown : public MccAngle
{
using MccAngle::MccAngle;
};
enum class MccCoordKind : size_t { enum class MccCoordKind : size_t {
COORDS_KIND_GENERIC = traits::mcc_type_hash<MccAngle>, COORDS_KIND_GENERIC = traits::mcc_type_hash<MccAngle>,
@ -518,7 +523,8 @@ enum class MccCoordKind : size_t {
COORDS_KIND_X = traits::mcc_type_hash<MccAngleX>, COORDS_KIND_X = traits::mcc_type_hash<MccAngleX>,
COORDS_KIND_Y = traits::mcc_type_hash<MccAngleY>, COORDS_KIND_Y = traits::mcc_type_hash<MccAngleY>,
COORDS_KIND_LAT = traits::mcc_type_hash<MccAngleLAT>, COORDS_KIND_LAT = traits::mcc_type_hash<MccAngleLAT>,
COORDS_KIND_LON = traits::mcc_type_hash<MccAngleLON> COORDS_KIND_LON = traits::mcc_type_hash<MccAngleLON>,
COORDS_KIND_UKNOWN = traits::mcc_type_hash<MccAngleUnknown>
}; };
enum class MccCoordPairKind : size_t { enum class MccCoordPairKind : size_t {
@ -529,7 +535,8 @@ enum class MccCoordPairKind : size_t {
COORDS_KIND_AZZD = traits::mcc_type_pair_hash<MccAngleAZ, MccAngleZD>(), COORDS_KIND_AZZD = traits::mcc_type_pair_hash<MccAngleAZ, MccAngleZD>(),
COORDS_KIND_AZALT = traits::mcc_type_pair_hash<MccAngleAZ, MccAngleALT>(), COORDS_KIND_AZALT = traits::mcc_type_pair_hash<MccAngleAZ, MccAngleALT>(),
COORDS_KIND_XY = traits::mcc_type_pair_hash<MccAngleX, MccAngleY>(), COORDS_KIND_XY = traits::mcc_type_pair_hash<MccAngleX, MccAngleY>(),
COORDS_KIND_LATLON = traits::mcc_type_pair_hash<MccAngleLAT, MccAngleLON>() COORDS_KIND_LATLON = traits::mcc_type_pair_hash<MccAngleLAT, MccAngleLON>(),
COORDS_KIND_UNKNOWN = traits::mcc_type_pair_hash<MccAngleUnknown, MccAngleUnknown>()
}; };
@ -587,7 +594,7 @@ static constexpr MccCoordPairKind MccCoordStrToPairKind(R&& spair)
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_XY_STR) ? MccCoordPairKind::COORDS_KIND_XY : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_XY_STR) ? MccCoordPairKind::COORDS_KIND_XY
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_LATLON_STR) ? MccCoordPairKind::COORDS_KIND_LATLON : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_LATLON_STR) ? MccCoordPairKind::COORDS_KIND_LATLON
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_GENERIC_STR) ? MccCoordPairKind::COORDS_KIND_GENERIC : hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_GENERIC_STR) ? MccCoordPairKind::COORDS_KIND_GENERIC
: MccCoordPairKind::COORDS_KIND_GENERIC; : MccCoordPairKind::COORDS_KIND_UNKNOWN;
} }

View File

@ -96,7 +96,7 @@ public:
return ep; return ep;
} }
MccCelestialCoordEpoch() : _MJD(J2000_MJD), _UTC(J2000_UTC), _JEpoch(2000.0) {} MccCelestialCoordEpoch() : _UTC(J2000_UTC), _MJD(J2000_MJD), _JEpoch(2000.0) {}
template <traits::mcc_input_char_range IR> template <traits::mcc_input_char_range IR>
bool fromCharRange(IR&& str) bool fromCharRange(IR&& str)
@ -196,7 +196,7 @@ public:
template <traits::mcc_time_duration_c DT> template <traits::mcc_time_duration_c DT>
friend MccCelestialCoordEpoch operator+(const MccCelestialCoordEpoch& lhs, const DT& dt) friend MccCelestialCoordEpoch operator+(const MccCelestialCoordEpoch& lhs, const DT& dt)
{ {
MccCelestialCoordEpoch ep; MccCelestialCoordEpoch ep = lhs;
ep += dt; ep += dt;
return ep; return ep;
@ -210,7 +210,7 @@ public:
template <traits::mcc_time_duration_c DT> template <traits::mcc_time_duration_c DT>
friend MccCelestialCoordEpoch operator-(const MccCelestialCoordEpoch& lhs, const DT& dt) friend MccCelestialCoordEpoch operator-(const MccCelestialCoordEpoch& lhs, const DT& dt)
{ {
MccCelestialCoordEpoch ep; MccCelestialCoordEpoch ep = lhs;
ep -= dt; ep -= dt;
return ep; return ep;
@ -330,7 +330,7 @@ protected:
jd += 2400001.0; jd += 2400001.0;
double s = 0.5, cs = 0.0; double s = 0.5, cs = 0.0;
double v[] = {f1, f2}; // double v[] = {f1, f2};
auto lmd = [&](double v) { auto lmd = [&](double v) {
// double x = v; // double x = v;

View File

@ -826,26 +826,125 @@ public:
: base_t(ctx, {}, std::forward<LoggerCtorArgsTs>(log_args)...) : base_t(ctx, {}, std::forward<LoggerCtorArgsTs>(log_args)...)
{ {
base_t::_handleMessageFunc = [mount = std::move(mount), this](std::string_view command) { base_t::_handleMessageFunc = [mount = std::move(mount), this](std::string_view command) {
using mount_error_t = decltype(mount)::error_t;
mount_error_t m_err;
MccNetMessage input_msg; MccNetMessage input_msg;
MccNetMessage<std::vector<char>> output_msg; MccNetMessage<std::vector<char>> output_msg;
std::error_code err{};
if (auto ec = parseMessage(command, input_msg)) { if (auto ec = parseMessage(command, input_msg)) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec);
} else { } else {
bool imsg_ok = true;
if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange! if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange!
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR)) { // ??!!! } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR)) { // ??!!!
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) { } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) {
this->restart(); this->restart();
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR); } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) {
m_err = mount.initMount();
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) {
m_err = mount.stopMount();
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) {
m_err = mount.slewToTarget(false);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) {
m_err = mount.slewToTarget(true);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) {
m_err = mount.trackTarget();
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) {
auto v = input_msg.paramValue<MccNetMessageCoordFormat>(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<MccNetMessageCoordPrec>(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<MccCelestialPoint>(0); // is it set operation?
if (vc) { // coordinates are given - set operation
auto m_err = mount.setPointingTarget(vc.value());
if (m_err) {
// !!!!!!!!!!!!!
err = m_err;
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
}
} else {
auto vp = input_msg.paramValue<MccCoordPairKind>(0);
if (vp) { // coordinate pair kind is given
cp.pair_kind = vp.value();
err = coordsFromTelemetryData(mount, true, cp);
if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR,
MCC_COMMPROTO_KEYWORD_TARGET_STR, cp);
}
} else { // invalid command!!!
err = vp.error();
}
}
} else { // get operation
err = coordsFromTelemetryData(mount, true, cp);
if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR,
cp);
}
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOUNT_STR)) {
// by default return ICRS coordinates
MccCelestialPoint cp{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
if (input_msg.paramSize()) { // ccordinate pair kind is given
auto vp = input_msg.paramValue<MccCoordPairKind>(0);
if (vp) { // coordinate pair kind is given
cp.pair_kind = vp.value();
err = coordsFromTelemetryData(mount, false, cp);
if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR,
MCC_COMMPROTO_KEYWORD_MOUNT_STR, cp);
}
} else { // invalid command!!!
err = vp.error();
}
} else {
err = coordsFromTelemetryData(mount, false, cp);
if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
cp);
}
}
} else {
err = std::make_error_code(std::errc::invalid_argument);
} }
if (imsg_ok) { // send ACK if (m_err) {
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg); // ?????!!!!!!
err = m_err;
} }
if (err) { // send error description
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, err);
}
// else { // send ACK with copy of the input message
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
// }
} }
return output_msg; return output_msg;
@ -855,6 +954,9 @@ public:
virtual ~MccGenericMountNetworkServer() {} virtual ~MccGenericMountNetworkServer() {}
protected: protected:
MccNetMessageCoordFormat _coordFormat{MccNetMessageCoordFormat::CFMT_SGM}; // ouput coordinates format
MccNetMessageCoordPrec _coordPrec{2, 1};
template <typename MSG_T> template <typename MSG_T>
std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg) std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg)
{ {
@ -862,6 +964,82 @@ protected:
return ec; return ec;
} }
std::error_code coordsFromTelemetryData(mcc_generic_mount_c auto& mount,
bool target, // true - target coordinates, false - mount coordinates
mcc_celestial_point_c auto& cp)
{
MccTelemetryData tdata;
auto t_err = mount.telemetryData(&tdata);
if (t_err) {
// ??!!!!
return t_err;
}
mcc_tp2tp(tdata.target.time_point, cp.time_point);
switch (cp.pair_kind) {
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
if (target) {
cp.X = tdata.target.RA_ICRS;
cp.Y = tdata.target.DEC_ICRS;
mcc_tp2tp(MccCelestialCoordEpoch::J2000_UTC, cp.time_point);
} // ??!!!
break;
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP:
if (target) {
cp.X = tdata.target.RA_APP;
cp.Y = tdata.target.DEC_APP;
} else {
cp.X = tdata.RA_APP;
cp.Y = tdata.DEC_APP;
}
break;
case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP:
if (target) {
cp.X = tdata.target.HA;
cp.Y = tdata.target.DEC_APP;
} else {
cp.X = tdata.HA;
cp.Y = tdata.DEC_APP;
}
break;
case mcc::MccCoordPairKind::COORDS_KIND_AZZD:
if (target) {
cp.X = tdata.target.AZ;
cp.Y = tdata.target.ZD;
} else {
cp.X = tdata.AZ;
cp.Y = tdata.ZD;
}
break;
case mcc::MccCoordPairKind::COORDS_KIND_AZALT:
if (target) {
cp.X = tdata.target.AZ;
cp.Y = tdata.target.ALT;
} else {
cp.X = tdata.AZ;
cp.Y = tdata.ALT;
}
break;
case mcc::MccCoordPairKind::COORDS_KIND_XY:
if (target) {
cp.X = tdata.target.X;
cp.Y = tdata.target.Y;
} else {
cp.X = tdata.X;
cp.Y = tdata.Y;
}
break;
default:
return std::make_error_code(std::errc::invalid_argument);
}
return {};
}
}; };
} // namespace mcc::network } // namespace mcc::network

View File

@ -156,7 +156,7 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FI
// arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT) // arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT)
// precision must be given as non-negative integer number // precision must be given as non-negative integer number
// e.g. // e.g.
// "COORDPREC 2 1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9) // "COORDPREC 2,1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
// //
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC"; static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
@ -492,23 +492,25 @@ static_assert(mcc_netmsg_valid_keys_c<MccNetMessageValidKeywords>, "");
template <typename T> template <typename T>
concept mcc_netmessage_c = requires(T t) { T(); }; concept mcc_netmessage_c = requires(T t) { T(); };
/* helper types to format serialized celestial coordinates */
/* it can be used as inputs in "construct" method or corresponded constructor */
// format of output (serialized) coordinates
enum class MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM };
// precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds)
struct MccNetMessageCoordPrec {
uint8_t hour_prec = 2;
uint8_t deg_prec = 1;
};
template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view, template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
mcc_netmsg_valid_keys_c BASE_T = MccNetMessageValidKeywords> mcc_netmsg_valid_keys_c BASE_T = MccNetMessageValidKeywords>
class MccNetMessage class MccNetMessage
{ {
public: public:
/* helper types to format serialized celestial coordinates */
/* it can be used as inputs in "construct" method or corresponded constructor */
// format of output (serialized) coordinates
enum MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM };
// precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds)
struct MccNetMessageCoordPrec {
uint8_t hour_prec = 2;
uint8_t deg_prec = 1;
};
protected: protected:
class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer
{ {
@ -599,6 +601,46 @@ protected:
pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{}); pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{});
mcc_copy_celestial_point(pt, &value); mcc_copy_celestial_point(pt, &value);
} else if constexpr (std::same_as<VT, MccCoordPairKind>) {
value = MccCoordStrToPairKind(bytes);
if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
return std::make_error_code(std::errc::invalid_argument);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordFormat>) {
std::string v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
return ec;
}
if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR) == 0) {
value = MccNetMessageCoordFormat::CFMT_SGM;
} else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) {
value = MccNetMessageCoordFormat::CFMT_DEGREES;
} else {
return std::make_error_code(std::errc::invalid_argument);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordPrec>) {
std::vector<int64_t> v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
return ec;
}
auto hprec = v[0];
value.hour_prec = hprec > 0 ? (hprec < std::numeric_limits<decltype(value.hour_prec)>::max()
? hprec
: std::numeric_limits<decltype(value.hour_prec)>::max())
: 2;
if (v.size() == 1) {
value.deg_prec = 1;
} else {
auto dprec = v[1];
value.deg_prec = dprec > 0 ? dprec < std::numeric_limits<decltype(value.deg_prec)>::max()
? dprec
: std::numeric_limits<decltype(value.deg_prec)>::max()
: 1;
}
} else { } else {
return base_t::operator()(std::forward<IR>(bytes), value); return base_t::operator()(std::forward<IR>(bytes), value);
} }
@ -610,7 +652,7 @@ protected:
class DefaultSerializer class DefaultSerializer
{ {
MccNetMessageCoordFormat _currentCoordFormat = MccNetMessage::CFMT_SGM; MccNetMessageCoordFormat _currentCoordFormat = MccNetMessageCoordFormat::CFMT_SGM;
MccNetMessageCoordPrec _currentCoordPrec{2, 1}; MccNetMessageCoordPrec _currentCoordPrec{2, 1};
public: public:
@ -635,12 +677,12 @@ protected:
std::ranges::copy(std::string(value), std::back_inserter(bytes)); std::ranges::copy(std::string(value), std::back_inserter(bytes));
} else if constexpr (traits::mcc_char_range<T>) { } else if constexpr (traits::mcc_char_range<T>) {
std::ranges::copy(std::string(value.begin(), value.end()), std::back_inserter(bytes)); std::ranges::copy(std::string(value.begin(), value.end()), std::back_inserter(bytes));
} else if constexpr (std::same_as<T, MccCoordPairKind>) { // } else if constexpr (std::same_as<T, MccCoordPairKind>) {
std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes)); // std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes));
} else if constexpr (traits::mcc_time_duration_c<T>) { } else if constexpr (traits::mcc_time_duration_c<T>) {
(*this)(value.count(), bytes); (*this)(value.count(), bytes);
} else if constexpr (mcc_celestial_point_c<T>) { } else if constexpr (mcc_celestial_point_c<T>) {
if (_currentCoordFormat == MccNetMessage::CFMT_DEGREES) { if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) {
std::format_to(std::back_inserter(bytes), "{}{}{}", MccAngle(value.X).degrees(), std::format_to(std::back_inserter(bytes), "{}{}{}", MccAngle(value.X).degrees(),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccAngle(value.Y).degrees()); MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccAngle(value.Y).degrees());
} else { } else {
@ -683,7 +725,6 @@ protected:
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}", value.value(), std::format_to(std::back_inserter(bytes), "{}{}{}{}{}", value.value(),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.message(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.message(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
value.category().name()); value.category().name());
} else if constexpr (std::same_as<T, MccNetMessage>) {
} else if constexpr (std::formattable<T, char>) { } else if constexpr (std::formattable<T, char>) {
std::format_to(std::back_inserter(bytes), "{}", value); std::format_to(std::back_inserter(bytes), "{}", value);
} else { } else {
@ -751,8 +792,13 @@ public:
} }
size_t paramSize() const
{
return _params.size();
}
template <std::ranges::range R> template <std::ranges::range R>
R params(size_t start_idx, size_t Nelemes = std::numeric_limits<size_t>::max()) R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max())
requires(traits::mcc_view_or_output_char_range<R> || traits::mcc_range_of_char_range<R>) requires(traits::mcc_view_or_output_char_range<R> || traits::mcc_range_of_char_range<R>)
{ {
if (start_idx >= _params.size()) { if (start_idx >= _params.size()) {
@ -791,7 +837,7 @@ public:
} }
} }
std::string_view params(size_t start_idx, size_t Nelemes = std::numeric_limits<size_t>::max()) std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max())
{ {
return params<std::string_view>(start_idx, Nelemes); return params<std::string_view>(start_idx, Nelemes);
} }

View File

@ -60,7 +60,7 @@ int main()
.Y = mcc::MccAngle(67.9827148715, mcc::mcc_degrees)}; .Y = mcc::MccAngle(67.9827148715, mcc::mcc_degrees)};
// msg2.construct("ACK", "MOUNT", msg2_t::CFMT_DEGREES, msg2_t::MccNetMessageCoordPrec{2, 3}, cpt); // msg2.construct("ACK", "MOUNT", msg2_t::CFMT_DEGREES, msg2_t::MccNetMessageCoordPrec{2, 3}, cpt);
msg2.construct("ACK", "MOUNT", msg2_t::MccNetMessageCoordPrec{2, 3}, cpt); msg2.construct("ACK", "MOUNT", mcc::network::MccNetMessageCoordPrec{2, 3}, cpt);
std::cout << "MSG2: " << msg2.byteRepr() << "\n"; std::cout << "MSG2: " << msg2.byteRepr() << "\n";
auto cpt1 = msg2.paramValue<mcc::MccCelestialPoint>(1); auto cpt1 = msg2.paramValue<mcc::MccCelestialPoint>(1);
if (cpt1) { if (cpt1) {