mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-27 18:59:26 +08:00
添加Openssl,Gmssl加密库
This commit is contained in:
@@ -71,6 +71,7 @@ include_directories(
|
||||
${THIRDPARTY_PATH}/spdlog-1.13.0/include
|
||||
${THIRDPARTY_PATH}/OpenXLSX/include
|
||||
${THIRDPARTY_PATH}/GmSSL-3.1.1/include
|
||||
${THIRDPARTY_PATH}/OpenSSL-3.5.3/include
|
||||
#${PVLIBS_PATH}/include/pvserver
|
||||
#${PVLIBS_PATH}/include/rllib
|
||||
)
|
||||
@@ -108,7 +109,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||
${THIRDPARTY_PATH}/paho_mqtt/lib/paho-mqtt3c.lib
|
||||
${THIRDPARTY_PATH}/OpenXLSX/lib/OpenXLSX.lib
|
||||
${THIRDPARTY_PATH}/GmSSL-3.1.1/lib/gmssl.lib
|
||||
${THIRDPARTY_PATH}/OpenSSL-3.5.3/lib/VC/x64/MD/libcrypto.lib
|
||||
#${PVLIBS_PATH}/x64/serverlib.lib
|
||||
#${PVLIBS_PATH}/x64/rllib.lib
|
||||
|
||||
)
|
||||
@@ -115,7 +115,7 @@ void Application::runThreadStat()
|
||||
while (!isQuit)
|
||||
{
|
||||
static TimeTick ttStat(1);
|
||||
if(ttStat.elapse(10))
|
||||
if(Config::option.stat.enabled && ttStat.elapse(Config::option.stat.interval))
|
||||
{
|
||||
// 设备历史数据(电压、电流、功率),存储到 history_day
|
||||
// 统计数据,存储到 stat_day
|
||||
|
||||
@@ -24,6 +24,7 @@ bool Config::init(std::string filename)
|
||||
JSON::read(jsonroot, "weburl", option.webSrvUrl);
|
||||
JSON::read(jsonroot, "launchdate", option.lunchDate);
|
||||
JSON::read(jsonroot, "exportpath", option.exportpath);
|
||||
JSON::read(jsonroot, "windowEnabled", option.windowEnabled);
|
||||
|
||||
if (jsonroot.contains("database"))
|
||||
{
|
||||
@@ -110,6 +111,14 @@ bool Config::init(std::string filename)
|
||||
JSON::read(jsonItem, "enabled", info.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonroot.contains("statistics"))
|
||||
{
|
||||
njson& json = jsonroot["statistics"];
|
||||
JSON::read(json, "enabled", option.stat.enabled);
|
||||
JSON::read(json, "interval", option.stat.interval);
|
||||
if (option.stat.interval <= 0) { option.stat.interval = 60; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ struct AppOption
|
||||
|
||||
std::map<std::string, VideoInfo> mapVideo;
|
||||
|
||||
int windowEnabled {0};
|
||||
|
||||
struct {
|
||||
int enabled {0};
|
||||
int interval {60};
|
||||
} stat;
|
||||
};
|
||||
|
||||
class Config
|
||||
|
||||
@@ -2,18 +2,8 @@
|
||||
#include "common/JsonN.h"
|
||||
#include "common/Utils.h"
|
||||
|
||||
std::string REGAddrOffset(std::string addr, int offset)
|
||||
{
|
||||
unsigned int val;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << addr;
|
||||
ss >> val;
|
||||
return Utils::toHexStr(val + offset);
|
||||
}
|
||||
|
||||
std::map<std::string, std::map<std::string, RegAddrUnit>> REGAddr::s_mapReg;
|
||||
|
||||
|
||||
void REGAddr::load(std::string filename)
|
||||
{
|
||||
njson json;
|
||||
|
||||
@@ -32,7 +32,7 @@ enum class EDeviceType
|
||||
PCU = 103, //103 PCU 1
|
||||
BMS = 104, //104 BMS 1
|
||||
BCU = 105, //105 BCU 1
|
||||
//106 充电桩 2
|
||||
CHARGER = 106, //106 充电桩 2
|
||||
//107 充电枪 2
|
||||
//108 集中器 2
|
||||
//109 光伏板 3
|
||||
|
||||
@@ -241,16 +241,16 @@ bool Device::cache(int npos)
|
||||
if (iter != s_mapDeviceAddrCurve.end())
|
||||
{
|
||||
auto& vecAddr = iter->second;
|
||||
auto size = addrV.size();
|
||||
auto size = vecAddr.size();
|
||||
if (size >= 1) { addrV = vecAddr[0]; }
|
||||
else if (size >= 2) { addrI = vecAddr[1]; }
|
||||
else if (size >= 3) { addrP = vecAddr[2]; }
|
||||
if (size >= 2) { addrI = vecAddr[1]; }
|
||||
if (size >= 3) { addrP = vecAddr[2]; }
|
||||
}
|
||||
|
||||
// 根据设备类型从参数(寄存器地址)中读取实时数据进行保存
|
||||
int U = Utils::toInt(this->getParam(addrV, "0"));
|
||||
int I = Utils::toInt(this->getParam(addrI, "0"));
|
||||
int P = addrP.empty() ? U*I : Utils::toInt(this->getParam(addrP, "0"));
|
||||
int P = addrP.empty() ? U*I*0.001 : Utils::toInt(this->getParam(addrP, "0"));
|
||||
mapCacheVoltage[npos] = U;
|
||||
mapCacheCurrent[npos] = I;
|
||||
mapCachePower[npos] = P;
|
||||
@@ -299,33 +299,33 @@ void Device::setParam(std::string k, int v)
|
||||
{
|
||||
running = 1;
|
||||
}
|
||||
else if (type == 101) // EMS
|
||||
else if (type == int(EDeviceType::EMS)) // 101 EMS
|
||||
{
|
||||
running = 1;
|
||||
}
|
||||
else if (type == 102) // PCS
|
||||
else if (type == int(EDeviceType::PCS)) // 102 PCS
|
||||
{
|
||||
if (k == "0x1003") err = v; // 故障状态 R uint16 1故障,0正常 0 0x1003
|
||||
else if (k == "0x1005") online = v; // 设备在线 R uint16 1在线,0无效 1 0x1005
|
||||
else if (k == "0x1009") running = (v==1 || v==2); //充放状态 R uint16 0:待机, 1:充电, 2:放电, 3:搁置 0 0x1009
|
||||
}
|
||||
else if (type == 103) // PCU
|
||||
else if (type == int(EDeviceType::PCU)) // 103 PCU
|
||||
{
|
||||
if (k == "0x1002") err = v; //故障状态 R uint16 1故障,0正常 0 0x1002
|
||||
else if (k == "0x1004") online = v; //设备在线 R uint16 1在线,0无效 1 0x1004
|
||||
else if (k == "0x1006") running = v; //启停状态 R uint16 1开机,0关机 1 0x1006
|
||||
}
|
||||
else if (type == 104) // BMS
|
||||
else if (type == int(EDeviceType::BMS)) // 104 BMS
|
||||
{
|
||||
if (k == "0x004A") { err = (v==1); } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x004A
|
||||
else if (k == "0x004B") running = (v==1 || v==2); //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004B
|
||||
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
|
||||
{
|
||||
if (k == "0xA003") { running = (v==0x33 || v==0x44); } //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003
|
||||
else if (k == "0xA004") { err = (v==0x55); } //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004
|
||||
}
|
||||
else if (type == 106) // 充电桩
|
||||
else if (type == int(EDeviceType::CHARGER)) // 106 充电桩
|
||||
{
|
||||
if (k == "21") {
|
||||
running = (mapParams["11"] == "充电" || mapParams["21"] == "充电"); // 充电状态: 0:空闲,1:充电
|
||||
|
||||
@@ -205,16 +205,23 @@ void Station::checkDevice()
|
||||
}
|
||||
}
|
||||
|
||||
void Station::readAlert(std::shared_ptr<Device> device, int v, std::string text)
|
||||
void Station::readAlert(std::shared_ptr<Device> device, std::string addr, int v, std::string text)
|
||||
{
|
||||
Fields fields;
|
||||
fields.set("log_id", Snowflake::instance().getIdStr());
|
||||
if (device) { fields.set("device_id", device->deviceId); }
|
||||
fields.set("type", int(EAlertType::DEVICE));
|
||||
fields.set("context", text + ":故障(" + std::to_string(v) + ")");
|
||||
fields.set("status", 1);
|
||||
auto dao = DaoEntity::create("log_alert");
|
||||
dao->insertFields(fields);
|
||||
int64_t ts = Utils::time();
|
||||
std::string alertId = std::to_string(device->deviceId) + "_" + addr;
|
||||
int tsCache = mapAlertCache[alertId];
|
||||
if (ts - tsCache > 60*5)
|
||||
{
|
||||
Fields fields;
|
||||
fields.set("log_id", Snowflake::instance().getIdStr());
|
||||
if (device) { fields.set("device_id", device->deviceId); }
|
||||
fields.set("type", int(EAlertType::DEVICE));
|
||||
fields.set("content", text + ":故障(" + std::to_string(v) + ")");
|
||||
fields.set("status", 1);
|
||||
auto dao = DaoEntity::create("log_alert");
|
||||
dao->insertFields(fields);
|
||||
mapAlertCache[alertId] = ts;
|
||||
}
|
||||
}
|
||||
|
||||
void Station::readRuntimeData(int deviceNo, string addr, int val)
|
||||
@@ -360,12 +367,13 @@ void Station::writeStatistic()
|
||||
std::string dt = Utils::dateStr();
|
||||
int64_t tTime = Utils::time();
|
||||
int64_t tDate = Utils::date();
|
||||
int64_t tDelta = tTime - tDate;
|
||||
int npos = (tTime-tDate) / 600;
|
||||
|
||||
for (auto iter = mapDevice.begin(); iter!=mapDevice.end(); ++iter)
|
||||
{
|
||||
auto device = iter->second;
|
||||
if (device->cache(npos))
|
||||
if (device->cache(npos) && device->type == int(EDeviceType::BMS))
|
||||
{
|
||||
Fields fields;
|
||||
fields.set("dt", dt);
|
||||
@@ -391,7 +399,6 @@ void Station::writeStatistic()
|
||||
Fields fields;
|
||||
fields.set("dt", Utils::dateStr(statData.ts));
|
||||
fields.set("station_id", this->stationId);
|
||||
fields.set("category", 1);
|
||||
fields.set("device_id", 0);
|
||||
fields.set("elect_in", statData.dayElectIn);
|
||||
fields.set("elect_out", statData.dayElectOut);
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
void setGarewayWorkMode();
|
||||
void checkDevice();
|
||||
|
||||
void readAlert(std::shared_ptr<Device> device, int v, std::string text);
|
||||
void readAlert(std::shared_ptr<Device> device, std::string addr, int v, std::string text);
|
||||
void readRuntimeData(int deviceNo, string addr, int val);
|
||||
void readTHData(int deviceNo, string addr, int val);
|
||||
void readFire40Data(int deviceNo, string addr, int val);
|
||||
@@ -123,6 +123,7 @@ public:
|
||||
void readGatewayStatus(int cdzStatus, int emuStatus);
|
||||
|
||||
void writeStatistic();
|
||||
int posDayStat {0};
|
||||
|
||||
public:
|
||||
int stationId {};
|
||||
@@ -244,4 +245,6 @@ public:
|
||||
|
||||
int cdzStatus {-1};
|
||||
int emuStatus {-1};
|
||||
|
||||
std::map<std::string, int64_t> mapAlertCache;
|
||||
};
|
||||
@@ -150,6 +150,79 @@ string Crypto::md5(string src)
|
||||
return md5_format(tempA) + md5_format(tempB) + md5_format(tempC) + md5_format(tempD);
|
||||
}
|
||||
|
||||
#include "common/Utils.h"
|
||||
|
||||
static std::vector<uint8_t> hexToByte(const std::string& hexstr)
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
v.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)));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
std::string Crypto::gmssl_sm2Encrypt(std::string pubKeyHex, std::string priKeyHex, std::string plainByte)
|
||||
{
|
||||
std::vector<uint8_t> pub_key = hexToByte(pubKeyHex);
|
||||
|
||||
std::vector<uint8_t> pri_keyBuf = hexToByte(priKeyHex);
|
||||
sm2_z256_t pri_key {0};
|
||||
sm2_z256_from_bytes(pri_key, pri_keyBuf.data());
|
||||
|
||||
SM2_KEY sm2k;
|
||||
sm2_key_set_public_key(&sm2k, (SM2_Z256_POINT*)pub_key.data()); // +1 跳过 0x04 标记
|
||||
sm2_key_set_private_key(&sm2k, pri_key);
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2k);
|
||||
|
||||
//std::vector<uint8_t> plainText(plainByte.begin(), plainByte.end());
|
||||
std::vector<uint8_t> ciphertext(SM2_MAX_CIPHERTEXT_SIZE);
|
||||
size_t ciphertext_len = 0;
|
||||
|
||||
int ret = sm2_encrypt(&sm2k, (const uint8_t*)plainByte.data(), plainByte.size(), ciphertext.data(), &ciphertext_len);
|
||||
return std::string(ciphertext.begin(), ciphertext.begin()+ciphertext_len);
|
||||
}
|
||||
|
||||
|
||||
std::string Crypto::gmssl_sm2Decrypt(std::string pubKeyHex, std::string priKeyHex, std::string cipherByte)
|
||||
{
|
||||
std::vector<uint8_t> pub_key = hexToByte(pubKeyHex);
|
||||
|
||||
std::vector<uint8_t> pri_keyBuf = hexToByte(priKeyHex);
|
||||
sm2_z256_t pri_key {0};
|
||||
sm2_z256_from_bytes(pri_key, pri_keyBuf.data());
|
||||
|
||||
SM2_KEY sm2k;
|
||||
sm2_key_set_public_key(&sm2k, (SM2_Z256_POINT*)pub_key.data()); // +1 跳过 0x04 标记
|
||||
sm2_key_set_private_key(&sm2k, pri_key);
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2k);
|
||||
|
||||
//std::string ciphertHex = "44d37f6c644f22508b5387663e3a174384917eba7ce3b2a5bb9f79e191d40dfc6c0cfaf1819af562c1ee1bffcc55d2fb1da8114527e3a6993aaadda12a26b4b6f688ecd5d7700c8bd82a069ab4b30e0b499eef82d1dfeea261d2fd19d1f0ae95a4b3fd";
|
||||
//Utils::toHex(ciphertext, ciphertext_len);
|
||||
//std::vector<uint8_t> buf = hexToByte(ciphertHex);
|
||||
std::vector<uint8_t> plainText(SM2_MAX_PLAINTEXT_SIZE);
|
||||
size_t len = 0;
|
||||
int ret = sm2_decrypt(&sm2k, (const uint8_t*)cipherByte.data(), cipherByte.size(), plainText.data(), &len);
|
||||
return std::string(plainText.begin(), plainText.begin() + len);
|
||||
}
|
||||
|
||||
|
||||
string Crypto::sm3(std::string data)
|
||||
{
|
||||
SM3_CTX ctx;
|
||||
sm3_init(&ctx);
|
||||
sm3_update(&ctx, (const unsigned char*)data.data(), data.length());
|
||||
std::vector<unsigned char> digest(SM3_DIGEST_SIZE);
|
||||
sm3_finish(&ctx, digest.data());
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < digest.size(); ++i)
|
||||
{
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Crypto::sm4EcbEncrypt(const std::vector<uint8_t>& key, const std::vector<uint8_t>& plaintext)
|
||||
{
|
||||
SM4_KEY sm4_key;
|
||||
@@ -172,4 +245,175 @@ std::vector<uint8_t> Crypto::sm4EcbDecrypt(const std::vector<uint8_t>& key, cons
|
||||
sm4_encrypt(&sm4_key, &ciphertext[i], &plaintext[i]); // 注意解密时也是用sm4_encrypt函数,但密钥是解密密钥
|
||||
}
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
|
||||
// 错误处理函数
|
||||
static void HandleOpensslError()
|
||||
{
|
||||
ERR_print_errors_fp(stderr);
|
||||
unsigned long err = ERR_get_error();
|
||||
}
|
||||
|
||||
// SM2 加密函数
|
||||
std::string Crypto::ssl_sm2Encrypt(const std::string& public_key_hex, const std::string& plaintext)
|
||||
{
|
||||
EVP_PKEY* pubkey = Crypto::create_sm2_public_key_from_hex(public_key_hex);
|
||||
|
||||
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pubkey, NULL);
|
||||
if (!ctx) HandleOpensslError();
|
||||
|
||||
if (EVP_PKEY_encrypt_init(ctx) <= 0) HandleOpensslError();
|
||||
|
||||
// 获取加密后数据的长度
|
||||
size_t ciphertext_len;
|
||||
if (EVP_PKEY_encrypt(ctx, NULL, &ciphertext_len, (const uint8_t*)plaintext.data(), plaintext.size()) <= 0) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 执行加密
|
||||
std::vector<unsigned char> ciphertext(ciphertext_len);
|
||||
if (EVP_PKEY_encrypt(ctx, ciphertext.data(), &ciphertext_len, (const uint8_t*)plaintext.data(), plaintext.size()) <= 0) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pubkey);
|
||||
// 清理 OpenSSL
|
||||
EVP_cleanup();
|
||||
ERR_free_strings();
|
||||
|
||||
return std::string(ciphertext.begin(), ciphertext.begin() + ciphertext_len);
|
||||
}
|
||||
|
||||
// SM2 解密函数
|
||||
std::string Crypto::ssl_sm2Decrypt(const std::string& private_key_hex, const std::string& ciphertext)
|
||||
{
|
||||
EVP_PKEY* privkey = Crypto::create_sm2_private_key_from_hex(private_key_hex);
|
||||
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(privkey, NULL);
|
||||
if (!ctx) HandleOpensslError();
|
||||
|
||||
if (EVP_PKEY_decrypt_init(ctx) <= 0) HandleOpensslError();
|
||||
|
||||
// 获取解密后数据的长度
|
||||
size_t plaintext_len;
|
||||
if (EVP_PKEY_decrypt(ctx, NULL, &plaintext_len, (const uint8_t*)ciphertext.data(), ciphertext.size()) <= 0) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 执行解密
|
||||
std::vector<unsigned char> plaintext(plaintext_len);
|
||||
if (EVP_PKEY_decrypt(ctx, plaintext.data(), &plaintext_len, (const uint8_t*)ciphertext.data(), ciphertext.size()) <= 0) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(privkey);
|
||||
|
||||
// 清理 OpenSSL
|
||||
EVP_cleanup();
|
||||
ERR_free_strings();
|
||||
|
||||
return std::string(plaintext.begin(), plaintext.begin() + plaintext_len);
|
||||
}
|
||||
|
||||
// 将16进制字符串转换为字节数组
|
||||
static std::vector<unsigned char> hexToBytes(const std::string& hex) {
|
||||
std::vector<unsigned char> bytes;
|
||||
for (size_t i = 0; i < hex.length(); i += 2)
|
||||
{
|
||||
std::string byteString = hex.substr(i, 2);
|
||||
unsigned char byte = static_cast<unsigned char>(strtol(byteString.c_str(), NULL, 16));
|
||||
bytes.push_back(byte);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// 从16进制字符串创建SM2私钥
|
||||
EVP_PKEY* Crypto::create_sm2_private_key_from_hex(const std::string& private_key_hex)
|
||||
{
|
||||
// 将16进制私钥转换为字节
|
||||
std::vector<unsigned char> private_key_bytes = hexToBytes(private_key_hex);
|
||||
|
||||
// 创建BIGNUM
|
||||
BIGNUM* privBN = BN_bin2bn(private_key_bytes.data(), private_key_bytes.size(), NULL);
|
||||
if (!privBN) HandleOpensslError();
|
||||
|
||||
// 创建EC_KEY并设置曲线和私钥
|
||||
EC_KEY* ecKey = EC_KEY_new_by_curve_name(NID_sm2);
|
||||
if (!ecKey) HandleOpensslError();
|
||||
|
||||
if (!EC_KEY_set_private_key(ecKey, privBN)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 计算公钥
|
||||
const EC_GROUP* group = EC_KEY_get0_group(ecKey);
|
||||
EC_POINT* pub_point = EC_POINT_new(group);
|
||||
if (!pub_point) HandleOpensslError();
|
||||
|
||||
if (!EC_POINT_mul(group, pub_point, privBN, NULL, NULL, NULL)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_public_key(ecKey, pub_point)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 创建EVP_PKEY
|
||||
EVP_PKEY* pkey = EVP_PKEY_new();
|
||||
if (!pkey) HandleOpensslError();
|
||||
|
||||
if (!EVP_PKEY_set1_EC_KEY(pkey, ecKey)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
BN_free(privBN);
|
||||
EC_POINT_free(pub_point);
|
||||
EC_KEY_free(ecKey);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 从16进制字符串创建SM2公钥
|
||||
EVP_PKEY* Crypto::create_sm2_public_key_from_hex(const std::string& public_key_hex)
|
||||
{
|
||||
// 将16进制公钥转换为字节
|
||||
std::vector<unsigned char> public_key_bytes = hexToBytes(public_key_hex);
|
||||
|
||||
// 创建EC_KEY
|
||||
EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_sm2);
|
||||
if (!ec_key) HandleOpensslError();
|
||||
|
||||
// 从字节创建公钥点
|
||||
const EC_GROUP* group = EC_KEY_get0_group(ec_key);
|
||||
EC_POINT* pub_point = EC_POINT_new(group);
|
||||
if (!pub_point) HandleOpensslError();
|
||||
|
||||
if (!EC_POINT_oct2point(group, pub_point, public_key_bytes.data(), public_key_bytes.size(), NULL)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_public_key(ec_key, pub_point)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 创建EVP_PKEY
|
||||
EVP_PKEY* pkey = EVP_PKEY_new();
|
||||
if (!pkey) HandleOpensslError();
|
||||
|
||||
if (!EVP_PKEY_set1_EC_KEY(pkey, ec_key)) {
|
||||
HandleOpensslError();
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
EC_POINT_free(pub_point);
|
||||
EC_KEY_free(ec_key);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
@@ -1,14 +1,29 @@
|
||||
#ifndef _Crypto_H_
|
||||
#define _Crypto_H_
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -16,7 +31,14 @@ using namespace std;
|
||||
class Crypto
|
||||
{
|
||||
public:
|
||||
static string md5(string src);
|
||||
static string md5(string data);
|
||||
|
||||
static string sm3(std::string data);
|
||||
|
||||
|
||||
static std::string gmssl_sm2Encrypt(std::string pubKeyHex, std::string priKeyHex, std::string plain);
|
||||
static std::string gmssl_sm2Decrypt(std::string pubKeyHex, std::string priKeyHex, std::string cipher);
|
||||
|
||||
|
||||
/**
|
||||
* @brief SM4-ECB 加密示例
|
||||
@@ -33,6 +55,13 @@ public:
|
||||
* @return 明文字节向量
|
||||
*/
|
||||
static std::vector<uint8_t> sm4EcbDecrypt(const std::vector<uint8_t>& key, const std::vector<uint8_t>& ciphertext);
|
||||
|
||||
|
||||
static std::string ssl_sm2Encrypt(const std::string& public_key_hex, const std::string& plaintext);
|
||||
static std::string ssl_sm2Decrypt(const std::string& private_key_hex, const std::string& ciphertext);
|
||||
|
||||
static EVP_PKEY* create_sm2_private_key_from_hex(const std::string& private_key_hex);
|
||||
static EVP_PKEY* create_sm2_public_key_from_hex(const std::string& public_key_hex);
|
||||
};
|
||||
|
||||
#endif // ! _Crypto_H_
|
||||
@@ -6,6 +6,36 @@
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
std::string Utils::toHex(std::vector<unsigned char>& s, int len/*=0*/)
|
||||
{
|
||||
if (len == 0) len = s.size();
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << (int)s[i];
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
std::string Utils::toHex(const std::string& s)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < s.size(); ++i)
|
||||
{
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << (int)static_cast<unsigned char>(s[i]);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
std::string Utils::fromHex(const std::string& hexstr)
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
v.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)));
|
||||
}
|
||||
return std::string(v.begin(), v.end());
|
||||
}
|
||||
|
||||
string Utils::toStr(int v)
|
||||
{
|
||||
return std::to_string(v);
|
||||
@@ -499,9 +529,3 @@ std::string Utils::readFile(std::string filename)
|
||||
}
|
||||
|
||||
|
||||
std::string Utils::toHexStr(int64_t val)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::uppercase << setw(4) << setfill('0') << std::hex << val;
|
||||
return ss.str();
|
||||
}
|
||||
@@ -16,6 +16,10 @@ using namespace std;
|
||||
class Utils
|
||||
{
|
||||
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 toStr(int v);
|
||||
static string toStr(float v, int precision = 2);
|
||||
static string toStr(double v, int precision = 2);
|
||||
@@ -85,8 +89,6 @@ public:
|
||||
static void split(string buf, string c, vector<string>& res);
|
||||
|
||||
static std::string readFile(std::string filename);
|
||||
|
||||
static std::string toHexStr(int64_t val);
|
||||
};
|
||||
|
||||
class TimeTick
|
||||
|
||||
258
src/main.cpp
258
src/main.cpp
@@ -1,130 +1,179 @@
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QtWebEngineWidgets/QtWebEngineWidgets>
|
||||
#include <filesystem>
|
||||
|
||||
#include "common/Utils.h"
|
||||
#include "common/Snowflake.h"
|
||||
#include "common/JsonN.h"
|
||||
|
||||
#include "app/Application.h"
|
||||
#include "app/Config.h"
|
||||
#include "protocol/TcpEntity.h"
|
||||
|
||||
#include "widgets/MainWindow.h"
|
||||
|
||||
|
||||
#include "common/Spdlogger.h"
|
||||
#include "database/DaoEntity.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "DataStruct.h"
|
||||
#include <filesystem>
|
||||
#include <QApplication>
|
||||
#include <QtWebEngineWidgets/QtWebEngineWidgets>
|
||||
|
||||
#include "qt/MainWeb.h"
|
||||
#include "common/Utils.h"
|
||||
#include "common/Snowflake.h"
|
||||
#include "common/JsonN.h"
|
||||
#include "common/Spdlogger.h"
|
||||
#include "common/XlsxEntity.h"
|
||||
#include "common/Crypto.h"
|
||||
|
||||
#include "app/Application.h"
|
||||
#include "app/Config.h"
|
||||
#include "app/DataStruct.h"
|
||||
|
||||
#include "database/Dao.h"
|
||||
#include "common/XlsxEntity.h"
|
||||
#include "protocol/TcpEntity.h"
|
||||
#include "widgets/MainWindow.h"
|
||||
#include "qt/MainWeb.h"
|
||||
#include "qt/MainApp.h"
|
||||
|
||||
void memberJsonTest()
|
||||
int SM2_test()
|
||||
{
|
||||
std::string fromJson = "fromJson(const std::string& str) {\nNJsonNode jsonroot;\nauto ret = NJson::parse(str, jsonroot);\nif (!ret) { return; }\n";
|
||||
std::string toJson = "toJson() {\nNJsonNode jsonroot;";
|
||||
// 未压缩格式(最常见)
|
||||
// 前缀 : 04 (1字节) X坐标 : 32字节(64个十六进制字符), Y坐标 : 32字节(64个十六进制字符),总长度 : 1 + 32 + 32 = 65字节 = 130个十六进制字符
|
||||
std::string hex_pub_key = "04661013d0b881d817085a251f0c0a7024e72c76e6eb0fd22c0170a508b123864ef7514df30cecb45deecf9b35810d0315b5164d63199c971ac3323c228ab48606";
|
||||
std::string hex_pri_key = "b935087295c448b221abc571d88018ee9d037407c32aa4d7fbf627a143ad86a0";
|
||||
|
||||
std::ifstream ifs("", std::ios::in);
|
||||
std::string line;
|
||||
std::string cpp = "#include \"DataStruct.h\"\n\n";
|
||||
if (ifs.is_open())
|
||||
{
|
||||
std::string s1;
|
||||
std::string s2;
|
||||
while (std::getline(ifs, line))
|
||||
{
|
||||
int pos = line.find("struct");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::string className = line.substr(pos+7);
|
||||
s1 = "void " + className + "::" + fromJson;
|
||||
s2 = "}\nstd::string " + className + "::" + toJson;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string key;
|
||||
pos = line.find("uint");
|
||||
if (pos != std::string::npos) { key = line.substr(pos+9); }
|
||||
if (!key.empty())
|
||||
{
|
||||
pos = key.find(";");
|
||||
if (pos != std::string::npos) { key = key.substr(0, pos); }
|
||||
}
|
||||
if (!key.empty())
|
||||
{
|
||||
s1 += ("NJson::read(jsonroot, \"" + key + "\", " + key + ");\n");
|
||||
s2 += ("jsonroot[\"" + key + "\"] = " + key + ";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
ifs.close();
|
||||
}
|
||||
std::string cipherText = Crypto::gmssl_sm2Encrypt(hex_pub_key, hex_pri_key, "123456");
|
||||
std::cout << "加密: " << Utils::toHex(cipherText) << std::endl;
|
||||
|
||||
|
||||
//std::string strTmp = R"()";
|
||||
//std::vector<std::string> vecTmp;
|
||||
//Utils::split(strTmp, "\n", vecTmp);
|
||||
std::string text = "306f022100f180bb383cddea024dfb6fea6c321f4b6901a468646df3da7d0040ebf107199f022009c363df8958c037f658da7060d429647802ac40560140e79685884a38f81cb10420783eb5b893994afdf7f68e2123e0c6e9469b3ea1f26297cb2b8e9cf6e27162a60406f99e4cbe6655";
|
||||
std::string plainText = Crypto::gmssl_sm2Decrypt(hex_pub_key, hex_pri_key, Utils::fromHex(text));
|
||||
std::cout << "解密: " << plainText << std::endl;
|
||||
|
||||
//std::string from = "void fromJson(const std::string& str) {\nNJsonNode jsonroot;\nauto ret = NJson::parse(str, jsonroot);\nif (!ret) { return; }\n";
|
||||
//std::string to = "std::string toJson() {\nNJsonNode jsonroot;";
|
||||
//for (auto& item: vecTmp)
|
||||
//{
|
||||
// std::string key;
|
||||
// int pos = item.find_first_of("_");
|
||||
// if (pos != std::string::npos) { key = item.substr(pos+3); }
|
||||
// pos = key.find_first_of(";");
|
||||
// if (pos != std::string::npos) { key = key.substr(0, pos); }
|
||||
// SM2_KEY sm2k;
|
||||
|
||||
// if (!key.empty())
|
||||
// FILE* f = fopen("D:/sm2pub.pem", "rb");
|
||||
// if (f)
|
||||
// {
|
||||
// from += ("NJson::read(jsonroot, \"" + key + "\", " + key + ");\n");
|
||||
// to += ("jsonroot[\"" + key + "\"] = " + key + ";\n");
|
||||
// sm2_public_key_info_from_pem(&sm2k, f);
|
||||
// std::vector<uint8_t> plainText(SM2_MAX_PLAINTEXT_SIZE);
|
||||
// std::vector<uint8_t> ciphertext(SM2_MAX_CIPHERTEXT_SIZE);
|
||||
// size_t ciphertext_len = -1;
|
||||
// int ret = sm2_encrypt(&sm2k, plainText.data(), plainText.size(), ciphertext.data(), &ciphertext_len);
|
||||
// std::cout << "加密: " << Utils::toHex(ciphertext, ciphertext_len) << std::endl;
|
||||
// }
|
||||
|
||||
// FILE* f1 = fopen("D:/sm2.pem", "rb");
|
||||
// if (f1)
|
||||
// {
|
||||
// sm2_private_key_info_from_pem(&sm2k, f1);
|
||||
// }
|
||||
// sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2k);
|
||||
|
||||
// std::cout << "";
|
||||
//}
|
||||
//from += "}";
|
||||
//to += "return jsonroot.dump();\n}";
|
||||
//std::cout << from << std::endl;
|
||||
//std::cout << to << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#include "common/Crypto.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
// 错误处理函数
|
||||
void HandleOpensslError() {
|
||||
ERR_print_errors_fp(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// 将16进制字符串转换为字节数组
|
||||
std::vector<unsigned char> hexToBytes(const std::string& hex) {
|
||||
std::vector<unsigned char> bytes;
|
||||
|
||||
for (size_t i = 0; i < hex.length(); i += 2) {
|
||||
std::string byteString = hex.substr(i, 2);
|
||||
unsigned char byte = static_cast<unsigned char>(strtol(byteString.c_str(), NULL, 16));
|
||||
bytes.push_back(byte);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// 将字节数组转换为16进制字符串
|
||||
std::string bytes_to_hex(const std::vector<unsigned char>& bytes) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
|
||||
for (unsigned char byte : bytes) {
|
||||
ss << std::setw(2) << static_cast<unsigned int>(byte);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void OpensslSM2_test()
|
||||
{
|
||||
// 初始化 OpenSSL
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
// 示例16进制密钥
|
||||
std::string private_key_hex = "b935087295c448b221abc571d88018ee9d037407c32aa4d7fbf627a143ad86a0";
|
||||
std::string public_key_hex = "04661013d0b881d817085a251f0c0a7024e72c76e6eb0fd22c0170a508b123864ef7514df30cecb45deecf9b35810d0315b5164d63199c971ac3323c228ab48606";
|
||||
|
||||
// 要加密的明文
|
||||
std::string plaintext = "123";
|
||||
|
||||
std::cout << "Original text: " << plaintext << std::endl;
|
||||
std::cout << "Private key (hex): " << private_key_hex << std::endl;
|
||||
std::cout << "Public key (hex): " << public_key_hex << std::endl;
|
||||
|
||||
// 加密
|
||||
auto ciphertext = Crypto::ssl_sm2Encrypt(public_key_hex, plaintext);
|
||||
std::cout << "Ciphertext (hex): " << Utils::toHex(ciphertext) << std::endl;
|
||||
|
||||
// 解密^
|
||||
auto decryptedText = Crypto::ssl_sm2Decrypt(private_key_hex, ciphertext);
|
||||
std::cout << "Decrypted text: " << decryptedText << std::endl;
|
||||
|
||||
// 验证加解密是否正确
|
||||
if (plaintext == decryptedText) {
|
||||
std::cout << "SM2 encryption and decryption successful!" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "SM2 encryption and decryption failed!" << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
// 未压缩格式(最常见)
|
||||
// 前缀 : 04 (1字节) X坐标 : 32字节(64个十六进制字符), Y坐标 : 32字节(64个十六进制字符),总长度 : 1 + 32 + 32 = 65字节 = 130个十六进制字符
|
||||
//std::string private_key_hex = "04661013d0b881d817085a251f0c0a7024e72c76e6eb0fd22c0170a508b123864ef7514df30cecb45deecf9b35810d0315b5164d63199c971ac3323c228ab48606";
|
||||
//std::string public_key_hex = "b935087295c448b221abc571d88018ee9d037407c32aa4d7fbf627a143ad86a0";
|
||||
|
||||
//std::string cipherText = Crypto::sm2Encrypt(public_key_hex, private_key_hex, "123456");
|
||||
//std::cout << "加密: " << Utils::toHex(cipherText) << std::endl;
|
||||
|
||||
std::string text(ciphertext.begin(), ciphertext.end());
|
||||
//std::string textHex = "306f022100f180bb383cddea024dfb6fea6c321f4b6901a468646df3da7d0040ebf107199f022009c363df8958c037f658da7060d429647802ac40560140e79685884a38f81cb10420783eb5b893994afdf7f68e2123e0c6e9469b3ea1f26297cb2b8e9cf6e27162a60406f99e4cbe6655";
|
||||
//std::string text = Utils::fromHex(text);
|
||||
std::string plainText = Crypto::gmssl_sm2Decrypt(public_key_hex, private_key_hex, text);
|
||||
std::cout << "解密: " << plainText << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// 示例密钥 (16字节)
|
||||
std::string key = "1234567890123456";
|
||||
// 示例明文 (必须是16字节的整数倍,本例为16字节)
|
||||
std::string plaintext = "HelloWorld";
|
||||
|
||||
// 加密
|
||||
auto encryptText = Crypto::sm4EcbEncrypt(vector<uint8_t>(key.begin(), key.end()), vector<uint8_t>(plaintext.begin(), plaintext.end()));
|
||||
// 解密
|
||||
auto decryptText = Crypto::sm4EcbDecrypt(vector<uint8_t>(key.begin(), key.end()), encryptText);
|
||||
|
||||
// 输出十六进制结果
|
||||
std::cout << "Original: " << plaintext << std::endl;
|
||||
std::cout << "Encrypted: " << std::string(encryptText.begin(), encryptText.end()) << std::endl;
|
||||
std::cout << "Decrypted: " << std::string(decryptText.begin(), decryptText.end()) << std::endl;
|
||||
|
||||
// 设置控制台输出为 UTF-8 编码
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
// 设置控制台输入为 UTF-8 编码(如果需要输入中文)
|
||||
SetConsoleCP(CP_UTF8);
|
||||
|
||||
//OpensslSM2_test();
|
||||
//SM2_test();
|
||||
|
||||
// 初始化日志
|
||||
Spdlogger::init(spdlog::level::info, "");
|
||||
spdlog::info("[main] start ... ======================================================================");
|
||||
@@ -133,7 +182,24 @@ int main(int argc, char** argv)
|
||||
// 运行后台服务
|
||||
Application::instance().init();
|
||||
|
||||
while (1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); };
|
||||
|
||||
if (Config::option.windowEnabled)
|
||||
{
|
||||
QApplication qapp(argc, argv);
|
||||
|
||||
QFont font("微软雅黑", 10, 600);
|
||||
QApplication::setFont(font);
|
||||
MainApp mainApp;
|
||||
return qapp.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 启动 PV 服务主线程
|
||||
//std::thread([=]()
|
||||
|
||||
@@ -1042,19 +1042,16 @@ Errcode HttpEntity::updateAlertLog(const httplib::Request& req, njson& json, std
|
||||
|
||||
Errcode HttpEntity::queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg)
|
||||
{
|
||||
njson jsonData = njson::array();
|
||||
|
||||
std::vector<std::string> vecStoreIn(144), vecStoreOut(144), vecCharge(144), vecSolar(144), vecSolarP(144);
|
||||
for (int i = 0; i<144; ++i)
|
||||
const int num = 144;
|
||||
std::vector<int> vecStoreIn(num, 0), vecStoreOut(num, 0), vecCharge(num, 0), vecSolar(num, 0), vecSolarP(num, 0);
|
||||
for (int i = 0; i<num; ++i)
|
||||
{
|
||||
vecStoreIn[i] = Utils::toStr(float(Utils::random(50, 100)));
|
||||
vecStoreOut[i] = Utils::toStr(float(Utils::random(50, 100)));
|
||||
vecCharge[i] = Utils::toStr(float(Utils::random(50, 100)));
|
||||
vecSolar[i] = Utils::toStr(float(Utils::random(50, 100)));
|
||||
vecSolarP[i] = Utils::toStr(float(Utils::random(50, 100)));
|
||||
vecStoreIn[i] = 0;
|
||||
vecStoreOut[i] = 0;
|
||||
vecCharge[i] = 0;
|
||||
vecSolar[i] = 0;
|
||||
vecSolarP[i] = 0;
|
||||
}
|
||||
|
||||
json["data"] = jsonData;
|
||||
json["data"] = {
|
||||
{"W_store_in", vecStoreIn},
|
||||
{"W_store_out", vecStoreOut},
|
||||
|
||||
@@ -279,7 +279,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] <<< message arrived: topic=[{},{}], len={}, payload={}", topic, msg->qos, len, payload);
|
||||
|
||||
njson json;
|
||||
bool ret = JSON::parse(payload, json);
|
||||
@@ -388,9 +388,9 @@ void MqttClient::ParseArrivedMessage(njson& json, string command, std::shared_pt
|
||||
{
|
||||
auto addr = iter->first;
|
||||
auto& regUnit = iter->second;
|
||||
if (regUnit.alert && val>=0)
|
||||
if (regUnit.alert && val > 0)
|
||||
{
|
||||
station->readAlert(device, val, "[" + command + "]" + regUnit.name + "(" + addr + ")");
|
||||
station->readAlert(device, addr, val, "[" + command + "]" + regUnit.name + "(" + addr + ")");
|
||||
}
|
||||
|
||||
device->setParam(addr, val);
|
||||
|
||||
178
src/qt/MainApp.cpp
Normal file
178
src/qt/MainApp.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "MainApp.h"
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QPalette>
|
||||
#include <QGroupBox>
|
||||
|
||||
static const std::string QSS_BTN_MENU =
|
||||
"QPushButton{background:rgba(50,128,218,200);color:white;border-radius:5px;border:2px solid rgb(10,120,215);font:bold 18px;}"
|
||||
"QPushButton:hover{background-color:rgb(32,164,128);}"
|
||||
"QPushButton:pressed{border-width:3px 0 0 3px;background-color:rgb(1,32,54);border-style:inset;}"
|
||||
"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 rgb(18, 251, 255); border-radius: 5px; font: normal 13px; }";
|
||||
|
||||
static const std::string QSS_GROUP =
|
||||
"QGroupBox { border: 1px solid gray; margin-top: 8px; border-radius: 5px;}"
|
||||
"QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; left:10px; margin-left: 0px; padding:0 1px; }";
|
||||
|
||||
MainApp::MainApp()
|
||||
{
|
||||
QPalette palette(this->palette());
|
||||
|
||||
// 设置背景为黑色
|
||||
palette.setColor(QPalette::Window, QColor(1, 32, 54));
|
||||
this->setAutoFillBackground(true);
|
||||
this->setPalette(palette);
|
||||
this->setStyleSheet("color: white;");
|
||||
|
||||
this->resize(1440, 900);
|
||||
this->show();
|
||||
|
||||
//ui.bkg.setGeometry(0, 0, 1440, 900);
|
||||
//ui.bkg.setStyleSheet("background-color: rgb(17, 36, 102);");
|
||||
|
||||
//ui.weburl = std::make_shared<LabelPair>(this, 10, 10, 240, 30);
|
||||
//ui.weburl->setTitle("页面地址:");
|
||||
//ui.weburl->setValue("http://www.baidu.com");
|
||||
|
||||
this->setMyLayout();
|
||||
}
|
||||
|
||||
class MyMenu : public QWidget
|
||||
{
|
||||
public:
|
||||
MyMenu(QWidget* parent) : QWidget(parent), layout(this)
|
||||
{
|
||||
this->setObjectName("menu");
|
||||
this->setStyleSheet("#menu { background-color:rgba(120,120,120,80); }");
|
||||
this->show();
|
||||
vecMenuItems.reserve(20);
|
||||
|
||||
layout.setSpacing(2);
|
||||
layout.setContentsMargins(2, 2, 2, 2);
|
||||
|
||||
this->addMenuItem("系统总览");
|
||||
this->addMenuItem("运行监控");
|
||||
}
|
||||
|
||||
void addMenuItem(std::string name)
|
||||
{
|
||||
int row = vecMenuItems.size();
|
||||
auto item = std::make_shared<QPushButton>(this);
|
||||
vecMenuItems.push_back(item);
|
||||
item->setText(name.c_str());
|
||||
item->setStyleSheet(QSS_BTN_MENU.c_str());
|
||||
|
||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
item->setSizePolicy(sizePolicy);
|
||||
layout.addWidget(item.get(), row, 0, 1, 1);
|
||||
|
||||
// 设置列宽和行高
|
||||
layout.setRowMinimumHeight(row, 50); // 设置第0列的最小宽度为100像素
|
||||
// 设置列和行的伸缩因子
|
||||
layout.setRowStretch(row, 0); // 设置第0列的伸缩因子为0,不伸缩
|
||||
layout.setRowStretch(row+1, 2); // 设置第1列的伸缩因子为2,使其更宽
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<QPushButton>> vecMenuItems;
|
||||
|
||||
QGridLayout layout;
|
||||
};
|
||||
|
||||
void PairLine(QWidget* parent, int x, int y, string k, string v)
|
||||
{
|
||||
auto key = new QLabel(parent);
|
||||
key->setText(k.c_str());
|
||||
key->setGeometry(x, y, 80, 26);
|
||||
auto value = new QLineEdit(parent);
|
||||
value->setText(v.c_str());
|
||||
value->setGeometry(x+80, y, 180, 26);
|
||||
value->setStyleSheet(QSS_LINE.c_str());
|
||||
}
|
||||
|
||||
|
||||
class MyWorkspace : public QWidget
|
||||
{
|
||||
public:
|
||||
MyWorkspace(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
this->setObjectName("workspace");
|
||||
this->setStyleSheet("#workspace { background-color:rgba(100,100,100,50); }");
|
||||
|
||||
int x=10, y=10;
|
||||
{
|
||||
QGroupBox* groupBox = new QGroupBox("HTTP", this);
|
||||
groupBox->setGeometry(x, y, 300, 120);
|
||||
groupBox->setStyleSheet(QSS_GROUP.c_str());
|
||||
|
||||
PairLine(groupBox, 20, 20, "服务类型: ", "服务端");
|
||||
PairLine(groupBox, 20, 50, "服务地址: ", "92.168.0.13:17900");
|
||||
PairLine(groupBox, 20, 80, "服务状态: ", "---");
|
||||
}
|
||||
{
|
||||
x += 320;
|
||||
QGroupBox* groupBox = new QGroupBox("MQTT", this);
|
||||
groupBox->setGeometry(x, y, 300, 120);
|
||||
groupBox->setStyleSheet(QSS_GROUP.c_str());
|
||||
|
||||
PairLine(groupBox, 20, 20, "服务类型: ", "客户端");
|
||||
PairLine(groupBox, 20, 50, "服务地址: ", "92.168.0.13:17800");
|
||||
PairLine(groupBox, 20, 80, "服务状态: ", "---");
|
||||
}
|
||||
{
|
||||
x += 320;
|
||||
QGroupBox* groupBox = new QGroupBox("数据库", this);
|
||||
groupBox->setGeometry(x, y, 300, 120);
|
||||
groupBox->setStyleSheet(QSS_GROUP.c_str());
|
||||
|
||||
PairLine(groupBox, 20, 20, "数据库名: ", "ees");
|
||||
PairLine(groupBox, 20, 50, "主机地址: ", "92.168.0.13:17800");
|
||||
PairLine(groupBox, 20, 80, "用 户 名: ", "root");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void MainApp::setMyLayout()
|
||||
{
|
||||
layout.main = std::make_shared<QGridLayout>(this);
|
||||
|
||||
auto Widget = this;
|
||||
|
||||
layout.main->setObjectName(QString::fromUtf8("layout.main"));
|
||||
layout.main->setSpacing(6);
|
||||
layout.main->setContentsMargins(11, 11, 11, 11);
|
||||
//// 设置间距和边距
|
||||
//layout->setHorizontalSpacing(10); // 设置列间距为10像素
|
||||
//layout->setVerticalSpacing(10); // 设置行间距为10像素
|
||||
//layout->setContentsMargins(10, 10, 10, 10); // 设置内容边距为10像素
|
||||
|
||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
|
||||
MyMenu* menu = new MyMenu(this);
|
||||
menu->setSizePolicy(sizePolicy);
|
||||
layout.main->addWidget(menu, 0, 0, 1, 1);
|
||||
|
||||
MyWorkspace* workspace = new MyWorkspace(this);
|
||||
workspace->setSizePolicy(sizePolicy);
|
||||
layout.main->addWidget(workspace, 0, 1, 1, 1);
|
||||
|
||||
// 设置列宽和行高
|
||||
layout.main->setColumnMinimumWidth(0, 200); // 设置第0列的最小宽度为100像素
|
||||
//gridLayout->setRowMinimumHeight(0, 200); // 设置第0行的最小高度为50像素
|
||||
|
||||
// 设置列和行的伸缩因子
|
||||
layout.main->setColumnStretch(0, 0); // 设置第0列的伸缩因子为0,不伸缩
|
||||
layout.main->setColumnStretch(1, 2); // 设置第1列的伸缩因子为2,使其更宽
|
||||
//gridLayout->setRowStretch(0, 1); // 设置第0行的伸缩因子为1
|
||||
|
||||
}
|
||||
53
src/qt/MainApp.h
Normal file
53
src/qt/MainApp.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <QMainWindow>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class LabelPair
|
||||
{
|
||||
public:
|
||||
LabelPair(QWidget* parent, int x, int y, int w, int h)
|
||||
{
|
||||
title.setParent(parent);
|
||||
value.setParent(&title);
|
||||
|
||||
title.setGeometry(x, y, w, h);
|
||||
value.setGeometry(80, 0, w-80, h);
|
||||
|
||||
title.show();
|
||||
value.show();
|
||||
}
|
||||
|
||||
void setTitle(std::string text)
|
||||
{
|
||||
title.setText(text.c_str());
|
||||
}
|
||||
|
||||
void setValue(std::string text)
|
||||
{
|
||||
value.setText(text.c_str());
|
||||
}
|
||||
|
||||
QLabel title;
|
||||
QLabel value;
|
||||
};
|
||||
|
||||
class MainApp : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainApp();
|
||||
|
||||
void setMyLayout();
|
||||
|
||||
struct {
|
||||
std::shared_ptr<LabelPair> weburl {};
|
||||
} ui;
|
||||
|
||||
struct {
|
||||
std::shared_ptr<QGridLayout> main;
|
||||
} layout;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user