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.

841 lines
31 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. #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. // int h2o2_0 = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(0);
  257. // int h2o2_1 = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(1);
  258. // int h2o2_2 = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(2);
  259. // int humid0 = m_deviceIoControlService->H2O2Sensor_readHumid(0);
  260. // int humid1 = m_deviceIoControlService->H2O2Sensor_readHumid(1);
  261. // int humid2 = m_deviceIoControlService->H2O2Sensor_readHumid(2);
  262. // int temp0 = m_deviceIoControlService->H2O2Sensor_readTemperature(0);
  263. // int temp1 = m_deviceIoControlService->H2O2Sensor_readTemperature(1);
  264. // int temp2 = m_deviceIoControlService->H2O2Sensor_readTemperature(2);
  265. // int sat0 = m_deviceIoControlService->H2O2Sensor_readSaturation(0);
  266. // int sat1 = m_deviceIoControlService->H2O2Sensor_readSaturation(1);
  267. // int sat2 = m_deviceIoControlService->H2O2Sensor_readSaturation(2);
  268. auto& cx = context;
  269. auto ds = m_deviceIoControlService;
  270. float dvalue = 0;
  271. if (m_context.dvalue <= 0) {
  272. dvalue = 0;
  273. } else {
  274. dvalue = m_context.dvalue;
  275. }
  276. int remaintime = getEstimatedRemainingTimeS();
  277. context.csvlogger->write(
  278. fmt::format("{},"
  279. "s0({},{},{},{}),"
  280. "s1({},{},{},{}),"
  281. "s2({},{},{},{}),"
  282. "s2({},{},{},{}),"
  283. "min_h2o2:{},max_h2o2:{},max_hum:{},max_sa:{},"
  284. "dv:{},log:{},tlog:{},"
  285. "h:{},airB:{},airC:{},pump:{},"
  286. "g:{},remainS:{}",
  287. "\n",
  288. getTime(), //
  289. cx.h2o2[0], cx.temp[0], cx.humid[0], cx.saturation[0], //
  290. cx.h2o2[1], cx.temp[1], cx.humid[1], cx.saturation[1], //
  291. cx.h2o2[2], cx.temp[2], cx.humid[2], cx.saturation[2], //
  292. m_context.max_h2o2, m_context.min_h2o2, m_context.max_humid, m_context.max_saturation, //
  293. (int32_t)dvalue, (int32_t)m_context.m_nowLoglevel, (int32_t)m_context.m_targetLoglevel, //
  294. ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), //
  295. m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime)));
  296. #endif
  297. }
  298. void DisinfectionCtrlService::finishDisinfection(DisinfectionContext& context) {
  299. context.m_remaintime = 0;
  300. logger->info("stop disinfection {}", context.m_disinfectionID);
  301. // sprayLiquidPump_close();
  302. m_deviceIoControlService->sprayLiquidPump_close();
  303. usleep(1000 * 1000);
  304. // airCompressor(false);
  305. m_deviceIoControlService->airCompressor_setState(false);
  306. usleep(1000 * 1000);
  307. // blower_setPower(false);
  308. m_deviceIoControlService->airBlower_setState(false);
  309. usleep(1000 * 1000);
  310. // heartingPlate_setPower(false);
  311. m_deviceIoControlService->heartingPlate_setPower(false);
  312. m_disinfectionWorkState = 3;
  313. m_zcanHost->warning_light_ctrl_c1002(1, 0, 0, 0, 0);
  314. context.csvlogger = nullptr;
  315. }
  316. void DisinfectionCtrlService::processPreheatState(DisinfectionContext& context) {
  317. int hasstarttime = zsteady_clock().elapsedTimeS(context.m_starttp);
  318. // logger->info("preheat {}", context.m_disinfectionID);
  319. if ((context.m_state == kpreheat && hasstarttime > m_context.pre_heat_time_s)) {
  320. logger->info("preheat finished {}", context.m_disinfectionID);
  321. m_deviceIoControlService->airBlower_setState(true);
  322. usleep(1000 * 1000);
  323. m_deviceIoControlService->airCompressor_setState(true);
  324. usleep(1000 * 1000);
  325. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  326. context.m_state = kdisinfection;
  327. } else {
  328. logger->info("{}: preheat {}", context.m_disinfectionID, m_context.pre_heat_time_s - hasstarttime);
  329. }
  330. }
  331. /**
  332. * @brief
  333. *
  334. */
  335. void DisinfectionCtrlService::processDisinfectionState(DisinfectionContext& context) {
  336. ZCHECK(context.m_state == kdisinfection || context.m_state == kdisinfection_take_a_break, "state error");
  337. /**
  338. * @brief
  339. */
  340. /**
  341. * @brief 湿
  342. */
  343. if (m_context.m_state == kdisinfection) {
  344. /**
  345. * @brief
  346. */
  347. float nowSatur = m_context.max_saturation;
  348. float nowh2o2 = m_context.max_h2o2;
  349. float humid = m_context.max_humid;
  350. if (m_context.injection_pump_speed_changed) {
  351. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  352. m_context.injection_pump_speed_changed = false;
  353. }
  354. // humid > m_context.stoped_satur
  355. if (nowSatur > m_context.stoped_satur || nowh2o2 > m_context.stoped_gs || humid > m_context.stoped_humi) {
  356. logger->info("stop sprayLiquid");
  357. m_deviceIoControlService->sprayLiquidPump_close();
  358. usleep(1000 * 1000);
  359. m_deviceIoControlService->airCompressor_setState(false);
  360. // m_context.sprayLiquidFlag = false;
  361. m_context.m_state = kdisinfection_take_a_break;
  362. }
  363. } else {
  364. float nowSatur = m_context.max_saturation;
  365. float nowh2o2 = m_context.max_h2o2;
  366. float humid = m_context.max_humid;
  367. // && humid < m_context.continued_satur
  368. if (nowSatur < m_context.continued_satur && nowh2o2 < m_context.continued_gs && humid < context.continued_humi) {
  369. logger->info("start sprayLiquid");
  370. m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
  371. usleep(1000 * 1000);
  372. m_deviceIoControlService->airCompressor_setState(true);
  373. m_context.m_state = kdisinfection;
  374. }
  375. }
  376. }
  377. void DisinfectionCtrlService::disinfectionLoop(bool& breakflag) {
  378. // logger->info("disinfection running {} {}s preheatFlag:{}", m_context.m_disinfectionID, m_context.m_remaintime, m_context.m_preheatFlag);
  379. m_context.m_remaintime--;
  380. bool forcelog = false;
  381. if (m_context.m_remaintime < 0) {
  382. m_context.m_remaintime = 0;
  383. }
  384. /**
  385. * @brief
  386. */
  387. updateH2O2SensorData(m_context);
  388. /**
  389. * @brief D值
  390. */
  391. m_context.dvalue = getDisinfectionDValue(m_context.min_h2o2);
  392. if (zsteady_clock().elapsedTimeS(m_context.m_lastComputeDvalueTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
  393. m_context.m_lastComputeDvalueTp = zsteady_clock().now();
  394. //
  395. if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  396. m_context.m_nowLoglevel = computeNowLogLevel(m_context);
  397. computeRemainTime(m_context);
  398. }
  399. }
  400. if (m_context.m_state == kpreheat) {
  401. /**
  402. * @brief
  403. */
  404. processPreheatState(m_context);
  405. } else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  406. /**
  407. * @brief
  408. */
  409. processDisinfectionState(m_context);
  410. //
  411. if (m_context.m_remaintime <= 0 && m_context.m_nowLoglevel > (m_context.m_targetLoglevel + 0.01)) {
  412. m_context.m_remaintime = 0;
  413. m_context.m_nowLoglevel = m_context.m_targetLoglevel + 0.01;
  414. logger->info("disinfection finished {},but waitting for h2o2 to safe", m_context.m_disinfectionID);
  415. m_deviceIoControlService->sprayLiquidPump_close();
  416. usleep(1000 * 1000);
  417. m_deviceIoControlService->airCompressor_setState(false);
  418. usleep(1000 * 1000);
  419. m_deviceIoControlService->heartingPlate_setPower(false);
  420. m_context.m_state = kwait_for_h2o2_down;
  421. forcelog = true;
  422. }
  423. } else if (m_context.m_state == kwait_for_h2o2_down) {
  424. /**
  425. * @brief h2o2浓度下降
  426. */
  427. logger->info("waitting for h2o2 concentration to safe value {}=>{}", m_context.min_h2o2, 1);
  428. if (m_context.min_h2o2 < 1) {
  429. logger->info("h2o2 concentration to safe value");
  430. breakflag = true;
  431. forcelog = true;
  432. m_context.m_state = kfinished;
  433. }
  434. } else {
  435. ZCHECK(false, "state error");
  436. }
  437. if (forcelog || zsteady_clock().elapsedTimeS(m_context.m_lastlogTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
  438. m_context.m_lastlogTp = zsteady_clock().now();
  439. dumpDisinfectionLogsToCSV(m_context);
  440. log(m_context);
  441. }
  442. }
  443. void DisinfectionCtrlService::changeDisinfectionParameter(int injection_pump_speed, //
  444. int stoped_gs, //
  445. int continued_gs, //
  446. int stoped_satur, //
  447. int continued_satur, //
  448. int stoped_humi, //
  449. int continued_humi) {
  450. lock_guard<recursive_mutex> lock(lock_);
  451. // logger->info("changeInjectionPumpSpeed {}=>{}", m_context.injection_pump_speed, speed);
  452. // m_context.injection_pump_speed = speed;
  453. m_context.injection_pump_speed = injection_pump_speed;
  454. m_context.stoped_gs = stoped_gs;
  455. m_context.continued_gs = continued_gs;
  456. m_context.stoped_satur = stoped_satur;
  457. m_context.continued_satur = continued_satur;
  458. m_context.stoped_humi = stoped_humi;
  459. m_context.continued_humi = continued_humi;
  460. m_context.injection_pump_speed_changed = true;
  461. logger->info("changeDisinfectionParameter {} {} {} {} {} {} {}", injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi);
  462. }
  463. void DisinfectionCtrlService::startDisinfection(int loglevel, //
  464. int injection_pump_speed, //
  465. int stoped_gs, //
  466. int continued_gs, //
  467. int stoped_satur, //
  468. int continued_satur, //
  469. int stoped_humi, //
  470. int continued_humi //
  471. ) {
  472. lock_guard<recursive_mutex> lock(lock_);
  473. /**
  474. * @TODO
  475. * 湿湿
  476. */
  477. if (m_disinfectionThread) {
  478. stopDisinfection();
  479. }
  480. initContext(m_context, loglevel, injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi);
  481. m_disinfectionThread.reset(new Thread("m_disinfectionThread", [this]() {
  482. ThisThread thisThread;
  483. while (!thisThread.getExitFlag()) {
  484. thisThread.sleepForMs(1000);
  485. bool breakflag = false;
  486. disinfectionLoop(breakflag);
  487. if (breakflag) {
  488. break;
  489. }
  490. }
  491. printfDisinfectionContextResult();
  492. //
  493. finishDisinfection(m_context);
  494. }));
  495. //
  496. }
  497. void DisinfectionCtrlService::printfDisinfectionContextResult() {
  498. /**
  499. * @brief
  500. * = = = = = = = = = = = = = = =
  501. *
  502. * XXXXX
  503. * 2021-03-10 10:00:00
  504. * 2021-03-10 10:00:00
  505. * 01:59
  506. * LOG 6
  507. * LOG 6
  508. * = = = = = = = = = = = = = = =
  509. *
  510. */
  511. auto dio = m_deviceIoControlService;
  512. auto ds = GET_SERVICE(DeviceStateService);
  513. m_context.m_endtp_str = getTime();
  514. int totaltime = zsteady_clock().elapsedTimeS(m_context.m_starttp) / 60;
  515. dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
  516. dio->printerPrintf(fmt::format(" 全思美特\n"));
  517. dio->printerPrintf(fmt::format("操作人 {}\n", ds->getLoginUid()));
  518. dio->printerPrintf(fmt::format("开始时间 {}\n", m_context.m_starttp_str));
  519. dio->printerPrintf(fmt::format("结束时间 {}\n", m_context.m_endtp_str));
  520. dio->printerPrintf(fmt::format("总耗时 {}:{}\n", totaltime / 60, totaltime % 60));
  521. dio->printerPrintf(fmt::format("目标LOG {}\n", (int)m_context.m_targetLoglevel));
  522. dio->printerPrintf(fmt::format("实际LOG {}\n", (int)m_context.m_nowLoglevel));
  523. dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
  524. dio->printerPrintf(fmt::format("\n"));
  525. dio->printerPrintf(fmt::format("\n"));
  526. dio->printerPrintf(fmt::format("\n"));
  527. // getTime
  528. // dio->printerPrintf(fmt::format("开始时间 {}\n", zsteady_clock().formatTime(m_context.m_starttp)));
  529. }
  530. int DisinfectionCtrlService::getDisinfectionWorkState() { return m_context.m_state; }
  531. void DisinfectionCtrlService::stopDisinfection() {
  532. lock_guard<recursive_mutex> lock(lock_);
  533. if (m_disinfectionThread) {
  534. m_disinfectionThread->join();
  535. m_disinfectionThread = nullptr;
  536. }
  537. m_context.m_state = kfinished;
  538. m_disinfectionWorkState = 0;
  539. }
  540. int32_t DisinfectionCtrlService::getEstimatedRemainingTimeS() {
  541. lock_guard<recursive_mutex> lock(lock_);
  542. if (m_context.m_state == kpreheat) {
  543. return getPreHeatRaminTimeS();
  544. } else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
  545. if (m_context.dvalue > 0) {
  546. return m_context.m_remaintime;
  547. } else {
  548. return -1;
  549. }
  550. } else {
  551. return 0;
  552. }
  553. }
  554. int32_t DisinfectionCtrlService::getPreHeatRaminTimeS() {
  555. lock_guard<recursive_mutex> lock(lock_);
  556. int32_t remaintime = 0;
  557. if (m_context.m_state == kpreheat) {
  558. remaintime = m_context.pre_heat_time_s - zsteady_clock().elapsedTimeS(m_context.m_starttp);
  559. if (remaintime < 0) {
  560. remaintime = 0;
  561. }
  562. return remaintime;
  563. } else {
  564. return 0;
  565. }
  566. }
  567. string DisinfectionCtrlService::getDisinfectionID() {
  568. lock_guard<recursive_mutex> lock(lock_);
  569. return m_context.m_disinfectionID;
  570. }
  571. bool DisinfectionCtrlService::isPreheatState() {
  572. lock_guard<recursive_mutex> lock(lock_);
  573. return m_context.m_state == kpreheat;
  574. }
  575. int DisinfectionCtrlService::getReplenishingFluidsWorkState() { return m_replenishingFluidsWorkState; }
  576. int DisinfectionCtrlService::getDrainingWorkState() { return m_drainingWorkState; }
  577. /*******************************************************************************
  578. * // 加液 *
  579. *******************************************************************************/
  580. /**
  581. * @brief
  582. *
  583. * @param stopatg
  584. */
  585. void DisinfectionCtrlService::startReplenishingFluids(int stopatg) {
  586. lock_guard<recursive_mutex> lock(lock_);
  587. if (m_disinfectionThread) {
  588. m_disinfectionThread->join();
  589. m_disinfectionThread = nullptr;
  590. }
  591. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  592. int maxg = DISINFECTANT_BUCKET_CAPACITY;
  593. if (stopatg > maxg) {
  594. logger->warn("start Replenishing fail, stopatg {} > maxg {}", stopatg, maxg);
  595. stopatg = maxg;
  596. }
  597. if (nowvolume > stopatg) {
  598. logger->warn("start Replenishing fail, nowvolume {} > stopatg {}", nowvolume, stopatg);
  599. return;
  600. }
  601. m_disinfectionThread.reset(new Thread("disinfectionThread", [this, stopatg]() {
  602. ThisThread thisThread;
  603. m_deviceIoControlService->replenishingFluidsPump_open();
  604. logger->info("startReplenishingFluids {}g", stopatg);
  605. while (!thisThread.getExitFlag()) {
  606. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  607. logger->info("replenishingFluids {}g", nowvolume);
  608. if (nowvolume > stopatg) {
  609. break;
  610. }
  611. if (nowvolume > MAX_VOLUME) {
  612. logger->warn("replenishingFluids reach full level {}g", nowvolume);
  613. break;
  614. }
  615. thisThread.sleepForMs(1000);
  616. }
  617. logger->info("stopReplenishingFluids");
  618. // replenishingFluidsPump_close();
  619. m_deviceIoControlService->replenishingFluidsPump_close();
  620. m_replenishingFluidsWorkState = 0;
  621. }));
  622. //
  623. m_replenishingFluidsWorkState = 1;
  624. logger->info("startReplenishingFluids ");
  625. }
  626. /**
  627. * @brief
  628. *
  629. */
  630. void DisinfectionCtrlService::stopReplenishingFluids() {
  631. lock_guard<recursive_mutex> lock(lock_);
  632. if (m_disinfectionThread) {
  633. m_disinfectionThread->join();
  634. m_disinfectionThread = nullptr;
  635. }
  636. logger->info("stopReplenishingFluids");
  637. // replenishingFluidsPump_close();
  638. m_deviceIoControlService->replenishingFluidsPump_close();
  639. m_replenishingFluidsWorkState = 0;
  640. }
  641. /*******************************************************************************
  642. * *
  643. *******************************************************************************/
  644. /**
  645. * @brief
  646. *
  647. */
  648. void DisinfectionCtrlService::startDraining() {
  649. lock_guard<recursive_mutex> lock(lock_);
  650. if (m_disinfectionThread) {
  651. m_disinfectionThread->join();
  652. m_disinfectionThread = nullptr;
  653. }
  654. m_disinfectionThread.reset(new Thread("disinfectionThread", [this]() {
  655. ThisThread thisThread;
  656. m_deviceIoControlService->drainingPump_open();
  657. logger->info("startDraining ");
  658. auto startdrainingtime = zsteady_clock().now();
  659. zsteady_tp volumeReachZeroTime;
  660. bool volumeReachZeroFlag = false;
  661. while (!thisThread.getExitFlag()) {
  662. int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g();
  663. logger->info("draining remain {} g", nowvolume);
  664. if (!volumeReachZeroFlag && nowvolume == 0) {
  665. volumeReachZeroTime = zsteady_clock().now();
  666. volumeReachZeroFlag = true;
  667. }
  668. if (volumeReachZeroFlag) {
  669. logger->info("stopDraining after {} s", 30 - zsteady_clock().elapsedTimeS(volumeReachZeroTime));
  670. if (zsteady_clock().elapsedTimeS(volumeReachZeroTime) > 30) {
  671. break;
  672. }
  673. }
  674. thisThread.sleepForMs(1000);
  675. }
  676. logger->info("stopDraining");
  677. // replenishingFluidsPump_close();
  678. m_deviceIoControlService->drainingPump_close();
  679. m_drainingWorkState = 0;
  680. }));
  681. logger->info("startDraining");
  682. // drainingPump_open();
  683. m_drainingWorkState = 1;
  684. }
  685. /**
  686. * @brief
  687. */
  688. void DisinfectionCtrlService::stopDraining() {
  689. lock_guard<recursive_mutex> lock(lock_);
  690. if (m_disinfectionThread) {
  691. m_disinfectionThread->join();
  692. m_disinfectionThread = nullptr;
  693. }
  694. logger->info("stopDraining");
  695. m_drainingWorkState = 0;
  696. // drainingPump_close();
  697. m_deviceIoControlService->drainingPump_close();
  698. }
  699. void DisinfectionCtrlService::updateH2O2SensorData(DisinfectionContext& context) {
  700. auto& cx = context;
  701. for (size_t i = 0; i < MAX_EXT_H2O2_SENSOR_NUM; i++) {
  702. cx.h2o2[i] = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(i);
  703. }
  704. for (size_t i = 0; i < MAX_EXT_H2O2_SENSOR_NUM; i++) {
  705. cx.humid[i] = m_deviceIoControlService->H2O2Sensor_readHumid(i);
  706. }
  707. for (size_t i = 0; i < MAX_EXT_H2O2_SENSOR_NUM; i++) {
  708. cx.temp[i] = m_deviceIoControlService->H2O2Sensor_readTemperature(i);
  709. }
  710. for (size_t i = 0; i < MAX_EXT_H2O2_SENSOR_NUM; i++) {
  711. cx.saturation[i] = m_deviceIoControlService->H2O2Sensor_readSaturation(i);
  712. }
  713. cx.min_h2o2 = cx.h2o2[0];
  714. cx.max_h2o2 = cx.h2o2[0];
  715. cx.max_humid = cx.humid[0];
  716. cx.max_saturation = cx.saturation[0];
  717. for (size_t i = 0; i < MAX_EXT_H2O2_SENSOR_NUM; i++) {
  718. if (cx.h2o2[i] < cx.min_h2o2) {
  719. cx.min_h2o2 = cx.h2o2[i];
  720. }
  721. if (cx.h2o2[i] > cx.max_h2o2) {
  722. cx.max_h2o2 = cx.h2o2[i];
  723. }
  724. if (cx.humid[i] > cx.max_humid) {
  725. cx.max_humid = cx.humid[i];
  726. }
  727. if (cx.saturation[i] > cx.max_saturation) {
  728. cx.max_saturation = cx.saturation[i];
  729. }
  730. }
  731. if (cx.max_h2o2 < 0) cx.max_h2o2 = 0;
  732. if (cx.min_h2o2 < 0) cx.min_h2o2 = 0;
  733. if (cx.max_humid < 0) cx.max_humid = 0;
  734. if (cx.max_saturation < 0) cx.max_saturation = 0;
  735. }