CcosSMachineV3.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. // CcosSMachine.cpp : 定义 DLL 应用程序的导出函数。
  2. //
  3. #include <sstream>
  4. #include "stdafx.h"
  5. #include "common_api.h"
  6. #include "CcosSMachineV3.h"
  7. #include "CcosThread.h"
  8. #include "LogLocalHelper.h"
  9. #include "Log4CPP.h"
  10. using namespace std;
  11. static string glo_runHistory;
  12. static string glo_eventList;
  13. #define Wxx_Test 0
  14. //-----------------标准状态机--------------------
  15. CcosSMachine::CcosSMachine()
  16. {
  17. try {
  18. string strLogPath = GetProcessDirectory() + R"(/Conf/log_config.xml)";
  19. string LogHost = (string)getRootpath();
  20. std::string moduleName = "StateMachineV3";
  21. bool ret = initLogModule(
  22. LogHost, // 主机名(用于日志路径中的{host}占位符)
  23. moduleName, // 唯一模块名
  24. strLogPath, // 配置文件路径
  25. true // 是否输出到控制台(可选)
  26. );
  27. if (!ret) {
  28. std::cerr << "Log init failed!" << std::endl;
  29. }
  30. // 绑定当前动态库的模块名(调用自身实现的接口)
  31. MachineV3_SetLocalModuleName(moduleName);
  32. m_hTransStateEvt = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, false);
  33. m_hRunningEvt = LinuxEvent::CreateEvent(LinuxEvent::MANUAL_RESET, false);
  34. m_strName = "CcosSMachineV3";
  35. m_nSMState = SMST_NULL;
  36. FDEBUG("StateMachine:[SMST_NULL:{$}]", (int)SMST_NULL);
  37. }
  38. catch (...)
  39. {
  40. FERROR("CcosSMachine crash");
  41. }
  42. }
  43. CcosSMachine::~CcosSMachine()
  44. {
  45. /*if (m_pUIDebugObj)
  46. {
  47. if(m_pUIDebugObj->GetTID())
  48. m_pUIDebugObj->StopThread();
  49. delete m_pUIDebugObj;
  50. m_pUIDebugObj = nullptr;
  51. }*/
  52. StopStateMachine(STATEMACHINE_DefState_TIMEOUT);
  53. }
  54. bool CcosSMachine::Exec()
  55. {
  56. ExecStateMachine();
  57. return false;
  58. }
  59. bool CcosSMachine::OnStartThread()
  60. {
  61. if (CCOSSMRET_SUCCESS == StateMachineEntry(STATEMACHINE_DefState_TIMEOUT)) //进入流程跳转
  62. {
  63. return true;
  64. }
  65. else
  66. {
  67. FERROR("StateMachineEntry Failed");
  68. return false;
  69. }
  70. }
  71. bool CcosSMachine::OnEndThread()
  72. {
  73. //防止ExecStateMachine处于等待
  74. if (CCOSSMRET_SUCCESS == StateMachineExit(STATEMACHINE_DefState_TIMEOUT))//退出流程跳转
  75. return true;
  76. else
  77. return false;
  78. }
  79. void CcosSMachine::ClearState()
  80. {
  81. Thread_Lock();
  82. m_EventsList.clear();
  83. m_EventsList.reserve(STATEMACHINE_MaxWaitEventList);
  84. m_StateMap.clear();
  85. m_DeviceMap.clear();
  86. m_AttributeCountMap.clear();
  87. Thread_UnLock();
  88. }
  89. CCOSSTMRET CcosSMachine::StateMachineEntry(DWORD timeout)
  90. {
  91. FDEBUG("Enter StateMachine");
  92. CCOSSTMRET ret = CCOSSMRET_FAILED;
  93. //跳转至起始状态
  94. if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END)
  95. {
  96. FWARN("wrong state[{$}] can't -> SMST_BEGIN", (int)m_nSMState.load());
  97. }
  98. else
  99. {
  100. FDEBUG("StateMachine:[SMST_BEGIN:{$}]", (int)SMST_BEGIN);
  101. m_nSMState = SMST_BEGIN;
  102. m_strCurrentState.clear();
  103. //给client池设置上层退出事件
  104. m_DevicePool.SetTopExitHandle(GetExitEvt());
  105. //提前将不存在设备的属性关联的条件设置为true
  106. for (auto& item : m_EventsList)
  107. {
  108. if (item.GetType() == EventType_Conditions)
  109. {
  110. map<string, stru_Condition>* coditionsMap = item.GetCoditionsMap();
  111. if (coditionsMap)
  112. {
  113. for (auto& finder : (*coditionsMap))
  114. {
  115. auto checker = m_AttributeCountMap.find(finder.second.m_Key);
  116. if (checker != m_AttributeCountMap.end())
  117. {
  118. if (checker->second <= 0)
  119. {
  120. finder.second.m_Result = true;
  121. item.CaculateCondition();
  122. }
  123. }
  124. }
  125. }
  126. }
  127. }
  128. //检查是否有直接跳转至下一个状态,有则激活
  129. CheckExternal();
  130. //状态跳转至起始状态
  131. ret = TransToPos(m_strBeginState.c_str());
  132. if (ret == CCOSSMRET_SUCCESS)//跳转成功后执行初始状态动作
  133. {
  134. ret = StateMachineAction(m_strBeginState.c_str(), timeout);
  135. }
  136. if (ret == CCOSSMRET_SUCCESS)//给client池设置属性获取后的处理接口
  137. {
  138. auto NotfiyProcess = [this](string& Pathkey, string& Context) -> void
  139. {
  140. WaitNotfiyProcess(Pathkey, Context);
  141. };
  142. if (!m_DevicePool.BeginNotifyLoop(NotfiyProcess))
  143. {
  144. ret = CCOSSMRET_FAILED;
  145. }
  146. }
  147. }
  148. return ret;
  149. }
  150. CCOSSTMRET CcosSMachine::StateMachineExit(DWORD timeout)
  151. {
  152. FDEBUG("Exit StateMachine");
  153. //跳转至结束状态
  154. if (m_nSMState.load() == SMST_END)
  155. {
  156. FDEBUG("StateMachine:[SMST_EXIT:{$}]", (int)SMST_EXIT);
  157. m_nSMState = SMST_EXIT;
  158. m_strCurrentState.clear();
  159. //结束client池属性获取循环
  160. m_DevicePool.EndNotifyLoop();
  161. }
  162. return CCOSSMRET_SUCCESS;
  163. }
  164. bool CcosSMachine::ExecStateMachine()
  165. {
  166. CCOSSTMRET ret = CCOSSMRET_NULL;
  167. try {
  168. //设置运行状态
  169. SetRunningState(true);
  170. do
  171. {
  172. //防止状态机流程状态跳转过快导致上层处理不过来
  173. if (m_hRunningEvt->Wait())
  174. {
  175. if (m_nSMState.load() == SMST_END || m_nSMState.load() == SMST_EXIT)
  176. {
  177. break;
  178. }
  179. }
  180. //获取当前状态关于超时的定义
  181. string timeoutState;
  182. DWORD confTimeout = GetCurrentStateTimeout(timeoutState);
  183. //检查是否有直接跳转至下一个状态,有则激活
  184. //string eventFrom;
  185. //GetCurrentState(eventFrom);
  186. //CheckExternal(eventFrom);
  187. //等待跳转到下一个状态条件触发
  188. string nextState;
  189. DWORD waitEventCount = m_hCurrentWaitEvtArray.size();
  190. if (waitEventCount <= 1 && confTimeout == INFINITE)//固定会有一个线程退出句柄
  191. {
  192. FERROR("CurrentWaitEvtArray is empty and no TimeoutEvt");
  193. return false;
  194. }
  195. DWORD dwret = LinuxEvent::WaitForMultipleEvents(m_hCurrentWaitEvtArray,confTimeout);
  196. if (dwret >= WAIT_OBJECT_0 && dwret < WAIT_OBJECT_0 + waitEventCount)
  197. {
  198. int eventNumber = dwret - WAIT_OBJECT_0;
  199. if (eventNumber >= 0 && eventNumber < waitEventCount)
  200. {
  201. std::cout << "Triggered eventList[" << m_hCurrentWaitEvtArray[eventNumber] << "]" << std::endl;
  202. if (m_hCurrentWaitEvtArray[eventNumber] == GetExitEvt())//Exec结束所以退出
  203. {
  204. return false;
  205. }
  206. else//获取触发事件对应的To
  207. {
  208. for (auto& findItem : m_EventsList)
  209. {
  210. if (m_hCurrentWaitEvtArray[eventNumber] == findItem.GetTriggerHandle())
  211. {
  212. nextState = findItem.GetTo();
  213. FDEBUG("wait Event[{$}] Triggered", findItem.GetName().c_str());
  214. if (findItem.GetFrom().empty())//全局事件只允许触发一次
  215. {
  216. findItem.ResetTrigger();
  217. }
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. else
  224. {
  225. FERROR("Trigger event number[{$}] not exist", eventNumber);
  226. }
  227. }
  228. else if (dwret == -1)
  229. {
  230. if (!timeoutState.empty())
  231. {
  232. nextState = timeoutState;
  233. FDEBUG("status[{$}] wait[{$}] timeout", m_strCurrentState.c_str(), (int)confTimeout);
  234. }
  235. else
  236. {
  237. break;
  238. }
  239. }
  240. else
  241. {
  242. FERROR("WaitForMultipleObjects get wrong [{$}] return", dwret);
  243. }
  244. //可以跳转至下一个状态
  245. if (!nextState.empty())
  246. {
  247. //获取当前状态
  248. string CurrentState;
  249. GetCurrentState(CurrentState);
  250. if (nextState == CurrentState)//状态跳转至自身为死循环了
  251. {
  252. FERROR("StateMachinein loop[{$}]", nextState.c_str());
  253. return false;
  254. }
  255. if (TransToPos(nextState.c_str()) != CCOSSMRET_SUCCESS)//跳转至下一个状态
  256. {
  257. FERROR("TransToPos[{$}] failed", nextState.c_str());
  258. return false;
  259. }
  260. //获取状态跳转后的超时定义
  261. confTimeout = GetCurrentStateTimeout(timeoutState);
  262. //执行新状态对应的方法
  263. ret = StateMachineAction(nextState.c_str(), confTimeout);
  264. switch (ret)
  265. {
  266. case CCOSSMRET_SUCCESS:
  267. {}break;
  268. case CCOSSMRET_TIMEOUT:
  269. case CCOSSMRET_FAILED:
  270. {
  271. if (!timeoutState.empty())
  272. {
  273. nextState = timeoutState;
  274. }
  275. else
  276. {
  277. break;
  278. }
  279. }break;
  280. case CCOSSMRET_EXIT:
  281. {
  282. return false;
  283. }break;
  284. default:
  285. break;
  286. }
  287. }
  288. if (m_strEndState == nextState)
  289. {
  290. break;
  291. }
  292. } while (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END);
  293. }
  294. catch (...)
  295. {
  296. FERROR("ExecStateMachine crash");
  297. StopStateMachine(STATEMACHINE_DefState_TIMEOUT);
  298. }
  299. return true;
  300. }
  301. DWORD CcosSMachine::GetCurrentStateTimeout(string& timeoutState)
  302. {
  303. int timeout = INFINITE;
  304. string eventFrom; GetCurrentState(eventFrom);
  305. string eventTo;
  306. string confTimeout;
  307. for (auto& item : m_EventsList)
  308. {
  309. if (item.CheckTimeout(confTimeout, eventFrom, eventTo))
  310. {
  311. timeoutState = eventTo;
  312. timeout = atol(confTimeout.c_str());
  313. return timeout;
  314. }
  315. }
  316. return timeout;
  317. }
  318. CCOSSTMRET CcosSMachine::CheckExternal(string eventFrom)
  319. {
  320. string eventTo;
  321. int activeCount = 0;
  322. for (auto &item : m_EventsList)
  323. {
  324. if (item.CheckExternal(eventFrom, eventTo))
  325. {
  326. activeCount++;
  327. }
  328. }
  329. if(activeCount > 0)
  330. return CCOSSMRET_SUCCESS;
  331. else
  332. return CCOSSMRET_FAILED;
  333. }
  334. void CcosSMachine::WaitNotfiyProcess(string& Pathkey, string& Context)
  335. {
  336. string deviceKey = Pathkey;
  337. string strValue = Context;
  338. string eventFrom; GetCurrentState(eventFrom);
  339. //当前状态的事件检查
  340. for (auto& item : m_EventsList)
  341. {
  342. string eventTo;
  343. item.CheckConditions(deviceKey, strValue, eventFrom, eventTo);
  344. }
  345. }
  346. CCOSSTMRET CcosSMachine::TransToPos(const char* pPosName)
  347. {
  348. CCOSSTMRET ret = CCOSSMRET_NULL;
  349. try {
  350. auto findItem = m_StateMap.find(pPosName);
  351. if (findItem == m_StateMap.end())
  352. {
  353. ret = CCOSSMRET_EXIT;
  354. }
  355. else
  356. {
  357. Thread_Lock();
  358. //设置新事件
  359. m_strCurrentState = pPosName;
  360. Thread_UnLock();
  361. /*if (m_pUIDebugObj)
  362. {
  363. string temp(pPosName);
  364. glo_runHistory += (temp + "->");
  365. m_pUIDebugObj->SetRunHistory(glo_runHistory);
  366. }*/
  367. m_hCurrentWaitEvtArray.clear(); //清除之前的等待事件列表
  368. m_hCurrentWaitEvtArray.push_back(GetExitEvt());//设置Exec退出事件
  369. for (int i = 0; i < m_EventsList.size(); i++)//设置当前的等待事件表
  370. {
  371. vector<string> eventFrom = m_EventsList[i].GetFrom();
  372. if (eventFrom.empty() || std::find(eventFrom.begin(), eventFrom.end(), pPosName) != eventFrom.end())
  373. {
  374. if (m_EventsList[i].GetTriggerHandle())
  375. {
  376. m_hCurrentWaitEvtArray.push_back(m_EventsList[i].GetTriggerHandle());
  377. std::cout << "current wait eventList[" << m_hCurrentWaitEvtArray[i] << "]" << std::endl;
  378. glo_eventList += m_EventsList[i].GetName();
  379. }
  380. else
  381. {
  382. FERROR("state[{$}] no TriggerHandle", m_EventsList[i].GetName().c_str());
  383. }
  384. }
  385. }
  386. /*if (m_pUIDebugObj)
  387. {
  388. m_pUIDebugObj->SetWaitEventList(glo_eventList);
  389. }*/
  390. //先停止后续流程跳转,给予上层订阅者执行时间
  391. SetRunningState(false);
  392. //再回调通知
  393. if (m_StateNotify != nullptr)
  394. {
  395. m_StateNotify(m_strMachineName.c_str(), pPosName);
  396. }
  397. //最后以事件通知上层订阅者(一般是子系统)
  398. m_hTransStateEvt->SetEvent();
  399. FDEBUG("TransToPos:[{$}]", pPosName);
  400. ret = CCOSSMRET_SUCCESS;
  401. }
  402. }
  403. catch (...)
  404. {
  405. FERROR("TransToPos crash");
  406. ret = CCOSSMRET_NULL;
  407. }
  408. return ret;
  409. }
  410. CCOSSTMRET CcosSMachine::StateMachineAction(const char* pState, DWORD timeout)
  411. {
  412. CCOSSTMRET ret = CCOSSMRET_NULL;
  413. auto findItem = m_StateMap.find(pState);
  414. if (findItem != m_StateMap.end())
  415. {
  416. //查找状态中的动作定义
  417. if (findItem->second.GetFirstOf(ConfItem_Actions) >= 0)
  418. {
  419. ResDataObject reqAction = findItem->second[ConfItem_Actions];
  420. ResDataObject resAction;
  421. //执行动作
  422. ret = m_DevicePool.StateMachineAction(reqAction, resAction, timeout);
  423. switch (ret)
  424. {
  425. case CCOSSMRET_SUCCESS:
  426. {
  427. //触发Action执行结果判断
  428. for (int aidx = 0; aidx < resAction.size(); aidx++)
  429. {
  430. string key = resAction.GetKey(aidx);
  431. string deviceName = key.substr(0, key.find(ConfItem_delim));
  432. string actionKey = key.substr(key.find(ConfItem_delim) + 1, key.length());
  433. string actionRet = (string)resAction[aidx];
  434. string eventFrom; GetCurrentState(eventFrom);
  435. for (auto &item : m_EventsList)
  436. {
  437. string eventTo;
  438. string deviceNotfiyKey;
  439. item.CheckConditions(deviceNotfiyKey, actionRet, eventFrom, eventTo);
  440. }
  441. }
  442. }break;
  443. case CCOSSMRET_TIMEOUT:
  444. {}break;
  445. case CCOSSMRET_FAILED:
  446. {}break;
  447. case CCOSSMRET_EXIT:
  448. {}break;
  449. default:
  450. break;
  451. }
  452. }
  453. }
  454. else
  455. {
  456. FERROR("Unrecognized state[{$}]", pState);
  457. }
  458. return ret;
  459. }
  460. //=============对外提供接口=============
  461. void CcosSMachine::SetDebugMode(bool bEnable)
  462. {
  463. if (m_bDebugEnable != bEnable)
  464. {
  465. m_bDebugEnable = bEnable;
  466. FDEBUG("SetDebugMode[{$}]", m_bDebugEnable);
  467. if (m_bDebugEnable)
  468. {
  469. auto FUN_DlgCallBack = [this](string name, string value) -> void
  470. {
  471. if (name == "TriggerEvent")
  472. {
  473. TriggerEvent(value);
  474. }
  475. else if (name == "SetRunningState")
  476. {
  477. SetRunningState(true);
  478. }
  479. };
  480. /*m_pUIDebugObj = new SMachineDlg("Ccos State Mechine Debug", "CcosStateMechineDlg", FUN_DlgCallBack);
  481. m_pUIDebugObj->StartThread();*/
  482. }
  483. else
  484. {
  485. /*if (m_pUIDebugObj)
  486. {
  487. m_pUIDebugObj->StopThread();
  488. delete m_pUIDebugObj;
  489. }*/
  490. }
  491. }
  492. }
  493. bool CcosSMachine::Reset(DWORD Timeout)
  494. {
  495. for (auto& item : m_EventsList)
  496. {
  497. item.ResetTrigger();
  498. }
  499. return true;
  500. }
  501. bool CcosSMachine::TriggerEvent(string EventName)
  502. {
  503. FDEBUG("TriggerEvent:[{$}]", EventName.c_str());
  504. if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() <= SMST_END)
  505. {
  506. for (auto& item : m_EventsList)
  507. {
  508. if (item.GetName() == EventName)
  509. {
  510. item.SetTrigger();
  511. return true;
  512. }
  513. }
  514. }
  515. else
  516. {
  517. FWARN("wrong state[{$}] can't TriggerEvent",(int)m_nSMState.load());
  518. }
  519. return false;
  520. }
  521. void CcosSMachine::GetStateMachineState(SMSTATETYPE& state)
  522. {
  523. state = m_nSMState;
  524. }
  525. //从状态机定义中加载当前状态机定义
  526. bool CcosSMachine::LoadMachine(ResDataObject& Machine)
  527. {
  528. FDEBUG("Enter LoadMachine");
  529. if (m_nSMState.load() < SMST_BEGIN || m_nSMState.load() >= SMST_END)
  530. {
  531. m_nSMState = SMST_INIT;
  532. FDEBUG("StateMachine:[SMST_INIT:{$}]", (int)SMST_INIT);
  533. glo_runHistory.clear();
  534. glo_eventList.clear();
  535. if (Machine.GetFirstOf(ConfItem_MachineName) >= 0)
  536. {
  537. string tempName = (string)Machine[ConfItem_MachineName];
  538. if (m_strMachineName != tempName)
  539. {
  540. m_strMachineName = tempName;
  541. }
  542. else
  543. {
  544. FDEBUG("same workFlow file[{$}],didn't reload", m_strMachineName.c_str());
  545. Reset(STATEMACHINE_DefState_TIMEOUT);
  546. return true;
  547. }
  548. }
  549. ClearState();
  550. if (Machine.GetFirstOf(ConfItem_Variable) >= 0)
  551. {
  552. m_resUserVariable = Machine[ConfItem_Variable];
  553. }
  554. if (Machine.GetFirstOf(ConfItem_States) >= 0)
  555. {
  556. ResDataObject stats;
  557. stats = Machine[ConfItem_States];
  558. for (int i = 0; i < stats.size(); i++)
  559. {
  560. string stateName = stats.GetKey(i);
  561. if (stateName == ConfItem_Begin)
  562. {
  563. m_strBeginState = (string)stats[i];
  564. }
  565. else if (stateName == ConfItem_End)
  566. {
  567. m_strEndState = (string)stats[i];
  568. }
  569. else
  570. {
  571. ResDataObject stateDefine = stats[i];
  572. m_StateMap[stateName] = stateDefine;
  573. FDEBUG("get State[{$}]", stateName.c_str());
  574. if (stateDefine.GetFirstOf(ConfItem_Events) >= 0)
  575. {
  576. ResDataObject stateEvt = stateDefine[ConfItem_Events];
  577. int count = stateEvt.size();
  578. for (int i = 0; i < count; i++)
  579. {
  580. if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList)
  581. {
  582. string eventName = stateEvt.GetKey(i);
  583. m_EventsList.emplace_back(eventName, &(stateEvt[i]), &m_AttributeCountMap); //容器扩张导致会调用copy construct, 导致所有的m_hTriggered丢失
  584. FDEBUG("get member event[{$}]", eventName.c_str());
  585. }
  586. else
  587. {
  588. FDEBUG("eventList[size:{$}]too big", m_EventsList.size());
  589. }
  590. }
  591. }
  592. }
  593. }
  594. }
  595. if (Machine.GetFirstOf(ConfItem_Events) >= 0)
  596. {
  597. ResDataObject evts = Machine[ConfItem_Events];
  598. for (int i = 0; i < evts.size(); i++)
  599. {
  600. if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList)
  601. {
  602. string eventName = evts.GetKey(i);
  603. m_EventsList.emplace_back(eventName, &(evts[i]), &m_AttributeCountMap);
  604. FDEBUG("get global event[{$}]", eventName.c_str());
  605. }
  606. else
  607. {
  608. FDEBUG("eventList[size:{$}]too big", m_EventsList.size());
  609. }
  610. }
  611. }
  612. if (Machine.GetFirstOf(ConfItem_DevList) >= 0)
  613. {
  614. ResDataObject devs = Machine[ConfItem_DevList];
  615. if (devs.size() > 0)
  616. {
  617. AddDevices(devs, "");
  618. }
  619. }
  620. }
  621. else
  622. {
  623. FWARN("wrong state[{$}] can't -> SMST_INIT", (int)m_nSMState.load());
  624. }
  625. return true;
  626. }
  627. //设置用户变量,只提供根一层的Key
  628. void CcosSMachine::SetUserVariable(const char* pKey, ResDataObject& resValue)
  629. {
  630. int vidx = m_resUserVariable.GetFirstOf(pKey);
  631. if (vidx < 0)
  632. m_resUserVariable.add(pKey, resValue);
  633. }
  634. //读取用户变量值,只提供根一层的Key
  635. void CcosSMachine::GetUserVariable(const char* pKey, ResDataObject& resValue)
  636. {
  637. if (pKey == nullptr)
  638. {
  639. resValue = m_resUserVariable;
  640. return;
  641. }
  642. int vidx = m_resUserVariable.GetFirstOf(pKey);
  643. if (vidx >= 0)
  644. resValue = m_resUserVariable[vidx];
  645. }
  646. void CcosSMachine::SetStateMachineName(string Name)
  647. {
  648. m_strMachineName = Name;
  649. }
  650. string CcosSMachine::GetStateMachineName()
  651. {
  652. return m_strMachineName;
  653. }
  654. void CcosSMachine::SetNotifyCallback(StateChangedCallback callback)
  655. {
  656. m_StateNotify = callback;
  657. }
  658. bool CcosSMachine::AddStateActions(ResDataObject& ActionMap)
  659. {
  660. if (ActionMap.GetFirstOf(ConfItem_States) >= 0)
  661. {
  662. ResDataObject globalstatus;
  663. globalstatus = ActionMap[ConfItem_States];
  664. for (int i = 0; i < globalstatus.size(); i++)
  665. {
  666. string stateName = globalstatus.GetKey(i);
  667. if (stateName == ConfItem_Begin)
  668. {
  669. m_strBeginState = (string)globalstatus[i];
  670. }
  671. else if (stateName == ConfItem_End)
  672. {
  673. m_strEndState = (string)globalstatus[i];
  674. }
  675. else
  676. {
  677. ResDataObject stateDefine = globalstatus[i];
  678. m_StateMap[stateName] = stateDefine;
  679. FDEBUG("get State[{$}]", stateName.c_str());
  680. }
  681. }
  682. }
  683. return true;
  684. }
  685. bool CcosSMachine::AddStateEvents(ResDataObject& EventMap)
  686. {
  687. if (EventMap.GetFirstOf(ConfItem_Events) >= 0)
  688. {
  689. ResDataObject globalEvt = EventMap[ConfItem_Events];
  690. for (int i = 0; i < globalEvt.size(); i++)
  691. {
  692. if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList)
  693. {
  694. string eventName = globalEvt.GetKey(i);
  695. m_EventsList.emplace_back(eventName, &(globalEvt[i]), &m_AttributeCountMap);
  696. FDEBUG("get event[{$}]", eventName.c_str());
  697. }
  698. else
  699. {
  700. FDEBUG("eventList[size:{$}]too big", m_EventsList.size());
  701. }
  702. }
  703. }
  704. return true;
  705. }
  706. bool CcosSMachine::AddDevices(ResDataObject& DevList, string WS)
  707. {
  708. if (m_nSMState.load() == SMST_INIT)
  709. {
  710. FDEBUG("AddDevices:deviceCount[{$}], WorkStation[{$}]", (int)DevList.size(), WS.c_str());
  711. if (m_EventsList.empty())
  712. {
  713. FWARN("must LoadMachine first");
  714. return false;
  715. }
  716. m_DeviceMap.clear();
  717. for (int devIdx = 0; devIdx < DevList.size(); devIdx++)
  718. {
  719. string strDeviceType = DevList.GetKey(devIdx);
  720. string strDevicePath = DevList[devIdx].encode();
  721. m_DeviceMap[strDeviceType] = strDevicePath;
  722. }
  723. ResDataObject tempAttributes;
  724. for (auto& item : m_AttributeCountMap)
  725. {
  726. string devType = item.first.substr(0, item.first.find(ConfItem_delim));
  727. string attr = item.first.substr(item.first.find(ConfItem_delim) + 1, item.first.length());
  728. tempAttributes.add(devType.c_str(), attr.c_str());
  729. if (m_DeviceMap.find(devType) == m_DeviceMap.end())//不存在的设备判断条件默认为真
  730. {
  731. FWARN("device[{$}] not exist, Condition with Attribute[{$}] default true", devType.c_str(), item.first.c_str());
  732. item.second = 0;
  733. }
  734. }
  735. if (!m_DevicePool.SetDeviceAttributes(DevList, tempAttributes, WS))
  736. {
  737. FERROR("can't apply DeviceList of config file");
  738. return false;
  739. }
  740. }
  741. else
  742. {
  743. FWARN("wrong state[{$}] can't AddDevices", (int)m_nSMState.load());
  744. }
  745. return true;
  746. }
  747. //检查:路径,状态点,以及它们的ActiveState
  748. bool CcosSMachine::PrePareStateMachine()
  749. {
  750. //设备属性初始化
  751. for (auto &item : m_EventsList)
  752. {
  753. //使用Get?
  754. }
  755. return true;
  756. }
  757. bool CcosSMachine::StartStateMachine()
  758. {
  759. bool ret = true;
  760. if (m_nSMState.load() == SMST_INIT)
  761. {
  762. if (WaitTheThreadEnd(0) == false)
  763. {
  764. FERROR("StartStateMachine Failed.it's in running state");
  765. return false;
  766. }
  767. ret = StartThread();
  768. }
  769. else
  770. {
  771. FWARN("wrong state[{$}] can't StartStateMachine", (int)m_nSMState.load());
  772. }
  773. return ret;
  774. }
  775. std::shared_ptr<LinuxEvent> CcosSMachine::GetStateTransEvent()
  776. {
  777. return m_hTransStateEvt;
  778. }
  779. void CcosSMachine::GetCurrentState(string& State)
  780. {
  781. Thread_Lock();
  782. State = m_strCurrentState;
  783. Thread_UnLock();
  784. }
  785. void CcosSMachine::SetRunningState(bool Running)
  786. {
  787. if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() <= SMST_END)
  788. {
  789. if (Running)
  790. {
  791. if (m_nSMState != SMST_RUN)
  792. {
  793. FDEBUG("StateMachine:[SMST_RUN:{$}]", (int)SMST_RUN);
  794. m_nSMState = SMST_RUN;
  795. m_hRunningEvt->SetEvent();
  796. }
  797. }
  798. else
  799. {
  800. if (m_nSMState != SMST_STOP)
  801. {
  802. FDEBUG("StateMachine:[SMST_STOP:{$}]", (int)SMST_STOP);
  803. m_nSMState = SMST_STOP;
  804. m_hRunningEvt->ResetEvent();
  805. }
  806. }
  807. }
  808. else
  809. {
  810. FWARN("wrong state[{$}] can't -> SMST_RUN or SMST_STOP", (int)m_nSMState.load());
  811. }
  812. }
  813. void CcosSMachine::StopStateMachine(DWORD timeout)
  814. {
  815. if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END)
  816. {
  817. FDEBUG("StateMachine:[SMST_END:{$}]", (int)SMST_END);
  818. m_nSMState = SMST_END;
  819. SetRunningState(true);
  820. StopThread(timeout);
  821. m_StateNotify == nullptr;
  822. Reset(STATEMACHINE_DefState_TIMEOUT);
  823. FDEBUG("StateMachine:[SMST_EXIT:{$}]", (int)SMST_EXIT);
  824. m_nSMState = SMST_EXIT;
  825. }
  826. else
  827. {
  828. FWARN("StopStateMachine: already stop");
  829. }
  830. }
  831. #if Debug_HTTP
  832. RET_STATUS CcosSMachine::OnUpdate(const char* pszProperty, const char* pszValueUpdate, ResDataObject& resRespons)
  833. {
  834. return RET_STATUS::RET_SUCCEED;
  835. }
  836. RET_STATUS CcosSMachine::OnDel(const char* pszPropery, ResDataObject& resDelValue, ResDataObject& resResponse)
  837. {
  838. return RET_STATUS::RET_SUCCEED;
  839. }
  840. RET_STATUS CcosSMachine::OnAdd(const char* pszPropery, ResDataObject& reAddValue, ResDataObject& resResponse)
  841. {
  842. return RET_STATUS::RET_SUCCEED;
  843. }
  844. RET_STATUS CcosSMachine::SetItem(const char* pszPropery, ResDataObject& resSetValue, ResDataObject& resResponse)
  845. {
  846. return RET_STATUS::RET_SUCCEED;
  847. }
  848. RET_STATUS CcosSMachine::GetItem(const char* pszPropery, ResDataObject& resResponse)
  849. {
  850. return RET_STATUS::RET_SUCCEED;
  851. }
  852. RET_STATUS CcosSMachine::OnAction(const char* pszActionName, const char* pszParams, ResDataObject& resResponse)
  853. {
  854. return RET_STATUS::RET_SUCCEED;
  855. }
  856. #endif
  857. extern "C" void* CreateCcosSMachine()
  858. {
  859. return new CcosSMachine();
  860. }
  861. extern "C" void DeleteCcosSMachine(void* ptr)
  862. {
  863. if (ptr)
  864. {
  865. delete (CcosSMachine*)ptr;
  866. ptr = nullptr;
  867. }
  868. }