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.

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