实现服务端的QT应用界面

This commit is contained in:
lixiaoyuan
2025-09-24 19:06:31 +08:00
parent 0abb4e54f1
commit d7888c2be4
26 changed files with 435 additions and 173 deletions

View File

@@ -69,9 +69,9 @@ bool AppData::initFromDB()
std::string name = fields.value(DMDefWorkMode::NAME);
this->mapping.policyType.push_back({std::to_string(policyTypeId), name});
this->mapPolicyType[policyTypeId] = name;
str += ("策略类型: {" + std::to_string(policyTypeId) + ":" + name + "},");
//str += ("策略类型: {" + std::to_string(policyTypeId) + ":" + name + "},");
}
spdlog::info(str);
//spdlog::info(str);
}
{ // 数据库读取设备类型定义
str = "", result.clear();
@@ -87,9 +87,9 @@ bool AppData::initFromDB()
item->fieldsAttr.parseJson(item->attr);
mapDeviceType[item->typeId] = item;
mapping.deviceType.push_back({std::to_string(item->typeId), item->name});
str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},");
//str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},");
}
spdlog::info(str);
//spdlog::info(str);
}
{ // 数据库读取角色定义
str = "", result.clear();
@@ -103,9 +103,9 @@ bool AppData::initFromDB()
item->isOpen = fields.get<int>(DMRole::IS_OPEN);
mapRole[item->roleId] = item;
mapping.role.push_back({std::to_string(item->roleId), item->name});
str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},");
//str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},");
}
spdlog::info(str);
//spdlog::info(str);
}
{ // 数据库读取场站信息
str = "", result.clear();
@@ -118,9 +118,8 @@ bool AppData::initFromDB()
station->setFields(fields);
this->mapStation[station->stationId] = station;
this->mapping.stationName.push_back({std::to_string(station->stationId), station->name});
str += ("场站: {" + std::to_string(station->stationId) + ":" + station->name + "},");
spdlog::info("场站: {}:{}, {}", station->stationId, station->name, station->status>0 ? "启用" : "未启用");
}
spdlog::info(str);
}
{ // 数据库读取设备信息
str = "", result.clear();
@@ -158,32 +157,32 @@ bool AppData::initFromDB()
}
}
{ // 数据库读取电价分段信息
result.clear();
vecElectPeriods.resize(12);
DAO::exec(dao, "SELECT * FROM configure;", result);
Fields info;
for (auto& fields: result)
{
auto k = fields.value("key");
auto v = fields.value("val");
info.set(k, v);
}
//result.clear();
//vecElectPeriods.resize(12);
//DAO::exec(dao, "SELECT * FROM configure;", result);
//
//Fields info;
//for (auto& fields: result)
//{
// auto k = fields.value("key");
// auto v = fields.value("val");
// info.set(k, v);
//}
for (int month = 1; month<=12; month++)
{
if (month-1 < vecElectPeriods.size())
{
auto& vecItems = vecElectPeriods[month-1];
std::string str = info.value("period_" + std::to_string(month));
std::vector<std::string> vec;
Utils::split(str, ",", vecItems);
}
}
electPriceSuperPeak = info.get<double>("price_super_peak");
electPricePeak = info.get<double>("price_peak");
electPriceShoulder = info.get<double>("price_shoulder");
electPriceOffPeak = info.get<double>("price_off_peak");
//for (int month = 1; month<=12; month++)
//{
// if (month-1 < vecElectPeriods.size())
// {
// auto& vecItems = vecElectPeriods[month-1];
// std::string str = info.value("period_" + std::to_string(month));
// std::vector<std::string> vec;
// Utils::split(str, ",", vecItems);
// }
//}
//electPriceSuperPeak = info.get<double>("price_super_peak");
//electPricePeak = info.get<double>("price_peak");
//electPriceShoulder = info.get<double>("price_shoulder");
//electPriceOffPeak = info.get<double>("price_off_peak");
}
{ // 数据库读取统计数据
vector<Fields> result;
@@ -457,32 +456,32 @@ int AppData::getPolicyTypeId(std::string name)
}
std::vector<std::string> AppData::getElectPreiodVals(int month)
{
if (month > 0 && month-1 < vecElectPeriods.size())
{
return vecElectPeriods[month-1];
}
return {};
}
std::string AppData::getElectPreiodVal(int month, int hour)
{
if (month > 0 && month-1 < vecElectPeriods.size())
{
auto& vec = vecElectPeriods[month-1];
if (hour > 0 && hour-1 < vec.size())
{
auto& val = vec[hour-1];
if (val == "") return "尖峰";
if (val == "") return "高峰";
if (val == "") return "平段";
if (val == "") return "低谷";
return val;
}
}
return "";
}
//std::vector<std::string> AppData::getElectPreiodVals(int month)
//{
// if (month > 0 && month-1 < vecElectPeriods.size())
// {
// return vecElectPeriods[month-1];
// }
// return {};
//}
//
//std::string AppData::getElectPreiodVal(int month, int hour)
//{
// if (month > 0 && month-1 < vecElectPeriods.size())
// {
// auto& vec = vecElectPeriods[month-1];
// if (hour > 0 && hour-1 < vec.size())
// {
// auto& val = vec[hour-1];
// if (val == "尖") return "尖峰";
// if (val == "峰") return "高峰";
// if (val == "平") return "平段";
// if (val == "谷") return "低谷";
// return val;
// }
// }
// return "";
//}
void AppData::storeRuntimeDB()
{

View File

@@ -99,9 +99,8 @@ public:
// 根据策略类型名称获取策略类型ID
int getPolicyTypeId(std::string name);
std::vector<std::string> getElectPreiodVals(int month);
std::string getElectPreiodVal(int month, int hour);
//std::vector<std::string> getElectPreiodVals(int month);
//std::string getElectPreiodVal(int month, int hour);
void storeRuntimeDB();
@@ -134,10 +133,12 @@ public:
VecPairSS stationName;
} mapping;
double electPriceSuperPeak {};
double electPricePeak {};
double electPriceShoulder {};
double electPriceOffPeak {};
//double electPriceSuperPeak {};
//double electPricePeak {};
//double electPriceShoulder {};
//double electPriceOffPeak {};
// 电力峰谷分段 (12个月每个月按小时分成24个时段)
//std::vector<std::vector<std::string>> vecElectPeriods;
// 场站信息
std::unordered_map<int, std::shared_ptr<Station>> mapStation;
@@ -157,8 +158,7 @@ public:
// 策略信息
std::unordered_map<int, std::shared_ptr<SysPolicy>> mapPolicy;
// 电力峰谷分段 (12个月每个月按小时分成24个时段)
std::vector<std::vector<std::string>> vecElectPeriods;
std::map<int64_t, double> mapDataDay;

View File

@@ -73,6 +73,8 @@ void Application::runThreadDevice()
void Application::runThreadMain()
{
std::this_thread::sleep_for(std::chrono::seconds(10)); // 延迟10秒执行
while (!isQuit)
{
if (!this->isInit) // 初始化失败
@@ -85,27 +87,29 @@ void Application::runThreadMain()
static TimeTick ttMqtt; // 检查 场站的 MQTT 连接
if (ttMqtt.elapse(30))
{
auto& optionMqtt = Config::option.mqtt;
if (!optionMqtt.host.empty())
for (auto& item : appdata.mapStation)
{
for (auto& item : appdata.mapStation)
auto& station = item.second;
// 检查MQTT的连接状态
if (!Config::option.mqtt.host.empty()) { station->initMqtt(); }
// 检查设备的在线状态
station->checkDevice();
}
}
static TimeTick ttMqttPolling; // 召测
if (!Config::option.mqtt.host.empty() && ttMqttPolling.elapse(10))
{
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
if (Utils::time() - station->getPollingTS() > Config::option.mqtt.interval)
{
auto& station = item.second;
if (station)
{
if (station->isOpen)
{
// 该函数检查连接状态,若已经连接,则无操作;若未连接,则进行连接操作
item.second->initMqtt();
// 召测
item.second->polling();
}
// 检查设备的在线状态
station->checkDevice();
}
item.second->polling();
}
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}

View File

@@ -47,8 +47,7 @@ bool Config::init(std::string filename)
JSON::read(json, "token", option.http.useToken);
JSON::read(json, "port", option.http.port);
JSON::read(json, "encryption", option.http.encryption);
JSON::read(json, "encryptKey", option.http.encryptKey);
}
JSON::read(json, "encryptKey", option.http.encryptKey); }
else
{
spdlog::error("[config] parse http failed: not found.");
@@ -60,6 +59,7 @@ bool Config::init(std::string filename)
JSON::read(json, "host", option.mqtt.host);
JSON::read(json, "username", option.mqtt.username);
JSON::read(json, "password", option.mqtt.password);
JSON::read(json, "interval", option.mqtt.interval);
}
else
{

View File

@@ -29,6 +29,7 @@ struct AppOption
std::string host;
std::string username;
std::string password;
int interval {60};
} mqtt;
struct {

View File

@@ -317,7 +317,10 @@ void Device::setParam(std::string k, int v)
}
else if (type == int(EDeviceType::BMS)) // 104 BMS
{
if (k == "0x0049") { err = (v==1); } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x0049
if (k == "0x0049")
{
err = (v==1);
} //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x0049
else if (k == "0x004A") { running = (v==1 || v==2); } //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004A
}
else if (type == int(EDeviceType::BCU)) // BCU

View File

@@ -24,8 +24,8 @@ void Station::setFields(Fields& fields)
this->workMode = fields.get<int>(DMStation::WORK_MODE);
this->code = fields.value(DMStation::CODE);
this->status = fields.get<int>(DMStation::STATUS);
this->operationDate = fields.value(DMStation::OPERATION_DATE);
this->isOpen = fields.get<int>(DMStation::STATUS);
this->launchDate = fields.value("operation_date");
this->policy.setFields(fields);
}
@@ -156,12 +156,25 @@ void Station::initMqtt()
void Station::polling()
{
if (mqttCli)
if (status > 0 && mqttCli)
{
mqttCli->polling();
if (mqttCli->isConnected)
{
mqttCli->polling();
}
//else
//{
// // 该函数检查连接状态,若已经连接,则无操作;若未连接,则进行连接操作
// this->initMqtt();
//}
}
}
int64_t Station::getPollingTS()
{
return (mqttCli != nullptr) ? mqttCli->tsPolling : 0;
}
void Station::setGarewayWorkMode()
{
if (!mqttCli)

View File

@@ -111,6 +111,7 @@ public:
void initMqtt();
void polling();
int64_t getPollingTS();
void setGarewayWorkMode();
void checkDevice();
@@ -129,7 +130,6 @@ public:
int stationId {};
std::string name;
std::string code;
bool isOpen {false};
int status {0};
std::string operationDate;
SysPolicy policy;
@@ -236,6 +236,28 @@ public:
float dayFeeOut {0.0}; // 日放电费用 R uint32 1RMB 0 0x1114
float dayIncome {0.0}; // 日收益 R int32 1RMB 0 0x1116
//日正向尖有功电能 R uint32 1kWh 0x0039
//日正向峰有功电能 R uint32 1kWh 0x003B
//日正向平有功电能 R uint32 1kWh 0x003D
//日正向谷有功电能 R uint32 1kWh 0x003F
//日正向总有功电能 R uint32 1kWh 0x0041
//日反向尖有功电能 R uint32 1kWh 0x0043
//日反向峰有功电能 R uint32 1kWh 0x0045
//日反向平有功电能 R uint32 1kWh 0x0047
//日反向谷有功电能 R uint32 1kWh 0x0049
//日反向总有功电能 R uint32 1kWh 0x004B
//总正向尖有功电能 R uint32 1kWh 0x0057
//总正向峰有功电能 R uint32 1kWh 0x0059
//总正向平有功电能 R uint32 1kWh 0x005B
//总正向谷有功电能 R uint32 1kWh 0x005D
//总正向总有功电能 R uint32 1kWh 0x005F
//总反向尖有功电能 R uint32 1kWh 0x0061
//总反向峰有功电能 R uint32 1kWh 0x0063
//总反向平有功电能 R uint32 1kWh 0x0065
//总反向谷有功电能 R uint32 1kWh 0x0067
//总反向总有功电能 R uint32 1kWh 0x0069
} statData;
///////////////////////////////////////////////////////////////////////////////////////////////