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.

705 lines
26 KiB

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