This commit is contained in:
Timur A. Fatkhullin 2025-10-29 15:07:53 +03:00
parent 78e4bb182c
commit bc300bb3de
6 changed files with 508 additions and 166 deletions

View File

@ -6,10 +6,47 @@ namespace asibfm700
template <mcc::traits::mcc_range_of_input_char_range R>
Asibfm700MountNetServer::Asibfm700MountNetServer(asio::io_context& ctx,
Asibfm700Mount& mount,
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)
: base_t(ctx, mount, std::move(logger), pattern_range)
{
// to avoid possible compiler optimization (one needs to catch 'mount' strictly by reference)
auto* mount_ptr = &mount;
base_t::_handleMessageFunc = [base_hndl_func = std::move(base_t::_handleMessageFunc), mount_ptr,
this](std::string_view command) {
using mount_error_t = typename Asibfm700Mount::error_t;
std::error_code err{};
Asibfm700NetMessage input_msg;
Asibfm700NetMessage<handle_message_func_result_t> output_msg;
auto ec = parseMessage(command, input_msg);
if (ec) {
output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec);
} else {
if (input_msg.withKey(ASIBFM700_COMMPROTO_KEYWORD_METEO_STR)) {
// what is operation type (set or get)?
if (input_msg.paramSize()) { // set operation
auto vp = input_msg.paramValue<Asibfm700CCTE::meteo_t>(0);
if (vp) {
mount_ptr->updateMeteoERFA(vp.value());
} else {
output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, vp.error());
}
} else { // get operation
output_msg.construct(mcc::network::MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR,
ASIBFM700_COMMPROTO_KEYWORD_METEO_STR, mount_ptr->getStateERFA().meteo);
}
} else {
output_msg = base_t::handleMessage<decltype(output_msg)>(input_msg, mount_ptr);
}
}
return output_msg.byteRepr();
};
}
} // namespace asibfm700

View File

@ -4,6 +4,7 @@
#include <mcc_netserver_proto.h>
#include "asibfm700_common.h"
#include "asibfm700_mount.h"
namespace asibfm700
{
@ -57,11 +58,59 @@ struct Asibfm700NetMessageValidKeywords {
};
template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view>
class Asibfm700MountNetMessage : public mcc::network::MccNetMessage<BYTEREPR_T, Asibfm700NetMessageValidKeywords>
class Asibfm700NetMessage : public mcc::network::MccNetMessage<BYTEREPR_T, Asibfm700NetMessageValidKeywords>
{
protected:
using base_t = mcc::network::MccNetMessage<BYTEREPR_T, Asibfm700NetMessageValidKeywords>;
class serializer_t : public base_t::DefaultSerializer
{
public:
template <typename T, mcc::traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
if constexpr (std::same_as<T, Asibfm700CCTE::meteo_t>) {
// serialize just like a vector
std::vector<double> meteo{value.temperature, value.humidity, value.pressure};
base_t::operator()(meteo, bytes);
} else {
base_t::operator()(value, bytes);
}
}
} _serializer;
class deserializer_t : public base_t::DefaultDeserializer
{
public:
template <mcc::traits::mcc_input_char_range IR, typename VT>
std::error_code operator()(IR&& bytes, VT& value)
{
if constexpr (std::same_as<VT, Asibfm700CCTE::meteo_t>) {
// deserialize just like a vector
std::vector<double> v;
auto ec = base_t::operator()(std::forward<IR>(bytes), v);
if (ec) {
return ec;
}
if (v.size() < 3) {
return std::make_error_code(std::errc::invalid_argument);
}
value.temperature = v[0];
value.humidity = v[1];
value.pressure = v[2];
return {};
} else {
return base_t::operator()(std::forward<IR>(bytes), value);
}
}
} _deserializer;
public:
using base_t::base_t;
@ -69,7 +118,7 @@ public:
template <typename T>
std::expected<T, std::error_code> paramValue(size_t idx)
{
return paramValue<T>(idx, _defaultDeserilizer);
return paramValue<T>(idx, _deserializer);
}
@ -78,19 +127,20 @@ public:
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)...);
return construct(_serializer, std::forward<KT>(key), std::forward<PTs>(params)...);
}
};
class Asibfm700MountNetServer : public mcc::network::MccGenericNetworkServer<Asibfm700Logger>
class Asibfm700MountNetServer : public mcc::network::MccGenericMountNetworkServer<Asibfm700Logger>
{
using _base_t = mcc::network::MccGenericNetworkServer<Asibfm700Logger>;
using base_t = mcc::network::MccGenericMountNetworkServer<Asibfm700Logger>;
public:
template <mcc::traits::mcc_range_of_input_char_range R = decltype(Asibfm700Logger::LOGGER_DEFAULT_FORMAT)>
Asibfm700MountNetServer(asio::io_context& ctx,
Asibfm700Mount& mount,
std::shared_ptr<spdlog::logger> logger,
const R& pattern_range = Asibfm700Logger::LOGGER_DEFAULT_FORMAT);

View File

@ -19,7 +19,8 @@ enum class MccGenericMountErrorCode : int {
ERROR_HW_STOP,
ERROR_HW_GETSTATE,
ERROR_SET_TARGET,
ERROR_MOUNT_SLEW
ERROR_MOUNT_SLEW,
ERROR_MOUNT_TRACK
};
enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT };
@ -152,6 +153,9 @@ public:
using typename SlewModelT::slewing_params_t;
using typename TrackModelT::tracking_params_t;
enum class mount_status_t : int { IDLE, INITIALIZATION, STOPPED, SLEWING, ADJUSTING, TRACKING, ERROR };
MccGenericMount(HardwareT hardware,
TelemetryT telemetry,
PZoneContT pzone_cont,
@ -163,8 +167,10 @@ public:
PZoneContT(std::move(pzone_cont)),
SlewModelT(std::move(slew_model)),
TrackModelT(std::move(track_model)),
LoggerT(std::move(logger))
LoggerT(std::move(logger)),
_mountStatus(new mount_status_t)
{
*_mountStatus = mount_status_t::IDLE;
}
MccGenericMount(MccGenericMount&&) = default;
@ -173,7 +179,10 @@ public:
MccGenericMount& operator=(MccGenericMount&&) = default;
MccGenericMount& operator=(const MccGenericMount&) = delete;
virtual ~MccGenericMount() = default;
virtual ~MccGenericMount()
{
stopMount();
};
error_t stopMount()
{
@ -184,11 +193,15 @@ public:
auto hw_err = this->hardwareStop();
if (hw_err) {
*_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
}
logInfo("Stop command was sent");
*_mountStatus = mount_status_t::STOPPED;
return MccGenericMountErrorCode::ERROR_OK;
}
@ -196,13 +209,19 @@ public:
{
logInfo("Start generic mount initialization ...");
*_mountStatus = mount_status_t::INITIALIZATION;
auto hw_err = this->hardwareInit();
if (hw_err) {
*_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
}
logInfo("Generic mount initialization was performed");
*_mountStatus = mount_status_t::IDLE;
return MccGenericMountErrorCode::ERROR_OK;
}
@ -231,17 +250,66 @@ public:
// re-implements SlewModelT::slewToTarget to fetch input target coordinates from intermediate buffer
error_t slewToTarget(bool slew_and_stop = false)
{
*_mountStatus = mount_status_t::SLEWING;
auto err = TelemetryT::setPointingTarget(_enteredTargetCoordiniates);
if (err) {
*_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_SET_TARGET);
}
if (slew_and_stop) {
*_mountStatus = mount_status_t::IDLE;
}
return mcc_deduce_error_code(SlewModelT::slewToTarget(slew_and_stop),
MccGenericMountErrorCode::ERROR_MOUNT_SLEW);
}
error_t trackTarget()
{
auto err = TrackModelT::traclTarget();
if (err) {
*_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_MOUNT_TRACK);
}
*_mountStatus = mount_status_t::TRACKING;
return MccGenericMountErrorCode::ERROR_OK;
}
error_t stopSlewing()
{
*_mountStatus = mount_status_t::IDLE;
SlewModelT::stopSlewing();
return MccGenericMountErrorCode::ERROR_OK;
}
error_t stopTracking()
{
*_mountStatus = mount_status_t::IDLE;
TrackModelT::stopTracking();
return MccGenericMountErrorCode::ERROR_OK;
}
MccGenericMount::mount_status_t mountStatus() const
{
return _mountStatus.get();
}
protected:
MccCelestialPoint _enteredTargetCoordiniates;
MccCelestialPoint _enteredTargetCoordiniates{};
std::unique_ptr<std::atomic<MccGenericMount::mount_status_t>> _mountStatus;
};

View File

@ -975,7 +975,7 @@ concept mcc_all_controls_c = mcc_position_controls_c<T> && mcc_telemetry_c<T> &&
// 2) prohibited zones related methods
// 3) slewing and tracking, stop and init mount methods
template <typename T>
concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> && requires(T t) {
concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> && requires(T t, const T t_const) {
// requires mcc_error_c<typename T::error_t>;
// slew mount to target (it is assumed that the target coordinates are determined in the telemetry data)
@ -996,6 +996,42 @@ concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> &&
// init mount
{ t.initMount() };
//
// minimal set of mount status mnemonic constants
//
requires requires(typename T::mount_status_t type) {
requires std::formattable<
std::conditional_t<std::is_enum_v<typename T::mount_status_t>,
std::underlying_type_t<typename T::mount_status_t>, typename T::mount_status_t>,
char>;
[]() {
// mount initialization
static constexpr auto v1 = T::mount_status_t::INITIALIZATION;
// IDLE
static constexpr auto v2 = T::mount_status_t::IDLE;
// mount is in state after the stopMount() method invoking
static constexpr auto v3 = T::mount_status_t::STOPPED;
// mount is slewing (move to given celestial point)
static constexpr auto v4 = T::mount_status_t::SLEWING;
// mount is adjusting its position in the end of slewing
// (adjusting actual mount position to align with target celestial point at the end of slewing process)
static constexpr auto v5 = T::mount_status_t::ADJUSTING;
// mount is tracking
static constexpr auto v6 = T::mount_status_t::TRACKING;
// an error occured while mount operation
static constexpr auto v7 = T::mount_status_t::ERROR;
}();
};
{ t_const.mountStatus() } -> std::same_as<typename T::mount_status_t>;
};
@ -1011,6 +1047,4 @@ concept mcc_generic_fsm_mount_c = mcc_generic_mount_c<T> && std::derived_from<T,
template <typename T>
concept mcc_generic_fsm_log_mount_c =
mcc_generic_mount_c<T> && mcc_logger_c<T> && std::derived_from<T, fsm::MccFiniteStateMachine>;
} // namespace mcc

View File

@ -899,154 +899,317 @@ public:
MccGenericMountNetworkServer(asio::io_context& ctx, MountT& mount, LoggerCtorArgsTs&&... log_args)
: base_t(ctx, {}, std::forward<LoggerCtorArgsTs>(log_args)...)
{
base_t::_handleMessageFunc = [mount = std::move(mount), this](std::string_view command) {
using mount_error_t = decltype(mount)::error_t;
// to avoid possible compiler optimization (one needs to catch 'mount' strictly by reference)
auto* mount_ptr = &mount;
base_t::_handleMessageFunc = [mount_ptr, this](std::string_view command) {
using mount_error_t = typename MountT::error_t;
mount_error_t m_err;
MccNetMessage input_msg;
MccNetMessage<handle_message_func_result_t> output_msg;
std::error_code err{};
if (auto ec = parseMessage(command, input_msg)) {
auto ec = parseMessage(command, input_msg);
if (ec) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec);
} else {
if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange!
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
} else if (input_msg.withKey(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)) {
this->restart();
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) {
m_err = mount.initMount();
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) {
m_err = mount.stopMount();
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) {
m_err = mount.slewToTarget(false);
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) {
m_err = mount.slewToTarget(true);
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) {
m_err = mount.trackTarget();
if (m_err) {
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<MccCoordinateSerializer::SerializedCoordFormat>(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<MccCoordinateSerializer::SexagesimalCoordPrec>(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) {
if (m_err) {
err = mcc_deduce_error_code(
m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET);
}
} 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,
_coordFormat, _coordPrec, 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,
_coordFormat, _coordPrec, cp);
}
}
} else {
err = std::make_error_code(std::errc::invalid_argument);
}
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);
// }
output_msg = handleMessage<decltype(output_msg)>(input_msg, mount_ptr);
}
return output_msg.byteRepr();
// std::error_code err{};
// if (auto ec = parseMessage(command, input_msg)) {
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, ec);
// } else {
// if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange!
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
// } else if (input_msg.withKey(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)) {
// this->restart();
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, command);
// } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) {
// m_err = mount_ptr->initMount();
// if (m_err) {
// err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT);
// }
// } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) {
// m_err = mount_ptr->stopMount();
// if (m_err) {
// err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP);
// }
// } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) {
// m_err = mount_ptr->slewToTarget(false);
// if (m_err) {
// err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW);
// }
// } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) {
// m_err = mount_ptr->slewToTarget(true);
// if (m_err) {
// err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE);
// }
// } else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) {
// m_err = mount_ptr->trackTarget();
// if (m_err) {
// 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<MccCoordinateSerializer::SerializedCoordFormat>(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<MccCoordinateSerializer::SexagesimalCoordPrec>(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_ptr->setPointingTarget(vc.value());
// if (m_err) {
// if (m_err) {
// err = mcc_deduce_error_code(
// m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET);
// }
// } 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_ptr, 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_ptr, true, cp);
// if (!err) {
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR,
// MCC_COMMPROTO_KEYWORD_TARGET_STR,
// _coordFormat, _coordPrec, 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_ptr, 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_ptr, false, cp);
// if (!err) {
// output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR,
// MCC_COMMPROTO_KEYWORD_MOUNT_STR,
// _coordFormat, _coordPrec, cp);
// }
// }
// } else {
// err = std::make_error_code(std::errc::invalid_argument);
// }
// 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.byteRepr();
};
}
virtual ~MccGenericMountNetworkServer() {}
protected:
// 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 RESULT_MSG_T, typename INPUT_MSG_T, mcc_generic_mount_c MountT>
RESULT_MSG_T handleMessage(const INPUT_MSG_T& input_msg, MountT* mount_ptr)
requires(
std::derived_from<RESULT_MSG_T,
MccNetMessage<typename RESULT_MSG_T::byte_repr_t, typename RESULT_MSG_T::valid_keys_t>> &&
std::derived_from<INPUT_MSG_T,
MccNetMessage<typename INPUT_MSG_T::byte_repr_t, typename INPUT_MSG_T::valid_keys_t>>)
{
using mount_error_t = typename MountT::error_t;
mount_error_t m_err;
RESULT_MSG_T output_msg;
std::error_code err{};
if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR)) { // strange!
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR)) { // ??!!!
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR)) {
this->restart();
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STATUS_STR)) {
auto st = mount_ptr->status(); // according to mcc_generic_mount_c 'st' is formattable
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_STATUS_STR, st);
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_INIT_STR)) {
m_err = mount_ptr->initMount();
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_INIT);
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_INIT_STR);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_STOP_STR)) {
m_err = mount_ptr->stopMount();
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_STOP);
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_STOP_STR);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_SLEW_STR)) {
m_err = mount_ptr->slewToTarget(false);
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SLEW);
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SLEW_STR);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_MOVE_STR)) {
m_err = mount_ptr->slewToTarget(true);
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_MOVE);
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_MOVE_STR);
}
} else if (input_msg.withKey(MCC_COMMPROTO_KEYWORD_TRACK_STR)) {
m_err = mount_ptr->trackTarget();
if (m_err) {
err = mcc_deduce_error_code(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_TRACK);
} else {
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();
}
} 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();
}
} 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.template paramValue<MccCelestialPoint>(0); // is it set operation?
if (vc) { // coordinates are given - 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);
}
} else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
}
} else {
auto vp = input_msg.template paramValue<MccCoordPairKind>(0);
if (vp) { // coordinate pair kind is given
cp.pair_kind = vp.value();
err = coordsFromTelemetryData(*mount_ptr, 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_ptr, true, cp);
if (!err) {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR,
_coordFormat, _coordPrec, 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.template paramValue<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, cp);
}
} else { // invalid command!!!
err = vp.error();
}
} else {
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 {
err = std::make_error_code(std::errc::invalid_argument);
}
if (err) { // send error description
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, err);
}
return output_msg;
}
template <typename MSG_T>
std::error_code parseMessage(std::string_view msg_bytes, MSG_T& msg)
{

View File

@ -493,18 +493,6 @@ template <typename 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 corresponding 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,
mcc_netmsg_valid_keys_c BASE_T = MccNetMessageValidKeywords>
@ -537,7 +525,7 @@ protected:
if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
return std::make_error_code(std::errc::invalid_argument);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordFormat>) {
} else if constexpr (std::same_as<VT, MccCoordinateSerializer::SerializedCoordFormat>) {
std::string v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
@ -545,13 +533,13 @@ protected:
}
if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR) == 0) {
value = MccNetMessageCoordFormat::CFMT_SGM;
value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM;
} else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) {
value = MccNetMessageCoordFormat::CFMT_DEGREES;
value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_DEGREES;
} else {
return std::make_error_code(std::errc::invalid_argument);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordPrec>) {
} else if constexpr (std::same_as<VT, MccCoordinateSerializer::SexagesimalCoordPrec>) {
std::vector<int64_t> v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
@ -683,8 +671,10 @@ public:
// fromCharRange(msg);
// }
virtual ~MccNetMessage() = default;
template <traits::mcc_input_char_range KT>
constexpr bool withKey(const KT& key)
constexpr bool withKey(const KT& key) const
{
if constexpr (std::is_pointer_v<std::decay_t<KT>>) {
return withKey(std::string_view{key});
@ -719,7 +709,7 @@ public:
}
template <std::ranges::range R>
R params(size_t start_idx = 0, 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()) const
requires(traits::mcc_view_or_output_char_range<R> || traits::mcc_range_of_char_range<R>)
{
if (start_idx >= _params.size()) {
@ -758,13 +748,13 @@ public:
}
}
std::string_view params(size_t start_idx = 0, 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()) const
{
return params<std::string_view>(start_idx, Nelemes);
}
template <traits::mcc_view_or_output_char_range R>
R param(size_t idx)
R param(size_t idx) const
{
if (idx >= _params.size()) {
return {};
@ -780,7 +770,7 @@ public:
}
}
std::string_view param(size_t idx)
std::string_view param(size_t idx) const
{
if (idx >= _params.size()) {
return {};
@ -791,7 +781,7 @@ public:
template <typename T, typename DeserFuncT>
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func)
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const
{
if (idx >= _params.size()) {
return std::unexpected{std::make_error_code(std::errc::argument_out_of_domain)};
@ -808,9 +798,9 @@ public:
}
template <typename T>
std::expected<T, std::error_code> paramValue(size_t idx)
std::expected<T, std::error_code> paramValue(size_t idx) const
{
return paramValue<T>(idx, _defaultDeserilizer);
return paramValue<T>(idx, _defaultDeserializer);
}
@ -948,7 +938,7 @@ protected:
BYTEREPR_T _msgBuffer{};
inline static DefaultDeserializer _defaultDeserilizer{};
inline static DefaultDeserializer _defaultDeserializer{};
DefaultSerializer _defaultSerializer{};