You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
824 lines
30 KiB
824 lines
30 KiB
#include "disinfection_ctl_service.hpp"
|
|
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
#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;
|
|
/**
|
|
* @brief
|
|
* 流程
|
|
* 预热:
|
|
*
|
|
* 风机开
|
|
* 1s
|
|
* 空压机
|
|
* 1s
|
|
* 蠕动泵
|
|
* 1s
|
|
*
|
|
*
|
|
* 关蠕动泵
|
|
* 1s
|
|
* 关空压机
|
|
* 1s
|
|
* 关风机
|
|
*
|
|
*/
|
|
|
|
// #define PRE_HEAT_TIME (2)
|
|
// #define PRE_HEAT_TIME (5 * 60)
|
|
|
|
#define DVALUE_COMPUTEPERIOD_TIME_S (10.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);
|
|
struct tm* tmp = 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);
|
|
}
|
|
|
|
DisinfectionCtrlService::DisinfectionCtrlService() {}
|
|
void DisinfectionCtrlService::initialize() {
|
|
GET_TO_SERVICE(m_zcanHost);
|
|
GET_TO_SERVICE(m_deviceIoControlService);
|
|
GET_TO_SERVICE(m_dbService);
|
|
GET_TO_SERVICE(m_disinfectionLogsManager);
|
|
|
|
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);
|
|
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);
|
|
}
|
|
static bool zfeq(float a, float b, float eps = 0.01) {
|
|
if (fabs(a - b) < eps) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
float DisinfectionCtrlService::getDisinfectionDValue(float ppm) { //
|
|
return m_dvalueComputer.computeDValue(ppm);
|
|
}
|
|
float DisinfectionCtrlService::computeNowLogLevel(DisinfectionContext& context) {
|
|
float dvalue = context.dvalue;
|
|
if (dvalue > 0) {
|
|
/**
|
|
* @brief 计算 m_nowLoglevel
|
|
*/
|
|
return context.m_nowLoglevel + DVALUE_COMPUTEPERIOD_TIME_S / (dvalue * 60);
|
|
}
|
|
return context.m_nowLoglevel;
|
|
}
|
|
|
|
void DisinfectionCtrlService::computeRemainTime(DisinfectionContext& context) {
|
|
/**
|
|
* @brief 计算Dvalue
|
|
*/
|
|
float dvalue = context.dvalue;
|
|
|
|
if (dvalue > 0) {
|
|
/**
|
|
* @brief 计算 m_nowLoglevel
|
|
*/
|
|
if (context.m_targetLoglevel >= context.m_nowLoglevel) {
|
|
context.m_remaintime = (context.m_targetLoglevel - context.m_nowLoglevel) * (dvalue * 60);
|
|
} else {
|
|
context.m_remaintime = 0;
|
|
}
|
|
} else {
|
|
//
|
|
}
|
|
|
|
logger->info("computeRemainTime minh2o2 {} dvalue {}", context.min_h2o2, dvalue);
|
|
}
|
|
|
|
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.m_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("");
|
|
|
|
// m_remaintime = loglevel * 20 * 60; // 计算总的加热时间
|
|
context.m_remaintime = context.pre_heat_time_s + loglevel * 90 * 60; // 计算总的加热时间
|
|
m_disinfectionWorkState = 1;
|
|
context.m_targetLoglevel = loglevel;
|
|
context.m_nowLoglevel = 0;
|
|
// m_context.m_preheatFlag = true;
|
|
m_context.dvalue = 0;
|
|
// m_context.stopedflag = false;
|
|
|
|
m_context.m_state = kpreheat;
|
|
|
|
m_context.m_starttp = zsteady_clock().now();
|
|
m_context.m_starttp_str = getTime();
|
|
|
|
m_zcanHost->warning_light_ctrl_c1002(1, 0, 0, 1, 0);
|
|
m_deviceIoControlService->heartingPlate_setPower(true);
|
|
context.csvlogger = createCSVLogger(context.m_disinfectionID);
|
|
}
|
|
|
|
shared_ptr<DisinfectionLogger> DisinfectionCtrlService::createCSVLogger(string log_file_name) {
|
|
shared_ptr<DisinfectionLogger> _logger = m_disinfectionLogsManager->createNewLogger(log_file_name);
|
|
// ZIconv::utf8_to_gb2312(str)
|
|
|
|
// context.csvlogger->write(
|
|
// "Date," // 1
|
|
// "H2O20(ppm),Temp0(C),RH0(%RH),RS0(%RS)," // 2,3,4,5
|
|
// "H2O21(ppm),Temp1(C),RH1(%RH),RS1(%RS)," // 6,7,8,9
|
|
// "H2O22(ppm),Temp2(C),RH2(%RH),RS2(%RS)," // 10,11,12,13
|
|
// "Dvalue,Loglevel,Targetloglevel," // 14,15,16
|
|
// "Heating,Blower,Compressor,Pump(g/min)," // 17,18,19,20
|
|
// "Disinfectant Volume(g)," // 21,
|
|
// "Remaining time (s)\n" // 22
|
|
// );
|
|
|
|
_logger->write(
|
|
fmt::format("{},"
|
|
"{},{},{},{},"
|
|
"{},{},{},{},"
|
|
"{},{},{},{},"
|
|
"{},{},{},"
|
|
"{},{},{},{},"
|
|
"{},{}"
|
|
"\n",
|
|
ZIconv::noChange("日期"), //
|
|
ZIconv::noChange("过氧化氢浓度(PPM)"), ZIconv::noChange("温度(C)"), ZIconv::noChange("相对湿度"), ZIconv::noChange("相对饱和度"), //
|
|
ZIconv::noChange("远端-过氧化氢浓度1(PPM)"), ZIconv::noChange("远端-温度1(C)"), ZIconv::noChange("远端-相对湿度1"), ZIconv::noChange("远端-相对饱和度1"), //
|
|
ZIconv::noChange("远端-过氧化氢浓度2(PPM)"), ZIconv::noChange("远端-温度2(C)"), 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)")));
|
|
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.dvalue <= 0) {
|
|
dvalue = 0;
|
|
} else {
|
|
dvalue = m_context.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.m_nowLoglevel, (int32_t)m_context.m_targetLoglevel, //
|
|
ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), //
|
|
m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime)));
|
|
#endif
|
|
}
|
|
|
|
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.dvalue <= 0) {
|
|
dvalue = 0;
|
|
} else {
|
|
dvalue = m_context.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.max_h2o2, m_context.min_h2o2, m_context.max_humid, m_context.max_saturation, //
|
|
(int32_t)dvalue, (int32_t)m_context.m_nowLoglevel, (int32_t)m_context.m_targetLoglevel, //
|
|
ds->heatingStrip_getstate(), ds->airBlower_getstate(), ds->airCompressor_getstate(), ds->sprayLiquidPump_getGPM(), //
|
|
m_deviceIoControlService->getDisinfectantVolume_g(), formattimeS(remaintime)));
|
|
#endif
|
|
}
|
|
|
|
void DisinfectionCtrlService::finishDisinfection(DisinfectionContext& context) {
|
|
context.m_remaintime = 0;
|
|
logger->info("stop disinfection {}", context.m_disinfectionID);
|
|
|
|
// 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_zcanHost->warning_light_ctrl_c1002(1, 0, 0, 0, 0);
|
|
context.csvlogger = nullptr;
|
|
}
|
|
|
|
void DisinfectionCtrlService::processPreheatState(DisinfectionContext& context) {
|
|
int hasstarttime = zsteady_clock().elapsedTimeS(context.m_starttp);
|
|
|
|
// logger->info("preheat {}", context.m_disinfectionID);
|
|
if ((context.m_state == kpreheat && hasstarttime > m_context.pre_heat_time_s)) {
|
|
logger->info("preheat finished {}", context.m_disinfectionID);
|
|
m_deviceIoControlService->airBlower_setState(true);
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->airCompressor_setState(true);
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
|
|
context.m_state = kdisinfection;
|
|
} else {
|
|
logger->info("{}: preheat {}", context.m_disinfectionID, m_context.pre_heat_time_s - hasstarttime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
* 消毒中状态处理
|
|
*/
|
|
void DisinfectionCtrlService::processDisinfectionState(DisinfectionContext& context) {
|
|
ZCHECK(context.m_state == kdisinfection || context.m_state == kdisinfection_take_a_break, "state error");
|
|
|
|
/**
|
|
* @brief 周期性计算剩余时间
|
|
*/
|
|
|
|
/**
|
|
* @brief 根据湿度启停喷雾
|
|
*/
|
|
if (m_context.m_state == kdisinfection) {
|
|
/**
|
|
* @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) {
|
|
m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
|
|
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");
|
|
|
|
m_deviceIoControlService->sprayLiquidPump_close();
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->airCompressor_setState(false);
|
|
|
|
// m_context.sprayLiquidFlag = false;
|
|
m_context.m_state = kdisinfection_take_a_break;
|
|
}
|
|
} 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");
|
|
|
|
m_deviceIoControlService->sprayLiquidPump_open(context.injection_pump_speed);
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->airCompressor_setState(true);
|
|
m_context.m_state = kdisinfection;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DisinfectionCtrlService::disinfectionLoop(bool& breakflag) {
|
|
// logger->info("disinfection running {} {}s preheatFlag:{}", m_context.m_disinfectionID, m_context.m_remaintime, m_context.m_preheatFlag);
|
|
m_context.m_remaintime--;
|
|
bool forcelog = false;
|
|
if (m_context.m_remaintime < 0) {
|
|
m_context.m_remaintime = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief 更新传感器信息
|
|
*/
|
|
updateH2O2SensorData(m_context);
|
|
/**
|
|
* @brief 计算D值
|
|
*/
|
|
m_context.dvalue = getDisinfectionDValue(m_context.min_h2o2);
|
|
|
|
if (zsteady_clock().elapsedTimeS(m_context.m_lastComputeDvalueTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
|
|
m_context.m_lastComputeDvalueTp = zsteady_clock().now();
|
|
//
|
|
if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
|
|
m_context.m_nowLoglevel = computeNowLogLevel(m_context);
|
|
computeRemainTime(m_context);
|
|
}
|
|
}
|
|
|
|
if (m_context.m_state == kpreheat) {
|
|
/**
|
|
* @brief 预热中
|
|
*/
|
|
processPreheatState(m_context);
|
|
} else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
|
|
/**
|
|
* @brief 消毒中
|
|
*/
|
|
processDisinfectionState(m_context);
|
|
//
|
|
if (m_context.m_remaintime <= 0 && m_context.m_nowLoglevel > (m_context.m_targetLoglevel + 0.01)) {
|
|
m_context.m_remaintime = 0;
|
|
m_context.m_nowLoglevel = m_context.m_targetLoglevel + 0.01;
|
|
logger->info("disinfection finished {},but waitting for h2o2 to safe", m_context.m_disinfectionID);
|
|
m_deviceIoControlService->sprayLiquidPump_close();
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->airCompressor_setState(false);
|
|
usleep(1000 * 1000);
|
|
m_deviceIoControlService->heartingPlate_setPower(false);
|
|
m_context.m_state = kwait_for_h2o2_down;
|
|
forcelog = true;
|
|
}
|
|
|
|
} else if (m_context.m_state == kwait_for_h2o2_down) {
|
|
/**
|
|
* @brief 等待h2o2浓度下降
|
|
*/
|
|
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");
|
|
breakflag = true;
|
|
forcelog = true;
|
|
m_context.m_state = kfinished;
|
|
}
|
|
} else {
|
|
ZCHECK(false, "state error");
|
|
}
|
|
|
|
if (forcelog || zsteady_clock().elapsedTimeS(m_context.m_lastlogTp) > DVALUE_COMPUTEPERIOD_TIME_S) {
|
|
m_context.m_lastlogTp = zsteady_clock().now();
|
|
dumpDisinfectionLogsToCSV(m_context);
|
|
log(m_context);
|
|
}
|
|
}
|
|
|
|
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<recursive_mutex> lock(lock_);
|
|
// logger->info("changeInjectionPumpSpeed {}=>{}", m_context.injection_pump_speed, speed);
|
|
// m_context.injection_pump_speed = speed;
|
|
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, //
|
|
int stoped_gs, //
|
|
int continued_gs, //
|
|
int stoped_satur, //
|
|
int continued_satur, //
|
|
int stoped_humi, //
|
|
int continued_humi //
|
|
) {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
|
|
/**
|
|
* @TODO
|
|
* 检查当前环境湿度,湿度过大,不允许消毒
|
|
*/
|
|
|
|
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 (!thisThread.getExitFlag()) {
|
|
thisThread.sleepForMs(1000);
|
|
bool breakflag = false;
|
|
disinfectionLoop(breakflag);
|
|
if (breakflag) {
|
|
break;
|
|
}
|
|
}
|
|
printfDisinfectionContextResult();
|
|
//
|
|
finishDisinfection(m_context);
|
|
}));
|
|
//
|
|
}
|
|
|
|
void DisinfectionCtrlService::printfDisinfectionContextResult() {
|
|
/**
|
|
* @brief
|
|
* = = = = = = = = = = = = = = =
|
|
* 全思美特
|
|
* 操作人 XXXXX
|
|
* 开始时间 2021-03-10 10:00:00
|
|
* 结束时间 2021-03-10 10:00:00
|
|
* 总耗时 01:59
|
|
* 目标LOG 6
|
|
* 实际LOG 6
|
|
* = = = = = = = = = = = = = = =
|
|
*
|
|
*/
|
|
|
|
auto dio = m_deviceIoControlService;
|
|
auto ds = GET_SERVICE(DeviceStateService);
|
|
m_context.m_endtp_str = getTime();
|
|
int totaltime = zsteady_clock().elapsedTimeS(m_context.m_starttp) / 60;
|
|
|
|
dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
|
|
dio->printerPrintf(fmt::format(" 全思美特\n"));
|
|
dio->printerPrintf(fmt::format("操作人 {}\n", ds->getLoginUid()));
|
|
dio->printerPrintf(fmt::format("开始时间 {}\n", m_context.m_starttp_str));
|
|
dio->printerPrintf(fmt::format("结束时间 {}\n", m_context.m_endtp_str));
|
|
dio->printerPrintf(fmt::format("总耗时 {}:{}\n", totaltime / 60, totaltime % 60));
|
|
dio->printerPrintf(fmt::format("目标LOG {}\n", (int)m_context.m_targetLoglevel));
|
|
dio->printerPrintf(fmt::format("实际LOG {}\n", (int)m_context.m_nowLoglevel));
|
|
dio->printerPrintf(fmt::format("= = = = = = = = = = = = = = = \n"));
|
|
dio->printerPrintf(fmt::format("\n"));
|
|
dio->printerPrintf(fmt::format("\n"));
|
|
dio->printerPrintf(fmt::format("\n"));
|
|
|
|
// getTime
|
|
// dio->printerPrintf(fmt::format("开始时间 {}\n", zsteady_clock().formatTime(m_context.m_starttp)));
|
|
}
|
|
|
|
int DisinfectionCtrlService::getDisinfectionWorkState() { return m_context.m_state; }
|
|
|
|
void DisinfectionCtrlService::stopDisinfection() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
if (m_disinfectionThread) {
|
|
m_disinfectionThread->join();
|
|
m_disinfectionThread = nullptr;
|
|
}
|
|
m_context.m_state = kfinished;
|
|
m_disinfectionWorkState = 0;
|
|
}
|
|
|
|
int32_t DisinfectionCtrlService::getEstimatedRemainingTimeS() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
if (m_context.m_state == kpreheat) {
|
|
return getPreHeatRaminTimeS();
|
|
} else if (m_context.m_state == kdisinfection || m_context.m_state == kdisinfection_take_a_break) {
|
|
if (m_context.dvalue > 0) {
|
|
return m_context.m_remaintime;
|
|
} else {
|
|
return -1;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
int32_t DisinfectionCtrlService::getPreHeatRaminTimeS() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
int32_t remaintime = 0;
|
|
if (m_context.m_state == kpreheat) {
|
|
remaintime = m_context.pre_heat_time_s - zsteady_clock().elapsedTimeS(m_context.m_starttp);
|
|
if (remaintime < 0) {
|
|
remaintime = 0;
|
|
}
|
|
return remaintime;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
string DisinfectionCtrlService::getDisinfectionID() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
return m_context.m_disinfectionID;
|
|
}
|
|
bool DisinfectionCtrlService::isPreheatState() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
return m_context.m_state == kpreheat;
|
|
}
|
|
|
|
int DisinfectionCtrlService::getReplenishingFluidsWorkState() { return m_replenishingFluidsWorkState; }
|
|
int DisinfectionCtrlService::getDrainingWorkState() { return m_drainingWorkState; }
|
|
|
|
/*******************************************************************************
|
|
* // 加液 *
|
|
*******************************************************************************/
|
|
/**
|
|
* @brief 开始加液
|
|
*
|
|
* @param stopatg
|
|
*/
|
|
void DisinfectionCtrlService::startReplenishingFluids(int stopatg) {
|
|
lock_guard<recursive_mutex> 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 ");
|
|
}
|
|
/**
|
|
* @brief 停止加液
|
|
*
|
|
*/
|
|
void DisinfectionCtrlService::stopReplenishingFluids() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
if (m_disinfectionThread) {
|
|
m_disinfectionThread->join();
|
|
m_disinfectionThread = nullptr;
|
|
}
|
|
|
|
logger->info("stopReplenishingFluids");
|
|
// replenishingFluidsPump_close();
|
|
m_deviceIoControlService->replenishingFluidsPump_close();
|
|
m_replenishingFluidsWorkState = 0;
|
|
}
|
|
/*******************************************************************************
|
|
* 排液 *
|
|
*******************************************************************************/
|
|
/**
|
|
* @brief 开始排液
|
|
*
|
|
*/
|
|
void DisinfectionCtrlService::startDraining() {
|
|
lock_guard<recursive_mutex> 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;
|
|
}
|
|
/**
|
|
* @brief 停止排液体
|
|
*/
|
|
void DisinfectionCtrlService::stopDraining() {
|
|
lock_guard<recursive_mutex> lock(lock_);
|
|
if (m_disinfectionThread) {
|
|
m_disinfectionThread->join();
|
|
m_disinfectionThread = nullptr;
|
|
}
|
|
logger->info("stopDraining");
|
|
m_drainingWorkState = 0;
|
|
// drainingPump_close();
|
|
m_deviceIoControlService->drainingPump_close();
|
|
}
|
|
|
|
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;
|
|
}
|