PouExecution.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743
  1. #include "Pou.h"
  2. #include "WindowAppItemInterface.h"
  3. #include "WindowAppBlockStandard.h"
  4. #include "WindowAppBlockStandardBase.h"
  5. #include "WindowAppBlockGoto.h"
  6. #include "WindowAppBlockWait.h"
  7. #include "WindowAppVariableTable.h"
  8. #include "GvlManager.h"
  9. #include "TaskManager.h"
  10. #include "WindowAppTaskView.h"
  11. #include "WindowAppPouScene.h"
  12. #include "WindowAppPouFrame.h"
  13. #include "../Common/CameraBaseClass/IBaseCamCommon.h"
  14. #include "../Common/CameraBaseClass/IBaseCamera.h"
  15. //======================================================================
  16. //
  17. // 与Pou执行相关的函数集合
  18. //
  19. //======================================================================
  20. /// <summary>
  21. /// 2022-9-6,执行前预检查
  22. /// </summary>
  23. /// <param name="pTool"></param>
  24. /// <param name="runMode"></param>
  25. /// <returns></returns>
  26. VPEnum::RETURN_VALUE POU::ToolExecutionDispatcherPreCheck(TOOL*& pTool, TOOL_RUN_MODE runMode)
  27. {
  28. Q_UNUSED(runMode);
  29. // 如果本工具加入了并行组,则需要特殊处理一下
  30. if (pTool->isParallelSubTool())
  31. {
  32. //// 如果处于并行模式下运行,则等待执行信号
  33. //if (runMode == TOOL_RUN_MODE::IN_PARALLEL)
  34. //{
  35. // // 设置Tool为Wait状态
  36. // pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Wait;
  37. // vDebug() << "ParallelSubTool [" << pTool->strInstanceName << "] waiting...";
  38. // pTool->waitForExecution();
  39. // vDebug() << "ParallelSubTool [" << pTool->strInstanceName << "] waiting finished.";
  40. //}
  41. //// 否则,直接跳过执行
  42. //else
  43. //{
  44. vDebug() << "Ignore Tool[" + pTool->strInstanceName + "], reason: isParallelized.";
  45. return VPEnum::RETURN_VALUE::Abort;
  46. //}
  47. }
  48. // 如果本工具加入了For循环,则跳过执行
  49. else if (pTool->isForloopSubTool())
  50. {
  51. vDebug() << "Ignore Tool[" + pTool->strInstanceName + "], reason: isForlooped.";
  52. return VPEnum::RETURN_VALUE::Abort;
  53. }
  54. return VPEnum::RETURN_VALUE::Success;
  55. }
  56. /// <summary>
  57. /// 2022-5-1 工具的执行总调度
  58. /// </summary>
  59. /// <param name="pTool"></param>
  60. /// <returns></returns>
  61. VPEnum::RETURN_VALUE POU::ToolExecutionDispatcher(TOOL*& pTool, TOOL_RUN_MODE runMode)
  62. {
  63. VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None;
  64. // 执行预检查
  65. ret = this->ToolExecutionDispatcherPreCheck(pTool, runMode);
  66. if (ret != VPEnum::RETURN_VALUE::Success)
  67. {
  68. return ret;
  69. }
  70. // 正常流程
  71. // 设置Tool为Busy状态
  72. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Busy;
  73. // 执行标准工具
  74. if (pTool->isStandardTool())
  75. {
  76. ret = this->ToolExecuteStandard(pTool);
  77. }
  78. // 执行Goto工具
  79. else if (pTool->isGotoTool())
  80. {
  81. int nNextIndex = 0;
  82. // 执行Goto工具
  83. ret = this->ToolExecuteGoto(pTool, nNextIndex);
  84. // TODO:此处是否需要跳转到下一个工具继续执行
  85. if (ret == VPEnum::RETURN_VALUE::Goto)
  86. {
  87. TOOL* pNextTool = m_StandardTools[nNextIndex];
  88. ret = this->ToolExecuteStandard(pNextTool);
  89. }
  90. }
  91. // 执行并行工具
  92. else if (pTool->isParallelTool())
  93. {
  94. ret = this->ToolExecuteParallel(pTool);
  95. }
  96. // 执行ForLoop工具
  97. else if (pTool->isForloopTool())
  98. {
  99. ret = this->ToolExecuteForloop(pTool);
  100. }
  101. // 执行Wait工具
  102. else if (pTool->isWaitTool())
  103. {
  104. ret = this->ToolExecuteWait(pTool, runMode);
  105. }
  106. else
  107. {
  108. qDebug() << "[Error] POU::ToolExecute - Unknown tool type:" << (short)pTool->Type;
  109. ret = VPEnum::RETURN_VALUE::Error;
  110. }
  111. // 设置Tool为完成状态
  112. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done;
  113. return ret;
  114. }
  115. /// <summary>
  116. /// 2022-5-1 工具的执行总调度(Task中使用,关联执行序号)
  117. /// </summary>
  118. /// <param name="pTool"></param>
  119. /// <param name="index"></param>
  120. /// <returns></returns>
  121. VPEnum::RETURN_VALUE POU::ToolExecutionDispatcher(TOOL*& pTool, int& index, TOOL_RUN_MODE runMode)
  122. {
  123. VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None;
  124. // 执行预检查
  125. ret = this->ToolExecutionDispatcherPreCheck(pTool, runMode);
  126. if (ret != VPEnum::RETURN_VALUE::Success)
  127. {
  128. return ret;
  129. }
  130. // 设置Tool为Busy状态
  131. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Busy;
  132. // 如果是标准工具,正常执行
  133. if (pTool->isStandardTool())
  134. {
  135. ret = this->ToolExecuteStandard(pTool);
  136. index++;
  137. }
  138. // 如果是Goto工具,要做跳转
  139. else if (pTool->isGotoTool())
  140. {
  141. // 执行Goto
  142. ret = this->ToolExecuteGoto(pTool, index);
  143. // 如果执行过程中没有发生跳转,那么继续执行下一个工具
  144. if (ret != VPEnum::RETURN_VALUE::Goto)
  145. {
  146. index++;
  147. }
  148. }
  149. // 如果是并行工具,则并行执行
  150. else if (pTool->isParallelTool())
  151. {
  152. ret = this->ToolExecuteParallel(pTool);
  153. index++;
  154. }
  155. // 如果是For循环工具,则执行For循环
  156. else if (pTool->isForloopTool())
  157. {
  158. ret = this->ToolExecuteForloop(pTool);
  159. index++;
  160. }
  161. // 如果是Wait工具,则执行等待
  162. else if (pTool->isWaitTool())
  163. {
  164. ret = this->ToolExecuteWait(pTool, runMode);
  165. index++;
  166. }
  167. // 设置Tool为完成状态
  168. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done;
  169. return ret;
  170. }
  171. ///// <summary>
  172. ///// 执行当前工具
  173. ///// </summary>
  174. ///// <param name="pBlockItem"></param>
  175. //VPEnum::RETURN_VALUE POU::ToolExecuteStandard(WindowAppBlockStandardBase* pBlockItem)
  176. //{
  177. // // 重置所有工具执行状态
  178. // ResetToolExecCode();
  179. //
  180. // TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
  181. //
  182. // // 交给调度器执行
  183. // return this->ToolExecutionDispatcher(pActiveTool);
  184. //}
  185. /// <summary>
  186. /// 执行当前工具
  187. /// </summary>
  188. /// <param name="pActiveTool"></param>
  189. VPEnum::RETURN_VALUE POU::ToolExecuteStandard(TOOL* pActiveTool)
  190. {
  191. VPEnum::RETURN_VALUE nRet = VPEnum::RETURN_VALUE::None;
  192. if (pActiveTool == nullptr)
  193. {
  194. qDebug() << "[Error] [POU:" << m_strPouName << "] ToolExecuteStandard failed: pActiveTool is nullptr.";
  195. return VPEnum::RETURN_VALUE::Error;
  196. }
  197. // Execute前更新上连接口
  198. nRet = this->ToolPreExecute(pActiveTool);
  199. // TODO:此处是否需要处理更新上行接口的执行结果
  200. // 然后执行本工具的Execute
  201. if (pActiveTool->pDllPtr != nullptr)
  202. {
  203. nRet = pActiveTool->pDllPtr->Execute();
  204. }
  205. else
  206. {
  207. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pActiveTool->strInstanceName << "] executed finished.";
  208. }
  209. // 在窗体可见时候,才调用调试窗口。以便在后台运行的时候,提高运行速度
  210. if (this->parentScene()->parentFrame()->isVisible())
  211. {
  212. try
  213. {
  214. DebugData data = pActiveTool->pDllPtr->GetDebugData();
  215. this->parentScene()->parentFrame()->UpdataDebugData(data);
  216. }
  217. catch (...){ }
  218. }
  219. // 保存工具执行返回值
  220. pActiveTool->execParams.nRetValue = nRet;
  221. // 如果返回值不是成功的话,就需要加一个错误计数(Pou和Tool的都需要+1)
  222. if (nRet != VPEnum::RETURN_VALUE::Success)
  223. {
  224. pActiveTool->execParams.nErrorCount++;
  225. this->execParams.nErrorCount++;
  226. }
  227. // Execute后更新下连接口
  228. /*nRet =*/ this->ToolPostExecute(pActiveTool);
  229. //// 根据是否在Task中执行,输出不同的log
  230. //if (m_pParentTask == nullptr)
  231. //{
  232. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pActiveTool->strInstanceName
  233. << "][Index:" << pActiveTool->nIndex << "] executed finished.";
  234. //}
  235. // 执行完之后,重绘一下此工具,用于功能块的状态显示
  236. WindowAppBlockBase* pBlock = this->m_instNameToToolItems[pActiveTool->strInstanceName];
  237. pBlock->update();
  238. // 执行计数 +1
  239. pActiveTool->execParams.nExecCount++;
  240. return nRet;
  241. }
  242. /// <summary>
  243. /// Execute前更新上连接口
  244. /// </summary>
  245. VPEnum::RETURN_VALUE POU::ToolPreExecute(TOOL* pActiveTool)
  246. {
  247. VPEnum::RETURN_VALUE nRet = VPEnum::RETURN_VALUE::None;
  248. // qDebug() << "[POU] Execute tool start ------- " << pActiveTool->strInstanceName;
  249. // 先检查一下所有的输入接口
  250. for (_INTERFACE* pInf : pActiveTool->Interfaces)
  251. {
  252. // 2022-4-30,跳过Tool类型接口(尽管这种情况不会出现,但是以防万一还是加上)
  253. if (pInf->isToolInterface())
  254. {
  255. continue;
  256. }
  257. // 如果本接口有link连接的话,需要先到link那边去取值
  258. if (pInf->Direction == INF_DIRECTION::INF_DIR_IN
  259. && pInf->pUpLinkInterface != nullptr)
  260. {
  261. // 从工具Dll中更新值
  262. if (pInf->pUpLinkInterface->Type == INF_TYPE::INF_TYPE_STANDARD)
  263. {
  264. // 2022-8-26增加,由于标准接口的情况分为两种,一种是dll工具,还有一种是系统内置工具,所以这里要区分一下
  265. // 如果上联工具为标准工具,则从Dll中更新值(这里这里要用realParent,防止Port工具绑定的情况)
  266. if (pInf->pUpLinkInterface->realParent()->Type == TOOL_TYPE::TOOL_TYPE_STANDARD)
  267. {
  268. QString strValueString = updateInterfaceValue(pInf, UPDATE_VALUE_MODE::MODE_FROM_TOOL);
  269. if (!strValueString.isEmpty())
  270. {
  271. qDebug() << "[POU] updateInterfaceValue from up link dll[" << pInf->strFullName << "], Value:" << strValueString;
  272. }
  273. else
  274. {
  275. // return nRet;
  276. continue;
  277. }
  278. }
  279. // 2022-8-26 是否应该是内置工具,直接从接口中取值,和变量一样
  280. else
  281. {
  282. QString strValueString = updateInterfaceValue(pInf, UPDATE_VALUE_MODE::MODE_FROM_VARIABLE);
  283. if (!strValueString.isEmpty())
  284. {
  285. qDebug() << "[POU] updateInterfaceValue from up link internal[" << pInf->strFullName << "], Value:" << strValueString;
  286. }
  287. else
  288. {
  289. // return nRet;
  290. continue;
  291. }
  292. }
  293. }
  294. // 从变量中更新值
  295. else if (pInf->pUpLinkInterface->Type == INF_TYPE::INF_TYPE_VALUE)
  296. {
  297. // 判断下上联的端口(全局变量组或者局部变量组)是否存在
  298. TOOL* pGvl = pInf->pUpLinkInterface->bindedParent();
  299. // 如果查询到了对应的变量组
  300. if (pGvl != nullptr)
  301. {
  302. QString strValueString = updateInterfaceValue(pInf, UPDATE_VALUE_MODE::MODE_FROM_VARIABLE);
  303. if (!strValueString.isEmpty())
  304. {
  305. qDebug() << "[POU] updateInterfaceValue from up link variable[" << pInf->strFullName << "], Value:" << strValueString;
  306. }
  307. else
  308. {
  309. // return nRet;
  310. continue;
  311. }
  312. }
  313. // 没查询到对应的全局变量或局部变量
  314. else
  315. {
  316. // 把端口的状态设置为Error
  317. TOOL* pPort = pInf->pUpLinkInterface->parent();
  318. if (pPort != nullptr)
  319. {
  320. pPort->setPortError();
  321. }
  322. QString strErrorMsg = pInf->pUpLinkInterface->strName + " ----------->" +
  323. pActiveTool->strInstanceName + "." + pInf->strName;
  324. qWarning() << strErrorMsg << "Error";
  325. }
  326. }
  327. // 2022-3-25 增加一个错误处理(此处屏蔽,因为有Goto连接到Tool的时候,一定会走到这里)
  328. else
  329. {
  330. qWarning() << "[Warning] POU::ToolPreExecute - Ingore value update, invalid interface category:" << (short)pInf->pUpLinkInterface->Type;
  331. }
  332. }
  333. }
  334. // 加上前延时
  335. Utility::qSleep(pActiveTool->execParams.nPreDelay);
  336. return nRet;
  337. }
  338. /// <summary>
  339. /// Execute后更新下连接口
  340. /// MEMO:对于Tool的接口来说不需要更新下联接口,但是对于Value类型,是需要更新下联接口的
  341. /// </summary>
  342. VPEnum::RETURN_VALUE POU::ToolPostExecute(TOOL* pActiveTool)
  343. {
  344. VPEnum::RETURN_VALUE nRet = VPEnum::RETURN_VALUE::None;
  345. // 加上后延时
  346. Utility::qSleep(pActiveTool->execParams.nPostDelay);
  347. // qDebug() << "[POU] Execute tool - " << pActiveTool->strInstanceName << " Index - " << pActiveTool->nIndex;
  348. // LOG("[POU] Execute tool - {} , index - {}.", pActiveTool->strInstanceName.toStdString(), pActiveTool->nIndex);
  349. // 2021-11-9,添加要向UI同步的接口
  350. QList<_INTERFACE*> syncInfs;
  351. // 2021-11-14,添加要向界面表格同步的接口
  352. QList<VARIABLE*> syncValues;
  353. // 2021-12-12,添加要向复杂控件同步的接口(直接发向Runtime)
  354. // 复杂控件的同步机制就是直接从Pou中索引链接的数值变动直接向Runtime触发的
  355. QList<VARIABLE*> syncComplexIndexes;
  356. // 2021-5-29添加,execute完毕之后,如果有下联接口是Value类型的话(全局变量或局部变量)
  357. // 需要额外更新一下Value的值
  358. for (_INTERFACE* pInf : pActiveTool->Interfaces)
  359. {
  360. // 2022-4-30,跳过Top类型
  361. // REASON: 因为Top类型都是用来下联Tool的,不需要执行更新
  362. if (pInf->isToolEnd())
  363. {
  364. continue;
  365. }
  366. QVector<_INTERFACE*> pDownLinks = pInf->pDownLinkInterfaces;
  367. // 增加需要同步到Runtime的接口信息
  368. if (pInf->bDataLink)
  369. {
  370. syncInfs.push_back(pInf);
  371. }
  372. // 2021-12-15 如果是复杂控件索引,加入推送通知列表中
  373. if (pInf->bComplexLinkIndex)
  374. {
  375. syncComplexIndexes.push_back(pInf);
  376. }
  377. // 遍历所有的下联接口
  378. for (int i = 0; i < pDownLinks.size(); i++)
  379. {
  380. _INTERFACE* pDownInf = pDownLinks[i];
  381. // 只需要更新数值类型的输出接口
  382. if (pInf->Direction == INF_DIRECTION::INF_DIR_OUT
  383. && pDownInf->Type == INF_TYPE::INF_TYPE_VALUE)
  384. {
  385. // 判断下上联的端口(全局变量组或者局部变量组)是否存在
  386. TOOL* pGvl = pDownInf->bindedParent();
  387. if (pGvl != nullptr)
  388. {
  389. // 将值更新到下接接口中
  390. QString strValueString = updateInterfaceValue(pDownInf, UPDATE_VALUE_MODE::MODE_TO_VARIABLE);
  391. if (strValueString.isEmpty())
  392. {
  393. // return nRet;
  394. continue;
  395. }
  396. qDebug() << "[POU] updateInterfaceValue to down link value - " << pDownInf->strFullName;
  397. }
  398. else
  399. // 没查询到对应的全局变量或局部变量
  400. {
  401. // 把端口的状态设置为Error
  402. TOOL* pPort = pDownInf->parent();
  403. if (pPort != nullptr)
  404. {
  405. pPort->setPortError();
  406. }
  407. QString strErrorMsg =
  408. pActiveTool->strInstanceName + "." + pInf->strName +
  409. " ----------->" +
  410. pDownInf->strName;
  411. qWarning() << strErrorMsg << "Error";
  412. }
  413. // 添加需要刷新到变量界面表格的接口
  414. syncValues.push_back(pDownInf);
  415. // 添加需要刷新到界面的接口
  416. if (pDownInf->bDataLink)
  417. {
  418. syncInfs.push_back(pDownInf);
  419. }
  420. // 2021-12-15 如果是复杂控件索引,加入推送通知列表中
  421. if (pDownInf->bComplexLinkIndex)
  422. {
  423. syncComplexIndexes.push_back(pInf);
  424. }
  425. }
  426. }
  427. }
  428. // 2021-11-14 增加,一次性使用postEvent异步刷新所有变量界面表格
  429. if (syncValues.size() > 0)
  430. {
  431. syncValuesToTableUI(syncValues);
  432. }
  433. // 如果需要的话,则向UI同步(只有非硬件工具才触发execute后的更新动作)
  434. if (syncInfs.size() > 0 && !pActiveTool->isHardwareTool())
  435. {
  436. syncValuesToUi(syncInfs);
  437. }
  438. // 2021-12-15 进行复杂控件索引到Runtime的推送
  439. if (syncComplexIndexes.size() > 0)
  440. {
  441. syncComplexIndexesToRuntime(syncComplexIndexes);
  442. }
  443. return nRet;
  444. }
  445. /// <summary>
  446. /// 执行Goto工具(应该为内部工具专门设计一套数据结构,暂时先放在这里)
  447. /// </summary>
  448. /// <param name="pGoto"></param>
  449. /// <param name="index">goto的下一步跳转目标</param>
  450. VPEnum::RETURN_VALUE POU::ToolExecuteGoto(TOOL* pTool, int& index)
  451. {
  452. // 是否执行了跳转
  453. VPEnum::RETURN_VALUE nRet = VPEnum::RETURN_VALUE::None;
  454. // Execute前更新上连接口
  455. nRet = this->ToolPreExecute(pTool);
  456. // TODO:此处是否需要处理上联接口状态
  457. //// 如果返回值不是成功的话,就需要加一个错误计数(Pou和Tool的都需要+1)
  458. //if (nRet != VPEnum::RETURN_VALUE::Success)
  459. //{
  460. // pGoto->execParams.nErrorCount++;
  461. // this->execParams.nErrorCount++;
  462. //}
  463. // 然后开始执行Goto的内部逻辑
  464. // 如果这个Goto已经绑定了工具
  465. if (pTool->Interfaces[GOTO_OUTPUT_INDX]->isBinded())
  466. {
  467. // 获取输入接口的值
  468. bool bInput = false;
  469. if (pTool->Interfaces[GOTO_INPUT_INDX]->value.Ptr != nullptr)
  470. {
  471. bInput = pTool->Interfaces[GOTO_INPUT_INDX]->value.getValue<bool>();
  472. }
  473. // 然后根据取反位决定是否执行跳转
  474. WindowAppBlockGoto* pGotoBlock = qgraphicsitem_cast<WindowAppBlockGoto*>(m_instNameToToolItems[pTool->strInstanceName]);
  475. bool bNegation = pGotoBlock->m_bNegation;
  476. bool bJmp = false;
  477. // 是否取反
  478. bNegation ? bJmp = !bInput : bJmp = bInput;
  479. if (bJmp)
  480. {
  481. // 执行跳转
  482. // index = pGoto->Interfaces[1]->bindedParent()->nIndex;
  483. // 取出跳转的Tool
  484. QString strToolName = pTool->Interfaces[GOTO_OUTPUT_INDX]->pBindInterface->strName;
  485. TOOL* pGotoTool = this->GetToolByName(strToolName);
  486. if (pGotoTool != nullptr)
  487. {
  488. index = pGotoTool->nIndex;
  489. // 设置Goto工具状态
  490. pGotoTool->execParams.nRetValue = VPEnum::RETURN_VALUE::Goto;
  491. // Goto工具只有执行跳转,执行计数才会 +1
  492. pGotoTool->execParams.nExecCount++;
  493. //qDebug() << "[POU] Execute Goto tool - " << pGoto->strInstanceName << " Index[" << pGoto->nIndex
  494. // << "] Goto Index[" << index << "].";
  495. if (m_pParentTask == nullptr)
  496. {
  497. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pGotoTool->strInstanceName
  498. << "][Index:" << pGotoTool->nIndex << "] executed finished: GOTO Index[" << index << "].";
  499. }
  500. // 返回跳转标志
  501. return VPEnum::RETURN_VALUE::Goto;
  502. }
  503. }
  504. }
  505. // 不执行跳转
  506. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pTool->strInstanceName
  507. << "][Index:" << pTool->nIndex << "] executed finished: but not GOTO.";
  508. //// 根据是否在Task中执行,输出不同的log
  509. //if (m_pParentTask != nullptr)
  510. //{
  511. // qDebug() << "[TASK:" << m_pParentTask->strName << "][POU:" << m_strGroup << "][Tool:" << pGoto->strInstanceName << "] executed finished.";
  512. //}
  513. //else
  514. //{
  515. // qDebug() << "[TASK:null][POU:" << m_strGroup << "][Tool:" << pGoto->strInstanceName << "] executed finished.";
  516. //}
  517. // 设置Goto工具状态
  518. pTool->execParams.nRetValue = VPEnum::RETURN_VALUE::Success;
  519. return VPEnum::RETURN_VALUE::Success;;
  520. }
  521. /// <summary>
  522. /// 2022-4-30 执行Parallel工具
  523. /// </summary>
  524. /// <param name="pTool"></param>
  525. /// <returns></returns>
  526. VPEnum::RETURN_VALUE POU::ToolExecuteParallel(TOOL* pTool)
  527. {
  528. // 并行工具一定需要有ToolEnd接口
  529. Q_ASSERT(pTool->ToolInterfaces.size() >=0 );
  530. QString strLog;
  531. // QVector<TOOL*> runningTools;
  532. // 首先解析出本并行工具组中有几个并行子工具,并且逐一触发执行
  533. for (auto pDownInf : pTool->ToolInterfaces[INF_END]->pDownLinkInterfaces)
  534. {
  535. TOOL* pRunningTool = pDownInf->parent();
  536. if (pRunningTool == nullptr)
  537. {
  538. continue;
  539. }
  540. strLog += pRunningTool->strInstanceName + " ";
  541. // 启动线程执行此工具
  542. m_ParallelThreadPool.start( new _ParallelThread(this, pRunningTool) );
  543. //// 触发并行子工具执行
  544. //pRunningTool->activator.wakeAll();
  545. //runningTools.push_back(pRunningTool);
  546. }
  547. //qDebug() << "[POU:" << m_strPouName << "][Parallel:" << pTool->strInstanceName
  548. // << "] Run parallel tools [" << strLog << "] start.";
  549. //// 等待所有Tool执行完毕(所有工具都是Done的状态)
  550. //
  551. //bool bContinue = true;
  552. //while (bContinue)
  553. //{
  554. // bContinue = false;
  555. // for (int i = 0; i < runningTools.size(); i++)
  556. // {
  557. // if (runningTools[i]->execParams.nStatus == VPEnum::EXEC_STATUS::Busy)
  558. // {
  559. // bContinue = true;
  560. // Utility::qSleep(10);
  561. // break;
  562. // }
  563. // }
  564. //}
  565. //qDebug() << "[POU:" << m_strPouName << "][Parallel:" << pTool->strInstanceName
  566. // << "] Run parallel tools [" << strLog << "] finished.";
  567. qDebug() << "[POU:" << m_strPouName << "][Parallel:" << pTool->strInstanceName
  568. << "] Run parallel tools [" << strLog << "] start.";
  569. // 等待所有线程执行完毕
  570. m_ParallelThreadPool.waitForDone();
  571. qDebug() << "[POU:" << m_strPouName << "][Parallel:" << pTool->strInstanceName
  572. << "] Run parallel tools [" << strLog << "] finished.";
  573. return VPEnum::RETURN_VALUE::Success;
  574. }
  575. /// <summary>
  576. /// 针对TOOL的index,从小到大排序
  577. /// </summary>
  578. /// <param name="a"></param>
  579. /// <param name="b"></param>
  580. /// <returns></returns>
  581. bool sortLoopTool(TOOL*& a, TOOL*& b)
  582. {
  583. if (a->nIndex < b->nIndex)
  584. {
  585. return true;
  586. }
  587. else
  588. {
  589. return false;
  590. }
  591. }
  592. /// <summary>
  593. /// 2022-8-25 执行ForLoop工具
  594. /// </summary>
  595. /// <param name="pForloopTool"></param>
  596. /// <returns></returns>
  597. VPEnum::RETURN_VALUE POU::ToolExecuteForloop(TOOL* pTool)
  598. {
  599. // 执行返回值
  600. VPEnum::RETURN_VALUE nRet = VPEnum::RETURN_VALUE::None;
  601. // ForLoop工具的计数与其他工具不同,需要在ForLoop工具内部处理运行计数,统计For循环的真正执行次数
  602. // Execute前首先更新上连接口,获取执行的Size(此处也有可能是通过对话框设置的Size,所以没有上级连接)
  603. nRet = this->ToolPreExecute(pTool);
  604. // 如果没有取到上联接口的值,则跳过ForLoop的执行,因为没有Size
  605. if (pTool->Interfaces[0]->isValueNullptr())
  606. {
  607. // 跳过执行
  608. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pTool->strInstanceName
  609. << "][Index:" << pTool->nIndex << "] executed ignore: input size is <=0.";
  610. return VPEnum::RETURN_VALUE::Success;
  611. }
  612. // 然后开始执行Forloop的内部逻辑
  613. // 如果没有下联标准工具,直接跳过执行
  614. if (pTool->ToolInterfaces[INF_END]->pDownLinkInterfaces.size() <=0 )
  615. {
  616. // 跳过执行
  617. qDebug() << "[POU:" << m_strPouName << "][Tool:" << pTool->strInstanceName
  618. << "][Index:" << pTool->nIndex << "] executed ignore: invalid standard tool count in forloop.";
  619. return VPEnum::RETURN_VALUE::Success;
  620. }
  621. // 找到所有下联的工具,按照Index排序执行
  622. QVector<TOOL*> loopTools;
  623. for (auto& inf : pTool->ToolInterfaces[INF_END]->pDownLinkInterfaces)
  624. {
  625. if (inf->parent() != nullptr)
  626. {
  627. loopTools.push_back(inf->parent());
  628. }
  629. }
  630. // 按照Index排序(从小到大)
  631. qSort(loopTools.begin(), loopTools.end(), sortLoopTool);
  632. // 取出循环的Size(从Size输入接口中取)
  633. // 0号接口固定为ForLoop工具的Size输入值
  634. int nSize = pTool->Interfaces[0]->value.toInt();
  635. // 开始循环执行
  636. for (int i = 0; i < nSize; i++)
  637. {
  638. // 输出当前Index
  639. // 1号接口固定为ForLoop工具的Index输出值
  640. pTool->Interfaces[1]->value.setValue<int>(i);
  641. // 遍历所有For循环内部的工具,依次执行
  642. for (int toolIndex = 0; toolIndex < loopTools.size(); toolIndex++)
  643. {
  644. // 取出当前需要执行的工具
  645. TOOL* runningTool = loopTools[toolIndex];
  646. // 执行此工具
  647. this->ToolExecuteStandard(runningTool);
  648. qDebug() << "[ForLoop(" << pTool->strInstanceName << ") Index:" << i << "] | [POU:"
  649. << m_strPouName << "][Tool:" << runningTool->strInstanceName << "] executed finished.";
  650. }
  651. // 2022-8-28 ,执行次数 +1
  652. pTool->execParams.nExecCount++;
  653. }
  654. vDebug() << "[POU:" << m_strPouName << "][Forloop:" << pTool->strInstanceName << "] Round[" << nSize << "] finished.";
  655. // 设置ForLoop工具状态
  656. pTool->execParams.nRetValue = VPEnum::RETURN_VALUE::Success;
  657. return nRet;
  658. }
  659. /// <summary>
  660. /// 2022-9-3 执行Wait工具
  661. /// </summary>
  662. /// <param name="pTool"></param>
  663. /// <returns></returns>
  664. VPEnum::RETURN_VALUE POU::ToolExecuteWait(TOOL* pTool, TOOL_RUN_MODE runMode)
  665. {
  666. // WaitBlock指针,用于获取用户设定的功能块执行参数
  667. WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(m_instNameToToolItems[pTool->strInstanceName]);
  668. // 异常
  669. if (pWaitBlock == nullptr)
  670. {
  671. vDebug() << "[Error] pWaitBlock is nullptr.";
  672. return VPEnum::RETURN_VALUE::Error;
  673. }
  674. // 如果处于单步执行状态,需要看一下用户是否选择了单步执行跳过等待
  675. if (runMode == TOOL_RUN_MODE::SINGLE_STEP)
  676. {
  677. if (pWaitBlock->m_bSkipWait)
  678. {
  679. vDebug() << "[POU:" << m_strPouName << "][Wait:" << pTool->strInstanceName << "] ignore waiting, reason: m_bSkipWait = true.";
  680. return VPEnum::RETURN_VALUE::Abort;
  681. }
  682. }
  683. // 如果本Wait工具都没有注册触发事件,则跳过等待
  684. if (!g_pTaskManager->isToolTriggerable(pTool))
  685. {
  686. vDebug() << "[POU:" << m_strPouName << "][Wait:" << pTool->strInstanceName << "] ignore waiting, reason: no event trigger.";
  687. return VPEnum::RETURN_VALUE::Abort;
  688. }
  689. // 启动等待机制
  690. vDebug() << "[POU:" << m_strPouName << "][Wait:" << pTool->strInstanceName
  691. << "] start waiting for " << pWaitBlock->m_nTimeout << "ms .......";
  692. // 设置Tool为Wait状态
  693. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Wait;
  694. // 2022-9-26,为接口的等待时长计时
  695. QElapsedTimer waitTimer;
  696. waitTimer.start();
  697. // 直接开始等待工具事件触发
  698. pTool->waitForExecution(pWaitBlock->m_nTimeout);
  699. // 2022-9-26,然后将本轮等待时长输出到1号接口中
  700. int nWaitTime = waitTimer.elapsed();
  701. pTool->Interfaces[1]->value.setValue<int>(nWaitTime);
  702. // 等待结束,设置Tool为Busy状态
  703. pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Busy;
  704. vDebug() << "[POU:" << m_strPouName << "][Wait:" << pTool->strInstanceName
  705. << "] waiting finished, elapse:" << nWaitTime;
  706. return VPEnum::RETURN_VALUE::Success;
  707. }
  708. /// <summary>
  709. /// BreakPoint
  710. /// </summary>
  711. /// <param name="pBlockItem"></param>
  712. void POU::ToolBreakPoint(WindowAppBlockStandardBase* pBlockItem)
  713. {
  714. TOOL* pTool = m_itemToTools.value(pBlockItem);
  715. if (pTool)
  716. {
  717. pTool->bEnableBreakPoint = !pTool->bEnableBreakPoint;
  718. if (pTool->bEnableBreakPoint)
  719. {
  720. qDebug() << "Enable Tool" << pTool->strName << "Enable BreakPoint ";
  721. }
  722. }
  723. }
  724. /// <summary>
  725. /// 从当前位置执行
  726. /// </summary>
  727. /// <param name="pBlockItem"></param>
  728. void POU::ToolExecuteSub(WindowAppBlockStandardBase* pBlockItem)
  729. {
  730. int nExecuteIndex = m_itemToTools.value(pBlockItem)->nIndex;
  731. // 从当前序号开始执行
  732. this->ToolExecuteAll(nExecuteIndex);
  733. }
  734. /// <summary>
  735. /// 全部按顺序执行
  736. /// </summary>
  737. void POU::ToolExecuteAll(const int startIndex)
  738. {
  739. qDebug() << "[POU:" << this->pouName() << "] ExecuteAll Start...";
  740. VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None;
  741. for (int index = startIndex; index < m_StandardTools.size(); )
  742. {
  743. TOOL* pRunningTool = m_StandardTools[index];
  744. //// 设置为busy状态
  745. //pRunningTool->execParams.nStatus = VPEnum::EXEC_STATUS::Busy;
  746. // 交给Pou执行调度器执行
  747. ret = this->ToolExecutionDispatcher(pRunningTool, index, TOOL_RUN_MODE::SEQUENTIAL);
  748. //// 设置为完成状态
  749. //pRunningTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done;
  750. }
  751. qDebug() << "[POU:" << this->pouName() << "] ExecuteAll Finish.";
  752. }
  753. /// <summary>
  754. /// 单步执行
  755. /// </summary>
  756. void POU::ToolExecuteSingleStep()
  757. {
  758. int index = m_nExecuteIndex;
  759. VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None;
  760. if ((index >= 0) && (index < m_StandardTools.size()))
  761. {
  762. // 将前一个执行完毕的工具状态设置为Done
  763. if ((index == 0))
  764. {
  765. int nIndex = m_StandardTools.size() - 1;
  766. TOOL* pRunningTool = m_StandardTools[nIndex];
  767. pRunningTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done;
  768. }
  769. else
  770. {
  771. int nIndex = index - 1;
  772. TOOL* pRunningTool = m_StandardTools[nIndex];
  773. pRunningTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done;
  774. }
  775. TOOL* pRunningTool = m_StandardTools[index];
  776. // 2022-8-28,通过Dispatcher统一调度执行(以单步执行模式)
  777. ret = this->ToolExecutionDispatcher(pRunningTool, index, TOOL_RUN_MODE::SINGLE_STEP);
  778. }
  779. // 执行指针返回
  780. m_nExecuteIndex++;
  781. if (m_StandardTools.size() <= m_nExecuteIndex)
  782. {
  783. m_nExecuteIndex = 0;
  784. }
  785. }
  786. /// <summary>
  787. /// 根据不同的传值情况从dll中取值
  788. /// </summary>
  789. /// <typeparam name="T"></typeparam>
  790. /// <param name="tValue"></param>
  791. /// <param name="pInf"></param>
  792. /// <param name="mode"></param>
  793. template<typename T>
  794. void POU::MoveValue(T& tValue, _INTERFACE* pInf, UPDATE_VALUE_MODE mode)
  795. {
  796. // 被标记为废弃的端口,不参与数据链接
  797. if (pInf->pUpLinkInterface->Discard != INF_DISCARD::INF_DEFAULT
  798. || pInf->Discard != INF_DISCARD::INF_DEFAULT
  799. )
  800. {
  801. qWarning() << "[LinkError]" <<
  802. m_strPouName << "." <<
  803. pInf->pUpLinkInterface->strFullName << " to " <<
  804. pInf->strFullName <<
  805. "Error Interface Is Discard.";
  806. return;
  807. }
  808. if (mode == UPDATE_VALUE_MODE::MODE_FROM_TOOL)
  809. {
  810. if (pInf->value.passMode == VALUE_PASS_MODE::PASS_BY_VALUE)
  811. {
  812. this->MoveValueByConverter(tValue, pInf->pUpLinkInterface, pInf);
  813. }
  814. else
  815. {
  816. T& value = GetDllInfValue<T>(pInf->pUpLinkInterface);
  817. SetDllInfValue(value, pInf);
  818. tValue = value;
  819. }
  820. }
  821. else if (mode == UPDATE_VALUE_MODE::MODE_FROM_VARIABLE)
  822. {
  823. tValue = pInf->pUpLinkInterface->getValue<T>();
  824. SetDllInfValue(tValue, pInf);
  825. }
  826. else if (mode == UPDATE_VALUE_MODE::MODE_TO_VARIABLE)
  827. {
  828. tValue = GetDllInfValue<T>(pInf->pUpLinkInterface);
  829. pInf->setValue(tValue, VALUE_PASS_MODE::PASS_BY_VALUE);
  830. }
  831. }
  832. /// <summary>
  833. /// 2021-8-24 将基础数据类型转换后,再执行操作
  834. /// </summary>
  835. /// <param name="pSrcInf"></param>
  836. /// <param name="pDstInf"></param>
  837. template<typename T>
  838. void POU::MoveValueByConverter(T& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  839. {
  840. // 走到这个函数里的,应该都是两种类型相同的接口,那么直接计算即可
  841. tValue = GetDllInfValue<T>(pSrcInf);
  842. SetDllInfValue(tValue, pDstInf);
  843. //// 异常,不应该执行到这里
  844. //else
  845. //{
  846. // qWarning() << "[POU Execute] MoveValueByConverter(), but unknown value type.";
  847. //}
  848. }
  849. /// <summary>
  850. /// 模板特例化 - 目标类型是QString时(为了实现自动接口数值类型转换)
  851. /// </summary>
  852. /// <param name="tValue"></param>
  853. /// <param name="pSrcInf"></param>
  854. /// <param name="pDstInf"></param>
  855. void POU::MoveValueByConverter(QString& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  856. {
  857. VALUE_TYPE srcType = pSrcInf->value.type;
  858. if (srcType == VALUE_TYPE::Type_Int)
  859. {
  860. int nValue = GetDllInfValue<int>(pSrcInf);
  861. tValue = QString::number(nValue);
  862. }
  863. // float
  864. else if (srcType == VALUE_TYPE::Type_Float)
  865. {
  866. float fValue = GetDllInfValue<float>(pSrcInf);
  867. tValue = QString("%1").arg(fValue);
  868. }
  869. // double
  870. else if (srcType == VALUE_TYPE::Type_Double)
  871. {
  872. double dValue = GetDllInfValue<double>(pSrcInf);
  873. tValue = QString("%1").arg(dValue);
  874. }
  875. // bool
  876. else if (srcType == VALUE_TYPE::Type_Bool)
  877. {
  878. bool bValue = GetDllInfValue<bool>(pSrcInf);
  879. tValue = QString("%1").arg(bValue);
  880. }
  881. else
  882. {
  883. tValue = GetDllInfValue<QString>(pSrcInf);
  884. }
  885. SetDllInfValue<QString>(tValue, pDstInf);
  886. }
  887. /// <summary>
  888. /// 模板特例化 - 目标类型是int时(为了实现自动接口数值类型转换)
  889. /// </summary>
  890. /// <param name="tValue"></param>
  891. /// <param name="pSrcInf"></param>
  892. /// <param name="pDstInf"></param>
  893. void POU::MoveValueByConverter(int& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  894. {
  895. VALUE_TYPE srcType = pSrcInf->value.type;
  896. // QString
  897. if (srcType == VALUE_TYPE::Type_String)
  898. {
  899. QString strValue = GetDllInfValue<QString>(pSrcInf);
  900. tValue = strValue.toInt();
  901. }
  902. // float
  903. else if (srcType == VALUE_TYPE::Type_Float)
  904. {
  905. float fValue = GetDllInfValue<float>(pSrcInf);
  906. tValue = static_cast<int>(fValue);
  907. }
  908. // double
  909. else if (srcType == VALUE_TYPE::Type_Double)
  910. {
  911. double dValue = GetDllInfValue<double>(pSrcInf);
  912. tValue = static_cast<int>(dValue);
  913. }
  914. // bool
  915. else if (srcType == VALUE_TYPE::Type_Bool)
  916. {
  917. bool bValue = GetDllInfValue<bool>(pSrcInf);
  918. tValue = static_cast<int>(bValue);
  919. }
  920. else
  921. {
  922. tValue = GetDllInfValue<int>(pSrcInf);
  923. }
  924. SetDllInfValue<int>(tValue, pDstInf);
  925. }
  926. /// <summary>
  927. /// 模板特例化 - 目标类型是float时(为了实现自动接口数值类型转换)
  928. /// </summary>
  929. /// <param name="tValue"></param>
  930. /// <param name="pSrcInf"></param>
  931. /// <param name="pDstInf"></param>
  932. void POU::MoveValueByConverter(float& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  933. {
  934. VALUE_TYPE srcType = pSrcInf->value.type;
  935. // QString
  936. if (srcType == VALUE_TYPE::Type_String)
  937. {
  938. QString strValue = GetDllInfValue<QString>(pSrcInf);
  939. tValue = strValue.toFloat();
  940. }
  941. // int
  942. else if (srcType == VALUE_TYPE::Type_Int)
  943. {
  944. int nValue = GetDllInfValue<int>(pSrcInf);
  945. tValue = static_cast<float>(nValue);
  946. }
  947. // double
  948. else if (srcType == VALUE_TYPE::Type_Double)
  949. {
  950. double dValue = GetDllInfValue<double>(pSrcInf);
  951. tValue = static_cast<float>(dValue);
  952. }
  953. // bool
  954. else if (srcType == VALUE_TYPE::Type_Bool)
  955. {
  956. bool bValue = GetDllInfValue<bool>(pSrcInf);
  957. tValue = static_cast<float>(bValue);
  958. }
  959. else
  960. {
  961. tValue = GetDllInfValue<float>(pSrcInf);
  962. }
  963. SetDllInfValue<float>(tValue, pDstInf);
  964. }
  965. /// <summary>
  966. /// 模板特例化 - 目标类型是double时(为了实现自动接口数值类型转换)
  967. /// </summary>
  968. /// <param name="tValue"></param>
  969. /// <param name="pSrcInf"></param>
  970. /// <param name="pDstInf"></param>
  971. void POU::MoveValueByConverter(double& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  972. {
  973. VALUE_TYPE srcType = pSrcInf->value.type;
  974. // QString
  975. if (srcType == VALUE_TYPE::Type_String)
  976. {
  977. QString strValue = GetDllInfValue<QString>(pSrcInf);
  978. tValue = strValue.toDouble();
  979. }
  980. // int
  981. else if (srcType == VALUE_TYPE::Type_Int)
  982. {
  983. int nValue = GetDllInfValue<int>(pSrcInf);
  984. tValue = static_cast<double>(nValue);
  985. }
  986. // float
  987. else if (srcType == VALUE_TYPE::Type_Float)
  988. {
  989. float fValue = GetDllInfValue<float>(pSrcInf);
  990. tValue = static_cast<double>(fValue);
  991. }
  992. // bool
  993. else if (srcType == VALUE_TYPE::Type_Bool)
  994. {
  995. bool bValue = GetDllInfValue<bool>(pSrcInf);
  996. tValue = static_cast<double>(bValue);
  997. }
  998. else
  999. {
  1000. tValue = GetDllInfValue<double>(pSrcInf);
  1001. }
  1002. SetDllInfValue<double>(tValue, pDstInf);
  1003. }
  1004. /// <summary>
  1005. /// 模板特例化 - 目标类型是bool时(为了实现自动接口数值类型转换)
  1006. /// </summary>
  1007. /// <param name="tValue"></param>
  1008. /// <param name="pSrcInf"></param>
  1009. /// <param name="pDstInf"></param>
  1010. void POU::MoveValueByConverter(bool& tValue, _INTERFACE* pSrcInf, _INTERFACE* pDstInf)
  1011. {
  1012. VALUE_TYPE srcType = pSrcInf->value.type;
  1013. // QString
  1014. if (srcType == VALUE_TYPE::Type_String)
  1015. {
  1016. QString strValue = GetDllInfValue<QString>(pSrcInf);
  1017. if (strValue == STRING_TRUE || strValue == "1")
  1018. {
  1019. tValue = true;
  1020. }
  1021. else
  1022. {
  1023. tValue = false;
  1024. }
  1025. }
  1026. // int
  1027. else if (srcType == VALUE_TYPE::Type_Int)
  1028. {
  1029. int nValue = GetDllInfValue<int>(pSrcInf);
  1030. tValue = static_cast<bool>(nValue);
  1031. }
  1032. // float
  1033. else if (srcType == VALUE_TYPE::Type_Double)
  1034. {
  1035. double dValue = GetDllInfValue<float>(pSrcInf);
  1036. tValue = static_cast<bool>(dValue);
  1037. }
  1038. // double
  1039. else if (srcType == VALUE_TYPE::Type_Double)
  1040. {
  1041. double dValue = GetDllInfValue<double>(pSrcInf);
  1042. tValue = static_cast<bool>(dValue);
  1043. }
  1044. else
  1045. {
  1046. tValue = GetDllInfValue<bool>(pSrcInf);
  1047. }
  1048. SetDllInfValue<bool>(tValue, pDstInf);
  1049. }
  1050. /// <summary>
  1051. /// 2021-11-9 向UI同步接口数值
  1052. /// </summary>
  1053. /// <param name="pInf"></param>
  1054. void POU::syncValuesToUi(QList<_INTERFACE*> pInfs)
  1055. {
  1056. SyncValueEvent* valueEvent = new SyncValueEvent();
  1057. // 携带需要同步的多个接口
  1058. valueEvent->setSyncValues(pInfs);
  1059. // post数值同步消息,post内部会自动释放event的指针,无需手工释放
  1060. QCoreApplication::postEvent((QObject*)g_pUiManager, valueEvent);
  1061. }
  1062. /// <summary>
  1063. /// 2021-11-14 向变量表界面同步数值
  1064. /// </summary>
  1065. /// <param name="pInfs"></param>
  1066. void POU::syncValuesToTableUI(QList<_INTERFACE*> pInfs)
  1067. {
  1068. SyncValueEvent* valueEvent = new SyncValueEvent();
  1069. // 携带需要同步的多个接口
  1070. valueEvent->setSyncValues(pInfs);
  1071. // post数值同步消息,post内部会自动释放event的指针,无需手工释放
  1072. QCoreApplication::postEvent((QObject*)g_pGvlManager, valueEvent);
  1073. }
  1074. /// <summary>
  1075. /// 2021-12-15 向Runtime推送索引数值的变动
  1076. /// </summary>
  1077. /// <param name="pInfs"></param>
  1078. void POU::syncComplexIndexesToRuntime(QList<VARIABLE*> pIndexes)
  1079. {
  1080. SyncValueEvent* valueEvent = new SyncValueEvent();
  1081. // 携带需要同步的多个接口
  1082. valueEvent->setSyncValues(pIndexes);
  1083. // post数值同步消息,post内部会自动释放event的指针,无需手工释放
  1084. QCoreApplication::postEvent((QObject*)g_pRuntime, valueEvent);
  1085. }
  1086. /// <summary>
  1087. /// 更新接口的值(根据不同的模式)
  1088. /// </summary>
  1089. /// <param name="pInf"></param>
  1090. /// <param name="mode"></param>
  1091. QString POU::updateInterfaceValue(_INTERFACE* pInf, UPDATE_VALUE_MODE mode)
  1092. {
  1093. // 2021-6-5 增加, 防止变量中的变量被删除的情况,首先检查值是否为空
  1094. //if (mode == UPDATE_VALUE_MODE::MODE_FROM_VARIABLE)
  1095. //{
  1096. // if (pInf->pUpLinkInterface->value.Ptr == nullptr)
  1097. // {
  1098. // Utility::VPCriticalMessageBox("Can't update value from " + pInf->pUpLinkInterface->strFullName + ", Reason: value is invalid.");
  1099. // return false;
  1100. // }
  1101. //}
  1102. // 被标记为废弃的端口,不参与数据链接
  1103. if (pInf == nullptr || pInf->Discard != INF_DISCARD::INF_DEFAULT)
  1104. {
  1105. return "Interface Error";
  1106. }
  1107. // 根据不同类型分别进行操作
  1108. VALUE_TYPE type = pInf->value.type;
  1109. switch (type)
  1110. {
  1111. case VALUE_TYPE::Type_Bool:
  1112. {
  1113. bool value = false;
  1114. MoveValue<bool>(value, pInf, mode);
  1115. pInf->valueString = QString(value);
  1116. }
  1117. break;
  1118. case VALUE_TYPE::Type_Int:
  1119. {
  1120. int value = 0;
  1121. MoveValue<int>(value, pInf, mode);
  1122. // 2021-11-9,保存接口数值
  1123. pInf->valueString = QString::number(value);
  1124. }
  1125. break;
  1126. case VALUE_TYPE::Type_Float:
  1127. {
  1128. float value = 0;
  1129. MoveValue<float>(value, pInf, mode);
  1130. pInf->valueString = QString("%1").arg(value);
  1131. }
  1132. break;
  1133. case VALUE_TYPE::Type_Double:
  1134. {
  1135. double value = 0.0;
  1136. MoveValue<double>(value, pInf, mode);
  1137. pInf->valueString = QString("%1").arg(value);
  1138. }
  1139. break;
  1140. //case VALUE_TYPE::Type_CharP:
  1141. //{
  1142. // char* value = nullptr;
  1143. // MoveValue<char*>(value, pInf, mode);
  1144. // return QString("%1").arg(value);
  1145. //}
  1146. //break;
  1147. case VALUE_TYPE::Type_StdString:
  1148. {
  1149. std::string value = "";
  1150. MoveValue<std::string>(value, pInf, mode);
  1151. pInf->valueString = QString("%1").arg(value.c_str());
  1152. }
  1153. break;
  1154. case VALUE_TYPE::Type_String:
  1155. {
  1156. QString value = "";
  1157. MoveValue<QString>(value, pInf, mode);
  1158. pInf->valueString = value;
  1159. }
  1160. break;
  1161. case VALUE_TYPE::Type_QImage:
  1162. {
  1163. QImage value;
  1164. MoveValue<QImage>(value, pInf, mode);
  1165. //pInf->valueString = QString("%1 - %1").arg(value.size().width()).arg(value.size().height());
  1166. pInf->valueString = QString("QImage");
  1167. }
  1168. break;
  1169. case VALUE_TYPE::Type_Mat:
  1170. {
  1171. Mat value;
  1172. MoveValue<Mat>(value, pInf, mode);
  1173. //pInf->valueString = QString("%1 - %1").arg(value.size().width()).arg(value.size().height());
  1174. pInf->valueString = QString("Mat");
  1175. }
  1176. break;
  1177. case VALUE_TYPE::Type_HTuple:
  1178. {
  1179. HTuple value;
  1180. MoveValue<HTuple>(value, pInf, mode);
  1181. pInf->valueString = QString("HTuple");
  1182. }
  1183. break;
  1184. case VALUE_TYPE::Type_HObject:
  1185. {
  1186. HObject value;
  1187. MoveValue<HObject>(value, pInf, mode);
  1188. pInf->valueString = QString("HObject");
  1189. }
  1190. break;
  1191. case VALUE_TYPE::Type_HImage:
  1192. {
  1193. HImage value;
  1194. MoveValue<HImage>(value, pInf, mode);
  1195. pInf->valueString = QString("HImage");
  1196. }
  1197. break;
  1198. case VALUE_TYPE::Type_ST_Pos:
  1199. {
  1200. ST_POS value;
  1201. MoveValue<ST_POS>(value, pInf, mode);
  1202. pInf->valueString = QString("ST Pose");
  1203. }
  1204. break;
  1205. case VALUE_TYPE::Type_ST_HomMat2D:
  1206. {
  1207. HHomMat2D value;
  1208. MoveValue<HHomMat2D>(value, pInf, mode);
  1209. pInf->valueString = QString("HHomMat2D");
  1210. }
  1211. break;
  1212. case VALUE_TYPE::Type_ST_Point:
  1213. {
  1214. }
  1215. break;
  1216. case VALUE_TYPE::Type_ST_Line:
  1217. {
  1218. }
  1219. break;
  1220. case VALUE_TYPE::Type_ST_Circle:
  1221. {
  1222. }
  1223. break;
  1224. case VALUE_TYPE::Type_ST_Disp:
  1225. {
  1226. }
  1227. break;
  1228. case VALUE_TYPE::Type_ST_Window:
  1229. {
  1230. }
  1231. break;
  1232. case VALUE_TYPE::Type_ST_Ncc_Modle:
  1233. {
  1234. }
  1235. break;
  1236. case VALUE_TYPE::Type_ST_Shape_Modle:
  1237. {
  1238. }
  1239. break;
  1240. case VALUE_TYPE::Type_ST_Calibration:
  1241. {
  1242. }
  1243. break;
  1244. case VALUE_TYPE::Type_ST_CamParam_PoseCalib:
  1245. {
  1246. }
  1247. break;
  1248. case VALUE_TYPE::Type_pIBaseCamera:
  1249. {
  1250. IBaseCamera* value= nullptr;
  1251. MoveValue<IBaseCamera*>(value, pInf, mode);
  1252. if (value != nullptr)
  1253. {
  1254. pInf->valueString = QString("%1").arg(value->serial());
  1255. }
  1256. else
  1257. {
  1258. pInf->valueString = "null";
  1259. }
  1260. }
  1261. break;
  1262. case VALUE_TYPE::Type_pIpImage:
  1263. {
  1264. }
  1265. break;
  1266. case VALUE_TYPE::Type_pISocket:
  1267. {
  1268. }
  1269. break;
  1270. case VALUE_TYPE::Type_pArrayIn:
  1271. {
  1272. }
  1273. break;
  1274. case VALUE_TYPE::Type_pArrayOut:
  1275. {
  1276. }
  1277. break;
  1278. case VALUE_TYPE::Type_pArrayRobotPos:
  1279. {
  1280. }
  1281. break;
  1282. default:
  1283. qWarning() << "[POU][LINK][ERROR]: updateInterfaceValue - Unknown value type: " << (short)type;
  1284. return "";
  1285. pInf->valueString.clear();
  1286. }
  1287. return pInf->valueString;
  1288. // return "";
  1289. }
  1290. /// <summary>
  1291. /// 重置所有工具执行状态
  1292. /// </summary>
  1293. void POU::ResetToolExecCode()
  1294. {
  1295. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  1296. while (iter != m_itemToTools.end())
  1297. {
  1298. // 返回值
  1299. iter.value()->execParams.nRetValue = VPEnum::RETURN_VALUE::None;
  1300. // 状态
  1301. iter.value()->execParams.nStatus = VPEnum::EXEC_STATUS::StandBy;
  1302. iter++;
  1303. }
  1304. }
  1305. /// <summary>
  1306. /// 从Dll获取接口的值
  1307. /// </summary>
  1308. /// <typeparam name="T"></typeparam>
  1309. /// <param name="pInf"></param>
  1310. /// <returns></returns>
  1311. template<typename T>
  1312. T& POU::GetDllInfValue(_INTERFACE* pInf)
  1313. {
  1314. // DllTool* pDllTool = pInf->pParentTool->pDllPtr;
  1315. // 2022-3-23 根据真实的Parent获取对应的Dll(处理Port绑定的情况)
  1316. DllTool* pDllTool = pInf->realParent()->pDllPtr;
  1317. return pDllTool->Value<T>(pInf->nIndex);
  1318. }
  1319. /// <summary>
  1320. /// 设置Dll中接口的值
  1321. /// </summary>
  1322. /// <typeparam name="T"></typeparam>
  1323. /// <param name="tValue"></param>
  1324. /// <param name="pInf"></param>
  1325. template<typename T>
  1326. void POU::SetDllInfValue(T& tValue, _INTERFACE* pInf)
  1327. {
  1328. DllTool* pDllTool = pInf->realParent()->pDllPtr;
  1329. if (pDllTool != nullptr)
  1330. {
  1331. if (pInf->value.passMode == VALUE_PASS_MODE::PASS_BY_VALUE)
  1332. {
  1333. pDllTool->UpdateValue<T>(pInf->nIndex, tValue);
  1334. }
  1335. else
  1336. {
  1337. pDllTool->UpdateValue<T>(pInf->nIndex, tValue, VALUE_PASS_MODE::PASS_BY_ADDRESS);
  1338. }
  1339. }
  1340. else
  1341. {
  1342. pInf->setValue(tValue, VALUE_PASS_MODE::PASS_BY_VALUE);
  1343. }
  1344. }
  1345. /// <summary>
  1346. /// 2022-9-25,查询WaitTool的等待Value(用于在TaskManager触发WaitTool执行的时候进行判断)
  1347. /// </summary>
  1348. /// <param name="pTool"></param>
  1349. /// <returns></returns>
  1350. VALUE* POU::getWaitToolValue(TOOL* pTool)
  1351. {
  1352. WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(m_instNameToToolItems[pTool->strInstanceName]);
  1353. return &pWaitBlock->m_WaitValue;
  1354. }
  1355. //============================================================
  1356. //
  1357. // Task 线程
  1358. //
  1359. //============================================================
  1360. /// <summary>
  1361. /// 线程函数
  1362. /// </summary>
  1363. void _ParallelThread::run()
  1364. {
  1365. // 调用函数执行任务
  1366. this->m_pPou->ToolExecutionDispatcher(m_pParallelSubTool, TOOL_RUN_MODE::IN_PARALLEL);
  1367. }
  1368. ///// <summary>
  1369. ///// 线程函数
  1370. ///// </summary>
  1371. //void _ParallelThread::run()
  1372. //{
  1373. // VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None;
  1374. //
  1375. // // 循环执行任务,直到工具退出为止
  1376. // while (ret != VPEnum::RETURN_VALUE::Abort)
  1377. // {
  1378. // // 调用函数执行任务
  1379. // this->m_pPou->ToolExecutionDispatcher(m_pParallelSubTool, TOOL_RUN_MODE::IN_PARALLEL);
  1380. // }
  1381. //
  1382. // vDebug() << " _ParallelThread of SubTool[" << m_pParallelSubTool->strInstanceName << "] exit.";
  1383. //}
  1384. //
  1385. //
  1386. ///// <summary>
  1387. ///// 将本工具加入到并行子工具的预启动中
  1388. ///// </summary>
  1389. ///// <param name="pTool"></param>
  1390. //void POU::addParallelSubTool(TOOL* pTool)
  1391. //{
  1392. // // 并行子工具在刚链接的时候,就直接启动线程,但是处于等待状态不执行
  1393. // m_ParallelThreadPool.start(new _ParallelThread(this, pTool));
  1394. //
  1395. // vDebug() << "ParallelSubTool[" << pTool->strInstanceName << "] thread start...";
  1396. //}
  1397. //
  1398. //
  1399. ///// <summary>
  1400. ///// 移除一个并行子工具
  1401. ///// </summary>
  1402. ///// <param name="pTool"></param>
  1403. //void POU::removeParallelSubTool(TOOL* pTool)
  1404. //{
  1405. // Q_UNUSED(pTool);
  1406. //}