修改现场设备联调问题

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

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

View File

@@ -134,6 +134,7 @@ void Application::runThreadStat()
//spdlog::info("保存历史数据倒计时: {}", 600 - offset);
}
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; }
}
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);
if (type == 106) // 充电桩状态,特殊数据格式
{

View File

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

View File

@@ -674,12 +674,11 @@ void Station::writeStatistic()
}
}
{
int pos = npos;
if (tOffset > 20) { pos += 1; }
mapCacheElectIn[pos] = statData.dayElectIn;
mapCacheElectOut[pos] = statData.dayElectOut;
mapCacheElectIn[pos] = (pos == 0) ? 0 : statData.dayElectIn;
mapCacheElectOut[pos] = (pos == 0) ? 0 : statData.dayElectOut;
mapCacheElectCharger[pos] = 0;
// 预测数据源记录
@@ -703,57 +702,61 @@ void Station::writeStatistic()
}
void Station::predict()
{
int64_t tNow = Utils::time();
string dt1 = Utils::dateStr(tNow-86400*7);
int days = 7;
string dt1 = Utils::dateStr(tNow-86400*days);
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)
+ "'AND dt>='" + dt1 + "' AND dt<='" + dt2 + "'";
+ "' AND dt>='" + dt1 + " AND dt<'" + dt2 + "';";
vector<Fields> result;
DAO::exec(NULL, sql, result);
// 数据源的条数1天的数据算作1条
int countStorageIn = 0;
int countStorageOut = 0;
int countCharge = 0;
// 数据源的每个时刻数据点的个数
vector<int> countStorageIn(predictStorageIn.size(), 0);
vector<int> countStorageOut(predictStorageOut.size(), 0);
vector<int> countCharge(predictCharge.size(), 0);
for (int row=0; row<result.size(); ++row)
{
// 如果数据全是0则不参与计算
auto& fields = result[row];
vector<int>* vdptr = NULL;
int datatype = fields.get<int>("datatype"); // 1储能充电2储能放电3充电桩充电4发电
if (datatype == 1)
{
countStorageIn++;
vdptr = &predictStorageIn;
}
else if (datatype == 2)
{
countStorageOut++;
vdptr = &predictStorageOut;
}
else if (datatype == 3)
{
countCharge++;
vdptr = &predictCharge;
}
if (datatype == 1) { vdptr = &predictStorageIn; }
else if (datatype == 2) { vdptr = &predictStorageOut; }
else if (datatype == 3) { vdptr = &predictCharge; }
if (vdptr)
{
string& strval = fields.value("value");
std::vector<int> vec;
JSON::parseArray(strval, vec);
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::vector<uint8_t> v;
v.reserve(hexstr.size() / 2);
std::vector<uint8_t> result;
result.reserve(hexstr.size() / 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)
@@ -80,57 +141,9 @@ double Utils::toDouble(const std::string& str)
ss >> 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)
//{
@@ -166,16 +179,7 @@ string Utils::from_hex_text(string s)
// 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()
{
@@ -418,13 +422,8 @@ int64_t Utils::timeDaySeconds()
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));
}

View File

@@ -8,9 +8,6 @@
#include <iomanip>
#include <functional>
#include <thread>
//#include "Crypto.h"
using namespace std;
class Utils
@@ -19,6 +16,11 @@ public:
static std::string toHex(std::vector<unsigned char>& s, int len = 0);
static std::string toHex(const std::string& s);
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(float v, int precision = 2);
@@ -28,12 +30,6 @@ public:
static float toFloat(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>
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 utf8ToGbk(string s);
static void sleep_ms(int ms);
static void sleepMS(int ms);
static int random(int min, int max);
@@ -96,8 +92,6 @@ public:
class TimeTick
{
public:
int64_t tickMS_ = 0;
TimeTick(int t=0)
{
if (t !=0) { tickMS_ = Utils::time(); }
@@ -105,19 +99,16 @@ public:
bool elapse(int64_t second, bool reset = true)
{
auto tick_now = Utils::time();
bool res = tick_now - tickMS_ > second;
if (res && reset)
{
tickMS_ = tick_now;
}
return res;
auto tickNow = Utils::time();
bool ret = tickNow - tickMS_ > second;
if (ret && reset) { tickMS_ = tickNow; }
return ret;
}
void reset()
{
tickMS_ = Utils::time();
}
void reset() { tickMS_ = Utils::time(); }
public:
int64_t tickMS_ = 0;
};
#endif // !!! _Utils_H_

View File

@@ -167,10 +167,27 @@ void OpensslSM2_test()
int main(int argc, char** argv)
{
stringstream ss;
{
stringstream ss;
float v = 3.123456;
float ratio = 0.1;
std::cout << Utils::toStr(v, 0) << std::endl;
std::cout << Utils::toStr(v, 1) << std::endl;
ss << "(" << setw(2) << setfill('0') << 1;
std::cout << ss.str();
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 编码
SetConsoleOutputCP(CP_UTF8);

View File

@@ -13,10 +13,9 @@
MainApp::MainApp()
{
// 设置背景色
QPalette palette(this->palette());
// 设置背景为黑色
palette.setColor(QPalette::Window, QColor(1, 32, 54));
palette.setColor(QPalette::Window, QColor(11, 33, 77));
this->setAutoFillBackground(true);
this->setPalette(palette);
this->setStyleSheet("color: white;");
@@ -59,6 +58,7 @@ void MainApp::initMenu()
ui.labelDT = std::make_shared< QLabel>();
ui.labelDT->setAlignment(Qt::AlignCenter);
ui.labelDT->setText(Utils::timeStr().c_str());
ui.labelDT->setFont(QFont("微软雅黑", 14));
ui.layoutMenu->addWidget(ui.labelDT.get(), 0, 0, 1, 1);
// 设置列宽和行高
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; }";
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 =
"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);}";
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 = // 表格整体样式
"QTableWidget {"
@@ -70,6 +72,13 @@ MyWidget::MyWidget(QWidget* parent) : QWidget(parent)
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)
{

View File

@@ -81,6 +81,8 @@ using MyPairLabelLine = pair<shared_ptr<QLabel>, shared_ptr<QLineEdit>>;
class MyQUI
{
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 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);
}
logFilter = MyQUI::PairLine(this, 10, y += 270, "日志过滤: ", "", false);
btnLogClean = std::make_shared<QPushButton>("清除", this);
btnLogClean->setGeometry(400, y, 80, 26);
logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
connect(btnLogClean.get(), &QPushButton::clicked, this, [=]() { texteditLog->clear(); });
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->setReadOnly(true);
texteditLog->document()->setMaximumBlockCount(1000);