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.

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