调试预制舱通讯协议修改数据解析

This commit is contained in:
lixiaoyuan
2025-09-18 20:12:46 +08:00
parent cec5cdc19a
commit 2ba4ab2781
28 changed files with 363415 additions and 662 deletions

Binary file not shown.

BIN
bin/Release/ESS.pdb Normal file

Binary file not shown.

View File

@@ -1,34 +1,8 @@
{ {
"debug":0,
"launchdate": "2025-09-01", "launchdate": "2025-09-01",
"weburl": "http://127.0.0.1:19601/",
"database": {"host": "localhost", "port": 3306, "user": "root", "passwd": "123456", "dbname": "ess"}, "database": {"host": "localhost", "port": 3306, "user": "root", "passwd": "123456", "dbname": "ess"},
"token":"",
"http": {"token":0, "port": 19801, "encryption":0, "encryptKey":""}, "http": {"port": 19801},
"mqtt": {"host":"mqtt://43.136.119.46:6203","username":"jsyhsec","password":"123456"}, "mqtt": {"host":"mqtt://43.136.119.46:6203","username":"jsyhsec","password":"123456"},
"topic": { "weburl": "http://127.0.0.1:19601/"
"EMS_YX": {"deviceType":101, "polling":0, "enabled": 1},
"EMS_YC": {"deviceType":101, "polling":0, "enabled": 1},
"EMS_YT": {"deviceType":101, "polling":0, "enabled": 1},
"PCS_YX": {"deviceType":102, "polling":1, "enabled": 1},
"PCS_YC": {"deviceType":102, "polling":1, "enabled": 1},
"PCU_YX": {"deviceType":103, "polling":0, "enabled": 1},
"PCU_YC": {"deviceType":103, "polling":0, "enabled": 1},
"BMS_YX": {"deviceType":104, "polling":0, "enabled": 1},
"BMS_YC": {"deviceType":104, "polling":0, "enabled": 1},
"BCU_YC": {"deviceType":105, "polling":1, "enabled": 1},
"BCU_YX": {"deviceType":105, "polling":1, "enabled": 1},
"MEM_YC": {"deviceType":3, "polling":0, "enabled": 1},
"TH_YC": {"deviceType":10, "polling":1, "enabled": 1},
"Fire40_YX": {"deviceType":7, "polling":1, "enabled": 1},
"Cooling_YC": {"deviceType":14, "polling":1, "enabled": 1},
"Cooling_YX": {"deviceType":14, "polling":1, "enabled": 1},
"Gateway_YX": {"deviceType":15, "polling":1, "enabled": 1},
"Gateway_YC": {"deviceType":15, "polling":1, "enabled": 1},
"Charger_YC": {"deviceType":106, "polling":0, "enabled": 1}
},
"view": {"latitude":0,"longitude":0,"altitude":0},
"video": {
"1":{"host":"", "port":9000, "user":"", "passwd":""}
}
} }

View File

@@ -866,25 +866,5 @@
{"key": "40021", "datatype": "uint16", "remark": "自定时间段"}, {"key": "40021", "datatype": "uint16", "remark": "自定时间段"},
{"key": "40038", "datatype": "uint16", "remark": "其他参数"} {"key": "40038", "datatype": "uint16", "remark": "其他参数"}
] ]
},
"Charger_YC":{
"addr":[
{"key": "11", "datatype": "uint16", "remark": "枪1:状态"},
{"key": "12", "datatype": "uint16", "remark": "枪1:需求电压"},
{"key": "13", "datatype": "uint16", "remark": "枪1:需求电流"},
{"key": "14", "datatype": "uint16", "remark": "枪1:需求功率"},
{"key": "15", "datatype": "uint16", "remark": "枪1:输出电压"},
{"key": "16", "datatype": "uint16", "remark": "枪1:输出电流"},
{"key": "17", "datatype": "uint16", "remark": "枪1:输出功率"},
{"key": "18", "datatype": "uint16", "remark": "枪1:功率限值"},
{"key": "21", "datatype": "uint16", "remark": "枪2:状态"},
{"key": "22", "datatype": "uint16", "remark": "枪2:需求电压"},
{"key": "23", "datatype": "uint16", "remark": "枪2:需求电流"},
{"key": "24", "datatype": "uint16", "remark": "枪2:需求功率"},
{"key": "25", "datatype": "uint16", "remark": "枪2:输出电压"},
{"key": "26", "datatype": "uint16", "remark": "枪2:输出电流"},
{"key": "27", "datatype": "uint16", "remark": "枪2:输出功率"},
{"key": "28", "datatype": "uint16", "remark": "枪2:功率限值"}
]
} }
} }

View File

@@ -96,15 +96,14 @@
"Charger": { "Charger": {
"deviceType":106, "deviceType":106,
"addrYC":[ "addrYC":[
["工作状态", "11", "空闲", ""], ["需求电压", "31071", "0.0", " V"],
["需求电", "12", "0.0", " V", "0.1"], ["需求电", "31073", "0.0", " A"],
["需求电流", "13", "0.0", " A", "0.01"], ["需求功率", "31075", "0.0", " kW"],
["需求功率", "14", "0.0", " kW", "0.1"], ["功率限值", "31077", "0.0", " kW"],
["输出电压", "15", "0.0", " V", "0.1"], ["输出电压", "31079", "0.0", " V"],
["输出电流", "16", "0.0", " A", "0.01"], ["输出电流", "31081", "0.0", " A"],
["输出功率", "17", "0.0", " kW", "0.1"], ["输出功率", "31083", "0.0", " kW"]
["功率限值", "18", "0.0", " kW", "0.1"],
], ],
"addrCurve": ["15", "16", "17"] "addrCurve": ["31079", "31081", "31083"]
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,6 @@ void Application::init()
{ {
// 初始化系统配置,读取配置文件 // 初始化系统配置,读取配置文件
Config::init("assets/config/app.json"); Config::init("assets/config/app.json");
if (Config::option.debug)
{
spdlog::set_level(spdlog::level::debug); // 设置全局日志等级为 debug
spdlog::debug("[app] spdlog debug enable.");
}
// MQTT 数据结构 // MQTT 数据结构
REGAddr::load("assets/config/regaddrs.json"); REGAddr::load("assets/config/regaddrs.json");
@@ -82,8 +77,8 @@ void Application::runThreadMain()
if (!this->isInit) { continue; } if (!this->isInit) { continue; }
} }
static TimeTick ttMqtt; // 检查 场站的 MQTT 连接 static TimeTick ttMqtt(1); // 检查 场站的 MQTT 连接
if (ttMqtt.elapse(30)) if (ttMqtt.elapse(20))
{ {
auto& optionMqtt = Config::option.mqtt; auto& optionMqtt = Config::option.mqtt;
if (!optionMqtt.host.empty()) if (!optionMqtt.host.empty())
@@ -91,20 +86,21 @@ void Application::runThreadMain()
for (auto& item : appdata.mapStation) for (auto& item : appdata.mapStation)
{ {
auto& station = item.second; auto& station = item.second;
if (station) if (station && station->isOpen)
{
if (station->isOpen)
{ {
// 该函数检查连接状态,若已经连接,则无操作;若未连接,则进行连接操作 // 该函数检查连接状态,若已经连接,则无操作;若未连接,则进行连接操作
item.second->initMqtt(); item.second->initMqtt();
// 召测 // 召测
item.second->polling(); item.second->polling();
} }
// 检查设备的在线状态
station->checkDevice();
} }
} }
} }
static TimeTick ttData(1); // 检查数据
if (ttData.elapse(20))
{
//appdata.initFromDB();
} }
} }
} }
@@ -114,14 +110,20 @@ void Application::runThreadStat()
int nCachePos = 0; int nCachePos = 0;
while (!isQuit) while (!isQuit)
{ {
static TimeTick ttStat(1); int64_t tTime = Utils::time();
if(ttStat.elapse(10)) int64_t tDate = Utils::date();
int64_t delta = tTime-tDate;
int n = delta / 600;
int offset = delta % 600;
bool flagStore = (delta >=0 && delta < 86400 && offset <= 10 && n != nCachePos);
if (flagStore)
{ {
// 设备历史数据(电压、电流、功率),存储到 history_day nCachePos = n;
// 统计数据,存储到 stat_station std::string dt = Utils::dateStr(tDate);
// // 设备历史数据(电压、电流、功率),存储到 history_day
for (auto item: appdata.mapStation) for (auto item: appdata.mapStation)
{ {
item.second->writeStatistic(); item.second->writeRuntimeData(dt, nCachePos);
} }
} }
else else
@@ -129,6 +131,12 @@ void Application::runThreadStat()
//spdlog::info("保存历史数据倒计时: {}", 600 - offset); //spdlog::info("保存历史数据倒计时: {}", 600 - offset);
} }
// 统计计算,存储到 stat_station
for (auto& station : appdata.mapStation)
{
}
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
} }
} }

View File

@@ -5,7 +5,6 @@
#include "common/JsonN.h" #include "common/JsonN.h"
#include "common/Spdlogger.h" #include "common/Spdlogger.h"
#include "AppData.h" #include "AppData.h"
#include "protocol/MqttEntity.h"
AppOption Config::option; AppOption Config::option;
@@ -20,106 +19,49 @@ bool Config::init(std::string filename)
} }
spdlog::info("[config] load config file success, filename={}", filename); spdlog::info("[config] load config file success, filename={}", filename);
JSON::read(jsonroot, "debug", option.debug);
JSON::read(jsonroot, "weburl", option.webSrvUrl);
JSON::read(jsonroot, "launchdate", option.lunchDate);
if (jsonroot.contains("database")) if (jsonroot.contains("database"))
{ {
njson& json = jsonroot.at("database"); njson json = jsonroot.at("database");
JSON::read(json, "host", option.database.host); JSON::read(json, "host", option.database.host);
JSON::read(json, "port", option.database.port); JSON::read(json, "port", option.database.port);
JSON::read(json, "user", option.database.user); JSON::read(json, "user", option.database.user);
JSON::read(json, "passwd", option.database.passwd); JSON::read(json, "passwd", option.database.passwd);
JSON::read(json, "dbname", option.database.dbname); JSON::read(json, "dbname", option.database.dbname);
spdlog::info("[config] parse database success. host={}", option.database.host); spdlog::info("[config] parse database success. host={}", option.database.host);
} }
else else
{ {
spdlog::error("[config] parse database failed: not found."); spdlog::info("[config] parse database failed: not found.");
} }
if (jsonroot.contains("http")) if (jsonroot.contains("http"))
{ {
njson& json = jsonroot.at("http"); njson json = jsonroot.at("http");
JSON::read(json, "token", option.http.useToken); std:string token;
JSON::read(json, "token", token);
option.http.useToken = !token.empty();
JSON::read(json, "port", option.http.port); JSON::read(json, "port", option.http.port);
JSON::read(json, "encryption", option.http.encryption);
JSON::read(json, "encryptKey", option.http.encryptKey);
} }
else else
{ {
spdlog::error("[config] parse http failed: not found."); spdlog::info("[config] parse http failed: not found.");
} }
if (jsonroot.contains("mqtt")) if (jsonroot.contains("mqtt"))
{ {
njson& json = jsonroot.at("mqtt"); njson json = jsonroot.at("mqtt");
JSON::read(json, "host", option.mqtt.host); JSON::read(json, "host", option.mqtt.host);
JSON::read(json, "username", option.mqtt.username); JSON::read(json, "username", option.mqtt.username);
JSON::read(json, "password", option.mqtt.password); JSON::read(json, "password", option.mqtt.password);
} }
else else
{ {
spdlog::error("[config] parse mqtt failed: not found."); spdlog::info("[config] parse mqtt failed: not found.");
} }
if (jsonroot.contains("view")) JSON::read(jsonroot, "weburl", option.webSrvUrl);
{ JSON::read(jsonroot, "launchdate", option.lunchDate);
njson& json = jsonroot["view"];
JSON::read(json, "latitude", option.view.latitude);
JSON::read(json, "longitude", option.view.longitude);
JSON::read(json, "altitude", option.view.altitude);
}
else
{
spdlog::error("[config] parse view failed: not found.");
}
if (jsonroot.contains("video"))
{
njson& json = jsonroot["video"];
for (auto& item: json.items())
{
auto& key = item.key();
auto& jsonItem = item.value();
auto& itemVideo = option.mapVideo[key];
JSON::read(jsonItem, "host", itemVideo.host);
JSON::read(jsonItem, "port", itemVideo.port);
JSON::read(jsonItem, "user", itemVideo.user);
JSON::read(jsonItem, "passwd", itemVideo.passwd);
}
}
else
{
spdlog::error("[config] parse video failed: not found.");
}
if (jsonroot.contains("topic"))
{
njson& json = jsonroot["topic"];
for (auto& item: json.items())
{
auto& key = item.key();
auto& jsonItem = item.value();
auto& info = MqttClient::s_mapTopicInfo[key];
info.name = key;
JSON::read(jsonItem, "deviceType", info.deviceType);
JSON::read(jsonItem, "polling", info.polling);
JSON::read(jsonItem, "enabled", info.enabled);
}
}
return true; return true;
} }
AppOption::VideoInfo* Config::getVideoInfo(std::string name)
{
auto iter = option.mapVideo.find(name);
if (iter!=option.mapVideo.end())
{
return &(iter->second);
}
return nullptr;
}

View File

@@ -1,27 +1,23 @@
#pragma once #pragma once
#include <map>
#include <string> #include <string>
struct AppOption struct DatabaseOption
{ {
int debug {0};
std::string webSrvUrl;
std::string lunchDate;
struct {
std::string host; std::string host;
int port; int port;
std::string user; std::string user;
std::string passwd; std::string passwd;
std::string dbname; std::string dbname;
} database; };
struct AppOption
{
DatabaseOption database;
struct { struct {
int useToken {1}; bool useToken {true};
int port {0}; int port {0};
int encryption {1};
std::string encryptKey;
} http; } http;
struct { struct {
@@ -30,20 +26,8 @@ struct AppOption
std::string password; std::string password;
} mqtt; } mqtt;
struct { std::string webSrvUrl;
float latitude {0}; std::string lunchDate;
float longitude {0};
float altitude {0};
} view;
struct VideoInfo {
std::string host;
int port;
std::string user;
std::string passwd;
};
std::map<std::string, VideoInfo> mapVideo;
}; };
@@ -52,7 +36,6 @@ class Config
public: public:
static bool init(std::string filename); static bool init(std::string filename);
static AppOption::VideoInfo* getVideoInfo(std::string name);
static AppOption option; static AppOption option;
}; };

View File

@@ -256,9 +256,6 @@ void Device::storeDB(int npos)
void Device::setParam(std::string k, int v) void Device::setParam(std::string k, int v)
{ {
this->ts = Utils::time();
online = 1;
float ratio = 1.0; float ratio = 1.0;
auto iter = mapMyParams.find(k); auto iter = mapMyParams.find(k);
if (iter != mapMyParams.end()) if (iter != mapMyParams.end())
@@ -267,62 +264,40 @@ void Device::setParam(std::string k, int v)
//spdlog::info("[device] set param: {} {}={}, ratio={}", iter->second->name, k, v, ratio); //spdlog::info("[device] set param: {} {}={}, ratio={}", iter->second->name, k, v, ratio);
} }
if (type == 106) // 充电桩2号枪特殊数据格式
{
if (k=="22") { ratio = 0.1; }
else if (k=="23") { ratio = 0.01; }
else if (k== "24") { ratio = 0.1; }
else if (k== "25") { ratio = 0.1; }
else if (k== "26") { ratio = 0.01; }
else if (k== "27") { ratio = 0.1; }
else if (k== "28") { ratio = 0.1; }
}
int precision = (ratio != 1.0f) ? 1 : 0; int precision = (ratio != 1.0f) ? 1 : 0;
std::string valStr = Utils::toStr(v*ratio, precision); mapParams[k] = Utils::toStr(v*ratio, precision);
if (type == 106) // 充电桩状态,特殊数据格式
{
if (k=="11" || k == "21") {
valStr = (valStr == "1" ? "充电" : "空闲");
}
}
mapParams[k] = valStr;
if (type == 3 ) // 电表 if (type == 3 ) // 电表
{ {
running = 1; if (k == "") this->err = v;
} }
else if (type == 101) // EMS else if (type == 101) // EMS
{ {
running = 1;
} }
else if (type == 102) // PCS else if (type == 102) // PCS
{ {
if (k == "0x1003") err = v; // 故障状态 R uint16 1故障0正常 0 0x1003 if (k == "0x1003") err = v; // 故障状态 R uint16 1故障0正常 0 0x1003
else if (k == "0x1005") online = v; // 设备在线 R uint16 1在线0无效 1 0x1005 if (k == "0x1005") online = v; // 设备在线 R uint16 1在线0无效 1 0x1005
else if (k == "0x1009") running = (v==1 || v==2); //充放状态 R uint16 0待机, 1充电, 2放电, 3搁置 0 0x1009 if (k == "0x1009") running = (v==1 || v==2); //充放状态 R uint16 0待机, 1充电, 2放电, 3搁置 0 0x1009
} }
else if (type == 103) // PCU else if (type == 103) // PCU
{ {
if (k == "0x1002") err = v; //故障状态 R uint16 1故障0正常 0 0x1002 if (k == "0x1002") err = v; //故障状态 R uint16 1故障0正常 0 0x1002
else if (k == "0x1004") online = v; //设备在线 R uint16 1在线0无效 1 0x1004 if (k == "0x1004") online = v; //设备在线 R uint16 1在线0无效 1 0x1004
else if (k == "0x1006") running = v; //启停状态 R uint16 1开机0关机 1 0x1006 if (k == "0x1006") running = v; //启停状态 R uint16 1开机0关机 1 0x1006
} }
else if (type == 104) // BMS else if (type == 104) // BMS
{ {
if (k == "0x004A") { err = (v==1); } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x004A if (k == "0x004A") { err = (v==1); online = 1; } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x004A
else if (k == "0x004B") running = (v==1 || v==2); //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004B if (k == "0x004B") running = (v==1 || v==2); //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004B
} }
else if (type == 105) // BCU else if (type == 105) // BCU
{ {
if (k == "0xA003") { running = (v==0x33 || v==0x44); } //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003 if (k == "0xA003") running = (v==0x33 || v==0x44); //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003
else if (k == "0xA004") { err = (v==0x55); } //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004 if (k == "0xA004") err = (v==0x55); online=1; //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004
} }
else if (type == 106) // 充电桩 else if (type == 106) // 充电桩
{ {
if (k == "21") {
running = (mapParams["11"] == "充电" || mapParams["21"] == "充电"); // 充电状态: 0空闲1充电
}
} }
else if (type == 109) // 光伏板 else if (type == 109) // 光伏板
{ {
@@ -368,13 +343,12 @@ void Device::getRuntimeParams1(std::vector<std::pair<std::string, std::string>>&
{ {
if (type == 106) if (type == 106)
{ {
params.push_back({"工作状态", getParam("21", "空闲")}); params.push_back({"需求电压", getParam("31072", "0.0") + " V"});
params.push_back({"需求电", getParam("22", "0.0") + " V"}); params.push_back({"需求电", getParam("31074", "0.0") + " A"});
params.push_back({"需求电流", getParam("23", "0.0") + " A"}); params.push_back({"需求功率", getParam("31076", "0.0") + " kW"});
params.push_back({"需求功率", getParam("24", "0.0") + " kW"}); params.push_back({"功率限值", getParam("31078", "0.0") + " kW"});
params.push_back({"输出电压", getParam("25", "0.0") + " V"}); params.push_back({"输出电压", getParam("31080", "0.0") + " V"});
params.push_back({"输出电流", getParam("26", "0.0") + " A"}); params.push_back({"输出电流", getParam("31082", "0.0") + " A"});
params.push_back({"输出功率", getParam("27", "0.0") + " kW"}); params.push_back({"输出功率", getParam("31084", "0.0") + " kW"});
params.push_back({"功率限值", getParam("28", "0.0") + " kW"});
} }
} }

View File

@@ -73,8 +73,6 @@ public:
int online = 0; int online = 0;
int running = 0; int running = 0;
int64_t ts {0};
//std::map<std::string, std::string> mapAttrs; //std::map<std::string, std::string> mapAttrs;
Fields attrs; Fields attrs;

View File

@@ -12,6 +12,20 @@
Station::Station() : stationId(0) Station::Station() : stationId(0)
{ {
mqttCli = std::make_shared<MqttClient>(); mqttCli = std::make_shared<MqttClient>();
// 测试,设置默认值
for (int i = 1; i<=5; i++) {
auto& unit = mapCoolingUnit[i];
unit.powerOn = 1;
unit.mode = i%2;
}
for (int i = 1; i<=5; i++) {
auto& unit = mapAircUnit[i];
unit.powerOn = 1;
unit.temp = Utils::random(20, 40);
unit.hum = Utils::random(20, 80);
}
} }
void Station::setFields(Fields& fields) void Station::setFields(Fields& fields)
@@ -19,12 +33,12 @@ void Station::setFields(Fields& fields)
this->stationId = fields.get<int>(DMStation::STATION_ID); this->stationId = fields.get<int>(DMStation::STATION_ID);
this->name = fields.value(DMStation::NAME); this->name = fields.value(DMStation::NAME);
this->capacity = fields.get<double>(DMStation::CAPACITY); this->capacity = fields.get<double>(DMStation::CAPACITY);
this->workMode = fields.get<int>(DMStation::WORK_MODE); this->workModeId = fields.get<int>(DMStation::WORK_MODE);
this->code = fields.value(DMStation::CODE); this->code = fields.value(DMStation::CODE);
this->status = fields.get<int>(DMStation::STATUS); this->status = fields.get<int>(DMStation::STATUS);
this->operationDate = fields.value(DMStation::OPERATION_DATE); this->operationDate = fields.value(DMStation::OPERATION_DATE);
this->isOpen = fields.get<int>(DMStation::STATUS); this->isOpen = fields.get<int>(DMStation::STATUS);
this->launchDate = fields.value("operation_date");
this->policy.setFields(fields); this->policy.setFields(fields);
} }
@@ -120,7 +134,7 @@ void Station::getDeviceByCategory(int category, std::vector<std::shared_ptr<Devi
void Station::setWorkMode(int modeId) void Station::setWorkMode(int modeId)
{ {
this->workMode = modeId; this->workModeId = modeId;
std::string sql = SQL(SQL::TYPE::update).table(DMStation::TABLENAME) std::string sql = SQL(SQL::TYPE::update).table(DMStation::TABLENAME)
.update(DMStation::WORK_MODE, std::to_string(modeId)) .update(DMStation::WORK_MODE, std::to_string(modeId))
.where(DMStation::STATION_ID + "=" + std::to_string(stationId)).str(); .where(DMStation::STATION_ID + "=" + std::to_string(stationId)).str();
@@ -143,6 +157,71 @@ void Station::setPolicy(int policyId)
} }
} }
static std::string MapValueToJson(int npos, std::map<int, double>& mapV)
{
njson jsonarray = njson::array();
for (int i = 0; i<=npos; i++)
{
jsonarray.push_back(mapV[i]);
}
return jsonarray.dump();
}
void Station::writeRuntimeData(std::string dt, int npos)
{
auto dao = DaoEntity::create("history_day");
for (auto iter = mapDevice.begin(); iter!=mapDevice.end(); ++iter)
{
auto device = iter->second;
if (device->cache(npos))
{
Fields fields;
fields.set("dt", dt);
fields.set("station_id", this->stationId);
fields.set("device_id", device->deviceId);
fields.set("datatype", 1);
fields.set("value", MapValueToJson(npos, device->mapCacheVoltage));
DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 2);
fields.set("value", MapValueToJson(npos, device->mapCacheCurrent));
DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 3);
fields.set("value", MapValueToJson(npos, device->mapCachePower));
DAO::insertRuntimeData(dao, fields);
spdlog::info("[device] write runtime date to database, deviceId={}", device->deviceId);
}
}
}
void Station::writeStatistic(std::string dt)
{
Fields fields;
fields.set("storage_elect_in", statData.totalElectIn);
fields.set("storage_elect_out", statData.totalElectOut);
//fields.set("storage_num_in", statData.totalElectIn);
//fields.set("storage_num_out", 0);
//fields.set("storage_num_err", 0);
//fields.set("storage_t_in", 0);
//fields.set("storage_t_out", 0);
//fields.set("storage_usage", 0);
//fields.set("solar_elect_gen", 0);
//fields.set("solar_elect_grid", 0);
//fields.set("solar_num_err", 0);
//fields.set("solar_t", 0);
//fields.set("solar_usage", 0);
//fields.set("charge_elect", 0);
//fields.set("charge_num", 0);
//fields.set("charge_num_err", 0);
//fields.set("charge_t", 0);
//fields.set("charge_usage", 0);
fields.set("income_elect", statData.totalIncome);
//fields.set("income_charge", 0);
//fields.set("usage_rate", 0);
}
void Station::initMqtt() void Station::initMqtt()
{ {
if (status!=0 && mqttCli) if (status!=0 && mqttCli)
@@ -170,7 +249,7 @@ void Station::setGarewayWorkMode()
njson json; njson json;
json["ts"] = Utils::time(); json["ts"] = Utils::time();
json["no"] = 1; // 设备编号 json["no"] = 1; // 设备编号
json["40001"] = this->workMode; json["40001"] = this->workModeId;
if (policy.type == 1) if (policy.type == 1)
{ {
@@ -188,43 +267,19 @@ void Station::setGarewayWorkMode()
mqttCli->publish("Gateway_YT", text); mqttCli->publish("Gateway_YT", text);
} }
void Station::checkDevice()
{
for (auto& item: mapDevice)
{
auto& device = item.second;
if (device)
{
if (Utils::time() - device->ts > 60*6)
{
device->online = 0;
}
}
}
}
void Station::setRuntimeData(int deviceNo, string addr, int val) void Station::setRuntimeData(string addr, int val)
{ {
if (deviceNo == 1) if (addr == "0x110E") { statData.dayElectIn = val; } //日充电电量 R uint32 1kWh 0 0x110E
{ else if (addr == "0x1110") { statData.dayElectOut = val; } //日放电电量 R uint32 1kWh 0 0x1110
if (addr == "0x000B") { this->voltage = val; } // A相电压 R uint32 1V 0x000B else if (addr == "0x1112") { statData.dayIncomeIn = val; } //日充电费用 R uint32 1RMB 0 0x1112
if (addr == "0x0011") { this->current = val; } // A相电流 R int32 1A 0x0011 else if (addr == "0x1114") { statData.dayIncomeOut = val; } //日放电费用 R uint32 1RMB 0 0x1114
if (addr == "0x0011") { this->power = val; } // 三相总有功 R int32 1kW 0x0023 else if (addr == "0x1116") { statData.dayIncome = val; } //日收益 R int32 1RMB 0 0x1116
} else if (addr == "0x112C") { statData.totalElectIn = val; } //总充电电量 R uint32 1kWh 6659(0x112D) 0x112C
else if (deviceNo == 2) else if (addr == "0x112E") { statData.totalElectOut = val; } //总放电电量 R uint32 1kWh 4925(0x112F) 0x112E
{ else if (addr == "0x1130") { statData.totalIncomeIn = val; } //总充电费用 R uint32 1RMB 6605(0x1131) 0x1130
statData.ts = Utils::time(); else if (addr == "0x1132") { statData.totalIncomeOut = val; } //总放电费用 R uint32 1RMB 4949(0x1133) 0x1132
if (addr == "0x002F") { statData.dayElectIn = val; } //日充电电量 R uint32 1kWh 0x002F else if (addr == "0x1134") { statData.totalIncome = val; } //总收益 R int32 1RMB -1 0x1134
else if (addr == "0x0031") { statData.dayElectOut = val; } //日放电电量 R uint32 1kWh 0x0031
else if (addr == "0x0033") { statData.dayIncomeIn = val; } //日充电费用 R uint32 1RMB 0x0033
else if (addr == "0x0035") { statData.dayIncomeOut = val; } //日放电费用 R uint32 1RMB 0x0035
else if (addr == "0x0037") { statData.dayIncome = val; } //日收益 R int32 1RMB 0x0037
else if (addr == "0x004D") { statData.totalElectIn = val; } //总充电电量 R uint32 1kWh 0x004D
else if (addr == "0x004F") { statData.totalElectOut = val; } //总放电电量 R uint32 1kWh 0x004F
else if (addr == "0x0051") { statData.totalIncomeIn = val; } //总充电费用 R uint32 1RMB 0x0051
else if (addr == "0x0053") { statData.totalIncomeOut = val; } //总放电费用 R uint32 1RMB 0x0053
else if (addr == "0x0055") { statData.totalIncome = val; } //总收益 R int32 1RMB 0x0055
}
} }
void Station::setTHData(int deviceNo, string addr, int val) void Station::setTHData(int deviceNo, string addr, int val)
@@ -232,16 +287,8 @@ void Station::setTHData(int deviceNo, string addr, int val)
auto& unit = mapTempHumUnit[deviceNo]; auto& unit = mapTempHumUnit[deviceNo];
if (addr == "0x0001") { ; } //所属通道号 R uint16 1 0x0001 if (addr == "0x0001") { ; } //所属通道号 R uint16 1 0x0001
else if (addr == "0x0002") { ; } //所属温湿度号 R uint16 1~10 0x0002 else if (addr == "0x0002") { ; } //所属温湿度号 R uint16 1~10 0x0002
else if (addr == "0x0003") //温度 R int16 0.1℃ 0x0003 else if (addr == "0x0003") { unit.temp = float(val) * 0.1; } //温度 R int16 0.1℃ 0x0003
{ else if (addr == "0x0004") { unit.hum = float(val) * 0.1; } //湿度 R int16 0.1℃ 0x0004
unit.temp = float(val) * 0.1;
if (deviceNo == 1) temperature = unit.temp;
}
else if (addr == "0x0004") //湿度 R int16 0.1℃ 0x0004
{
unit.hum = float(val) * 0.1;
if (deviceNo == 1) humidity = unit.hum;
}
} }
void Station::setFire40Data(int deviceNo, string addr, int val) void Station::setFire40Data(int deviceNo, string addr, int val)
@@ -281,8 +328,8 @@ void Station::setCoolingData(int deviceNo, string addr, int val)
if (addr == "0x1001") { ; } //所属通道号 R uint16 1 0x1001 if (addr == "0x1001") { ; } //所属通道号 R uint16 1 0x1001
else if (addr == "0x1002") { ; }// 所属冷机号 R uint16 1~10 0x1002 else if (addr == "0x1002") { ; }// 所属冷机号 R uint16 1~10 0x1002
else if (addr == "0x1003") { coolingStatus = unit.powerOn = val; }// 开关 R uint16 0关机1开机 0x1003 else if (addr == "0x1003") { unit.powerOn = val; }// 开关 R uint16 0关机1开机 0x1003
else if (addr == "0x1004") { unit.mode = val; }// 采样模式 R uint16 0-出水温度 1-电芯温度 0x1004 else if (addr == "0x1004") { ; }// 采样模式 R uint16 0-出水温度 1-电芯温度 0x1004
else if (addr == "0x1005") { unit.cooling = val; }// 制冷状态 R uint16 0关闭, 1启动 0x1005 else if (addr == "0x1005") { unit.cooling = val; }// 制冷状态 R uint16 0关闭, 1启动 0x1005
else if (addr == "0x1006") { unit.heating = val; }// 制热状态 R uint16 0关闭, 1启动 0x1006 else if (addr == "0x1006") { unit.heating = val; }// 制热状态 R uint16 0关闭, 1启动 0x1006
else if (addr == "0x1007") { unit.highTemp = val; }// 高温告警 R uint16 0正常1告警 0x1007 else if (addr == "0x1007") { unit.highTemp = val; }// 高温告警 R uint16 0正常1告警 0x1007
@@ -294,111 +341,3 @@ void Station::setCoolingData(int deviceNo, string addr, int val)
else if (addr == "0x100D") { ; }// 进水压力传感器 R uint16 0正常1告警 0x100D else if (addr == "0x100D") { ; }// 进水压力传感器 R uint16 0正常1告警 0x100D
else if (addr == "0x100E") { ; }// 出水压力传感器 R uint16 0正常1告警 0x100E else if (addr == "0x100E") { ; }// 出水压力传感器 R uint16 0正常1告警 0x100E
} }
void Station::setWorkModeFromGateway(int mode)
{
if (mode != this->workMode)
{
//std::string sql = "update station set work_mode='" + std::to_string(mode) + "'";
//auto ret = DaoEntity::execOnce(sql);
//if (ret)
//{
// spdlog::info("[station] wrok_mode is diffent with gateway, update success.[{}]-[{}]", workMode, mode);
// this->workMode = mode;
//}
//else
//{
// spdlog::error("[station] wrok_mode is diffent with gateway, update failed.[{}]-[{}]", workMode, mode);
//}
//this->setGarewayWorkMode();
}
}
static std::string MapValueToJson(int npos, std::map<int, double>& mapV)
{
njson jsonarray = njson::array();
for (int i = 0; i<=npos; i++)
{
jsonarray.push_back(mapV[i]);
}
return jsonarray.dump();
}
void Station::writeStatistic()
{
auto dao = DaoEntity::create("history_day");
std::string dt = Utils::dateStr();
int64_t tTime = Utils::time();
int64_t tDate = Utils::date();
int npos = (tTime-tDate) / 600;
for (auto iter = mapDevice.begin(); iter!=mapDevice.end(); ++iter)
{
auto device = iter->second;
if (device->cache(npos))
{
Fields fields;
fields.set("dt", dt);
fields.set("station_id", this->stationId);
fields.set("device_id", device->deviceId);
fields.set("datatype", 1);
fields.set("value", MapValueToJson(npos, device->mapCacheVoltage));
DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 2);
fields.set("value", MapValueToJson(npos, device->mapCacheCurrent));
DAO::insertRuntimeData(dao, fields);
fields.set("datatype", 3);
fields.set("value", MapValueToJson(npos, device->mapCachePower));
DAO::insertRuntimeData(dao, fields);
//spdlog::info("[device] write runtime date to database, deviceId={}", device->deviceId);
}
}
if (statData.ts != 0)
{
Fields fields;
fields.set("dt", Utils::dateStr(statData.ts));
fields.set("station_id", this->stationId);
fields.set("device_id", 0);
fields.set("elect_in", statData.dayElectIn);
fields.set("elect_out", statData.dayElectOut);
fields.set("income_in", statData.dayIncomeIn);
fields.set("income_out", statData.dayIncomeOut);
fields.set("income", statData.dayIncome);
//fields.set("num_in", "");
//fields.set("num_out", "");
//fields.set("num_err", "");
//fields.set("t_in", "");
//fields.set("t_out", "");
//fields.set("usage_rate", "");
fields.set("elect_in_total", statData.totalElectIn);
fields.set("elect_out_total", statData.totalElectOut);
fields.set("income_in_total", statData.totalIncomeIn);
fields.set("income_out_total", statData.totalIncomeOut);
fields.set("income_total", statData.totalIncome);
dao->setTableName("stat_storage");
std::vector<std::string> vecKeys = {
"elect_in", "elect_out", "num_in", "num_out", "num_err", "t_in", "t_out", "usage_rate", "income_in", "income_out",
"elect_in_total", "elect_out_total", "income_in_total", "income_out_total"
};
dao->duplicateUpdate(fields, vecKeys);
{
Fields fields;
fields.set("dt", Utils::dateStr(statData.ts));
fields.set("station_id", this->stationId);
fields.set("device_id", 0);
fields.set("storage_elect_in", statData.dayElectIn);
fields.set("storage_elect_out", statData.dayElectOut);
fields.set("income_elect", statData.dayIncome);
DAO::insertStatStation(dao, fields);
}
}
}

View File

@@ -109,18 +109,17 @@ public:
void setWorkMode(int modeId); void setWorkMode(int modeId);
void setPolicy(int policyId); void setPolicy(int policyId);
void writeRuntimeData(std::string dt, int npos);
void writeStatistic(std::string dt);
void initMqtt(); void initMqtt();
void polling(); void polling();
void setGarewayWorkMode(); void setGarewayWorkMode();
void checkDevice();
void setRuntimeData(int deviceNo, string addr, int val); void setRuntimeData(string addr, int val);
void setTHData(int deviceNo, string addr, int val); void setTHData(int deviceNo, string addr, int val);
void setFire40Data(int deviceNo, string addr, int val); void setFire40Data(int deviceNo, string addr, int val);
void setCoolingData(int deviceNo, string addr, int val); void setCoolingData(int deviceNo, string addr, int val);
void setWorkModeFromGateway(int mode);
void writeStatistic();
public: public:
int stationId {}; int stationId {};
@@ -130,13 +129,14 @@ public:
int status {0}; int status {0};
std::string operationDate; std::string operationDate;
SysPolicy policy; SysPolicy policy;
std::string launchDate {};
bool isConnected {false}; bool isConnected {false};
int workMode {}; // 运行模式 int workModeId {}; // 运行模式
int runPolicyId {}; // 运行策略 int runPolicyId {}; // 运行策略
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 === /// === 系统统计 ===
// 累计发电量单位kWh // 累计发电量单位kWh
@@ -185,12 +185,6 @@ public:
double temperature {}; double temperature {};
// 湿度 // 湿度
double humidity {}; double humidity {};
int aircStatus {0};
int coolingStatus {0};
double voltage {0};
double current {0};
double power {0};
double powerFactor {0};
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 设备信息 === /// === 设备信息 ===
@@ -213,25 +207,25 @@ public:
struct { struct {
int64_t ts {0}; int64_t ts;
float totalElectIn {0.0}; //总充电电量 R uint32 1kWh 6659(0x112D) 0x112C double totalElectIn; //总充电电量 R uint32 1kWh 6659(0x112D) 0x112C
float totalElectOut {0.0}; //总放电电量 R uint32 1kWh 4925(0x112F) 0x112E double totalElectOut; //总放电电量 R uint32 1kWh 4925(0x112F) 0x112E
float totalIncomeIn {0.0}; //总充电费用 R uint32 1RMB 6605(0x1131) 0x1130 double totalIncomeIn; //总充电费用 R uint32 1RMB 6605(0x1131) 0x1130
float totalIncomeOut {0.0}; //总放电费用 R uint32 1RMB 4949(0x1133) 0x1132 double totalIncomeOut; //总放电费用 R uint32 1RMB 4949(0x1133) 0x1132
float totalIncome {0.0}; //总收益 R int32 1RMB -1 0x1134 double totalIncome; //总收益 R int32 1RMB -1 0x1134
//储能充放电时段hh R uint16 时 336 0x01 0x121C //储能充放电时段hh R uint16 时 336 0x01 0x121C
//储能充放电时段mm R uint16 分 0 0x01 0x121D //储能充放电时段mm R uint16 分 0 0x01 0x121D
//储能充放电时段ss R uint16 秒 0 0x01 0x121E //储能充放电时段ss R uint16 秒 0 0x01 0x121E
float totalDurationIn {0.0}; double totalDurationIn;
float totalDurationOut {0.0}; double totalDurationOut;
float dayElectIn {0.0}; // 日充电电量 R uint32 1kWh 0 0x110E double dayElectIn; // 日充电电量 R uint32 1kWh 0 0x110E
float dayElectOut {0.0}; // 日放电电量 R uint32 1kWh 0 0x1110 double dayElectOut; // 日放电电量 R uint32 1kWh 0 0x1110
float dayIncomeIn {0.0}; // 日充电费用 R uint32 1RMB 0 0x1112 double dayIncomeIn; // 日充电费用 R uint32 1RMB 0 0x1112
float dayIncomeOut {0.0}; // 日放电费用 R uint32 1RMB 0 0x1114 double dayIncomeOut; // 日放电费用 R uint32 1RMB 0 0x1114
float dayIncome {0.0}; // 日收益 R int32 1RMB 0 0x1116 double dayIncome; // 日收益 R int32 1RMB 0 0x1116
} statData; } statData;

View File

@@ -21,7 +21,7 @@ void Spdlogger::init(spdlog::level::level_enum log_level, std::string filename)
// 创建控制台接收器 // 创建控制台接收器
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>(); auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
//consoleSink->set_level(log_level); // 设置控制台日志等级 consoleSink->set_level(spdlog::level::info); // 设置控制台日志等级
//consoleSink->set_pattern("[%T] [%^%l%$] %v"); // 设置日志格式 //consoleSink->set_pattern("[%T] [%^%l%$] %v"); // 设置日志格式
// 创建文件接收器 // 创建文件接收器
@@ -31,7 +31,7 @@ void Spdlogger::init(spdlog::level::level_enum log_level, std::string filename)
// 每日文件sink可选每天生成新文件 // 每日文件sink可选每天生成新文件
auto dailySink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logs/ess.log", 0, 0); auto dailySink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logs/ess.log", 0, 0);
//dailySink->set_level(log_level); dailySink->set_level(spdlog::level::debug);
//dailySink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v"); //dailySink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
// 创建一个多重接收器的 logger // 创建一个多重接收器的 logger
@@ -40,8 +40,8 @@ void Spdlogger::init(spdlog::level::level_enum log_level, std::string filename)
// 设置全局 logger // 设置全局 logger
spdlog::set_default_logger(logger); spdlog::set_default_logger(logger);
spdlog::set_level(log_level); // 设置全局日志等级为 debug spdlog::set_level(spdlog::level::debug); // 设置全局日志等级为 debug
spdlog::flush_on(log_level); // 开启日志刷新 spdlog::flush_on(spdlog::level::info); // 开启日志刷新
} }
void Spdlogger::drop() void Spdlogger::drop()

View File

@@ -644,7 +644,6 @@ Errcode DAO::insertStatStation(std::shared_ptr<DaoEntity> dao, Fields& fields)
{ {
// 根据主键dt、station_id、category写入或更新数据 // 根据主键dt、station_id、category写入或更新数据
if (!dao) { dao = DaoEntity::create("stat_station"); } if (!dao) { dao = DaoEntity::create("stat_station"); }
else { dao->setTableName("stat_station"); }
std::vector<std::string> vecKeys = { std::vector<std::string> vecKeys = {
"storage_elect_in", "storage_elect_in",
"storage_elect_out", "storage_elect_out",

View File

@@ -129,18 +129,21 @@ int DaoEntity::duplicateUpdate(Fields& fields, const vector<string>& keys)
string val; string val;
for (auto& item : fields.map()) for (auto& item : fields.map())
{ {
if (!key.empty()) { key += ","; val += ","; } if (!key.empty())
{
key += ","; val += ",";
}
key += (item.first); key += (item.first);
val += ("'" + item.second + "'"); val += ("'" + item.second + "'");
} }
string str; string str;
for (auto& k : keys) for (auto& k : keys)
{ {
if (fields.contains(k)) if (!str.empty())
{ {
if (!str.empty()) { str += ","; } str += ",";
str += (k + "='" + fields.value(k) + "'");
} }
str += (k + "='" + fields.value(k) + "'");
} }
string sql = "INSERT INTO " + tableName + "(" + key + ") VALUES (" + val + ") ON duplicate KEY UPDATE " + str; string sql = "INSERT INTO " + tableName + "(" + key + ") VALUES (" + val + ") ON duplicate KEY UPDATE " + str;
return this->db->exec(sql); return this->db->exec(sql);

View File

@@ -124,15 +124,14 @@ int main(int argc, char** argv)
// 设置控制台输入为 UTF-8 编码(如果需要输入中文) // 设置控制台输入为 UTF-8 编码(如果需要输入中文)
SetConsoleCP(CP_UTF8); SetConsoleCP(CP_UTF8);
// 初始化日志 // 初始化日志
Spdlogger::init(spdlog::level::info, ""); Spdlogger::init(spdlog::level::debug, "");
spdlog::info("[main] start ... ======================================================================"); spdlog::info("[main] start ... ======================================================================");
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blacklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --num-raster-threads=4"); qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blacklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --num-raster-threads=4");
// 运行后台服务 // 运行后台服务
Application::instance().init(); Application::instance().init();
while (1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }; while (1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); };
// 启动 PV 服务主线程 // 启动 PV 服务主线程

View File

@@ -128,8 +128,6 @@ public:
static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet = static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{ {
{"/queryBaseinfo", HandlerOptions(&HttpEntity::logqueryBaseinfoin, {})},
{"/login", HandlerOptions(&HttpEntity::login, {DMUser::ACCOUNT, DMUser::PASSWD})}, {"/login", HandlerOptions(&HttpEntity::login, {DMUser::ACCOUNT, DMUser::PASSWD})},
{"/queryUserList", HandlerOptions(&HttpEntity::queryUserList, {})}, {"/queryUserList", HandlerOptions(&HttpEntity::queryUserList, {})},
{"/deleteUser", HandlerOptions(&HttpEntity::deleteUser, { DMUser::USER_ID})}, {"/deleteUser", HandlerOptions(&HttpEntity::deleteUser, { DMUser::USER_ID})},
@@ -282,7 +280,6 @@ void HttpEntity::runHandler(std::string name, const HandlerOptions& handler, con
jsonresp["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg)); jsonresp["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
resp.set_content(jsonresp.dump(), "text/plain; charset=utf-8"); resp.set_content(jsonresp.dump(), "text/plain; charset=utf-8");
resp.status = 200; resp.status = 200;
spdlog::info("[http] request: {}, response: {}.", name, int(errcode));
} }
void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp)) void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp))
@@ -290,18 +287,6 @@ void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const htt
this->httpsvr.Get(name, std::bind(func, this, std::placeholders::_1, std::placeholders::_2)); this->httpsvr.Get(name, std::bind(func, this, std::placeholders::_1, std::placeholders::_2));
} }
Errcode HttpEntity::logqueryBaseinfoin(const httplib::Request& req, njson& json, std::string& errmsg)
{
json["data"] = {
{"encryption", Config::option.http.encryption},
{"encryptKey", Config::option.http.encryptKey},
{"latitude", Config::option.view.latitude},
{"longitude", Config::option.view.longitude},
{"altitude", Config::option.view.altitude}
};
return Errcode::OK;
}
Errcode HttpEntity::login(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::login(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
std::string userId; std::string userId;
@@ -617,13 +602,12 @@ Errcode HttpEntity::insertStation(const httplib::Request& req, njson& json, std:
Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
GetRequestParam(req, {"station_id", "name", "address", "lon", "lat", "tel", "capacity", "status", "work_mode", "policy_id", "operation_date"}, params); GetRequestParam(req, {"station_id", "name", "address", "lon", "lat", "tel", "capacity", "status", "work_mode", "policy_id"}, params);
std::string stationId = params.value("station_id"); std::string stationId = params.value("station_id");
params.check("capacity", "", "0.0"); params.check("capacity", "", "0.0");
params.check("lon", "", "0.0"); params.check("lon", "", "0.0");
params.check("lat", "", "0.0"); params.check("lat", "", "0.0");
params.check("status", "", "1"); params.check("status", "", "1");
params.check("policy_id", "", "NULL");
Errcode err = DAO::updateStationById(params); Errcode err = DAO::updateStationById(params);
if (err == Errcode::OK) if (err == Errcode::OK)
{ {
@@ -636,13 +620,18 @@ Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std:
spdlog::error("[http] update station success, set station cache error, station_id={}", stationId); spdlog::error("[http] update station success, set station cache error, station_id={}", stationId);
} }
else else
{
if (result.size() > 0)
{ {
auto station = Application::data().getStation(Utils::toInt(stationId)); auto station = Application::data().getStation(Utils::toInt(stationId));
if (result.size() > 0 && station) if (station)
{ {
station->setFields(result[0]); station->setFields(result[0]);
station->setGarewayWorkMode();
} }
} }
}
} }
return err; return err;
}; };
@@ -692,15 +681,6 @@ Errcode HttpEntity::queryStationOverview(const httplib::Request& req, njson& jso
njson jsonCharge = njson::parse(R"({"category":2, "count":0, "power":0.0})"); njson jsonCharge = njson::parse(R"({"category":2, "count":0, "power":0.0})");
njson jsonSolar = njson::parse(R"({"category":3, "count":0, "power":0.0})"); njson jsonSolar = njson::parse(R"({"category":3, "count":0, "power":0.0})");
njson jsonSecurity = njson::parse(R"({"category":4, "count":0, "power":0.0})"); njson jsonSecurity = njson::parse(R"({"category":4, "count":0, "power":0.0})");
auto videoInfo = Config::getVideoInfo(stationId);
if (videoInfo)
{
jsonSecurity["host"] = videoInfo->host;
jsonSecurity["port"] = videoInfo->port;
jsonSecurity["user"] = videoInfo->user;
jsonSecurity["passwd"] = videoInfo->passwd;
}
for (auto& fields : result) for (auto& fields : result)
{ {
int category = fields.get<int>("category"); int category = fields.get<int>("category");
@@ -763,21 +743,16 @@ Errcode HttpEntity::queryStationInfo(const httplib::Request& req, njson& json, s
} }
Errcode HttpEntity::queryStationData(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStationData(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
std::string stationId = req.get_param_value("station_id");
auto station = Application::data().getStation(Utils::toInt(stationId));
njson jsondata;
if (station)
{
// 温度, 电压、电流、功率、功率因数、 // 温度, 电压、电流、功率、功率因数、
jsondata["voltage"] = station->voltage; njson jsondata;
jsondata["current"] = station->current; jsondata["voltage"] = Utils::toStr(200.32);
jsondata["power"] = station->power; jsondata["current"] = Utils::toStr(20.56);
jsondata["powerFactor"] = station->powerFactor; jsondata["power"] = Utils::toStr(200.32);
jsondata["envTemp"] = station->temperature; jsondata["powerFactor"] = Utils::toStr(1);
jsondata["envhum"] = station->humidity; jsondata["envTemp"] = Utils::toStr(200.32);
jsondata["aircStatus"] = station->aircStatus; jsondata["envhum"] = Utils::toStr(200.32);
jsondata["coolingStatus"] = station->coolingStatus; jsondata["aircStatus"] = Utils::toStr(1);
} jsondata["coolingStatus"] = Utils::toStr(0);
json["data"] = jsondata; json["data"] = jsondata;
return Errcode::OK; return Errcode::OK;
@@ -1131,9 +1106,9 @@ static std::string VerifyStatSqlCondition(Fields& params)
return sqlCondition; return sqlCondition;
} }
static std::string GetRequestStatParams(const httplib::Request& req, Fields& params) static std::string GetRequestStatParams(const httplib::Request& req)
{ {
Fields params;
GetRequestParam(req, {"station_id", "category", "start_date", "end_date"}, params); GetRequestParam(req, {"station_id", "category", "start_date", "end_date"}, params);
VerifyRequstParamsStatDate(params); VerifyRequstParamsStatDate(params);
return VerifyStatSqlCondition(params); return VerifyStatSqlCondition(params);
@@ -1141,8 +1116,7 @@ static std::string GetRequestStatParams(const httplib::Request& req, Fields& par
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; std::string sqlCondition = GetRequestStatParams(req);
std::string sqlCondition = GetRequestStatParams(req, params);
std::string sql = R"(SELECT SUM(ss.storage_elect_in) storage_elect_in, std::string sql = R"(SELECT SUM(ss.storage_elect_in) storage_elect_in,
SUM(storage_elect_in) storage_elect_in, SUM(storage_elect_in) storage_elect_in,
SUM(storage_elect_out) storage_elect_out, SUM(storage_elect_out) storage_elect_out,
@@ -1161,22 +1135,12 @@ Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std
SUM(income_charge) income_charge SUM(income_charge) income_charge
FROM stat_station ss)" + sqlCondition + ";"; FROM stat_station ss)" + sqlCondition + ";";
std::string stationId = params.value("station_id");
njson jsondata;
auto station = Application::data().getStation(Utils::toInt(stationId));
if (station)
{
jsondata["launch_date"] = station->launchDate;
}
std::vector<Fields> result; std::vector<Fields> result;
DaoEntity::execOnce(sql, result); DaoEntity::execOnce(sql, result);
if (result.size() > 0) if (result.size() > 0)
{ {
auto& fields = result[0]; auto& fields = result[0];
njson jsondata;
// jsondata["launch_date"] = "2025-09-01"; //场站上线日期 // jsondata["launch_date"] = "2025-09-01"; //场站上线日期
// jsondata["station_id"] = station_id; // jsondata["station_id"] = station_id;
jsondata["storage_elect_in"] = fields.value("storage_elect_in"); //储能充电电量kWh精度0.001 jsondata["storage_elect_in"] = fields.value("storage_elect_in"); //储能充电电量kWh精度0.001
@@ -1236,8 +1200,7 @@ Errcode HttpEntity::queryStatDetailList(const httplib::Request& req, njson& json
std::vector<Fields> result; std::vector<Fields> result;
auto err = DAO::queryStatStationList(pageinfo, params, result); auto err = DAO::queryStatStationList(pageinfo, params, result);
//json["data"] = FieldsToJsonArray(result); json["data"] = FieldsToJsonArray(result);
HttpHelper::setPagination(pageinfo, result, json);
return err; return err;
} }
@@ -1323,38 +1286,40 @@ Errcode HttpEntity::queryEnvironment(const httplib::Request& req, njson& json, s
auto& unit = iter->second; auto& unit = iter->second;
njson node; njson node;
node["pos"] = "#" + std::to_string(iter->first); node["pos"] = "#" + std::to_string(iter->first);
node["temp"] = Utils::toStr(unit.temp); node["temp"] = unit.temp;
node["hum"] = Utils::toStr(unit.hum); node["hum"] = unit.hum;
nodearray.push_back(node); nodearray.push_back(node);
} }
jsondata["temp_hum"] = nodearray; jsondata["temp_hum"] = nodearray;
} }
{ //空调 { //空调
auto& mapAircUnit = station->mapAircUnit; auto& mapAircUnit = station->mapAircUnit;
AircUnit unitTmp;
AircUnit* unit = (mapAircUnit.size() > 0) ? &(mapAircUnit[0]) : &unitTmp;
njson nodearray = njson::array(); njson nodearray = njson::array();
for (auto& item: mapAircUnit) if (unit)
{ {
auto& unit = item.second; nodearray.push_back({{"pos", "开关"}, {"status", unit->powerOn == 0 ? "关机" : "开机"}});
nodearray.push_back({{"pos", "开关"}, {"status", unit.powerOn == 0 ? "关机" : "开机"}}); nodearray.push_back({{"pos", "启动制冷指令"}, {"status", unit->cooling == 0 ? "启动" : "关闭"}});
nodearray.push_back({{"pos", "启动制冷指令"}, {"status", unit.cooling == 0 ? "启动" : "关闭"}}); nodearray.push_back({{"pos", "启动送风指令"}, {"status", unit->airSupply == 0 ? "关闭" : "启动"}});
nodearray.push_back({{"pos", "启动送风指令"}, {"status", unit.airSupply == 0 ? "关闭" : "启动"}}); nodearray.push_back({{"pos", "启动待机指令"}, {"status", unit->standby == 0 ? "关闭" : "启动"}});
nodearray.push_back({{"pos", "启动待机指令"}, {"status", unit.standby == 0 ? "关闭" : "启动"}}); nodearray.push_back({{"pos", "启动加热指令"}, {"status", unit->heating == 0 ? "关闭" : "启动"}});
nodearray.push_back({{"pos", "启动加热指令"}, {"status", unit.heating == 0 ? "关闭" : "启动"}}); nodearray.push_back({{"pos", "传感器故障"}, {"status", unit->sensorAlarm == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "传感器故障"}, {"status", unit.sensorAlarm == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "高低电压告警"}, {"status", unit->voltageAlarm == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "高低电压告警"}, {"status", unit.voltageAlarm == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "高低告警"}, {"status", unit->tempAlarm == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "高低告警"}, {"status", unit.tempAlarm == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "高低告警"}, {"status", unit->pressureAlarm == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "高低压告警"}, {"status", unit.pressureAlarm == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "缩机告警"}, {"status", unit->compressorAlarm == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "压缩机告警"}, {"status", unit.compressorAlarm == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "当前温度"}, {"status", std::to_string(unit->temp) + ""}});
nodearray.push_back({{"pos", "当前"}, {"status", std::to_string(unit.temp) + ""}}); nodearray.push_back({{"pos", "当前湿"}, {"status", std::to_string(unit->hum) + "%"}});
nodearray.push_back({{"pos", "当前湿度"}, {"status", std::to_string(unit.hum) + "%"}});
break;
} }
jsondata["airc"] = nodearray; jsondata["airc"] = nodearray;
} }
{ // 消防 { // 消防
static std::map<int, std::string> mapFireStatusDef = { {0, "正常"}, {1,"预警"}, {2,"火警"} }; static std::map<int, std::string> mapFireStatusDef = { {0, "正常"}, {1,"预警"}, {2,"火警"} };
std::map<int, string> mapStatusDef = {{0, "无效"}, {1, "掉线"}, {2, "正常"}, {3, "启动"}}; std::map<int, string> mapStatusDef = {{0, "无效"}, {1, "掉线"}, {2, "正常"}, {3, "启动"}};
auto& mapFire40Unit = station->mapFire40Unit; auto& mapFire40Unit = station->mapFire40Unit;
njson nodearray = njson::array(); njson nodearray = njson::array();
for (auto iter = mapFire40Unit.begin(); iter!=mapFire40Unit.end(); ++iter) for (auto iter = mapFire40Unit.begin(); iter!=mapFire40Unit.end(); ++iter)
@@ -1373,19 +1338,20 @@ Errcode HttpEntity::queryEnvironment(const httplib::Request& req, njson& json, s
} }
{ // 冷机 { // 冷机
auto& mapCoolingUnit = station->mapCoolingUnit; auto& mapCoolingUnit = station->mapCoolingUnit;
CoolingUnit unitTmp;
CoolingUnit* unit = (mapCoolingUnit.size() > 0) ? &(mapCoolingUnit[0]) : &unitTmp;
njson nodearray = njson::array(); njson nodearray = njson::array();
for (auto& item: mapCoolingUnit) if (unit)
{ {
auto& unit = item.second;
njson node; njson node;
nodearray.push_back({{"pos", "开关"}, {"status", unit.powerOn == 0 ? "关机" : "开机"}}); nodearray.push_back({{"pos", "开关"}, {"status", unit->powerOn == 0 ? "关机" : "开机"}});
nodearray.push_back({{"pos", "采样模式"}, {"status", unit.mode == 0 ? "出水温度" : "电芯温度"}}); nodearray.push_back({{"pos", "采样模式"}, {"status", unit->mode == 0 ? "出水温度" : "电芯温度"}});
nodearray.push_back({{"pos", "制冷状态"}, {"status", unit.cooling == 0 ? "关闭" : "启动"}}); nodearray.push_back({{"pos", "制冷状态"}, {"status", unit->cooling == 0 ? "关闭" : "启动"}});
nodearray.push_back({{"pos", "制热状态"}, {"status", unit.heating == 0 ? "关闭" : "启动"}}); nodearray.push_back({{"pos", "制热状态"}, {"status", unit->heating == 0 ? "关闭" : "启动"}});
nodearray.push_back({{"pos", "高温告警"}, {"status", unit.highTemp == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "高温告警"}, {"status", unit->highTemp == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "低温告警"}, {"status", unit.lowTemp == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "低温告警"}, {"status", unit->lowTemp == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "高压告警"}, {"status", unit.highPressure == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "高压告警"}, {"status", unit->highPressure == 0 ? "正常" : "告警"}});
nodearray.push_back({{"pos", "低压告警"}, {"status", unit.lowPressure == 0 ? "正常" : "告警"}}); nodearray.push_back({{"pos", "低压告警"}, {"status", unit->lowPressure == 0 ? "正常" : "告警"}});
} }
jsondata["cooling"] = nodearray; jsondata["cooling"] = nodearray;
} }

View File

@@ -29,7 +29,6 @@ public:
//void onGet(const httplib::Request& req, httplib::Response& resp); //void onGet(const httplib::Request& req, httplib::Response& resp);
Errcode logqueryBaseinfoin(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode login(const httplib::Request& req, njson& json, std::string& errmsg); Errcode login(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryUserList(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryUserList(const httplib::Request& req, njson& json, std::string& errmsg);

View File

@@ -9,20 +9,6 @@
#define TIMEOUT 10000L #define TIMEOUT 10000L
bool MqttClient::load(std::string filename)
{
njson jsonroot;
bool ret = JSON::load(filename, jsonroot);
if (!ret)
{
spdlog::error("[mqtt] load config file failed, filename={}", filename);
return false;
}
return true;
}
std::map<std::string, TopicInfo> MqttClient::s_mapTopicInfo;
int MqttClient::init(string addr, string clientId, string username, string password) int MqttClient::init(string addr, string clientId, string username, string password)
{ {
@@ -39,7 +25,7 @@ int MqttClient::init(string addr, string clientId, string username, string passw
this->clientId = clientId; this->clientId = clientId;
//this->mapTopicInfo["EMS_YX"] = TopicInfo("EMS_YX", 101); //this->mapTopicInfo["EMS_YX"] = TopicInfo("EMS_YX", 101);
//this->mapTopicInfo["EMS_YC"] = TopicInfo("EMS_YC", 101); this->mapTopicInfo["EMS_YC"] = TopicInfo("EMS_YC", 101);
//this->mapTopicInfo["EMS_YT"] = TopicInfo("EMS_YT", 101); //this->mapTopicInfo["EMS_YT"] = TopicInfo("EMS_YT", 101);
//this->mapTopicInfo["PCS_YX"] = TopicInfo("PCS_YX", 102, 1); //this->mapTopicInfo["PCS_YX"] = TopicInfo("PCS_YX", 102, 1);
//this->mapTopicInfo["PCS_YC"] = TopicInfo("PCS_YC", 102, 1); //this->mapTopicInfo["PCS_YC"] = TopicInfo("PCS_YC", 102, 1);
@@ -49,14 +35,14 @@ int MqttClient::init(string addr, string clientId, string username, string passw
//this->mapTopicInfo["BMS_YC"] = TopicInfo("BMS_YC", 104); //this->mapTopicInfo["BMS_YC"] = TopicInfo("BMS_YC", 104);
//this->mapTopicInfo["BCU_YX"] = TopicInfo("BCU_YX", 105, 1); //this->mapTopicInfo["BCU_YX"] = TopicInfo("BCU_YX", 105, 1);
//this->mapTopicInfo["BCU_YC"] = TopicInfo("BCU_YC", 105, 1); //this->mapTopicInfo["BCU_YC"] = TopicInfo("BCU_YC", 105, 1);
//this->mapTopicInfo["MEM_YC"] = TopicInfo("MEM_YC", 3); // 不召测 //this->mapTopicInfo["MEM_YC"] = TopicInfo("MEM_YC", 3, 1);
//this->mapTopicInfo["TH_YC"] = TopicInfo("TH_YC", 10, 1); //this->mapTopicInfo["TH_YC"] = TopicInfo("TH_YC", 10, 1);
//this->mapTopicInfo["Fire40_YX"] = TopicInfo("Fire40_YX", 7, 1); //this->mapTopicInfo["Fire40_YX"] = TopicInfo("Fire40_YX", 7, 1);
//this->mapTopicInfo["Cooling_YC"] = TopicInfo("Cooling_YC", 14, 1); this->mapTopicInfo["Cooling_YC"] = TopicInfo("Cooling_YC", 14, 1);
//this->mapTopicInfo["Cooling_YX"] = TopicInfo("Cooling_YX", 14, 1); this->mapTopicInfo["Cooling_YX"] = TopicInfo("Cooling_YX", 14, 1);
//this->mapTopicInfo["Gateway_YX"] = TopicInfo("Gateway_YX", 15, 1); //this->mapTopicInfo["Gateway_YX"] = TopicInfo("Gateway_YX", 15, 1);
//this->mapTopicInfo["Gateway_YC"] = TopicInfo("Gateway_YC", 15, 1); //this->mapTopicInfo["Gateway_YC"] = TopicInfo("Gateway_YC", 15, 1);
//this->mapTopicInfo["Charger_YC"] = TopicInfo("Charger_YC", 106); //this->mapTopicInfo["Charger_YC"] = TopicInfo("Charger_YC", 106, 1);
MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer; MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer; MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
@@ -149,9 +135,7 @@ void MqttClient::subscribe()
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer; MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
options.onSuccess = funcSuccess; options.onSuccess = funcSuccess;
options.onFailure = funcFailure; options.onFailure = funcFailure;
for (auto& item: MqttClient::s_mapTopicInfo) for (auto& item: mapTopicInfo)
{
if (item.second.enabled)
{ {
std::string topic = "up/json/" + clientId + "/" + item.first; std::string topic = "up/json/" + clientId + "/" + item.first;
options.context = (void*)&item.first; options.context = (void*)&item.first;
@@ -165,7 +149,6 @@ void MqttClient::subscribe()
spdlog::info("[mqtt] subscribe [{},{}] ", topic, qos); spdlog::info("[mqtt] subscribe [{},{}] ", topic, qos);
} }
} }
}
} }
int MqttClient::publish(std::string topic, std::string text) int MqttClient::publish(std::string topic, std::string text)
@@ -216,10 +199,10 @@ int MqttClient::polling()
return 0; return 0;
} }
for (auto& item: MqttClient::s_mapTopicInfo) for (auto& item: mapTopicInfo)
{ {
auto& topicInfo = item.second; auto& topicInfo = item.second;
if (topicInfo.polling && topicInfo.enabled) if (topicInfo.polling)
{ {
std::vector<std::shared_ptr<Device>> vecDevice; std::vector<std::shared_ptr<Device>> vecDevice;
station->getDeviceByType(topicInfo.deviceType, vecDevice); station->getDeviceByType(topicInfo.deviceType, vecDevice);
@@ -285,6 +268,96 @@ void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp)
this->destory(); this->destory();
} }
void MqttClient::ParseArrivedMessage(njson& json, string clientId, string command, std::shared_ptr<Station> station)
{
std::string stationNo = clientId;
auto mapRegPtr = REGAddr::getRegMap(command);
if (!mapRegPtr)
{
spdlog::error("[mqtt] get register add info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return;
}
auto iterTopic = mapTopicInfo.find(command);
if (iterTopic == mapTopicInfo.end())
{
spdlog::error("[mqtt] get topic info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return;
}
TopicInfo& topicInfo = iterTopic->second;
int deviceNo = -1;
JSON::read(json, "no", deviceNo);
auto device = station->getDeviceByType(topicInfo.deviceType, Utils::toStr(deviceNo));
if (!device)
{
return;
}
for (auto& item: json.items())
{
std::string key = item.key();
if (key != "ts" && key != "no")
{
auto data = json.at(key);
if (data.is_array())
{
std::string addrText;
auto iter = mapRegPtr->find(key);
for (int i = 0; i<data.size(); ++i)
{
if (iter != mapRegPtr->end())
{
auto addr = iter->first;
int val = data[i];
device->setParam(addr, val);
spdlog::info("[mqtt] read [{}]={},{}", addr, val, iter->second.remark);
if (command == "EMS_YC" && addr == "0x110C")
{
int a = 30;
a = 100;
}
if (command == "EMS_YC")
{
station->setRuntimeData(addr, val);
}
else if (command == "Fire40_YX")
{
station->setFire40Data(deviceNo, addr, val);
}
else if (command == "TH_YC")
{
station->setTHData(deviceNo, addr, val);
}
else if (command == "Cooling_YX" || command == "Cooling_YC")
{
station->setCoolingData(deviceNo, addr, val);
}
else if (command == "Gateway_YX")
{
//if (key == "CDZ") "CDZ": 1, //充电桩 1在线0离线
//else if (key == "EMU") //储能 1在线0离线
}
++iter;
}
}
}
else if (data.is_number())
{
device->setParam(key, data.get<int>());
}
else if (data.is_string())
{
device->setParam(key, Utils::toInt(data.get<std::string>()));
}
}
}
}
int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* msg) int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* msg)
{ {
std::string topicStr = topic; std::string topicStr = topic;
@@ -339,7 +412,7 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
} }
else else
{ {
ParseArrivedMessage(json, command, station); ParseArrivedMessage(json, clientId, command, station);
} }
// 必须释放消息内存! // 必须释放消息内存!
@@ -349,119 +422,117 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
} }
void MqttClient::ParseArrivedMessage(njson& json, string command, std::shared_ptr<Station> station) string MQTT::pack(std::string name)
{ {
std::string stationNo = clientId; njson json;
json["ts"] = Utils::time();
json["no"] = 1;
auto iterTopic = MqttClient::s_mapTopicInfo.find(command); if (name == "EMS_YC")
if (iterTopic == MqttClient::s_mapTopicInfo.end())
{ {
spdlog::error("[mqtt] get topic info error, clientId={}, stationId={}, command={}", clientId, stationNo, command); //A相电压 R uint32 1V 0x107E
return; //B相电压 R uint32 1V 0x1080
} //C相电压 R uint32 1V 0x1082
TopicInfo& topicInfo = iterTopic->second; //A相电流 R int32 1A 0x1084
//B相电流 R int32 1A 0x1086
//C相电流 R int32 1A 0x1088
int deviceNo = -1; //储能系统SOC R uint16 0.1 0x107A
JSON::read(json, "no", deviceNo); //储能系统SOH R uint16 0.1 0x107B
auto device = station->getDeviceByType(topicInfo.deviceType, Utils::toStr(deviceNo));
if (!device)
{
spdlog::error("[mqtt] get device info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return;
}
auto mapRegPtr = REGAddr::getRegMap(command); json["addr"] = {"0x107A", "0x107B", "0x107E", "0x1080", "0x1082", "0x1084", "0x1086", "0x1088"};
if (!mapRegPtr)
{
spdlog::error("[mqtt] get register add info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return;
} }
for (auto& item: json.items()) else if (name == "PCS_YC")
{ {
std::string key = item.key(); //总充电量 R uint32 1kWh 0x0003
if (key == "ts" || key == "no") //总放电量 R uint32 1kWh 0x0005
{
continue;
}
auto data = json[key]; //A相电压 R int16 1V 0x0010
if (data.is_array()) //B相电压 R int16 1V 0x0011
{ //C相电压 R int16 1V 0x0012
if (command == "Charger_YC")
{
if (key == "1") key = "11";
else if (key == "2") key = "21";
}
std::string addrText;
auto iter = mapRegPtr->find(key);
if (iter != mapRegPtr->end())
{
for (int i = 0; i<data.size(); ++i)
{
auto addr = iter->first;
int val = data[i];
device->setParam(addr, val);
spdlog::debug("[mqtt] read [{}]={}, {}", addr, val, iter->second.remark);
if (command == "MEM_YC") { station->setRuntimeData(deviceNo, addr, val); } //A相电流 R int16 1A 0x0019
else if (command == "Fire40_YX") { station->setFire40Data(deviceNo, addr, val); } //B相电流 R int16 1A 0x001A
else if (command == "TH_YC") { station->setTHData(deviceNo, addr, val); } //C相电流 R int16 1A 0x001B
else if (command == "Cooling_YX" || command == "Cooling_YC") { station->setCoolingData(deviceNo, addr, val); }
else if (command == "Gateway_YX") //三相总有功功率 R int16 1kW 0x0025
//三相总无功功率 R int16 1kVar 0x0026
//三相总视在功率 R int16 1kVA 0x0027
//三相总功率因数 R int16 1 0x0028
//充电功率 R int16 1kW 0x002C
//放电功率 R int16 1kW 0x002D
json["addr"] = {"0x0003", "0x0005", "0x0010", "0x0011", "0x0012", "0x0019", "0x001A", "0x001B", "0x0025", "0x0026", "0x0027", "0x0028", "0x002C", "0x002D"};
}
else if (name == "PCU_YC")
{ {
//if (key == "CDZ") "CDZ": 1, //充电桩 1在线0离线 //PCS侧线A相电压 R int16 1v 0x0013
//else if (key == "EMU") //储能 1在线0离线 //PCS侧线B相电压 R int16 1v 0x0014
//PCS侧线C相电压 R int16 1v 0x0015
//PCS侧功率因数A R int16 1 0x0019
//PCS侧功率因数B R int16 1 0x001A
//PCS侧功率因数C R int16 1 0x001B
//PCS侧相电流A R int16 1A 0x001C
//PCS侧相电流B R int16 1A 0x001D
//PCS侧相电流C R int16 1A 0x001E
//PCS侧三相总有功功率 R int16 1kW 0x0028
//PCS侧三相总无功功率 R int16 1kVar 0x0029
//PCS侧三相总视在功率 R int16 1kVA 0x002A
//PCS侧三相总功率因数 R int16 1 0x002B
json["addr"] = {"0x0013", "0x0014", "0x0015", "0x1080", "0x1082", "0x1084", "0x1086", "0x1088"};
} }
++iter; else if (name == "BMS_YC")
}
}
}
else if (data.is_number())
{ {
device->setParam(key, data.get<int>()); //SOC R uint16 0.1 0x0001
//SOH R uint16 0.1 0x0002
//电压 R uint32 0.1V 0x0003
//电流 R int32 0.1A 0x0005
//可充电量 R uint32 1kWh 0x0007
//可放电量 R uint32 1kWh 0x0009
//可充电状态 R uint16 1可充电0不可充电 0x0047
//可放电状态 R uint16 1可放电0不可放电 0x0048
//运行状态 R uint16 运行状态 0-正常 1-告警 2-保护 0x0049
//充放电状态 R uint16 0-待机 1-充电 2-放电 0x004A
json["addr"] = {"0x0001", "0x0002", "0x0003", "0x0005", "0x0007", "0x0009", "0x0047", "0x0048", "0x0049", "0x004A"};
} }
else if (data.is_string()) else if (name == "BCU_YC")
{ {
device->setParam(key, Utils::toInt(data.get<std::string>())); //电表类型 R uint16 "0储能站总表 1逆变前侧电表 2逆变后侧电表 3配电柜电表 4并网口电表" 0x0008
} //A相电压 R uint32 1V 0x000B
} //B相电压 R uint32 1V 0x000D
} //C相电压 R uint32 1V 0x000F
std::vector<std::string> KEY_CHARGER_1 = {"31071", "31073", "31075", "31077", "31079", "31081", "31083"}; //A相电流 R int32 1A 0x0011
std::vector<std::string> KEY_CHARGER_2 = {"31072", "31074", "31076", "31078", "31080", "31082", "31084"}; //B相电流 R int32 1A 0x0013
void MqttClient::ParseMessageCharge(njson& json, string command, std::shared_ptr<Station> station, std::shared_ptr<Device> device) //C相电流 R int32 1A 0x0015
{
if (json.contains("1")) //尖段电价 R uint32 1RMB 0x0027
{ //峰段电价 R uint32 1RMB 0x0029
auto& jsondata = json["1"]; //平段电价 R uint32 1RMB 0x002B
if (jsondata.is_array()) //谷段电价 R uint32 1RMB 0x002D
{ //日充电电量 R uint32 1kWh 0x002F
for (int i = 0; i<jsondata.size(); i++) //日放电电量 R uint32 1kWh 0x0031
{ //日充电费用 R uint32 1RMB 0x0033
if (i<KEY_CHARGER_1.size()) //日放电费用 R uint32 1RMB 0x0035
{ //日收益 R int32 1RMB 0x0037
auto& addr = KEY_CHARGER_1[i];
auto val = jsondata[i].get<int>(); //总充电电量 R uint32 1kWh 0x004D
device->setParam(addr, val); //总放电电量 R uint32 1kWh 0x004F
spdlog::info("[mqtt] read: 枪1 [{}]={}", addr, val); //总充电费用 R uint32 1RMB 0x0051
} //总放电费用 R uint32 1RMB 0x0053
} //总收益 R int32 1RMB 0x0055
}
}
if (json.contains("2"))
{
auto& jsondata = json["2"];
if (jsondata.is_array())
{
for (int i = 0; i<jsondata.size(); i++)
{
if (i<KEY_CHARGER_2.size())
{
auto& addr = KEY_CHARGER_2[i];
auto val = jsondata[i].get<int>();
device->setParam(addr, val);
spdlog::info("[mqtt] read: 枪2 [{}]={}", addr, val);
}
}
} }
else if (name == "TH_YC")
{
//所属通道号 R uint16 1 0x0001
//所属温湿度号 R uint16 1~10 0x0002
//温度 R int16 0.1℃ 0x0003
//湿度 R int16 0.1℃ 0x0004
} }
return json.dump();
} }

View File

@@ -7,14 +7,13 @@
#include "common/JsonN.h" #include "common/JsonN.h"
class Station; class Station;
class Device;
struct TopicInfo struct TopicInfo
{ {
std::string name; std::string name;
int deviceType {0}; int deviceType {0};
int polling {0}; // 召测 int polling {0}; // 召测
int enabled {1};
TopicInfo() {}; TopicInfo() {};
TopicInfo(std::string name, int deviceType, int polling=0) TopicInfo(std::string name, int deviceType, int polling=0)
:name(name), deviceType(deviceType), polling(polling) :name(name), deviceType(deviceType), polling(polling)
@@ -26,8 +25,6 @@ using namespace std;
class MqttClient class MqttClient
{ {
public: public:
static bool load(std::string filename);
int init(string addr, string clientId, string username, string password); int init(string addr, string clientId, string username, string password);
void destory(); void destory();
@@ -42,8 +39,7 @@ public:
void onConnectFaiure(MQTTAsync_failureData* resp); void onConnectFaiure(MQTTAsync_failureData* resp);
int onMessageArrived(char* topic, int len, MQTTAsync_message* msg); int onMessageArrived(char* topic, int len, MQTTAsync_message* msg);
void ParseArrivedMessage(njson& json, string command, std::shared_ptr<Station> station); void ParseArrivedMessage(njson& json, string clientId, string command, std::shared_ptr<Station> station);
void ParseMessageCharge(njson& json, string command, std::shared_ptr<Station> station, std::shared_ptr<Device> device);
public: public:
// MQTT clientId (使用station 的 code) // MQTT clientId (使用station 的 code)
@@ -55,7 +51,7 @@ public:
bool isConnected {false}; bool isConnected {false};
bool isSubscribed {false}; bool isSubscribed {false};
static std::map<std::string, TopicInfo> s_mapTopicInfo; std::map<std::string, TopicInfo> mapTopicInfo;
}; };
@@ -75,3 +71,12 @@ public:
#define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC" #define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC"
#define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC" #define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC"
class MQTT
{
public:
public:
static string pack(std::string name);
};