mountcontrol/cxx/mcc_mount_events_states.h
2025-06-10 18:19:11 +03:00

345 lines
9.9 KiB
C++

#pragma once
/* MOUNT CONTROL COMPONENTS LIBRARY */
/*
* BASIC EVENTS AND MOUNT STATES DEFINITIONS (REFERENCE IMPLEMENTATION)
*
*/
#include "mount.h"
namespace mcc
{
namespace traits
{
template <typename T>
concept mcc_mount_c = requires {
requires std::same_as<const MccMountType, decltype(T::mountType)>;
typename T::mount_config_t;
requires std::derived_from<T, MccMount<T::mountType, typename T::mount_config_t>>;
};
} // namespace traits
/* MOUNT STATE MACHINE STATES */
// a base class for mount state machine events
template <traits::mcc_mount_c MountT>
class MccMountEventBase
{
protected:
typedef MountT mount_t;
MccMountEventBase(mount_t& mount) : _mount(mount) {}
virtual ~MccMountEventBase() = default;
mount_t& mount() const
{
return _mount;
}
mount_t& _mount;
};
// transit to IDLE state
template <traits::mcc_mount_c MountT>
struct MccMountEventIDLE : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-IDLE-EVENT";
// CTAD does not work for clang++ (at least till v. 20 and -std=c++23)!
// so, one must explicitly define constructor here
MccMountEventIDLE(MountT& mount) : base_t(mount) {}
};
// transit to initialization state
template <traits::mcc_mount_c MountT>
struct MccMountEventInit : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-INIT-EVENT";
// CTAD does not work for clang++ (at least till v. 20 and -std=c++23)!
// so, one must explicitly define constructor here
MccMountEventInit(MountT& mount) : base_t(mount) {}
};
// transit to error state
template <traits::mcc_mount_c MountT>
struct MccMountEventError : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-ERROR-EVENT";
using event_data_t = std::error_code;
event_data_t eventData() const
{
return _error;
}
MccMountEventError(MountT& mount, const event_data_t& error) : base_t(mount), _error(error) {}
protected:
event_data_t _error;
};
// transit to slew state
template <traits::mcc_mount_c MountT>
struct MccMountEventSlew : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-SLEW-EVENT";
struct event_data_t {
MccCoordPairKind kind{MccCoordPairKind::COORDS_KIND_RADEC_IRCS};
MccAngle x{0.0}, y{0.0};
bool stop{false}; // stop after slewing: if false - start guiding
};
event_data_t eventData() const
{
return _eventData;
}
MccMountEventSlew(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {}
protected:
event_data_t _eventData;
};
// transit to guiding state
template <traits::mcc_mount_c MountT>
struct MccMountEventGuiding : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-EVENT";
// CTAD does not work for clang++ (at least till v. 20 and -std=c++23)!
// so, one must explicitly define constructor here
MccMountEventGuiding(MountT& mount) : base_t(mount) {}
};
// transit to stop state
template <traits::mcc_mount_c MountT>
struct MccMountEventStop : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-STOP-EVENT";
enum event_data_t {
EVENT_STOP_CLIENT, // software stop (mount client)
EVENT_STOP_BUTTON // hardware button
};
event_data_t eventData() const
{
return _reason;
}
MccMountEventStop(MountT& mount, event_data_t reason) : base_t(mount), _reason(reason) {}
protected:
event_data_t _reason;
};
// transit to shutdown state
template <traits::mcc_mount_c MountT>
struct MccMountEventShutdown : public MccMountEventBase<MountT> {
typedef MccMountEventBase<MountT> base_t;
static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-EVENT";
// CTAD does not work for clang++ (at least till v. 20 and -std=c++23)!
// so, one must explicitly define constructor here
MccMountEventShutdown(MountT& mount) : base_t(mount) {}
};
/* MOUNT STATE MACHINE STATES */
template <traits::mcc_mount_c MountT>
struct MccMountStateBase {
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void exit(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
std::forward<decltype(self)>(self).exitImpl(event);
event.mount().logDebug("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
}
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void enter(this auto&& self, EvT& event)
{
using self_t = std::remove_cvref_t<decltype(self)>;
event.mount().logDebug("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
std::forward<decltype(self)>(self).enterImpl(event);
}
protected:
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void exitImpl(EvT& event)
{
event.mount().logWarning("Call an empty MccMountStateBase::exitImpl method!!! Event type is '{}'", EvT::ID);
}
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void enterImpl(EvT& event)
{
event.mount().logWarning("Call an empty MccMountStateBase::enterImpl method!!! Event type is '{}'", EvT::ID);
}
};
// just forward declarations
template <traits::mcc_mount_c MountT>
struct MccMountStateIDLE;
template <traits::mcc_mount_c MountT>
struct MccMountStateInit;
template <traits::mcc_mount_c MountT>
struct MccMountStateError;
template <traits::mcc_mount_c MountT>
struct MccMountStateSlew;
template <traits::mcc_mount_c MountT>
struct MccMountStateStop;
template <traits::mcc_mount_c MountT>
struct MccMountStateGuiding;
template <traits::mcc_mount_c MountT>
struct MccMountStateShutdown;
// initialization state
template <traits::mcc_mount_c MountT>
struct MccMountStateInit : MccMountStateBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-INIT-STATE";
using transition_t = fsm::fsm_transition_table_t<std::pair<MccMountEventIDLE<MountT>, MccMountStateIDLE<MountT>>>;
protected:
void exitImpl(MccMountEventIDLE<MountT>& event)
{
// normal exit from the state
}
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void enterImpl(EvT& event)
{
event.mount().initMount();
// switch to IDLE state
event.mount().template dispatchEvent<MccMountEventIDLE<MountT>>();
}
};
template <traits::mcc_mount_c MountT>
struct MccMountStateError : MccMountStateBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-ERROR-STATE";
using transition_t = fsm::fsm_transition_table_t<
std::pair<MccMountEventIDLE<MountT>, MccMountStateIDLE<MountT>>, // ???? after error correction?
std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
std::pair<MccMountEventError<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventSlew<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventGuiding<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventStop<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
protected:
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void exitImpl(EvT& event)
{
event.mount().logWarning(
"The mount is in the error state!!! One must correct it before transit to any states! Event type is '{}'",
EvT::ID);
}
void exitImpl(MccMountEventIDLE<MountT>& event)
{
event.mount().logWarning("Suppose the error was corrected!");
}
void exitImpl(MccMountEventInit<MountT>& event)
{
// normal exit from the state
}
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void enterImpl(EvT& event)
{
auto err = event.eventData();
event.mount().logError("The mount is in the error state: code = {}, category = {}, message = '{}'", err.value(),
err.category().name(), err.message());
}
};
template <traits::mcc_mount_c MountT>
struct MccMountStateIDLE : MccMountStateBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-IDLE-STATE";
using transition_t =
fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
std::pair<MccMountEventError<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventSlew<MountT>, MccMountStateSlew<MountT>>,
std::pair<MccMountEventGuiding<MountT>, MccMountStateGuiding<MountT>>,
std::pair<MccMountEventStop<MountT>, MccMountStateIDLE<MountT>>,
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
};
template <traits::mcc_mount_c MountT>
struct MccMountStateShutdown : MccMountStateBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-STATE";
using transition_t =
fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
std::pair<MccMountEventError<MountT>, MccMountStateError<MountT>>,
std::pair<MccMountEventSlew<MountT>, MccMountStateSlew<MountT>>,
std::pair<MccMountEventGuiding<MountT>, MccMountStateGuiding<MountT>>,
std::pair<MccMountEventStop<MountT>, MccMountStateIDLE<MountT>>,
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
};
} // namespace mcc