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, Asibfm700Mount(Asibfm700MountConfig const& config,
std::shared_ptr<spdlog::logger> logger, std::shared_ptr<spdlog::logger> logger,
const auto& pattern_range = LOGGER_DEFAULT_FORMAT); const auto& pattern_range = mcc::utils::MccSpdlogLogger::LOGGER_DEFAULT_FORMAT);
~Asibfm700Mount(); ~Asibfm700Mount();
}; };

View File

@ -52,7 +52,7 @@ struct MccFiniteStateMachineCategory : public std::error_category {
const char* name() const noexcept const char* name() const noexcept
{ {
return "ADC_GENERIC_DEVICE"; return "MCC-FSM-ERROR-CATEGORY";
} }
std::string message(int ec) const 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 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 } // 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 } // 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; virtual ~MccGenericMount() = default;
error_t stopMount() error_t stopMount()
@ -114,20 +127,29 @@ public:
/* GENERIC FINITE-STATE-MACHINE MOUNT REFERENCE IMPLEMENTATION */ /* 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> template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountBaseEvent { struct MccGenericFsmMountBaseEvent {
typedef MOUNT_T mount_t;
// static constexpr std::string_view ID{""}; // static constexpr std::string_view ID{""};
virtual ~MccGenericFsmMountBaseEvent() = default; virtual ~MccGenericFsmMountBaseEvent() = default;
MOUNT_T& mount() const MOUNT_T* mount() const
{ {
return _mount; return _mount;
} }
protected: 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; struct MccGenericFsmMountStopEvent;
template <mcc_generic_mount_c MOUNT_T> 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> template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountSlewEvent; struct MccGenericFsmMountSlewEvent;
@ -149,138 +188,306 @@ struct MccGenericFsmMountSlewEvent;
template <mcc_generic_mount_c MOUNT_T> template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountTrackEvent; struct MccGenericFsmMountTrackEvent;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountBaseState { // struct MccGenericFsmMountBaseState {
// static constexpr std::string_view ID{""}; // typedef MOUNT_T mount_t;
virtual ~MccGenericFsmMountBaseState() = default;
protected: // virtual ~MccGenericFsmMountBaseState() = default;
MccGenericFsmMountBaseState() = default;
template <fsm::traits::fsm_event_c EvT> // protected:
void exitLog(this auto&& self, EvT& event) // MccGenericFsmMountBaseState() = default;
{
using self_t = std::remove_cvref_t<decltype(self)>;
if constexpr (mcc_generic_log_mount_c<MOUNT_T> && // template <fsm::traits::fsm_event_c EvT>
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) { // void exitLog(this auto&& self, EvT& event)
event.mount().logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID)); // {
} // using self_t = std::remove_cvref_t<decltype(self)>;
}
template <fsm::traits::fsm_event_c EvT> // if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
void enterLog(this auto&& self, EvT& event) // std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) {
{ // event.mount()->logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID));
using self_t = std::remove_cvref_t<decltype(self)>; // }
// }
if constexpr (mcc_generic_log_mount_c<MOUNT_T> && // template <fsm::traits::fsm_event_c EvT>
std::derived_from<EvT, MccGenericFsmMountBaseEvent<MOUNT_T>>) { // void enterLog(this auto&& self, EvT& event)
event.mount().logDebug(std::format("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID)); // {
} // using self_t = std::remove_cvref_t<decltype(self)>;
}
};
template <mcc_generic_mount_c MOUNT_T> // if constexpr (mcc_generic_log_mount_c<MOUNT_T> &&
struct MccGenericFsmMountStartState; // 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> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountIdleState; // struct MccGenericFsmMountStartState;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountStopState; // struct MccGenericFsmMountIdleState;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountErrorState; // struct MccGenericFsmMountStopState;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountSlewState; // struct MccGenericFsmMountErrorState;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountTrackState; // struct MccGenericFsmMountSlewState;
template <mcc_generic_mount_c MOUNT_T> // template <mcc_generic_mount_c MOUNT_T>
struct MccGenericFsmMountInitState { // struct MccGenericFsmMountTrackState;
static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
using transition_t = fsm::fsm_transition_table_t< // template <mcc_generic_mount_c MOUNT_T>
std::pair<MccGenericFsmMountIdleEvent<MOUNT_T>, MccGenericFsmMountIdleState<MOUNT_T>>, // struct MccGenericFsmMountInitState : MccGenericFsmMountBaseState<MOUNT_T> {
std::pair<MccGenericFsmMountErrorEvent<MOUNT_T>, MccGenericFsmMountErrorState<MOUNT_T>>, // static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
std::pair<MccGenericFsmMountInitEvent<MOUNT_T>, MccGenericFsmMountInitState<MOUNT_T>>>;
// 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) // void exit(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{ // {
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) { // 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!"); // event.mount()->logWarn("It seems a re-entering to the initializing state was asked! Ignore the event!");
} // }
} // }
void enter(MccGenericFsmMountInitEvent<MOUNT_T>& event) // void enter(MccGenericFsmMountInitEvent<MOUNT_T>& event)
{ // {
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) { // if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
event.mount().logWarn( // event.mount()->logWarn(
"It seems a re-entering to the initializing state was asked! Ignore the event and wait for the mount " // "It seems a re-entering to the initializing state was asked! Ignore the event and wait for the mount
"to initialize!"); // " "to initialize!");
} // }
} // }
void exit(fsm::traits::fsm_event_c auto& event) // void exit(fsm::traits::fsm_event_c auto& event)
{ // {
exitLog(event); // exitLog(event);
} // }
void enter(fsm::traits::fsm_event_c auto& event) // void enter(fsm::traits::fsm_event_c auto& event)
{ // {
enterLog(event); // enterLog(event);
} // auto err = event.mount()->initMount();
}; // }
// };
template <mcc_generic_mount_c MOUNT_T, template <mcc_generic_mount_c MOUNT_T,
fsm::traits::fsm_state_c START_STATE_T = MccGenericFsmMountStartState<MOUNT_T>, mcc_generic_fsm_mount_event_c INIT_EVENT_T = MccGenericFsmMountInitEvent<MOUNT_T>,
fsm::traits::fsm_event_c INIT_EVENT_T = MccGenericFsmMountInitEvent<MOUNT_T>, mcc_generic_fsm_mount_event_c STOP_EVENT_T = MccGenericFsmMountStopEvent<MOUNT_T>,
fsm::traits::fsm_event_c IDLE_EVENT_T = MccGenericFsmMountIdleEvent<MOUNT_T>, mcc_generic_fsm_mount_event_c SLEW_EVENT_T = MccGenericFsmMountSlewEvent<MOUNT_T>,
fsm::traits::fsm_event_c STOP_EVENT_T = MccGenericFsmMountStopEvent<MOUNT_T>, mcc_generic_fsm_mount_event_c TRACK_EVENT_T = MccGenericFsmMountTrackEvent<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>>
class MccGenericFsmMount : public MOUNT_T, protected fsm::MccFiniteStateMachine class MccGenericFsmMount : public MOUNT_T, protected fsm::MccFiniteStateMachine
{ {
// to prevent infinite recursion!
static_assert(!std::derived_from<MOUNT_T, MccGenericFsmMount>, "!!!!!!!!!");
public: 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 // reimplementation of base-class methods to adapt it to FSM-behavior
auto initMount() 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() 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() 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() 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() 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() 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;
} }