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.

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