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.
 
 

399 lines
14 KiB

#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 <typename T>
static T jsonGet(json j) {
T val;
getJsonValFromJson(j, val);
return val;
}
void MainControlService::initialize() {
GET_TO_SERVICE(m_zconfig);
/**
* @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(SensorDataScan);
GET_SERVICE(SensorDataScan)->initialize();
GET_TO_SERVICE(m_sensorDataScan);
m_sensorDataScan->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> 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_dbService.reset(new DBService());
m_dbService->initialize();
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_sensorDataScan->getAirCompressor_io1();
report["airCompressor"]["io2"] = m_sensorDataScan->getAirCompressor_io2();
report["airCompressor"]["currentVal"] = m_sensorDataScan->getAirCompressor_currentValue();
report["airBlower"]["io1"] = m_sensorDataScan->getAirBlower_io1();
report["airBlower"]["io2"] = m_sensorDataScan->getAirBlower_io2();
report["airBlower"]["currentVal"] = m_sensorDataScan->getAirBlower_currentValue();
report["heatingStrip"]["io1"] = m_sensorDataScan->getHeatingStrip_io1();
report["heatingStrip"]["io2"] = m_sensorDataScan->getHeatingStrip_io2();
report["heatingStrip"]["currentVal"] = m_sensorDataScan->getHeatingStrip_currentValue();
report["sprinklerPump"] = m_sensorDataScan->getSprinkler_PumpRPM();
report["chargingPump"] = m_sensorDataScan->getChargingPump_PumpRPM();
report["waterImmersionSensor1"] = m_sensorDataScan->getWaterImmersionSensor1();
report["waterImmersionSensor2"] = m_sensorDataScan->getWaterImmersionSensor2();
// Water immersion sensor
report["disinfectant_volume"] = m_sensorDataScan->getDisinfectantVolume_g();
report["h2o2_1"] = m_sensorDataScan->getH2O2SenSorData1().h2o2;
report["temp_1"] = m_sensorDataScan->getH2O2SenSorData1().temp;
report["humid_1"] = m_sensorDataScan->getH2O2SenSorData1().humid;
report["saturation_1"] = m_sensorDataScan->getH2O2SenSorData1().saturation;
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(weak_ptr<WebSocket> webSocket, json& cmd, json& receipt) {
string cmdstr = cmd["command"];
/*******************************************************************************
* LOGIN_CMD *
*******************************************************************************/
if (cmdstr == "login") {
string uid = cmd["userid"];
string pwd = cmd["passwd"];
auto usr = m_dbService->getUser(uid);
if (usr == nullptr) {
logger->warn("login fail, user {} not exist", 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 (usr->passwd != pwd) {
logger->warn("login fail, user {} passwd error", uid);
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, usr->permission_level, usr->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 pwd = cmd["passwd"];
logger->info("changet passwd {} {}", uid, pwd);
return;
}
/*******************************************************************************
* shutdown *
*******************************************************************************/
if (cmdstr == "shutdown") {
int delayms = jsonGet<int>(cmd["delayms"]);
logger->info("shutdown {} ms", delayms);
m_autoshutdownThread.reset(new Thread("autoShutdown", [delayms]() {
ThisThread thisThread;
thisThread.sleepForMs(delayms);
system("shutdown -h now");
}));
return;
}
if (cmdstr == "updateDate") {
#if 0
{
"command":"updateDate",
"messageId":"1111222333444555",
"year":2023,
"month":8,
"day":25,
"hour":11,
"min":12,
"second":13,
}
#endif
int32_t year = jsonGet<int>(cmd["year"]);
int32_t month = jsonGet<int>(cmd["month"]);
int32_t day = jsonGet<int>(cmd["day"]);
int32_t hour = jsonGet<int>(cmd["hour"]);
int32_t min = jsonGet<int>(cmd["min"]);
int32_t second = jsonGet<int>(cmd["second"]);
logger->info("updateDate {} {} {} {}:{}:{}", year, month, day, hour, min, second);
return;
}
/*******************************************************************************
* 消毒相关指令 *
*******************************************************************************/
if (cmdstr == "startDisinfection") {
int loglevel = jsonGet<int>(cmd["loglevel"]);
int roomVolume = jsonGet<int>(cmd["roomVolume"]); //
m_disinfectionCtrlService->startDisinfection(loglevel, roomVolume);
return;
}
if (cmdstr == "stopDisinfection") {
m_disinfectionCtrlService->stopDisinfection();
return;
}
if (cmdstr == "pauseDisinfection") {
m_disinfectionCtrlService->pauseDisinfection();
return;
}
if (cmdstr == "continueDisinfection") {
m_disinfectionCtrlService->continueDisinfection();
return;
}
#if 0
//开始加液
{
"command":"startReplenishingFluids",
}
//停止加液
{
"command":"stopReplenishingFluids",
}
//开始排液
{
"command":"startDraining",
}
//停止排液
{
"command":"stopDraining",
}
#endif
if (cmdstr == "startReplenishingFluids") {
int16_t stopAt = jsonGet<int>(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;
}
/*******************************************************************************
* 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();
receipt["state"]["disinfectionWorkState"] = m_disinfectionCtrlService->getDisinfectionWorkState();
receipt["state"]["replenishingFluidsWorkState"] = m_disinfectionCtrlService->getReplenishingFluidsWorkState();
receipt["state"]["drainingWorkState"] = m_disinfectionCtrlService->getDrainingWorkState();
receipt["state"]["estimatedRemainingTimeS"] = m_disinfectionCtrlService->getEstimatedRemainingTimeS();
receipt["state"]["disinfection_id"] = m_disinfectionCtrlService->getDisinfectionID();
receipt["state"]["sensor_data"] = createSensorDataJson();
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;
}
/*******************************************************************************
* 数据库查询 *
*******************************************************************************/
if (cmdstr == "getAllUser") {
auto users = m_dbService->getAllUserJson();
receipt["dbval"] = users;
return;
}
if (cmdstr == "getAllSetting") {
auto dbval = m_dbService->getAllSettingJson();
receipt["dbval"] = dbval;
return;
}
if (cmdstr == "getAllRecords") {
string disinfection_id = cmd["disinfection_id"];
auto dbval = m_dbService->getAllRecords(disinfection_id);
receipt["dbval"] = dbval;
return;
}
if (cmdstr == "setSettingVal") {
string settingName = cmd["settingName"];
int settingVal = jsonGet<int>(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;
}
}
HttpResponsePtr MainControlService::hello_world( //
HttpRequestPtr request, shared_ptr<RestfulServer::Context> context, std::shared_ptr<ConnectionState>) {
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "hello_world");
}
HttpResponsePtr MainControlService::doscript(HttpRequestPtr httpreq, shared_ptr<RestfulServer::Context> context, std::shared_ptr<ConnectionState> conn) {
// logger->info("do\n{}", httpreq->body);
// if (m_a8000_script_processer->isWorking()) {
// return std::make_shared<HttpResponse>(200, "FAIL", HttpErrorCode::Ok, WebSocketHttpHeaders(), "do script fail, script processer is running");
// }
// m_a8000_script_processer->executeScript(httpreq->body);
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "do script success");
}
HttpResponsePtr MainControlService::stopscript(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>) {
// m_a8000_script_processer->stopScript();
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "stop script success");
}