...
This commit is contained in:
parent
85dfa2e9a5
commit
78e4bb182c
@ -12,13 +12,14 @@
|
||||
#include <mcc_spdlog.h>
|
||||
|
||||
#include "asibfm700_servocontroller.h"
|
||||
#include "mcc_ccte_erfa.h"
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
static constexpr mcc::MccMountType asibfm700MountType = mcc::MccMountType::FORK_TYPE;
|
||||
|
||||
|
||||
typedef mcc::ccte::erfa::MccCCTE_ERFA Asibfm700CCTE;
|
||||
typedef mcc::MccDefaultPCM<asibfm700MountType> Asibfm700PCM;
|
||||
typedef mcc::MccPZoneContainer<mcc::MccTimeDuration> Asibfm700PZoneContainer;
|
||||
typedef mcc::utils::MccSpdlogLogger Asibfm700Logger;
|
||||
|
||||
@ -115,8 +115,51 @@ Asibfm700Mount::error_t Asibfm700Mount::initMount()
|
||||
if (hw_err) {
|
||||
errorLogging("", hw_err);
|
||||
return hw_err;
|
||||
} else {
|
||||
logInfo("Hardware initialization was performed sucessfully!");
|
||||
}
|
||||
|
||||
logInfo("ERFA engine initialization ...");
|
||||
|
||||
// set ERFA state
|
||||
Asibfm700CCTE::engine_state_t ccte_state{.meteo{},
|
||||
.wavelength = _mountConfig.refractWavelength(),
|
||||
.lat = _mountConfig.siteLatitude(),
|
||||
.lon = _mountConfig.siteLongitude(),
|
||||
.elev = _mountConfig.siteElevation()};
|
||||
|
||||
|
||||
if (!_mountConfig.leapSecondFilename().empty()) { // load leap seconds file
|
||||
logInfo("Loading leap second file: {} ...", _mountConfig.leapSecondFilename());
|
||||
bool ok = ccte_state._leapSeconds.load(_mountConfig.leapSecondFilename());
|
||||
if (ok) {
|
||||
logInfo("Leap second file was loaded successfully (expire date: {})", ccte_state._leapSeconds.expireDate());
|
||||
} else {
|
||||
logError("Leap second file loading failed! Using hardcoded defauls (expire date: {})",
|
||||
ccte_state._leapSeconds.expireDate());
|
||||
}
|
||||
} else {
|
||||
logError("Using hardcoded leap seconds defauls (expire date: {})", ccte_state._leapSeconds.expireDate());
|
||||
}
|
||||
|
||||
if (!_mountConfig.bulletinAFilename().empty()) { // load IERS Bulletin A file
|
||||
logInfo("Loading IERS Bulletin A file: {} ...", _mountConfig.bulletinAFilename());
|
||||
bool ok = ccte_state._bulletinA.load(_mountConfig.bulletinAFilename());
|
||||
if (ok) {
|
||||
logInfo("IERS Bulletin A file was loaded successfully (date range: {} - {})",
|
||||
ccte_state._bulletinA.dateRange().begin, ccte_state._bulletinA.dateRange().end);
|
||||
} else {
|
||||
logError("IERS Bulletin A file loading failed! Using hardcoded defauls (date range: {} - {})",
|
||||
ccte_state._bulletinA.dateRange().begin, ccte_state._bulletinA.dateRange().end);
|
||||
}
|
||||
} else {
|
||||
logError("Using hardcoded IERS Bulletin A defauls (date range: {} - {})",
|
||||
ccte_state._bulletinA.dateRange().begin, ccte_state._bulletinA.dateRange().end);
|
||||
}
|
||||
|
||||
setStateERFA(std::move(ccte_state));
|
||||
|
||||
|
||||
return mcc::MccGenericMountErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <mcc_ccte_erfa.h>
|
||||
#include <mcc_generic_mount.h>
|
||||
#include <mcc_pcm.h>
|
||||
#include <mcc_pzone_container.h>
|
||||
#include <mcc_slewing_model.h>
|
||||
#include <mcc_spdlog.h>
|
||||
@ -19,8 +17,8 @@ namespace asibfm700
|
||||
|
||||
|
||||
|
||||
class Asibfm700Mount : public mcc::ccte::erfa::MccCCTE_ERFA,
|
||||
public mcc::MccDefaultPCM<asibfm700MountType>,
|
||||
class Asibfm700Mount : public Asibfm700CCTE,
|
||||
public Asibfm700PCM,
|
||||
public mcc::MccGenericFsmMount<mcc::MccGenericMount<AsibFM700ServoController,
|
||||
mcc::MccTelemetry,
|
||||
Asibfm700PZoneContainer,
|
||||
@ -82,10 +80,10 @@ protected:
|
||||
public:
|
||||
using base_gm_class_t::error_t;
|
||||
|
||||
using mcc::ccte::erfa::MccCCTE_ERFA::setStateERFA;
|
||||
using mcc::ccte::erfa::MccCCTE_ERFA::updateBulletinA;
|
||||
using mcc::ccte::erfa::MccCCTE_ERFA::updateLeapSeconds;
|
||||
using mcc::ccte::erfa::MccCCTE_ERFA::updateMeteoERFA;
|
||||
using Asibfm700CCTE::setStateERFA;
|
||||
using Asibfm700CCTE::updateBulletinA;
|
||||
using Asibfm700CCTE::updateLeapSeconds;
|
||||
using Asibfm700CCTE::updateMeteoERFA;
|
||||
|
||||
using Asibfm700Logger::logCritical;
|
||||
using Asibfm700Logger::logDebug;
|
||||
|
||||
@ -5,7 +5,7 @@ namespace asibfm700
|
||||
{
|
||||
|
||||
template <mcc::traits::mcc_range_of_input_char_range R>
|
||||
Asibfm700MountNetserver::Asibfm700MountNetserver(asio::io_context& ctx,
|
||||
Asibfm700MountNetServer::Asibfm700MountNetServer(asio::io_context& ctx,
|
||||
std::shared_ptr<spdlog::logger> logger,
|
||||
const R& pattern_range)
|
||||
: _base_t(ctx, [this](std::string_view msg) { return handleMessage(msg); }, std::move(logger), pattern_range)
|
||||
|
||||
@ -8,17 +8,93 @@
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
class Asibfm700MountNetserver : public mcc::network::MccGenericNetworkServer<Asibfm700Logger>
|
||||
namespace details
|
||||
{
|
||||
|
||||
template <typename VT, size_t N1, size_t N2>
|
||||
static constexpr auto merge_arrays(const std::array<VT, N1>& arr1, const std::array<VT, N2>& arr2)
|
||||
{
|
||||
constexpr auto N = N1 + N2;
|
||||
std::array<VT, N> res;
|
||||
|
||||
for (size_t i = 0; i < N1; ++i) {
|
||||
res[i] = arr1[i];
|
||||
}
|
||||
|
||||
for (size_t i = N1; i < N; ++i) {
|
||||
res[i] = arr2[i - N1];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
constexpr static std::string_view ASIBFM700_COMMPROTO_KEYWORD_METEO_STR{"METEO"};
|
||||
|
||||
struct Asibfm700NetMessageValidKeywords {
|
||||
static constexpr std::array NETMSG_VALID_KEYWORDS =
|
||||
details::merge_arrays(mcc::network::MccNetMessageValidKeywords::NETMSG_VALID_KEYWORDS,
|
||||
std::array{ASIBFM700_COMMPROTO_KEYWORD_METEO_STR});
|
||||
|
||||
// hashes of valid keywords
|
||||
static constexpr std::array NETMSG_VALID_KEYWORD_HASHES = []<size_t... Is>(std::index_sequence<Is...>) {
|
||||
return std::array{mcc::utils::FNV1aHash(NETMSG_VALID_KEYWORDS[Is])...};
|
||||
}(std::make_index_sequence<NETMSG_VALID_KEYWORDS.size()>());
|
||||
|
||||
constexpr static const size_t* isKeywordValid(std::string_view key)
|
||||
{
|
||||
const auto hash = mcc::utils::FNV1aHash(key);
|
||||
|
||||
for (auto const& h : NETMSG_VALID_KEYWORD_HASHES) {
|
||||
if (h == hash) {
|
||||
return &h;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view>
|
||||
class Asibfm700MountNetMessage : public mcc::network::MccNetMessage<BYTEREPR_T, Asibfm700NetMessageValidKeywords>
|
||||
{
|
||||
protected:
|
||||
using base_t = mcc::network::MccNetMessage<BYTEREPR_T, Asibfm700NetMessageValidKeywords>;
|
||||
|
||||
|
||||
public:
|
||||
using base_t::base_t;
|
||||
|
||||
template <typename T>
|
||||
std::expected<T, std::error_code> paramValue(size_t idx)
|
||||
{
|
||||
return paramValue<T>(idx, _defaultDeserilizer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <mcc::traits::mcc_input_char_range KT, typename... PTs>
|
||||
std::error_code construct(KT&& key, PTs&&... params)
|
||||
requires mcc::traits::mcc_output_char_range<BYTEREPR_T>
|
||||
{
|
||||
return construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Asibfm700MountNetServer : public mcc::network::MccGenericNetworkServer<Asibfm700Logger>
|
||||
{
|
||||
using _base_t = mcc::network::MccGenericNetworkServer<Asibfm700Logger>;
|
||||
|
||||
public:
|
||||
template <mcc::traits::mcc_range_of_input_char_range R = decltype(Asibfm700Logger::LOGGER_DEFAULT_FORMAT)>
|
||||
Asibfm700MountNetserver(asio::io_context& ctx,
|
||||
Asibfm700MountNetServer(asio::io_context& ctx,
|
||||
std::shared_ptr<spdlog::logger> logger,
|
||||
const R& pattern_range = Asibfm700Logger::LOGGER_DEFAULT_FORMAT);
|
||||
|
||||
~Asibfm700MountNetserver();
|
||||
~Asibfm700MountNetServer();
|
||||
|
||||
private:
|
||||
std::vector<char> handleMessage(std::string_view msg);
|
||||
|
||||
@ -134,7 +134,12 @@ public:
|
||||
|
||||
bool load(traits::mcc_input_char_range auto const& filename, char comment_sym = '#')
|
||||
{
|
||||
std::ifstream fst(filename);
|
||||
std::ifstream fst;
|
||||
if constexpr (std::same_as<std::remove_cvref_t<decltype(filename)>, std::string>) {
|
||||
fst.open(filename);
|
||||
} else {
|
||||
fst.open(std::string{filename.begin(), filename.end()});
|
||||
}
|
||||
|
||||
bool ok = fst.is_open();
|
||||
if (!ok) {
|
||||
@ -436,7 +441,12 @@ public:
|
||||
|
||||
bool load(traits::mcc_input_char_range auto const& filename, char comment_sym = '*')
|
||||
{
|
||||
std::ifstream fst(filename);
|
||||
std::ifstream fst;
|
||||
if constexpr (std::same_as<std::remove_cvref_t<decltype(filename)>, std::string>) {
|
||||
fst.open(filename);
|
||||
} else {
|
||||
fst.open(std::string{filename.begin(), filename.end()});
|
||||
}
|
||||
|
||||
bool ok = fst.is_open();
|
||||
if (!ok) {
|
||||
|
||||
@ -515,6 +515,15 @@ static constexpr std::string_view MccCoordinateDefaultDelimiter{","};
|
||||
class MccCoordinateDeserializer
|
||||
{
|
||||
public:
|
||||
MccCoordinateDeserializer() = default;
|
||||
|
||||
template <traits::mcc_input_char_range R>
|
||||
MccCoordinateDeserializer(R&& delim) : MccCoordinateDeserializer()
|
||||
{
|
||||
setDelimiter(std::forward<R>(delim));
|
||||
}
|
||||
|
||||
|
||||
virtual ~MccCoordinateDeserializer() = default;
|
||||
|
||||
template <traits::mcc_input_char_range R>
|
||||
@ -612,9 +621,9 @@ public:
|
||||
};
|
||||
|
||||
|
||||
MccCoordinateSerializer() = default;
|
||||
constexpr MccCoordinateSerializer() = default;
|
||||
|
||||
MccCoordinateSerializer(SerializedCoordFormat fmt, SexagesimalCoordPrec prec)
|
||||
constexpr MccCoordinateSerializer(SerializedCoordFormat fmt, SexagesimalCoordPrec prec)
|
||||
{
|
||||
setFormat(fmt);
|
||||
setPrecision(std::move(prec));
|
||||
@ -701,6 +710,8 @@ protected:
|
||||
class MccCelestialPointSerializer : public MccCoordinateSerializer
|
||||
{
|
||||
public:
|
||||
using MccCoordinateSerializer::MccCoordinateSerializer;
|
||||
|
||||
template <mcc_celestial_point_c T, traits::mcc_output_char_range OR>
|
||||
void operator()(const T& value, OR& bytes)
|
||||
{
|
||||
@ -737,6 +748,8 @@ public:
|
||||
class MccCelestialPointDeserializer : public MccCoordinateDeserializer
|
||||
{
|
||||
public:
|
||||
using MccCoordinateDeserializer::MccCoordinateDeserializer;
|
||||
|
||||
template <traits::mcc_input_char_range IR, mcc_celestial_point_c T>
|
||||
std::error_code operator()(IR&& bytes, T& value)
|
||||
{
|
||||
@ -808,6 +821,8 @@ public:
|
||||
class MccEqtHrzCoordsSerializer : public MccCoordinateSerializer
|
||||
{
|
||||
public:
|
||||
using MccCoordinateSerializer::MccCoordinateSerializer;
|
||||
|
||||
template <mcc_eqt_hrz_coord_c T, traits::mcc_output_char_range OR>
|
||||
void operator()(const T& value, OR& bytes)
|
||||
{
|
||||
@ -855,6 +870,8 @@ public:
|
||||
class MccEqtHrzCoordsDeserializer : public MccCoordinateDeserializer
|
||||
{
|
||||
public:
|
||||
using MccCoordinateDeserializer::MccCoordinateDeserializer;
|
||||
|
||||
template <traits::mcc_input_char_range IR, mcc_eqt_hrz_coord_c T>
|
||||
std::error_code operator()(IR&& bytes, T& value)
|
||||
{
|
||||
@ -1019,6 +1036,8 @@ public:
|
||||
class MccTelemetryDataDeserializer : public MccCoordinateDeserializer
|
||||
{
|
||||
public:
|
||||
using MccCoordinateDeserializer::MccCoordinateDeserializer;
|
||||
|
||||
template <traits::mcc_input_char_range IR, mcc_telemetry_data_c T>
|
||||
std::error_code operator()(IR&& bytes, T& value)
|
||||
{
|
||||
|
||||
@ -159,8 +159,9 @@ public:
|
||||
static constexpr std::chrono::duration DEFAULT_RCV_TIMEOUT = std::chrono::hours(12);
|
||||
static constexpr std::chrono::duration DEFAULT_SND_TIMEOUT = std::chrono::milliseconds(2000);
|
||||
|
||||
typedef std::vector<char> handle_message_func_result_t;
|
||||
// handle received message user function
|
||||
typedef std::function<std::vector<char>(std::string_view)> handle_message_func_t;
|
||||
typedef std::function<handle_message_func_result_t(std::string_view)> handle_message_func_t;
|
||||
|
||||
|
||||
MccGenericNetworkServer(asio::io_context& ctx, const handle_message_func_t& func)
|
||||
@ -892,6 +893,8 @@ class MccGenericMountNetworkServer : public MccGenericNetworkServer<LoggerT>
|
||||
using base_t = MccGenericNetworkServer<LoggerT>;
|
||||
|
||||
public:
|
||||
using typename base_t::handle_message_func_result_t;
|
||||
|
||||
template <mcc_generic_mount_c MountT, typename... LoggerCtorArgsTs>
|
||||
MccGenericMountNetworkServer(asio::io_context& ctx, MountT& mount, LoggerCtorArgsTs&&... log_args)
|
||||
: base_t(ctx, {}, std::forward<LoggerCtorArgsTs>(log_args)...)
|
||||
@ -901,7 +904,7 @@ public:
|
||||
mount_error_t m_err;
|
||||
|
||||
MccNetMessage input_msg;
|
||||
MccNetMessage<std::vector<char>> output_msg;
|
||||
MccNetMessage<handle_message_func_result_t> output_msg;
|
||||
|
||||
std::error_code err{};
|
||||
|
||||
@ -941,7 +944,7 @@ public:
|
||||
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_TRACK);
|
||||
}
|
||||
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDFMT_STR)) {
|
||||
auto v = input_msg.paramValue<MccNetMessageCoordFormat>(0);
|
||||
auto v = input_msg.paramValue<MccCoordinateSerializer::SerializedCoordFormat>(0);
|
||||
if (v) {
|
||||
_coordFormat = v.value();
|
||||
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
|
||||
@ -949,7 +952,7 @@ public:
|
||||
err = v.error();
|
||||
}
|
||||
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_COORDPREC_STR)) {
|
||||
auto v = input_msg.paramValue<MccNetMessageCoordPrec>(0);
|
||||
auto v = input_msg.paramValue<MccCoordinateSerializer::SexagesimalCoordPrec>(0);
|
||||
if (v) {
|
||||
_coordPrec = v.value();
|
||||
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
|
||||
@ -990,7 +993,7 @@ public:
|
||||
err = coordsFromTelemetryData(mount, true, cp);
|
||||
if (!err) {
|
||||
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR,
|
||||
cp);
|
||||
_coordFormat, _coordPrec, cp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1015,7 +1018,7 @@ public:
|
||||
err = coordsFromTelemetryData(mount, false, cp);
|
||||
if (!err) {
|
||||
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
|
||||
cp);
|
||||
_coordFormat, _coordPrec, cp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1030,15 +1033,19 @@ public:
|
||||
// }
|
||||
}
|
||||
|
||||
return output_msg;
|
||||
return output_msg.byteRepr();
|
||||
};
|
||||
}
|
||||
|
||||
virtual ~MccGenericMountNetworkServer() {}
|
||||
|
||||
protected:
|
||||
MccNetMessageCoordFormat _coordFormat{MccNetMessageCoordFormat::CFMT_SGM}; // ouput coordinates format
|
||||
MccNetMessageCoordPrec _coordPrec{2, 1};
|
||||
// MccNetMessageCoordFormat _coordFormat{MccNetMessageCoordFormat::CFMT_SGM}; // ouput coordinates format
|
||||
// MccNetMessageCoordPrec _coordPrec{2, 1};
|
||||
|
||||
MccCoordinateSerializer::SerializedCoordFormat _coordFormat{
|
||||
MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM};
|
||||
MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{2, 1};
|
||||
|
||||
template <typename MSG_T>
|
||||
std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg)
|
||||
|
||||
@ -516,90 +516,22 @@ protected:
|
||||
protected:
|
||||
using base_t = mcc::utils::MccSimpleDeserializer;
|
||||
|
||||
inline static mcc::MccCelestialPointDeserializer _cpDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
|
||||
inline static mcc::MccEqtHrzCoordsDeserializer _eqhrDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
|
||||
inline static mcc::MccTelemetryDataDeserializer _telemetryDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
|
||||
|
||||
public:
|
||||
DefaultDeserializer() : base_t(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ) {}
|
||||
|
||||
template <traits::mcc_input_char_range IR, typename VT>
|
||||
std::error_code operator()(IR&& bytes, VT& value)
|
||||
{
|
||||
if constexpr (mcc_celestial_point_c<VT>) {
|
||||
std::vector<std::string> vs;
|
||||
auto ec = base_t::operator()(std::forward<IR>(bytes), vs);
|
||||
if (ec) {
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (vs.size() < 2) { // at least a pair of coordinates must be given
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||
|
||||
if (vs.size() > 2) { // pair of coordinates and the pair kind
|
||||
pt.pair_kind = MccCoordStrToPairKind(vs[2]);
|
||||
if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_GENERIC) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
|
||||
// J2000.0: 11:58:55.816 1 January 2000 UTC
|
||||
auto tp = std::chrono::sys_days(std::chrono::year_month_day(
|
||||
std::chrono::January / std::chrono::day(1) / std::chrono::year(2000))) +
|
||||
std::chrono::hours(11) + std::chrono::minutes(58) + std::chrono::milliseconds(55816);
|
||||
mcc_tp2tp(tp, pt.time_point);
|
||||
} else {
|
||||
if (vs.size() > 3) { // coordinates epoch is given
|
||||
// std::chrono::sys_time<std::chrono::system_clock::duration> tp;
|
||||
|
||||
// std::istringstream iss(std::string{utils::trimSpaces(vs[3])});
|
||||
|
||||
// std::chrono::from_stream(iss, "%FT%T", tp);
|
||||
// if (iss.fail()) {
|
||||
// return std::make_error_code(std::errc::invalid_argument);
|
||||
// }
|
||||
|
||||
// mcc_tp2tp(tp, pt.time_point);
|
||||
|
||||
MccCelestialCoordEpoch cep;
|
||||
// bool ok = cep.fromCharRange(utils::trimSpaces(vs[3]));
|
||||
bool ok = cep.fromCharRange(vs[3]);
|
||||
if (!ok) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
mcc_tp2tp(cep.UTC(), pt.time_point);
|
||||
} else { // no time point - use NOW
|
||||
mcc_tp2tp(std::chrono::system_clock::now(), pt.time_point);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<double> ang1, ang2;
|
||||
|
||||
switch (pt.pair_kind) {
|
||||
// if sexagesimal then hours:minutes:seconds form
|
||||
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||
case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||
ang1 = mcc::utils::parsAngleString(vs[0], true);
|
||||
break;
|
||||
default:
|
||||
// if sexagesimal then degrees:arcminutes:arcseconds form
|
||||
ang1 = mcc::utils::parsAngleString(vs[0]);
|
||||
}
|
||||
if (!ang1) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
ang2 = mcc::utils::parsAngleString(vs[1]);
|
||||
if (!ang2) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
pt.X = MccAngle(ang1.value(), mcc::MccDegreeTag{});
|
||||
pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{});
|
||||
|
||||
mcc_copy_celestial_point(pt, &value);
|
||||
if constexpr (mcc_telemetry_data_c<VT>) {
|
||||
return _telemetryDeserializer(std::forward<IR>(bytes), value);
|
||||
} else if constexpr (mcc_eqt_hrz_coord_c<VT>) {
|
||||
return _eqhrDeserializer(std::forward<IR>(bytes), value);
|
||||
} else if constexpr (mcc_celestial_point_c<VT>) {
|
||||
return _cpDeserializer(std::forward<IR>(bytes), value);
|
||||
} else if constexpr (std::same_as<VT, MccCoordPairKind>) {
|
||||
value = MccCoordStrToPairKind(bytes);
|
||||
if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
||||
@ -651,20 +583,12 @@ protected:
|
||||
|
||||
class DefaultSerializer
|
||||
{
|
||||
MccNetMessageCoordFormat _currentCoordFormat = MccNetMessageCoordFormat::CFMT_SGM;
|
||||
MccNetMessageCoordPrec _currentCoordPrec{2, 1};
|
||||
friend class MccNetMessage;
|
||||
|
||||
MccCoordinateSerializer::SerializedCoordFormat _coordFmt{};
|
||||
MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{};
|
||||
|
||||
public:
|
||||
void setCoordFormat(MccNetMessageCoordFormat fmt)
|
||||
{
|
||||
_currentCoordFormat = fmt;
|
||||
}
|
||||
|
||||
void setCoordPrec(MccNetMessageCoordPrec prec)
|
||||
{
|
||||
_currentCoordPrec = prec;
|
||||
}
|
||||
|
||||
template <typename T, traits::mcc_output_char_range OR>
|
||||
void operator()(const T& value, OR& bytes)
|
||||
{
|
||||
@ -680,83 +604,30 @@ protected:
|
||||
// std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes));
|
||||
} else if constexpr (traits::mcc_time_duration_c<T>) {
|
||||
(*this)(value.count(), bytes);
|
||||
} else if constexpr (mcc_telemetry_data_c<T>) {
|
||||
static MccTelemetryDataSerializer sr;
|
||||
|
||||
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
sr.setFormat(_coordFmt);
|
||||
sr.setPrecision(_coordPrec);
|
||||
|
||||
sr(value, bytes);
|
||||
} else if constexpr (mcc_eqt_hrz_coord_c<T>) {
|
||||
// output format: RA, DEC, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point
|
||||
// in the case of sexagesimal output X,Y coordinates will be interpretated
|
||||
// according to value.pair_kind field
|
||||
if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) {
|
||||
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
MccAngle(value.RA).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.DEC).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.HA).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.AZ).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.ZD).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.ALT).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.X).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.Y).degrees());
|
||||
} else {
|
||||
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
MccAngle(value.RA).sexagesimal(true, _currentCoordPrec.hour_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.DEC).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.HA).sexagesimal(true, _currentCoordPrec.hour_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.AZ).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.ZD).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
|
||||
MccAngle(value.ALT).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
static MccEqtHrzCoordsSerializer sr;
|
||||
|
||||
// interpretate X,Y angles according to .pair_kind field
|
||||
switch (value.pair_kind) {
|
||||
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||
std::format_to(std::back_inserter(bytes), "{}{}{}{}",
|
||||
MccAngle(value.X).sexagesimal(true, _currentCoordPrec.hour_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
break;
|
||||
default:
|
||||
std::format_to(std::back_inserter(bytes), "{}{}",
|
||||
MccAngle(value.X).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
}
|
||||
std::format_to(std::back_inserter(bytes), "{}",
|
||||
MccAngle(value.Y).sexagesimal(false, _currentCoordPrec.deg_prec));
|
||||
}
|
||||
|
||||
std::format_to(std::back_inserter(bytes), "{0:}{1:}{2:}{3:%F}T{3:%T}",
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccCoordPairKindToStr(value.pair_kind),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.time_point);
|
||||
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
sr.setFormat(_coordFmt);
|
||||
sr.setPrecision(_coordPrec);
|
||||
|
||||
sr(value, bytes);
|
||||
} else if constexpr (mcc_celestial_point_c<T>) {
|
||||
if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) {
|
||||
std::format_to(std::back_inserter(bytes), "{}{}{}", MccAngle(value.X).degrees(),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccAngle(value.Y).degrees());
|
||||
} else {
|
||||
switch (value.pair_kind) {
|
||||
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||
std::format_to(std::back_inserter(bytes), "{}{}",
|
||||
MccAngle(value.X).sexagesimal(true, _currentCoordPrec.hour_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
break;
|
||||
default:
|
||||
std::format_to(std::back_inserter(bytes), "{}{}",
|
||||
MccAngle(value.X).sexagesimal(false, _currentCoordPrec.deg_prec),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
}
|
||||
MccCelestialPointSerializer sr;
|
||||
|
||||
std::format_to(std::back_inserter(bytes), "{}",
|
||||
MccAngle(value.Y).sexagesimal(false, _currentCoordPrec.deg_prec));
|
||||
}
|
||||
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
|
||||
sr.setFormat(_coordFmt);
|
||||
sr.setPrecision(_coordPrec);
|
||||
|
||||
std::format_to(std::back_inserter(bytes), "{0:}{1:}{2:}{3:%F}T{3:%T}",
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccCoordPairKindToStr(value.pair_kind),
|
||||
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.time_point);
|
||||
sr(value, bytes);
|
||||
} else if constexpr (std::ranges::range<T>) {
|
||||
auto sz = std::ranges::size(value);
|
||||
if (sz == 0) {
|
||||
@ -796,7 +667,7 @@ public:
|
||||
MccNetMessage(KT&& key, PTs&&... params)
|
||||
requires traits::mcc_output_char_range<BYTEREPR_T>
|
||||
{
|
||||
construct(std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||
construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||
}
|
||||
|
||||
template <traits::mcc_input_char_range R>
|
||||
@ -964,9 +835,22 @@ public:
|
||||
template <traits::mcc_input_char_range KT, typename... PTs>
|
||||
std::error_code construct(KT&& key, PTs&&... params)
|
||||
requires traits::mcc_output_char_range<BYTEREPR_T>
|
||||
{
|
||||
return construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||
}
|
||||
|
||||
//
|
||||
// serializing function SerFuncT - a callable with the signature:
|
||||
// template<typename T, mcc_output_char_range R>
|
||||
// void ser_func(const T& val, R&& buffer)
|
||||
//
|
||||
template <typename SerFuncT, traits::mcc_input_char_range KT, typename... PTs>
|
||||
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
|
||||
requires(traits::mcc_output_char_range<BYTEREPR_T> &&
|
||||
!traits::mcc_input_char_range<std::remove_cvref_t<SerFuncT>>)
|
||||
{
|
||||
if constexpr (std::is_pointer_v<std::decay_t<KT>>) {
|
||||
return construct(std::string_view(key), std::forward<PTs>(params)...);
|
||||
return construct(std::forward<SerFuncT>(ser_func), std::string_view(key), std::forward<PTs>(params)...);
|
||||
}
|
||||
|
||||
|
||||
@ -993,7 +877,7 @@ public:
|
||||
if constexpr (sizeof...(PTs)) {
|
||||
std::ranges::copy(MCC_COMMPROTO_KEYPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
|
||||
|
||||
convertFunc(par_idx, std::forward<PTs>(params)...);
|
||||
convertFunc(std::forward<SerFuncT>(ser_func), par_idx, std::forward<PTs>(params)...);
|
||||
|
||||
for (size_t i = 0; i < par_idx.size(); i += 2) {
|
||||
_params.emplace_back(_msgBuffer.begin() + par_idx[i], _msgBuffer.begin() + par_idx[i + 1]);
|
||||
@ -1005,7 +889,6 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
template <traits::mcc_input_char_range R>
|
||||
constexpr MccNetMessageError fromCharRange(const R& r)
|
||||
{
|
||||
@ -1072,30 +955,68 @@ protected:
|
||||
template <typename T, typename... Ts>
|
||||
void convertFunc(std::vector<size_t>& idx, const T& par, const Ts&... pars)
|
||||
{
|
||||
if constexpr (std::same_as<T, MccNetMessageCoordFormat>) {
|
||||
_defaultSerializer.setCoordFormat(par);
|
||||
if constexpr (std::same_as<T, MccCoordinateSerializer::SerializedCoordFormat>) {
|
||||
_defaultSerializer._coordFmt = par;
|
||||
if constexpr (sizeof...(Ts)) {
|
||||
convertFunc(idx, pars...);
|
||||
}
|
||||
} else if constexpr (std::same_as<T, MccNetMessageCoordPrec>) {
|
||||
_defaultSerializer.setCoordPrec(par);
|
||||
} else if constexpr (std::same_as<T, MccCoordinateSerializer::SexagesimalCoordPrec>) {
|
||||
_defaultSerializer._coordPrec = par;
|
||||
if constexpr (sizeof...(Ts)) {
|
||||
convertFunc(idx, pars...);
|
||||
}
|
||||
} else {
|
||||
convertFunc(_defaultSerializer, idx, par, pars...);
|
||||
// idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
// _defaultSerializer(par, _msgBuffer);
|
||||
|
||||
// idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
// if constexpr (sizeof...(Ts)) {
|
||||
// std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
|
||||
|
||||
// convertFunc(idx, pars...);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
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::derived_from<std::remove_cvref_t<SerFuncT>, DefaultSerializer>) {
|
||||
if constexpr (std::same_as<T, MccCoordinateSerializer::SerializedCoordFormat>) {
|
||||
_defaultSerializer._coordFmt = par;
|
||||
} else if constexpr (std::same_as<T, MccCoordinateSerializer::SexagesimalCoordPrec>) {
|
||||
_defaultSerializer._coordPrec = par;
|
||||
} else {
|
||||
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
std::forward<SerFuncT>(ser_func)(par, _msgBuffer);
|
||||
|
||||
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
if constexpr (sizeof...(Ts)) {
|
||||
std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
_defaultSerializer(par, _msgBuffer);
|
||||
std::forward<SerFuncT>(ser_func)(par, _msgBuffer);
|
||||
|
||||
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||
|
||||
if constexpr (sizeof...(Ts)) {
|
||||
std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
|
||||
|
||||
convertFunc(idx, pars...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if constexpr (sizeof...(Ts)) {
|
||||
convertFunc(std::forward<SerFuncT>(ser_func), idx, pars...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(MccNetMessage<std::string, MccNetMessageValidKeywords>{"ACK"}.withKey("ACK"));
|
||||
|
||||
@ -60,7 +60,9 @@ int main()
|
||||
.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", mcc::network::MccNetMessageCoordPrec{2, 3}, cpt);
|
||||
// msg2.construct("ACK", "MOUNT", mcc::network::MccNetMessageCoordPrec{2, 3}, cpt);
|
||||
msg2.construct("ACK", "MOUNT", mcc::MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM,
|
||||
mcc::MccCoordinateSerializer::SexagesimalCoordPrec{3, 2}, cpt);
|
||||
std::cout << "MSG2: " << msg2.byteRepr() << "\n";
|
||||
auto cpt1 = msg2.paramValue<mcc::MccCelestialPoint>(1);
|
||||
if (cpt1) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user