mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-28 03:09:24 +08:00
实现MQTT功能, 修改HTTP接口
This commit is contained in:
@@ -6,8 +6,17 @@
|
||||
#include "app/Application.h"
|
||||
#include "app/AppData.h"
|
||||
#include "app/Config.h"
|
||||
#include "app/Station.h"
|
||||
|
||||
static NJsonNode FieldsToJsonArray(std::vector<Fields> vecFields)
|
||||
static void FieldsToJson(Fields& fields, NJsonNode& json)
|
||||
{
|
||||
for (auto& item : fields.map())
|
||||
{
|
||||
json[item.first] = item.second;
|
||||
}
|
||||
}
|
||||
|
||||
static NJsonNode FieldsToJsonArray(std::vector<Fields>& vecFields)
|
||||
{
|
||||
NJsonNode jsonnode = NJsonNode::array();
|
||||
for (auto& fields : vecFields)
|
||||
@@ -24,13 +33,45 @@ static NJsonNode FieldsToJsonArray(std::vector<Fields> vecFields)
|
||||
|
||||
static void GetRequestParam(const httplib::Request& req, const std::vector<std::string>& vecKeys, Fields& fields)
|
||||
{
|
||||
for (auto& key : vecKeys)
|
||||
|
||||
if (req.method == "GET")
|
||||
{
|
||||
if (req.has_param(key))
|
||||
for (auto& key : vecKeys)
|
||||
{
|
||||
fields.set(key, req.get_param_value(key));
|
||||
if (req.has_param(key))
|
||||
{
|
||||
fields.set(key, req.get_param_value(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (req.method == "POST")
|
||||
{
|
||||
NJsonNode json;
|
||||
NJson::parse(req.body, json);
|
||||
for (auto& key : vecKeys)
|
||||
{
|
||||
if (json.contains(key)) {
|
||||
|
||||
switch (json[key].type())
|
||||
{
|
||||
case NJsonNode::value_t::string: { fields.set(key, json[key].get<std::string>()); } break;
|
||||
case NJsonNode::value_t::boolean: { fields.set(key, json[key].get<bool>()); } break;
|
||||
case NJsonNode::value_t::number_integer: { fields.set(key, json[key].get<int>()); } break;
|
||||
case NJsonNode::value_t::number_unsigned: { fields.set(key, json[key].get<int>()); } break;
|
||||
case NJsonNode::value_t::number_float: { fields.set(key, json[key].get<float>()); } break;
|
||||
case NJsonNode::value_t::null: {} break;
|
||||
case NJsonNode::value_t::object: {} break;
|
||||
case NJsonNode::value_t::array: {} break;
|
||||
case NJsonNode::value_t::binary: {} break;
|
||||
case NJsonNode::value_t::discarded: {} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HttpHelper
|
||||
@@ -77,86 +118,106 @@ struct HandlerOptions
|
||||
}
|
||||
};
|
||||
|
||||
static std::map<std::string, HandlerOptions> g_mapHttpHandler =
|
||||
static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
|
||||
{
|
||||
{"/login", HandlerOptions(&HttpEntity::login, {DMUser::ACCOUNT, DMUser::PASSWD})},
|
||||
{"/queryUserList", HandlerOptions(&HttpEntity::queryUserList, {"token"})},
|
||||
{"/insertUser", HandlerOptions(&HttpEntity::insertUser, {"token", DMUser::ACCOUNT})},
|
||||
{"/updateUser", HandlerOptions(&HttpEntity::updateUser, {"token", DMUser::USER_ID})},
|
||||
{"/deleteUser", HandlerOptions(&HttpEntity::deleteUser, {"token", DMUser::USER_ID})},
|
||||
{"/queryUserList", HandlerOptions(&HttpEntity::queryUserList, {})},
|
||||
{"/deleteUser", HandlerOptions(&HttpEntity::deleteUser, { DMUser::USER_ID})},
|
||||
|
||||
{"/queryPermissionList", HandlerOptions(&HttpEntity::queryPermissionList, {"token"})},
|
||||
{"/insertPermission", HandlerOptions(&HttpEntity::insertPermission, {"token", DMPermission::NAME})},
|
||||
{"/updatePermission", HandlerOptions(&HttpEntity::updatePermission, {"token", DMPermission::PERMISSION_ID})},
|
||||
{"/deletePermission", HandlerOptions(&HttpEntity::deletePermission, {"token", DMPermission::PERMISSION_ID})},
|
||||
{"/queryPermissionList", HandlerOptions(&HttpEntity::queryPermissionList, {})},
|
||||
{"/deletePermission", HandlerOptions(&HttpEntity::deletePermission, { DMPermission::PERMISSION_ID})},
|
||||
|
||||
{"/queryRoleList", HandlerOptions(&HttpEntity::queryRoleList, {"token"})},
|
||||
{"/insertRole", HandlerOptions(&HttpEntity::insertRole, {"token", DMRole::NAME})},
|
||||
{"/updateRole", HandlerOptions(&HttpEntity::updateRole, {"token", DMRole::ROLE_ID})},
|
||||
{"/deleteRole", HandlerOptions(&HttpEntity::deleteRole, {"token", DMRole::ROLE_ID})},
|
||||
{"/queryRoleList", HandlerOptions(&HttpEntity::queryRoleList, {})},
|
||||
{"/deleteRole", HandlerOptions(&HttpEntity::deleteRole, { DMRole::ROLE_ID})},
|
||||
|
||||
{"/queryStationList", HandlerOptions(&HttpEntity::queryStationList, {"token"})},
|
||||
{"/insertStation", HandlerOptions(&HttpEntity::insertStation, {"token", DMStation::NAME})},
|
||||
{"/updateStation", HandlerOptions(&HttpEntity::updateStation, {"token", DMStation::STATION_ID})},
|
||||
{"/deleteStation", HandlerOptions(&HttpEntity::deleteStation, {"token", DMStation::STATION_ID})},
|
||||
|
||||
{"/queryDeviceList", HandlerOptions(&HttpEntity::queryDeviceList, {"token"})},
|
||||
{"/insertDevice", HandlerOptions(&HttpEntity::insertDevice, {"token", DMDevice::NAME})},
|
||||
{"/updateDevice", HandlerOptions(&HttpEntity::updateDevice, {"token", DMDevice::DEVICE_ID})},
|
||||
{"/deleteDevice", HandlerOptions(&HttpEntity::deleteDevice, {"token", DMDevice::DEVICE_ID})},
|
||||
{"/queryDevicTypeDef", HandlerOptions(&HttpEntity::queryDevicTypeDef, {"token"})},
|
||||
|
||||
{"/queryPolicyList", HandlerOptions(&HttpEntity::queryPolicyList, {"token"})},
|
||||
{"/insertPolicy", HandlerOptions(&HttpEntity::insertPolicy, {"token", DMPolicy::NAME})},
|
||||
{"/updatePolicy", HandlerOptions(&HttpEntity::updatePolicy, {"token", DMPolicy::POLICY_ID})},
|
||||
{"/deletePolicy", HandlerOptions(&HttpEntity::deletePolicy, {"token", DMPolicy::POLICY_ID})},
|
||||
{"/queryStationList", HandlerOptions(&HttpEntity::queryStationList, {})},
|
||||
{"/deleteStation", HandlerOptions(&HttpEntity::deleteStation, { DMStation::STATION_ID})},
|
||||
|
||||
{"/querySystemLogList", HandlerOptions(&HttpEntity::querySystemLogList, {"token"})},
|
||||
{"/queryStationInfo", HandlerOptions(&HttpEntity::queryStationInfo, { DMStation::STATION_ID})},
|
||||
{"/queryStationRuntime", HandlerOptions(&HttpEntity::queryStationRuntime, { DMStation::STATION_ID})},
|
||||
|
||||
{"/queryAlertLogList", HandlerOptions(&HttpEntity::queryAlertLogList, {"token"})},
|
||||
{"/queryDeviceList", HandlerOptions(&HttpEntity::queryDeviceList, {})},
|
||||
{"/deleteDevice", HandlerOptions(&HttpEntity::deleteDevice, { DMDevice::DEVICE_ID})},
|
||||
{"/queryDevicTypeDef", HandlerOptions(&HttpEntity::queryDevicTypeDef, {})},
|
||||
|
||||
{"/queryPolicyList", HandlerOptions(&HttpEntity::queryPolicyList, {})},
|
||||
|
||||
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {"token"})},
|
||||
|
||||
{"/deletePolicy", HandlerOptions(&HttpEntity::deletePolicy, { DMPolicy::POLICY_ID})},
|
||||
|
||||
{"/querySystemLogList", HandlerOptions(&HttpEntity::querySystemLogList, {})},
|
||||
|
||||
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {"token"})},
|
||||
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {"token"})},
|
||||
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {"token"})},
|
||||
{"/queryAlertLogList", HandlerOptions(&HttpEntity::queryAlertLogList, {})},
|
||||
|
||||
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})},
|
||||
|
||||
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})},
|
||||
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})},
|
||||
{"/queryStatStation", HandlerOptions(&HttpEntity::queryStatStation, {})},
|
||||
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})},
|
||||
|
||||
{"/queryEnvironment", HandlerOptions(&HttpEntity::queryEnvironment, { "station_id"})},
|
||||
|
||||
//{"/insert", HandlerOptions(&HttpEntity::insert, {})},
|
||||
//{"/update", HandlerOptions(&HttpEntity::update, {})},
|
||||
//{"/delete", HandlerOptions(&HttpEntity::delete, {})},
|
||||
};
|
||||
|
||||
static std::map<std::string, HandlerOptions> g_mapHttpHandlerPost
|
||||
{
|
||||
{"/insertUser", HandlerOptions(&HttpEntity::insertUser, { DMUser::ACCOUNT})},
|
||||
{"/updateUser", HandlerOptions(&HttpEntity::updateUser, { DMUser::USER_ID})},
|
||||
|
||||
{"/insertPermission", HandlerOptions(&HttpEntity::insertPermission, { DMPermission::NAME})},
|
||||
{"/updatePermission", HandlerOptions(&HttpEntity::updatePermission, { DMPermission::PERMISSION_ID})},
|
||||
|
||||
{"/insertRole", HandlerOptions(&HttpEntity::insertRole, { DMRole::NAME})},
|
||||
{"/updateRole", HandlerOptions(&HttpEntity::updateRole, { DMRole::ROLE_ID})},
|
||||
|
||||
{"/insertStation", HandlerOptions(&HttpEntity::insertStation, { DMStation::NAME})},
|
||||
{"/updateStation", HandlerOptions(&HttpEntity::updateStation, { DMStation::STATION_ID})},
|
||||
|
||||
{"/insertDevice", HandlerOptions(&HttpEntity::insertDevice, { DMDevice::NAME})},
|
||||
{"/updateDevice", HandlerOptions(&HttpEntity::updateDevice, { DMDevice::DEVICE_ID})},
|
||||
|
||||
{"/insertPolicy", HandlerOptions(&HttpEntity::insertPolicy, { DMPolicy::NAME})},
|
||||
{"/updatePolicy", HandlerOptions(&HttpEntity::updatePolicy, { DMPolicy::POLICY_ID})},
|
||||
};
|
||||
|
||||
bool CheckHttpToken(const httplib::Request& req)
|
||||
{
|
||||
// 验证token
|
||||
std::string token = req.get_param_value("token");
|
||||
if (!token.empty())
|
||||
{
|
||||
User user = Application::data().getUser(token);
|
||||
if (!user.userId.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
HttpEntity::HttpEntity()
|
||||
{
|
||||
bool useToken = Config::option.http.useToken;
|
||||
for (auto& item : g_mapHttpHandler)
|
||||
for (auto& item : g_mapHttpHandlerGet)
|
||||
{
|
||||
std::string name = item.first;
|
||||
HandlerOptions& handler = item.second;
|
||||
this->httpsvr.Get(name, [=, &handler](const httplib::Request& req, httplib::Response& resp)
|
||||
{
|
||||
spdlog::info("[http] request: {}", name);
|
||||
NJsonNode json;
|
||||
Errcode errcode = Errcode::OK;
|
||||
|
||||
if (name != "/login" && useToken)
|
||||
{
|
||||
// 验证token
|
||||
std::string token = req.get_param_value("token");
|
||||
if (token.empty())
|
||||
{
|
||||
errcode = Errcode::ERR_TOKEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
User user = Application::data().getUser(token);
|
||||
if (user.userId.empty())
|
||||
{
|
||||
errcode = Errcode::ERR_TOKEN;
|
||||
}
|
||||
}
|
||||
bool ret = CheckHttpToken(req);
|
||||
errcode = ret ? Errcode::OK : Errcode::ERR_TOKEN;
|
||||
}
|
||||
|
||||
NJsonNode json;
|
||||
std::string errmsg;
|
||||
if (errcode == Errcode::OK)
|
||||
{
|
||||
@@ -169,7 +230,38 @@ HttpEntity::HttpEntity()
|
||||
errcode = (this->*(handler.func))(req, resp, json);
|
||||
}
|
||||
}
|
||||
json["errcode"] = errcode;
|
||||
json["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
|
||||
resp.set_content(json.dump(), "text/plain; charset=utf-8");
|
||||
resp.status = 200;
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& item : g_mapHttpHandlerPost)
|
||||
{
|
||||
std::string name = item.first;
|
||||
HandlerOptions& handler = item.second;
|
||||
this->httpsvr.Post(name, [=](const httplib::Request& req, httplib::Response& resp)
|
||||
{
|
||||
Errcode errcode = Errcode::OK;
|
||||
std::string errmsg;
|
||||
if (name != "/login" && useToken)
|
||||
{
|
||||
bool ret = CheckHttpToken(req);
|
||||
errcode = ret ? Errcode::OK : Errcode::ERR_TOKEN;
|
||||
}
|
||||
|
||||
if (errcode == Errcode::OK)
|
||||
{
|
||||
NJsonNode jsonparam;
|
||||
bool ret = NJson::parse(req.body, jsonparam);
|
||||
if (ret)
|
||||
{
|
||||
errcode = (this->*(handler.func))(req, resp, jsonparam);
|
||||
}
|
||||
}
|
||||
|
||||
NJsonNode json;
|
||||
json["errcode"] = errcode;
|
||||
json["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
|
||||
resp.set_content(json.dump(), "text/plain; charset=utf-8");
|
||||
@@ -383,6 +475,61 @@ Errcode HttpEntity::deleteStation(const httplib::Request& req, httplib::Response
|
||||
return DAO::remove(NULL, DMStation::TABLENAME, primaryKey, req.get_param_value(primaryKey));
|
||||
};
|
||||
|
||||
Errcode HttpEntity::queryStationInfo(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
// 查询场站的基础配置信息
|
||||
std::string stationId = req.get_param_value("station_id");
|
||||
if (stationId.empty())
|
||||
{
|
||||
return Errcode::ERR_PARAM;
|
||||
}
|
||||
|
||||
std::string sql = "SELECT * FROM " + DMStation::TABLENAME + " WHERE station_id=" + stationId + ";";
|
||||
std::vector<Fields> result;
|
||||
Errcode err = DAO::exec(NULL, sql, result);
|
||||
if (err != Errcode::OK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
if (result.size() == 0)
|
||||
{
|
||||
return Errcode::ERR_DATA_NUL;
|
||||
}
|
||||
auto& fields = result[0];
|
||||
|
||||
NJsonNode jsondata;
|
||||
std::string attr = fields.remove(DMStation::ATTR);
|
||||
NJson::parse(attr, jsondata);
|
||||
|
||||
FieldsToJson(fields, jsondata);
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
|
||||
// work_mode: 运行模式:
|
||||
// capacity: 储能容量:
|
||||
|
||||
// {"batttey_type": "磷酸铁锂", "cooling_type":"风冷", "voltage_rated":"300", "power_rated": "1500"}
|
||||
// batttey_type: 电池类型:
|
||||
// cooling_type: 冷却方式:
|
||||
// voltage_rated: 电池额定电压:
|
||||
// power_rated: PCS额定功率
|
||||
}
|
||||
Errcode HttpEntity::queryStationData(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
// 温度, 电压、电流、功率、功率因数、
|
||||
NJsonNode jsondata;
|
||||
jsondata["voltage"] = Utils::toStr(200.32);
|
||||
jsondata["current"] = Utils::toStr(20.56);
|
||||
jsondata["power"] = Utils::toStr(200.32);
|
||||
jsondata["powerFactor"] = Utils::toStr(1);
|
||||
jsondata["envTemp"] = Utils::toStr(200.32);
|
||||
jsondata["envhum"] = Utils::toStr(200.32);
|
||||
jsondata["aircStatus"] = Utils::toStr(1);
|
||||
jsondata["coolingStatus"] = Utils::toStr(0);
|
||||
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
|
||||
Errcode HttpEntity::queryDeviceList(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
@@ -513,40 +660,70 @@ Errcode HttpEntity::queryStatSystem(const httplib::Request& req, httplib::Respon
|
||||
{
|
||||
auto& appdata = Application::data();
|
||||
|
||||
json["launch_date"] = "2025-01-01"; //: 系统上线启用日期,格式:yyyy-mm-dd
|
||||
json["income_total"] = "0.00"; // : 累计收益(元),精度0.01
|
||||
json["station_num"] = Utils::toStr(appdata.getStationCount()); // : 能源站数量
|
||||
json["storage_device_num "] = Utils::toStr(appdata.getStationCount()); //: 储能设备数量
|
||||
json["solar_device_num"] = "0"; // : 光伏设备数量
|
||||
json["capacity_total"] = "0.000"; // : 储能总容量(kWh),精度0.001
|
||||
json["elect_gen"] = "0.000"; // : 发电总电量(kWh),精度0.001
|
||||
json["elect_grid"] = "0.000"; // : 入网种电量(kWh),精度0.001
|
||||
json["storage_elect_in"] = "0.000"; // : 储能充电总电量(kWh),精度0.001
|
||||
json["storage_elect_out"] = "0.000"; // : 储能放电总电量(kWh),精度0.001
|
||||
NJsonNode jsondata;
|
||||
jsondata["launch_date"] = "2025-01-01"; //: 系统上线启用日期,格式:yyyy-mm-dd
|
||||
jsondata["income_total"] = std::to_string(Utils::random(100, 200)); // : 累计收益(元),精度0.01
|
||||
jsondata["station_num"] = Utils::toStr(appdata.getStationCount()); // : 能源站数量
|
||||
jsondata["storage_device_num "] = Utils::toStr(appdata.getStationCount()); //: 储能设备数量
|
||||
jsondata["solar_device_num"] = "0"; // : 光伏设备数量
|
||||
jsondata["capacity_total"] = std::to_string(Utils::random(100, 200)); // : 储能总容量(kWh),精度0.001
|
||||
jsondata["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); // : 发电总电量(kWh),精度0.001
|
||||
jsondata["solar_elect_grid"] = std::to_string(Utils::random(100, 200)); // : 入网种电量(kWh),精度0.001
|
||||
jsondata["storage_elect_in"] = std::to_string(Utils::random(100, 200)); // : 储能充电总电量(kWh),精度0.001
|
||||
jsondata["storage_elect_out"] = std::to_string(Utils::random(100, 200)); // : 储能放电总电量(kWh),精度0.001
|
||||
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
|
||||
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
std::string station_id = req.get_param_value("station_id");
|
||||
std::string category = req.get_param_value("category");
|
||||
|
||||
json["dt"] = "2025-01-01"; //日期
|
||||
json["storage_elect_in"] = "123.123"; //储能充电电量(kWh),精度:0.001
|
||||
json["storage_elect_out"] = "123.123"; //储能放电电量(kWh),精度:0.001
|
||||
json["storage_num_in"] = "1"; //储能设备充电次数
|
||||
json["storage_num_out"] = "1"; //储能设备放电次数
|
||||
json["storage_num_err"] = "1"; //储能设备故障次数
|
||||
json["solar_elect_gen"] = "123.123"; //光伏发电电量(kWh),精度:0.001
|
||||
json["solar_elect_grid"] = "123.123"; //光伏入网电量(kWh),精度:0.001
|
||||
json["solar_num_err"] = "1"; //光伏设备故障次数
|
||||
json["charge_elect"] = "123.123"; //充电设备充电电量(kWh),精度:0.001
|
||||
json["charge_num"] = "1"; //充电设备充电次数
|
||||
json["charge_num_err"] = "1"; //充电设备故障次数
|
||||
json["income_elect"] = ""; //发电收益(元),精度:0.01
|
||||
json["income_charge"] = ""; //充电收益(元),精度:0.01
|
||||
json["usage"] = "";
|
||||
NJsonNode jsondata;
|
||||
jsondata["station_id"] = "1";
|
||||
jsondata["launch_date"] = "2025-01-01"; //场站上线日期
|
||||
jsondata["usage_rate"] = "12";
|
||||
jsondata["storage_elect_in"] = "123.123"; //储能充电电量(kWh),精度:0.001
|
||||
jsondata["storage_elect_out"] = "123.123"; //储能放电电量(kWh),精度:0.001
|
||||
jsondata["storage_num_in"] = "1"; //储能设备充电次数
|
||||
jsondata["storage_num_out"] = "1"; //储能设备放电次数
|
||||
jsondata["storage_num_err"] = "1"; //储能设备故障次数
|
||||
jsondata["solar_elect_gen"] = "123.123"; //光伏发电电量(kWh),精度:0.001
|
||||
jsondata["solar_elect_grid"] = "123.123"; //光伏入网电量(kWh),精度:0.001
|
||||
jsondata["solar_num_err"] = "1"; //光伏设备故障次数
|
||||
jsondata["charge_elect"] = "123.123"; //充电设备充电电量(kWh),精度:0.001
|
||||
jsondata["charge_num"] = "1"; //充电设备充电次数
|
||||
jsondata["charge_num_err"] = "1"; //充电设备故障次数
|
||||
jsondata["income_elect"] = "123.123"; //发电收益(元),精度:0.01
|
||||
jsondata["income_charge"] = "123.123"; //充电收益(元),精度:0.01
|
||||
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
Errcode HttpEntity::queryStatStation(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
std::string station_id = req.get_param_value("station_id");
|
||||
std::string category = req.get_param_value("category");
|
||||
NJsonNode jsondata;
|
||||
jsondata["station_id"] = "1";
|
||||
jsondata["launch_date"] = "2025-01-01"; //场站上线日期
|
||||
jsondata["usage_rate"] = "12";
|
||||
jsondata["storage_elect_in"] = "123.123"; //储能充电电量(kWh),精度:0.001
|
||||
jsondata["storage_elect_out"] = "123.123"; //储能放电电量(kWh),精度:0.001
|
||||
jsondata["storage_num_in"] = "1"; //储能设备充电次数
|
||||
jsondata["storage_num_out"] = "1"; //储能设备放电次数
|
||||
jsondata["storage_num_err"] = "1"; //储能设备故障次数
|
||||
jsondata["solar_elect_gen"] = "123.123"; //光伏发电电量(kWh),精度:0.001
|
||||
jsondata["solar_elect_grid"] = "123.123"; //光伏入网电量(kWh),精度:0.001
|
||||
jsondata["solar_num_err"] = "1"; //光伏设备故障次数
|
||||
jsondata["charge_elect"] = "123.123"; //充电设备充电电量(kWh),精度:0.001
|
||||
jsondata["charge_num"] = "1"; //充电设备充电次数
|
||||
jsondata["charge_num_err"] = "1"; //充电设备故障次数
|
||||
jsondata["income_elect"] = "123.123"; //发电收益(元),精度:0.01
|
||||
jsondata["income_charge"] = "123.123"; //充电收益(元),精度:0.01
|
||||
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
|
||||
@@ -554,12 +731,124 @@ Errcode HttpEntity::queryStatDayList(const httplib::Request& req, httplib::Respo
|
||||
{
|
||||
std::string station_id = req.get_param_value("station_id");
|
||||
std::string category = req.get_param_value("category");
|
||||
std::string dt_start = req.get_param_value("dt_start");
|
||||
std::string dt_end = req.get_param_value("dt_end");
|
||||
std::string dt_start = req.get_param_value("start_date");
|
||||
std::string dt_end = req.get_param_value("end_date");
|
||||
|
||||
if (!dt_start.empty() && dt_end.empty())
|
||||
int64_t t1 = Utils::time(dt_start)/1000;
|
||||
int64_t t2 = Utils::time(dt_end)/1000;
|
||||
|
||||
int64_t tMax = t1+ 86400 * 30;
|
||||
NJsonNode jsondata = NJsonNode::array();
|
||||
for (int64_t t = t1; t<=t2 && t<=tMax; t += 86400)
|
||||
{
|
||||
NJsonNode jnode;
|
||||
jnode["station_id"] = station_id;
|
||||
if (!category.empty()) jnode["category"] = category;
|
||||
jnode["dt"] = Utils::dateStr(t*1000); //日期
|
||||
jnode["storage_elect_in"] = std::to_string(Utils::random(100, 200)); //储能充电电量(kWh),精度:0.001
|
||||
jnode["storage_elect_out"] = std::to_string(Utils::random(100, 200)); //储能放电电量(kWh),精度:0.001
|
||||
jnode["storage_num_in"] = std::to_string(Utils::random(1,5)); //储能设备充电次数
|
||||
jnode["storage_num_out"] = std::to_string(Utils::random(1, 5)); //储能设备放电次数
|
||||
jnode["storage_num_err"] = std::to_string(Utils::random(1, 5)); //储能设备故障次数
|
||||
jnode["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); //光伏发电电量(kWh),精度:0.001
|
||||
jnode["solar_elect_grid "] = std::to_string(Utils::random(100, 200)); //光伏入网电量(kWh),精度:0.001
|
||||
jnode["solar_num_err"] = std::to_string(Utils::random(1, 5)); //光伏设备故障次数
|
||||
jnode["charge_elect"] = std::to_string(Utils::random(100, 200)); //充电设备充电电量(kWh),精度:0.001
|
||||
jnode["charge_num"] = std::to_string(Utils::random(1, 5)); //充电设备充电次数
|
||||
jnode["charge_num_err"] = std::to_string(Utils::random(1, 5)); //充电设备故障次数
|
||||
jnode["income_elect"] = std::to_string(Utils::random(100, 200)); //发电收益(元),精度:0.01
|
||||
jnode["income_charge"] = std::to_string(Utils::random(100, 200)); //充电收益(元),精度:0.01
|
||||
jnode["usage_rate"] = std::to_string(Utils::random(10, 50)); //利用率
|
||||
jsondata.push_back(jnode);
|
||||
}
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
|
||||
Errcode HttpEntity::queryEnvironment(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||
{
|
||||
std::string stationId = req.get_param_value("station_id");
|
||||
auto& appdata = Application::data();
|
||||
|
||||
auto station = appdata.getStation(Utils::toInt(stationId));
|
||||
if (!station)
|
||||
{
|
||||
spdlog::error("[http] request queryEnvironment failed, get station info error, station_id={}", stationId);
|
||||
return Errcode::ERR_PARAM;
|
||||
}
|
||||
|
||||
NJsonNode jsondata;
|
||||
|
||||
{ // 温湿度
|
||||
auto& mapTempHumUnit = station->mapTempHumUnit;
|
||||
NJsonNode nodearray = NJsonNode::array();
|
||||
for (auto iter = mapTempHumUnit.begin(); iter!=mapTempHumUnit.end(); iter++)
|
||||
{
|
||||
auto& unit = iter->second;
|
||||
NJsonNode node;
|
||||
node["pos"] = "#" + std::to_string(iter->first);
|
||||
node["temp"] = unit.temp;
|
||||
node["hum"] = unit.hum;
|
||||
nodearray.push_back(node);
|
||||
}
|
||||
jsondata["temp_hum"] = nodearray;
|
||||
}
|
||||
{ //空调
|
||||
auto& mapAircUnit = station->mapAircUnit;
|
||||
AircUnit unitTmp;
|
||||
AircUnit* unit = (mapAircUnit.size() > 0) ? &(mapAircUnit[0]) : &unitTmp;
|
||||
NJsonNode nodearray = NJsonNode::array();
|
||||
if (unit)
|
||||
{
|
||||
NJsonNode node;
|
||||
nodearray.push_back({{"pos", "开关"}, {"status", unit->powerOn == 0 ? "关机" : "开机"}});
|
||||
nodearray.push_back({{"pos", "启动制冷指令"}, {"status", unit->cooling == 0 ? "启动" : "关闭"}});
|
||||
nodearray.push_back({{"pos", "启动送风指令"}, {"status", unit->airSupply == 0 ? "关闭" : "启动"}});
|
||||
nodearray.push_back({{"pos", "启动待机指令"}, {"status", unit->standby == 0 ? "关闭" : "启动"}});
|
||||
nodearray.push_back({{"pos", "启动加热指令"}, {"status", unit->heating == 0 ? "关闭" : "启动"}});
|
||||
nodearray.push_back({{"pos", "传感器故障"}, {"status", unit->sensorAlarm == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "高低电压告警"}, {"status", unit->voltageAlarm == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "高低温告警"}, {"status", unit->tempAlarm == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "高低压告警"}, {"status", unit->pressureAlarm == 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->hum) + "%"}});
|
||||
}
|
||||
jsondata["airc"] = nodearray;
|
||||
}
|
||||
{ // 消防
|
||||
static std::map<int, std::string> mapFireStatusDef = { {0, "正常"}, {1,"预警"}, {2,"火警"} };
|
||||
|
||||
auto& mapFire40Unit = station->mapFire40Unit;
|
||||
NJsonNode nodearray = NJsonNode::array();
|
||||
for (auto iter = mapFire40Unit.begin(); iter!=mapFire40Unit.end(); ++iter)
|
||||
{
|
||||
NJsonNode node;
|
||||
node["pos"] = "#" + std::to_string(iter->first);
|
||||
node["status"] = mapFireStatusDef[iter->second]; // 0:正常 1:预警 2:火警
|
||||
nodearray.push_back(node);
|
||||
}
|
||||
jsondata["fire40"] = nodearray;
|
||||
}
|
||||
{ // 冷机
|
||||
auto& mapCoolingUnit = station->mapCoolingUnit;
|
||||
CoolingUnit unitTmp;
|
||||
CoolingUnit* unit = (mapCoolingUnit.size() > 0) ? &(mapCoolingUnit[0]) : &unitTmp;
|
||||
NJsonNode nodearray = NJsonNode::array();
|
||||
if (unit)
|
||||
{
|
||||
NJsonNode node;
|
||||
nodearray.push_back({{"pos", "开关"}, {"status", unit->powerOn == 0 ? "关机" : "开机"}});
|
||||
nodearray.push_back({{"pos", "采样模式"}, {"status", unit->mode == 0 ? "出水温度" : "电芯温度"}});
|
||||
nodearray.push_back({{"pos", "制冷状态"}, {"status", unit->cooling == 0 ? "关闭" : "启动"}});
|
||||
nodearray.push_back({{"pos", "制热状态"}, {"status", unit->heating == 0 ? "关闭" : "启动"}});
|
||||
nodearray.push_back({{"pos", "高温告警"}, {"status", unit->highTemp == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "低温告警"}, {"status", unit->lowTemp == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "高压告警"}, {"status", unit->highPressure == 0 ? "正常" : "告警"}});
|
||||
nodearray.push_back({{"pos", "低压告警"}, {"status", unit->lowPressure == 0 ? "正常" : "告警"}});
|
||||
}
|
||||
jsondata["cooling"] = nodearray;
|
||||
}
|
||||
json["data"] = jsondata;
|
||||
return Errcode::OK;
|
||||
}
|
||||
@@ -35,6 +35,9 @@ public:
|
||||
Errcode updateStation(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode deleteStation(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
|
||||
Errcode queryStationInfo(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode queryStationData(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
|
||||
Errcode queryDeviceList(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode insertDevice(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode updateDevice(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
@@ -58,5 +61,8 @@ public:
|
||||
|
||||
Errcode queryStatSystem(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode queryStatTotal(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode queryStatStation(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
Errcode queryStatDayList(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
|
||||
Errcode queryEnvironment(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||
};
|
||||
@@ -4,17 +4,31 @@
|
||||
|
||||
#define TIMEOUT 10000L
|
||||
|
||||
int MqttClient::init(string addr, string client_id, string username, string password, std::vector<std::string> vecTopic)
|
||||
int MqttClient::init(string addr, string clientId, string username, string password)
|
||||
{
|
||||
this->addr = addr;
|
||||
this->vecTopic = vecTopic;
|
||||
this->clientId = clientId;
|
||||
this->vecTopic = {
|
||||
"up/json/" + clientId + "/EMS_YX",
|
||||
"up/json/" + clientId + "/EMS_YC",
|
||||
"up/json/" + clientId + "/EMS_YT",
|
||||
"up/json/" + clientId + "/PCU_YX",
|
||||
"up/json/" + clientId + "/PCU_YC",
|
||||
"up/json/" + clientId + "/PCS_YX",
|
||||
"up/json/" + clientId + "/PCS_YC",
|
||||
"up/json/" + clientId + "/BCU_YX",
|
||||
"up/json/" + clientId + "/BCU_YC",
|
||||
"up/json/" + clientId + "/BMS_YX",
|
||||
"up/json/" + clientId + "/BMS_YC",
|
||||
"up/json/" + clientId + "/MEM_YC",
|
||||
};
|
||||
|
||||
MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer;
|
||||
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||
int rc {0};
|
||||
|
||||
// "tcp://localhost:1883"
|
||||
rc = MQTTAsync_create(&client, addr.c_str(), client_id.c_str(), MQTTCLIENT_PERSISTENCE_NONE, NULL);
|
||||
rc = MQTTAsync_create(&client, addr.c_str(), clientId.c_str(), MQTTCLIENT_PERSISTENCE_NONE, NULL);
|
||||
if (rc != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
spdlog::error("[mqtt] MQTTAsync_create error: {}", rc);
|
||||
@@ -42,6 +56,7 @@ int MqttClient::init(string addr, string client_id, string username, string pass
|
||||
if (rc != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
spdlog::error("[mqtt] MQTTAsync_setCallbacks error");
|
||||
this->destory();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -70,55 +85,43 @@ int MqttClient::init(string addr, string client_id, string username, string pass
|
||||
//MQTTAsync_destroy(&client);
|
||||
}
|
||||
|
||||
void MqttClient::destory()
|
||||
{
|
||||
if (client)
|
||||
{
|
||||
MQTTAsync_destroy(&client);
|
||||
client = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscribInfo
|
||||
{
|
||||
std::function<void(int id)> callback;
|
||||
};
|
||||
|
||||
void MqttClient::subscribe(std::vector<std::string> vecTopics, std::function<void(int)> callback)
|
||||
void MqttClient::subscribe()
|
||||
{
|
||||
SubscribInfo* info = new SubscribInfo();
|
||||
info->callback = callback;
|
||||
MQTTAsync_onSuccess* funcSuccess = [](void* context, MQTTAsync_successData* response)
|
||||
{
|
||||
spdlog::info("[mqtt] subscribe {} success.", (char*)context);
|
||||
};
|
||||
MQTTAsync_onFailure* funcFailure = [](void* context, MQTTAsync_failureData* response)
|
||||
{
|
||||
spdlog::error("[mqtt] subscribe {} failed.", (char*)context);
|
||||
};
|
||||
|
||||
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
|
||||
options.context = info;
|
||||
options.onSuccess = [](void* context, MQTTAsync_successData* response)
|
||||
{
|
||||
spdlog::info("[mqtt] subscribe success.");
|
||||
SubscribInfo* info = (SubscribInfo*)context;
|
||||
info->callback(0);
|
||||
delete info;
|
||||
|
||||
};
|
||||
options.onFailure = [](void* context, MQTTAsync_failureData* response)
|
||||
{
|
||||
spdlog::error("[mqtt] subscribe failed.");
|
||||
SubscribInfo* info = (SubscribInfo*)context;
|
||||
info->callback(-1);
|
||||
delete info;
|
||||
};
|
||||
|
||||
|
||||
int count = 3;
|
||||
char* topicsTmp[] = {
|
||||
"topic/aa",
|
||||
"topic/bb",
|
||||
"topic/cc"
|
||||
};
|
||||
std::vector<int> qosTmp(count, 1); // 为每个主题指定 QoS
|
||||
|
||||
if (count > 0)
|
||||
options.onSuccess = funcSuccess;
|
||||
options.onFailure = funcFailure;
|
||||
for (auto& topic: vecTopic)
|
||||
{
|
||||
int rc = MQTTAsync_subscribeMany(client, count, topicsTmp, qosTmp.data(), &options);
|
||||
options.context = topic.data();
|
||||
int rc = MQTTAsync_subscribe(client, topic.data(), qos, &options);
|
||||
if (rc != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
spdlog::error("[mqtt] subscribe failed, err={}", rc);
|
||||
spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete info;
|
||||
}
|
||||
}
|
||||
|
||||
int MqttClient::publish(string topic, string text)
|
||||
@@ -151,18 +154,45 @@ int MqttClient::publish(string topic, string text)
|
||||
void MqttClient::onConnectionLost(char* cause)
|
||||
{
|
||||
this->isConnected = false;
|
||||
this->destory();
|
||||
spdlog::error("MQTT connection lost, cause={}", cause);
|
||||
}
|
||||
|
||||
std::string GetSubStr(std::string c, std::string& str)
|
||||
{
|
||||
std::string v;
|
||||
int pos = str.find_first_of("/");
|
||||
if (pos != string::npos)
|
||||
{
|
||||
v = str.substr(0, pos);
|
||||
str = str.substr(pos);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* msg)
|
||||
{
|
||||
std::string topicStr = topic;
|
||||
int len = msg->payloadlen;
|
||||
char* payload = (char*)msg->payload;
|
||||
std::string payload = (char*)msg->payload;
|
||||
spdlog::info("MQTT message arrived: topic=[{},{}], payload len={}, payload msg={}", topic, msg->qos, len, payload);
|
||||
|
||||
// <数据方向>/<数据格式>/<厂家ID>/<指合>/<设备标识,上行可选>
|
||||
std::string direction = GetSubStr("/", topicStr);
|
||||
std::string datatype = GetSubStr("/", topicStr);
|
||||
std::string stationId = GetSubStr("/", topicStr);
|
||||
std::string command = GetSubStr("/", topicStr);
|
||||
std::string deviceCode = GetSubStr("/", topicStr);
|
||||
|
||||
if (command == "EMS_YX") {}
|
||||
else if (command == "EMS_YC") {}
|
||||
else if (command == "PCU_YX") { this->parsePCU_YX(payload); }
|
||||
else if (command == "PCU_YC") {}
|
||||
|
||||
// 必须释放消息内存!
|
||||
MQTTAsync_freeMessage(&msg);
|
||||
MQTTAsync_free(topic);
|
||||
|
||||
return 1; // 1表示消息已经处理
|
||||
}
|
||||
|
||||
@@ -175,8 +205,9 @@ void MqttClient::onDeliveryComplete(MQTTAsync_token token)
|
||||
|
||||
void MqttClient::onConnectSuccess( MQTTAsync_successData* resp)
|
||||
{
|
||||
spdlog::info("[mqtt] connect to {} success.", addr);
|
||||
this->isConnected = true;
|
||||
//spdlog::info("[mqtt] connect success: {}", addr);
|
||||
this->subscribe();
|
||||
//MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
|
||||
//options.context = this;
|
||||
//options.onSuccess = [](void* context, MQTTAsync_successData* response)
|
||||
@@ -203,63 +234,23 @@ void MqttClient::onConnectSuccess( MQTTAsync_successData* resp)
|
||||
}
|
||||
void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp)
|
||||
{
|
||||
spdlog::error("[mqtt] connect to {} error.", addr);
|
||||
this->isConnected = false;
|
||||
this->destory();
|
||||
}
|
||||
|
||||
string MQTT::packEquipmentInfo(mqtt::EquipmentInfo& info)
|
||||
|
||||
void MqttClient::parseEMS_YC(std::string& text)
|
||||
{
|
||||
|
||||
}
|
||||
void MqttClient::parsePCU_YX(std::string& text)
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
jsonroot["EquipmentID"] = info.EquipmentID.c_str();
|
||||
jsonroot["ManufacturerID"] = info.ManufacturerID.c_str();
|
||||
jsonroot["EquipmentModel"] = info.EquipmentModel.c_str();
|
||||
jsonroot["ProductionDate"] = info.ProductionDate.c_str();
|
||||
jsonroot["OpenForBusinessDate"] = info.OpenForBusinessDate.c_str();
|
||||
jsonroot["EquipmentType"] = info.EquipmentType;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
|
||||
string MQTT::packSwapEquipmentStatusInfo(string node_id)
|
||||
string MQTT::packEquipmentInfo()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
|
||||
string MQTT::packNotifyStationInfo()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
|
||||
string MQTT::packNotifyAlarm()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
string MQTT::packNotifyChargeStatus()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
string MQTT::packNotifySwapStatus()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
string MQTT::packNotifyChargeOrder()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
|
||||
|
||||
string MQTT::packNotifySwapOrder()
|
||||
{
|
||||
NJsonNode jsonroot;
|
||||
return jsonroot.dump();
|
||||
}
|
||||
@@ -10,10 +10,10 @@ using namespace std;
|
||||
class MqttClient
|
||||
{
|
||||
public:
|
||||
int init(string addr, string client_id, string username, string password, std::vector<std::string> vecTopic);
|
||||
|
||||
void subscribe(std::vector<std::string> topics, std::function<void(int)> callback);
|
||||
int init(string addr, string clientId, string username, string password);
|
||||
void destory();
|
||||
|
||||
void subscribe();
|
||||
int publish(string topic, string text);
|
||||
|
||||
void onConnectionLost(char* cause);
|
||||
@@ -23,13 +23,15 @@ public:
|
||||
void onConnectSuccess(MQTTAsync_successData* resp);
|
||||
void onConnectFaiure(MQTTAsync_failureData* resp);
|
||||
|
||||
void parseEMS_YC(std::string& text);
|
||||
void parsePCU_YX(std::string& text);
|
||||
|
||||
public:
|
||||
std::string clientId;
|
||||
MQTTAsync client = nullptr;
|
||||
std::vector<std::string> vecTopic;
|
||||
std::string addr; // "tcp://localhost:1883"
|
||||
int qos {1};
|
||||
std::string clientId;
|
||||
bool isConnected {false};
|
||||
bool isSubscribed {false};
|
||||
};
|
||||
@@ -52,317 +54,11 @@ public:
|
||||
#define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC"
|
||||
|
||||
|
||||
#define MQTT_TOPIC_NOTIFY_STATION "notification_stationInfo" // 充(换)电站信息变化推送
|
||||
#define MQTT_TOPIC_QUERY_STATION "query_stations_info" // 查询充(换)电站信息
|
||||
#define MQTT_TOPIC_NOTIFY_ALARM "notification_alarmInfo" // 告警信息推送
|
||||
#define MQTT_TOPIC_NOTIFY_CHARGE_STATUS "notification_connectorStatus" //充电设备状态变化推送
|
||||
#define MQTT_TOPIC_NOTIFY_SWAP_STATUS "notification_swapStatus" //换电设备状态变化推送
|
||||
#define MQTT_TOPIC_QUERY_STATUS "query_station_status" //查询站内设备接口状态
|
||||
#define MQTT_TOPIC_NOTIFY_CHARGE_ORDER "notification_orderInfo" //充电电量信息推送
|
||||
#define MQTT_TOPIC_QUERY_ORDER "query_order_info" //查询充电电量信息
|
||||
#define MQTT_TOPIC_NOTIFY_SWAP_ORDER "notification_swapInfo" //换电记录信息推送
|
||||
#define MQTT_TOPIC_QUERY_SWAP_ORDER "query_swap_info" //查询换电电量信息
|
||||
|
||||
namespace mqtt
|
||||
{
|
||||
// 充(换)电运营商信息
|
||||
struct OperatorInfo
|
||||
{
|
||||
string OperatorID; // 运营商ID 组织机构代码 是 字符串 9 字符
|
||||
string OperatorName; // 运营商名称 机构全称 是 字符串 <= 64 字符
|
||||
string OperatorTel1; // 运营商电话1 运营商客服电话 1 是 字符串 <= 32 字符
|
||||
string OperatorTel2; // 运营商电话2 运营商客服电话 2 否 字符串 <= 32 字符
|
||||
string OperatorRegAddress; // 运营商注册地址 运营商注册地址 否 字符串 <= 64 字符
|
||||
string OperatorNote; // 备注 备注信息 否 字符串 <= 255 字符
|
||||
};
|
||||
|
||||
// 充(换)电站信息
|
||||
struct StationInfo
|
||||
{
|
||||
string StationID; // 充(换)电站 ID 运营商自定义的唯一编码 是 字符串 <= 20 字 符
|
||||
string OperatorID; // 运营商 ID 电动汽车充(换)电服务平台的运营商 ID 是 字符串 9 字符
|
||||
string EquipmentOwnerID; // 设备所属方 ID 设备所属方组织机构代码,所属方为个人时可不填 否 字符串 9 字符
|
||||
|
||||
string StationName; // 充(换)电站名称 充(换)电站名称的描述 是 字符串 <= 50 字
|
||||
|
||||
string CountryCode; // 充(换)电站国家代码 比如 CN 是 字符串 2 字符
|
||||
string AreaCode; // 充(换)电站省市辖区编码 填写内容为参照 GB / T2260,以民政部发布最新数据为准 是 字符串 <= 20 字符
|
||||
string Address; // 详细地址 是 字符串<= 100字符
|
||||
string StationTel; // 站点电话 能够联系场站工作人员进行协助的联系电话 否 字符串<= 30 字符
|
||||
string ServiceTel; // 服务电话 平台服务电话,例如 400 电话 是 字符串<= 30字符
|
||||
string ServiceType; // *服务类型 1:充电 2:换电 3:充换电 255:其他 是 整型
|
||||
string StationType; // 站点类型 1:公共充(换)电站 2:专用充(换)电站 3:居民充电站 255:其他 是 整型
|
||||
string StationStatus; // 站点状态 0:未知 1:建设中 5:关闭下线 6:维护中 50:正常使用 是 整型
|
||||
string ParkNums; // 车位数量 可停放进行充电的车位总数, 默认:0 未知 是 整型
|
||||
float StationLng; // 经度 GCJ - 02 坐标系 是 浮点型 保留小数点后6 位
|
||||
float StationLat; // 纬度 GCJ - 02 坐标系 是 浮点型保留小数点后6 位
|
||||
string SiteGuide; // 站点引导描述性文字,用于引导车主找到充电车位 否 字符串<= 255字符
|
||||
|
||||
|
||||
int Construction; // 建设场所
|
||||
//101:公共服务场所
|
||||
//102:公共停车场
|
||||
//103:城市交通节点
|
||||
//104:加油站
|
||||
//105:具备停车条件的充电区域
|
||||
//106:高速服务区
|
||||
//201:政府机关
|
||||
//202:公共机构
|
||||
//203:企业事业单位
|
||||
//204:公交
|
||||
//205:环卫
|
||||
//206:物流
|
||||
//207:出租车
|
||||
//208:港口码头
|
||||
//209:重卡换电场所
|
||||
//210:矿卡换电场所
|
||||
//301:居民(小)区
|
||||
//255:其他
|
||||
// 是 整型
|
||||
string Pictures; // 站点照片 充(换)电设备照片、充(换)电车位照片、停车场入口照片 是 字符串数组 无照片时可传空数组
|
||||
string MatchCars; // 服务车型描述 描述该站点可充(换)电服务 的车辆类型:如大巴、物流车、私家乘用车、出租车、重卡型卡车等 否 字符串<= 255字符
|
||||
string ParkInfo; // 车位楼层及数量描述车位楼层以及数量信息 否 字符串<= 100字符
|
||||
int OpenAllDay; // *全天开放 0:否 1:是 是 整型
|
||||
string OpenForBusinessDate; // *投运日期 站点投运日期 yyyy - MM - dd 格式 是 字符串
|
||||
string BusineHours; // 营业时间 营业时间描述 否 字符串<=255字符
|
||||
|
||||
string ElectricityFee; // *电费费率 示例 [{"StartTime":"000000","Price":"1.0000"},{"StartTime":"120000","Price":"1.2000"}] 否 字符串 <= 2000 字符
|
||||
string ServiceFee; // *服务费率 示例[{"StartTime":"000000","Price":"1.0000"},{"StartTime":"120000","Price":"1.2000"}] 否 字符串 <= 2000 字符
|
||||
|
||||
|
||||
string ParkOwner; // *停车场产权方 停车场产权人 否 字符串
|
||||
string ParkManager; // *停车场管理方 停车场管理人(如:XX 物业) 否 字符串
|
||||
int ParkType; // 停车费类型 0:免费 1:不免费 2:限时免费停车 3:充电限时减免 255:参考场地实际收费标准 否 整型
|
||||
string ParkFee; // 停车费描述 停车费率描述 否 字符串 <= 255字符
|
||||
string Payment; // 支付方式 支付方式: 刷卡、线上、现金其中电子钱包类卡为刷卡,身份鉴权卡、微信 / 支付宝等在线支付、APP 支付为线上否 字符串<= 20 字符
|
||||
int SupportOrder; // 是否支持预约 0:不支持预约 1:支持预约。不填默认为 0 否 整型
|
||||
string Remark; // 备注 其他备注信息 否 字符串<= 100字符
|
||||
string EquipmentInfos; // 充电设备信息列表 该充(换)电站所有充电设备 信息对象数组 是 EquipmentInfos[],参照 4.4
|
||||
string SwapEquipmentInfos; // *换电设备信息列表 该充(换)电站所有换电设备。换电站以及充换电站提供此数据,充电站默认空数组。 是 SwapEquipmentInfo[],参照 4.6 换电工位信息
|
||||
int BatteryNo; // *备用电池数量换电站内可提供更换最大电池数量。换电站以及充换电站提供此数据,充电站默认填0。 是 整型
|
||||
};
|
||||
|
||||
// 充电设备信息
|
||||
struct EquipmentInfo
|
||||
{
|
||||
string EquipmentID;
|
||||
string ManufacturerID;
|
||||
string EquipmentModel;
|
||||
string ProductionDate;
|
||||
string OpenForBusinessDate;
|
||||
int EquipmentType;
|
||||
int EquipmentStatus;
|
||||
vector<int> ConnectorInfos;
|
||||
float EquipmentLng;
|
||||
float EquipmentLat;
|
||||
float Power;
|
||||
string EquipmentName;
|
||||
};
|
||||
|
||||
// 充电设备接口信息
|
||||
struct ConnectorInfo
|
||||
{
|
||||
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一运营商内唯一 是 字符串 <= 64 字符
|
||||
string ConnectorName; // 充电设备接口名称 否 字符串 <= 30 字符
|
||||
int ConnectorType; // 充电设备接口类型
|
||||
//1:家用插座(模式 2)
|
||||
//2:交流接口插座(模式 3,连接方式 B )
|
||||
//3:交流接口插头(带枪线,模式 3,连接方式 C)
|
||||
//4:直流接口枪头(带枪线,模式 4)
|
||||
//5:无线充电座
|
||||
//6:其他
|
||||
//7:对换电站电池箱的接口
|
||||
//是 整型
|
||||
int VoltageUpperLimits; // 额定电压上限 单位:V 是 整型
|
||||
int VoltageLowerLimits; // 额定电压下限 单位:V 交流可与额定电压上限相同 是 整型
|
||||
int ConstantVoltageUpperLimits; // *恒功率电压上限 单位:V 否 整型
|
||||
int ConstantVoltageLowerLimits; // *恒功率电压下限 单位:V 否 整型
|
||||
int Current; // 额定电流 单位:A 是 整型
|
||||
float Power; // 额定功率 单位:kW 是 浮点型 保留小数点后一位
|
||||
string ParkNo; // 车位号 停车场车位编号,或充电架编号 否 字符串 <= 10 字符
|
||||
int NationalStandard; // 国家标准 1:2011 2 : 2015 3 : 兼容 2011 和 2015 是 整型
|
||||
};
|
||||
|
||||
// 换电设备信息(SwapEquipmentInfo)
|
||||
class SwapEquipmentInfo
|
||||
{
|
||||
string EquipmentID; // 设备编码 换电设备唯一编码,同一运营商下唯一 是 字符串 <= 64 字符
|
||||
string ManufacturerID; // 设备生产商组织机构代码 设备生产商组织机构代码 否 字符串 9 字符
|
||||
string EquipmentModel; // 设备型号 由设备生厂商定义的设备型号 否 字符串 <= 20 字符
|
||||
string ProductionDate; // 设备生产日期 YYYY - MM - DD 否 字符串 10 字符
|
||||
string OpenForBusinessDate; // *投运日期 充电桩投运日期 yyyy - MM - dd 格式 是 字符串
|
||||
string OpreateStatus; // 运营状态 0:未知 1:建设中 5:关闭下线 6:维护中 50:正常使用 是 整型
|
||||
int EquipmentType; // 换电设备类型 填写内容为参照GB29317 - 2021 4.3节中的描述 1:侧向换电 2:底部换电 3:顶部换电 4:端部换电 5:中置换电 255:其他 是 整型
|
||||
string MatchCars; // 服务车型描述 描述该设备可服务的车辆类型以及 型号等 否 字符串<= 1000 字符
|
||||
string SupplyBattery; // 提供电池描述 描述该设备提供的电池类型以及型号等 否 字符串<= 100 字符
|
||||
};
|
||||
|
||||
//电池箱信息
|
||||
struct BatteryInfo
|
||||
{
|
||||
string BatteryNo; // 电池箱编号 运营商自定义唯一编码 是 字符串 <= 32 字
|
||||
string BatteryOwnerID; // 电池所属方ID 设备所属方组织机构代码,所属方为个人时可不填 否 字符串 9 字符
|
||||
string ManufacturerID; // 设备生产商组织机构代码 设备生产商组织机构代码 否 字符串 9 字符
|
||||
string BatteryModel; // 电池型号 由设备生厂商定义的设备型号 否 字符串 <= 20 字符
|
||||
string ProductionDate; // 设备生产日期 YYYY - MM - DD 否 字符串 10 字符
|
||||
string OpenForBusinessDate; // 投运日期 电池投运日期 yyyy - MM - dd 格式 是 字符串
|
||||
int CellNum; // 电池箱所含单体电池个数 电池箱所含单体个数 是 整型
|
||||
int SeriesNum; // 单体电池串联总数 串联总数 否 整型
|
||||
int ParallelNum; // 单体电池并联总数 并联总数 否 整型
|
||||
int BatteryType; // 电池类型
|
||||
//1:磷酸铁锂电池
|
||||
//2:锰酸锂电池
|
||||
//3:钴酸锂电池
|
||||
//4:三元材料电池
|
||||
//5:聚合物锂离子电池
|
||||
//6:钛酸锂电池
|
||||
//7:燃料电池
|
||||
//255:其它
|
||||
//是 整型
|
||||
float RatedCapacity; // 电池箱额定容量 单位:Ah,小数点后 1 位 是 浮点型
|
||||
float RatedVoltage; // 电池箱额定电压 单位:V,小数点后 1 位 是 浮点型
|
||||
};
|
||||
|
||||
// 充电设备接口状态
|
||||
struct ConnectorStatusInfo
|
||||
{
|
||||
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一运营商内唯一 是 字符串<= 64 字符
|
||||
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy -MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||
int Status; // 接口状态 0:离线 1:空闲 2:占用(未充电) 3:占用(充电中) 4:占用(预约锁定) 255:故障 是 整型
|
||||
int ParkStatus; // 车位状态 0:未知 10:空闲 50:占用 否 整型
|
||||
int LockStatus; // 地锁状态 0:未知 10:已解锁 50:已上锁 否 整型
|
||||
int CurrentA; // A 相电流 单位:A,默认:0 含直流(输出) 是 整型
|
||||
int CurrentB; // B 相电流 单位:A,默认:0 否 整型
|
||||
int CurrentC; // C 相电流 单位:A,默认:0 否 整型
|
||||
int VoltageA; // A 相电压 单位:V,默认:0 含直流(输出) 是 整型
|
||||
int VoltageB; // B 相电压 单位:V,默认:0 否 整型
|
||||
int VoltageC; // C 相电压 单位:V,默认:0 否 整型
|
||||
float SOC; // *剩余电量 默认:0 交流充电桩采集不到SOC 值的填 0 是 浮点型
|
||||
string Begin_time; // *开始充电时间 格式 为 yyyy-MM-dd HH:mm:ss 是 字符串
|
||||
float Current_kwh; // *本次已充电量 单位:kWh 是 浮点型
|
||||
float Current_meter; // *当前电表读数 单位:kWh 否 浮点型
|
||||
string Vin; // *车架号 否 字符串 <= 20 字符
|
||||
//BatteryStatusInfo //*电池状态信息 充电设备有电池情况下需上报 是 BatteryStatusInfo,参照4.9
|
||||
};
|
||||
|
||||
// 电池箱状态
|
||||
struct BatteryStatusInfo
|
||||
{
|
||||
string BatteryNo; // 电池箱编号 (充电设备有电池情况下需上报) 是 字符串<= 32 字符
|
||||
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy -MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||
float Voltage; // 当前电压 单位:V,小数点后 2 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||
float Current; // 当前电流 单位:V,小数点后 2 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||
float SOC; // 当前 Soc 当前电池电量百分比,范围:0~100,小数点后 1 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||
float SOH; // 当前 Soh 当前电池健康度,范围:0~100,小数点后 1 位(充电设备有电池情况下需上报)是 浮点型
|
||||
int BatteryIsFault; // 电池箱是否故障 0:未知 1:是 2:否 (充电设备有电池情况下需上报) 是 整型
|
||||
int MaxVoltageBatteryNo; // 最高电压单体电池编号 充电设备有电池情况下需上报 否 整型
|
||||
float MaxVoltage; // 最高电压单体电池电压值单位: V,小数点后3位 充电设备有电池情况下需上报 否 浮点型
|
||||
int MinVoltageBatteryNo; // 最低电压单体电池编号 充电设备有电池情况下需上报 否 整型
|
||||
float MinVoltage; // 最低电压单体电池电压值 单位: V,小数点后 3 位 充电设备有电池情况下需上报 否 浮点型
|
||||
float MaxTempBatteryNo; // 最高温度测温点编号 充电设备有电池情况下需上报 否 整型
|
||||
int MaxTemp; // 最高温度测温点温度值 单位:℃ 充电设备有电池情况下需上报 否 整型
|
||||
int MinTempBatteryNo; // 最低温度测温点编号 充电设备有电池情况下需上报 否 整型
|
||||
int MinTemp; // 最低温度测温点温度值 单位:℃ 充电设备有电池情况下需上报 否 整型
|
||||
};
|
||||
|
||||
// 换电设备状态(SwapEquipmentStatusInfo)
|
||||
struct SwapEquipmentStatusInfo
|
||||
{
|
||||
string EquipmentID; // 换电设备编码 换电设备编码,同一运营商内唯一 是 字符串 <= 64 字符
|
||||
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy - MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||
int Status; // 换电设备状态 0:离线 1:空闲 2:工作 255:故障 是 整型
|
||||
int SwapMode; // 换电模式 0:手动模式 1:半自动模式 2:全自动模式 3:检修模式 否 整型
|
||||
};
|
||||
|
||||
// 充(换)电站状态(StationStatusInfo)
|
||||
struct StationStatusInfo
|
||||
{
|
||||
string StationID; // 充(换)电站 ID 运营商自定义的唯一编码 是 字符串 <= 20 字符
|
||||
string ConnectorStatusInfos; // 充电设备接口状态列表 充(换)电站下所有充电设备接口的状态对象数组 是 ConnectorStatusInfos[], 参照 5.6
|
||||
|
||||
string SwapEquipmentStatusInfo; // 换电设备状态列 所有充电设备接口的是 SwapEquipmentStatusInfo[]表 状态 ,参照4.10
|
||||
};
|
||||
|
||||
//充电电量信息(OrderInfo)
|
||||
struct OrderInfo
|
||||
{
|
||||
string OperatorID; // 运营商 ID 统一社会信用代码 是 字符串 9 字符
|
||||
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一充(换)电运营平台内唯一 是 字符串 <= 26 字符
|
||||
string StartChargeSeq; // 充电业务编号 运营商充电业务编号 是 字符串 <= 32 字符
|
||||
int UserChargeType; // 用户发起充电类型 1:充(换)电运营平台注册用户 2 : 监管平台注册用户 3 : 其他 否 整型
|
||||
string MobileNumber; // 用户手机号 若用户发起充电类型为APP,用户手机号必填否 字符串
|
||||
float Money; // 本次充电消费总金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||
float ElectMoney; // 本次充电电费总金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||
float ServiceMoney; // 本次充电服务费金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||
float Elect; // 本次充电电量 单位 kWh,精度0.001,如果不设置峰谷电价,平电量等于本次充电电量,其他分电量为零。 是 浮点型
|
||||
float CuspElect; // *尖阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||
float PeakElect; // *峰阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||
float FlatElect; // *平阶段电量 单位 kWh,精度0.001, 是 浮点型
|
||||
float ValleyElect; // *谷阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||
float StartTime; // 本次充电开始时间 格式“yyyy - MM - ddHH : mm:ss” 是 字符串
|
||||
float EndTime; // 本次充电结束时间 格式“yyyy - MM - ddHH : mm: ss” 是 字符串
|
||||
float PaymentAmount; // 支付金额 支付金额 若通过苏e充APP启动,此字段为必填项。 否 浮点型 保留小数点后 2 位
|
||||
float MeterValueStart; // *电表总起值 单位 kWh,精度0.001 是 浮点型 保留小数点后三位
|
||||
float MeterValueEnd; // *电表总止值 单位 kWh,精度0.001 是 浮点型 保留小数点后三位
|
||||
float Vin; // *本次充电车架号 充电设备有车辆VIN码需上报 否 字符串 <= 64 字符
|
||||
float BatteryNo; // *本次充电电池编号 充电设备有电池情况下需上报 否 字符串 <= 64 字符
|
||||
float ExchangeChargeSeq;// *换电记录编号 格式“运营商 ID + 唯一编号”,27 字符,如果有对应的换电记录需要填写是 字符串 <= 40 字符
|
||||
};
|
||||
|
||||
// 换电记录信息(SwapInfo)
|
||||
struct SwapInfo
|
||||
{
|
||||
string OperatorID; //运营商 ID 统一社会信用代码 是 字符串 9 字符
|
||||
string EquipmentID; // 换电设备编码 换电设备接口编码,同一充(换)电运营平台内唯一 是 字符串 <= 40 字符
|
||||
|
||||
string ExchangeChargeSeq; // 换电记录编号 格式“运营商 ID + 唯一编号”,27 字 符 是 字符串
|
||||
string SwapMode; // 换电模式 0:手动模式 1:半自动模式 2:全自动模式 3:检修模式 否 整型
|
||||
string CarNo; // 车牌号 否 字符串 <= 16 字符
|
||||
string Vin; // 车辆VIN码 车辆识别码;见GB - T - 27930 - 2015国标PGN512 BMS 和车辆辨识报文(BRM)约定 否 字符串
|
||||
string RepDownBatteryNo;// 换下电池箱编号 运营商自定义唯一 编码, 是 字符串 <= 32 字符
|
||||
string RepDownBatterySoc;// 换下电池箱SOC 电池电量百分比,范围:0~100, 是 整型
|
||||
string RepOnBatteryNo;//换上电池箱编号 运营商自定义唯一编码,是 字符串 <= 32 字符
|
||||
int RepOnBatterySoc; //换上电池箱SOC 电池电量百分比,范围:0~100 是 整型
|
||||
float TotalPower; //换上电池箱总充入电量 单位:度(kWh) 是 浮点型 保留小数点后两位
|
||||
string StartTime; //换电开始时间 格式“yyyy - MM - dd HH : mm:ss” 是 字符串
|
||||
string EndTime; //换电结束时间 格式“yyyy - MM - dd HH : mm: ss” 是 字符串
|
||||
};
|
||||
|
||||
// 充(换)电设备告警信息(AlarmInfo)
|
||||
struct AlarmInfo
|
||||
{
|
||||
string EquipmentID; // 设备编码 充电接口唯一编码,对同一运营商,保证唯一 是 字符串 23 字符
|
||||
int EquipmentType; //设备类型 1:充电设备 2:换电设备 整型
|
||||
string Alert_time; //告警时间 格 式 为 yyyy - MMdd HH : mm:ss 是 字符串
|
||||
int Alert_code; //告警代码 告警代码 是 整型
|
||||
string Describe; //描述 文字描述,最大长度 256字符。是 字符串 256 字符
|
||||
int Status; //状态 告警发生:0;告警 恢复: 1,默认为 0。是 整型
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class MQTT
|
||||
{
|
||||
public:
|
||||
static string packEquipmentInfo(mqtt::EquipmentInfo& info);
|
||||
|
||||
|
||||
static string packSwapEquipmentStatusInfo(string node_name);
|
||||
|
||||
// 充(换)电站信息变化推送
|
||||
static string packNotifyStationInfo();
|
||||
|
||||
// 告警信息推送
|
||||
static string packNotifyAlarm();
|
||||
|
||||
// 充电设备状态变化推送, 充电启停或者离线状态改变时推送,充电过程中每分钟一次推送
|
||||
static string packNotifyChargeStatus();
|
||||
|
||||
// 换电设备状态变化推送
|
||||
static string packNotifySwapStatus();
|
||||
|
||||
// 充电电量信息推送(chon), 充电结束后5分钟内推送
|
||||
static string packNotifyChargeOrder();
|
||||
|
||||
// 换电记录信息推送, 换电结束后5分钟内推送
|
||||
static string packNotifySwapOrder();
|
||||
public:
|
||||
static string packEquipmentInfo();
|
||||
};
|
||||
Reference in New Issue
Block a user