You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

733 lines
28 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "disinfection_ctl_service.hpp"
  2. #include <cstring>
  3. #include <iostream>
  4. #include "configs/gconfig.hpp"
  5. #include "configs/project_setting.hpp"
  6. #include "iflytop/components/uart_printer/uart_printer.hpp"
  7. #include "service/device_state_service.hpp"
  8. using namespace iflytop;
  9. using namespace std;
  10. /**
  11. * @brief
  12. *
  13. * :
  14. *
  15. *
  16. * 1s
  17. *
  18. * 1s
  19. *
  20. * 1s
  21. *
  22. *
  23. *
  24. * 1s
  25. *
  26. * 1s
  27. *
  28. *
  29. */
  30. // #define PRE_HEAT_TIME (2)
  31. // #define PRE_HEAT_TIME (5 * 60)
  32. #define DVALUE_COMPUTEPERIOD_TIME_S (10.0)
  33. #define MAX_VOLUME (5000)
  34. namespace iflytop {
  35. extern bool g_in_test;
  36. }
  37. DisinfectionCtrlService::DisinfectionCtrlService() {}
  38. void DisinfectionCtrlService::initialize() {
  39. GET_TO_SERVICE(m_zcanHost);
  40. GET_TO_SERVICE(m_deviceIoControlService);
  41. GET_TO_SERVICE(m_dbService);
  42. GET_TO_SERVICE(m_disinfectionLogsManager);
  43. m_deviceIoControlService->drainingPump_close();
  44. m_deviceIoControlService->replenishingFluidsPump_close();
  45. m_deviceIoControlService->sprayLiquidPump_close();
  46. m_deviceIoControlService->heartingPlate_setPower(false);
  47. m_deviceIoControlService->airBlower_setState(false);
  48. m_deviceIoControlService->airCompressor_setState(false);
  49. m_dvalueComputer.initialize();
  50. }
  51. static string getTime() {
  52. struct tm tm = {0};
  53. time_t t = time(nullptr);
  54. struct tm* tmp = localtime_r(&t, &tm);
  55. return fmt::format("{:0>4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", tm.tm_year + 1900, //
  56. tm.tm_mon + 1, //
  57. tm.tm_mday, //
  58. tm.tm_hour, //
  59. tm.tm_min, tm.tm_sec);
  60. }
  61. string DisinfectionCtrlService::createDisinfectionID() {
  62. struct tm tm = {0};
  63. time_t t = time(nullptr);
  64. if (t == -1) {
  65. logger->error("time(nullptr) failed");
  66. exit(-1);
  67. }
  68. struct tm* tmp = localtime_r(&t, &tm);
  69. if (!tmp) {
  70. logger->error("localtime_r failed");
  71. exit(-1);
  72. }
  73. // tm = *utctime::tm_increment_hour(&tm, 8);
  74. // logger->info("trace sendmsg_startCapture {}:{}", __FILE__, __LINE__);
  75. return fmt::format("{:0>4}-{:0>2}{:0>2}-{:0>2}{:0>2}{:0>2}", tm.tm_year + 1900, //
  76. tm.tm_mon + 1, //
  77. tm.tm_mday, //
  78. tm.tm_hour, //
  79. tm.tm_min, tm.tm_sec);
  80. }
  81. static bool zfeq(float a, float b, float eps = 0.01) {
  82. if (fabs(a - b) < eps) {
  83. return true;
  84. }
  85. return false;
  86. }
  87. float DisinfectionCtrlService::getDisinfectionDValue(float ppm) { //
  88. return m_dvalueComputer.computeDValue(ppm);
  89. }
  90. float DisinfectionCtrlService::computeNowLogLevel(DisinfectionContext& context) {
  91. float dvalue = context.dvalue;
  92. if (dvalue > 0) {
  93. /**
  94. * @brief m_nowLoglevel
  95. */
  96. return context.m_nowLoglevel + DVALUE_COMPUTEPERIOD_TIME_S / (dvalue * 60);
  97. }
  98. return context.m_nowLoglevel;
  99. }
  100. void DisinfectionCtrlService::computeRemainTime(DisinfectionContext& context) {
  101. /**
  102. * @brief Dvalue
  103. */
  104. float dvalue = context.dvalue;
  105. if (dvalue > 0) {
  106. /**
  107. * @brief m_nowLoglevel
  108. */
  109. if (context.m_targetLoglevel >= context.m_nowLoglevel) {
  110. context.m_remaintime = (context.m_targetLoglevel - context.m_nowLoglevel) * (dvalue * 60);
  111. } else {
  112. context.m_remaintime = 0;
  113. }
  114. } else {
  115. //
  116. }
  117. logger->info("computeRemainTime minh2o2 {} dvalue {}", context.h2o2data.min_h2o2, dvalue);
  118. }
  119. void DisinfectionCtrlService::initContext(DisinfectionContext& context, //
  120. int loglevel, //
  121. float injection_pump_speed, //
  122. float stoped_gs, //
  123. float continued_gs, //
  124. float stoped_satur, //
  125. float continued_satur, //
  126. float stoped_humi, //
  127. float continued_humi //
  128. ) {
  129. context.m_disinfectionID = createDisinfectionID();
  130. context.pre_heat_time_s = m_dbService->getSettingVal("pre_heat_time_s");
  131. context.stoped_gs = stoped_gs;
  132. context.continued_gs = continued_gs;
  133. context.stoped_satur = stoped_satur;
  134. context.continued_satur = continued_satur;
  135. context.stoped_humi = stoped_humi;
  136. context.continued_humi = continued_humi;
  137. context.injection_pump_speed = injection_pump_speed;
  138. context.injection_pump_speed_changed = true;
  139. if (g_in_test) {
  140. logger->warn("in test mode, pre_heat_time_s = 5");
  141. context.pre_heat_time_s = 5;
  142. }
  143. logger->info("startDisinfection {} {}", m_context.m_targetLoglevel, m_context.m_disinfectionID);
  144. logger->info(" stoped_gs {}", context.stoped_gs);
  145. logger->info(" continued_gs {}", context.continued_gs);
  146. logger->info(" stoped_satur {}", context.stoped_satur);
  147. logger->info(" continued_satur {}", context.continued_satur);
  148. logger->info(" stoped_humi {}", context.stoped_humi);
  149. logger->info(" continued_humi {}", context.continued_humi);
  150. logger->info(" pre_heat_time_s {}", context.pre_heat_time_s);
  151. logger->info("");
  152. // m_remaintime = loglevel * 20 * 60; // 计算总的加热时间
  153. context.m_remaintime = context.pre_heat_time_s + loglevel * 90 * 60; // 计算总的加热时间
  154. m_disinfectionWorkState = 1;
  155. context.m_targetLoglevel = loglevel;
  156. context.m_nowLoglevel = 0;
  157. // m_context.m_preheatFlag = true;
  158. m_context.dvalue = 0;
  159. // m_context.stopedflag = false;
  160. m_context.m_state = kpreheat;
  161. m_context.m_starttp = zsteady_clock().now();
  162. m_context.m_starttp_str = getTime();
  163. m_zcanHost->warning_light_ctrl_c1002(1, 0, 0, 1, 0);
  164. m_deviceIoControlService->heartingPlate_setPower(true);
  165. context.csvlogger = m_disinfectionLogsManager->createNewLogger(context.m_disinfectionID);
  166. // zsteady_clock().elapsedTimeS(m_context.m_starttp), //
  167. // sensors[0].h2o2, sensors[0].temp, sensors[0].humid, sensors[0].saturation, //
  168. // sensors[1].h2o2, sensors[1].temp, sensors[1].humid, sensors[1].saturation, //
  169. // sensors[2].h2o2, sensors[2].temp, sensors[2].humid, sensors[2].saturation, //
  170. // m_context.dvalue, m_context.m_nowLoglevel, (int)m_context.m_targetLoglevel, //
  171. // ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getRPM(), //
  172. // ds->getPressureSensorData(1), ds->getPressureSensorData(2), ds->getPressureSensorData(3), ds->getPressureSensorData(4), //
  173. // m_deviceIoControlService->getDisinfectantVolume_g(), //
  174. // m_context.m_remaintime
  175. context.csvlogger->write(
  176. "Date," //
  177. "Hydrogen peroxide volume(ppm),Temperature(C),Relative humidity(%RH),H2O H2O2 RS(%RS)," //
  178. // "h2o22,temp2,humi2,saturation2," //
  179. // "h2o23,temp3,humi3,saturation3," //
  180. "Dvalue,Loglevel,Targetloglevel," //
  181. "Heating,Blower,Compressor,Pump(g/min)," //
  182. "Disinfectant Volume(g)," //
  183. "Remaining time (s)\n" //
  184. );
  185. }
  186. static string formattimeS(int sec) {
  187. if (sec >= 0) {
  188. return fmt::format("{:0>2}:{:0>2}:{:0>2}", sec / 3600, sec % 3600 / 60, sec % 60);
  189. } else {
  190. return fmt::format("--:--:--");
  191. }
  192. }
  193. void DisinfectionCtrlService::dumpDisinfectionLogsToCSV(DisinfectionContext& context) {
  194. auto* sensors = &m_context.h2o2data.h2o2sensor_data[0];
  195. auto ds = m_deviceIoControlService;
  196. float dvalue = 0;
  197. if (m_context.dvalue <= 0) {
  198. dvalue = 0;
  199. } else {
  200. dvalue = m_context.dvalue;
  201. }
  202. int remaintime = getEstimatedRemainingTimeS();
  203. context.csvlogger->write(
  204. fmt::format("{}," //
  205. "{},{},{},{}," //
  206. // "{},{},{},{}," //
  207. // "{},{},{},{}," //
  208. "{},{},{}," //
  209. "{},{},{},{}," //
  210. // "{},{},{},{}," //
  211. "{}," //
  212. "{}\n" //
  213. ,
  214. getTime(), //
  215. sensors[0].h2o2, sensors[0].temp, sensors[0].humid, sensors[0].saturation, //
  216. // sensors[1].h2o2, sensors[1].temp, sensors[1].humid, sensors[1].saturation, //
  217. // sensors[2].h2o2, sensors[2].temp, sensors[2].humid, sensors[2].saturation, //
  218. (int32_t)dvalue, (int32_t)m_context.m_nowLoglevel, (int32_t)m_context.m_targetLoglevel, //
  219. ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), //
  220. m_deviceIoControlService->getDisinfectantVolume_g(), //
  221. formattimeS(remaintime)));
  222. }
  223. void DisinfectionCtrlService::finishDisinfection(DisinfectionContext& context) {
  224. context.m_remaintime = 0;
  225. logger->info("stop disinfection {}", context.m_disinfectionID);
  226. // sprayLiquidPump_close();
  227. m_deviceIoControlService->sprayLiquidPump_close();
  228. usleep(1000 * 1000);
  229. // airCompressor(false);
  230. m_deviceIoControlService->airCompressor_setState(false);
  231. usleep(1000 * 1000);
  232. // blower_setPower(false);
  233. m_deviceIoControlService->airBlower_setState(false);
  234. usleep(1000 * 1000);
  235. // heartingPlate_setPower(false);
  236. m_deviceIoControlService->heartingPlate_setPower(false);
  237. m_disinfectionWorkState = 3;
  238. m_zcanHost->warning_light_ctrl_c1002(1, 0, 0, 0, 0);
  239. context.csvlogger = nullptr;
  240. }
  241. void DisinfectionCtrlService::processPreheatState(DisinfectionContext& context) {
  242. int hasstarttime = zsteady_clock().elapsedTimeS(context.m_starttp);
  243. // logger->info("preheat {}", context.m_disinfectionID);
  244. if ((context.m_state == kpreheat && hasstarttime > m_context.pre_heat_time_s)) {
  245. logger->info("preheat finished {}", context.m_disinfectionID);
  246. // blower_setPower(true);
  247. m_deviceIoControlService->airBlower_setState(true);
  248. usleep(1000 * 1000);
  249. // airCompressor(true);
  250. m_deviceIoControlService->airCompressor_setState(true);
  251. usleep(1000 * 1000);
  252. // sprayLiquidPump_open();
  253. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  254. context.m_state = kdisinfection;
  255. // context.m_preheatFlag = false;
  256. // context.sprayLiquidFlag = true;
  257. } else {
  258. logger->info("{}: preheat {}", context.m_disinfectionID, m_context.pre_heat_time_s - hasstarttime);
  259. }
  260. }
  261. void DisinfectionCtrlService::dumpDisinfectionLogs(DisinfectionContext& context) {
  262. // float h2o2_g = m_deviceIoControlService->getDisinfectantVolume_g();
  263. auto* sensors = &m_context.h2o2data.h2o2sensor_data[0];
  264. auto ds = m_deviceIoControlService;
  265. logger->info(
  266. "T:{}," //
  267. "s1:({},{},{},{})," //
  268. "s2:({},{},{},{})," //
  269. "s3:({},{},{},{})," //
  270. "D:{},log:({}:{})," //
  271. "io:({},{},{},{})," //
  272. "p:({},{},{},{})," //
  273. "h2o2g:{}," //
  274. "rt:{}" //
  275. ,
  276. zsteady_clock().elapsedTimeS(m_context.m_starttp), //
  277. sensors[0].h2o2, sensors[0].temp, sensors[0].humid, sensors[0].saturation, //
  278. sensors[1].h2o2, sensors[1].temp, sensors[1].humid, sensors[1].saturation, //
  279. sensors[2].h2o2, sensors[2].temp, sensors[2].humid, sensors[2].saturation, //
  280. m_context.dvalue, m_context.m_nowLoglevel, (int)m_context.m_targetLoglevel, //
  281. ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getRPM(), //
  282. ds->getPressureSensorData(1), ds->getPressureSensorData(2), ds->getPressureSensorData(3), ds->getPressureSensorData(4), //
  283. m_deviceIoControlService->getDisinfectantVolume_g(), //
  284. getEstimatedRemainingTimeS());
  285. }
  286. /**
  287. * @brief
  288. *
  289. */
  290. void DisinfectionCtrlService::processDisinfectionState(DisinfectionContext& context) {
  291. ZCHECK(context.m_state == kdisinfection || context.m_state == kdisinfection_take_a_break, "state error");
  292. /**
  293. * @brief
  294. */
  295. /**
  296. * @brief 湿
  297. */
  298. if (m_context.m_state == kdisinfection) {
  299. /**
  300. * @brief
  301. */
  302. float nowSatur = m_context.h2o2data.max_saturation;
  303. float nowh2o2 = m_context.h2o2data.max_h2o2;
  304. float humid = m_context.h2o2data.max_humid;
  305. if (m_context.injection_pump_speed_changed) {
  306. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  307. m_context.injection_pump_speed_changed = false;
  308. }
  309. // humid > m_context.stoped_satur
  310. if (nowSatur > m_context.stoped_satur || nowh2o2 > m_context.stoped_gs || humid > m_context.stoped_humi) {
  311. logger->info("stop sprayLiquid");
  312. m_deviceIoControlService->sprayLiquidPump_close();
  313. usleep(1000 * 1000);
  314. m_deviceIoControlService->airCompressor_setState(false);
  315. // m_context.sprayLiquidFlag = false;
  316. m_context.m_state = kdisinfection_take_a_break;
  317. }
  318. } else {
  319. float nowSatur = m_context.h2o2data.max_saturation;
  320. float nowh2o2 = m_context.h2o2data.max_h2o2;
  321. float humid = m_context.h2o2data.max_humid;
  322. // && humid < m_context.continued_satur
  323. if (nowSatur < m_context.continued_satur && nowh2o2 < m_context.continued_gs && humid < context.continued_humi) {
  324. logger->info("start sprayLiquid");
  325. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  326. usleep(1000 * 1000);
  327. m_deviceIoControlService->airCompressor_setState(true);
  328. m_context.m_state = kdisinfection;
  329. }
  330. }
  331. }
  332. void DisinfectionCtrlService::disinfectionLoop(bool& breakflag) {
  333. // logger->info("disinfection running {} {}s preheatFlag:{}", m_context.m_disinfectionID, m_context.m_remaintime, m_context.m_preheatFlag);
  334. m_context.m_remaintime--;
  335. bool forcelog = false;
  336. if (m_context.m_remaintime < 0) {
  337. m_context.m_remaintime = 0;
  338. }
  339. /**
  340. * @brief
  341. */
  342. m_deviceIoControlService->getAllSensorData(m_context.h2o2data);
  343. /**
  344. * @brief D值
  345. */
  346. m_context.dvalue = getDisinfectionDValue(m_context.h2o2data.min_h2o2);
  347. if (zsteady_clock().elapsedTimeS(m_context.m_lastComputeDvalueTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
  348. m_context.m_lastComputeDvalueTp = zsteady_clock().now();
  349. //
  350. if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  351. m_context.m_nowLoglevel = computeNowLogLevel(m_context);
  352. computeRemainTime(m_context);
  353. }
  354. }
  355. if (m_context.m_state == kpreheat) {
  356. /**
  357. * @brief
  358. */
  359. processPreheatState(m_context);
  360. } else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  361. /**
  362. * @brief
  363. */
  364. processDisinfectionState(m_context);
  365. //
  366. if (m_context.m_remaintime <= 0 && m_context.m_nowLoglevel > (m_context.m_targetLoglevel + 0.01)) {
  367. m_context.m_remaintime = 0;
  368. m_context.m_nowLoglevel = m_context.m_targetLoglevel + 0.01;
  369. logger->info("disinfection finished {},but waitting for h2o2 to safe", m_context.m_disinfectionID);
  370. m_deviceIoControlService->sprayLiquidPump_close();
  371. usleep(1000 * 1000);
  372. m_deviceIoControlService->airCompressor_setState(false);
  373. usleep(1000 * 1000);
  374. m_deviceIoControlService->heartingPlate_setPower(false);
  375. m_context.m_state = kwait_for_h2o2_down;
  376. forcelog = true;
  377. }
  378. } else if (m_context.m_state == kwait_for_h2o2_down) {
  379. /**
  380. * @brief h2o2浓度下降
  381. */
  382. logger->info("waitting for h2o2 concentration to safe value {}=>{}", m_context.h2o2data.min_h2o2, 1);
  383. if (m_context.h2o2data.min_h2o2 < 1) {
  384. logger->info("h2o2 concentration to safe value");
  385. breakflag = true;
  386. forcelog = true;
  387. m_context.m_state = kfinished;
  388. }
  389. } else {
  390. ZCHECK(false, "state error");
  391. }
  392. if (forcelog || zsteady_clock().elapsedTimeS(m_context.m_lastlogTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
  393. m_context.m_lastlogTp = zsteady_clock().now();
  394. dumpDisinfectionLogs(m_context);
  395. dumpDisinfectionLogsToCSV(m_context);
  396. }
  397. }
  398. void DisinfectionCtrlService::changeDisinfectionParameter(int injection_pump_speed, //
  399. int stoped_gs, //
  400. int continued_gs, //
  401. int stoped_satur, //
  402. int continued_satur, //
  403. int stoped_humi, //
  404. int continued_humi) {
  405. lock_guard<recursive_mutex> lock(lock_);
  406. // logger->info("changeInjectionPumpSpeed {}=>{}", m_context.injection_pump_speed, speed);
  407. // m_context.injection_pump_speed = speed;
  408. m_context.injection_pump_speed = injection_pump_speed;
  409. m_context.stoped_gs = stoped_gs;
  410. m_context.continued_gs = continued_gs;
  411. m_context.stoped_satur = stoped_satur;
  412. m_context.continued_satur = continued_satur;
  413. m_context.stoped_humi = stoped_humi;
  414. m_context.continued_humi = continued_humi;
  415. m_context.injection_pump_speed_changed = true;
  416. logger->info("changeDisinfectionParameter {} {} {} {} {} {} {}", injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi,
  417. continued_humi);
  418. }
  419. void DisinfectionCtrlService::startDisinfection(int loglevel, //
  420. int injection_pump_speed, //
  421. int stoped_gs, //
  422. int continued_gs, //
  423. int stoped_satur, //
  424. int continued_satur, //
  425. int stoped_humi, //
  426. int continued_humi //
  427. ) {
  428. lock_guard<recursive_mutex> lock(lock_);
  429. /**
  430. * @TODO
  431. * 湿湿
  432. */
  433. if (m_disinfectionThread) {
  434. stopDisinfection();
  435. }
  436. initContext(m_context, loglevel, injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi);
  437. m_disinfectionThread.reset(new Thread("m_disinfectionThread", [this]() {
  438. ThisThread thisThread;
  439. while (!thisThread.getExitFlag()) {
  440. thisThread.sleepForMs(1000);
  441. bool breakflag = false;
  442. disinfectionLoop(breakflag);
  443. if (breakflag) {
  444. break;
  445. }
  446. }
  447. printfDisinfectionContextResult();
  448. //
  449. finishDisinfection(m_context);
  450. }));
  451. //
  452. }
  453. void DisinfectionCtrlService::printfDisinfectionContextResult() {
  454. /**
  455. * @brief
  456. * = = = = = = = = = = = = = = =
  457. *
  458. * XXXXX
  459. * 2021-03-10 10:00:00
  460. * 2021-03-10 10:00:00
  461. * 01:59
  462. * LOG 6
  463. * LOG 6
  464. * = = = = = = = = = = = = = = =
  465. *
  466. */
  467. auto dio = m_deviceIoControlService;
  468. auto ds = GET_SERVICE(DeviceStateService);
  469. m_context.m_endtp_str = getTime();
  470. int totaltime = zsteady_clock().elapsedTimeS(m_context.m_starttp) / 60;
  471. dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
  472. dio->printerPrintf(fmt::format(" 全思美特\n"));
  473. dio->printerPrintf(fmt::format("操作人 {}\n", ds->getLoginUid()));
  474. dio->printerPrintf(fmt::format("开始时间 {}\n", m_context.m_starttp_str));
  475. dio->printerPrintf(fmt::format("结束时间 {}\n", m_context.m_endtp_str));
  476. dio->printerPrintf(fmt::format("总耗时 {}:{}\n", totaltime / 60, totaltime % 60));
  477. dio->printerPrintf(fmt::format("目标LOG {}\n", (int)m_context.m_targetLoglevel));
  478. dio->printerPrintf(fmt::format("实际LOG {}\n", (int)m_context.m_nowLoglevel));
  479. dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
  480. dio->printerPrintf(fmt::format("\n"));
  481. dio->printerPrintf(fmt::format("\n"));
  482. dio->printerPrintf(fmt::format("\n"));
  483. // getTime
  484. // dio->printerPrintf(fmt::format("开始时间 {}\n", zsteady_clock().formatTime(m_context.m_starttp)));
  485. }
  486. int DisinfectionCtrlService::getDisinfectionWorkState() { return m_context.m_state; }
  487. void DisinfectionCtrlService::stopDisinfection() {
  488. lock_guard<recursive_mutex> lock(lock_);
  489. if (m_disinfectionThread) {
  490. m_disinfectionThread->join();
  491. m_disinfectionThread = nullptr;
  492. }
  493. m_context.m_state = kfinished;
  494. m_disinfectionWorkState = 0;
  495. }
  496. int32_t DisinfectionCtrlService::getEstimatedRemainingTimeS() {
  497. lock_guard<recursive_mutex> lock(lock_);
  498. if (m_context.m_state == kpreheat) {
  499. return getPreHeatRaminTimeS();
  500. } else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  501. if (m_context.dvalue > 0) {
  502. return m_context.m_remaintime;
  503. } else {
  504. return -1;
  505. }
  506. } else {
  507. return 0;
  508. }
  509. }
  510. int32_t DisinfectionCtrlService::getPreHeatRaminTimeS() {
  511. lock_guard<recursive_mutex> lock(lock_);
  512. int32_t remaintime = 0;
  513. if (m_context.m_state == kpreheat) {
  514. remaintime = m_context.pre_heat_time_s - zsteady_clock().elapsedTimeS(m_context.m_starttp);
  515. if (remaintime < 0) {
  516. remaintime = 0;
  517. }
  518. return remaintime;
  519. } else {
  520. return 0;
  521. }
  522. }
  523. string DisinfectionCtrlService::getDisinfectionID() {
  524. lock_guard<recursive_mutex> lock(lock_);
  525. return m_context.m_disinfectionID;
  526. }
  527. bool DisinfectionCtrlService::isPreheatState() {
  528. lock_guard<recursive_mutex> lock(lock_);
  529. return m_context.m_state == kpreheat;
  530. }
  531. int DisinfectionCtrlService::getReplenishingFluidsWorkState() { return m_replenishingFluidsWorkState; }
  532. int DisinfectionCtrlService::getDrainingWorkState() { return m_drainingWorkState; }
  533. /*******************************************************************************
  534. * // 加液 *
  535. *******************************************************************************/
  536. /**
  537. * @brief
  538. *
  539. * @param stopatg
  540. */
  541. void DisinfectionCtrlService::startReplenishingFluids(int stopatg) {
  542. lock_guard<recursive_mutex> lock(lock_);
  543. if (m_disinfectionThread) {
  544. m_disinfectionThread->join();
  545. m_disinfectionThread = nullptr;
  546. }
  547. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  548. int maxg = DISINFECTANT_BUCKET_CAPACITY;
  549. if (stopatg > maxg) {
  550. logger->warn("start Replenishing fail, stopatg {} > maxg {}", stopatg, maxg);
  551. stopatg = maxg;
  552. }
  553. if (nowvolume > stopatg) {
  554. logger->warn("start Replenishing fail, nowvolume {} > stopatg {}", nowvolume, stopatg);
  555. return;
  556. }
  557. m_disinfectionThread.reset(new Thread("disinfectionThread", [this, stopatg]() {
  558. ThisThread thisThread;
  559. m_deviceIoControlService->replenishingFluidsPump_open();
  560. logger->info("startReplenishingFluids {}g", stopatg);
  561. while (!thisThread.getExitFlag()) {
  562. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  563. logger->info("replenishingFluids {}g", nowvolume);
  564. if (nowvolume > stopatg) {
  565. break;
  566. }
  567. if (nowvolume > MAX_VOLUME) {
  568. logger->warn("replenishingFluids reach full level {}g", nowvolume);
  569. break;
  570. }
  571. thisThread.sleepForMs(1000);
  572. }
  573. logger->info("stopReplenishingFluids");
  574. // replenishingFluidsPump_close();
  575. m_deviceIoControlService->replenishingFluidsPump_close();
  576. m_replenishingFluidsWorkState = 0;
  577. }));
  578. //
  579. m_replenishingFluidsWorkState = 1;
  580. logger->info("startReplenishingFluids ");
  581. }
  582. /**
  583. * @brief
  584. *
  585. */
  586. void DisinfectionCtrlService::stopReplenishingFluids() {
  587. lock_guard<recursive_mutex> lock(lock_);
  588. if (m_disinfectionThread) {
  589. m_disinfectionThread->join();
  590. m_disinfectionThread = nullptr;
  591. }
  592. logger->info("stopReplenishingFluids");
  593. // replenishingFluidsPump_close();
  594. m_deviceIoControlService->replenishingFluidsPump_close();
  595. m_replenishingFluidsWorkState = 0;
  596. }
  597. /*******************************************************************************
  598. * *
  599. *******************************************************************************/
  600. /**
  601. * @brief
  602. *
  603. */
  604. void DisinfectionCtrlService::startDraining() {
  605. lock_guard<recursive_mutex> lock(lock_);
  606. if (m_disinfectionThread) {
  607. m_disinfectionThread->join();
  608. m_disinfectionThread = nullptr;
  609. }
  610. m_disinfectionThread.reset(new Thread("disinfectionThread", [this]() {
  611. ThisThread thisThread;
  612. m_deviceIoControlService->drainingPump_open();
  613. logger->info("startDraining ");
  614. auto startdrainingtime = zsteady_clock().now();
  615. zsteady_tp volumeReachZeroTime;
  616. bool volumeReachZeroFlag = false;
  617. while (!thisThread.getExitFlag()) {
  618. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  619. logger->info("draining remain {} g", nowvolume);
  620. if (!volumeReachZeroFlag && nowvolume == 0) {
  621. volumeReachZeroTime = zsteady_clock().now();
  622. volumeReachZeroFlag = true;
  623. }
  624. if (volumeReachZeroFlag) {
  625. logger->info("stopDraining after {} s", 30 - zsteady_clock().elapsedTimeS(volumeReachZeroTime));
  626. if (zsteady_clock().elapsedTimeS(volumeReachZeroTime) > 30) {
  627. break;
  628. }
  629. }
  630. thisThread.sleepForMs(1000);
  631. }
  632. logger->info("stopDraining");
  633. // replenishingFluidsPump_close();
  634. m_deviceIoControlService->drainingPump_close();
  635. m_drainingWorkState = 0;
  636. }));
  637. logger->info("startDraining");
  638. // drainingPump_open();
  639. m_drainingWorkState = 1;
  640. }
  641. /**
  642. * @brief
  643. */
  644. void DisinfectionCtrlService::stopDraining() {
  645. lock_guard<recursive_mutex> lock(lock_);
  646. if (m_disinfectionThread) {
  647. m_disinfectionThread->join();
  648. m_disinfectionThread = nullptr;
  649. }
  650. logger->info("stopDraining");
  651. m_drainingWorkState = 0;
  652. // drainingPump_close();
  653. m_deviceIoControlService->drainingPump_close();
  654. }