123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- #pragma once
- // 下列 ifdef 块是创建使从 DLL 导出更简单的
- // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DIOSSMACHINE_EXPORTS
- // 符号编译的。在使用此 DLL 的
- // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
- // DIOSSMACHINE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
- // 符号视为是被导出的。
- #ifndef DIOSSMACHINE_EXPORTS
- #ifdef _WIN64
- #ifdef _DEBUG
- #pragma comment(lib, "DiosSMachineV3X64D.lib")
- #else
- #pragma comment(lib, "DiosSMachineV3X64.lib")
- #endif
- #else
- #ifdef _DEBUG
- #pragma comment(lib, "DiosSMachineV3D.lib")
- #else
- #pragma comment(lib, "DiosSMachineV3.lib")
- #endif
- #endif
- #endif
- #ifdef DIOSSMACHINE_EXPORTS
- #define DIOSSMACHINE_API __declspec(dllexport)
- #define DIOSSMACHINE_C_API extern "C" __declspec(dllexport)
- #else
- #define DIOSSMACHINE_API __declspec(dllimport)
- #define DIOSSMACHINE_C_API extern "C" __declspec(dllimport)
- #endif
- #include "ResDataObject.h"
- #include "DiosThread.h"
- #include "MsgCircle.h"
- #include "DiosLock.h"
- #include "MsgQueue.h"
- #include "LogicClient.h"
- #include <map>
- using namespace std;
- #define TIMEOUT_TEMP (3000)
- //#define DiosErrorType "Error"
- //行为,失败,超时等正常执行时错误
- //#define DiosFrameError "Frame"
- //人为的错误发送
- //#define DiosSeqError "Seq"
- //状态机不关心状态是不是Error,定义者自己来定义错误状态
- //#define DiosStmEntryPosName "StateMachineEntry"
- //#define DiosStmExitPosName "StateMachineExit"
- //状态机进出状态名称,用户自定义
- //#define DiosTopStateMachineName ("SMOuter")
- class StateMachineDevicePool;
- typedef enum _DiosStMachineRet
- {
- DIOSSMRET_NG,
- DIOSSMRET_OK,
- DIOSSMRET_TIMEOUT,
- DIOSSMRET_EXIT,
- DIOSSMRET_MAX
- }DIOSSTMRET;
- //assert,通用的事件和錯誤的事件處理上有所不同
- //最终有个==的判断,到时候错误和事件的处理方案不一样
- #define DiosStmEvtInfo "DiosStmEvtInfo"
- class ConditionEvent;
- //JSON格式,EVT事件相关的必须有,而INFO相关的是附加内容,可有可无
- /*
- {
- "evtkey" : "evt内容",
- "DiosStmEvtInfo" : "错误内容 or 事件INFO or 其他附加信息"
- }
- */
- typedef enum _SMEVTTYPE {
- SMEVT_NOTIFY,//有硬件事件,只读通知
- SMEVT_READATTR,//有硬件事件,step1:读通知,step2:没有通知情况下读属性,step3:没有属性置位情况下等通知.
- SMEVT_PASS,//无匹配,无条件穿过.
- SMEVT_BLOCK,//无匹配,保持阻挡状态
- SMEVT_MAX
- }SMEVTTYPE;
- class DIOSSMACHINE_API DiosStMEvt
- {
- ResDataObject *m_pEvt;
- ResDataObject *m_pInfo;
- SMEVTTYPE m_type;
- bool m_bTriggered;
- HANDLE m_hTriggered;
- ConditionEvent* m_pConditions;
- bool m_bActived;
- public:
- DiosStMEvt();
- DiosStMEvt(const DiosStMEvt &tValue);
- ~DiosStMEvt();
- bool SetEvt(const char* pKey, INT Val, const char *pInfo = NULL);
- bool SetEvt(const char* pKey, const char *pVal, const char *pInfo = NULL);
- DiosStMEvt& operator = (const DiosStMEvt &tValue);
- bool operator == (const DiosStMEvt &Obj);
- bool operator == (const char* pszEventName);
- const char *encode_s();
- bool decode(const char *pdata);
- //设置事件上下文
- bool parse(ResDataObject *evtContext);
- bool IsEmpty();
- ResDataObject& GetEvtContext();
- bool IsTriggered(); //事件是激发态
- //过滤激活事件,包括Action/Notfiy/External
- bool Active(const char* pszType, ResDataObject* resContext, const char* pszDevice);
- const char* GetEventName() { return m_pEvt->GetKey(0); }
- HANDLE GetHandle() { return m_hTriggered; }
- void Reset();
- void Enable(bool state) { m_bActived = state; }
- int GetTimeout();
- };
- //state route pos
- class DIOSSMACHINE_API DiosStMRouteLine
- {
- bool m_ActiveState;
- bool m_InRoute;
- DWORD m_Timeout;
- DiosStMEvt *m_pEvt; //一个out对应一个 事件
- string *m_pSrcRoutePos;
- string *m_pGuard;
- string *m_pDesRoutePos;
- public:
- DiosStMRouteLine();
- DiosStMRouteLine(const DiosStMRouteLine &tValue);
- virtual ~DiosStMRouteLine();
- void SetRoute(DiosStMEvt &evt, const char* pGuard, const char* pDes);
- void SetRoute(DiosStMEvt &evt, const char* pSrc,const char* pGuard, const char* pDes);
- const char* GetDesName();
- const char* GetSrcName();
- const char* GetGuardName();
- bool GetRouteType();//true:in,false:out
- void Active(bool state, DWORD timeout);
- bool GetActiveState();
- operator DiosStMEvt *();
- DiosStMRouteLine& operator = (const DiosStMRouteLine &tValue);
- DWORD GetTimeout();
- };
- class DiosSMachineIF;
- //一个状态有多个RouteLine, 每个RouteLine有一个单独的事件
- class DIOSSMACHINE_API DiosStMRoutePos
- {
- bool m_ActiveState;
- DWORD m_Timeout;
- string *m_pRoutePosName;
- vector<DiosStMRouteLine *> *m_pOutRouteLineVec;
- vector< DiosStMEvt*>* m_pRouteLineEvents; //出状态的事件列表,和RouteLine一一对应
- StateMachineDevicePool* m_pDevicePool;
- ResDataObject m_resStateActions;
- ResDataObject m_resDisable; //禁用全局事件列表
- ResDataObject m_resEvent2DestPos;
- bool m_bBreakIn;
- bool m_bBreakAction;
- bool m_bBreakOut;
- public:
- DiosStMRoutePos();
- DiosStMRoutePos(const char *pName, StateMachineDevicePool* pDevicePool);
- virtual ~DiosStMRoutePos();
- virtual bool IsSMachine();//no
- void SetName(const char *pName);
- const char* GetName();
- bool PosAddOutRouteLine(DiosStMEvt *Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName);
- void SetAction(ResDataObject actions) { m_resStateActions = actions; }
- DWORD GetRouteLineCount();
- DiosStMRouteLine **GetOutRouteLineVec();
- DiosStMRouteLine *operator [](DiosStMEvt &Evt);
- void Active(bool state, DWORD timeout);
- bool GetActiveState();
- DWORD GetTimeout();
- vector< DiosStMEvt*>* GetPosEvent() { return m_pRouteLineEvents; }
- //执行进入当前状态的Action
- DIOSSTMRET DoAction(DiosSMachineIF* pSM);
- DIOSSTMRET DoIn(DiosSMachineIF* pSM);
- DIOSSTMRET DoOut(DiosSMachineIF* pSM);
- //定时检查是否超时,最小间隔为1s,有可能不执行
- DIOSSTMRET CheckTimeout();
- //状态到了的检查,是否激活事件
- DIOSSTMRET CheckNotify(const char* pszDevice, ResDataObject* res);
- //
- bool TriggerEvent(const char* pszEvent);
- DiosStMRouteLine* WaitFroNextState(int timeout); //等待进入下一个状态
- //禁用全局事件
- void SetDisable(ResDataObject disable);
- void SetBreak(bool bBreakIn, bool bBrakAction, bool bBreakOut);
- //
- void EnableEvent(const char* pszEventName, bool state);
- };
- using StateChangedCallback = std::function<void (const char*, const char*)>;
- //通用状态机类
- class DIOSSMACHINE_API DiosSMachineIF : public DiosLock
- {
- protected:
- //DiosSMachineIF *m_pParent;
- string *m_pStateMachineName;
- StateMachineDevicePool* m_pDevicePool;
- string m_strLastPos; //上一个状态点
- string m_strCurrentPos; //当前状态点
- string m_StmEntryPosName; //状态机入口状态名称
- string m_StmExitPosName; //状态机出口状态名称
- ResDataObject m_resUserVariable; //用户变量
- ResDataObject m_resSystemVariable; //系统变量
- HANDLE m_StateCangeEvt;
- HANDLE m_RunningState;
- DiosStMRouteLine* StateMachineWaitForEvents(/*int &ExtEvtIndex*/);//[< 0]:Local or outline, [>= 0]: externalEvtIndex
- StateChangedCallback m_StateNotify;
- bool m_bDebugEnable; //是否启用Debug模式
- HANDLE m_hBreaked; //断点等待事件,用户发送Continue后触发,状态机继续执行,直至下一个断点
- protected:
- DiosStMRoutePos *m_pCurrentRoutePos;
- MsgCircle<DiosStMEvt> *m_pArrivedEvts;
- //状态与路由映射表
- map<string, DiosStMRoutePos*> *m_pRoutePosMap;
- //inline,全局路由表
- //vector<DiosStMRouteLine*> *m_pRouteInLineMap;
- DiosStMRoutePos* m_pGlobalRoute;
- ////external
- //size_t m_RouteExternalEvtCount;
- //DiosStMRouteLine** m_pRouteExternalMap;
- void ClearState();//reset
- DIOSSTMRET TransToPos(const char *pPosName);
- void PostError(const char *pErrorVal,const char *pErrorInfo = NULL);
- DiosStMRouteLine *GetEntryRouteLine();
- INT ExecStateMachine(HANDLE ThreadExitEvt/*,DiosStMRouteLine *pExternalWaitEvts[], size_t WaitCount*/);
- //INT EnterSubStateMachine(HANDLE ThreadExitEvt);
- bool PrePareStateMachine();
- bool GetRunningState(DWORD waittime = 0);
- void SetRunningState(bool Running);
- virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos
- public:
- void SetMachineName(const char* pszEntryName, const char * pszExitName); //设置状态机名称及进出状态名称
- void SetUserVariable(const char* pKey, ResDataObject& resValue); //设置用户变量
- void GetUserVariable(const char* pKey, ResDataObject& resValue); //读取用户变量值
- void GetSystemVariable(const char* pKey, ResDataObject& resValue); //读取系统变量
- void EnableEvent(const char* pszGlobalEvent, bool state);
- DIOSSTMRET ProcessUserVaiable(const char* vName, ResDataObject& resVaiable);
- void SetNotifyCallback(StateChangedCallback callback) { m_StateNotify = callback; }
- public:
- DiosSMachineIF(void);
- virtual ~DiosSMachineIF(void);
- void SetStateMachineName(const char *pszName);
-
- const char *GetStateMachineName();
- //void SetParentSMachine(DiosSMachineIF *pParent);
- const char* GetCurrentState() { return m_strCurrentPos.c_str(); }
- //for this IF
- //virtual bool IsSMachine();//yes
- //void CopyEvtTo(DiosSMachineIF *pDes);
- //init state machine
- //第一个节点的接入比较特殊,所以做了个函数
- bool AddEntryRoutePos(DiosStMRoutePos *pPos);
- bool AddRoutePos(DiosStMRoutePos *pPos);
- bool AddInRouteLine(DiosStMEvt &Evt, const char *pGuardName, const char *pDesPosName);
- bool AddOutRouteLine(DiosStMEvt *Evt,const char *pSrcPosName,const char *pGuardName,const char *pDesPosName);
- //active state machine
- bool ActiveRoutePos(const char *pPosName, DWORD timeout = TIMEOUT_TEMP);
- bool ActiveRouteLine(DiosStMEvt &Evt, DWORD timeout = TIMEOUT_TEMP);
- bool DeActiveAll();
- DiosStMRoutePos *GetCurrentRoutePos();
- //evt
- bool PushEvent(DiosStMEvt &Evt);
- bool PopEvent(DiosStMEvt &Evt);
- bool PeekEvent(DiosStMEvt &Evt);
- HANDLE GetEvtNotifyHandle();
- //for Debug
-
- //设置Debug模式,启用或者禁用
- void SetDebugMode(bool bEnable);
- bool InDebugMode() { return m_bDebugEnable; }
- //设置状态断点,IN/ACTION/OUT 三个断点位置可以设置
- void EnableBreakPoint(const char* pState, bool bBreakInEable, bool bActionInEnable, bool bBreakOutEnable);
- //继续运行,当处于中断状态时
- void Continue();
- //获取状态的所有事件的激活值
- void GetEventStatus(const char* pState, const char* pszEvent);
- //获取当前断点位置
- void GetCurrentBreak();
- //等待继续事件触发
- void WaitContinue();
- HANDLE GetStateChangeEvtHandle();
- //for state machine thread
- virtual DIOSSTMRET StateMachineEntry(DWORD timeout);//Begin状态点
- virtual DIOSSTMRET StateMachineExit(DWORD timeout);//End状态点
- //状态点Action执行动作
- virtual DIOSSTMRET StateMachineAction(const char *pState, DWORD timeout);
- //状态点Guard
- virtual DIOSSTMRET StateMachineGuard(const char * pState, DWORD timeout);
- //返回值的定义
- //因为全局事件,本状态机事件,本状态点事件都需要监控
- //所以
- //返回值为负:退出状态机
- //返回值为正: 0 <= EvtIdx < CountOfLocal + CountOfExternal + CountOfOutpath
- // 至于那个数组的事件,可以自行推算
- // 例: Outpath第二个事件 => EvtIdx = CountOfLocal + CountOfExternal + 1
- //关于TIMEOUT:函数中wait的是OutpathEvts,LocalEvts和ExternalEvts是没有必要等待,有就有,没有就没有....
- virtual DiosStMRouteLine* WaitNotfiyProcess(); //子类需要从设备上获取通知,然后根据优先级找到目标状态路由
-
- //virtual int StateMachineWaitForEvents(
- // DiosStMRouteLine *pLocalEvts[], DWORD CountOfLocal,
- // //DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal,
- // DiosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath,
- // DWORD timeout
- // );
- };
- class StateMachineDevicePool;
- //标准状态机
- class DIOSSMACHINE_API DiosSMachine : public Dios_Thread,public DiosSMachineIF
- {
- protected:
- virtual bool OnStartThread();
- virtual bool Exec();
- HANDLE m_StateQuedEvent;
- ResDataObject m_LastHitStatePos;
- MsgQueue<ResDataObject> *m_pStatePosList;
- virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos
- public:
- DiosSMachine(void);
- virtual ~DiosSMachine(void);
- void SetStateMachineLog(const char *pszLogTitle);
- bool PopStateChange(ResDataObject &LastPos);
- HANDLE GetStateQuedEvent();
- bool RunStateMachine(const char* pszLogTitle);
- //for other threads to call
- bool StartStateMachine(/*DiosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount*/);
- void StopStateMachine(DWORD timeout);
- //清除所有的状态和设备.
- virtual bool Reset(DWORD Timeout);
- /*
- 在状态机停止情况下是可以的.
- 单元设备列表添加
- */
- virtual bool AddDevices(ResDataObject& DevList) ;//.
- //单元设备列表清理.
- virtual bool ClearDevices();
- /*
- 触发状态机事件
- */
- bool TriggerEvent(const char* pEventName);//
- //添加状态点映射,各个状态点的Actions with Params.
- /*
- List of below format...
- "ParentStateName":"StateName":"Devpath":ActionName:Params
- */
- bool AddStateActions(ResDataObject& ActionMap);//状态机激活中,应该是在SeqReady点位
- //添加事件映射,所有的抽象事件的物理映射.
- /*
- List of EventName:{
- Need : 1 or 0,
- Devpath : Key:Value
- }
- */
- bool AddStateEvents(ResDataObject& EventMap);//状态机激活中,应该是在SeqReady点位
- //从状态机定义中加载当前状态机定义
- bool LoadMachine(ResDataObject& Machine);
- //状态机自行跳入FrameError的时候,错误信息读取.(空的情况反馈false)
- bool GetStateMachinesErrorInfo(ResDataObject& ErrInfo);
- void ClearStateActionMaps();
- void ClearStateEventMaps();
- //Actions----------------------------------------------------------------------
- //Entry&Exit Action
- virtual DIOSSTMRET StateMachineEntry(DWORD timeout);//Begin状态点
- virtual DIOSSTMRET StateMachineExit(DWORD timeout);//End状态点
- //RoutePos Action
- //virtual DIOSSTMRET StateMachineAction(const char* pAction, DWORD timeout) = 0;
- //virtual DIOSSTMRET StateMachineGuard(const char* pGuard, DWORD timeout) = 0;
- DiosStMRouteLine* WaitNotfiyProcess() override;
- //int StateMachineWaitForEvents(
- // DiosStMRouteLine* pLocalEvts[], DWORD CountOfLocal,
- // //DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal,
- // DiosStMRouteLine* pOutpathEvts[], DWORD CountOfOutpath,
- // DWORD timeout
- //) override;
- };
- /*
- //子状态机
- class DIOSSMACHINE_API DiosSubSMachine : public DiosStMRoutePos, public DiosSMachineIF
- {
- protected:
- public:
- DiosSubSMachine(void);
- DiosSubSMachine(const char *pName);
- virtual ~DiosSubSMachine(void);
- virtual bool IsSMachine();//yes
- };
- */
- typedef enum _DrStateMachineErrorType {
- DSM_ERROR_NORMAL,
- DSM_ERROR_ACTION_FAILED,
- DSM_ERROR_ACTION_TIMEOUT,
- DSM_ERROR_WAITEVENT_TIMEOUT,
- DSM_ERROR_MAX
- }DSMERRORTYPE;
- #define INVALID_DEVIDX (-1)
- #define STATEMACHINE_ACTION_TIMEOUT (2500)
- class DIOSSMACHINE_API StateMachineDevicePool : public DiosLock
- {
- MsgQueue<ResDataObject>* m_pErrorInfoQue;
- HANDLE m_ThreadExitHandle;
- //map<DWORD, string>* m_pDevpath;//devidx:devpath 设备序号->设备路径
- LogicClient* m_pDevNotifyClient;//devidx:client 用于获取通知的连接
- LogicClient* m_pDevActionClient; // 用于执行Action的连接
- DWORD GetDeviceIdx(const char* pszDevpath);
- const char* GetStateMachineEventName(DWORD DevIdx, const char* pKey, const char* pVal);
- void PushErrInfo(const char* pszContext, DSMERRORTYPE ErrType = DSM_ERROR_NORMAL);
- DWORD WINAPI ActionThread(LPVOID pPara);
- public:
- StateMachineDevicePool();
- ~StateMachineDevicePool();
- void SetThreadExitHandle(HANDLE tHand);
- //list of "devicepath":""
- bool AddDevices(ResDataObject& Devices);
- LogicClient* FindClient(const char* pszDevShortPath);
- /*
- List of below format...
- "ParentStateName":"StateName":"Devpath":ActionName:Params
- */
- bool AddStateActions(ResDataObject& ActionMaps);
- /*
- List of
- EventName:{ {Need : 1 or 0}, {ReadFromAttribute : 1 or 0},{Devpath : Key:Value}}
- */
- bool AddStateEvents(ResDataObject& EventMaps);
- void ClearStateActionMaps();
- void ClearStateEventMaps();
- //device init
- bool ClearDevices();
- bool OpenDevices();
- bool CloseDevices();
- //通用的Action和Event处理
- //DIOSSTMRET StateMachineAction(const char* pParentStatePos, const char* pStatePos, DWORD timeout);
- DIOSSTMRET StateMachineAction(ResDataObject* resActions, ResDataObject& resResult, ResDataObject* pVariable, DWORD Timeout);
- //DIOSSTMRET StateMachineAction(ResDataObject* resActions, ResDataObject& resResult);
- int ReadForDeviceEvents(ResDataObject& resNotfiy, DWORD timeout, int nMaxNotifyNum);
- //error info
- bool PopErrInfo(ResDataObject& info);
- };
|