From 436d60204db24354714a6b7a7228d823eb330922 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Sat, 18 May 2024 11:21:07 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/cmds/device_state_cmd_impl.cpp | 59 +- api/cmds/device_state_cmd_impl.hpp | 2 + api/cmds/disinfection_cmd_impl.cpp | 32 +- service/disfection_ctl/add_liquid_service.cpp | 92 +++ service/disfection_ctl/add_liquid_service.hpp | 76 ++ service/disfection_ctl/disinfection_service.cpp | 864 +++++++++++++++++++ service/disfection_ctl/disinfection_service.hpp | 145 ++++ service/disfection_ctl/disinfection_state.hpp | 143 ++++ service/disfection_ctl/drain_liquid_service.cpp | 102 +++ service/disfection_ctl/drain_liquid_service.hpp | 82 ++ service/disinfection_ctl_service.cpp | 1010 +---------------------- service/disinfection_ctl_service.hpp | 113 +-- service/disinfection_printer_service.hpp | 2 +- service/disinfection_state.hpp | 143 ---- 14 files changed, 1617 insertions(+), 1248 deletions(-) create mode 100644 service/disfection_ctl/add_liquid_service.cpp create mode 100644 service/disfection_ctl/add_liquid_service.hpp create mode 100644 service/disfection_ctl/disinfection_service.cpp create mode 100644 service/disfection_ctl/disinfection_service.hpp create mode 100644 service/disfection_ctl/disinfection_state.hpp create mode 100644 service/disfection_ctl/drain_liquid_service.cpp create mode 100644 service/disfection_ctl/drain_liquid_service.hpp delete mode 100644 service/disinfection_state.hpp diff --git a/api/cmds/device_state_cmd_impl.cpp b/api/cmds/device_state_cmd_impl.cpp index f42defb..fcd6427 100644 --- a/api/cmds/device_state_cmd_impl.cpp +++ b/api/cmds/device_state_cmd_impl.cpp @@ -72,29 +72,29 @@ void DeviceStateCmdImpl::getState(json& cmd, json& receipt) { * disinfectionState * *******************************************************************************/ #if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - receipt["state"]["replenishingFluidsWorkState"] = m_disinfectionCtrlService->getReplenishingFluidsWorkState(); - receipt["state"]["drainingWorkState"] = m_disinfectionCtrlService->getDrainingWorkState(); + receipt["state"]["replenishingFluidsWorkState"] = m_disinfectionCtrlService->getAddLiquidService()->getReplenishingFluidsWorkState(); + receipt["state"]["drainingWorkState"] = m_disinfectionCtrlService->getDrainLiquidService()->getDrainingWorkState(); #elif (defined PROJECT_TYPE_DRAW_BAR_BOX) #else #endif - receipt["state"]["disinfectionWorkState"] = m_disinfectionCtrlService->getDisinfectionWorkState(); + receipt["state"]["disinfectionWorkState"] = m_disinfectionCtrlService->getDisinfectionService()->getDisinfectionWorkState(); /** * @brief 历史接口 */ - receipt["state"]["preHeat"] = m_disinfectionCtrlService->isPreheatState(); - receipt["state"]["preHeatRaminTimeS"] = m_disinfectionCtrlService->getPreHeatRaminTimeS(); // 预热剩余时间 - receipt["state"]["estimatedRemainingTimeS"] = m_disinfectionCtrlService->getEstimatedRemainingTimeS(); - receipt["state"]["disinfection_id"] = m_disinfectionCtrlService->getDisinfectionID(); + receipt["state"]["preHeat"] = m_disinfectionCtrlService->getDisinfectionService()->isPreheatState(); + receipt["state"]["preHeatRaminTimeS"] = m_disinfectionCtrlService->getDisinfectionService()->getPreHeatRaminTimeS(); // 预热剩余时间 + receipt["state"]["estimatedRemainingTimeS"] = m_disinfectionCtrlService->getDisinfectionService()->getEstimatedRemainingTimeS(); + receipt["state"]["disinfection_id"] = m_disinfectionCtrlService->getDisinfectionService()->getDisinfectionID(); // 消毒状态 - receipt["state"]["disinfectionState"]["id"] = m_disinfectionCtrlService->getDisinfectionID(); - receipt["state"]["disinfectionState"]["estimatedRemainingTimeS"] = m_disinfectionCtrlService->getEstimatedRemainingTimeS(); - receipt["state"]["disinfectionState"]["workState"] = m_disinfectionCtrlService->getDisinfectionWorkState(); - receipt["state"]["disinfectionState"]["preHeat"] = m_disinfectionCtrlService->isPreheatState(); - receipt["state"]["disinfectionState"]["preHeatRaminTimeS"] = m_disinfectionCtrlService->getPreHeatRaminTimeS(); // 预热剩余时间 - receipt["state"]["disinfectionState"]["nowlog"] = m_disinfectionCtrlService->m_context.state_now_loglevel; - receipt["state"]["disinfectionState"]["targetlog"] = m_disinfectionCtrlService->m_context.cfg_targetLoglevel; - receipt["state"]["disinfectionState"]["dvalue"] = m_disinfectionCtrlService->m_context.state_dvalue; + receipt["state"]["disinfectionState"]["id"] = m_disinfectionCtrlService->getDisinfectionService()->getDisinfectionID(); + receipt["state"]["disinfectionState"]["estimatedRemainingTimeS"] = m_disinfectionCtrlService->getDisinfectionService()->getEstimatedRemainingTimeS(); + receipt["state"]["disinfectionState"]["workState"] = m_disinfectionCtrlService->getDisinfectionService()->getDisinfectionWorkState(); + receipt["state"]["disinfectionState"]["preHeat"] = m_disinfectionCtrlService->getDisinfectionService()->isPreheatState(); + receipt["state"]["disinfectionState"]["preHeatRaminTimeS"] = m_disinfectionCtrlService->getDisinfectionService()->getPreHeatRaminTimeS(); // 预热剩余时间 + receipt["state"]["disinfectionState"]["nowlog"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.state_now_loglevel; + receipt["state"]["disinfectionState"]["targetlog"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.cfg_targetLoglevel; + receipt["state"]["disinfectionState"]["dvalue"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.state_dvalue; /******************************************************************************* * sensor * @@ -103,21 +103,27 @@ void DeviceStateCmdImpl::getState(json& cmd, json& receipt) { /******************************************************************************* * disinfectionConfig * *******************************************************************************/ - receipt["disinfectionConfig"]["loglevel"] = m_disinfectionCtrlService->m_context.cfg_targetLoglevel; - receipt["disinfectionConfig"]["injection_pump_speed"] = m_disinfectionCtrlService->m_context.injection_pump_speed; - receipt["disinfectionConfig"]["stoped_gs"] = m_disinfectionCtrlService->m_context.stoped_gs; - receipt["disinfectionConfig"]["continued_gs"] = m_disinfectionCtrlService->m_context.continued_gs; - receipt["disinfectionConfig"]["stoped_satur"] = m_disinfectionCtrlService->m_context.stoped_satur; - receipt["disinfectionConfig"]["continued_satur"] = m_disinfectionCtrlService->m_context.continued_satur; - receipt["disinfectionConfig"]["stoped_humi"] = m_disinfectionCtrlService->m_context.stoped_humi; - receipt["disinfectionConfig"]["continued_humi"] = m_disinfectionCtrlService->m_context.continued_humi; + receipt["disinfectionConfig"]["loglevel"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.cfg_targetLoglevel; + receipt["disinfectionConfig"]["injection_pump_speed"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.injection_pump_speed; + receipt["disinfectionConfig"]["stoped_gs"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_gs; + receipt["disinfectionConfig"]["continued_gs"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_gs; + receipt["disinfectionConfig"]["stoped_satur"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_satur; + receipt["disinfectionConfig"]["continued_satur"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_satur; + receipt["disinfectionConfig"]["stoped_humi"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_humi; + receipt["disinfectionConfig"]["continued_humi"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_humi; + +#if (defined PROJECT_TYPE_DRAW_BAR_BOX) + receipt["subboardstate"]["extChannelCtrlBoard"]["online"] = m_deviceIoControlService->DBDB__extValBoardIsOnline(); +#endif + return; } - +#if (defined PROJECT_TYPE_DRAW_BAR_BOX) void DeviceStateCmdImpl::DeviceState__getDBDBExtChannelCtrlComponentState(json& cmd, json& receipt) { receipt["ack"]["online"] = m_deviceIoControlService->DBDB__extValBoardIsOnline(); return; } +#endif void DeviceStateCmdImpl::initialize() { GET_TO_SERVICE(m_msgProcesser); @@ -134,6 +140,11 @@ void DeviceStateCmdImpl::initialize() { m_msgProcesser->registerMsgProcesser("getState", std::bind(&DeviceStateCmdImpl::getState, this, std::placeholders::_1, std::placeholders::_2)); +#if (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_msgProcesser->registerMsgProcesser("DeviceState__getDBDBExtChannelCtrlComponentState", + std::bind(&DeviceStateCmdImpl::DeviceState__getDBDBExtChannelCtrlComponentState, this, std::placeholders::_1, std::placeholders::_2)); +#endif + m_reportThread.reset(new Thread("reportThread", [this]() { ThisThread thisThread; while (!thisThread.getExitFlag()) { diff --git a/api/cmds/device_state_cmd_impl.hpp b/api/cmds/device_state_cmd_impl.hpp index 2c759d6..8e467e5 100644 --- a/api/cmds/device_state_cmd_impl.hpp +++ b/api/cmds/device_state_cmd_impl.hpp @@ -34,7 +34,9 @@ class DeviceStateCmdImpl : public enable_shared_from_this { private: void getState(json& cmd, json& receipt); +#if (defined PROJECT_TYPE_DRAW_BAR_BOX) void DeviceState__getDBDBExtChannelCtrlComponentState(json& cmd, json& receipt); +#endif private: json createSensorDataJson(); diff --git a/api/cmds/disinfection_cmd_impl.cpp b/api/cmds/disinfection_cmd_impl.cpp index 2d341ba..9be66b5 100644 --- a/api/cmds/disinfection_cmd_impl.cpp +++ b/api/cmds/disinfection_cmd_impl.cpp @@ -15,13 +15,13 @@ void DisinfectionCmdImpl::startDisinfection(json& cmd, json& receipt) { return; } void DisinfectionCmdImpl::changeDisinfectionParameter(json& cmd, json& receipt) { - int injection_pump_speed = m_disinfectionCtrlService->m_context.injection_pump_speed; - int stoped_gs = m_disinfectionCtrlService->m_context.stoped_gs; - int continued_gs = m_disinfectionCtrlService->m_context.continued_gs; - int stoped_satur = m_disinfectionCtrlService->m_context.stoped_satur; - int continued_satur = m_disinfectionCtrlService->m_context.continued_satur; - int stoped_humi = m_disinfectionCtrlService->m_context.stoped_humi; - int continued_humi = m_disinfectionCtrlService->m_context.continued_humi; + int injection_pump_speed = m_disinfectionCtrlService->getDisinfectionService()->m_context.injection_pump_speed; + int stoped_gs = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_gs; + int continued_gs = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_gs; + int stoped_satur = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_satur; + int continued_satur = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_satur; + int stoped_humi = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_humi; + int continued_humi = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_humi; if (cmd.find("injection_pump_speed") != cmd.end()) { injection_pump_speed = jsonGet(cmd["injection_pump_speed"]); @@ -58,11 +58,13 @@ void DisinfectionCmdImpl::stopDisinfection(json& cmd, json& receipt) { void DisinfectionCmdImpl::startReplenishingFluids(json& cmd, json& receipt) { int16_t stopAt = jsonGet(cmd["stopAt"]); logger->info("startReplenishingFluids {}", stopAt); + // m_disinfectionCtrlService->startReplenishingFluids(stopAt); m_disinfectionCtrlService->startReplenishingFluids(stopAt); return; } void DisinfectionCmdImpl::stopReplenishingFluids(json& cmd, json& receipt) { logger->info("stopReplenishingFluids"); + // m_disinfectionCtrlService->stopReplenishingFluids(); m_disinfectionCtrlService->stopReplenishingFluids(); return; } @@ -112,14 +114,14 @@ void DisinfectionCmdImpl::getDisinfectionConfig(json& cmd, json& receipt) { /******************************************************************************* * disinfectionConfig * *******************************************************************************/ - receipt["disinfectionConfig"]["loglevel"] = m_disinfectionCtrlService->m_context.cfg_targetLoglevel; - receipt["disinfectionConfig"]["injection_pump_speed"] = m_disinfectionCtrlService->m_context.injection_pump_speed; - receipt["disinfectionConfig"]["stoped_gs"] = m_disinfectionCtrlService->m_context.stoped_gs; - receipt["disinfectionConfig"]["continued_gs"] = m_disinfectionCtrlService->m_context.continued_gs; - receipt["disinfectionConfig"]["stoped_satur"] = m_disinfectionCtrlService->m_context.stoped_satur; - receipt["disinfectionConfig"]["continued_satur"] = m_disinfectionCtrlService->m_context.continued_satur; - receipt["disinfectionConfig"]["stoped_humi"] = m_disinfectionCtrlService->m_context.stoped_humi; - receipt["disinfectionConfig"]["continued_humi"] = m_disinfectionCtrlService->m_context.continued_humi; + receipt["disinfectionConfig"]["loglevel"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.cfg_targetLoglevel; + receipt["disinfectionConfig"]["injection_pump_speed"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.injection_pump_speed; + receipt["disinfectionConfig"]["stoped_gs"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_gs; + receipt["disinfectionConfig"]["continued_gs"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_gs; + receipt["disinfectionConfig"]["stoped_satur"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_satur; + receipt["disinfectionConfig"]["continued_satur"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_satur; + receipt["disinfectionConfig"]["stoped_humi"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.stoped_humi; + receipt["disinfectionConfig"]["continued_humi"] = m_disinfectionCtrlService->getDisinfectionService()->m_context.continued_humi; return; } diff --git a/service/disfection_ctl/add_liquid_service.cpp b/service/disfection_ctl/add_liquid_service.cpp new file mode 100644 index 0000000..43d01b2 --- /dev/null +++ b/service/disfection_ctl/add_liquid_service.cpp @@ -0,0 +1,92 @@ +#include "add_liquid_service.hpp" + +#include +#include + +#include "configs/gconfig.hpp" +#include "configs/project_setting.hpp" +#include "iflytop/components/uart_printer/uart_printer.hpp" +#include "iflytoplinuxsdk/src/iflytop/components/ziconv.hpp" +#include "service/device_state_service.hpp" + +// #define PROJECT_TYPE_LARGE_SPACE_DISINFECTION 1 // 大空间 +// #define PROJECT_TYPE_SMALL_SPACE_DISINFECTION 1 // 小空间 + +using namespace iflytop; +using namespace std; + +namespace iflytop { +extern bool g_in_test; +} + +AddLiquidService::AddLiquidService() {} +void AddLiquidService::initialize() { + GET_TO_SERVICE(m_deviceIoControlService); + GET_TO_SERVICE(m_dbService); + GET_TO_SERVICE(m_disinfectionLogsManager); + GET_TO_SERVICE(m_disinfectionPrinterService); +} +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + +/******************************************************************************* + * // 加液 * + *******************************************************************************/ +int AddLiquidService::getReplenishingFluidsWorkState() { return m_replenishingFluidsWorkState; } +void AddLiquidService::startReplenishingFluids(int stopatg) { + lock_guard lock(lock_); + if (m_disinfectionThread) { + m_disinfectionThread->join(); + m_disinfectionThread = nullptr; + } + int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); + + int maxg = DISINFECTANT_BUCKET_CAPACITY; + + if (stopatg > maxg) { + logger->warn("start Replenishing fail, stopatg {} > maxg {}", stopatg, maxg); + stopatg = maxg; + } + + if (nowvolume > stopatg) { + logger->warn("start Replenishing fail, nowvolume {} > stopatg {}", nowvolume, stopatg); + return; + } + + m_disinfectionThread.reset(new Thread("disinfectionThread", [this, stopatg]() { + ThisThread thisThread; + m_deviceIoControlService->replenishingFluidsPump_open(); + logger->info("startReplenishingFluids {}g", stopatg); + while (!thisThread.getExitFlag()) { + int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); + logger->info("replenishingFluids {}g", nowvolume); + if (nowvolume > stopatg) { + break; + } + + thisThread.sleepForMs(1000); + } + logger->info("stopReplenishingFluids"); + // replenishingFluidsPump_close(); + m_deviceIoControlService->replenishingFluidsPump_close(); + m_replenishingFluidsWorkState = 0; + })); + + // + m_replenishingFluidsWorkState = 1; + logger->info("startReplenishingFluids "); +} + +void AddLiquidService::stopReplenishingFluids() { + lock_guard lock(lock_); + if (m_disinfectionThread) { + m_disinfectionThread->join(); + m_disinfectionThread = nullptr; + } + + logger->info("stopReplenishingFluids"); + // replenishingFluidsPump_close(); + m_deviceIoControlService->replenishingFluidsPump_close(); + m_replenishingFluidsWorkState = 0; +} + +#endif diff --git a/service/disfection_ctl/add_liquid_service.hpp b/service/disfection_ctl/add_liquid_service.hpp new file mode 100644 index 0000000..99ce616 --- /dev/null +++ b/service/disfection_ctl/add_liquid_service.hpp @@ -0,0 +1,76 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db/db_service.hpp" +#include "disinfection_state.hpp" +#include "iflytop/components/zcanreceiver/zcanhost.hpp" +#include "iflytop/core/core.hpp" +#include "service/device_io_control_service.hpp" +#include "service/disinfection_logs_manager.hpp" +#include "service/disinfection_printer_service.hpp" +#include "utils/dvalue_computer.hpp" +#include "zservice_container/zservice_container.hpp" +/** + * @brief + * + * service: AddLiquidService + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; +class AddLiquidService : public enable_shared_from_this { + ENABLE_LOGGER(AddLiquidService); + + private: + recursive_mutex lock_; + + unique_ptr m_disinfectionThread; + shared_ptr m_deviceIoControlService; + shared_ptr m_dbService; + shared_ptr m_disinfectionLogsManager; + shared_ptr m_disinfectionPrinterService; + DValueComputer m_dvalueComputer; + + int m_disinfectionWorkState = 0; + int m_replenishingFluidsWorkState = 0; + int m_drainingWorkState = 0; // 消毒工作状态,0:未工作,1:工作中 + + public: + DisinfectionContext m_context; + + public: + AddLiquidService(); + + public: + void initialize(); +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + + /******************************************************************************* + * 加液 * + *******************************************************************************/ + void startReplenishingFluids(int stopatg); + void stopReplenishingFluids(); + int getReplenishingFluidsWorkState(); +#endif +}; +} // namespace iflytop \ No newline at end of file diff --git a/service/disfection_ctl/disinfection_service.cpp b/service/disfection_ctl/disinfection_service.cpp new file mode 100644 index 0000000..4d60c3e --- /dev/null +++ b/service/disfection_ctl/disinfection_service.cpp @@ -0,0 +1,864 @@ +#include "disinfection_service.hpp" + +#include +#include + +#include "configs/gconfig.hpp" +#include "configs/project_setting.hpp" +#include "iflytop/components/uart_printer/uart_printer.hpp" +#include "iflytoplinuxsdk/src/iflytop/components/ziconv.hpp" +#include "service/device_state_service.hpp" + +// #define PROJECT_TYPE_LARGE_SPACE_DISINFECTION 1 // 大空间 +// #define PROJECT_TYPE_SMALL_SPACE_DISINFECTION 1 // 小空间 + +using namespace iflytop; +using namespace std; +#define DVALUE_COMPUTEPERIOD_TIME_S (10.0) +#define DUMP_LOG_PERIOD (5 * 60.0) +#define MAX_VOLUME (5000) + +namespace iflytop { +extern bool g_in_test; + +} + +static string formattimeS(int sec) { + if (sec >= 0) { + return fmt::format("{:0>2}:{:0>2}:{:0>2}", sec / 3600, sec % 3600 / 60, sec % 60); + } else { + return fmt::format("--:--:--"); + } +} + +static string getTime() { + struct tm tm = {0}; + + time_t t = time(nullptr); + localtime_r(&t, &tm); + return fmt::format("{:0>4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", tm.tm_year + 1900, // + tm.tm_mon + 1, // + tm.tm_mday, // + tm.tm_hour, // + tm.tm_min, tm.tm_sec); +} + +static bool zfeq(float a, float b, float eps = 0.01) { + if (fabs(a - b) < eps) { + return true; + } + return false; +} + +DisinfectionService::DisinfectionService() {} +void DisinfectionService::initialize() { + GET_TO_SERVICE(m_deviceIoControlService); + GET_TO_SERVICE(m_dbService); + GET_TO_SERVICE(m_disinfectionLogsManager); + GET_TO_SERVICE(m_disinfectionPrinterService); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->drainingPump_close(); + m_deviceIoControlService->replenishingFluidsPump_close(); + m_deviceIoControlService->sprayLiquidPump_close(); + + m_deviceIoControlService->heartingPlate_setPower(false); + m_deviceIoControlService->airBlower_setState(false); + m_deviceIoControlService->airCompressor_setState(false); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_context.beforeDisinfectantVolume_g = 0; +#else +#endif + + m_dvalueComputer.initialize(); +} + +string DisinfectionService::createDisinfectionID() { + struct tm tm = {0}; + + time_t t = time(nullptr); + if (t == -1) { + logger->error("time(nullptr) failed"); + exit(-1); + } + struct tm* tmp = localtime_r(&t, &tm); + if (!tmp) { + logger->error("localtime_r failed"); + exit(-1); + } + // tm = *utctime::tm_increment_hour(&tm, 8); + // logger->info("trace sendmsg_startCapture {}:{}", __FILE__, __LINE__); + return fmt::format("{:0>4}-{:0>2}{:0>2}-{:0>2}{:0>2}{:0>2}", tm.tm_year + 1900, // + tm.tm_mon + 1, // + tm.tm_mday, // + tm.tm_hour, // + tm.tm_min, tm.tm_sec); +} + +float DisinfectionService::getDisinfectionDValue(float ppm) { // + return m_dvalueComputer.computeDValue(ppm); +} +float DisinfectionService::computeNowLogLevel(DisinfectionContext& context) { + float dvalue = context.state_dvalue; + if (dvalue > 0) { + /** + * @brief 计算 state_now_loglevel + */ + return context.state_now_loglevel + DVALUE_COMPUTEPERIOD_TIME_S / (dvalue * 60); + } + return context.state_now_loglevel; +} + +void DisinfectionService::computeRemainTime(DisinfectionContext& context) { + /** + * @brief 计算Dvalue + */ + float dvalue = context.state_dvalue; + + if (dvalue > 0) { + /** + * @brief 计算 state_now_loglevel + */ + if (context.cfg_targetLoglevel >= context.state_now_loglevel) { + context.state_remaintime = (context.cfg_targetLoglevel - context.state_now_loglevel) * (dvalue * 60); + } else { + context.state_remaintime = 0; + } + } else { + // + } + + logger->info("computeRemainTime minh2o2 {} dvalue {}", context.min_h2o2, dvalue); +} + +shared_ptr DisinfectionService::createCSVLogger(string log_file_name) { + shared_ptr _logger = m_disinfectionLogsManager->createNewLogger(log_file_name); +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) + + _logger->write( + fmt::format("{}," + " {} , {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {}" + "\n", + ZIconv::noChange("时间"), // + ZIconv::noChange("仓内-气化过氧化氢浓度"), ZIconv::noChange("仓内-温度"), ZIconv::noChange("仓内-相对湿度"), ZIconv::noChange("仓内-相对饱和度"), // + ZIconv::noChange("环境1-气化过氧化氢浓度"), ZIconv::noChange("环境1-温度"), ZIconv::noChange("环境1-相对湿度"), ZIconv::noChange("环境1-相对饱和度"), // + ZIconv::noChange("环境2-气化过氧化氢浓度"), ZIconv::noChange("环境2-温度"), ZIconv::noChange("环境2-相对湿度"), ZIconv::noChange("环境2-相对饱和度"), // + ZIconv::noChange("D值"), ZIconv::noChange("当前LOG"), ZIconv::noChange("目标LOG"), // + ZIconv::noChange("加热器电源"), ZIconv::noChange("风机电源"), ZIconv::noChange("空压机电源"), ZIconv::noChange("喷液泵(g/min)"), // + ZIconv::noChange("消毒剩余剂量(g)"), ZIconv::noChange("剩余时间(s)"))); +#endif + +#ifdef PROJECT_TYPE_PIPE_DISINFECTION + + _logger->write( + fmt::format(" {} ," + " {} , {} , {} , {} ," + " {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} " + "\n", + ZIconv::noChange("时间"), // + ZIconv::noChange("仓内-气化过氧化氢浓度"), ZIconv::noChange("仓内-温度"), ZIconv::noChange("仓内-相对湿度"), ZIconv::noChange("仓内-相对饱和度"), // + ZIconv::noChange("D值"), ZIconv::noChange("当前LOG"), ZIconv::noChange("目标LOG"), // + ZIconv::noChange("加热器电源"), ZIconv::noChange("风机电源"), ZIconv::noChange("空压机电源"), ZIconv::noChange("喷液泵(g/min)"), // + ZIconv::noChange("消毒剩余剂量(g)"), ZIconv::noChange("剩余时间(s)"))); +#endif + return _logger; +} + +void DisinfectionService::dumpDisinfectionLogsToCSV(DisinfectionContext& context) { +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) + + static_assert(MAX_H2O2_SENSOR_NUM == 3, "MAX_H2O2_SENSOR_NUM must be 3"); + + auto& cx = context; + string h2o2str[MAX_H2O2_SENSOR_NUM]; + string tempstr[MAX_H2O2_SENSOR_NUM]; + string humidstr[MAX_H2O2_SENSOR_NUM]; + string satstr[MAX_H2O2_SENSOR_NUM]; + + for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + h2o2str[i] = fmt::format("{}", cx.h2o2[i]); + tempstr[i] = fmt::format("{}", cx.temp[i]); + humidstr[i] = fmt::format("{}", cx.humid[i]); + satstr[i] = fmt::format("{}", cx.saturation[i]); + } + + for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + if (cx.h2o2[i] < 0) h2o2str[i] = "N/A"; + if (cx.temp[i] < 0) tempstr[i] = "N/A"; + if (cx.humid[i] < 0) humidstr[i] = "N/A"; + if (cx.saturation[i] < 0) satstr[i] = "N/A"; + } + + auto ds = m_deviceIoControlService; + float dvalue = 0; + if (m_context.state_dvalue <= 0) { + dvalue = 0; + } else { + dvalue = m_context.state_dvalue; + } + + int remaintime = getEstimatedRemainingTimeS(); + + context.csvlogger->write( + fmt::format(" {} ," + " {} , {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} " + "\n", + getTime(), // + h2o2str[0], tempstr[0], humidstr[0], satstr[0], // + h2o2str[1], tempstr[1], humidstr[1], satstr[1], // + h2o2str[2], tempstr[2], humidstr[2], satstr[2], // + (int32_t)dvalue, (int32_t)m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // + ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // + m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); +#endif + +#ifdef PROJECT_TYPE_PIPE_DISINFECTION + + static_assert(MAX_H2O2_SENSOR_NUM == 1, "MAX_H2O2_SENSOR_NUM must be 1"); + + auto& cx = context; + string h2o2str[MAX_H2O2_SENSOR_NUM]; + string tempstr[MAX_H2O2_SENSOR_NUM]; + string humidstr[MAX_H2O2_SENSOR_NUM]; + string satstr[MAX_H2O2_SENSOR_NUM]; + + for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + h2o2str[i] = fmt::format("{}", cx.h2o2[i]); + tempstr[i] = fmt::format("{}", cx.temp[i]); + humidstr[i] = fmt::format("{}", cx.humid[i]); + satstr[i] = fmt::format("{}", cx.saturation[i]); + } + + for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + if (cx.h2o2[i] < 0) h2o2str[i] = "N/A"; + if (cx.temp[i] < 0) tempstr[i] = "N/A"; + if (cx.humid[i] < 0) humidstr[i] = "N/A"; + if (cx.saturation[i] < 0) satstr[i] = "N/A"; + } + + auto ds = m_deviceIoControlService; + float dvalue = 0; + if (m_context.state_dvalue <= 0) { + dvalue = 0; + } else { + dvalue = m_context.state_dvalue; + } + + int remaintime = getEstimatedRemainingTimeS(); + + context.csvlogger->write( + fmt::format(" {} ," + " {} , {} , {} , {} ," + " {} , {} , {} ," + " {} , {} , {} , {} ," + " {} , {} " + "\n", + getTime(), // + h2o2str[0], tempstr[0], humidstr[0], satstr[0], // + (int32_t)dvalue, (int32_t)m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // + ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // + m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); + +#endif +} + +void DisinfectionService::pushDisinfectionPrinterTask(DisinfectionContext& context) { // + shared_ptr task = make_shared(); + auto ds = GET_SERVICE(DeviceStateService); + auto dio = m_deviceIoControlService; + + task->start_tp = context.start_tp; + task->complete_tp = context.complete_tp; + task->stateSnapshotList = context.stateSnapshotList; + task->disinfectantUsage = context.beforeDisinfectantVolume_g - context.afterDisinfectantVolume_g; + task->disinfection_id = context.m_disinfectionID; + task->usr = ds->getLoginUid(); + + task->targetLog = context.cfg_targetLoglevel; + task->actualLog = context.state_now_loglevel; + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + task->disinfectantVolume = dio->getDisinfectantVolume_g(); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + task->disinfectantVolume = 0; + +#else +#endif + + m_disinfectionPrinterService->pushPrintTask(task); +} + +void DisinfectionService::log(DisinfectionContext& context) { +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) + + auto& cx = context; + auto ds = m_deviceIoControlService; + float dvalue = 0; + if (m_context.state_dvalue <= 0) { + dvalue = 0; + } else { + dvalue = m_context.state_dvalue; + } + + int remaintime = getEstimatedRemainingTimeS(); + + logger->info( + fmt::format("{}," + "s0({},{},{},{})," + "s1({},{},{},{})," + "s2({},{},{},{})," + "min_h2o2:{},max_h2o2:{},max_hum:{},max_sa:{}," + "dv:{},log:{},tlog:{}," + "h:{},airB:{},airC:{},pump:{}," + "g:{},remainS:{}" + "\n", + getTime(), // + cx.h2o2[0], cx.temp[0], cx.humid[0], cx.saturation[0], // + cx.h2o2[1], cx.temp[1], cx.humid[1], cx.saturation[1], // + cx.h2o2[2], cx.temp[2], cx.humid[2], cx.saturation[2], // + m_context.min_h2o2, m_context.max_h2o2, m_context.max_humid, m_context.max_saturation, // + (int32_t)dvalue, m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // + ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // + m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); +#endif +#ifdef PROJECT_TYPE_PIPE_DISINFECTION + auto& cx = context; + auto ds = m_deviceIoControlService; + float dvalue = 0; + if (m_context.state_dvalue <= 0) { + dvalue = 0; + } else { + dvalue = m_context.state_dvalue; + } + + int remaintime = getEstimatedRemainingTimeS(); + + logger->info( + fmt::format("{}," + "s0({},{},{},{})," + "min_h2o2:{},max_h2o2:{},max_hum:{},max_sa:{}," + "dv:{},log:{},tlog:{}," + "h:{},airB:{},airC:{},pump:{}," + "g:{},remainS:{}" + "\n", + getTime(), // + cx.h2o2[0], cx.temp[0], cx.humid[0], cx.saturation[0], // + m_context.min_h2o2, m_context.max_h2o2, m_context.max_humid, m_context.max_saturation, // + (int32_t)dvalue, m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // + ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // + m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); +#endif +} + +/******************************************************************************* + * WORK * + *******************************************************************************/ + +void DisinfectionService::initContext(DisinfectionContext& context, // + int loglevel, // + float injection_pump_speed, // + float stoped_gs, // + float continued_gs, // + float stoped_satur, // + float continued_satur, // + float stoped_humi, // + float continued_humi // +) { + context.m_disinfectionID = createDisinfectionID(); + context.pre_heat_time_s = m_dbService->getSettingVal("pre_heat_time_s"); + context.stoped_gs = stoped_gs; + context.continued_gs = continued_gs; + context.stoped_satur = stoped_satur; + context.continued_satur = continued_satur; + context.stoped_humi = stoped_humi; + context.continued_humi = continued_humi; + context.injection_pump_speed = injection_pump_speed; + context.injection_pump_speed_changed = true; + + if (g_in_test) { + logger->warn("in test mode, pre_heat_time_s = 5"); + context.pre_heat_time_s = 5; + } + + logger->info("startDisinfection {} {}", m_context.cfg_targetLoglevel, m_context.m_disinfectionID); + logger->info(" stoped_gs {}", context.stoped_gs); + logger->info(" continued_gs {}", context.continued_gs); + logger->info(" stoped_satur {}", context.stoped_satur); + logger->info(" continued_satur {}", context.continued_satur); + logger->info(" stoped_humi {}", context.stoped_humi); + logger->info(" continued_humi {}", context.continued_humi); + logger->info(" pre_heat_time_s {}", context.pre_heat_time_s); + logger->info(""); + + context.state_remaintime = context.pre_heat_time_s + loglevel * 90 * 60; // 计算总的加热时间 + m_disinfectionWorkState = 1; + context.cfg_targetLoglevel = loglevel; + context.state_now_loglevel = 0; + m_context.state_dvalue = 0; + + m_context.m_state = kstate_preheat; + + m_context.start_tp = zsystem_clock().now(); + m_context.start_steady_tp = zsteady_clock().now(); + for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + m_context.h2o2[i] = 0; + m_context.humid[i] = 0; + m_context.temp[i] = 0; + m_context.saturation[i] = 0; + } + + m_context.min_h2o2 = 0; + m_context.max_h2o2 = 0; + m_context.max_humid = 0; + m_context.max_saturation = 0; + m_context.stateSnapshotList.clear(); + m_context.afterDisinfectantVolume_g = 0; + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_context.beforeDisinfectantVolume_g = m_deviceIoControlService->getDisinfectantVolume_g(); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_context.beforeDisinfectantVolume_g = 0; +#else +#endif + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) + m_deviceIoControlService->warningLightCtrl(0, 0, 1, 0); +#endif + +#ifdef PROJECT_TYPE_PIPE_DISINFECTION + m_deviceIoControlService->warningLightCtrl(1, 1, 0, 0); +#endif + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->heartingPlate_setPower(true); + m_deviceIoControlService->airBlower_setState(true); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif + + context.csvlogger = createCSVLogger(context.m_disinfectionID); + + m_context.firstLog = true; +} + +void DisinfectionService::finishDisinfection(DisinfectionContext& context) { + context.state_remaintime = 0; + logger->info("stop disinfection {}", context.m_disinfectionID); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + // sprayLiquidPump_close(); + m_deviceIoControlService->sprayLiquidPump_close(); + usleep(1000 * 1000); + // airCompressor(false); + m_deviceIoControlService->airCompressor_setState(false); + usleep(1000 * 1000); + // blower_setPower(false); + m_deviceIoControlService->airBlower_setState(false); + usleep(1000 * 1000); + // heartingPlate_setPower(false); + m_deviceIoControlService->heartingPlate_setPower(false); + m_disinfectionWorkState = 3; + + m_deviceIoControlService->warningLightCtrl(0, 1, 0, 0); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif +} + +void DisinfectionService::processPreheatState(DisinfectionContext& context) { + int hasstarttime = zsteady_clock().elapsedTimeS(context.start_steady_tp); + + // logger->info("preheat {}", context.m_disinfectionID); + if ((context.m_state == kstate_preheat && hasstarttime > m_context.pre_heat_time_s)) { + /** + * @brief + * 预热结束 + */ + logger->info("preheat finished {}", context.m_disinfectionID); + logger->info("preheat finished {}", context.m_disinfectionID); + +#ifdef PROJECT_TYPE_PIPE_DISINFECTION + m_deviceIoControlService->airCompressor_channelSelect(1); + m_deviceIoControlService->airCompressor_setValve1(1); + m_deviceIoControlService->airCompressor_setValve2(1); +#endif + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->airBlower_setState(true); + usleep(1000 * 1000); + m_deviceIoControlService->airCompressor_setState(true); + usleep(1000 * 1000); + m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_deviceIoControlService->DBDB__sprayAirCompressorPowerCtrl(1); + usleep(1000 * 1000); + m_deviceIoControlService->DBDB__heaterCtrl(1); + usleep(100 * 1000); + m_deviceIoControlService->DBDB__heaterCtrlSafeValve(1); + usleep(100 * 1000); + m_deviceIoControlService->DBDB__miniPwmBlowerCtrl(1); + usleep(100 * 1000); + m_deviceIoControlService->DBDB__extValveCtrl(IF_DeviceIoContrlService::kExtValveChannel_disinfectionChannel); +#else +#endif + + context.m_state = kstate_disinfection; + } else { + logger->info("{}: preheat {}", context.m_disinfectionID, m_context.pre_heat_time_s - hasstarttime); + } +} + +/** + * @brief + * 消毒中状态处理 + */ +void DisinfectionService::processDisinfectionState(DisinfectionContext& context) { + /** + * @brief 周期性计算剩余时间 + */ + + /** + * @brief 根据湿度启停喷雾 + */ + if (!m_context.state_is_disinfection_take_break) { + /** + * @brief 检查当前 + */ + float nowSatur = m_context.max_saturation; + float nowh2o2 = m_context.max_h2o2; + float humid = m_context.max_humid; + + if (m_context.injection_pump_speed_changed) { +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif + + m_context.injection_pump_speed_changed = false; + } + + // humid > m_context.stoped_satur + if (nowSatur > m_context.stoped_satur || nowh2o2 > m_context.stoped_gs || humid > m_context.stoped_humi) { + logger->info("stop sprayLiquid"); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->sprayLiquidPump_close(); + usleep(1000 * 1000); + m_deviceIoControlService->airCompressor_setState(false); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif + + // m_context.sprayLiquidFlag = false; + m_context.state_is_disinfection_take_break = true; + } + } else { + float nowSatur = m_context.max_saturation; + float nowh2o2 = m_context.max_h2o2; + float humid = m_context.max_humid; + + // && humid < m_context.continued_satur + if (nowSatur < m_context.continued_satur && nowh2o2 < m_context.continued_gs && humid < context.continued_humi) { + logger->info("start sprayLiquid"); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); + usleep(1000 * 1000); + m_deviceIoControlService->airCompressor_setState(true); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif + + m_context.state_is_disinfection_take_break = false; + } + } +} + +void DisinfectionService::processState_Preheat(DisinfectionContext& context) { + /** + * @brief 预热中 + */ + m_context.state_dvalue = 0; + processPreheatState(m_context); +} +void DisinfectionService::processState_Disinfection(DisinfectionContext& context, bool& updatedval) { + m_context.state_dvalue = getDisinfectionDValue(m_context.min_h2o2); + if (zsteady_clock().elapsedTimeS(m_context.state_last_compute_dvalue_tp) > DVALUE_COMPUTEPERIOD_TIME_S) { + m_context.state_last_compute_dvalue_tp = zsteady_clock().now(); + m_context.state_now_loglevel = computeNowLogLevel(m_context); + computeRemainTime(m_context); + updatedval = true; + } + + /** + * @brief 消毒中 + */ + processDisinfectionState(m_context); + // + if (m_context.state_remaintime <= 0 && m_context.state_now_loglevel > (m_context.cfg_targetLoglevel + 0.01)) { + m_context.state_remaintime = 0; + m_context.state_now_loglevel = m_context.cfg_targetLoglevel + 0.01; + logger->info("disinfection finished {},but waitting for h2o2 to safe", m_context.m_disinfectionID); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->sprayLiquidPump_close(); + usleep(1000 * 1000); + m_deviceIoControlService->airCompressor_setState(false); + usleep(1000 * 1000); + m_deviceIoControlService->heartingPlate_setPower(false); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) +#else +#endif + + m_context.m_state = kstate_degradation; + } +} +void DisinfectionService::processState_Degradation(DisinfectionContext& context) { + // 降解 + m_context.state_dvalue = 0; + logger->info("waitting for h2o2 concentration to safe value {}=>{}", m_context.min_h2o2, 1); + if (m_context.min_h2o2 < 1) { + logger->info("h2o2 concentration to safe value"); + m_context.m_state = kstate_finished; + } +} + +void DisinfectionService::disinfectionLoop(bool& breakflag) { + // logger->info("disinfection running {} {}s preheatFlag:{}", m_context.m_disinfectionID, m_context.state_remaintime, m_context.m_preheatFlag); + ThisThread thisThread; + disinfection_state_t enterstate; + disinfection_state_t exitstate; + bool statechanged = false; + bool updatedval = false; + + enterstate = m_context.m_state; + m_context.state_remaintime--; + + if (m_context.state_remaintime < 0) m_context.state_remaintime = 0; + updateH2O2SensorData(m_context); + + /******************************************************************************* + * 状态处理 * + *******************************************************************************/ + if (thisThread.getExitFlag()) { + m_context.m_state = kstate_finished; + } else if (m_context.m_state == kstate_preheat) { + processState_Preheat(m_context); + } else if (m_context.m_state == kstate_disinfection) { + processState_Disinfection(m_context, updatedval); + } else if (m_context.m_state == kstate_degradation) { + processState_Degradation(m_context); + } + + exitstate = m_context.m_state; + if (exitstate != enterstate) { + statechanged = true; + } + + /******************************************************************************* + * 打印日志 * + *******************************************************************************/ + if (exitstate == kstate_finished) { + /** + * @brief 消毒结束 + */ + breakflag = true; + m_context.complete_tp = zsystem_clock().now(); +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_context.afterDisinfectantVolume_g = m_deviceIoControlService->getDisinfectantVolume_g(); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_context.afterDisinfectantVolume_g = 0; +#else + m_context.afterDisinfectantVolume_g = 0; +#endif + + if (m_context.m_state != kstate_finished) { + m_context.m_state = kstate_finished; + } + m_disinfectionWorkState = 0; + takeStateSnapshot(m_context); + dumpDisinfectionLogsToCSV(m_context); + log(m_context); + pushDisinfectionPrinterTask(m_context); + finishDisinfection(m_context); + m_context.csvlogger = nullptr; + } else { + if (updatedval) { + log(m_context); + } + + if (m_context.firstLog || statechanged || zsteady_clock().elapsedTimeS(m_context.state_lastlog_tp) > DUMP_LOG_PERIOD) { + m_context.state_lastlog_tp = zsteady_clock().now(); + takeStateSnapshot(m_context); + dumpDisinfectionLogsToCSV(m_context); + m_context.firstLog = false; + } + } +} + +void DisinfectionService::changeDisinfectionParameter(int injection_pump_speed, // + int stoped_gs, // + int continued_gs, // + int stoped_satur, // + int continued_satur, // + int stoped_humi, // + int continued_humi) { + lock_guard lock(lock_); + m_context.injection_pump_speed = injection_pump_speed; + m_context.stoped_gs = stoped_gs; + m_context.continued_gs = continued_gs; + m_context.stoped_satur = stoped_satur; + m_context.continued_satur = continued_satur; + m_context.stoped_humi = stoped_humi; + m_context.continued_humi = continued_humi; + m_context.injection_pump_speed_changed = true; + + logger->info("changeDisinfectionParameter {} {} {} {} {} {} {}", // + injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi); +} + +void DisinfectionService::startDisinfection(int loglevel, // + int injection_pump_speed, // + int stoped_gs, // + int continued_gs, // + int stoped_satur, // + int continued_satur, // + int stoped_humi, // + int continued_humi // +) { + lock_guard lock(lock_); + + if (m_disinfectionThread) stopDisinfection(); + + initContext(m_context, loglevel, injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi); + m_disinfectionThread.reset(new Thread("m_disinfectionThread", [this]() { + ThisThread thisThread; + while (true) { + thisThread.sleepForMs(1000); + bool breakflag = false; + disinfectionLoop(breakflag); + if (breakflag) { + break; + } + } + })); + // +} +void DisinfectionService::stopDisinfection() { + lock_guard lock(lock_); + if (m_disinfectionThread) { + m_disinfectionThread->join(); + m_disinfectionThread = nullptr; + } +} + +int DisinfectionService::getDisinfectionWorkState() { return m_context.m_state; } + +int32_t DisinfectionService::getEstimatedRemainingTimeS() { + if (m_context.m_state == kstate_preheat) { + return getPreHeatRaminTimeS(); + } else if (m_context.m_state == kstate_disinfection) { + if (m_context.state_dvalue > 0) { + return m_context.state_remaintime; + } else { + return -1; + } + } else { + return 0; + } +} +int32_t DisinfectionService::getPreHeatRaminTimeS() { + int32_t remaintime = 0; + if (m_context.m_state == kstate_preheat) { + remaintime = m_context.pre_heat_time_s - zsteady_clock().elapsedTimeS(m_context.start_steady_tp); + if (remaintime < 0) { + remaintime = 0; + } + return remaintime; + } else { + return 0; + } +} + +string DisinfectionService::getDisinfectionID() { return m_context.m_disinfectionID; } +bool DisinfectionService::isPreheatState() { return m_context.m_state == kstate_preheat; } +void DisinfectionService::updateH2O2SensorData(DisinfectionContext& context) { + auto& cx = context; + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + cx.h2o2[i] = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(i); + } + + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + cx.humid[i] = m_deviceIoControlService->H2O2Sensor_readHumid(i); + } + + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + cx.temp[i] = m_deviceIoControlService->H2O2Sensor_readTemperature(i); + } + + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + cx.saturation[i] = m_deviceIoControlService->H2O2Sensor_readSaturation(i); + } + + cx.min_h2o2 = cx.h2o2[0]; + cx.max_h2o2 = cx.h2o2[0]; + cx.max_humid = cx.humid[0]; + cx.max_saturation = cx.saturation[0]; + + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + if (cx.h2o2[i] < cx.min_h2o2) { + cx.min_h2o2 = cx.h2o2[i]; + } + + if (cx.h2o2[i] > cx.max_h2o2) { + cx.max_h2o2 = cx.h2o2[i]; + } + + if (cx.humid[i] > cx.max_humid) { + cx.max_humid = cx.humid[i]; + } + + if (cx.saturation[i] > cx.max_saturation) { + cx.max_saturation = cx.saturation[i]; + } + } + + if (cx.max_h2o2 < 0) cx.max_h2o2 = 0; + if (cx.min_h2o2 < 0) cx.min_h2o2 = 0; + if (cx.max_humid < 0) cx.max_humid = 0; + if (cx.max_saturation < 0) cx.max_saturation = 0; +} + +void DisinfectionService::takeStateSnapshot(DisinfectionContext& context) { + auto& cx = context; + + shared_ptr snapshot = make_shared(); + snapshot->time = zsystem_clock().now(); + for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { + snapshot->h2o2[i] = cx.h2o2[i]; + snapshot->humid[i] = cx.humid[i]; + snapshot->temp[i] = cx.temp[i]; + snapshot->saturation[i] = cx.saturation[i]; + } + + snapshot->min_h2o2 = cx.min_h2o2; + snapshot->max_h2o2 = cx.max_h2o2; + snapshot->max_humid = cx.max_humid; + snapshot->max_saturation = cx.max_saturation; + snapshot->state = cx.m_state; + snapshot->dloglevel = cx.state_now_loglevel; + cx.stateSnapshotList.push_back(snapshot); +} diff --git a/service/disfection_ctl/disinfection_service.hpp b/service/disfection_ctl/disinfection_service.hpp new file mode 100644 index 0000000..0779fd5 --- /dev/null +++ b/service/disfection_ctl/disinfection_service.hpp @@ -0,0 +1,145 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db/db_service.hpp" +#include "service/disinfection_logs_manager.hpp" +#include "disinfection_state.hpp" +#include "iflytop/components/zcanreceiver/zcanhost.hpp" +#include "iflytop/core/core.hpp" +#include "service/device_io_control_service.hpp" +#include "service/disinfection_printer_service.hpp" +#include "utils/dvalue_computer.hpp" +#include "zservice_container/zservice_container.hpp" +/** + * @brief + * + * service: DisinfectionService + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; +class DisinfectionService : public enable_shared_from_this { + ENABLE_LOGGER(DisinfectionService); + + private: + recursive_mutex lock_; + + unique_ptr m_disinfectionThread; + shared_ptr m_deviceIoControlService; + shared_ptr m_dbService; + shared_ptr m_disinfectionLogsManager; + shared_ptr m_disinfectionPrinterService; + DValueComputer m_dvalueComputer; + + int m_disinfectionWorkState = 0; + int m_replenishingFluidsWorkState = 0; + int m_drainingWorkState = 0; // 消毒工作状态,0:未工作,1:工作中 + + public: + DisinfectionContext m_context; + + public: + DisinfectionService(); + + public: + void initialize(); + /** + * @brief 开始消毒 + * + * @param loglevel 消毒等级 + */ + + void startDisinfection(int loglevel, // + int injection_pump_speed, // + int stoped_gs, // + int continued_gs, // + int stoped_satur, // + int continued_satur, // + int stoped_humi, // + int continued_humi // + ); + void changeDisinfectionParameter(int injection_pump_speed, // + int stoped_gs, // + int continued_gs, // + int stoped_satur, // + int continued_satur, // + int stoped_humi, // + int continued_humi // + ); + + void stopDisinfection(); + + int getDisinfectionWorkState(); + + /******************************************************************************* + * State * + *******************************************************************************/ + bool isDisinfectionRunning(); + int32_t getEstimatedRemainingTimeS(); + string getDisinfectionID(); + bool isPreheatState(); + int32_t getPreHeatRaminTimeS(); + + private: + string createDisinfectionID(); + + private: + float getDisinfectionDValue(float ppm); + + void initContext(DisinfectionContext& context, // + int loglevel, // + float injection_pump_speed, // + float stoped_gs, // + float continued_gs, // + float stoped_satur, // + float continued_satur, // + float stoped_humi, // + float continued_humi // + ); + + void computeRemainTime(DisinfectionContext& context); + float computeNowLogLevel(DisinfectionContext& context); + void processPreheatState(DisinfectionContext& context); + void processDisinfectionState(DisinfectionContext& context); + void finishDisinfection(DisinfectionContext& context); + + void disinfectionLoop(bool& breakflag); + + void processState_Preheat(DisinfectionContext& context); + void processState_Disinfection(DisinfectionContext& context, bool& updatedval); + void processState_Degradation(DisinfectionContext& context); + + private: + shared_ptr createCSVLogger(string log_file_name); + void dumpDisinfectionLogsToCSV(DisinfectionContext& context); + + void pushDisinfectionPrinterTask(DisinfectionContext& context); + + void log(DisinfectionContext& context); + void takeStateSnapshot(DisinfectionContext& context); + void updateH2O2SensorData(DisinfectionContext& context); + + + private: +}; +} // namespace iflytop \ No newline at end of file diff --git a/service/disfection_ctl/disinfection_state.hpp b/service/disfection_ctl/disinfection_state.hpp new file mode 100644 index 0000000..a1937c5 --- /dev/null +++ b/service/disfection_ctl/disinfection_state.hpp @@ -0,0 +1,143 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "configs/project_setting.hpp" +#include "iflytop/core/components/timeutils.hpp" +/** + * @brief + * + * service: DisinfectionCtrlService + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; + +class DisinfectionLogger; + +typedef enum { + kstate_idle = 0, // 空闲 + kstate_preheat = 1, // 预热 + kstate_disinfection = 2, // 消毒中-工作 + kstate_degradation = 4, // 降解中 + kstate_finished = 5, // 结束 + kstate_dehumidification_before_disinfection = 6, // 消毒前除湿 + kstate_dehumidification_after_disinfection = 7, // 消毒后除湿 + +} disinfection_state_t; + +class StateSnapshot { + public: + disinfection_state_t state; + zsystem_tp time; + + int32_t h2o2[MAX_H2O2_SENSOR_NUM]; // ppm + int32_t humid[MAX_H2O2_SENSOR_NUM]; // %RH + int32_t temp[MAX_H2O2_SENSOR_NUM]; // °C + int32_t saturation[MAX_H2O2_SENSOR_NUM]; // %RS + + int min_h2o2; + int max_h2o2; + int max_humid; + int max_saturation; + + float dloglevel; +}; + +class DisinfectionPrinterTask { + public: + string disinfection_id; + string usr; + + vector> stateSnapshotList; // 状态快照I + + int disinfectantUsage; // 消毒剂使用量 + + zsystem_tp start_tp; + zsystem_tp complete_tp; + + int targetLog; + int actualLog; + + int disinfectantVolume; // g +}; + +class DisinfectionContext { + public: + string m_disinfectionID; + disinfection_state_t m_state = kstate_idle; + zsteady_tp start_steady_tp; + zsystem_tp start_tp; + zsystem_tp complete_tp; + + /** + * @brief 消毒中配置 + */ + int pre_heat_time_s = 0; // 预热时间 + int stoped_gs = 0; // 停止H2O2浓度 + int continued_gs = 0; // 继续H2O2浓度 + int stoped_satur = 0; // 停止饱和度 + int continued_satur = 0; // 继续饱和度 + int stoped_humi = 0; // 停止湿度 + int continued_humi = 0; // 继续湿度 + + int injection_pump_speed; + bool injection_pump_speed_changed = false; + + float cfg_targetLoglevel = 0; + + /** + * @brief 运行状态 + */ + zsteady_tp state_last_compute_dvalue_tp; // 上次计算dvalue时间 + zsteady_tp state_lastlog_tp; // 上次日志时间 + int state_remaintime = 0; + float state_now_loglevel = 0; + float state_dvalue = 0; + bool state_is_disinfection_take_break; // 消毒工作中是否暂停工作 + /******************************************************************************* + * 传感器信息 * + *******************************************************************************/ + + int32_t h2o2[MAX_H2O2_SENSOR_NUM]; // ppm + int32_t humid[MAX_H2O2_SENSOR_NUM]; // %RH + int32_t temp[MAX_H2O2_SENSOR_NUM]; // °C + int32_t saturation[MAX_H2O2_SENSOR_NUM]; // %RS + + int min_h2o2; + int max_h2o2; + int max_humid; + int max_saturation; + + /******************************************************************************* + * 日志与统计 * + *******************************************************************************/ + shared_ptr csvlogger; // 日志记录器 + vector> stateSnapshotList; // 状态快照I + + int beforeDisinfectantVolume_g; // 消毒前消毒剂量 + int afterDisinfectantVolume_g; // 消毒后消毒剂量 + + bool firstLog; +}; + +} // namespace iflytop \ No newline at end of file diff --git a/service/disfection_ctl/drain_liquid_service.cpp b/service/disfection_ctl/drain_liquid_service.cpp new file mode 100644 index 0000000..171e7a5 --- /dev/null +++ b/service/disfection_ctl/drain_liquid_service.cpp @@ -0,0 +1,102 @@ +#include "drain_liquid_service.hpp" + +#include +#include + +#include "configs/gconfig.hpp" +#include "configs/project_setting.hpp" +#include "iflytop/components/uart_printer/uart_printer.hpp" +#include "iflytoplinuxsdk/src/iflytop/components/ziconv.hpp" +#include "service/device_state_service.hpp" + +using namespace iflytop; +using namespace std; +namespace iflytop { +extern bool g_in_test; +} + +DrainLiquidService::DrainLiquidService() {} +void DrainLiquidService::initialize() { + GET_TO_SERVICE(m_deviceIoControlService); + GET_TO_SERVICE(m_dbService); + GET_TO_SERVICE(m_disinfectionLogsManager); + GET_TO_SERVICE(m_disinfectionPrinterService); + +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + m_deviceIoControlService->drainingPump_close(); + m_deviceIoControlService->replenishingFluidsPump_close(); + m_deviceIoControlService->sprayLiquidPump_close(); + + m_deviceIoControlService->heartingPlate_setPower(false); + m_deviceIoControlService->airBlower_setState(false); + m_deviceIoControlService->airCompressor_setState(false); +#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) + m_context.beforeDisinfectantVolume_g = 0; +#else +#endif + + m_dvalueComputer.initialize(); +} +/******************************************************************************* + * 排液 * + *******************************************************************************/ +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + +void DrainLiquidService::startDraining() { + lock_guard lock(lock_); + if (m_disinfectionThread) { + m_disinfectionThread->join(); + m_disinfectionThread = nullptr; + } + + m_disinfectionThread.reset(new Thread("disinfectionThread", [this]() { + ThisThread thisThread; + + m_deviceIoControlService->drainingPump_open(); + logger->info("startDraining "); + + auto startdrainingtime = zsteady_clock().now(); + + zsteady_tp volumeReachZeroTime; + bool volumeReachZeroFlag = false; + + while (!thisThread.getExitFlag()) { + int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); + logger->info("draining remain {} g", nowvolume); + if (!volumeReachZeroFlag && nowvolume == 0) { + volumeReachZeroTime = zsteady_clock().now(); + volumeReachZeroFlag = true; + } + + if (volumeReachZeroFlag) { + logger->info("stopDraining after {} s", 30 - zsteady_clock().elapsedTimeS(volumeReachZeroTime)); + if (zsteady_clock().elapsedTimeS(volumeReachZeroTime) > 30) { + break; + } + } + + thisThread.sleepForMs(1000); + } + logger->info("stopDraining"); + // replenishingFluidsPump_close(); + m_deviceIoControlService->drainingPump_close(); + m_drainingWorkState = 0; + })); + + logger->info("startDraining"); + // drainingPump_open(); + m_drainingWorkState = 1; +} +void DrainLiquidService::stopDraining() { + lock_guard lock(lock_); + if (m_disinfectionThread) { + m_disinfectionThread->join(); + m_disinfectionThread = nullptr; + } + logger->info("stopDraining"); + m_drainingWorkState = 0; + // drainingPump_close(); + m_deviceIoControlService->drainingPump_close(); +} +int DrainLiquidService::getDrainingWorkState() { return m_drainingWorkState; } +#endif diff --git a/service/disfection_ctl/drain_liquid_service.hpp b/service/disfection_ctl/drain_liquid_service.hpp new file mode 100644 index 0000000..1611b03 --- /dev/null +++ b/service/disfection_ctl/drain_liquid_service.hpp @@ -0,0 +1,82 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db/db_service.hpp" +#include "service/disinfection_logs_manager.hpp" +#include "disinfection_state.hpp" +#include "iflytop/components/zcanreceiver/zcanhost.hpp" +#include "iflytop/core/core.hpp" +#include "service/device_io_control_service.hpp" +#include "service/disinfection_printer_service.hpp" +#include "utils/dvalue_computer.hpp" +#include "zservice_container/zservice_container.hpp" +/** + * @brief + * + * service: DrainLiquidService + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; +class DrainLiquidService : public enable_shared_from_this { + ENABLE_LOGGER(DrainLiquidService); + + private: + recursive_mutex lock_; + + unique_ptr m_disinfectionThread; + shared_ptr m_deviceIoControlService; + shared_ptr m_dbService; + shared_ptr m_disinfectionLogsManager; + shared_ptr m_disinfectionPrinterService; + DValueComputer m_dvalueComputer; + + int m_disinfectionWorkState = 0; + int m_replenishingFluidsWorkState = 0; + int m_drainingWorkState = 0; // 消毒工作状态,0:未工作,1:工作中 + + public: + DisinfectionContext m_context; + + public: + DrainLiquidService(); + + public: + void initialize(); +#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) + + + /******************************************************************************* + * 排液 * + *******************************************************************************/ + void startDraining(); + void stopDraining(); + + int getDrainingWorkState(); + +#endif + + + private: +}; +} // namespace iflytop \ No newline at end of file diff --git a/service/disinfection_ctl_service.cpp b/service/disinfection_ctl_service.cpp index a71f877..8353fb0 100644 --- a/service/disinfection_ctl_service.cpp +++ b/service/disinfection_ctl_service.cpp @@ -1,734 +1,5 @@ #include "disinfection_ctl_service.hpp" - -#include -#include - -#include "configs/gconfig.hpp" -#include "configs/project_setting.hpp" -#include "iflytop/components/uart_printer/uart_printer.hpp" -#include "iflytoplinuxsdk/src/iflytop/components/ziconv.hpp" -#include "service/device_state_service.hpp" - -// #define PROJECT_TYPE_LARGE_SPACE_DISINFECTION 1 // 大空间 -// #define PROJECT_TYPE_SMALL_SPACE_DISINFECTION 1 // 小空间 - using namespace iflytop; -using namespace std; -#define DVALUE_COMPUTEPERIOD_TIME_S (10.0) -#define DUMP_LOG_PERIOD (5 * 60.0) -#define MAX_VOLUME (5000) - -namespace iflytop { -extern bool g_in_test; - -} - -static string formattimeS(int sec) { - if (sec >= 0) { - return fmt::format("{:0>2}:{:0>2}:{:0>2}", sec / 3600, sec % 3600 / 60, sec % 60); - } else { - return fmt::format("--:--:--"); - } -} - -static string getTime() { - struct tm tm = {0}; - - time_t t = time(nullptr); - localtime_r(&t, &tm); - return fmt::format("{:0>4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", tm.tm_year + 1900, // - tm.tm_mon + 1, // - tm.tm_mday, // - tm.tm_hour, // - tm.tm_min, tm.tm_sec); -} - -static bool zfeq(float a, float b, float eps = 0.01) { - if (fabs(a - b) < eps) { - return true; - } - return false; -} - -DisinfectionCtrlService::DisinfectionCtrlService() {} -void DisinfectionCtrlService::initialize() { - GET_TO_SERVICE(m_deviceIoControlService); - GET_TO_SERVICE(m_dbService); - GET_TO_SERVICE(m_disinfectionLogsManager); - GET_TO_SERVICE(m_disinfectionPrinterService); - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->drainingPump_close(); - m_deviceIoControlService->replenishingFluidsPump_close(); - m_deviceIoControlService->sprayLiquidPump_close(); - - m_deviceIoControlService->heartingPlate_setPower(false); - m_deviceIoControlService->airBlower_setState(false); - m_deviceIoControlService->airCompressor_setState(false); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) - m_context.beforeDisinfectantVolume_g = 0; -#else -#endif - - m_dvalueComputer.initialize(); -} - -string DisinfectionCtrlService::createDisinfectionID() { - struct tm tm = {0}; - - time_t t = time(nullptr); - if (t == -1) { - logger->error("time(nullptr) failed"); - exit(-1); - } - struct tm* tmp = localtime_r(&t, &tm); - if (!tmp) { - logger->error("localtime_r failed"); - exit(-1); - } - // tm = *utctime::tm_increment_hour(&tm, 8); - // logger->info("trace sendmsg_startCapture {}:{}", __FILE__, __LINE__); - return fmt::format("{:0>4}-{:0>2}{:0>2}-{:0>2}{:0>2}{:0>2}", tm.tm_year + 1900, // - tm.tm_mon + 1, // - tm.tm_mday, // - tm.tm_hour, // - tm.tm_min, tm.tm_sec); -} - -float DisinfectionCtrlService::getDisinfectionDValue(float ppm) { // - return m_dvalueComputer.computeDValue(ppm); -} -float DisinfectionCtrlService::computeNowLogLevel(DisinfectionContext& context) { - float dvalue = context.state_dvalue; - if (dvalue > 0) { - /** - * @brief 计算 state_now_loglevel - */ - return context.state_now_loglevel + DVALUE_COMPUTEPERIOD_TIME_S / (dvalue * 60); - } - return context.state_now_loglevel; -} - -void DisinfectionCtrlService::computeRemainTime(DisinfectionContext& context) { - /** - * @brief 计算Dvalue - */ - float dvalue = context.state_dvalue; - - if (dvalue > 0) { - /** - * @brief 计算 state_now_loglevel - */ - if (context.cfg_targetLoglevel >= context.state_now_loglevel) { - context.state_remaintime = (context.cfg_targetLoglevel - context.state_now_loglevel) * (dvalue * 60); - } else { - context.state_remaintime = 0; - } - } else { - // - } - - logger->info("computeRemainTime minh2o2 {} dvalue {}", context.min_h2o2, dvalue); -} - -shared_ptr DisinfectionCtrlService::createCSVLogger(string log_file_name) { - shared_ptr _logger = m_disinfectionLogsManager->createNewLogger(log_file_name); -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) - - _logger->write( - fmt::format("{}," - " {} , {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {}" - "\n", - ZIconv::noChange("时间"), // - ZIconv::noChange("仓内-气化过氧化氢浓度"), ZIconv::noChange("仓内-温度"), ZIconv::noChange("仓内-相对湿度"), ZIconv::noChange("仓内-相对饱和度"), // - ZIconv::noChange("环境1-气化过氧化氢浓度"), ZIconv::noChange("环境1-温度"), ZIconv::noChange("环境1-相对湿度"), ZIconv::noChange("环境1-相对饱和度"), // - ZIconv::noChange("环境2-气化过氧化氢浓度"), ZIconv::noChange("环境2-温度"), ZIconv::noChange("环境2-相对湿度"), ZIconv::noChange("环境2-相对饱和度"), // - ZIconv::noChange("D值"), ZIconv::noChange("当前LOG"), ZIconv::noChange("目标LOG"), // - ZIconv::noChange("加热器电源"), ZIconv::noChange("风机电源"), ZIconv::noChange("空压机电源"), ZIconv::noChange("喷液泵(g/min)"), // - ZIconv::noChange("消毒剩余剂量(g)"), ZIconv::noChange("剩余时间(s)"))); -#endif - -#ifdef PROJECT_TYPE_PIPE_DISINFECTION - - _logger->write( - fmt::format(" {} ," - " {} , {} , {} , {} ," - " {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} " - "\n", - ZIconv::noChange("时间"), // - ZIconv::noChange("仓内-气化过氧化氢浓度"), ZIconv::noChange("仓内-温度"), ZIconv::noChange("仓内-相对湿度"), ZIconv::noChange("仓内-相对饱和度"), // - ZIconv::noChange("D值"), ZIconv::noChange("当前LOG"), ZIconv::noChange("目标LOG"), // - ZIconv::noChange("加热器电源"), ZIconv::noChange("风机电源"), ZIconv::noChange("空压机电源"), ZIconv::noChange("喷液泵(g/min)"), // - ZIconv::noChange("消毒剩余剂量(g)"), ZIconv::noChange("剩余时间(s)"))); -#endif - return _logger; -} - -void DisinfectionCtrlService::dumpDisinfectionLogsToCSV(DisinfectionContext& context) { -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) - - static_assert(MAX_H2O2_SENSOR_NUM == 3, "MAX_H2O2_SENSOR_NUM must be 3"); - - auto& cx = context; - string h2o2str[MAX_H2O2_SENSOR_NUM]; - string tempstr[MAX_H2O2_SENSOR_NUM]; - string humidstr[MAX_H2O2_SENSOR_NUM]; - string satstr[MAX_H2O2_SENSOR_NUM]; - - for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - h2o2str[i] = fmt::format("{}", cx.h2o2[i]); - tempstr[i] = fmt::format("{}", cx.temp[i]); - humidstr[i] = fmt::format("{}", cx.humid[i]); - satstr[i] = fmt::format("{}", cx.saturation[i]); - } - - for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - if (cx.h2o2[i] < 0) h2o2str[i] = "N/A"; - if (cx.temp[i] < 0) tempstr[i] = "N/A"; - if (cx.humid[i] < 0) humidstr[i] = "N/A"; - if (cx.saturation[i] < 0) satstr[i] = "N/A"; - } - - auto ds = m_deviceIoControlService; - float dvalue = 0; - if (m_context.state_dvalue <= 0) { - dvalue = 0; - } else { - dvalue = m_context.state_dvalue; - } - - int remaintime = getEstimatedRemainingTimeS(); - - context.csvlogger->write( - fmt::format(" {} ," - " {} , {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} " - "\n", - getTime(), // - h2o2str[0], tempstr[0], humidstr[0], satstr[0], // - h2o2str[1], tempstr[1], humidstr[1], satstr[1], // - h2o2str[2], tempstr[2], humidstr[2], satstr[2], // - (int32_t)dvalue, (int32_t)m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // - ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // - m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); -#endif - -#ifdef PROJECT_TYPE_PIPE_DISINFECTION - - static_assert(MAX_H2O2_SENSOR_NUM == 1, "MAX_H2O2_SENSOR_NUM must be 1"); - - auto& cx = context; - string h2o2str[MAX_H2O2_SENSOR_NUM]; - string tempstr[MAX_H2O2_SENSOR_NUM]; - string humidstr[MAX_H2O2_SENSOR_NUM]; - string satstr[MAX_H2O2_SENSOR_NUM]; - - for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - h2o2str[i] = fmt::format("{}", cx.h2o2[i]); - tempstr[i] = fmt::format("{}", cx.temp[i]); - humidstr[i] = fmt::format("{}", cx.humid[i]); - satstr[i] = fmt::format("{}", cx.saturation[i]); - } - - for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - if (cx.h2o2[i] < 0) h2o2str[i] = "N/A"; - if (cx.temp[i] < 0) tempstr[i] = "N/A"; - if (cx.humid[i] < 0) humidstr[i] = "N/A"; - if (cx.saturation[i] < 0) satstr[i] = "N/A"; - } - - auto ds = m_deviceIoControlService; - float dvalue = 0; - if (m_context.state_dvalue <= 0) { - dvalue = 0; - } else { - dvalue = m_context.state_dvalue; - } - - int remaintime = getEstimatedRemainingTimeS(); - - context.csvlogger->write( - fmt::format(" {} ," - " {} , {} , {} , {} ," - " {} , {} , {} ," - " {} , {} , {} , {} ," - " {} , {} " - "\n", - getTime(), // - h2o2str[0], tempstr[0], humidstr[0], satstr[0], // - (int32_t)dvalue, (int32_t)m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // - ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // - m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); - -#endif -} - -void DisinfectionCtrlService::pushDisinfectionPrinterTask(DisinfectionContext& context) { // - shared_ptr task = make_shared(); - auto ds = GET_SERVICE(DeviceStateService); - auto dio = m_deviceIoControlService; - - task->start_tp = context.start_tp; - task->complete_tp = context.complete_tp; - task->stateSnapshotList = context.stateSnapshotList; - task->disinfectantUsage = context.beforeDisinfectantVolume_g - context.afterDisinfectantVolume_g; - task->disinfection_id = context.m_disinfectionID; - task->usr = ds->getLoginUid(); - - task->targetLog = context.cfg_targetLoglevel; - task->actualLog = context.state_now_loglevel; - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - task->disinfectantVolume = dio->getDisinfectantVolume_g(); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) - task->disinfectantVolume = 0; - -#else -#endif - - m_disinfectionPrinterService->pushPrintTask(task); -} - -void DisinfectionCtrlService::log(DisinfectionContext& context) { -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) - - auto& cx = context; - auto ds = m_deviceIoControlService; - float dvalue = 0; - if (m_context.state_dvalue <= 0) { - dvalue = 0; - } else { - dvalue = m_context.state_dvalue; - } - - int remaintime = getEstimatedRemainingTimeS(); - - logger->info( - fmt::format("{}," - "s0({},{},{},{})," - "s1({},{},{},{})," - "s2({},{},{},{})," - "min_h2o2:{},max_h2o2:{},max_hum:{},max_sa:{}," - "dv:{},log:{},tlog:{}," - "h:{},airB:{},airC:{},pump:{}," - "g:{},remainS:{}" - "\n", - getTime(), // - cx.h2o2[0], cx.temp[0], cx.humid[0], cx.saturation[0], // - cx.h2o2[1], cx.temp[1], cx.humid[1], cx.saturation[1], // - cx.h2o2[2], cx.temp[2], cx.humid[2], cx.saturation[2], // - m_context.min_h2o2, m_context.max_h2o2, m_context.max_humid, m_context.max_saturation, // - (int32_t)dvalue, m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // - ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // - m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); -#endif -#ifdef PROJECT_TYPE_PIPE_DISINFECTION - auto& cx = context; - auto ds = m_deviceIoControlService; - float dvalue = 0; - if (m_context.state_dvalue <= 0) { - dvalue = 0; - } else { - dvalue = m_context.state_dvalue; - } - - int remaintime = getEstimatedRemainingTimeS(); - - logger->info( - fmt::format("{}," - "s0({},{},{},{})," - "min_h2o2:{},max_h2o2:{},max_hum:{},max_sa:{}," - "dv:{},log:{},tlog:{}," - "h:{},airB:{},airC:{},pump:{}," - "g:{},remainS:{}" - "\n", - getTime(), // - cx.h2o2[0], cx.temp[0], cx.humid[0], cx.saturation[0], // - m_context.min_h2o2, m_context.max_h2o2, m_context.max_humid, m_context.max_saturation, // - (int32_t)dvalue, m_context.state_now_loglevel, (int32_t)m_context.cfg_targetLoglevel, // - ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), // - m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime))); -#endif -} - -/******************************************************************************* - * WORK * - *******************************************************************************/ - -void DisinfectionCtrlService::initContext(DisinfectionContext& context, // - int loglevel, // - float injection_pump_speed, // - float stoped_gs, // - float continued_gs, // - float stoped_satur, // - float continued_satur, // - float stoped_humi, // - float continued_humi // -) { - context.m_disinfectionID = createDisinfectionID(); - context.pre_heat_time_s = m_dbService->getSettingVal("pre_heat_time_s"); - context.stoped_gs = stoped_gs; - context.continued_gs = continued_gs; - context.stoped_satur = stoped_satur; - context.continued_satur = continued_satur; - context.stoped_humi = stoped_humi; - context.continued_humi = continued_humi; - context.injection_pump_speed = injection_pump_speed; - context.injection_pump_speed_changed = true; - - if (g_in_test) { - logger->warn("in test mode, pre_heat_time_s = 5"); - context.pre_heat_time_s = 5; - } - - logger->info("startDisinfection {} {}", m_context.cfg_targetLoglevel, m_context.m_disinfectionID); - logger->info(" stoped_gs {}", context.stoped_gs); - logger->info(" continued_gs {}", context.continued_gs); - logger->info(" stoped_satur {}", context.stoped_satur); - logger->info(" continued_satur {}", context.continued_satur); - logger->info(" stoped_humi {}", context.stoped_humi); - logger->info(" continued_humi {}", context.continued_humi); - logger->info(" pre_heat_time_s {}", context.pre_heat_time_s); - logger->info(""); - - context.state_remaintime = context.pre_heat_time_s + loglevel * 90 * 60; // 计算总的加热时间 - m_disinfectionWorkState = 1; - context.cfg_targetLoglevel = loglevel; - context.state_now_loglevel = 0; - m_context.state_dvalue = 0; - - m_context.m_state = kstate_preheat; - - m_context.start_tp = zsystem_clock().now(); - m_context.start_steady_tp = zsteady_clock().now(); - for (int i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - m_context.h2o2[i] = 0; - m_context.humid[i] = 0; - m_context.temp[i] = 0; - m_context.saturation[i] = 0; - } - - m_context.min_h2o2 = 0; - m_context.max_h2o2 = 0; - m_context.max_humid = 0; - m_context.max_saturation = 0; - m_context.stateSnapshotList.clear(); - m_context.afterDisinfectantVolume_g = 0; - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_context.beforeDisinfectantVolume_g = m_deviceIoControlService->getDisinfectantVolume_g(); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) - m_context.beforeDisinfectantVolume_g = 0; -#else -#endif - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) - m_deviceIoControlService->warningLightCtrl(0, 0, 1, 0); -#endif - -#ifdef PROJECT_TYPE_PIPE_DISINFECTION - m_deviceIoControlService->warningLightCtrl(1, 1, 0, 0); -#endif - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->heartingPlate_setPower(true); - m_deviceIoControlService->airBlower_setState(true); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif - - context.csvlogger = createCSVLogger(context.m_disinfectionID); - - m_context.firstLog = true; -} - -void DisinfectionCtrlService::finishDisinfection(DisinfectionContext& context) { - context.state_remaintime = 0; - logger->info("stop disinfection {}", context.m_disinfectionID); - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - // sprayLiquidPump_close(); - m_deviceIoControlService->sprayLiquidPump_close(); - usleep(1000 * 1000); - // airCompressor(false); - m_deviceIoControlService->airCompressor_setState(false); - usleep(1000 * 1000); - // blower_setPower(false); - m_deviceIoControlService->airBlower_setState(false); - usleep(1000 * 1000); - // heartingPlate_setPower(false); - m_deviceIoControlService->heartingPlate_setPower(false); - m_disinfectionWorkState = 3; - - m_deviceIoControlService->warningLightCtrl(0, 1, 0, 0); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif -} - -void DisinfectionCtrlService::processPreheatState(DisinfectionContext& context) { - int hasstarttime = zsteady_clock().elapsedTimeS(context.start_steady_tp); - - // logger->info("preheat {}", context.m_disinfectionID); - if ((context.m_state == kstate_preheat && hasstarttime > m_context.pre_heat_time_s)) { - /** - * @brief - * 预热结束 - */ - logger->info("preheat finished {}", context.m_disinfectionID); - logger->info("preheat finished {}", context.m_disinfectionID); - -#ifdef PROJECT_TYPE_PIPE_DISINFECTION - m_deviceIoControlService->airCompressor_channelSelect(1); - m_deviceIoControlService->airCompressor_setValve1(1); - m_deviceIoControlService->airCompressor_setValve2(1); -#endif - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->airBlower_setState(true); - usleep(1000 * 1000); - m_deviceIoControlService->airCompressor_setState(true); - usleep(1000 * 1000); - m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) - m_deviceIoControlService->DBDB__sprayAirCompressorPowerCtrl(1); - usleep(1000 * 1000); - m_deviceIoControlService->DBDB__heaterCtrl(1); - usleep(100 * 1000); - m_deviceIoControlService->DBDB__heaterCtrlSafeValve(1); - usleep(100 * 1000); - m_deviceIoControlService->DBDB__miniPwmBlowerCtrl(1); - usleep(100 * 1000); - m_deviceIoControlService->DBDB__extValveCtrl(IF_DeviceIoContrlService::kExtValveChannel_disinfectionChannel); -#else -#endif - - context.m_state = kstate_disinfection; - } else { - logger->info("{}: preheat {}", context.m_disinfectionID, m_context.pre_heat_time_s - hasstarttime); - } -} - -/** - * @brief - * 消毒中状态处理 - */ -void DisinfectionCtrlService::processDisinfectionState(DisinfectionContext& context) { - /** - * @brief 周期性计算剩余时间 - */ - - /** - * @brief 根据湿度启停喷雾 - */ - if (!m_context.state_is_disinfection_take_break) { - /** - * @brief 检查当前 - */ - float nowSatur = m_context.max_saturation; - float nowh2o2 = m_context.max_h2o2; - float humid = m_context.max_humid; - - if (m_context.injection_pump_speed_changed) { -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif - - m_context.injection_pump_speed_changed = false; - } - - // humid > m_context.stoped_satur - if (nowSatur > m_context.stoped_satur || nowh2o2 > m_context.stoped_gs || humid > m_context.stoped_humi) { - logger->info("stop sprayLiquid"); - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->sprayLiquidPump_close(); - usleep(1000 * 1000); - m_deviceIoControlService->airCompressor_setState(false); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif - - // m_context.sprayLiquidFlag = false; - m_context.state_is_disinfection_take_break = true; - } - } else { - float nowSatur = m_context.max_saturation; - float nowh2o2 = m_context.max_h2o2; - float humid = m_context.max_humid; - - // && humid < m_context.continued_satur - if (nowSatur < m_context.continued_satur && nowh2o2 < m_context.continued_gs && humid < context.continued_humi) { - logger->info("start sprayLiquid"); - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed); - usleep(1000 * 1000); - m_deviceIoControlService->airCompressor_setState(true); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif - - m_context.state_is_disinfection_take_break = false; - } - } -} - -void DisinfectionCtrlService::processState_Preheat(DisinfectionContext& context) { - /** - * @brief 预热中 - */ - m_context.state_dvalue = 0; - processPreheatState(m_context); -} -void DisinfectionCtrlService::processState_Disinfection(DisinfectionContext& context, bool& updatedval) { - m_context.state_dvalue = getDisinfectionDValue(m_context.min_h2o2); - if (zsteady_clock().elapsedTimeS(m_context.state_last_compute_dvalue_tp) > DVALUE_COMPUTEPERIOD_TIME_S) { - m_context.state_last_compute_dvalue_tp = zsteady_clock().now(); - m_context.state_now_loglevel = computeNowLogLevel(m_context); - computeRemainTime(m_context); - updatedval = true; - } - - /** - * @brief 消毒中 - */ - processDisinfectionState(m_context); - // - if (m_context.state_remaintime <= 0 && m_context.state_now_loglevel > (m_context.cfg_targetLoglevel + 0.01)) { - m_context.state_remaintime = 0; - m_context.state_now_loglevel = m_context.cfg_targetLoglevel + 0.01; - logger->info("disinfection finished {},but waitting for h2o2 to safe", m_context.m_disinfectionID); - -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_deviceIoControlService->sprayLiquidPump_close(); - usleep(1000 * 1000); - m_deviceIoControlService->airCompressor_setState(false); - usleep(1000 * 1000); - m_deviceIoControlService->heartingPlate_setPower(false); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) -#else -#endif - - m_context.m_state = kstate_degradation; - } -} -void DisinfectionCtrlService::processState_Degradation(DisinfectionContext& context) { - // 降解 - m_context.state_dvalue = 0; - logger->info("waitting for h2o2 concentration to safe value {}=>{}", m_context.min_h2o2, 1); - if (m_context.min_h2o2 < 1) { - logger->info("h2o2 concentration to safe value"); - m_context.m_state = kstate_finished; - } -} - -void DisinfectionCtrlService::disinfectionLoop(bool& breakflag) { - // logger->info("disinfection running {} {}s preheatFlag:{}", m_context.m_disinfectionID, m_context.state_remaintime, m_context.m_preheatFlag); - ThisThread thisThread; - disinfection_state_t enterstate; - disinfection_state_t exitstate; - bool statechanged = false; - bool updatedval = false; - - enterstate = m_context.m_state; - m_context.state_remaintime--; - - if (m_context.state_remaintime < 0) m_context.state_remaintime = 0; - updateH2O2SensorData(m_context); - - /******************************************************************************* - * 状态处理 * - *******************************************************************************/ - if (thisThread.getExitFlag()) { - m_context.m_state = kstate_finished; - } else if (m_context.m_state == kstate_preheat) { - processState_Preheat(m_context); - } else if (m_context.m_state == kstate_disinfection) { - processState_Disinfection(m_context, updatedval); - } else if (m_context.m_state == kstate_degradation) { - processState_Degradation(m_context); - } - - exitstate = m_context.m_state; - if (exitstate != enterstate) { - statechanged = true; - } - - /******************************************************************************* - * 打印日志 * - *******************************************************************************/ - if (exitstate == kstate_finished) { - /** - * @brief 消毒结束 - */ - breakflag = true; - m_context.complete_tp = zsystem_clock().now(); -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - m_context.afterDisinfectantVolume_g = m_deviceIoControlService->getDisinfectantVolume_g(); -#elif (defined PROJECT_TYPE_DRAW_BAR_BOX) - m_context.afterDisinfectantVolume_g = 0; -#else - m_context.afterDisinfectantVolume_g = 0; -#endif - - if (m_context.m_state != kstate_finished) { - m_context.m_state = kstate_finished; - } - m_disinfectionWorkState = 0; - takeStateSnapshot(m_context); - dumpDisinfectionLogsToCSV(m_context); - log(m_context); - pushDisinfectionPrinterTask(m_context); - finishDisinfection(m_context); - m_context.csvlogger = nullptr; - } else { - if (updatedval) { - log(m_context); - } - - if (m_context.firstLog || statechanged || zsteady_clock().elapsedTimeS(m_context.state_lastlog_tp) > DUMP_LOG_PERIOD) { - m_context.state_lastlog_tp = zsteady_clock().now(); - takeStateSnapshot(m_context); - dumpDisinfectionLogsToCSV(m_context); - m_context.firstLog = false; - } - } -} - -void DisinfectionCtrlService::changeDisinfectionParameter(int injection_pump_speed, // - int stoped_gs, // - int continued_gs, // - int stoped_satur, // - int continued_satur, // - int stoped_humi, // - int continued_humi) { - lock_guard lock(lock_); - m_context.injection_pump_speed = injection_pump_speed; - m_context.stoped_gs = stoped_gs; - m_context.continued_gs = continued_gs; - m_context.stoped_satur = stoped_satur; - m_context.continued_satur = continued_satur; - m_context.stoped_humi = stoped_humi; - m_context.continued_humi = continued_humi; - m_context.injection_pump_speed_changed = true; - - logger->info("changeDisinfectionParameter {} {} {} {} {} {} {}", // - injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi); -} void DisinfectionCtrlService::startDisinfection(int loglevel, // int injection_pump_speed, // @@ -739,255 +10,48 @@ void DisinfectionCtrlService::startDisinfection(int loglevel, // int stoped_humi, // int continued_humi // ) { - lock_guard lock(lock_); - - if (m_disinfectionThread) stopDisinfection(); - - initContext(m_context, loglevel, injection_pump_speed, stoped_gs, continued_gs, stoped_satur, continued_satur, stoped_humi, continued_humi); - m_disinfectionThread.reset(new Thread("m_disinfectionThread", [this]() { - ThisThread thisThread; - while (true) { - thisThread.sleepForMs(1000); - bool breakflag = false; - disinfectionLoop(breakflag); - if (breakflag) { - break; - } - } - })); - // + stopDisinfection(); + stopDraining(); + stopReplenishingFluids(); + m_disinfectionService->startDisinfection(loglevel, // + injection_pump_speed, // + stoped_gs, // + continued_gs, // + stoped_satur, // + continued_satur, // + stoped_humi, // + continued_humi); } -void DisinfectionCtrlService::stopDisinfection() { - lock_guard lock(lock_); - if (m_disinfectionThread) { - m_disinfectionThread->join(); - m_disinfectionThread = nullptr; - } -} - -int DisinfectionCtrlService::getDisinfectionWorkState() { return m_context.m_state; } - -int32_t DisinfectionCtrlService::getEstimatedRemainingTimeS() { - if (m_context.m_state == kstate_preheat) { - return getPreHeatRaminTimeS(); - } else if (m_context.m_state == kstate_disinfection) { - if (m_context.state_dvalue > 0) { - return m_context.state_remaintime; - } else { - return -1; - } - } else { - return 0; - } -} -int32_t DisinfectionCtrlService::getPreHeatRaminTimeS() { - int32_t remaintime = 0; - if (m_context.m_state == kstate_preheat) { - remaintime = m_context.pre_heat_time_s - zsteady_clock().elapsedTimeS(m_context.start_steady_tp); - if (remaintime < 0) { - remaintime = 0; - } - return remaintime; - } else { - return 0; - } -} - -string DisinfectionCtrlService::getDisinfectionID() { return m_context.m_disinfectionID; } -bool DisinfectionCtrlService::isPreheatState() { return m_context.m_state == kstate_preheat; } -#if (defined PROJECT_TYPE_LARGE_SPACE_DISINFECTION) || (defined PROJECT_TYPE_SMALL_SPACE_DISINFECTION) || (defined PROJECT_TYPE_PIPE_DISINFECTION) - -/******************************************************************************* - * // 加液 * - *******************************************************************************/ -int DisinfectionCtrlService::getReplenishingFluidsWorkState() { return m_replenishingFluidsWorkState; } -void DisinfectionCtrlService::startReplenishingFluids(int stopatg) { - lock_guard lock(lock_); - if (m_disinfectionThread) { - m_disinfectionThread->join(); - m_disinfectionThread = nullptr; - } - int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); - - int maxg = DISINFECTANT_BUCKET_CAPACITY; - - if (stopatg > maxg) { - logger->warn("start Replenishing fail, stopatg {} > maxg {}", stopatg, maxg); - stopatg = maxg; - } - - if (nowvolume > stopatg) { - logger->warn("start Replenishing fail, nowvolume {} > stopatg {}", nowvolume, stopatg); - return; - } - - m_disinfectionThread.reset(new Thread("disinfectionThread", [this, stopatg]() { - ThisThread thisThread; - m_deviceIoControlService->replenishingFluidsPump_open(); - logger->info("startReplenishingFluids {}g", stopatg); - while (!thisThread.getExitFlag()) { - int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); - logger->info("replenishingFluids {}g", nowvolume); - if (nowvolume > stopatg) { - break; - } - - if (nowvolume > MAX_VOLUME) { - logger->warn("replenishingFluids reach full level {}g", nowvolume); - break; - } - - thisThread.sleepForMs(1000); - } - logger->info("stopReplenishingFluids"); - // replenishingFluidsPump_close(); - m_deviceIoControlService->replenishingFluidsPump_close(); - m_replenishingFluidsWorkState = 0; - })); - - // - m_replenishingFluidsWorkState = 1; - logger->info("startReplenishingFluids "); +void DisinfectionCtrlService::changeDisinfectionParameter(int injection_pump_speed, // + int stoped_gs, // + int continued_gs, // + int stoped_satur, // + int continued_satur, // + int stoped_humi, // + int continued_humi // +) { + m_disinfectionService->changeDisinfectionParameter(injection_pump_speed, // + stoped_gs, // + continued_gs, // + stoped_satur, // + continued_satur, // + stoped_humi, // + continued_humi); } +void DisinfectionCtrlService::stopDisinfection() { m_disinfectionService->stopDisinfection(); } +void DisinfectionCtrlService::startReplenishingFluids(int stopatg) { m_addLiquidService->startReplenishingFluids(stopatg); } void DisinfectionCtrlService::stopReplenishingFluids() { - lock_guard lock(lock_); - if (m_disinfectionThread) { - m_disinfectionThread->join(); - m_disinfectionThread = nullptr; - } - - logger->info("stopReplenishingFluids"); - // replenishingFluidsPump_close(); - m_deviceIoControlService->replenishingFluidsPump_close(); - m_replenishingFluidsWorkState = 0; + stopDisinfection(); + stopDraining(); + stopReplenishingFluids(); + m_addLiquidService->stopReplenishingFluids(); } -/******************************************************************************* - * 排液 * - *******************************************************************************/ -void DisinfectionCtrlService::startDraining() { - lock_guard lock(lock_); - if (m_disinfectionThread) { - m_disinfectionThread->join(); - m_disinfectionThread = nullptr; - } - - m_disinfectionThread.reset(new Thread("disinfectionThread", [this]() { - ThisThread thisThread; - - m_deviceIoControlService->drainingPump_open(); - logger->info("startDraining "); - auto startdrainingtime = zsteady_clock().now(); - - zsteady_tp volumeReachZeroTime; - bool volumeReachZeroFlag = false; - - while (!thisThread.getExitFlag()) { - int32_t nowvolume = m_deviceIoControlService->getDisinfectantVolume_g(); - logger->info("draining remain {} g", nowvolume); - if (!volumeReachZeroFlag && nowvolume == 0) { - volumeReachZeroTime = zsteady_clock().now(); - volumeReachZeroFlag = true; - } - - if (volumeReachZeroFlag) { - logger->info("stopDraining after {} s", 30 - zsteady_clock().elapsedTimeS(volumeReachZeroTime)); - if (zsteady_clock().elapsedTimeS(volumeReachZeroTime) > 30) { - break; - } - } - - thisThread.sleepForMs(1000); - } - logger->info("stopDraining"); - // replenishingFluidsPump_close(); - m_deviceIoControlService->drainingPump_close(); - m_drainingWorkState = 0; - })); - - logger->info("startDraining"); - // drainingPump_open(); - m_drainingWorkState = 1; -} +void DisinfectionCtrlService::startDraining() { m_drainLiquidService->startDraining(); } void DisinfectionCtrlService::stopDraining() { - lock_guard lock(lock_); - if (m_disinfectionThread) { - m_disinfectionThread->join(); - m_disinfectionThread = nullptr; - } - logger->info("stopDraining"); - m_drainingWorkState = 0; - // drainingPump_close(); - m_deviceIoControlService->drainingPump_close(); -} -int DisinfectionCtrlService::getDrainingWorkState() { return m_drainingWorkState; } -#endif - -void DisinfectionCtrlService::updateH2O2SensorData(DisinfectionContext& context) { - auto& cx = context; - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - cx.h2o2[i] = m_deviceIoControlService->H2O2Sensor_readH2O2PPM(i); - } - - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - cx.humid[i] = m_deviceIoControlService->H2O2Sensor_readHumid(i); - } - - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - cx.temp[i] = m_deviceIoControlService->H2O2Sensor_readTemperature(i); - } - - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - cx.saturation[i] = m_deviceIoControlService->H2O2Sensor_readSaturation(i); - } - - cx.min_h2o2 = cx.h2o2[0]; - cx.max_h2o2 = cx.h2o2[0]; - cx.max_humid = cx.humid[0]; - cx.max_saturation = cx.saturation[0]; - - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - if (cx.h2o2[i] < cx.min_h2o2) { - cx.min_h2o2 = cx.h2o2[i]; - } - - if (cx.h2o2[i] > cx.max_h2o2) { - cx.max_h2o2 = cx.h2o2[i]; - } - - if (cx.humid[i] > cx.max_humid) { - cx.max_humid = cx.humid[i]; - } - - if (cx.saturation[i] > cx.max_saturation) { - cx.max_saturation = cx.saturation[i]; - } - } - - if (cx.max_h2o2 < 0) cx.max_h2o2 = 0; - if (cx.min_h2o2 < 0) cx.min_h2o2 = 0; - if (cx.max_humid < 0) cx.max_humid = 0; - if (cx.max_saturation < 0) cx.max_saturation = 0; -} - -void DisinfectionCtrlService::takeStateSnapshot(DisinfectionContext& context) { - auto& cx = context; - - shared_ptr snapshot = make_shared(); - snapshot->time = zsystem_clock().now(); - for (size_t i = 0; i < MAX_H2O2_SENSOR_NUM; i++) { - snapshot->h2o2[i] = cx.h2o2[i]; - snapshot->humid[i] = cx.humid[i]; - snapshot->temp[i] = cx.temp[i]; - snapshot->saturation[i] = cx.saturation[i]; - } - - snapshot->min_h2o2 = cx.min_h2o2; - snapshot->max_h2o2 = cx.max_h2o2; - snapshot->max_humid = cx.max_humid; - snapshot->max_saturation = cx.max_saturation; - snapshot->state = cx.m_state; - snapshot->dloglevel = cx.state_now_loglevel; - cx.stateSnapshotList.push_back(snapshot); + stopDisinfection(); + stopDraining(); + stopReplenishingFluids(); + m_drainLiquidService->stopDraining(); } diff --git a/service/disinfection_ctl_service.hpp b/service/disinfection_ctl_service.hpp index c679abd..8d1ba76 100644 --- a/service/disinfection_ctl_service.hpp +++ b/service/disinfection_ctl_service.hpp @@ -14,15 +14,10 @@ #include #include -#include "db/db_service.hpp" -#include "disinfection_logs_manager.hpp" -#include "disinfection_state.hpp" -#include "iflytop/components/zcanreceiver/zcanhost.hpp" -#include "iflytop/core/core.hpp" -#include "service/device_io_control_service.hpp" -#include "service/disinfection_printer_service.hpp" -#include "utils/dvalue_computer.hpp" -#include "zservice_container/zservice_container.hpp" +#include "disfection_ctl/add_liquid_service.hpp" +#include "disfection_ctl/disinfection_state.hpp" +#include "disfection_ctl/drain_liquid_service.hpp" +#include "disfection_ctl/disinfection_service.hpp" /** * @brief * @@ -44,30 +39,27 @@ class DisinfectionCtrlService : public enable_shared_from_this m_disinfectionThread; - shared_ptr m_deviceIoControlService; - shared_ptr m_dbService; - shared_ptr m_disinfectionLogsManager; - shared_ptr m_disinfectionPrinterService; - DValueComputer m_dvalueComputer; - - int m_disinfectionWorkState = 0; - int m_replenishingFluidsWorkState = 0; - int m_drainingWorkState = 0; // 消毒工作状态,0:未工作,1:工作中 + shared_ptr m_addLiquidService; + shared_ptr m_drainLiquidService; + shared_ptr m_disinfectionService; public: - DisinfectionContext m_context; + DisinfectionCtrlService(){} public: - DisinfectionCtrlService(); + void initialize() { + m_addLiquidService = make_shared(); + m_drainLiquidService = make_shared(); + m_disinfectionService = make_shared(); - public: - void initialize(); - /** - * @brief 开始消毒 - * - * @param loglevel 消毒等级 - */ + m_addLiquidService->initialize(); + m_drainLiquidService->initialize(); + m_disinfectionService->initialize(); + } + + shared_ptr getAddLiquidService() { return m_addLiquidService; } + shared_ptr getDrainLiquidService() { return m_drainLiquidService; } + shared_ptr getDisinfectionService() { return m_disinfectionService; } void startDisinfection(int loglevel, // int injection_pump_speed, // @@ -86,77 +78,14 @@ class DisinfectionCtrlService : public enable_shared_from_this createCSVLogger(string log_file_name); - void dumpDisinfectionLogsToCSV(DisinfectionContext& context); - - void pushDisinfectionPrinterTask(DisinfectionContext& context); - - void log(DisinfectionContext& context); - void takeStateSnapshot(DisinfectionContext& context); - void updateH2O2SensorData(DisinfectionContext& context); - - - private: }; } // namespace iflytop \ No newline at end of file diff --git a/service/disinfection_printer_service.hpp b/service/disinfection_printer_service.hpp index fd3bc45..eda5bfa 100644 --- a/service/disinfection_printer_service.hpp +++ b/service/disinfection_printer_service.hpp @@ -14,8 +14,8 @@ #include #include +#include "disfection_ctl/disinfection_state.hpp" #include "disinfection_logs_manager.hpp" -#include "disinfection_state.hpp" #include "iflytop/components/zcanreceiver/zcanhost.hpp" #include "iflytop/core/core.hpp" #include "service/device_io_control_service.hpp" diff --git a/service/disinfection_state.hpp b/service/disinfection_state.hpp deleted file mode 100644 index a1937c5..0000000 --- a/service/disinfection_state.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// Created by zwsd -// - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "configs/project_setting.hpp" -#include "iflytop/core/components/timeutils.hpp" -/** - * @brief - * - * service: DisinfectionCtrlService - * - * 监听事件: - * 依赖状态: - * 依赖服务: - * 作用: - * - */ - -namespace iflytop { -using namespace std; -using namespace core; - -class DisinfectionLogger; - -typedef enum { - kstate_idle = 0, // 空闲 - kstate_preheat = 1, // 预热 - kstate_disinfection = 2, // 消毒中-工作 - kstate_degradation = 4, // 降解中 - kstate_finished = 5, // 结束 - kstate_dehumidification_before_disinfection = 6, // 消毒前除湿 - kstate_dehumidification_after_disinfection = 7, // 消毒后除湿 - -} disinfection_state_t; - -class StateSnapshot { - public: - disinfection_state_t state; - zsystem_tp time; - - int32_t h2o2[MAX_H2O2_SENSOR_NUM]; // ppm - int32_t humid[MAX_H2O2_SENSOR_NUM]; // %RH - int32_t temp[MAX_H2O2_SENSOR_NUM]; // °C - int32_t saturation[MAX_H2O2_SENSOR_NUM]; // %RS - - int min_h2o2; - int max_h2o2; - int max_humid; - int max_saturation; - - float dloglevel; -}; - -class DisinfectionPrinterTask { - public: - string disinfection_id; - string usr; - - vector> stateSnapshotList; // 状态快照I - - int disinfectantUsage; // 消毒剂使用量 - - zsystem_tp start_tp; - zsystem_tp complete_tp; - - int targetLog; - int actualLog; - - int disinfectantVolume; // g -}; - -class DisinfectionContext { - public: - string m_disinfectionID; - disinfection_state_t m_state = kstate_idle; - zsteady_tp start_steady_tp; - zsystem_tp start_tp; - zsystem_tp complete_tp; - - /** - * @brief 消毒中配置 - */ - int pre_heat_time_s = 0; // 预热时间 - int stoped_gs = 0; // 停止H2O2浓度 - int continued_gs = 0; // 继续H2O2浓度 - int stoped_satur = 0; // 停止饱和度 - int continued_satur = 0; // 继续饱和度 - int stoped_humi = 0; // 停止湿度 - int continued_humi = 0; // 继续湿度 - - int injection_pump_speed; - bool injection_pump_speed_changed = false; - - float cfg_targetLoglevel = 0; - - /** - * @brief 运行状态 - */ - zsteady_tp state_last_compute_dvalue_tp; // 上次计算dvalue时间 - zsteady_tp state_lastlog_tp; // 上次日志时间 - int state_remaintime = 0; - float state_now_loglevel = 0; - float state_dvalue = 0; - bool state_is_disinfection_take_break; // 消毒工作中是否暂停工作 - /******************************************************************************* - * 传感器信息 * - *******************************************************************************/ - - int32_t h2o2[MAX_H2O2_SENSOR_NUM]; // ppm - int32_t humid[MAX_H2O2_SENSOR_NUM]; // %RH - int32_t temp[MAX_H2O2_SENSOR_NUM]; // °C - int32_t saturation[MAX_H2O2_SENSOR_NUM]; // %RS - - int min_h2o2; - int max_h2o2; - int max_humid; - int max_saturation; - - /******************************************************************************* - * 日志与统计 * - *******************************************************************************/ - shared_ptr csvlogger; // 日志记录器 - vector> stateSnapshotList; // 状态快照I - - int beforeDisinfectantVolume_g; // 消毒前消毒剂量 - int afterDisinfectantVolume_g; // 消毒后消毒剂量 - - bool firstLog; -}; - -} // namespace iflytop \ No newline at end of file