修改HTTP接口测试问题

This commit is contained in:
lixiaoyuan
2025-09-12 18:44:34 +08:00
parent 59b78d678d
commit 7f23138d9c
40 changed files with 1484 additions and 1165 deletions

View File

@@ -127,8 +127,7 @@ void AppData::initFromDB()
auto station = this->getStation(stationId);
if (station)
{
auto device = Device::create(fields);
station->addDevice(deviceId, device);
station->addDevice(fields);
}
else
{
@@ -248,7 +247,6 @@ void AppData::init()
for (auto& item : mapStation)
{
auto& station = item.second;
if (station->status == 1)
{
// "tcp://localhost:1883"
@@ -256,7 +254,6 @@ void AppData::init()
}
}
}
this->launchDate = Config::option.lunchDate;
}

View File

@@ -102,6 +102,17 @@ void Application::runThreadMain()
// }
//}
///////////////////////////////////////////////////////////////////////////////////////////
/// 召测
static TimeTick tt1;
if (tt1.elapse(10))
{
for (auto& item: appdata.mapStation)
{
auto& station = item.second;
station->polling();
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
@@ -131,6 +142,16 @@ void Application::runThreadStat()
{
//spdlog::info("保存历史数据倒计时: {}", 600 - offset);
}
for (auto& station : appdata.mapStation)
{
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}

View File

@@ -16,53 +16,45 @@ static bool CheckCacheType(int type)
std::shared_ptr<Device> Device::create(Fields& fields)
{
auto device = std::make_shared<Device>();
device->deviceId = fields.get<int>("device_id");
device->type = fields.get<int>("type");
device->name = fields.value("name");
device->code = fields.value("code");
device->isOpen = fields.get<int>("is_open");
device->attrsJson = fields.value("attrs");
device->category = fields.get<int>("category");
device->setFields(fields);
return device;
}
void Device::setFields(Fields& fields)
{
fields.get("device_id", this->deviceId);
fields.get("type", this->type);
fields.get("name", this->name);
fields.get("code", this->code);
fields.get("is_open", this->isOpen);
fields.get("attrs", this->attrsJson);
fields.get("category", this->category);
// 解析属性的JSON字符串转换成键值对
njson jsonroot;
bool ret = JSON::parse(device->attrsJson, jsonroot);
bool ret = JSON::parse(this->attrsJson, jsonroot);
if (!ret) // 解析错误
{
spdlog::error("[device] device attr json parse error, device_id={}", device->deviceId);
spdlog::error("[device] device attr json parse error, device_id={}", this->deviceId);
}
else
{
this->attrs.clear();
for (auto& [key, val] : jsonroot.items()) {
std::string valType = val.type_name();
if (valType == "string") {
device->attrs.set(key, val.get<std::string>());
this->attrs.set(key, val.get<std::string>());
}
else if (valType == "number") {
device->attrs.set(key, val.get<int>());
this->attrs.set(key, val.get<int>());
}
else {
spdlog::error("[device] device attr unknown type: key={}, valtype={}", key, valType);
}
}
}
//int step = 600;
//for (int i = 0; i*600<86400; ++i)
//{
// double voltage = double(Utils::random(20000, 30000))*0.01;
// double current = double(Utils::random(1000, 2000))*0.01;
// device->mapCacheVoltage[i*step] = voltage;
// device->mapCacheCurrent[i*step] = current;
// device->mapCachePower[i*step] = voltage * current;
//}
// 启动通讯该函数中会自动判断isOpen状态选择是否进行通讯连接
//device->startComm();
return device;
}
int Device::startComm()
{
if (!isOpen)

View File

@@ -16,6 +16,8 @@ class Device
public:
static std::shared_ptr<Device> create(Fields& fields);
void setFields(Fields& fields);
int startComm();
void getCacheVoltage(std::vector<std::string>& vec);

View File

@@ -35,7 +35,7 @@ void Station::setFields(Fields& fields)
{
this->stationId = fields.get<int>(DMStation::STATION_ID);
this->name = fields.value(DMStation::NAME);
this->energyCapacity = fields.get<double>(DMStation::CAPACITY);
this->capacity = fields.get<double>(DMStation::CAPACITY);
this->workModeId = fields.get<int>(DMStation::WORK_MODE);
this->code = fields.value(DMStation::CODE);
this->status = fields.get<int>(DMStation::STATUS);
@@ -47,6 +47,22 @@ void Station::addDevice(int deviceId, std::shared_ptr<Device> device)
mapDeviceGroup[device->category].push_back(device);
}
void Station::addDevice(Fields& fields)
{
int deviceId = fields.get<int>(DMDevice::DEVICE_ID);
int stationId = fields.get<int>(DMDevice::STATION_ID);
if (mapDevice.find(deviceId) != mapDevice.end())
{
mapDevice[deviceId]->setFields(fields);
}
else
{
auto device = Device::create(fields);
mapDevice[deviceId] = device;
mapDeviceGroup[device->category].push_back(device);
}
}
std::shared_ptr<Device> Station::getDevice(int deviceId)
{
auto iter = mapDevice.find(deviceId);
@@ -82,8 +98,13 @@ void Station::getDeviceByType(int deviceType, std::vector<std::shared_ptr<Device
}
}
int Station::getDeviceNumByGroup(int category)
int Station::getDeviceCount(int category)
{
auto iter = mapDeviceGroup.find(category);
if (iter != mapDeviceGroup.end())
{
return iter->second.size();
}
return 0;
}
@@ -159,3 +180,12 @@ void Station::writeRuntimeData(std::string dt, int npos)
}
}
}
void Station::polling()
{
if (mqttCli)
{
mqttCli->polling();
}
}

View File

@@ -95,11 +95,12 @@ public:
void setFields(Fields& fields);
void addDevice(int deviceId, std::shared_ptr<Device> device);
void addDevice(Fields& fields);
std::shared_ptr<Device> getDevice(int deviceId);
std::shared_ptr<Device> getDeviceByType(int deviceType, std::string code);
void getDeviceByType(int typeId, std::vector<std::shared_ptr<Device>>& res);
int getDeviceNumByGroup(int category);
int getDeviceCount(int category);
void getDeviceByGroup(int category, std::vector<std::shared_ptr<Device>>& res);
void setWorkMode(int modeId);
@@ -108,6 +109,7 @@ public:
void writeRuntimeData(std::string dt, int npos);
void polling();
public:
int stationId {};
@@ -119,24 +121,22 @@ public:
int workModeId {}; // 运行模式
int runPolicyId {}; // 运行策略
// 储能容量
double energyCapacity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 ===
// 累计发电量单位kWh
double electGenTatal {};
double electGenTotal {};
// 累计入网电量单位kWh
double electGridTotal {};
// 累计收益,单位:元
double incomeTotal {};
// 碳减排量, 单位:吨
double ccers {};
// 累计储能充电电量
double electStorageIn {};
// 累计储能放电电量
double electStorageOut {};
// 储能容量
double capacity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 日统计 ===
double storageIn {}; // 储能充电电量

View File

@@ -22,7 +22,7 @@ public:
Fields() {};
template <typename T>
void set(string key, T val, int precision=6)
void set(string key, T val, int precision=2)
{
stringstream ss;
ss.precision(precision);
@@ -31,7 +31,7 @@ public:
}
template <typename T>
T get(string key, int precision = 6)
T get(string key, int precision = 2)
{
T val {};
auto iter = mapFields.find(key);
@@ -44,6 +44,18 @@ public:
return val;
}
template <typename T>
void get(string key, T& val, int precision = 2)
{
auto iter = mapFields.find(key);
if (iter != mapFields.end())
{
stringstream ss(iter->second);
ss.precision(precision);
ss >> val;
}
}
/**
* 获取值
* @param: [string key] 索引名称

View File

@@ -99,10 +99,10 @@ public:
if (t !=0) { tickMS_ = Utils::time(); }
}
bool elapse(int64_t ms, bool reset = true)
bool elapse(int64_t second, bool reset = true)
{
auto tick_now = Utils::time();
bool res = tick_now - tickMS_ > ms;
bool res = tick_now - tickMS_ > second;
if (res && reset)
{
tickMS_ = tick_now;

View File

@@ -280,7 +280,7 @@ Errcode DAO::deleteUserById(std::string userId)
Errcode DAO::queryPermissionList(PageInfo& pageInfo, vector<Fields>& result)
{
std::string sqlFrom = "FROM " + DMPermission::TABLENAME;
std::string sqlFrom = "FROM permission WHERE permission.parent_id IS NULL OR permission.parent_id=''";
return QueryPagination("*", sqlFrom, pageInfo, result);
}
@@ -343,14 +343,31 @@ Errcode DAO::insertRole(Fields& params)
if (err == Errcode::OK && !permission.empty())
{
// 查询获取 roleId
std::vector<Fields> res;
std::string sql = "SELECT * FROM " + DMRole::TABLENAME + " WHERE name='" + name + "';";
err = DAO::exec(dao, sql, res);
if (err == Errcode::OK && res.size() > 0)
njson jsonarray;
if (JSON::parse(permission, jsonarray))
{
//std::string roleId = res[0].value("role_id");
//err = DAO::updateRolePermission(dao, roleId, permission);
// 查询获取 roleId
std::vector<Fields> res;
std::string sql = "SELECT * FROM " + DMRole::TABLENAME + " WHERE name='" + name + "';";
err = DAO::exec(dao, sql, res);
if (err == Errcode::OK && res.size() > 0)
{
std::string roleId = res[0].value("role_id");
std::vector<Fields> vecFields;
for (auto& item: jsonarray)
{
Fields fields;
fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
vecFields.push_back(fields);
}
err = DAO::updateRolePermission(dao, roleId, vecFields);
}
}
}
return err;

View File

@@ -113,7 +113,6 @@ public:
// === 统计数据管理 ===
static Errcode queryStatDataList(std::shared_ptr<DaoEntity> dao, std::string startDate, std::string endDate, vector<Fields>& result);
static Errcode queryWorkModeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);
static Errcode queryPolicyTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);

View File

@@ -128,13 +128,6 @@ int main(int argc, char** argv)
Spdlogger::init(spdlog::level::debug, "");
spdlog::info("[main] start ... ======================================================================");
spdlog::info("");
std::cout << Snowflake::instance().getId() << std::endl;
for (int i = 0; i<=10; ++i) {
std::cout << Snowflake::instance().getId() << std::endl;
}
// 运行后台服务
Application::instance().init();

View File

@@ -39,8 +39,8 @@ static void JsonToFields(njson& json, std::vector<std::string> vecKeys, Fields&
case njson::value_t::number_unsigned: { fields.set(key, json[key].get<int>()); } break;
case njson::value_t::number_float: { fields.set(key, json[key].get<float>()); } break;
case njson::value_t::null: {} break;
case njson::value_t::object: {} break;
case njson::value_t::array: {} break;
case njson::value_t::object: { fields.set(key, json[key].dump()); } break;
case njson::value_t::array: { fields.set(key, json[key].dump()); } break;
case njson::value_t::binary: {} break;
case njson::value_t::discarded: {} break;
default:
@@ -165,6 +165,7 @@ static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})},
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})},
{"/queryStatStation", HandlerOptions(&HttpEntity::queryStatStation, {})},
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})},
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})},
{"/queryStatCharts", HandlerOptions(&HttpEntity::queryStatCharts, {})},
@@ -390,6 +391,38 @@ Errcode HttpEntity::queryPermissionList(const httplib::Request& req, njson& json
std::vector<Fields> result;
auto err = DAO::queryPermissionList(pageinfo, result);
HttpHelper::setPagination(pageinfo, result, json);
// 查询所有的角色权限关联
if (err == Errcode::OK)
{
std::map<std::string, int> mapP;
for (int i = 0; i<result.size(); ++i)
{
auto& item = result[i];
std::string id = item.value("permission_id");
mapP[id] = json["data"].size() - 1;
}
std::vector<Fields> vecSubPermission;
DaoEntity::execOnce("SELECT * FROM permission WHERE permission.parent_id IS NOT NULL AND permission.parent_id!='';", vecSubPermission);
for (int i = 0; i<vecSubPermission.size(); ++i)
{
auto& item = vecSubPermission[i];
std::string parentId = item.value("parent_id");
std::string id = item.value("permission_id");
if (!parentId.empty())
{
if (mapP.count(parentId) > 0)
{
int index = mapP[parentId];
njson jsonnode;
FieldsToJson(item, jsonnode);
json["data"][index]["children"].push_back(jsonnode);
}
}
}
}
return err;
}
@@ -423,6 +456,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
std::vector<Fields> result;
auto err = DAO::queryRoleList(pageinfo, result);
HttpHelper::setPagination(pageinfo, result, json);
// 查询所有的角色权限关联
if (err == Errcode::OK)
{
@@ -432,8 +467,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
{
return err;
}
std::map<std::string, std::vector<Fields>> mapP;
for (int i = 0; i<vecPermission.size(); ++i)
{
auto& item = vecPermission[i];
@@ -444,7 +479,6 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
mapP[roleId].push_back(vecPermission[i]);
}
HttpHelper::setPagination(pageinfo, result, json);
for (auto& item : json["data"])
{
auto jsonpermission = njson::array();
@@ -487,6 +521,14 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
return err;
}
Errcode HttpEntity::queryRolePermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
GetRequestParam(req, {"role_id"}, params);
if (!params.contains("role_id")) { errmsg = "缺少参数[role_id]"; return Errcode::ERR_PARAM; }
return Errcode::OK;
}
Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
@@ -496,33 +538,34 @@ Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::st
Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
//GetRequestParam(req, {"role_id", "name", "describe", "is_open", "permission"}, params);
njson jsonparam;
if (!JSON::parse(req.body, jsonparam))
{
return Errcode::ERR_PARAM;
}
JsonToFields(jsonparam, {"role_id", "name", "describe", "is_open"}, params);
GetRequestParam(req, {"role_id", "name", "describe", "is_open", "permission"}, params);
auto roleId = params.value("role_id");
std::string permission = params.remove("permission");
auto dao = DaoEntity::create("");
auto err = DAO::updateRoleById(dao, params);
if (err == Errcode::OK && jsonparam.contains("permission"))
auto err = Errcode::OK;
if (params.size() > 1)
{
if (jsonparam["permission"].is_array())
err = DAO::updateRoleById(dao, params);
}
if (err == Errcode::OK && !permission.empty())
{
njson jsonarray;
if (JSON::parse(permission, jsonarray))
{
auto& jsonPermission = jsonparam["permission"];
std::vector<Fields> vecFields(jsonPermission.size());
int i = 0;
for (auto& item: jsonPermission)
std::vector<Fields> vecFields;
for (auto& item: jsonarray)
{
auto& fields = vecFields[i];
i++;
JsonToFields(item, {"permission_id", "is_add", "is_del", "is_edit", "is_view"}, fields);
Fields fields;
fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
vecFields.push_back(fields);
}
err = DAO::updateRolePermission(dao, roleId, vecFields);
}
@@ -704,13 +747,31 @@ Errcode HttpEntity::insertDevice(const httplib::Request& req, njson& json, std::
{
Fields params;
GetRequestParam(req, {"station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);
return DAO::insertDevice(params);
if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }
Errcode err = DAO::insertDevice(params);
if (err == Errcode::OK)
{
int stationId = params.get<int>("station_id");
auto station = Application::data().getStation(stationId);
if (station) { station->addDevice(params); }
}
return err;
};
Errcode HttpEntity::updateDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
GetRequestParam(req, {"device_id", "station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);
return DAO::updateDeviceById(params);
Errcode err = DAO::updateDeviceById(params);
if (err == Errcode::OK)
{
int stationId = params.get<int>("station_id");
auto station = Application::data().getStation(stationId);
if (station) { station->addDevice(params); }
}
return err;
};
Errcode HttpEntity::deleteDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{
@@ -906,21 +967,63 @@ Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, st
{
auto& appdata = Application::data();
double incomeTotal {};
double station_num = appdata.getStationCount();
double solarDeviceNum {};
double capacityTotal {};
double electGenTotal {};
double electGridTotal {};
double electStorageIn {};
double electStorageOut {};
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
solarDeviceNum += station->getDeviceCount(3);
capacityTotal += station->capacity;
electGenTotal += station->electGenTotal;
electGridTotal += station->electGridTotal;
electStorageIn += station->electStorageIn;
electStorageOut += station->electStorageOut;
}
njson jsondata;
jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式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
jsondata["income_total"] = incomeTotal; // : 累计收益精度0.01
jsondata["station_num"] = station_num; // : 能源站数量
jsondata["storage_device_num"] = station_num; //: 储能设备数量
jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量
jsondata["capacity_total"] = capacityTotal; // : 储能总容量kWh精度0.001
jsondata["solar_elect_gen"] = electGenTotal; // : 发电总电量kWh精度0.001
jsondata["solar_elect_grid"] = electGridTotal; // : 入网种电量kWh精度0.001
jsondata["storage_elect_in"] = electStorageIn; // : 储能充电总电量kWh精度0.001
jsondata["storage_elect_out"] = electStorageOut; // : 储能放电总电量kWh精度0.001
json["data"] = jsondata;
return Errcode::OK;
}
Errcode HttpEntity::queryStatStation(const httplib::Request& req, njson& json, std::string& errmsg)
{
njson jsondata = njson::array();
auto dao = DaoEntity::create("");
std::string sql = R"(SELECT s.station_id, s.name station_name, ss.income_elect, ss.income_charge, ss.usage_rate FROM station s LEFT JOIN
(SELECT station_id, SUM(income_elect ) income_elect , SUM(income_charge) income_charge, avg(usage_rate) usage_rate FROM stat_staion GROUP BY station_id) AS ss
ON ss.station_id = s.station_id)";
std::vector<Fields> vecStations;
auto err = dao->exec(sql, vecStations);
for (auto& fields: vecStations)
{
njson jsonnode;
jsonnode["station_name"] = fields.value("station_name");
jsonnode["income"] = fields.get<float>("income_elect") + fields.get<float>("income_charge");
jsonnode["usage_rate"] = fields.get<float>("usage_rate");
jsondata.push_back(jsonnode);
}
json["data"] = jsondata;
return Errcode(err);
}
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{
std::string station_id = req.get_param_value("station_id");
@@ -948,48 +1051,61 @@ Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std
jsondata["income_charge"] = "123.123"; //充电收益精度0.01
}
json["data"] = jsondata;
return Errcode::OK;
}
Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
{
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("start_date");
std::string dt_end = req.get_param_value("end_date");
int64_t t1 = Utils::time(dt_start)/1000;
int64_t t2 = Utils::time(dt_end)/1000;
int64_t tMax = t1+ 86400 * 30;
njson jsondata = njson::array();
for (int64_t t = t1; t<=t2 && t<=tMax; t += 86400)
//std::string stationId = req.get_param_value("station_id");
//std::string category = req.get_param_value("category");
std::string dtStart = req.get_param_value("start_date");
std::string dtEnd = req.get_param_value("end_date");
if (dtEnd.empty())
{
njson 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);
if (dtStart.empty())
{
dtEnd = Utils::dateStr();
dtStart = Utils::dateStr(Utils::date() - 86400*7);
}
else
{
dtEnd = Utils::dateStr(Utils::time(dtStart + " 00:00:00") + 86400*7);
}
}
json["data"] = jsondata;
std::vector<Fields> result;
Errcode err = DAO::queryStatDataList(NULL, dtStart, dtEnd, result);
json["data"] = FieldsToJsonArray(result);
return err;
//int64_t t1 = Utils::time(dtStart);
//int64_t t2 = Utils::time(dtEnd);
//int64_t tMax = t1+ 86400 * 30;
//njson jsondata = njson::array();
//for (int64_t t = t1; t<=t2 && t<=tMax; t += 86400)
//{
// njson jnode;
// jnode["station_id"] = station_id;
// if (!category.empty()) jnode["category"] = category;
// jnode["dt"] = Utils::dateStr(t); //日期
// 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;
}
@@ -999,10 +1115,11 @@ Errcode HttpEntity::queryStatCharts(const httplib::Request& req, njson& json, st
std::string stationId = req.get_param_value("station_id");
std::string category = req.get_param_value("category");
if (dt.empty()) { errmsg = "参数[dt]错误"; return Errcode::ERR_PARAM; }
if (stationId.empty()) { errmsg = "参数[station_id]错误"; return Errcode::ERR_PARAM; }
if (category.empty()) { errmsg = "参数[category]错误"; return Errcode::ERR_PARAM; }
if (dt.empty()) { dt=Utils::dateStr(); }
njson jsondata;
std::string sql = R"(SELECT hd.*, d.`type` device_type, ddt.category FROM history_day hd

View File

@@ -43,6 +43,7 @@ public:
Errcode queryRoleList(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryRolePermission(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode insertRole(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode updateRole(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode deleteRole(const httplib::Request& req, njson& json, std::string& errmsg);
@@ -80,8 +81,10 @@ public:
Errcode queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg);
// 系统总览所有场站统计
// 系统总览所有场站统计 (总览页 运行状况)
Errcode queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryStatStation(const httplib::Request& req, njson& json, std::string& errmsg);
// 一个场站的累计统计
Errcode queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg);
// 场站按类别按天统计

View File

@@ -29,7 +29,7 @@ void MqttClient::loadDataStruct(std::string filename)
{
std::string name = jsonitem.key();
auto jsonnodeItem = jsonitem.value();
int count = jsonnodeItem["count"];
//int count = jsonnodeItem["count"];
auto jsonaddrs = jsonnodeItem["addr"];
auto& mapItem = g_mapRegInfo[name];
@@ -59,23 +59,22 @@ int MqttClient::init(string addr, string clientId, string username, string passw
this->addr = addr;
this->clientId = clientId;
this->mapTopicInfo["EMS_YX"] = 101;
this->mapTopicInfo["EMS_YX"] = 101;
this->mapTopicInfo["EMS_YC"] = 101;
this->mapTopicInfo["EMS_YT"] = 101;
this->mapTopicInfo["PCS_YX"] = 102;
this->mapTopicInfo["PCS_YC"] = 102;
this->mapTopicInfo["PCU_YX"] = 103;
this->mapTopicInfo["PCU_YC"] = 103;
this->mapTopicInfo["BMS_YX"] = 104;
this->mapTopicInfo["BMS_YC"] = 104;
this->mapTopicInfo["BCU_YX"] = 105;
this->mapTopicInfo["BCU_YC"] = 105;
this->mapTopicInfo["MEM_YC"] = 3;
this->mapTopicInfo["Cooling_YC"] = 110;
this->mapTopicInfo["TH_YC"] = 111;
this->mapTopicInfo["Gateway_YX"] = 112;
this->mapTopicInfo["Charger_YC"] = 113;
//this->mapTopicInfo["EMS_YX"] = TopicInfo("EMS_YX", 101);
//this->mapTopicInfo["EMS_YC"] = TopicInfo("EMS_YC", 101);
//this->mapTopicInfo["EMS_YT"] = TopicInfo("EMS_YT", 101);
//this->mapTopicInfo["PCS_YX"] = TopicInfo("PCS_YX", 102, 1);
this->mapTopicInfo["PCS_YC"] = TopicInfo("PCS_YC", 102, 1);
//this->mapTopicInfo["PCU_YX"] = TopicInfo("PCU_YX", 103);
//this->mapTopicInfo["PCU_YC"] = TopicInfo("PCU_YC", 103);
//this->mapTopicInfo["BMS_YX"] = TopicInfo("BMS_YX", 104);
//this->mapTopicInfo["BMS_YC"] = TopicInfo("BMS_YC", 104);
//this->mapTopicInfo["BCU_YX"] = TopicInfo("BCU_YX", 105, 1);
//this->mapTopicInfo["BCU_YC"] = TopicInfo("BCU_YC", 105, 1);
//this->mapTopicInfo["MEM_YC"] = TopicInfo("MEM_YC", 3);
//this->mapTopicInfo["Cooling_YC"] = TopicInfo("Cooling_YC", 110);
//this->mapTopicInfo["TH_YC"] = TopicInfo("TH_YC", 111);
//this->mapTopicInfo["Gateway_YX"] = TopicInfo("Gateway_YX", 112);
//this->mapTopicInfo["Charger_YC"] = TopicInfo("Charger_YC", 113);
MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
@@ -168,25 +167,6 @@ void MqttClient::subscribe()
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
options.onSuccess = funcSuccess;
options.onFailure = funcFailure;
std::vector<std::string> 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",
//"up/json/" + clientId + "/Cooling_YC",
//"up/json/" + clientId + "/TH_YC",
//"up/json/" + clientId + "/Gateway_YX",
//"up/json/" + clientId + "/Charger_YC",
};
for (auto& item: mapTopicInfo)
{
std::string topic = "up/json/" + clientId + "/" + item.first;
@@ -199,38 +179,11 @@ void MqttClient::subscribe()
}
}
int MqttClient::polling()
int MqttClient::publish(std::string topic, std::string text)
{
// 召测 发布
std::vector<std::string> vecTopic = {
"down/json/" + clientId + "/EMS_YX",
"down/json/" + clientId + "/EMS_YC",
//"down/json/" + clientId + "/EMS_YT",
//"down/json/" + clientId + "/PCU_YX",
//"down/json/" + clientId + "/PCU_YC",
//"down/json/" + clientId + "/PCS_YX",
"down/json/" + clientId + "/PCS_YC",
//"down/json/" + clientId + "/BCU_YX",
//"down/json/" + clientId + "/BCU_YC",
//"down/json/" + clientId + "/BMS_YX",
//"down/json/" + clientId + "/BMS_YC",
//"down/json/" + clientId + "/MEM_YC",
//"down/json/" + clientId + "/Cooling_YC",
//"down/json/" + clientId + "/TH_YC",
//"down/json/" + clientId + "/Gateway_YX",
//"down/json/" + clientId + "/Charger_YC",
};
njson json;
json["ts"] = Utils::time();
json["no"] = 1;
std::string text = json.dump();
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
//options.onSuccess = onSend;
//options.onFailure = onSendFailure;
options.onSuccess = [](void* context, MQTTAsync_successData* response) {};
options.onFailure = [](void* context, MQTTAsync_failureData* response) {};
options.context = this;
MQTTAsync_message msg = MQTTAsync_message_initializer;
@@ -239,16 +192,48 @@ int MqttClient::polling()
msg.payloadlen = text.size();
msg.retained = 0;
for (auto& topic: vecTopic)
std::string topicName = "down/json/" + clientId + "/" + topic;
int rc = MQTTAsync_sendMessage(client, topicName.c_str(), &msg, &options);
if (rc == MQTTASYNC_SUCCESS)
{
int rc = MQTTAsync_sendMessage(client, topic.c_str(), &msg, &options);
if (rc == MQTTASYNC_SUCCESS)
spdlog::info("[mqtt] publish MQTTAsync_sendMessage success, topic={}, text={}", topicName, text);
}
else
{
spdlog::error("[mqtt] publish MQTTAsync_sendMessage error, topic={}, text={}", topicName, text);
}
return 0;
}
int MqttClient::polling()
{
if (!isConnected)
{
return 0;
}
njson json;
json["ts"] = Utils::time();
json["no"] = 0; // 设备编号
auto& appdata = Application::data();
auto station = appdata.getStationByCode(clientId);
for (auto& item: mapTopicInfo)
{
auto& topicInfo = item.second;
if (topicInfo.polling)
{
spdlog::info("MQTT send message success, topic={}, text={}", topic, msg.payload);
}
else
{
spdlog::error("MQTT send message error, topic={}, text={}", topic, msg.payload);
if (station)
{
std::vector<std::shared_ptr<Device>> vecDevice;
station->getDeviceByType(topicInfo.deviceType, vecDevice);
for (auto device: vecDevice)
{
json["no"] = Utils::toInt(device->code);
this->publish(topicInfo.name, json.dump());
}
}
}
}
return 0;
@@ -292,8 +277,7 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
std::string command = GetSubStr("/", topicStr);
std::string deviceCode = GetSubStr("/", topicStr);
spdlog::info("[mqtt] message arrived: topic=[{},{}], len={}, payload={}", topic, msg->qos, len, payload);
spdlog::info("[mqtt] parse topic: {}, stationNo={}, command={}", topic, stationNo, command);
spdlog::info("[mqtt] <<<<<<<<<< message arrived: topic=[{},{}], len={}, payload={}", topic, msg->qos, len, payload);
njson json;
bool ret = JSON::parse(payload, json);
@@ -317,16 +301,23 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
}
std::map<std::string, REGInfo>& mapRegInfo = iter->second;
auto iterTopic = mapTopicInfo.find(command);
if (iterTopic == mapTopicInfo.end())
{
spdlog::error("[mqtt] get topic info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return 1;
}
TopicInfo& topicInfo = iterTopic->second;
int deviceNo = -1;
JSON::read(json, "no", deviceNo);
auto device = station->getDeviceByType(mapTopicInfo[command], Utils::toStr(deviceNo));
auto device = station->getDeviceByType(topicInfo.deviceType, Utils::toStr(deviceNo));
if (!device)
{
return 1;
}
spdlog::info("[mqtt] deviceNo={}", deviceNo);
for (auto& item: json.items())
{
std::string key = item.key();
@@ -371,36 +362,13 @@ void MqttClient::onDeliveryComplete(MQTTAsync_token token)
//spdlog::info("MQTT delivery complete, token={}", token);
}
void MqttClient::onConnectSuccess( MQTTAsync_successData* resp)
{
spdlog::info("[mqtt] connect to {} success, clientId={}.", addr, clientId);
this->isConnected = true;
this->subscribe();
//MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
//options.context = this;
//options.onSuccess = [](void* context, MQTTAsync_successData* response)
// {
// spdlog::info("[mqtt] subscribe success.");
// };
//options.onFailure = [](void* context, MQTTAsync_failureData* response)
// {
// spdlog::info("[mqtt] subscribe failed.");
// };
//
//for (auto& topic: vecTopic)
//{
// int rc = MQTTAsync_subscribe(client, topic.c_str(), qos, &options);
// if (rc != MQTTASYNC_SUCCESS)
// {
// spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc);
// }
// else
// {
// spdlog::info("[mqtt] subscribe [{},{}] success", topic, qos);
// }
//}
}
void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp)
{
spdlog::error("[mqtt] connect to {} error, clientId={}.", addr, clientId);

View File

@@ -25,16 +25,16 @@ struct REGInfo
}
};
//struct TopicInfo
//{
// std::string name;
// std::string topic;
// int deviceType;
// TopicInfo() {};
// TopicInfo(std::string name, std::string topic, int deviceType)
// :name(name), topic(topic), deviceType(deviceType)
// {};
//};
struct TopicInfo
{
std::string name;
int deviceType {0};
int polling {0}; // 召测
TopicInfo() {};
TopicInfo(std::string name, int deviceType, int polling=0)
:name(name), deviceType(deviceType), polling(polling)
{};
};
using namespace std;
@@ -47,8 +47,7 @@ public:
void destory();
void subscribe();
//int publish();
int publish(std::string topic, std::string text);
int polling();
void onConnectionLost(char* cause);
@@ -61,6 +60,7 @@ public:
void parseEMS_YX(std::shared_ptr<Station> station, njson& json, std::map<std::string, REGInfo>& mapRegInfo);
public:
// MQTT clientId (使用station 的 code)
std::string clientId;
MQTTAsync client = nullptr;
@@ -69,7 +69,7 @@ public:
bool isConnected {false};
bool isSubscribed {false};
std::map<std::string, int> mapTopicInfo;
std::map<std::string, TopicInfo> mapTopicInfo;
};