This commit is contained in:
Timur A. Fatkhullin 2025-09-12 18:31:15 +03:00
parent 5f802ff57e
commit c7dd816481
3 changed files with 294 additions and 87 deletions

View File

@ -50,7 +50,7 @@ public:
Asibfm700Mount(Asibfm700MountConfig const& config,
std::shared_ptr<spdlog::logger> logger,
const auto& pattern_range = LOGGER_DEFAULT_FORMAT);
const auto& pattern_range = mcc::utils::MccSpdlogLogger::LOGGER_DEFAULT_FORMAT);
~Asibfm700Mount();
};

View File

@ -52,7 +52,7 @@ struct MccFiniteStateMachineCategory : public std::error_category {
const char* name() const noexcept
{
return "ADC_GENERIC_DEVICE";
return "MCC-FSM-ERROR-CATEGORY";
}
std::string message(int ec) const

View File

@ -14,6 +14,8 @@ namespace mcc
enum class MccGenericMountErrorCode : int { ERROR_OK, ERROR_HW_INIT, ERROR_HW_STOP, ERROR_HW_GETSTATE };
enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT };
} // namespace mcc
@ -25,6 +27,11 @@ class is_error_code_enum<mcc::MccGenericMountErrorCode> : public true_type
{
};
template <>
class is_error_code_enum<mcc::MccGenericFsmMountErrorCode> : public true_type
{
};
} // namespace std
@ -75,6 +82,12 @@ public:
{
}
MccGenericMount(MccGenericMount&&) = default;
MccGenericMount(const MccGenericMount&) = delete;
MccGenericMount& operator=(MccGenericMount&&) = default;
MccGenericMount& operator=(const MccGenericMount&) = delete;
virtual ~MccGenericMount() = default;
error_t stopMount()
@ -114,20 +127,29 @@ public:
/* GENERIC FINITE-STATE-MACHINE MOUNT REFERENCE IMPLEMENTATION */
template <typename T>
concept mcc_generic_fsm_mount_event_c =
fsm::traits::fsm_event_c<T> && std::constructible_from<typename T::mount_t*> && requires(T t) {
{ t.mount() } -> std::same_as<typename T::mount_t*>;
};
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountBaseEvent {
typedef MOUNT_T mount_t;
// static constexpr std::string_view ID{""};
virtual ~MccGenericFsmMountBaseEvent() = default;
MOUNT_T& mount() const
MOUNT_T* mount() const
{
return _mount;
}
protected:
MOUNT_T& _mount;
MOUNT_T* _mount;
MccGenericFsmMountBaseEvent(MOUNT_T& mount) : _mount(mount) {}
MccGenericFsmMountBaseEvent(MOUNT_T* mount) : _mount(mount) {}
};
@ -141,7 +163,24 @@ template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountStopEvent;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountErrorEvent;
struct MccGenericFsmMountErrorEvent : MccGenericFsmMountBaseEvent<MOUNT_T> {
static constexpr std::string_view ID{"GENERIC-MOUNT-ERROR-EVENT"};
typedef typename MOUNT_T::error_t mount_error_t;
MccGenericFsmMountErrorEvent(MOUNT_T* mount, const mount_error_t& err)
: MccGenericFsmMountBaseEvent<MOUNT_T>(mount), _err(err)
{
}
mount_error_t eventData() const noexcept
{
return _err;
}
protected:
mount_error_t _err;
};
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountSlewEvent;
@ -149,138 +188,306 @@ struct MccGenericFsmMountSlewEvent;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountTrackEvent;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountBaseState {
// static constexpr std::string_view ID{""};
virtual ~MccGenericFsmMountBaseState() = default;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountBaseState {
// typedef MOUNT_T mount_t;
protected:
MccGenericFsmMountBaseState() = default;
// virtual ~MccGenericFsmMountBaseState() = default;
template <fsm::traits::fsm_event_c EvT>
void exitLog(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
// protected:
// MccGenericFsmMountBaseState() = default;
if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
event.mount().logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
}
}
// template <fsm::traits::fsm_event_c EvT>
// void exitLog(this auto&& self, EvT& event)
// {
// using self_t = std::remove_cvref_t<decltype(self)>;
template <fsm::traits::fsm_event_c EvT>
void enterLog(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
// if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
// std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
// event.mount()->logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
// }
// }
if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
event.mount().logDebug(std::format("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
}
}
};
// template <fsm::traits::fsm_event_c EvT>
// void enterLog(this auto&& self, EvT& event)
// {
// using self_t = std::remove_cvref_t<decltype(self)>;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountStartState;
// if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
// std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
// event.mount()->logDebug(std::format("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
// }
// }
// };
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountIdleState;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountStartState;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountStopState;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountIdleState;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountErrorState;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountStopState;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountSlewState;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountErrorState;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountTrackState;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountSlewState;
template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountInitState {
static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountTrackState;
using transition_t = fsm::fsm_transition_table_t<
std::pair<MccGenericFsmMountIdleEvent<MOUNT_T>, MccGenericFsmMountIdleState<MOUNT_T>>,
std::pair<MccGenericFsmMountErrorEvent<MOUNT_T>, MccGenericFsmMountErrorState<MOUNT_T>>,
std::pair<MccGenericFsmMountInitEvent<MOUNT_T>, MccGenericFsmMountInitState<MOUNT_T>>>;
// template <mcc_generic_mount_c MOUNT_T>
// struct MccGenericFsmMountInitState : MccGenericFsmMountBaseState<MOUNT_T> {
// static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
// using transition_t = fsm::fsm_transition_table_t<
// std::pair<MccGenericFsmMountIdleEvent<MOUNT_T>, MccGenericFsmMountIdleState<MOUNT_T>>,
// std::pair<MccGenericFsmMountErrorEvent<MOUNT_T>, MccGenericFsmMountErrorState<MOUNT_T>>,
// std::pair<MccGenericFsmMountInitEvent<MOUNT_T>, MccGenericFsmMountInitState<MOUNT_T>>>;
void exit(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount().logWarn("It seems a re-entering to the initializing state was asked! Ignore the event!");
}
}
// void exit(MccGenericFsmMountInitEvent<MOUNT_T>& event)
// {
// if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
// event.mount()->logWarn("It seems a re-entering to the initializing state was asked! Ignore the event!");
// }
// }
void enter(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount().logWarn(
"It seems a re-entering to the initializing state was asked! Ignore the event and wait for the mount "
"to initialize!");
}
}
// void enter(MccGenericFsmMountInitEvent<MOUNT_T>& event)
// {
// if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
// event.mount()->logWarn(
// "It seems a re-entering to the initializing state was asked! Ignore the event and wait for the mount
// " "to initialize!");
// }
// }
void exit(fsm::traits::fsm_event_c auto& event)
{
exitLog(event);
}
// void exit(fsm::traits::fsm_event_c auto& event)
// {
// exitLog(event);
// }
void enter(fsm::traits::fsm_event_c auto& event)
{
enterLog(event);
}
};
// void enter(fsm::traits::fsm_event_c auto& event)
// {
// enterLog(event);
// auto err = event.mount()->initMount();
// }
// };
template <mcc_generic_mount_c MOUNT_T,
fsm::traits::fsm_state_c START_STATE_T = MccGenericFsmMountStartState<MOUNT_T>,
fsm::traits::fsm_event_c INIT_EVENT_T = MccGenericFsmMountInitEvent<MOUNT_T>,
fsm::traits::fsm_event_c IDLE_EVENT_T = MccGenericFsmMountIdleEvent<MOUNT_T>,
fsm::traits::fsm_event_c STOP_EVENT_T = MccGenericFsmMountStopEvent<MOUNT_T>,
fsm::traits::fsm_event_c ERROR_EVENT_T = MccGenericFsmMountErrorEvent<MOUNT_T>,
fsm::traits::fsm_event_c SLEW_EVENT_T = MccGenericFsmMountSlewEvent<MOUNT_T>,
fsm::traits::fsm_event_c TRACK_EVENT_T = MccGenericFsmMountTrackEvent<MOUNT_T>>
mcc_generic_fsm_mount_event_c INIT_EVENT_T = MccGenericFsmMountInitEvent<MOUNT_T>,
mcc_generic_fsm_mount_event_c STOP_EVENT_T = MccGenericFsmMountStopEvent<MOUNT_T>,
mcc_generic_fsm_mount_event_c SLEW_EVENT_T = MccGenericFsmMountSlewEvent<MOUNT_T>,
mcc_generic_fsm_mount_event_c TRACK_EVENT_T = MccGenericFsmMountTrackEvent<MOUNT_T>>
class MccGenericFsmMount : public MOUNT_T, protected fsm::MccFiniteStateMachine
{
// to prevent infinite recursion!
static_assert(!std::derived_from<MOUNT_T, MccGenericFsmMount>, "!!!!!!!!!");
public:
using typename MOUNT_T::error_t;
typedef std::error_code error_t;
protected:
/* default states implementation */
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountBaseState {
virtual ~MccGenericFsmMountBaseState() = default;
protected:
MccGenericFsmMountBaseState() = default;
template <fsm::traits::fsm_event_c EvT>
void exitLog(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
event.mount()->logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
}
}
template <fsm::traits::fsm_event_c EvT>
void enterLog(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
event.mount()->logDebug(std::format("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
}
}
};
struct MccGenericFsmMountErrorState;
struct MccGenericFsmMountStartState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountIdleState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountStopState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountSlewState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountTrackState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
struct MccGenericFsmMountInitState : MccGenericFsmMountBaseState<ERROR_STATE_T> {
static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
using transition_t = fsm::fsm_transition_table_t<
std::pair<MccGenericFsmMountIdleEvent<MOUNT_T>, MccGenericFsmMountIdleState<MccGenericFsmMountErrorState>>,
std::pair<MccGenericFsmMountErrorEvent<MOUNT_T>, MccGenericFsmMountErrorState>,
std::pair<MccGenericFsmMountInitEvent<MOUNT_T>, MccGenericFsmMountInitState>>;
void exit(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount()->logWarn("It seems a re-entering to the initializing state was asked! Ignore the event!");
}
}
void enter(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount()->logWarn(
"It seems a re-entering to the initializing state was asked! Ignore the event and wait for the "
"mount "
"to initialize!");
}
}
void exit(fsm::traits::fsm_event_c auto& event)
{
exitLog(event);
}
void enter(fsm::traits::fsm_event_c auto& event)
{
enterLog(event);
auto err = event.mount()->initMount();
}
};
struct MccGenericFsmMountErrorState // default implementation (just log error)
{
static constexpr std::string_view ID{"GENERIC-MOUNT-ERROR-STATE"};
using transition_t = fsm::fsm_transition_table_t<
std::pair<MccGenericFsmMountErrorEvent<MOUNT_T>, MccGenericFsmMountErrorState>,
std::pair<MccGenericFsmMountIdleEvent<MOUNT_T>, MccGenericFsmMountIdleState<MccGenericFsmMountErrorState>>,
std::pair<MccGenericFsmMountInitEvent<MOUNT_T>, MccGenericFsmMountInitState<MccGenericFsmMountErrorState>>>;
void exit(fsm::traits::fsm_event_c auto& event)
{
exitLog(event);
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount()->logWarn(
std::format("The mount is in the error state!!! One must correct it before transit to any states! "
"Event type is '{}'",
decltype(event)::ID));
}
}
void enter(fsm::traits::fsm_event_c auto& event)
{
enterLog(event);
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
auto err = event.eventData();
event.mount()->logError(
std::format("The mount is in the error state: code = {}, category = {}, message = '{}'",
err.value(), err.category().name(), err.message()));
}
}
};
public:
MccGenericFsmMount(MOUNT_T mount, fsm::traits::fsm_state_c auto start_state)
: MOUNT_T(std::move(mount)), fsm::MccFiniteStateMachine(std::move(start_state))
{
}
// reimplementation of base-class methods to adapt it to FSM-behavior
auto initMount()
{
this->dispatchEvent(INIT_EVENT_T{*this});
try {
this->dispatchEvent(INIT_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
auto stopMount()
{
this->dispatchEvent(STOP_EVENT_T{*this});
try {
this->dispatchEvent(STOP_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
auto slewToTarget()
{
this->dispatchEvent(SLEW_EVENT_T{*this});
try {
this->dispatchEvent(SLEW_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
auto stopSlewing()
{
this->dispatchEvent(STOP_EVENT_T{*this});
try {
this->dispatchEvent(STOP_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
auto trackTarget()
{
this->dispatchEvent(TRACK_EVENT_T{*this});
try {
this->dispatchEvent(TRACK_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
auto stopTracking()
{
this->dispatchEvent(STOP_EVENT_T{*this});
try {
this->dispatchEvent(STOP_EVENT_T{this});
} catch (std::system_error const& exc) {
return exc.code();
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}