123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752 |
- // DiosSMachine.cpp : 定义 DLL 应用程序的导出函数。
- //
- #include "stdafx.h"
- #include "DiosSMachineV3.h"
- #include "common_api.h"
- #include <sstream>
- using namespace std;
- //================================
- DiosStMRoutePos::DiosStMRoutePos()
- {
- m_ActiveState = false;
- m_pRoutePosName = new string();
- m_pOutRouteLineVec = new vector<DiosStMRouteLine *>();
- m_Timeout = TIMEOUT_TEMP;
- m_pRouteLineEvents = new vector<DiosStMEvt*>();
- m_pDevicePool = nullptr;
- }
- DiosStMRoutePos::DiosStMRoutePos(const char *pName, StateMachineDevicePool* pDevicePool)
- {
- m_ActiveState = false;
- m_pRoutePosName = new string();
- (*m_pRoutePosName) = pName;
- m_pOutRouteLineVec = new vector<DiosStMRouteLine *>();
- m_Timeout = TIMEOUT_TEMP;
- m_pRouteLineEvents = new vector<DiosStMEvt*>();
- m_pDevicePool = pDevicePool;
- }
- DiosStMRoutePos::~DiosStMRoutePos()
- {
- delete m_pRoutePosName;
- m_pRoutePosName = NULL;
- if (m_pOutRouteLineVec != NULL)
- {
- if (m_pOutRouteLineVec->size() > 0)
- {
- for (size_t i = 0; i < m_pOutRouteLineVec->size(); i++)
- {
- DiosStMRouteLine *p = (*m_pOutRouteLineVec)[i];
- delete p;
- }
- }
- delete m_pOutRouteLineVec;
- m_pOutRouteLineVec = NULL;
- }
- if (m_pRouteLineEvents != nullptr)
- {
- delete m_pRouteLineEvents;
- m_pRouteLineEvents = nullptr;
- }
- }
- void DiosStMRoutePos::Active(bool state,DWORD timeout)
- {
- m_ActiveState = state;
- if (m_ActiveState == false)
- {
- m_Timeout = timeout;
- }
- else
- {
- //get maximum timeperiod
- if (timeout > m_Timeout)
- {
- m_Timeout = timeout;
- }
- }
- }
- bool DiosStMRoutePos::GetActiveState()
- {
- return m_ActiveState;
- }
- bool DiosStMRoutePos::IsSMachine()
- {
- return false;
- }
- bool DiosStMRoutePos::PosAddOutRouteLine(DiosStMEvt *Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName)
- {
- DiosStMRouteLine *pLine = new DiosStMRouteLine();
- pLine->SetRoute(*Evt, pSrcPosName, pGuardName, pDesPosName);
- pLine->Active(true, 0);
- m_resEvent2DestPos.update(Evt->GetEventName(), pDesPosName);
- m_pOutRouteLineVec->push_back(pLine);
- m_pRouteLineEvents->push_back(Evt);
- return true;
- }
- void DiosStMRoutePos::SetName(const char *pName)
- {
- (*m_pRoutePosName) = pName;
- }
- const char* DiosStMRoutePos::GetName()
- {
- return m_pRoutePosName->c_str();
- }
- DWORD DiosStMRoutePos::GetRouteLineCount()
- {
- if (m_pOutRouteLineVec)
- {
- return (DWORD)m_pOutRouteLineVec->size();
- }
- return 0;
- }
- DiosStMRouteLine **DiosStMRoutePos::GetOutRouteLineVec()
- {
- if (m_pOutRouteLineVec)
- {
- if (m_pOutRouteLineVec->size() > 0)
- {
- return &((*m_pOutRouteLineVec)[0]);
- }
- }
- return NULL;
- }
- DiosStMRouteLine *DiosStMRoutePos::operator [](DiosStMEvt &Evt)
- {
- if (m_pOutRouteLineVec)
- {
- if (m_pOutRouteLineVec->size() > 0)
- {
- for (size_t i = 0; i < m_pOutRouteLineVec->size(); i++)
- {
- if ((*(DiosStMEvt *)(*(*m_pOutRouteLineVec)[i])) == Evt)
- {
- return (*m_pOutRouteLineVec)[i];
- }
- }
- }
- }
- return NULL;
- }
- DWORD DiosStMRoutePos::GetTimeout()
- {
- return m_Timeout;
- }
- void DiosStMRoutePos::SetDisable(ResDataObject disable)
- {
- m_resDisable = disable;
- }
- void DiosStMRoutePos::SetBreak(bool bBreakIn, bool bBreakAction, bool bBreakOut)
- {
- m_bBreakIn = bBreakIn;
- m_bBreakAction = bBreakAction;
- m_bBreakOut = bBreakOut;
- }
- DIOSSTMRET DiosStMRoutePos::DoIn(DiosSMachineIF* pSM)
- {
- if (pSM->InDebugMode() && m_bBreakIn)
- pSM->WaitContinue();
- for (int x = 0; x < m_resDisable.size(); x++)
- {
- pSM->EnableEvent((const char*)m_resDisable[x], false);
- }
- return DIOSSMRET_OK;
- }
- DIOSSTMRET DiosStMRoutePos::DoOut(DiosSMachineIF* pSM)
- {
- if (pSM->InDebugMode() && m_bBreakOut)
- pSM->WaitContinue();
- for (int x = 0; x < m_resDisable.size(); x++)
- {
- pSM->EnableEvent((const char*)m_resDisable[x], true);
- }
- return DIOSSMRET_OK;
- }
- DIOSSTMRET DiosStMRoutePos::DoAction(DiosSMachineIF* pSM) //执行进入当前状态的Action
- {
- ResDataObject resAction, resUserVaiable, resSystemVaiable;
- if (pSM->InDebugMode() && m_bBreakAction)
- pSM->WaitContinue();
- pSM->GetUserVariable(nullptr, resUserVaiable);
- pSM->GetSystemVariable(nullptr, resSystemVaiable);
- DIOSSTMRET ret = m_pDevicePool->StateMachineAction(&m_resStateActions, resAction, &resUserVaiable, m_Timeout);
- //存入系统变量
- //如果超时,触发超时
- if (ret == DIOSSMRET_TIMEOUT)
- {
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- if (resAction.size() <= 0)
- {
- pEvent->Active("Timeout", &resAction, "");
- }
-
- for (int aidx = 0; aidx < resAction.size(); aidx++)
- {
- string device = resAction.GetKey(aidx);
- pEvent->Active("Timeout", &resAction[aidx], device.substr(0, device.find('.')).c_str());
- }
- }
- }
- else if(resAction.size() <= 0)
- {
- //没有Action定义
- }
- //触发Action执行结果处理
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- for (int aidx = 0; aidx < resAction.size(); aidx++)
- {
- string device = resAction.GetKey(aidx);
- pEvent->Active("Action", &resAction[aidx], device.substr(0, device.find('.')).c_str());
- }
- }
- return ret;
- }
- //定时检查是否超时,最小间隔为1s,有可能不执行
- DIOSSTMRET DiosStMRoutePos::CheckTimeout()
- {
- return DIOSSMRET_NG;
- }
- //状态到了的检查,是否激活事件
- DIOSSTMRET DiosStMRoutePos::CheckNotify(const char* pszDevice, ResDataObject* res)
- {
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- pEvent->Active("Notify", res, pszDevice);
- }
- return DIOSSMRET_OK;
- }
- bool DiosStMRoutePos::TriggerEvent(const char* pszEvent)
- {
- ResDataObject res;
- bool bRet = false;
- res = pszEvent;
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- bRet |= pEvent->Active("External", &res, "");
- }
- return bRet;
- }
- DiosStMRouteLine* DiosStMRoutePos::WaitFroNextState(int timeout) //等待进入下一个状态
- {
- //在正常逻辑下,单个状态的 Action只会触发 当前状态的 事件
- // 除非有异常发生,产生了意外通知,这个由全局事件来管理
- HANDLE* pAllHandle = new HANDLE[m_pRouteLineEvents->size()];
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- pAllHandle[x] = pEvent->GetHandle();
- }
- DWORD dwret = WaitForMultipleObjects(m_pRouteLineEvents->size(), pAllHandle, FALSE, timeout);
- if (dwret >= WAIT_OBJECT_0 && dwret < WAIT_OBJECT_0 + m_pRouteLineEvents->size())
- {
- (*m_pRouteLineEvents)[dwret - WAIT_OBJECT_0]->Reset();
- delete[] pAllHandle;
- return m_pOutRouteLineVec->at(dwret - WAIT_OBJECT_0);
- }
- delete[] pAllHandle;
- return nullptr;
- }
- void DiosStMRoutePos::EnableEvent(const char* pszEventName, bool state)
- {
- for (int x = 0; x < m_pRouteLineEvents->size(); x++)
- {
- DiosStMEvt* pEvent = (*m_pRouteLineEvents)[x];
- if (*pEvent == pszEventName)
- {
- pEvent->Enable(state);
- return;
- }
- }
- }
- //================================
- //-------------------------------------
- DiosSMachine::DiosSMachine()
- {
- m_pStatePosList = new MsgQueue<ResDataObject>();
- m_StateQuedEvent = CreateEvent(0, 1, 0, 0);
- m_pDevicePool = new StateMachineDevicePool();
- m_strName = "DiosSMachine";
- m_pGlobalRoute = new DiosStMRoutePos("Global", m_pDevicePool);
- }
- DiosSMachine::~DiosSMachine()
- {
- delete m_pStatePosList;
- CloseHandle(m_StateQuedEvent);
-
- //if (GetLogger() != 0)
- //{
- // ReleseLogger((Logger*)GetLogger());
- // SetLogger(0);
- //}
- delete m_pDevicePool;
- }
- void DiosSMachine::SetStateMachineLog(const char *pszLogTitle)
- {
- //if (GetLogger() == 0)
- //{
- // string logfile = GetProcessDirectory() + "\\logs\\";
- // logfile = FormatstdString("%s%s.log", logfile.c_str(), pszLogTitle);
- // //Logger *pLog = CreateLogger();
- // pLog->SetLogFilepath(logfile.c_str());
- // SetLogger(pLog);
- //}
- }
- bool DiosSMachine::OnStartThread()
- {
- return PrePareStateMachine();
- }
- bool DiosSMachine::Exec()
- {
- ExecStateMachine(GetExitEvt());
- return false;
- }
- void DiosSMachine::PushStateChange(ResDataObject &ChangedPos)
- {
- m_pStatePosList->InQueue(ChangedPos);
- SetEvent(m_StateQuedEvent);
- }
- bool DiosSMachine::PopStateChange(ResDataObject &LastPos)
- {
- bool ret = false;
- if (m_pStatePosList->size() > 0)
- {
- m_pStatePosList->DeQueue(LastPos);
- m_LastHitStatePos = LastPos;
- ret = true;
- }
- if (m_pStatePosList->size() == 0)
- {
- ResetEvent(m_StateQuedEvent);
- }
- else
- {
- SetEvent(m_StateQuedEvent);
- }
- if (ret == false)
- {
- if (m_LastHitStatePos.size() > 0)
- {
- LastPos = m_LastHitStatePos;
- ret = true;
- }
- }
- return ret;
- }
- HANDLE DiosSMachine::GetStateQuedEvent()
- {
- return m_StateQuedEvent;
- }
- bool DiosSMachine::StartStateMachine(/*DiosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount*/)
- {
- m_LastHitStatePos.clear();
- if (WaitTheThreadEnd(0) == false)
- {
- //it's in running state
- printf("StartStateMachine Failed.it's in running state\n");
- return false;
- }
- //if (pExternalWaitEvts != NULL && WaitCount > 0)
- //{
- // m_RouteExternalEvtCount = WaitCount;
- // m_pRouteExternalMap = &pExternalWaitEvts[0];
- //}
- bool ret = StartThread();
- if (ret)
- {
- return GetRunningState(TIMEOUT_TEMP);
- }
- return ret;
- }
- void DiosSMachine::StopStateMachine(DWORD timeout)
- {
- //直接StopThread好像不是个办法,得让状态机退出前进行OnExit操作.
- StopThread(timeout);
- ClearState();
- }
- //DiosSubSMachine::DiosSubSMachine(void)
- //{
- //
- //}
- //
- //DiosSubSMachine::DiosSubSMachine(const char *pName) : DiosStMRoutePos(pName)
- //{
- // SetStateMachineName(pName);
- //}
- //
- //DiosSubSMachine::~DiosSubSMachine(void)
- //{
- //
- //}
- //
- //bool DiosSubSMachine::IsSMachine()
- //{
- // return true;
- //}
- bool DiosSMachine::Reset(DWORD Timeout)
- {
- StopStateMachine(Timeout);
- return m_pDevicePool->ClearDevices();
- }
- bool DiosSMachine::AddDevices(ResDataObject& DevList)
- {
- return m_pDevicePool->AddDevices(DevList);
- }
- bool DiosSMachine::ClearDevices()
- {
- return m_pDevicePool->ClearDevices();
- }
- bool DiosSMachine::TriggerEvent(const char* pEventName)
- {
- //DiosStMEvt Evt;
- bool bRet = false;
- printf("TriggerEvent:%s\n", pEventName);
- mLog::FDEBUG("TriggerEvent:%s\n", pEventName);
- if (!(bRet = m_pCurrentRoutePos->TriggerEvent(pEventName)))
- {
- //当前状态没有处理该事件
- bRet = m_pGlobalRoute->TriggerEvent(pEventName);
- }
- return bRet;
- //string ErrEvent = DiosErrorType;
- //if (ErrEvent == pEventName)
- //{
- // Evt.SetEvt(DiosErrorType, DiosFrameError);
- //}
- //else
- //{
- // Evt.SetEvt(pEventName, NULL);
- //}
- //return PushEvent(Evt);
- }
- //bool DiosSMachine::AddStateActions(ResDataObject& ActionMap)
- //{
- // return m_pDevicePool->AddStateActions(ActionMap);
- //}
- //
- //bool DiosSMachine::AddStateEvents(ResDataObject& EventMap)
- //{
- // return m_pDevicePool->AddStateEvents(EventMap);
- //}
- //从状态机定义中加载当前状态机定义
- //MachineName:单值
- //Variable:对象
- //States:
- // Begin:
- // xxxState:
- // In:
- // Out:
- // Action
- // Event:当前状态事件
- // End:
- // Event: 全局事件
- bool DiosSMachine::LoadMachine(ResDataObject& Machine)
- {
- //
- if (Machine.GetFirstOf("MachineName") >= 0)
- *m_pStateMachineName = (const char*)(Machine["MachineName"]);
- if (Machine.GetFirstOf("Variable") >= 0)
- m_resUserVariable = Machine["Variable"];
- ResDataObject stats;
- if (Machine.GetFirstOf("States") >= 0)
- stats = Machine["States"];
- if (stats.size() <= 0)
- return false;
- ResDataObject globalEvt;
- if (Machine.GetFirstOf("Events") >= 0)
- globalEvt = Machine["Events"];
- m_StmEntryPosName = (string)stats["Begin"];
- m_StmExitPosName = (string)stats["End"];
- ResDataObject stStep;
- int timeout = 0;
- for (int x = 0; x < stats.size(); x++)
- {
- string name = stats.GetKey(x);
- if (name != "Begin" && name != "End")
- {
- stStep = stats[x];
- //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);
- //状态点
- DiosStMRoutePos* pStep = new DiosStMRoutePos(name.c_str(), m_pDevicePool);
-
- AddRoutePos(pStep);
- //全局路由
- ResDataObject in;
- if (stStep.GetFirstOf("In") >= 0)
- {
- //有In全局路由
- ResDataObject ins = stStep["In"];
- for (int ot = 0; ot < ins.size(); ot++)
- {
- string evtName = ins.GetKey(ot);
- if (globalEvt.GetFirstOf(evtName.c_str()) >= 0)
- {
- //找到事件定义
- DiosStMEvt* stEvt = new DiosStMEvt();
- stEvt->parse(&globalEvt[evtName.c_str()]);
- //全局事件设置
- AddInRouteLine(*stEvt, (const char*)ins[evtName.c_str()], (const char*)ins[evtName.c_str()]);
- }
- }
- }
- if (stStep.GetFirstOf("Out") < 0)
- {
- //该状态点没有出路由,有问题,状态机不完整
- return false;
- }
- if (stStep.GetFirstOf("Event") < 0)
- {
- //事件表有问题
- return false;
- }
- if (stStep.GetFirstOf("Action") < 0)
- {
- //Action表有问题
- return false;
- }
- ResDataObject out = stStep["Out"];
- ResDataObject evt = stStep["Event"];
- ResDataObject action = stStep["Action"];
- for (int otIdx = 0; otIdx < out.size(); otIdx++)
- {
- string evtName = out.GetKey(otIdx);
- if (evt.GetFirstOf(evtName.c_str()) >= 0)
- {
- //找到事件定义
- DiosStMEvt* stEvt = new DiosStMEvt();
- stEvt->SetEvt(evtName.c_str(), evtName.c_str(), evt[evtName.c_str()]);
- stEvt->parse(&evt[evtName.c_str()]);
- //AddOutRouteLine(*stEvt, name.c_str(), name.c_str(), (const char*)out[evtName.c_str()]);
- pStep->PosAddOutRouteLine(stEvt, name.c_str(), name.c_str(), (const char*)out[evtName.c_str()]);
- int evtTimeout = stEvt->GetTimeout();
- if (evtTimeout > timeout)
- timeout = evtTimeout;
- }
- }
- ////禁用全局事件
- if (evt.GetFirstOf("Disable") >= 0)
- {
- pStep->SetDisable(evt["Disable"]);
- }
- std::cout << "StateMachine Add " << name << " has out line [" << pStep->GetRouteLineCount() << "] " << endl;
- //Actions
- if (timeout < STATEMACHINE_ACTION_TIMEOUT)
- timeout = STATEMACHINE_ACTION_TIMEOUT;
- pStep->Active(true, timeout);
- pStep->SetAction(action);
- }
- }
- PrePareStateMachine();
- return true;
- }
- void DiosSMachine::ClearStateActionMaps()
- {
- m_pDevicePool->ClearStateActionMaps();
- }
- void DiosSMachine::ClearStateEventMaps()
- {
- m_pDevicePool->ClearStateEventMaps();
- }
- bool DiosSMachine::RunStateMachine(const char* pszLogTitle)
- {
- SetStateMachineLog(pszLogTitle);
- return StartStateMachine();
- }
- DIOSSTMRET DiosSMachine::StateMachineEntry(DWORD timeout)
- {
- printf("Enter Dr StateMachine\n");
- mLog::FDEBUG("Enter Dr StateMachine");
- m_pDevicePool->SetThreadExitHandle(GetExitEvt());
- return DIOSSMRET_OK;
- }
- DIOSSTMRET DiosSMachine::StateMachineExit(DWORD timeout)
- {
- printf("Exit Dr StateMachine\n");
- mLog::FDEBUG("Exit Dr StateMachine");
- return DIOSSMRET_OK;
- }
- //DIOSSTMRET DiosSMachine::StateMachineAction(const char* pAction, DWORD timeout)
- //{
- // return m_pDevicePool->StateMachineAction("Root", m_pCurrentRoutePos->GetName(), timeout);
- //}
- //
- //DIOSSTMRET DiosSMachine::StateMachineGuard(const char* pGuard, DWORD timeout)
- //{
- // return DIOSSMRET_OK;
- //}
- //int DiosSMachine::StateMachineWaitForEvents(
- // DiosStMRouteLine* pLocalEvts[], DWORD CountOfLocal,
- // //DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal,
- // DiosStMRouteLine* pOutpathEvts[], DWORD CountOfOutpath,
- // DWORD timeout
- //)
- //{
- // return m_pDevicePool->StateMachineWaitForEvents(this, pLocalEvts, CountOfLocal, pOutpathEvts, CountOfOutpath, timeout);
- //}
- DiosStMRouteLine* DiosSMachine::WaitNotfiyProcess()
- {
- DiosStMRouteLine* pRet = nullptr;
- ResDataObject resNotify;
- m_pDevicePool->ReadForDeviceEvents(resNotify, 200, m_pCurrentRoutePos->GetRouteLineCount()/2 + 1);
- for (int x = 0; x < resNotify.size(); x++)
- {
- ResDataObject notify = resNotify[x];
- string ntName = resNotify.GetKey(x);
- ntName = ntName.substr(0, ntName.find('.'));
- //当前状态的事件检查
- m_pCurrentRoutePos->CheckNotify(ntName.c_str(), ¬ify);
- //全局事件的检查
- m_pGlobalRoute->CheckNotify(ntName.c_str(), ¬ify);
- }
- //优先检查当前状态
- pRet = m_pCurrentRoutePos->WaitFroNextState(50);
- if (pRet != nullptr)
- {
- //必须消耗掉全局的已触发的事件
- m_pGlobalRoute->WaitFroNextState(1);
- return pRet;
- }
- //全局状态跳转
- pRet = m_pGlobalRoute->WaitFroNextState(50);
- return pRet;
- }
|