This commit is contained in:
2026-02-13 09:57:10 +03:00
parent affaf176e5
commit accbeff765
3 changed files with 235 additions and 8 deletions

View File

@@ -217,6 +217,7 @@ set(MCC_SRC
mcc_serialization_common.h mcc_serialization_common.h
mcc_deserializer.h mcc_deserializer.h
mcc_serializer.h mcc_serializer.h
mcc_generic_mount.h
) )
if(USE_SPDLOG) if(USE_SPDLOG)

View File

@@ -979,17 +979,17 @@ concept mcc_mount_status_c = requires {
template <typename T> template <typename T>
concept mcc_generic_mount_c = concept mcc_generic_mount_c = mcc_logger_c<T> && mcc_pzone_container_c<T> && mcc_telemetry_c<T> &&
mcc_logger_c<T> && mcc_pzone_container_c<T> && mcc_telemetry_c<T> && mcc_movement_controls_c<T> && requires(T t) { mcc_movement_controls_c<T> && requires(T t, const T t_const) {
// error type // error type
requires mcc_error_c<typename T::error_t>; requires mcc_error_c<typename T::error_t>;
requires mcc_mount_status_c<typename T::mount_status_t>; requires mcc_mount_status_c<typename T::mount_status_t>;
{ t.initMount() } -> std::same_as<typename T::error_t>; { t.initMount() } -> std::same_as<typename T::error_t>;
{ t.mountStatus() } -> std::same_as<typename T::mount_status_t>; { t_const.mountStatus() } -> std::same_as<typename T::mount_status_t>;
}; };
} // namespace mcc } // namespace mcc

226
mcc_generic_mount.h Normal file
View File

@@ -0,0 +1,226 @@
#pragma once
/****************************************************************************************
* *
* MOUNT CONTROL COMPONENTS LIBRARY *
* *
* *
* IMPLEMENTATION OF A GENERIC MOUNT CLASS *
* (A SOME OF POSSIBLE GENERIC IMPLEMENTATIONS) *
* *
****************************************************************************************/
#include <thread>
#include "mcc_error.h"
namespace mcc::impl
{
enum class MccGenericMountErrorCode : int {
ERROR_OK,
ERROR_HW_INIT,
ERROR_HW_STOP,
ERROR_HW_GETSTATE,
ERROR_SET_TARGET,
ERROR_MOUNT_SLEW,
ERROR_MOUNT_TRACK,
ERROR_GET_TELEMETRY,
ERROR_UNSUPPORTED_TARGET_COORDPAIR,
ERROR_PZONE_COMP,
ERROR_TARGET_IN_ZONE
};
enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT };
} // namespace mcc::impl
namespace std
{
template <>
class is_error_code_enum<mcc::impl::MccGenericMountErrorCode> : public true_type
{
};
} // namespace std
namespace mcc::impl
{
// error category
struct MccGenericMountCategory : public std::error_category {
MccGenericMountCategory() : std::error_category() {}
const char* name() const noexcept
{
return "MCC-GENERIC-MOUNT";
}
std::string message(int ec) const
{
MccGenericMountErrorCode err = static_cast<MccGenericMountErrorCode>(ec);
switch (err) {
case MccGenericMountErrorCode::ERROR_OK:
return "OK";
case MccGenericMountErrorCode::ERROR_HW_INIT:
return "an error occured while initializing mount";
case MccGenericMountErrorCode::ERROR_HW_STOP:
return "an error occured while stopping mount";
case MccGenericMountErrorCode::ERROR_HW_GETSTATE:
return "cannot get state of hardware";
case MccGenericMountErrorCode::ERROR_SET_TARGET:
return "cannot set target coordinates";
case MccGenericMountErrorCode::ERROR_MOUNT_SLEW:
return "slewing error";
case MccGenericMountErrorCode::ERROR_MOUNT_TRACK:
return "tracking error";
case MccGenericMountErrorCode::ERROR_GET_TELEMETRY:
return "cannot get telemetry data";
case MccGenericMountErrorCode::ERROR_UNSUPPORTED_TARGET_COORDPAIR:
return "unsupported coordinate pair of target";
case MccGenericMountErrorCode::ERROR_PZONE_COMP:
return "an error occured while computing prohibited zone";
case MccGenericMountErrorCode::ERROR_TARGET_IN_ZONE:
return "target coordinates are in prohibitted zone";
default:
return "UNKNOWN";
}
}
static const MccGenericMountCategory& get()
{
static const MccGenericMountCategory constInst;
return constInst;
}
};
inline std::error_code make_error_code(MccGenericMountErrorCode ec)
{
return std::error_code(static_cast<int>(ec), MccGenericMountCategory::get());
}
template <mcc_hardware_c HARDWARE_T,
mcc_telemetry_c TELEMETRY_T,
mcc_pzone_container_c PZONE_CONT_T,
mcc_movement_controls_c MOVE_CNTRL_T,
mcc_logger_c LOGGER_T>
class MccGenericMount : protected HARDWARE_T,
public TELEMETRY_T,
public PZONE_CONT_T,
public MOVE_CNTRL_T,
public LOGGER_T
{
public:
using LOGGER_T::logDebug;
using LOGGER_T::logError;
using LOGGER_T::logInfo;
using LOGGER_T::logTrace;
using LOGGER_T::logWarn;
typedef MccError error_t;
using typename TELEMETRY_T::telemetry_data_t;
enum class mount_status_t : int {
MOUNT_STATUS_ERROR,
MOUNT_STATUS_IDLE,
MOUNT_STATUS_UNINITIALIZED,
MOUNT_STATUS_INITIALIZATION,
MOUNT_STATUS_STOPPED,
MOUNT_STATUS_STOPPING,
MOUNT_STATUS_SLEWING,
MOUNT_STATUS_ADJUSTING,
MOUNT_STATUS_GUIDING,
MOUNT_STATUS_TRACKING
};
template <typename... HardwareCtorTs,
typename... TelemetryCtorTs,
typename... PzoneContCtorTs,
typename... MoveCntrCtorTs,
typename... LoggerCtorTs>
MccGenericMount(std::tuple<HardwareCtorTs...> hw_ctor_args,
std::tuple<TelemetryCtorTs...> telemetry_ctor_args,
std::tuple<PzoneContCtorTs...> pzone_cont_ctor_ars,
std::tuple<MoveCntrCtorTs...> move_cntrl_ctor_ars,
std::tuple<LoggerCtorTs...> logger_ctor_args)
: HARDWARE_T(std::make_from_tuple<HARDWARE_T>(std::move(hw_ctor_args))),
TELEMETRY_T(std::make_from_tuple<TELEMETRY_T>(std::move(telemetry_ctor_args))),
PZONE_CONT_T(std::make_from_tuple<PZONE_CONT_T>(pzone_cont_ctor_ars)),
MOVE_CNTRL_T(std::make_from_tuple<MOVE_CNTRL_T>(move_cntrl_ctor_ars)),
LOGGER_T(std::make_from_tuple<LOGGER_T>(logger_ctor_args))
{
logDebug(std::format("Create MccGenericMount class instance (thread: {})", std::this_thread::get_id()));
}
MccGenericMount(const MccGenericMount&) = delete;
MccGenericMount(MccGenericMount&&) = default;
MccGenericMount& operator=(const MccGenericMount&) = delete;
MccGenericMount& operator=(MccGenericMount&&) = default;
virtual ~MccGenericMount()
{
logDebug(std::format("Delete MccGenericMount class instance (thread: {})", std::this_thread::get_id()));
auto err = MOVE_CNTRL_T::stopMount();
if (err) {
logError(formatError(err));
}
}
error_t initMount()
{
logInfo(std::format("Start MccGenericMount class initialization (thread: {}) ...", std::this_thread::get_id()));
*_lastMountError = MccGenericMountErrorCode::ERROR_OK;
*_mountStatus = mount_status_t::MOUNT_STATUS_INITIALIZATION;
auto hw_err = this->hardwareInit();
if (hw_err) {
*_mountStatus = mount_status_t::MOUNT_STATUS_ERROR;
*_lastMountError = mcc_deduce_err(hw_err, MccGenericMountErrorCode::ERROR_HW_INIT);
} else {
logInfo("Generic mount initialization was performed");
*_mountStatus = mount_status_t::IDLE;
}
return *_lastMountError;
}
mount_status_t mountStatus() const
{
return _mountStatus->load();
}
error_t mountLastError() const
{
return _lastMountError->load();
}
protected:
std::unique_ptr<std::atomic<mount_status_t>> _mountStatus{
new std::atomic<mount_status_t>{mount_status_t::MOUNT_STATUS_UNINITIALIZED}};
std::unique_ptr<std::atomic<error_t>> _lastMountError{new std::atomic<error_t>{MccGenericMountErrorCode::ERROR_OK}};
std::string formatError(error_t const& err, std::string_view prefix = "") const
{
return std::format("{}{} (category: {}, code: {})", prefix, err.message(), err.value(), err.category().name());
}
};
} // namespace mcc::impl