PLCMonitor.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. #include "PLCMonitor.h"
  2. #include <unistd.h>
  3. #include "../common.h"
  4. namespace modbus
  5. {
  6. #ifndef WIN32
  7. #define Sleep(T) usleep((T)*1000)
  8. #endif
  9. const double CPLCMonitor::PLC_LASER_TIMEOUT_READY = 1.0; //完成信号到心跳延时
  10. const double CPLCMonitor::PLC_LASER_TIMEOUT_PINGPANG = 0.1;
  11. const double CPLCMonitor::PLC_LASER_TIMEOUT_START = 0.3;
  12. const double CPLCMonitor::PLC_LASER_TIMEOUT_MAXMEASURE = 6.0;
  13. CPLCMonitor::CPLCMonitor(void* pOwnerObject)
  14. :_monitoring(false)
  15. , _heartbeat_write_clock(clock())
  16. , m_callback(0)
  17. ,m_pointer(0)
  18. ,m_PlcDataCallback(0)
  19. ,m_thread_read(0)
  20. {
  21. memset(&_value, 0, sizeof(_value));
  22. }
  23. CPLCMonitor::~CPLCMonitor()
  24. {
  25. _monitoring = false;
  26. if (m_thread_read)
  27. {
  28. if(m_thread_read->joinable())
  29. m_thread_read->join();
  30. m_thread_read = 0;
  31. }
  32. }
  33. int CPLCMonitor::connect(const char *ip, int port, int slave_id)
  34. {
  35. cs_pcl.lock();
  36. if (-1 == dev.initialize(ip, port, slave_id))
  37. {
  38. cs_pcl.unlock();
  39. return -1;
  40. }
  41. cs_pcl.unlock();
  42. _monitoring = true;
  43. if (FALSE == Start())
  44. {
  45. dev.deinitialize();
  46. return -1;
  47. }
  48. m_thread_read = new std::thread(thread_monitor, this);
  49. m_strIP = ip;
  50. m_port = port;
  51. m_slave_id = slave_id;
  52. return 0;
  53. }
  54. void CPLCMonitor::set_callback(CommandCallback func, PLCMonitorCallback monitorCallback,void* pointer)
  55. {
  56. m_callback = func;
  57. m_PlcDataCallback=monitorCallback;
  58. m_pointer = pointer;
  59. }
  60. int CPLCMonitor::reconnect()
  61. {
  62. cs_pcl.lock();
  63. if (-1 == dev.initialize(m_strIP.c_str(), m_port, m_slave_id))
  64. {
  65. cs_pcl.unlock();
  66. return -1;
  67. }
  68. cs_pcl.unlock();
  69. return 0;
  70. }
  71. void CPLCMonitor::disconnect()
  72. {
  73. _monitoring = false;
  74. Join(1000);
  75. cs_pcl.lock();
  76. dev.deinitialize();
  77. cs_pcl.unlock();
  78. }
  79. int CPLCMonitor::read_registers(int addr, int nb, uint16_t *dest)
  80. {
  81. cs_pcl.lock();
  82. int rc = dev.read_registers(addr, nb, dest);
  83. cs_pcl.unlock();
  84. if (0 != rc)
  85. {
  86. reconnect();//端开,重连
  87. }
  88. return rc;
  89. }
  90. int CPLCMonitor::write_registers(int addr, int nb, uint16_t *dest)
  91. {
  92. cs_pcl.lock();
  93. int rc = dev.write_registers(addr, nb, dest);
  94. cs_pcl.unlock();
  95. return rc;
  96. }
  97. int CPLCMonitor::read_register(int addr, uint16_t *dest)
  98. {
  99. cs_pcl.lock();
  100. int rc = dev.read_register(addr, dest);
  101. cs_pcl.unlock();
  102. return rc;
  103. }
  104. int CPLCMonitor::write_register(int addr, uint16_t *dest)
  105. {
  106. cs_pcl.lock();
  107. int rc = dev.write_register(addr, dest);
  108. cs_pcl.unlock();
  109. return rc;
  110. }
  111. int CPLCMonitor::clear_laserstatus_register(uint16_t value)
  112. {
  113. cs_pcl.lock();
  114. int rc = dev.write_register(REG_WHISKBOOMLASER_STATUS, &value);
  115. cs_pcl.unlock();
  116. _heartbeat_write_clock = clock();
  117. return rc;
  118. }
  119. int CPLCMonitor::write_laserstatus_register(uint16_t value)
  120. {
  121. uint16_t dest = 0xff;
  122. cs_pcl.lock();
  123. int rc = dev.read_register(REG_WHISKBOOMLASER_STATUS, &dest);
  124. if (PLC_LASER_ERROR != dest)
  125. {
  126. rc = dev.write_register(REG_WHISKBOOMLASER_STATUS, &value);
  127. }
  128. cs_pcl.unlock();
  129. _heartbeat_write_clock = clock();
  130. if (0 != rc)
  131. {
  132. reconnect();//端开,重连
  133. }
  134. return rc;
  135. }
  136. int CPLCMonitor::write_laserresult_register(int addr,uint16_t *pvalue)
  137. {
  138. uint16_t dest = 0xff;
  139. cs_pcl.lock();
  140. int rc= dev.write_registers(addr, 10, pvalue);
  141. /*int rc = dev.read_register(REG_WHISKBOOMLASER_STATUS, &dest);
  142. if (PLC_LASER_ERROR != dest)
  143. {
  144. rc = dev.write_registers(REG_WHISKBOOMLASER_STATUS, 7, pvalue);
  145. }*/
  146. cs_pcl.unlock();
  147. _heartbeat_write_clock = clock();
  148. return rc;
  149. }
  150. void CPLCMonitor::MeasureComplete(bool bOK)
  151. {
  152. //_measure_finished = TRUE;
  153. if (!bOK)
  154. {
  155. write_laserstatus_register(PLC_LASER_FINISH_FAILED);
  156. }
  157. else
  158. {
  159. write_laserstatus_register(PLC_LASER_FINISH_OK);
  160. }
  161. }
  162. bool CPLCMonitor::setMeasureResult(int addr, struct whiskboom_laser_value * p)
  163. {
  164. if (p == 0||addr<0) //失败,没有摆扫结果,硬件错误;
  165. {
  166. return false;
  167. }
  168. else
  169. {
  170. uint16_t response[10] = { 0 };
  171. memset(response, 0, sizeof(uint16_t) * 10);
  172. if (p->corrected)
  173. {
  174. response[6] = eLaser_data_ok;
  175. }
  176. else {
  177. response[6] = eLaser_data_failed;
  178. }
  179. response[0] = (p->x);
  180. response[1] = p->y;
  181. response[2] = (int(p->a) % 18000);
  182. response[3] = p->l;
  183. response[4] = p->w;
  184. response[5] = p->h;
  185. response[7] = p->l; ////轴距
  186. write_laserresult_register(addr,(uint16_t *)response);
  187. return true;
  188. }
  189. }
  190. void CPLCMonitor::Monitoring()
  191. {
  192. const int SIGNAL_NUM = 64;
  193. const int SIGNAL_ADDR = 0;
  194. static uint16_t value[SIGNAL_NUM] = { 0 };
  195. static uint16_t last_value[SIGNAL_NUM] = { 0 };
  196. int rc = read_registers(SIGNAL_ADDR, SIGNAL_NUM, last_value);
  197. LOG(INFO) << "\tStart signal monitoring thread";
  198. while (_monitoring)
  199. {
  200. memset(value, 0, SIGNAL_NUM * sizeof(uint16_t));
  201. int rc = read_registers(SIGNAL_ADDR, SIGNAL_NUM, value);
  202. if (rc == 0)
  203. {
  204. for (int i = REG_PARKSTATUS; i < SIGNAL_NUM; ++i)
  205. {
  206. if (value[i] != last_value[i])
  207. {
  208. if(m_PlcDataCallback && m_pointer)
  209. {
  210. QtMessageData data;
  211. data.msg_type=ePlcSignal;
  212. data.signal_size=SIGNAL_NUM;
  213. memcpy(data.plc_data,value,sizeof(uint16_t)*SIGNAL_NUM);
  214. m_PlcDataCallback(data,m_pointer);
  215. }
  216. break;
  217. }
  218. }
  219. memcpy(last_value, value, sizeof(uint16_t)*SIGNAL_NUM);
  220. }
  221. Sleep(200);
  222. }
  223. LOG(INFO) << "\tStop signal monitor thread!";
  224. }
  225. void CPLCMonitor::thread_monitor(void* lp)
  226. {
  227. CPLCMonitor* plc = (CPLCMonitor*)lp;
  228. plc->Monitoring();
  229. }
  230. void CPLCMonitor::Run()
  231. {
  232. uint16_t value[2] = { 0xffff,0xffff };
  233. uint16_t parking_status = 0xff;
  234. uint16_t response[7] = { 0 };
  235. int rc = -1;
  236. clock_t current_clock;
  237. uint16_t finite_state_machines = PLC_LASER_READY;
  238. write_laserstatus_register(finite_state_machines);
  239. uint16_t las_parkstatus = 0;
  240. while (_monitoring)
  241. {
  242. memset(value, 0xff, sizeof(value));
  243. rc = read_registers(REG_PARKSTATUS, 2, value);
  244. if (-1 == rc)
  245. {
  246. fprintf(stderr, "CPLCMonitor: read regiser failed\n");
  247. }
  248. parking_status = value[0];
  249. finite_state_machines = value[1];
  250. //上次状态为:开始测量,测量中
  251. if (PLC_LASER_START == finite_state_machines
  252. || PLC_LASER_WORKING == finite_state_machines)
  253. {
  254. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_READY)
  255. {
  256. write_laserstatus_register(PLC_LASER_PING);
  257. finite_state_machines = PLC_LASER_PING;
  258. }
  259. }
  260. //PLC 我要停车等待状态
  261. if (PLC_PARKING_WAIT == parking_status|| 2 == parking_status)
  262. {
  263. current_clock = clock();
  264. //激光上次状态为:测量完成成功或者测量完成失败的状态
  265. if (PLC_LASER_FINISH_OK == finite_state_machines
  266. || PLC_LASER_FINISH_FAILED == finite_state_machines)
  267. {
  268. //超过10秒,开始返回就绪状态
  269. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_READY)
  270. {
  271. //先清除数据
  272. if (PLC_LASER_FINISH_FAILED == finite_state_machines)
  273. {
  274. /*memset(response, 0, 7 * sizeof(uint16_t));
  275. write_laserresult_register((uint16_t *)response);*/
  276. }
  277. write_laserstatus_register(PLC_LASER_READY);
  278. finite_state_machines = PLC_LASER_READY;
  279. }
  280. }
  281. //激光上次状态为:就绪或者心跳状态1,
  282. else if (PLC_LASER_READY == finite_state_machines
  283. || PLC_LASER_PONG == finite_state_machines)
  284. {
  285. //超过3秒,开始返回心跳状态2
  286. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_PINGPANG)
  287. {
  288. write_laserstatus_register(PLC_LASER_PING);
  289. finite_state_machines = PLC_LASER_PING;
  290. }
  291. }
  292. //激光上次状态为:心跳状态2
  293. else if (PLC_LASER_PING == finite_state_machines)
  294. {
  295. //超过3秒,开始返回心跳状态1
  296. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_PINGPANG)
  297. {
  298. write_laserstatus_register(PLC_LASER_PONG);
  299. finite_state_machines = PLC_LASER_PONG;
  300. }
  301. }
  302. //激光上次状态为:测量开始,测量中)
  303. else if (PLC_LASER_START == finite_state_machines
  304. || PLC_LASER_WORKING == finite_state_machines)
  305. {
  306. //此时激光可能在测量状态中,让激光测量停止,结果:
  307. // 1. 如果未在测量状态,激光接受状态不会有任何返回值,
  308. // 2. 如果在测量状态会有测量失败信息须处理
  309. LOG(ERROR) << "\t 测量中开始信号终止";
  310. /* cs_cmd.Lock();
  311. for (std::vector<CLaserNet*>::iterator it = _cmdlistLaserPointer.begin(); it != _cmdlistLaserPointer.end(); ++it)
  312. (*it)->Stop();
  313. cs_cmd.Unlock();*/
  314. write_laserstatus_register(PLC_LASER_READY);
  315. finite_state_machines = PLC_LASER_READY;
  316. }
  317. //不可修复错误,等系统重启
  318. else if (PLC_LASER_ERROR == finite_state_machines)
  319. {
  320. fprintf(stderr, "\n\n\n\n\n\n不可修复错误,等系统重启\n\n\n\n\n\n");
  321. }
  322. else
  323. {
  324. fprintf(stderr, "\n\n\n\n\n\n&&&&&&&&&!!!!!!!!!!!!!@@@@@@@@@@@@@@$$$$$$$$$$$$$$$$$$$完全不可能出现的状态\n\n\n\n\n\n");
  325. }
  326. las_parkstatus = PLC_PARKING_WAIT;
  327. }
  328. //PLC 我要停车测量开始
  329. else if (parking_status>0)
  330. {
  331. //激光上次状态为:就绪,心跳状态1,心跳状态2
  332. if(PLC_LASER_READY == finite_state_machines
  333. || PLC_LASER_PING == finite_state_machines
  334. || PLC_LASER_PONG == finite_state_machines
  335. || PLC_LASER_FINISH_OK == finite_state_machines
  336. || PLC_LASER_FINISH_FAILED == finite_state_machines)
  337. {
  338. ///// 测量
  339. if (PLC_PARKING_WAIT == las_parkstatus && parking_status==1)
  340. {
  341. //置测量结果为未完成状态
  342. _measure_finished = FALSE;
  343. //测量开始
  344. if (m_callback)
  345. {
  346. //char plate = parking_status;
  347. uint16_t param = 0x03;
  348. m_callback(true, param, m_pointer, parking_status);
  349. }
  350. //返回测量开始状态
  351. write_laserstatus_register(PLC_LASER_START);
  352. finite_state_machines = PLC_LASER_START;
  353. }
  354. ////// 电子围栏测量
  355. /*else if ((PLC_LASER_READY == finite_state_machines
  356. || PLC_LASER_PING == finite_state_machines
  357. || PLC_LASER_PONG == finite_state_machines)
  358. &&parking_status == 2)
  359. {
  360. //置测量结果为未完成状态
  361. _measure_finished = FALSE;
  362. //测量开始
  363. if (m_callback)
  364. {
  365. uint16_t param = 0x03;
  366. m_callback(true, param, m_pointer, parking_status);
  367. }
  368. //返回测量开始状态
  369. write_laserstatus_register(PLC_LASER_START);
  370. finite_state_machines = PLC_LASER_START;
  371. }*/
  372. }
  373. //上次状态为:测量完成成功,测量完成错误,
  374. if (PLC_LASER_FINISH_OK == finite_state_machines
  375. || PLC_LASER_FINISH_FAILED == finite_state_machines)
  376. {
  377. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_PINGPANG)
  378. {
  379. write_laserstatus_register(PLC_LASER_PING);
  380. finite_state_machines = PLC_LASER_PING;
  381. }
  382. }
  383. //激光上次状态为:开始测量
  384. else if (PLC_LASER_START == finite_state_machines)
  385. {
  386. current_clock = clock();
  387. //超过200毫秒,返回测量中
  388. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC >= PLC_LASER_TIMEOUT_START)
  389. {
  390. write_laserstatus_register(PLC_LASER_WORKING);
  391. finite_state_machines = PLC_LASER_WORKING;
  392. }
  393. }
  394. else if (PLC_LASER_WORKING == finite_state_machines)
  395. {
  396. if (TRUE == _measure_finished)
  397. {
  398. //测量完成
  399. /* memset(response, 0, sizeof(uint16_t) * 7);
  400. if (_value.corrected)
  401. {
  402. response[0] = PLC_LASER_FINISH_OK;
  403. }
  404. else {
  405. response[0] = PLC_LASER_FINISH_FAILED;
  406. }
  407. response[1] = _value.x;
  408. response[2] = _value.y;
  409. response[3] = (int(_value.a) % 18000);
  410. response[4] = _value.l;
  411. response[5] = _value.w;
  412. response[6] = _value.h;
  413. write_laserresult_register((uint16_t *)response);*/
  414. write_laserstatus_register(PLC_LASER_FINISH_FAILED);
  415. finite_state_machines = PLC_LASER_FINISH_FAILED;
  416. }
  417. else {
  418. current_clock = clock();
  419. if (double(current_clock - _heartbeat_write_clock)/CLOCKS_PER_SEC > PLC_LASER_TIMEOUT_MAXMEASURE) //10分钟还没返回测量结果, 说明系统可能出错了
  420. {
  421. write_laserstatus_register(PLC_LASER_ERROR);
  422. finite_state_machines = PLC_LASER_ERROR;
  423. }
  424. }
  425. }
  426. else if (PLC_LASER_ERROR == finite_state_machines)
  427. {
  428. fprintf(stderr, "\n\n\n\n\n\n不可修复错误,等系统重启\n\n\n\n\n\n");
  429. }
  430. else
  431. {
  432. fprintf(stderr, "\n\n\n\n\n\n&&&&&&&&&!!!!!!!!!!!!!@@@@@@@@@@@@@@$$$$$$$$$$$$$$$$$$$完全不可能出现的状态\n\n\n\n\n\n");
  433. }
  434. las_parkstatus = PCL_PARKING_REQUEST;
  435. }
  436. else
  437. {
  438. if (PCL_PARKING_ERROR != las_parkstatus)
  439. {
  440. LOG(ERROR)<<("\t严重警告:PLC我要停车状态异常,不可修复错误,等系统重启");
  441. //停止所有激光
  442. if (m_callback)
  443. {
  444. char laser = 0xFF;
  445. m_callback(false, uint16_t(laser), m_pointer, parking_status);
  446. }
  447. write_laserstatus_register(PLC_LASER_READY);
  448. finite_state_machines = PLC_LASER_READY;
  449. }
  450. Sleep(200);
  451. las_parkstatus = PCL_PARKING_ERROR;
  452. }
  453. Sleep(50);
  454. }
  455. }
  456. }