#include "main_control_service.hpp" #include "configs/project_setting.hpp" #include "iflytop/components/zcanreceiver/zcanreceiverhost.hpp" #include "iflytop/core/components/stringutils.hpp" #include "iflytop/core/core.hpp" #include "version.hpp" using namespace iflytop; using namespace core; using namespace std; using namespace nlohmann; #define BIND static void getJsonValFromJson(json j, int& val) { if (j.is_string()) { string valstr = j; val = atoi(valstr.c_str()); } else if (j.is_number()) { val = j; } else { throw std::runtime_error("getJsonValFromJson(int) error"); } } template static T jsonGet(json j) { T val; getJsonValFromJson(j, val); return val; } void MainControlService::dosystem(string order) { logger->info("do:{}", order); system(order.c_str()); } void MainControlService::initialize() { GET_TO_SERVICE(m_zconfig); // system("systemctl restart zchromium.service"); // m_dbService.reset(new DBService()); // m_dbService->initialize(); BUILD_AND_REG_SERRVICE(DBService); GET_SERVICE(DBService)->initialize(); GET_TO_SERVICE(m_dbService); /** * @brief 构造系统中的单例服务 */ BUILD_AND_REG_SERRVICE(DeviceStateService); GET_SERVICE(DeviceStateService)->initialize(); GET_TO_SERVICE(m_deviceStateService); BUILD_AND_REG_SERRVICE(ZCanHost); GET_SERVICE(ZCanHost)->initialize(m_zconfig->get_iflytopSubDeviceCanIFName(), m_zconfig->get_iflytopSubDeviceCanBitrate(), false); GET_TO_SERVICE(m_zcanhost); BUILD_AND_REG_SERRVICE(DisinfectionLogsManager); GET_SERVICE(DisinfectionLogsManager)->initialize(); GET_TO_SERVICE(m_disinfectionLogsManager); BUILD_AND_REG_SERRVICE(DeviceIoControlService); GET_SERVICE(DeviceIoControlService)->initialize(); GET_TO_SERVICE(m_deviceIoControlService); m_deviceIoControlService->startScan(); /** * @brief Get the to service object */ m_disinfectionCtrlService.reset(new DisinfectionCtrlService()); m_disinfectionCtrlService->initialize(); m_restfulServer.reset(new RestfulServer()); m_restfulServer->regAPI("/hello_world", RESTFUL_SERVER_BIND(MainControlService::hello_world)); m_restfulServer->regAPI("/api1/script_processer/doscript", RESTFUL_SERVER_BIND(MainControlService::doscript)); m_restfulServer->regAPI("/api1/script_processer/stopscript", RESTFUL_SERVER_BIND(MainControlService::stopscript)); m_restfulServer->start(20000, 20001, "0.0.0.0"); m_iflytopwsService.reset(new IflytopFrontEndService()); m_iflytopwsService->initialize("0.0.0.0"); m_iflytopwsService->onMessage.connect([this](weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; if (cmdstr != "getState") { logger->info("rx:{}", cmd.dump()); } processFrontEndMessage(webSocket, cmd, receipt); if (cmdstr != "getState") { logger->info("tx:{}", receipt.dump()); } }); m_iflytopwsService->onUdpCmdMessage.connect([this](struct sockaddr_in* from, char* data, size_t len) { // for (size_t i = 0; i < len; i++) { if (data[i] == '\r' || data[i] == '\n') { data[i] = '\0'; } } bool execsuc = false; for (size_t i = 0; i < len; i++) { if (data[i] != '\0') { int inext = strlen(&data[i]) + i; { string retmsg; execsuc = m_zcanhost->execcmd(string(&data[i]), retmsg); string retmsgstr = fmt::format("{},{}", execsuc ? "suc" : "fail", retmsg); m_iflytopwsService->sendToUDP(from, retmsgstr.c_str(), retmsgstr.size()); } i = inext; if (!execsuc) { break; } } } }); m_iflytopwsService->startListen(); m_reportThread.reset(new Thread("reportThread", [this]() { ThisThread thisThread; while (!thisThread.getExitFlag()) { json report; report["command"] = "RealtimeSensorDataReport"; report["sensor_data"] = createSensorDataJson(); m_iflytopwsService->sendReport(report); thisThread.sleepForMs(1000); } })); }; json MainControlService::createSensorDataJson() { json report; report["airCompressor"]["io1"] = m_deviceIoControlService->airCompressor_getio1(); report["airCompressor"]["io2"] = m_deviceIoControlService->airCompressor_getio2(); report["airCompressor"]["currentVal"] = m_deviceIoControlService->airCompressor_getcurrentValue(); report["airBlower"]["io1"] = m_deviceIoControlService->airBlower_getio1(); report["airBlower"]["io2"] = m_deviceIoControlService->airBlower_getio2(); report["airBlower"]["currentVal"] = m_deviceIoControlService->airBlower_getcurrentValue(); report["heatingStrip"]["io1"] = m_deviceIoControlService->heatingStrip_getio1(); report["heatingStrip"]["io2"] = m_deviceIoControlService->heatingStrip_getio2(); report["heatingStrip"]["currentVal"] = m_deviceIoControlService->heatingStrip_getcurrentValue(); report["sprinklerPumpRPM"] = m_deviceIoControlService->sprayLiquidPump_getRPM(); report["chargingPumpRPM"] = m_deviceIoControlService->getChargingPump_PumpRPM(); report["sprinklerPumpGPM"] = m_deviceIoControlService->sprayLiquidPump_getGPM(); // report["chargingPumpGPM"] = m_deviceIoControlService->getChargingPump_PumpGPM(); report["waterImmersionSensor1"] = m_deviceIoControlService->getWaterImmersionSensor1(); report["waterImmersionSensor2"] = m_deviceIoControlService->getWaterImmersionSensor2(); // Water immersion sensor report["disinfectant_volume"] = m_deviceIoControlService->getDisinfectantVolume_g(); // report["h2o2_1"] = m_deviceIoControlService->getH2O2SenSorData1().h2o2; report["h2o2_1"] = m_deviceIoControlService->getH2O2SenSorData1().h2o2; report["temp_1"] = m_deviceIoControlService->getH2O2SenSorData1().temp; report["humid_1"] = m_deviceIoControlService->getH2O2SenSorData1().humid; report["saturation_1"] = m_deviceIoControlService->getH2O2SenSorData1().saturation + 1; // 为了让曲线不重叠 // logger->info("m_deviceIoControlService->getH2O2SenSorData1().h2o2 {}", m_deviceIoControlService->getH2O2SenSorData1().h2o2); report["h2o2_2"] = -1; report["temp_2"] = -1; report["humid_2"] = -1; report["saturation_2"] = -1; report["h2o2_3"] = -1; report["temp_3"] = -1; report["humid_3"] = -1; report["saturation_3"] = -1; return report; } // {"command":"startReplenishingFluids","messageId":"startReplenishingFluids","stopAt":123} void MainControlService::processFrontEndMessage_userOperate(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; /******************************************************************************* * LOGIN_CMD * *******************************************************************************/ if (cmdstr == "login") { string uid = cmd["userid"]; string pwd = cmd["passwd"]; if (uid == "admin" && pwd == "iflytop9973") { m_deviceStateService->setLoginState("admin", 0, 1); logger->info("user {} login success", "admin"); } else { if (!m_dbService->isUserExist(uid)) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kuser_not_exist); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kuser_not_exist, ""); return; } if (!m_dbService->ispasswdCorrect(uid, pwd)) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kpasswd_error); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kpasswd_error, ""); return; } m_deviceStateService->setLoginState(uid, m_dbService->getUser(uid)->permission_level, m_dbService->getUser(uid)->visible); logger->info("user {} login success", uid); } return; } /******************************************************************************* * unlogin * *******************************************************************************/ if (cmdstr == "unlogin") { m_deviceStateService->unlogin(); logger->info("user unlogin success"); return; } /******************************************************************************* * chpasswd * *******************************************************************************/ if (cmdstr == "chpasswd") { string uid = cmd["userId"]; string newpasswd = cmd["newpasswd"]; string passwd = cmd["passwd"]; logger->info("changet passwd {} {}", uid, passwd); if (!m_dbService->isUserExist(uid)) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kuser_not_exist); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kuser_not_exist, ""); return; } if (!m_dbService->ispasswdCorrect(uid, passwd)) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kpasswd_error); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kpasswd_error, ""); return; } m_dbService->changePasswd(uid, newpasswd); return; } if (cmdstr == "addUser") { string uid = cmd["uid"]; string passwd = cmd["passwd"]; int permission_level = jsonGet(cmd["permission_level"]); m_dbService->addUser(uid, passwd, permission_level); return; } if (cmdstr == "delUser") { int id = jsonGet(cmd["id"]); m_dbService->delUser(id); return; } if (cmdstr == "updateUserPermissionLevel") { int id = jsonGet(cmd["id"]); int permission_level = jsonGet(cmd["permission_level"]); m_dbService->updateUserPermissionLevel(id, permission_level); return; } if (cmdstr == "getAllUser") { auto users = m_dbService->getAllUserJson(); receipt["dbval"] = users; return; } } void MainControlService::processFrontEndMessage_systemOperate(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; /******************************************************************************* * shutdown * *******************************************************************************/ if (cmdstr == "shutdown") { int delayms = jsonGet(cmd["delayms"]); logger->info("shutdown {} ms", delayms); m_autoshutdownThread.reset(new Thread("autoShutdown", [delayms, this]() { ThisThread thisThread; thisThread.sleepForMs(delayms); dosystem("shutdown -h now"); })); return; } if (cmdstr == "updateDate") { #if 0 { "command":"updateDate", "messageId":"1111222333444555", "year":2023, "month":8, "day":25, } #endif int32_t year = jsonGet(cmd["year"]); int32_t month = jsonGet(cmd["month"]); int32_t day = jsonGet(cmd["day"]); logger->info("updateDate {} {} {}", year, month, day); // date -s "2023-01-02 02:32:32" dosystem(fmt::format("date -s \"{}{:02}{:02} `date +%T`\"", year, month, day).c_str()); dosystem(fmt::format("hwclock -w").c_str()); return; } if (cmdstr == "updateTime") { #if 0 { "command":"updateTime", "messageId":"1111222333444555", "hour":11, "min":12, "second":13, } #endif int32_t hour = jsonGet(cmd["hour"]); int32_t min = jsonGet(cmd["min"]); int32_t second = jsonGet(cmd["second"]); logger->info("updateDate {}:{}:{}", hour, min, second); // date -s "2023-01-02 02:32:32" dosystem(fmt::format("date -s \"`date +%Y-%m-%d` {:02}:{:02}:{:02}\"", hour, min, second).c_str()); dosystem(fmt::format("hwclock -w").c_str()); return; } } void MainControlService::processFrontEndMessage_Disinfection(weak_ptr webSocket, json& cmd, json& receipt) { /******************************************************************************* * 消毒相关指令 * *******************************************************************************/ string cmdstr = cmd["command"]; if (cmdstr == "startDisinfection") { m_disinfectionCtrlService->startDisinfection(jsonGet(cmd["loglevel"]), // m_dbService->getSettingVal("injection_pump_speed"), // m_dbService->getSettingVal("stoped_gs"), // m_dbService->getSettingVal("continued_gs"), // m_dbService->getSettingVal("stoped_satur"), // m_dbService->getSettingVal("continued_satur"), // m_dbService->getSettingVal("stoped_humi"), // m_dbService->getSettingVal("continued_humi")); return; } if (cmdstr == "changeDisinfectionParameter") { m_disinfectionCtrlService->changeDisinfectionParameter(jsonGet(cmd["injection_pump_speed"]), // jsonGet(cmd["stoped_gs"]), // jsonGet(cmd["continued_gs"]), // jsonGet(cmd["stoped_satur"]), // jsonGet(cmd["continued_satur"]), // jsonGet(cmd["stoped_humi"]), // jsonGet(cmd["continued_humi"])); return; } if (cmdstr == "stopDisinfection") { m_disinfectionCtrlService->stopDisinfection(); return; } if (cmdstr == "startReplenishingFluids") { int16_t stopAt = jsonGet(cmd["stopAt"]); logger->info("startReplenishingFluids {}", stopAt); m_disinfectionCtrlService->startReplenishingFluids(stopAt); return; } if (cmdstr == "stopReplenishingFluids") { logger->info("stopReplenishingFluids"); m_disinfectionCtrlService->stopReplenishingFluids(); return; } if (cmdstr == "startDraining") { logger->info("startDraining"); m_disinfectionCtrlService->startDraining(); return; } if (cmdstr == "stopDraining") { logger->info("stopDraining"); m_disinfectionCtrlService->stopDraining(); return; } } void MainControlService::processFrontEndMessage_test(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; if (cmdstr == "test_sprayLiquidPumpCtrl") { int ctrl = jsonGet(cmd["ctrl"]); int speed = jsonGet(cmd["speed"]); if (ctrl == 1) { m_deviceIoControlService->sprayLiquidPump_open_for_test(speed); } else if (ctrl == -1) { m_deviceIoControlService->sprayLiquidPump_open_for_test(-speed); } else { m_deviceIoControlService->sprayLiquidPump_close(); } return; } if (cmdstr == "test_replenishingFluidsPumpCtrl") { int ctrl = jsonGet(cmd["ctrl"]); int speed = jsonGet(cmd["speed"]); if (ctrl == 1) { m_deviceIoControlService->replenishingFluidsPump_open_for_test(speed); } else if (ctrl == -1) { m_deviceIoControlService->replenishingFluidsPump_open_for_test(-speed); } else { m_deviceIoControlService->replenishingFluidsPump_close_for_test(); } return; } /******************************************************************************* * 执行测试指令 * *******************************************************************************/ // { // "command":"exceCanCmd", // "cancmd": "", // } if (cmdstr == "exceCanCmd") { string cancmd = cmd["cancmd"]; logger->info("exceCanCmd {}", cancmd); string receipt_str; bool suc = m_zcanhost->execcmd(cancmd, receipt_str); receipt["receipt_str"] = receipt_str; if (!suc) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kfail); } return; } } void MainControlService::processFrontEndMessage_setting(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; if (cmdstr == "getAllSetting") { auto dbval = m_dbService->getAllSettingJson(); receipt["dbval"] = dbval; return; } if (cmdstr == "setSettingVal") { string settingName = cmd["settingName"]; int settingVal = jsonGet(cmd["settingVal"]); bool suc = m_dbService->setSettingVal(settingName, settingVal); if (!suc) { receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kdb_operate_error); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kdb_operate_error, "setSettingVal fail"); } return; } } void MainControlService::processFrontEndMessage_processFormulaCmd(weak_ptr webSocket, json& cmd, json& receipt) { /** * @brief 配方操作 */ string cmdstr = cmd["command"]; if (cmdstr == "startFormula") { int id = jsonGet(cmd["id"]); auto formul = m_dbService->getFormula(id); if (!formul) { logger->error("formula id {} not exist", id); receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kdb_operate_error); receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kdb_operate_error, ""); return; } m_disinfectionCtrlService->startDisinfection(atoi(formul->loglevel.c_str()), // atoi(formul->injection_pump_speed.c_str()), // atoi(formul->stoped_gs.c_str()), // atoi(formul->continued_gs.c_str()), // atoi(formul->stoped_satur.c_str()), // atoi(formul->continued_satur.c_str()), // atoi(formul->stoped_humi.c_str()), // atoi(formul->continued_humi.c_str())); // return; } if (cmdstr == "getAllFormula") { receipt["formula"] = m_dbService->getAllFormulaJson(); return; } if (cmdstr == "addFormula") { m_dbService->addFormula(cmd["formula_id"], // jsonGet(cmd["stoped_gs"]), // jsonGet(cmd["continued_gs"]), // jsonGet(cmd["stoped_satur"]), // jsonGet(cmd["continued_satur"]), // jsonGet(cmd["stoped_humi"]), // jsonGet(cmd["continued_humi"]), // jsonGet(cmd["injection_pump_speed"])); return; } if (cmdstr == "delFormula") { m_dbService->delFormula(jsonGet(cmd["id"])); return; } if (cmdstr == "updateFormula") { string val_str; if (cmd["val"].is_string()) { val_str = cmd["val"]; } else { val_str = std::to_string(cmd["val"].get()); } m_dbService->updateFormula(jsonGet(cmd["id"]), cmd["column"], val_str); return; } } void MainControlService::processFrontEndMessage_processBehaviorRecordCmd(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; if (cmdstr == "getUserBehaviorRecordDescJson") { receipt["records"] = m_dbService->getUserBehaviorRecordDescJson(jsonGet(cmd["page"]), jsonGet(cmd["page_size"])); return; } if (cmdstr == "cleanUserBehaviorRecord") { m_dbService->cleanUserBehaviorRecord(); return; } // 导入用户行为测试数据 if (cmdstr == "importTestData") { for (size_t i = 0; i < 100; i++) { logger->info("addUserBehaviorRecord {}", i); m_dbService->addUserBehaviorRecord("admin", kbehavior_login, "(admin)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_logout, "(admin)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_add_user, "(zhaohe)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_del_user, "(zhaohe)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_update_user_permission_level, "(zhaohe,3)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_update_user_passwd, "()"); m_dbService->addUserBehaviorRecord("admin", kbehavior_set_setting_val, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_add_formula, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_del_formula, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_update_formula, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_do_disinfection, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_stop_disinfection, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_do_formula, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_update_setting_val_on_disinfection, "(....)"); m_dbService->addUserBehaviorRecord("admin", kbehavior_export_data, "(....)"); } return; } } void MainControlService::processFrontEndMessage(weak_ptr webSocket, json& cmd, json& receipt) { string cmdstr = cmd["command"]; processFrontEndMessage_userOperate(webSocket, cmd, receipt); processFrontEndMessage_systemOperate(webSocket, cmd, receipt); processFrontEndMessage_Disinfection(webSocket, cmd, receipt); processFrontEndMessage_test(webSocket, cmd, receipt); processFrontEndMessage_setting(webSocket, cmd, receipt); processFrontEndMessage_processFormulaCmd(webSocket, cmd, receipt); processFrontEndMessage_processBehaviorRecordCmd(webSocket, cmd, receipt); /******************************************************************************* * getState * *******************************************************************************/ if (cmdstr == "getState") { receipt["state"]["isLogin"] = m_deviceStateService->isLogin(); receipt["state"]["loginuser"] = m_deviceStateService->getLoginUid(); receipt["state"]["permissionLevel"] = m_deviceStateService->getLoginPermissionLevel(); // receipt["state"]["workState"] = m_disinfectionCtrlService->isDisinfectionRunning(); /******************************************************************************* * disinfectionState * *******************************************************************************/ receipt["state"]["replenishingFluidsWorkState"] = m_disinfectionCtrlService->getReplenishingFluidsWorkState(); receipt["state"]["drainingWorkState"] = m_disinfectionCtrlService->getDrainingWorkState(); /** * @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"]["disinfectionWorkState"] = m_disinfectionCtrlService->getDisinfectionWorkState(); 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.m_nowLoglevel; receipt["state"]["disinfectionState"]["targetlog"] = m_disinfectionCtrlService->m_context.m_targetLoglevel; receipt["state"]["disinfectionState"]["dvalue"] = m_disinfectionCtrlService->m_context.dvalue; /******************************************************************************* * sensor * *******************************************************************************/ receipt["state"]["sensor_data"] = createSensorDataJson(); /******************************************************************************* * disinfectionConfig * *******************************************************************************/ receipt["disinfectionConfig"]["loglevel"] = m_disinfectionCtrlService->m_context.m_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; return; } } HttpResponsePtr MainControlService::hello_world( // HttpRequestPtr request, shared_ptr context, std::shared_ptr) { return std::make_shared(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "hello_world"); } HttpResponsePtr MainControlService::doscript(HttpRequestPtr httpreq, shared_ptr context, std::shared_ptr conn) { return std::make_shared(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "do script success"); } HttpResponsePtr MainControlService::stopscript(HttpRequestPtr, shared_ptr, std::shared_ptr) { return std::make_shared(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "stop script success"); }