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.

811 lines
30 KiB

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