// DiosSMachine.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include "DiosSMachineV3.h" #include "common_api.h" #include using namespace std; //================================ DiosStMRoutePos::DiosStMRoutePos() { m_ActiveState = false; m_pRoutePosName = new string(); m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; m_pRouteLineEvents = new vector(); m_pDevicePool = nullptr; } DiosStMRoutePos::DiosStMRoutePos(const char *pName, StateMachineDevicePool* pDevicePool) { m_ActiveState = false; m_pRoutePosName = new string(); (*m_pRoutePosName) = pName; m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; m_pRouteLineEvents = new vector(); 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(); 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; }