修改现场设备联调问题

This commit is contained in:
lixiaoyuan
2025-10-26 20:43:51 +08:00
parent 5f6511a3f0
commit ac17c41900
13 changed files with 175 additions and 144 deletions

View File

@@ -84,7 +84,7 @@
["SOH", "0x0002", "0", " %", "0.1"], ["SOH", "0x0002", "0", " %", "0.1"],
["电压", "0x0003", "0.0", " V", "0.1"], ["电压", "0x0003", "0.0", " V", "0.1"],
["电流", "0x0005", "0.0", " A", "0.1"], ["电流", "0x0005", "0.0", " A", "0.1"],
["单体最电压", "0x0021", "0.0", " V", "0.001"], ["单体最电压", "0x0021", "0.0", " V", "0.001"],
["单体最小电压", "0x0024", "0.0", " V", "0.001"], ["单体最小电压", "0x0024", "0.0", " V", "0.001"],
["单体最大温度", "0x0029", "0.0", " ℃", "0.1"], ["单体最大温度", "0x0029", "0.0", " ℃", "0.1"],
["单体最小温度", "0x002C", "0.0", " ℃", "0.1"] ["单体最小温度", "0x002C", "0.0", " ℃", "0.1"]

View File

@@ -21,7 +21,7 @@ endmacro(ADD_SOURCE_GROUP)
set(PROJECT_NAME ESS) set(PROJECT_NAME ESS)
project(${PROJECT_NAME}) project(${PROJECT_NAME})
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
# 【注意】visual studio编译时的字符编码问题配置属性 --> C/C++ --> 命令行 --> 其它选项: /utf-8 或添加如下指令 # 【注意】visual studio编译时的字符编码问题配置属性 --> C/C++ --> 命令行 --> 其它选项: /utf-8 或添加如下指令
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")

View File

@@ -134,6 +134,7 @@ void Application::runThreadStat()
//spdlog::info("保存历史数据倒计时: {}", 600 - offset); //spdlog::info("保存历史数据倒计时: {}", 600 - offset);
} }
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
} }
} }

View File

@@ -221,7 +221,10 @@ void Device::setParam(std::string k, int v)
else if (k== "28") { ratio = 0.1; } else if (k== "28") { ratio = 0.1; }
} }
int precision = (ratio != 1.0f) ? 1 : 0; int precision = 0;
if (ratio == 0.1f) { precision = 1; }
else if (ratio == 0.01f) { precision = 2; }
else if (ratio == 0.001f) { precision = 3; }
std::string valStr = Utils::toStr(v*ratio, precision); std::string valStr = Utils::toStr(v*ratio, precision);
if (type == 106) // 充电桩状态,特殊数据格式 if (type == 106) // 充电桩状态,特殊数据格式
{ {

View File

@@ -146,23 +146,30 @@ void SysPolicy::getGatewayJsonPeriods(njson& json)
{ {
if (vecPeriods1.size()>0) if (vecPeriods1.size()>0)
{ {
njson jsonArray = njson::array(); map<string, vector<int>> mapT;
for (auto& item: vecPeriods1[0]) for (auto& item: vecPeriods1[0])
{ {
int h = 0; int m = 0; int h = 0; int m = 0;
PeriodsTimeStrToInt(item.first, h, m); PeriodsTimeStrToInt(item.first, h, m);
if (jsonArray.size() == 0 && h!=0) int p = 0;
{
jsonArray.push_back({0, 0, 0});
}
int p = 1;
if (item.second == "") p = 1; if (item.second == "") p = 1;
else if (item.second == "") p = 2; else if (item.second == "") p = 2;
else if (item.second == "") p = 3; else if (item.second == "") p = 3;
else if (item.second == "") p = 4; else if (item.second == "") p = 4;
else p = 0; else p = 0;
jsonArray.push_back({h, m, p}); char str[5] = {};
sprintf(str, "%02d:%02d", h, m);
mapT[str] = {h, m, p};
}
njson jsonArray = njson::array();
for (auto& item: mapT)
{
if (jsonArray.size() == 0 && item.first != "00:00")
{
jsonArray.push_back({0, 0, 0});
}
jsonArray.push_back(item.second);
} }
json.push_back(jsonArray); json.push_back(jsonArray);
} }

View File

@@ -674,12 +674,11 @@ void Station::writeStatistic()
} }
} }
{ {
int pos = npos; int pos = npos;
if (tOffset > 20) { pos += 1; } if (tOffset > 20) { pos += 1; }
mapCacheElectIn[pos] = statData.dayElectIn; mapCacheElectIn[pos] = (pos == 0) ? 0 : statData.dayElectIn;
mapCacheElectOut[pos] = statData.dayElectOut; mapCacheElectOut[pos] = (pos == 0) ? 0 : statData.dayElectOut;
mapCacheElectCharger[pos] = 0; mapCacheElectCharger[pos] = 0;
// 预测数据源记录 // 预测数据源记录
@@ -703,57 +702,61 @@ void Station::writeStatistic()
} }
void Station::predict() void Station::predict()
{ {
int64_t tNow = Utils::time(); int64_t tNow = Utils::time();
int days = 7;
string dt1 = Utils::dateStr(tNow-86400*7); string dt1 = Utils::dateStr(tNow-86400*days);
string dt2 = Utils::dateStr(tNow-86400); string dt2 = Utils::dateStr(tNow-86400);
/// 预测实现方案: /// 预测实现方案:
// 查询前7天的历史数据根据历史数据计算今日数据每10分钟一个数据一天共144个数据点 // 查询前7天的历史数据(不包含今天)根据历史数据计算今日数据每10分钟一个数据一天共144个数据点
string sql = "SELECT * FROM predict_day pd WHERE pd.station_id='" + std::to_string(stationId) string sql = "SELECT * FROM predict_day pd WHERE pd.station_id='" + std::to_string(stationId)
+ "'AND dt>='" + dt1 + "' AND dt<='" + dt2 + "'"; + "' AND dt>='" + dt1 + " AND dt<'" + dt2 + "';";
vector<Fields> result; vector<Fields> result;
DAO::exec(NULL, sql, result); DAO::exec(NULL, sql, result);
// 数据源的条数1天的数据算作1条 // 数据源的每个时刻数据点的个数
int countStorageIn = 0; vector<int> countStorageIn(predictStorageIn.size(), 0);
int countStorageOut = 0; vector<int> countStorageOut(predictStorageOut.size(), 0);
int countCharge = 0; vector<int> countCharge(predictCharge.size(), 0);
for (int row=0; row<result.size(); ++row) for (int row=0; row<result.size(); ++row)
{ {
// 如果数据全是0则不参与计算
auto& fields = result[row]; auto& fields = result[row];
vector<int>* vdptr = NULL; vector<int>* vdptr = NULL;
int datatype = fields.get<int>("datatype"); // 1储能充电2储能放电3充电桩充电4发电 int datatype = fields.get<int>("datatype"); // 1储能充电2储能放电3充电桩充电4发电
if (datatype == 1) if (datatype == 1) { vdptr = &predictStorageIn; }
{ else if (datatype == 2) { vdptr = &predictStorageOut; }
countStorageIn++; else if (datatype == 3) { vdptr = &predictCharge; }
vdptr = &predictStorageIn;
}
else if (datatype == 2)
{
countStorageOut++;
vdptr = &predictStorageOut;
}
else if (datatype == 3)
{
countCharge++;
vdptr = &predictCharge;
}
if (vdptr) if (vdptr)
{ {
string& strval = fields.value("value"); string& strval = fields.value("value");
std::vector<int> vec; std::vector<int> vec;
JSON::parseArray(strval, vec); JSON::parseArray(strval, vec);
for (int i = 0; i<vdptr->size() && i<vec.size(); ++i) for (int i = 0; i<vdptr->size() && i<vec.size(); ++i)
{ {
(*vdptr)[i] += vec[i]; auto& v0 = vec[i];
if (v0 > 0)
{
(*vdptr)[i] += v0;
if (datatype == 1) { countStorageIn[i]++; }
else if (datatype == 2) { countStorageOut[i]++; }
else if (datatype == 3) { countCharge[i]++; }
} }
} }
} }
}
for (int i = 0; i<predictStorageIn.size(); ++i)
{
if (countStorageIn[i] > 0) { predictStorageIn[i] = predictStorageIn[i] / countStorageIn[i]; }
if (countStorageOut[i] > 0) { predictStorageOut[i] = predictStorageOut[i] / countStorageOut[i]; }
if (countCharge[i] > 0) { predictCharge[i] = predictCharge[i] / countCharge[i]; }
}
} }

View File

@@ -27,13 +27,74 @@ std::string Utils::toHex(const std::string& s)
} }
std::string Utils::fromHex(const std::string& hexstr) std::string Utils::fromHex(const std::string& hexstr)
{ {
std::vector<uint8_t> v; std::vector<uint8_t> result;
v.reserve(hexstr.size() / 2); result.reserve(hexstr.size() / 2);
for (std::string::const_iterator it = hexstr.begin(); it != hexstr.end(); it += 2) for (std::string::const_iterator it = hexstr.begin(); it != hexstr.end(); it += 2)
{ {
v.push_back(static_cast<char>(strtol(std::string(it, it + 2).c_str(), nullptr, 16))); result.push_back(static_cast<char>(strtol(std::string(it, it + 2).c_str(), nullptr, 16)));
} }
return std::string(v.begin(), v.end()); return std::string(result.begin(), result.end());
}
#include <iostream>
string Utils::fromHexText(string s)
{
vector<unsigned char> result;
string tmp;
stringstream ss;
int v;
for (auto ch : s)
{
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
{
tmp += ch;
if (tmp.size() == 2)
{
ss.clear();
ss.str("");
ss << hex << tmp;
ss >> v;
result.emplace_back((unsigned char)v);
tmp.clear();
}
}
}
return string(result.begin(), result.end());
}
string Utils::toHexText(string s, string d/* = " "*/)
{
stringstream ss;
for (unsigned int i = 0; i < s.size(); ++i)
{
ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)static_cast<unsigned char>(s[i]) << ((i < s.size() - 1) ? d : "");
}
return ss.str();
}
int64_t Utils::hexBinToInt(const string& str, bool swap/*=false*/)
{
int64_t v = 0;
for (size_t i = 0; i < str.size(); i++)
{
if (swap)
{
v = v + (str[str.size() - 1 - i] << (str.size() - 1 - i) * 8);
}
else
{
v = v + (str[i] << (str.size() - 1 - i) * 8);
}
}
return v;
}
int Utils::hexStrToInt(const std::string& str)
{
stringstream ss;
int ret;
ss << hex << str.c_str();
ss >> ret;
return ret;
} }
string Utils::toStr(int v) string Utils::toStr(int v)
@@ -80,57 +141,9 @@ double Utils::toDouble(const std::string& str)
ss >> ret; ss >> ret;
return ret; return ret;
} }
int64_t Utils::hexbinToInt(const string& str, bool swap/*=false*/)
{
int64_t v = 0;
for (size_t i = 0; i < str.size(); i++)
{
if (swap)
{
v = v + (str[str.size() - 1 - i] << (str.size() - 1 - i) * 8);
}
else
{
v = v + (str[i] << (str.size() - 1 - i) * 8);
}
}
return v;
}
int Utils::hexstrToInt(const std::string& str)
{
stringstream ss;
int ret;
ss << hex << str.c_str();
ss >> ret;
return ret;
}
#include <iostream>
string Utils::from_hex_text(string s)
{
vector<unsigned char> result;
string tmp;
stringstream ss;
int v;
for (auto ch : s)
{
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
{
tmp += ch;
if (tmp.size() == 2)
{
ss.clear();
ss.str("");
ss << hex << tmp;
ss >> v;
result.emplace_back((unsigned char)v);
tmp.clear();
}
}
}
return string(result.begin(), result.end());
}
//string Utils::fromHexText1(string s) //string Utils::fromHexText1(string s)
//{ //{
@@ -166,16 +179,7 @@ string Utils::from_hex_text(string s)
// return string(result.begin(), result.end()); // return string(result.begin(), result.end());
//} //}
string Utils::to_hex_text(string s, string d/* = " "*/)
{
stringstream ss;
for (unsigned int i = 0; i < s.size(); ++i)
{
unsigned char ch = s[i];
ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)ch << ((i < s.size() - 1) ? d : "");
}
return ss.str();
}
void time_point_to_duration() void time_point_to_duration()
{ {
@@ -418,13 +422,8 @@ int64_t Utils::timeDaySeconds()
return tsNow - tsDay; return tsNow - tsDay;
} }
void Utils::sleep_ms(int ms) void Utils::sleepMS(int ms)
{ {
// 计算时间间隔:
//auto start = chrono::high_resolution_clock::now();
//auto end = chrono::high_resolution_clock::now();
//chrono::duration<double, std::milli> elapsed = end - start;
//int64_t t = elapsed.count();
std::this_thread::sleep_for(chrono::milliseconds(ms)); std::this_thread::sleep_for(chrono::milliseconds(ms));
} }

View File

@@ -8,9 +8,6 @@
#include <iomanip> #include <iomanip>
#include <functional> #include <functional>
#include <thread> #include <thread>
//#include "Crypto.h"
using namespace std; using namespace std;
class Utils class Utils
@@ -19,6 +16,11 @@ public:
static std::string toHex(std::vector<unsigned char>& s, int len = 0); static std::string toHex(std::vector<unsigned char>& s, int len = 0);
static std::string toHex(const std::string& s); static std::string toHex(const std::string& s);
static std::string fromHex(const std::string& hexstr); static std::string fromHex(const std::string& hexstr);
static string fromHexText(string s);
static string toHexText(string s, string d = " ");
static int64_t hexBinToInt(const string& str, bool swap = false);
static int hexStrToInt(const string& str);
static string toStr(int v); static string toStr(int v);
static string toStr(float v, int precision = 2); static string toStr(float v, int precision = 2);
@@ -28,12 +30,6 @@ public:
static float toFloat(const string& str); static float toFloat(const string& str);
static double toDouble(const string& str); static double toDouble(const string& str);
static int64_t hexbinToInt(const string& str, bool swap = false);
static int hexstrToInt(const string& str);
static string from_hex_text(string s);
static string to_hex_text(string s, string d = " ");
template<typename T> template<typename T>
static void append_bytes(vector<unsigned char>& dest, const T& src, int len) static void append_bytes(vector<unsigned char>& dest, const T& src, int len)
@@ -84,7 +80,7 @@ public:
static string gbkToUtf8(string s); static string gbkToUtf8(string s);
static string utf8ToGbk(string s); static string utf8ToGbk(string s);
static void sleep_ms(int ms); static void sleepMS(int ms);
static int random(int min, int max); static int random(int min, int max);
@@ -96,8 +92,6 @@ public:
class TimeTick class TimeTick
{ {
public: public:
int64_t tickMS_ = 0;
TimeTick(int t=0) TimeTick(int t=0)
{ {
if (t !=0) { tickMS_ = Utils::time(); } if (t !=0) { tickMS_ = Utils::time(); }
@@ -105,19 +99,16 @@ public:
bool elapse(int64_t second, bool reset = true) bool elapse(int64_t second, bool reset = true)
{ {
auto tick_now = Utils::time(); auto tickNow = Utils::time();
bool res = tick_now - tickMS_ > second; bool ret = tickNow - tickMS_ > second;
if (res && reset) if (ret && reset) { tickMS_ = tickNow; }
{ return ret;
tickMS_ = tick_now;
}
return res;
} }
void reset() void reset() { tickMS_ = Utils::time(); }
{
tickMS_ = Utils::time(); public:
} int64_t tickMS_ = 0;
}; };
#endif // !!! _Utils_H_ #endif // !!! _Utils_H_

View File

@@ -167,10 +167,27 @@ void OpensslSM2_test()
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
{
stringstream ss; stringstream ss;
float v = 3.123456;
float ratio = 0.1;
ss << "(" << setw(2) << setfill('0') << 1; std::cout << Utils::toStr(v, 0) << std::endl;
std::cout << ss.str(); std::cout << Utils::toStr(v, 1) << std::endl;
ratio = 1;
if (ratio == 1.0f)
{
std::cout << Utils::toStr(ratio, 2) << std::endl;
}
std::cout << Utils::toFloat("1") << std::endl;
//ss << "(" << setw(2) << setfill('0') << 1 << ")";
//std::cout << ss.str();
std::cout << "======================" << std::endl;
}
// 设置控制台输出为 UTF-8 编码 // 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);

View File

@@ -13,10 +13,9 @@
MainApp::MainApp() MainApp::MainApp()
{ {
// 设置背景色
QPalette palette(this->palette()); QPalette palette(this->palette());
palette.setColor(QPalette::Window, QColor(11, 33, 77));
// 设置背景为黑色
palette.setColor(QPalette::Window, QColor(1, 32, 54));
this->setAutoFillBackground(true); this->setAutoFillBackground(true);
this->setPalette(palette); this->setPalette(palette);
this->setStyleSheet("color: white;"); this->setStyleSheet("color: white;");
@@ -59,6 +58,7 @@ void MainApp::initMenu()
ui.labelDT = std::make_shared< QLabel>(); ui.labelDT = std::make_shared< QLabel>();
ui.labelDT->setAlignment(Qt::AlignCenter); ui.labelDT->setAlignment(Qt::AlignCenter);
ui.labelDT->setText(Utils::timeStr().c_str()); ui.labelDT->setText(Utils::timeStr().c_str());
ui.labelDT->setFont(QFont("微软雅黑", 14));
ui.layoutMenu->addWidget(ui.labelDT.get(), 0, 0, 1, 1); ui.layoutMenu->addWidget(ui.labelDT.get(), 0, 0, 1, 1);
// 设置列宽和行高 // 设置列宽和行高
ui.layoutMenu->setRowMinimumHeight(0, 40); // 设置第0列的最小宽度为100像素 ui.layoutMenu->setRowMinimumHeight(0, 40); // 设置第0列的最小宽度为100像素

View File

@@ -5,7 +5,9 @@ static const std::string QSS_GROUP =
"QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; left:10px; margin-left: 0px; padding:0 1px; }"; "QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; left:10px; margin-left: 0px; padding:0 1px; }";
static const std::string QSS_BTN = static const std::string QSS_BTN =
"QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid gray;color:white;font:bold 13px;}"; "QPushButton {background:rgba(180,180,180,50);border-radius:2px;border:1px solid gray;color:white;}"
"QPushButton:hover {background-color:rgb(32,164,128);}"
"QPushButton:pressed {border-width:2px 0 0 2px;border-style:inset;}";
static const std::string QSS_BTN_ACTIVE = static const std::string QSS_BTN_ACTIVE =
"QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid green;color:green;font:bold 15px;}"; "QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid green;color:green;font:bold 15px;}";
@@ -29,7 +31,7 @@ static const std::string QSS_BTN_TAB =
//"QPushButton:disabled {color:rgb(150,150,150);}"; //"QPushButton:disabled {color:rgb(150,150,150);}";
static const std::string QSS_LINE = static const std::string QSS_LINE =
"QLineEdit { background-color: rgb(14, 49, 66); color: #ffffff; border: 1px solid gray; border-radius: 5px; font: bold 13px; }"; "QLineEdit { background-color:rgba(180,180,180,36); color:#ffffff; border:1px solid gray; border-radius:3px; font:bold 13px; }"; //14, 49, 66
static const std::string QSS_TABLE = // 表格整体样式 static const std::string QSS_TABLE = // 表格整体样式
"QTableWidget {" "QTableWidget {"
@@ -70,6 +72,13 @@ MyWidget::MyWidget(QWidget* parent) : QWidget(parent)
setAutoFillBackground(true); setAutoFillBackground(true);
} }
shared_ptr<QPushButton> MyQUI::Button(QWidget* parent, int x, int y, int w, int h, std::string title)
{
auto btn = std::make_shared<QPushButton>(title.c_str(), parent);
btn->setGeometry(x, y, w, h);
btn->setStyleSheet(QSS_BTN.c_str());
return btn;
}
std::shared_ptr<QGroupBox> MyQUI::GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title) std::shared_ptr<QGroupBox> MyQUI::GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title)
{ {

View File

@@ -81,6 +81,8 @@ using MyPairLabelLine = pair<shared_ptr<QLabel>, shared_ptr<QLineEdit>>;
class MyQUI class MyQUI
{ {
public: public:
static shared_ptr<QPushButton> Button(QWidget* parent, int x, int y, int w, int h, std::string title);
static shared_ptr<QGroupBox> GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title); static shared_ptr<QGroupBox> GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title);
static MyPairLabelLine PairLine(QWidget* parent, int x, int y, string k, string v, bool readonly=true); static MyPairLabelLine PairLine(QWidget* parent, int x, int y, string k, string v, bool readonly=true);

View File

@@ -64,13 +64,12 @@ QWHome::QWHome(QWidget* parent) : MyWidget(parent)
table->setColumnWidth(4, 80); table->setColumnWidth(4, 80);
} }
logFilter = MyQUI::PairLine(this, 10, y += 270, "日志过滤: ", "", false); logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
btnLogClean = std::make_shared<QPushButton>("清除", this); btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
btnLogClean->setGeometry(400, y, 80, 26);
connect(btnLogClean.get(), &QPushButton::clicked, this, [=]() { texteditLog->clear(); }); connect(btnLogClean.get(), &QPushButton::clicked, this, [=]() { texteditLog->clear(); });
texteditLog = std::make_shared<QTextEdit>(this); texteditLog = std::make_shared<QTextEdit>(this);
texteditLog->setGeometry(10, y += 30, 1190, 280); texteditLog->setGeometry(10, y += 35, 1190, 280);
texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;"); texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;");
texteditLog->setReadOnly(true); texteditLog->setReadOnly(true);
texteditLog->document()->setMaximumBlockCount(1000); texteditLog->document()->setMaximumBlockCount(1000);