使用tinyfsm

This commit is contained in:
zjk
2025-04-06 20:16:37 +08:00
parent 811fbf2924
commit c51eb7073a
18 changed files with 1720 additions and 322 deletions
+4 -4
View File
@@ -22,10 +22,10 @@ SET(SRC
PowerManger.cpp
PowerManger_Info.cpp
udpComm.cpp
fsm.cpp
main.cpp
SQLiteDB.cpp
driver.cpp
PowerManagerFsm.cpp
)
ADD_EXECUTABLE(pPowerManger ${SRC})
@@ -51,7 +51,7 @@ SET(SQLITEDB_SRC
)
SET(FSMLIB_SRC
fsm.cpp)
PowerManagerFsm.cpp)
SET(DRIVER_SRC
driver.cpp)
@@ -60,9 +60,9 @@ SET(POWERMANGE_SRC
PowerManger.cpp
PowerManger_Info.cpp
udpComm.cpp
fsm.cpp
SQLiteDB.cpp
driver.cpp)
driver.cpp
PowerManagerFsm.cpp)
ADD_LIBRARY(SQLiteDB STATIC ${SQLITEDB_SRC})
ADD_LIBRARY(UDPComm STATIC ${UDPCOMM_SRC})
+29
View File
@@ -0,0 +1,29 @@
#include "PowerManagerFsm.hpp"
#include "PowerManger.h"
// 初始化静态成员
PowerManger* PowerManagerFsm::pm = nullptr;
// 状态实例化
InitState initState;
StandbyState standbyState;
FaultState faultState;
// 状态机初始化
void PowerManagerFsm::init(PowerManger* powerManager) {
pm = powerManager;
start();
}
// 状态转换接口实现
void PowerManagerFsm::triggerInitEvent() {
dispatch(InitEvent());
}
void PowerManagerFsm::triggerStandbyEvent() {
dispatch(StandbyEvent());
}
void PowerManagerFsm::triggerFaultEvent(unsigned int faultCode) {
dispatch(FaultEvent(faultCode));
}
+153
View File
@@ -0,0 +1,153 @@
#ifndef POWER_MANAGER_FSM_HPP
#define POWER_MANAGER_FSM_HPP
#include "PowerManger.h"
#include "tinyfsm.hpp"
// 前向声明
class PowerManger;
// 定义事件类型
struct InitEvent : tinyfsm::Event { };
struct StandbyEvent : tinyfsm::Event { };
struct FaultEvent : tinyfsm::Event {
unsigned int faultCode;
FaultEvent(unsigned int code) : faultCode(code) {}
};
// 定义状态机基类
class PowerManagerFsm : public tinyfsm::Fsm<PowerManagerFsm> {
protected:
static PowerManger* pm;
public:
// 初始化状态机
static void init(PowerManger* powerManager) {
pm = powerManager;
}
// 响应事件默认实现
virtual void react(tinyfsm::Event const &) { }
// 状态转换接口
void triggerInitEvent() { dispatch(InitEvent()); }
void triggerStandbyEvent() { dispatch(StandbyEvent()); }
void triggerFaultEvent(unsigned int faultCode) { dispatch(FaultEvent(faultCode)); }
};
// 初始化静态成员
PowerManger* PowerManagerFsm::pm = nullptr;
// 定义状态类
class InitState : public PowerManagerFsm {
public:
void entry() {
PowerManagerFsm::pm->m_pmEvent = "初始化状态";
PowerManagerFsm::pm->printState("InitState", "进入初始化状态");
}
void react(InitEvent const &) {
// 1. 检查通信是否正常
double StartTime = PowerManagerFsm::pm->GetAppStartTime();
while (PowerManagerFsm::pm->connectState < 5) {
MOOSPause(1000);
PowerManagerFsm::pm->updateTime();
double dft = abs(PowerManagerFsm::pm->m_current_time - StartTime);
if(dft > 10) {
transit<FaultState>();
PowerManagerFsm::pm->m_faultNum = 1;
return;
}
string desp = "等待复合管控消息 : " + to_string(10-dft);
PowerManagerFsm::pm->printState("InitState", desp);
}
// 2. 检查复合管控器是否上报故障
if(PowerManagerFsm::pm->checkError() < 0) {
transit<FaultState>();
PowerManagerFsm::pm->m_faultNum = 2;
return;
}
// 3. 初始化系统为待机状态
PowerManagerFsm::pm->initControlCmd();
// 4. 判断关键断路器是否闭合
while (true) {
if(PowerManagerFsm::pm->m_currentDisBreakerState.bus3Breaker.unit4InstrumentDC48VCircuitBreaker == 1 ||
PowerManagerFsm::pm->m_currentDisBreakerState.bus4Breaker.unit5CircuitBreaker == 1 ||
PowerManagerFsm::pm->m_currentDisBreakerState.bus4Breaker.unit2CircuitBreaker == 1 ||
PowerManagerFsm::pm->m_currentDisBreakerState.bus4Breaker.unit3CircuitBreaker == 1 ||
PowerManagerFsm::pm->m_currentDisBreakerState.bus4Breaker.unit1CircuitBreaker == 1) {
transit<StandbyState>();
return;
}
PowerManagerFsm::pm->m_pmEvent = "等待关键断路器闭合";
MOOSPause(1000);
PowerManagerFsm::pm->printState("InitState", PowerManagerFsm::pm->m_pmEvent);
}
}
};
class StandbyState : public PowerManagerFsm {
public:
void entry() {
PowerManagerFsm::pm->m_stateData.note = "待机状态";
PowerManagerFsm::pm->printState("StandbyState", "进入待机状态");
}
void react(StandbyEvent const &) {
while (true) {
// 1. 检查当前是否存在故障
if(PowerManagerFsm::pm->checkError() < 0) {
transit<FaultState>();
return;
}
// 2. 处理上位机控制指令
handlePowerCommands();
MOOSPause(1000);
}
}
private:
void handlePowerCommands() {
switch (PowerManagerFsm::pm->m_msCmd.powerCMD) {
case 0: PowerManagerFsm::pm->m_pmEvent = "收到上位机控制指令:关机"; break;
case 1: handlePowerOn(); break;
// 其他处理函数省略...
}
}
void handlePowerOn() {
PowerManagerFsm::pm->m_pmEvent = "动力电上电";
PowerManagerFsm::pm->m_CcuColCmd.powerBatCmd = 0x10;
if(PowerManagerFsm::pm->m_pmCurrentState.ccustate.fcuState == 0x04)
PowerManagerFsm::pm->m_CcuColCmd.fcuCmd = 0x02;
}
};
class FaultState : public PowerManagerFsm {
public:
void entry() {
PowerManagerFsm::pm->printState("FaultState", "进入故障状态");
}
void react(FaultEvent const & e) {
switch (e.faultCode) {
case 1:
PowerManagerFsm::pm->m_pmEvent = "复合管控连接超时";
PowerManagerFsm::pm->printState("FaultState", "通信故障");
break;
case 2:
PowerManagerFsm::pm->m_pmEvent = "能源系统故障";
PowerManagerFsm::pm->printState("FaultState", "能源故障");
break;
}
}
};
// 设置初始状态
FSM_INITIAL_STATE(PowerManagerFsm, InitState);
#endif // POWER_MANAGER_FSM_HPP
+26 -220
View File
@@ -71,17 +71,9 @@ PowerManger::PowerManger()
m_db->createDriversTables(VAR_TO_STR(m_subDisSysCmd));
m_db->createDriversTables(VAR_TO_STR(m_MSDriverCmd));
//注册状态机
m_fsm.RegisterState("Init", 1, m_Inite_s1);
m_fsm.RegisterState("Stady", 2, m_Standby_s2);
m_fsm.RegisterState("Fault", 99, m_Fault_s99);
m_fsm.RegisterHandleFunction(&m_Inite_s1, handleInite_s1);
m_fsm.RegisterHandleFunction(&m_Standby_s2, handleStandby_s2);
m_fsm.RegisterHandleFunction(&m_Fault_s99, handleFault_s99);
// 初始化状态机
m_pmState = m_Inite_s1;
m_fsm.init(this);
PowerManagerFsm::start();
}
//---------------------------------------------------------
@@ -344,7 +336,14 @@ bool PowerManger::FsmLoop()
//状态机循环
while (!m_FsmThread.IsQuitRequested())
{
m_fsm.run(m_pmState,this);
// 检查故障并触发事件
if(int error = checkError()) {
triggerFaultEvent(error);
} else {
// 自动状态转换由状态机内部处理
MOOSPause(1000);
}
//延时1s
usleep(1000000);
}
@@ -599,7 +598,22 @@ int PowerManger::checkError()
}
void PowerManger::printState(FSM_State st, string desp){
void PowerManger::triggerInitEvent()
{
PowerManagerFsm::dispatch(InitEvent());
}
void PowerManger::triggerStandbyEvent()
{
PowerManagerFsm::dispatch(StandbyEvent());
}
void PowerManger::triggerFaultEvent(unsigned int faultCode)
{
PowerManagerFsm::dispatch(FaultEvent(faultCode));
}
void PowerManger::printState(const std::string& stateName, const std::string& desp){
cout << MOOS::ConsoleColours::Yellow() << "STATE " << st.id << " [" << st.name << "] " << MOOS::ConsoleColours::reset();
cout << MOOS::ConsoleColours::Blue() << " -> " << MOOS::ConsoleColours::reset();
// 检查desp是否有“故障”
@@ -610,214 +624,6 @@ void PowerManger::printState(FSM_State st, string desp){
cout << MOOS::ConsoleColours::Green() << desp << MOOS::ConsoleColours::reset() << endl;
}
int PowerManger::handleInite_s1(FSM_State &fsm, void* pData)
{
PowerManger* pm = (PowerManger*)pData;
bool ok = true;
//1. 检查通信是否正常 如果超时则进入故障状态
double StartTime = pm->GetAppStartTime();
while (pm->connectState < 5)
{
MOOSPause(1000);
pm->updateTime();
double dft = abs(pm->m_current_time - StartTime);
if(dft > 10)
{
pm->m_pmState = pm->m_Fault_s99;
pm->m_faultNum = 1; //通信故障
ok = false;
break;
}
string desp = "等待复合管控消息 : " + to_string(10-dft);
pm->printState(fsm,desp);
}
//2. 检查复合管控器是否上报故障 如果故障则进入故障状态
if(pm->checkError() < 0)
{
ok = false;
pm->m_faultNum = 2; //能源故障
}
//3. 初始化系统为待机状态
pm->initControlCmd();
//4.判断关键断路器是否闭合
ok = false;
while (!ok)
{
if(pm->m_currentDisBreakerState.bus3Breaker.unit4InstrumentDC48VCircuitBreaker == 1 ||
pm->m_currentDisBreakerState.bus4Breaker.unit5CircuitBreaker == 1 ||
pm->m_currentDisBreakerState.bus4Breaker.unit2CircuitBreaker == 1 ||
pm->m_currentDisBreakerState.bus4Breaker.unit3CircuitBreaker == 1 ||
pm->m_currentDisBreakerState.bus4Breaker.unit1CircuitBreaker == 1)
{
ok = true;
}
pm->m_pmEvent = "等待关键断路器闭合";
MOOSPause(1000);
pm->printState(fsm,pm->m_pmEvent);
}
//5. 进入下一状态
if(ok)
{
pm->m_pmState = pm->m_Standby_s2;
}
if(!ok)
{
pm->m_pmState = pm->m_Fault_s99;
}
return 0;
}
int PowerManger::handleStandby_s2(FSM_State &fsm, void* pData)
{
PowerManger* pm = (PowerManger*)pData;
pm->m_stateData.note = "待机状态";
while (true)
{
string desp = "待机状态";
pm->printState(fsm,desp);
//1. 检查当前是否存在故障
if(pm->checkError() < 0)
{
pm->m_pmState = pm->m_Fault_s99;
break;
}
//2. 检查上位机上电控制指令
switch (pm->m_msCmd.powerCMD)
{
case 0:
pm->m_pmEvent = "收到上位机控制指令:关机";
// pm->shutdown();
break;
case 1:
pm->m_pmEvent = "动力电上电";
// pm->powerOn();
//1.先上动力锂电池
pm->m_CcuColCmd.powerBatCmd = 0x10;
//2.检查燃料电池是否就绪,如果就绪则启动
if(pm->m_pmCurrentState.ccustate.fcuState = 0x04)
pm->m_CcuColCmd.fcuCmd = 0x02;
break;
case 2:
pm->m_pmEvent = "锂动力电启动";
pm->m_CcuColCmd.powerBatCmd = 0x10;
break;
case 3:
pm->m_pmEvent = "燃料电池启动";
pm->m_CcuColCmd.fcuCmd = 0x02;
break;
case 4:
pm->m_pmEvent = "锂动力电关闭";
pm->m_CcuColCmd.powerBatCmd = 0x20;
case 5:
pm->m_pmEvent = "燃料电池停机";
pm->m_CcuColCmd.fcuCmd = 0x03;
break;
case 6:
pm->m_pmEvent = "燃料电池预热指令";
pm->m_CcuColCmd.fcuCmd = 0x07;
break;
case 7:
pm->m_pmEvent = "燃料电池自检指令";
pm->m_CcuColCmd.fcuCmd = 0x01;
break;
case 8:
pm->m_pmEvent = "燃料电池紧急停机";
pm->m_CcuColCmd.fcuCmd = 0x05;
break;
case 9:
pm->m_pmEvent = "燃料电池复位指令";
pm->m_CcuColCmd.fcuCmd = 0x04;
break;
case 10:
pm->m_pmEvent = "燃料电池补给指令";
pm->m_CcuColCmd.fcuCmd = 0x06;
break;
case 11:
pm->m_pmEvent = "燃料电池停机维护";
pm->m_CcuColCmd.fcuCmd = 0x08;
break;
default:
break;
}
//2. 检查上位机模式切换指令
switch (pm->m_msCmd.modCMD)
{
case 0:
//无效
break;
case 1:
pm->m_pmEvent = "待机工况";
break;
case 2:
pm->m_pmEvent = "岸基备航";
break;
case 3:
pm->m_pmEvent = "水中备航";
break;
case 4:
pm->m_pmEvent = "遥控工况";
break;
case 5:
pm->m_pmEvent = "巡航模式";
break;
case 6:
pm->m_pmEvent = "高速模式";
break;
case 7:
pm->m_pmEvent = "上浮下潜";
break;
case 8:
pm->m_pmEvent = "浮调模式";
break;
case 9:
pm->m_pmEvent = "水下侦查";
break;
case 10:
pm->m_pmEvent = "水面侦查";
break;
case 11:
pm->m_pmEvent = "DJ模式";
break;
default:
break;
}
//3. 检查上位机工作模式切换控制指令
switch (pm->m_msCmd.workCMD)
{
case 0:
pm->m_pmEvent = "正常模式(默认)";
break;
case 1:
pm->m_pmEvent = "试验模式";
pm->currentMod = 1;
break;
case 2:
pm->m_pmEvent = "调试模式";
pm->currentMod = 2;
break;
}
MOOSPause(1000);
}
}
int PowerManger::handleFault_s99(FSM_State &fsm, void* pData)
{
// cout << fsm.name << endl;
PowerManger* pm = (PowerManger*)pData;
switch (pm->m_faultNum)
{
case 1:
pm->printState(fsm,"通信故障");
pm->m_pmEvent = "复合管控连接超时";
break;
default:
break;
}
pm->printState(fsm,"故障");
return 0;
}
//==============================系统操作函数====================
+75 -86
View File
@@ -30,7 +30,7 @@
#include "json/json.h"
#include "udpComm.h"
#include "pmSysvariable.h"
#include "fsm.h"
#include "PowerManagerFsm.hpp"
#include "SQLiteDB.h"
#include "driver.h"
@@ -96,92 +96,81 @@ class PowerManger : public AppCastingMOOSApp
double msg_disHighAVolBusFbMsg_Update_time;
double msg_disHighBVolBusFbMsg_Update_time;
double msg_disLowBusFbMsg_Update_time;
protected:
//===========================交互状态变量==================================
Driver m_driver; //设备驱动
pmState m_pmCurrentState; //能源系统的当前状态
disSysBreakerList m_currentDisBreakerState; //配电断路器状态
disSysBreakerList m_targetDisBreakerState;
DriverTable m_currentDriverState;
DriverTable m_MSDriverCmd;
DriverTable m_subDisSysCmd;
DriverTable m_subDisSysState;
//===========================================================================
//系统运行状态
unsigned char workCondition;
unsigned char currentMod;
unsigned char powerState;
unsigned char falutLevel;
vector<unsigned int> faultCode;
unsigned int soc;
unsigned int sustainableTime;
// 配电和CCU的反馈状态
msg_CcuStateFbMsg m_CcuCurrentState;
msg_disHighVolBusFbMsg m_disHighVolBusCurrentState;
msg_disHighAVolBusFbMsg m_disHighAVolBusCurrentState;
msg_disHighBVolBusFbMsg m_disHighBVolBusCurrentState;
msg_disLowBusFbMsg m_disLowBusState;
//下位机操作函数
ccuColCmd m_CcuColCmd;
void disSysOption();
void ccuOption();
char getBreakerOption(char cmd);
void initControlCmd();
//上位机操作函数
MSControlCmd m_msCmd;
bool buildPowerSysReport();
bool getMsCmdFromJson(MSControlCmd &cmd,const string &strJson);
private:
udpComm m_udpComm;
XPCUdpSocket *m_pCcuUdpComm;
CMOOSThread m_ListenThread;
CMOOSThread m_FsmThread;
long m_lPort;
unsigned int m_nReceiveBufferSizeKB;
unsigned int m_nSendBufferSizeKB;
double m_current_time;
unsigned int m_faultNum;
unsigned int m_ticker;
public:
//===========================状态机实现==============================================
void printState(FSM_State st, string desp);
protected:
//===========================交互状态变量==================================
Driver m_driver; //设备驱动
pmState m_pmCurrentState; //能源系统的当前状态
disSysBreakerList m_currentDisBreakerState; //配电断路器状态
disSysBreakerList m_targetDisBreakerState;
DriverTable m_currentDriverState;
DriverTable m_MSDriverCmd;
DriverTable m_subDisSysCmd;
DriverTable m_subDisSysState;
//===========================================================================
//系统运行状态
unsigned char workCondition;
unsigned char currentMod;
unsigned char powerState;
unsigned char falutLevel;
vector<unsigned int> faultCode;
unsigned int soc;
unsigned int sustainableTime;
// 配电和CCU的反馈状态
msg_CcuStateFbMsg m_CcuCurrentState;
msg_disHighVolBusFbMsg m_disHighVolBusCurrentState;
msg_disHighAVolBusFbMsg m_disHighAVolBusCurrentState;
msg_disHighBVolBusFbMsg m_disHighBVolBusCurrentState;
msg_disLowBusFbMsg m_disLowBusState;
//下位机操作函数
ccuColCmd m_CcuColCmd;
void disSysOption();
void ccuOption();
char getBreakerOption(char cmd);
void initControlCmd();
//上位机操作函数
MSControlCmd m_msCmd;
bool buildPowerSysReport();
bool getMsCmdFromJson(MSControlCmd &cmd,const string &strJson);
private:
udpComm m_udpComm;
XPCUdpSocket *m_pCcuUdpComm;
CMOOSThread m_ListenThread;
CMOOSThread m_FsmThread;
long m_lPort;
unsigned int m_nReceiveBufferSizeKB;
unsigned int m_nSendBufferSizeKB;
double m_current_time;
unsigned int m_faultNum;
unsigned int m_ticker;
// 状态机实例
PowerManagerFsm m_fsm;
public:
//===========================状态机接口=======================================
void printState(const std::string& stateName, const std::string& desp);
bool FSM_RUN_IS_OK = true;
StateData m_stateData;
FSM_State m_pmState; //当前状态
string m_pmEvent;
FSM m_fsm;
//初始化状态
FSM_State m_Inite_s1;
static int handleInite_s1(FSM_State &fsm, void* pData);
//待机状态
FSM_State m_Standby_s2;
static int handleStandby_s2(FSM_State &fsm, void* pData);
//岸基备航
// FSM_State m_ShoreReady_s3;
//水中备航
//自动工况
//故障处理
FSM_State m_Fault_s99;
static int handleFault_s99(FSM_State &fsm, void* pData);
//======================================================================================
int checkError();
bool shutdown();
bool powerOn();
bool powerOff();
// 初始化状态机
void initFsm() {
m_fsm.init(this);
}
// 状态机事件触发接口
void triggerInitEvent() { m_fsm.triggerInitEvent(); }
void triggerStandbyEvent() { m_fsm.triggerStandbyEvent(); }
void triggerFaultEvent(unsigned int faultCode) { m_fsm.triggerFaultEvent(faultCode); }
//==================================================================================
int checkError();
bool shutdown();
bool powerOn();
bool powerOff();
};
+13 -7
View File
@@ -27,14 +27,20 @@ public:
int run(FSM_State &fsm,void* data);
int run(FSM_State *fsm,void* data, std::string event);
//TODO: 事件注册机制实现
int RegisterEvent(FSM_State* fsm, std::string event, FSM_State *state);
int unRegisterEvent(FSM_State* fsm, std::string event);
int RegisterState(std::string name, unsigned int id,FSM_State &state);
FSM_State getState(std::string name);
unsigned int getStateId(std::string name);
// 事件处理机制
int RegisterEvent(FSM_State* fsm, const std::string& event, FSM_State *state);
int unRegisterEvent(FSM_State* fsm, const std::string& event);
// 状态管理
int RegisterState(const std::string& name, unsigned int id, FSM_State &state);
FSM_State getState(const std::string& name) const;
unsigned int getStateId(const std::string& name) const;
// 处理函数管理
int RegisterHandleFunction(FSM_State* fsm, FSM_Handle handle);
int unRegisterHandleFunction(FSM_State* fsm);
// 事件触发
int triggerEvent(FSM_State* currentState, const std::string& event, void* data);
};
#endif
+251
View File
@@ -0,0 +1,251 @@
/*
* TinyFSM - Tiny Finite State Machine Processor
*
* Copyright (c) 2012-2022 Axel Burri
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* ---------------------------------------------------------------------
* Version: 0.3.3
*
* API documentation: see "../doc/50-API.md"
*
* The official TinyFSM website is located at:
* https://digint.ch/tinyfsm/
*
* Author:
* Axel Burri <axel@tty0.ch>
* ---------------------------------------------------------------------
*/
#ifndef TINYFSM_HPP_INCLUDED
#define TINYFSM_HPP_INCLUDED
#ifndef TINYFSM_NOSTDLIB
#include <type_traits>
#endif
// #include <iostream>
// #define DBG(str) do { std::cerr << str << std::endl; } while( false )
// DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
namespace tinyfsm
{
// --------------------------------------------------------------------------
struct Event { };
// --------------------------------------------------------------------------
#ifdef TINYFSM_NOSTDLIB
// remove dependency on standard library (silent fail!).
// useful in conjunction with -nostdlib option, e.g. if your compiler
// does not provide a standard library.
// NOTE: this silently disables all static_assert() calls below!
template<typename F, typename S>
struct is_same_fsm { static constexpr bool value = true; };
#else
// check if both fsm and state class share same fsmtype
template<typename F, typename S>
struct is_same_fsm : std::is_same< typename F::fsmtype, typename S::fsmtype > { };
#endif
template<typename S>
struct _state_instance
{
using value_type = S;
using type = _state_instance<S>;
static S value;
};
template<typename S>
typename _state_instance<S>::value_type _state_instance<S>::value;
// --------------------------------------------------------------------------
template<typename F>
class Fsm
{
public:
using fsmtype = Fsm<F>;
using state_ptr_t = F *;
static state_ptr_t current_state_ptr;
// public, leaving ability to access state instance (e.g. on reset)
template<typename S>
static constexpr S & state(void) {
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
return _state_instance<S>::value;
}
template<typename S>
static constexpr bool is_in_state(void) {
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
return current_state_ptr == &_state_instance<S>::value;
}
/// state machine functions
public:
// explicitely specialized in FSM_INITIAL_STATE macro
static void set_initial_state();
static void reset() { };
static void enter() {
current_state_ptr->entry();
}
static void start() {
set_initial_state();
enter();
}
template<typename E>
static void dispatch(E const & event) {
current_state_ptr->react(event);
}
/// state transition functions
protected:
template<typename S>
void transit(void) {
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
current_state_ptr->exit();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
}
template<typename S, typename ActionFunction>
void transit(ActionFunction action_function) {
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
current_state_ptr->exit();
// NOTE: do not send events in action_function definisions.
action_function();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
}
template<typename S, typename ActionFunction, typename ConditionFunction>
void transit(ActionFunction action_function, ConditionFunction condition_function) {
if(condition_function()) {
transit<S>(action_function);
}
}
};
template<typename F>
typename Fsm<F>::state_ptr_t Fsm<F>::current_state_ptr;
// --------------------------------------------------------------------------
template<typename... FF>
struct FsmList;
template<> struct FsmList<> {
static void set_initial_state() { }
static void reset() { }
static void enter() { }
template<typename E>
static void dispatch(E const &) { }
};
template<typename F, typename... FF>
struct FsmList<F, FF...>
{
using fsmtype = Fsm<F>;
static void set_initial_state() {
fsmtype::set_initial_state();
FsmList<FF...>::set_initial_state();
}
static void reset() {
F::reset();
FsmList<FF...>::reset();
}
static void enter() {
fsmtype::enter();
FsmList<FF...>::enter();
}
static void start() {
set_initial_state();
enter();
}
template<typename E>
static void dispatch(E const & event) {
fsmtype::template dispatch<E>(event);
FsmList<FF...>::template dispatch<E>(event);
}
};
// --------------------------------------------------------------------------
template<typename... SS> struct StateList;
template<> struct StateList<> {
static void reset() { }
};
template<typename S, typename... SS>
struct StateList<S, SS...>
{
static void reset() {
_state_instance<S>::value = S();
StateList<SS...>::reset();
}
};
// --------------------------------------------------------------------------
template<typename F>
struct MooreMachine : tinyfsm::Fsm<F>
{
virtual void entry(void) { }; /* entry actions in some states */
void exit(void) { }; /* no exit actions */
};
template<typename F>
struct MealyMachine : tinyfsm::Fsm<F>
{
// input actions are modeled in react():
// - conditional dependent of event type or payload
// - transit<>(ActionFunction)
void entry(void) { }; /* no entry actions */
void exit(void) { }; /* no exit actions */
};
} /* namespace tinyfsm */
#define FSM_INITIAL_STATE(_FSM, _STATE) \
namespace tinyfsm { \
template<> void Fsm< _FSM >::set_initial_state(void) { \
current_state_ptr = &_state_instance< _STATE >::value; \
} \
}
#endif /* TINYFSM_HPP_INCLUDED */