Compare commits

44 Commits

Author SHA1 Message Date
lnk
6056ea167a add 2025-09-16 10:13:58 +08:00
zw
729a6b8fda 暂降新增终止符识别 2025-09-16 10:10:32 +08:00
zw
c301de5aab 同步 2025-09-16 08:41:46 +08:00
zw
03a1ae4583 回调了数据默认值配置 2025-09-16 08:40:35 +08:00
lnk
f27d208959 add recall reply 2025-09-15 16:36:21 +08:00
zw
a298ff847a 调整了不存在时标的占位 -9999.0f 2025-09-15 14:00:35 +08:00
lnk
e434f66986 finish file recall 2025-09-12 17:08:25 +08:00
zw
58ffb3a6aa 处理线程添加了错误通知 2025-09-11 15:25:57 +08:00
lnk
5d20597993 fix event fun 2025-09-10 17:09:12 +08:00
lnk
124df41911 add event fun 2025-09-10 16:59:50 +08:00
zw
2ef5b69dd8 新增了补招暂态波形文件和补招稳态数据功能码 2025-09-10 13:45:47 +08:00
zw
8dd6b1f0ea 添加了状态翻转和设备在线函数 2025-09-09 13:55:29 +08:00
lnk
d526ffe415 add connect interface and log4 with code 2025-09-08 16:06:53 +08:00
zw
374dd3e7b0 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-09-08 14:37:43 +08:00
zw
1e2dcf76a0 新增暂态事件补招功能 2025-09-08 14:37:39 +08:00
lnk
9dc138a617 finish dz function 2025-09-05 16:28:26 +08:00
lnk
869189d18e add function 2025-09-04 20:59:17 +08:00
zw
722512fad6 修改了装置重连相关代码,调整了状态翻转通知方法。增加了30分钟定时对时功能。 2025-09-04 15:37:26 +08:00
zw
bf805e1238 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-09-03 08:49:45 +08:00
zw
f4c74c7d67 装置运行信息报文与装置版本配置信息报文读取 2025-09-03 08:49:38 +08:00
zw
24fc98407f 装置运行信息报文与装置版本配置信息报文读取 2025-09-03 08:48:49 +08:00
lnk
0af8d02bb2 add function 2025-09-02 14:58:19 +08:00
lnk
077c3f45a2 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-08-11 08:53:35 +08:00
lnk
13e0bc18b3 add cloud mq 2025-08-08 16:35:36 +08:00
zw
e0b2c6d356 合并 2025-08-08 16:26:01 +08:00
zw
f310cb49a3 台账修改 2025-08-08 16:24:17 +08:00
lnk
16ccb567d0 runing with ledger interface 2025-08-08 11:16:38 +08:00
lnk
83986c35cb add qvvr interface 2025-08-07 18:59:11 +08:00
lnk
ee6d9c2689 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-08-05 20:00:28 +08:00
lnk
afc079465e add qvvr interface 2025-08-05 20:00:20 +08:00
zw
81667f3b0d Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-08-05 15:41:18 +08:00
zw
5539c10c0d 定值与内部定值修改完毕 2025-08-05 15:41:04 +08:00
lnk
0eab1e6fb5 add comments 2025-08-04 13:28:51 +08:00
lnk
868de7a909 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-07-31 13:40:26 +08:00
lnk
78938827f7 添加文件路径接口函数和文件下载接口函数 2025-07-31 13:38:55 +08:00
zw
cc9d651b5a 添加了文件管理:文件目录读取,文件下载功能 2025-07-30 13:52:52 +08:00
zw
fff1312c6e 调整了实时的转换方式,添加了不同接线方式的转换 2025-07-25 10:50:49 +08:00
zw
95cd3049a7 合并 2025-07-25 10:49:34 +08:00
zw
900569e5de 调整了实时数据与统计数据的转换方式。更新了暂态事件与波形的处理 2025-07-25 10:47:50 +08:00
lnk
8e4e45ce31 use set_real_state_count 2025-07-14 13:27:38 +08:00
lnk
3fb8ac84f5 rtdata use mq interface 2025-07-11 14:12:47 +08:00
zw
b1963098eb 完成了实时数据的接收和组装字节流 2025-07-10 10:32:29 +08:00
zw
7cfcdd0c5a Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-07-09 10:03:44 +08:00
zw
3ae8ba5900 添加了实时数据的报文组装 2025-07-09 10:03:37 +08:00
96 changed files with 9568 additions and 503 deletions

BIN
LFtid1056.rar Normal file

Binary file not shown.

View File

@@ -7,6 +7,8 @@
#include <cctype>
#include <cstdlib>
#include "client2.h"
#include <iostream>
// <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float IntToFloat(int num) {
return static_cast<float>(num) / 65536.0f;
@@ -23,8 +25,71 @@ float ShorToFloat1000(short num) {
float ShorToFloat10000(short num) {
return static_cast<float>(num) / 10000.0f;
}
// <20>ֽ<EFBFBD><D6BD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ReversalBuff(uint8_t* buff, int start, int length) {
for (int i = 0; i < length / 2; i++) {
std::swap(buff[start + i], buff[start + length - 1 - i]);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>MAC<41><43>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E4B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void GetMAC(const std::string& strMAC, std::vector<unsigned char>& packet, size_t startIndex) {
//lnk20250808
static inline int hex_nibble(char c) {
if (c >= '0' && c <= '9') return c - '0';
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
return -1;
}
// <20><>ȫ<EFBFBD><EFBFBD><E6A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> true/false
bool GetMAC(const std::string& strMAC,
std::vector<unsigned char>& packet,
size_t startIndex,
std::string* err = nullptr) {
// 1) <20><EFBFBD><E6B7B6><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5> '-', ':', ' '
std::string s;
s.reserve(strMAC.size());
for (char c : strMAC) {
if (c == '-' || c == ':' || c == ' ') continue;
s.push_back(c);
}
// 2) <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3>
if (s.size() != 12) {
if (err) *err = "MAC<EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>Ϊ12<EFBFBD><EFBFBD>ʮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>";
return false;
}
// 3) ʮ<><CAAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3> + <20><><EFBFBD><EFBFBD>
std::array<unsigned char, 6> mac{};
for (int i = 0; i < 6; ++i) {
int hi = hex_nibble(s[2*i]);
int lo = hex_nibble(s[2*i + 1]);
if (hi < 0 || lo < 0) {
if (err) *err = "MAC<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ַ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0-9<><39>A-F)";
return false;
}
mac[i] = static_cast<unsigned char>((hi << 4) | lo);
}
// 4) ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㹻д<E3B9BB><D0B4>64<36>ֽڣ<D6BD>MAC 6<>ֽ<EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const size_t need = startIndex + 64;
if (packet.size() < need) packet.resize(need, 0);
// 5) д<><D0B4>MAC
for (int i = 0; i < 6; ++i) {
packet[startIndex + i] = mac[i];
}
// 6) <20><><EFBFBD><EFBFBD>λ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD><E3A3A8> resize <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤һ<D6A4>£<EFBFBD>
for (size_t i = 6; i < 64; ++i) {
packet[startIndex + i] = 0;
}
return true;
}
/*void GetMAC(const std::string& strMAC, std::vector<unsigned char>& packet, size_t startIndex) {
// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>пո<D0BF><D5B8>Ͷ̺<CDB6><CCBA><EFBFBD>
std::string cleanedMAC = strMAC;
cleanedMAC.erase(std::remove(cleanedMAC.begin(), cleanedMAC.end(), ' '), cleanedMAC.end());
@@ -62,7 +127,7 @@ void GetMAC(const std::string& strMAC, std::vector<unsigned char>& packet, size_
catch (const std::exception& e) {
throw std::invalid_argument("<22><>Ч<EFBFBD><D0A7>MAC<41><43>ַ: " + std::string(e.what()));
}
}
}*/
// CRC<52><43><EFBFBD><EFBFBD><E3BAAF>
unsigned char GetCrcSum(const std::vector<unsigned char>& Check, int nOffset, int nLen) {
@@ -76,6 +141,139 @@ unsigned char GetCrcSum(const std::vector<unsigned char>& Check, int nOffset, in
return reg_b;
}
// ʱ<><CAB1>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TagMsTime -> <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint64_t convertTagMsTimeToMsTimestamp(const TagMsTime& t) {
struct tm tm_time = {};
tm_time.tm_year = t.Year - 1900;
tm_time.tm_mon = t.Month - 1;
tm_time.tm_mday = t.Day;
tm_time.tm_hour = t.Hour;
tm_time.tm_min = t.Min;
tm_time.tm_sec = t.Sec;
tm_time.tm_isdst = -1; // <20>Զ<EFBFBD><D4B6>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>ʱ
// ת<><D7AA>Ϊʱ<CEAA><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
time_t seconds = mktime(&tm_time);
if (seconds == -1) return 0;
// <20><><EFBFBD>Ϻ<EFBFBD><CFBA><EFBFBD>
return static_cast<uint64_t>(seconds) * 1000 + t.Ms;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>QVVRRecord
QVVRRecord DynamicLog_GetQVVRRecordFromLogBuffer(
const std::string& strScale,
uint32_t nPTType,
float fPT,
const NewTaglogbuffer& log) {
QVVRRecord record;
try {
// ת<><D7AA>ʱ<EFBFBD><CAB1>
record.triggerTimeMs = convertTagMsTimeToMsTimestamp(log.head.Devtime);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
float fParam1 = 0.0f; // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
float fParam2 = 0.0f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
float fParam3 = 0.0f; // <20><><EFBFBD><EFBFBD><EFBFBD>ż<EFBFBD>ֵ
for (const auto& body : log.bodyList) {
switch (body.ParaCode) {
case 0: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
fParam2 = static_cast<float>(body.ParaValue) / 65536.0f;
break;
case 1: // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>(˲̬<CBB2><CCAC><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>)
fParam1 = static_cast<float>(body.ParaValue) / 65536.0f;
break;
case 25: // <20><><EFBFBD><EFBFBD><EFBFBD>ż<EFBFBD>ֵ(˲̬<CBB2><CCAC><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>)
fParam3 = static_cast<float>(body.ParaValue) / 65536.0f;
break;
case 3: //<2F><>ѹ<EFBFBD><D1B9><EFBFBD>ȣ<EFBFBD>˲̬<CBB2><CCAC><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
record.fMagntitude = (static_cast<float>(body.ParaValue) / 65536.0f) / 100.0f;
break;
case 5: //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲̬<CBB2><CCAC><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
record.phase = static_cast<float>(body.ParaValue) / 65536.0f;
break;
case 6: //˲<><CBB2><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>˲̬<CBB2><CCAC><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
record.transientValue = (static_cast<float>(body.ParaValue) / 65536.0f) / 100.0f;
break;
default:
break;
}
}
record.fPersisstime = fParam1;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׼ֵfBase
float fBase = 0.0f;
if (fParam3 < 50.0f) { // δ<><CEB4><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>ż<EFBFBD>
if (fPT != 1.0f) { // <20><><EFBFBD>Ȳ<EFBFBD>Ϊ1
fBase = (nPTType == 0) ? 57.74f : 100.0f;
}
else {
std::string strTemp = strScale;
std::transform(strTemp.begin(), strTemp.end(), strTemp.begin(), ::tolower);
size_t pos = strTemp.find('k');
if (pos != std::string::npos) {
std::string numPart = strTemp.substr(0, pos);
try {
float fTemp = std::stof(numPart) * 1000.0f;
fBase = (nPTType == 0) ? (fTemp / std::sqrt(3.0f)) : fTemp;
}
catch (...) {
fBase = (nPTType == 0) ? 57.74f : 100.0f;
}
}
else {
fBase = (nPTType == 0) ? 57.74f : 100.0f;
}
}
}
else {
fBase = fParam3; // ʹ<>ø<EFBFBD><C3B8><EFBFBD><EFBFBD>ż<EFBFBD>ֵ
}
// <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
switch (log.head.LogCode) {
case 0: case 26: case 40: case 54: case 68: case 82:
record.nType = 3;
break;
case 1: case 27: case 41: case 55: case 69: case 83:
record.nType = 1;
break;
case 13: case 36: case 50: case 64: case 78: case 92:
record.nType = 2;
break;
case 24:
// <20>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
break;
case 100:
record.nType = 1; // ģ<><C4A3><EFBFBD><EFBFBD>ѹ<EFBFBD>ݽ<EFBFBD>
break;
case 3:
record.nType = 4; // ˲̬<CBB2>¼<EFBFBD>
default:
// δ֪<CEB4><D6AA><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>0
break;
}
// <20><><EFBFBD><EFBFBD><E2B4A6><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6>¼<EFBFBD><C2BC>ҷ<EFBFBD>ֵ<EFBFBD>ϴ<EFBFBD>
if (record.nType == 3 && fParam2 > fBase * 0.1f) {
fParam2 /= 100.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
record.fMagntitude = fParam2 / fBase;
}
catch (...) {
// <20>쳣ʱ<ECB3A3><CAB1><EFBFBD>ؿռ<D8BF>¼
record = QVVRRecord{};
}
return record;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD>
std::vector<unsigned char> GetMsg(const std::vector<unsigned char>& SrcData, unsigned char nType) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@@ -151,7 +349,13 @@ std::vector<unsigned char> generate_frontlogin_message(const std::string& strMac
// [16-19] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2 (<28><><EFBFBD><EFBFBD>Ϊ0)
// <20><><EFBFBD><EFBFBD>MAC<41><43>ַ (<28><>λ<EFBFBD><CEBB>20<32><30>ʼ<EFBFBD><CABC>64<36>ֽ<EFBFBD>)
GetMAC(strMac, packet, 20);
//GetMAC(strMac, packet, 20);
//lnk20250808
std::string err;
if (!GetMAC(strMac, packet, 20, &err)) {
std::cerr << "[GetMAC] parse failed: " << err << "\n";
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD>
}
// <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD> (<28><>ƫ<EFBFBD><C6AB>8<EFBFBD><38>137)
unsigned char checksum = 0;
@@ -163,6 +367,15 @@ std::vector<unsigned char> generate_frontlogin_message(const std::string& strMac
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
packet[packetSize - 1] = 0x16;
//lnk20250808
// ======= <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> =======
std::cout << "[generate_frontlogin_message] Packet (" << packet.size() << " bytes):\n";
for (size_t i = 0; i < packet.size(); ++i) {
printf("%02X ", packet[i]);
if ((i + 1) % 16 == 0) printf("\n");
}
if (packet.size() % 16 != 0) printf("\n");
return packet;
}
@@ -203,5 +416,353 @@ std::vector<unsigned char> generate_statequerystat_message(tagTime time, uint16_
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Stat));
}
//ѯ<><D1AF>ʵʱ<CAB5><CAB1><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD> <20><><EFBFBD><EFBFBD>1-6 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1-11 г<><D0B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0-2
std::vector<unsigned char> generate_realstat_message(unsigned char nCpuNo,
unsigned char StaTtype,
unsigned char flag)
{
// <20><><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD>С<EFBFBD><D0A1>3(<28><><EFBFBD><EFBFBD>) + 1(nCpuNo) + 1(StaTtype) + 1(<28>̶<EFBFBD>ֵ) + 1(flag)
const size_t totalSize = 7;
std::vector<unsigned char> DataBuf(totalSize, 0x00); // <20><>ʼ<EFBFBD><CABC>Ϊȫ0
size_t offset = 0;
// 1. <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽڱ<D6BD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѳ<EFBFBD>ʼ<EFBFBD><CABC>Ϊ0<CEAA><30>
offset += 3;
// 2. д<><D0B4>nCpuNo<4E><6F>1<EFBFBD>ֽڣ<D6BD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1-6
memcpy(DataBuf.data() + offset, &nCpuNo, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 3. д<><D0B4>StaTtype<70><65>1<EFBFBD>ֽڣ<D6BD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1-11 һ<><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1-6
memcpy(DataBuf.data() + offset, &StaTtype, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 4. д<><D0B4><EFBFBD>̶<EFBFBD>ֵ1<D6B5><31>1<EFBFBD>ֽڣ<D6BD> 3<><33>ʵʱ<CAB5><CAB1><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>1 <20><>ʾƽ<CABE><C6BD>ֵ
const unsigned char fixedValue = 1;
memcpy(DataBuf.data() + offset, &fixedValue, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 5. д<><D0B4>flag<61><67>1<EFBFBD>ֽڣ<D6BD> <20><>־λ 0-2 г<><D0B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 25 50 100<30><30>
memcpy(DataBuf.data() + offset, &flag, sizeof(unsigned char));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_New_3S));
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>+<2B>ļ<EFBFBD><C4BC><EFBFBD>
std::vector<unsigned char> generate_downloadfile_message(int frameIndex, const std::string& fileName) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С: 3(<28><><EFBFBD><EFBFBD>) + 4(֡<><D6A1><EFBFBD><EFBFBD>) + 128(<28>ļ<EFBFBD><C4BC><EFBFBD>) = 135<33>ֽ<EFBFBD>
std::vector<unsigned char> dataBuf(135, 0x00);
// д<><D0B4>֡<EFBFBD><D6A1><EFBFBD><EFBFBD> (4<>ֽڣ<D6BD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
//uint32_t netFrameIndex = htonl(static_cast<uint32_t>(frameIndex));
//memcpy(dataBuf.data() + 3, &netFrameIndex, sizeof(uint32_t));
// <20>Ƴ<EFBFBD>htonlת<6C><D7AA><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9>ԭʼ֡<CABC><D6A1><EFBFBD><EFBFBD>(С<><D0A1><EFBFBD><EFBFBD>)
uint32_t rawFrameIndex = static_cast<uint32_t>(frameIndex);
memcpy(dataBuf.data() + 3, &rawFrameIndex, sizeof(uint32_t));
// д<><D0B4><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD> (<28><><EFBFBD><EFBFBD>128<32>ֽ<EFBFBD>)
size_t copyLen = std::min(fileName.size(), static_cast<size_t>(128));
if (copyLen > 0) {
memcpy(dataBuf.data() + 7, fileName.c_str(), copyLen);
}
// <20><><EFBFBD><EFBFBD>GetMsg<73><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_File_Download));
}
//<2F>ļ<EFBFBD>Ŀ¼<C4BF><C2BC>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ȡ<EFBFBD><C8A1><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
std::vector<unsigned char> generate_getfilemenu_message(const std::string& filedir) {
// <20><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD>131<33>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD> (3 + 128)<29><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> dataBuf(131, 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>3<EFBFBD><33>ʼ<EFBFBD><CABC>
size_t copyLen = std::min(filedir.size(), static_cast<size_t>(128));
if (copyLen > 0) {
memcpy(dataBuf.data() + 3, filedir.c_str(), copyLen);
}
// <20><><EFBFBD><EFBFBD>GetMsg<73><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_FileDir));
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<unsigned char> generate_requestFixValue_message(unsigned char nCpuNo) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (nCpuNo < 1 || nCpuNo > 6)
return std::vector<unsigned char>();
// <20><><EFBFBD><EFBFBD>4<EFBFBD>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
std::vector<unsigned char> DataBuf(4, 0x00);
DataBuf[3] = nCpuNo; // CPU<50><55><EFBFBD>ŷ<EFBFBD><C5B7>ڵ<EFBFBD>4<EFBFBD>ֽ<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_FixValue));
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<unsigned char> generate_requestFixDes_message() {
// <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
std::vector<unsigned char> DataBuf(3, 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_FixDes));
}
// <20><><EFBFBD>ö<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<2B>޸ĵĶ<C4B5>ֵ<EFBFBD><D6B5><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD>
std::vector<unsigned char> generate_requestSetFixValue_message(
unsigned char nCpuNo,
const std::vector<float>& value)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (nCpuNo < 1 || nCpuNo > 6)
return std::vector<unsigned char>();
// <20><><EFBFBD><EFBFBD><E3BBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С: 4(ͷ<><CDB7>) + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E9B3A4>*4
const size_t bufSize = 4 + value.size() * 4;
std::vector<unsigned char> DataBuf(bufSize, 0x00);
DataBuf[3] = nCpuNo; // CPU<50><55><EFBFBD>ŷ<EFBFBD><C5B7>ڵ<EFBFBD>4<EFBFBD>ֽ<EFBFBD>
// <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
for (size_t i = 0; i < value.size(); i++) {
// <20><>floatת<74><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
uint32_t intValue;
memcpy(&intValue, &value[i], sizeof(float));
uint32_t netValue = htonl(intValue);
// <20><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
unsigned char* dest = DataBuf.data() + 4 + i * 4;
memcpy(dest, &netValue, sizeof(uint32_t));
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_Fix));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_requestinterfixvalue_message()
{
// <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> dataBuf(3, 0x00);
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_InterFix));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param nDesCW <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (1-<2D>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>, 2-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Чʱ<D0A7><CAB1><EFBFBD>ؿ<EFBFBD><D8BF><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_requestinterfixdes_message(unsigned char nDesCW)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>
if (nDesCW < 1 || nDesCW > 2) {
return std::vector<unsigned char>();
}
// <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
std::vector<unsigned char> dataBuf(3, 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
dataBuf[0] = nDesCW;
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_InterFixDes));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param values Ҫ<><D2AA><EFBFBD>õĶ<C3B5>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> (ushortֵ)
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_requestsetinterfixvalue_message(const std::vector<uint16_t>& values)
{
// <20><><EFBFBD><EFBFBD><E3BBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С: 3<>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + ÿ<><C3BF>ֵռ2<D5BC>ֽ<EFBFBD>
const size_t bufSize = 3 + values.size() * 2;
std::vector<unsigned char> dataBuf(bufSize, 0x00);
// <20><><EFBFBD>䶨ֵ<E4B6A8><D6B5><EFBFBD><EFBFBD>
for (size_t i = 0; i < values.size(); i++) {
// <20><>ushortֵת<D6B5><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> (<28><><EFBFBD><EFBFBD>)
uint16_t netValue = htons(values[i]);
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>λ<EFBFBD><CEBB>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>3<EFBFBD>ֽ<EFBFBD>ͷ<EFBFBD><CDB7>)
unsigned char* dest = dataBuf.data() + 3 + i * 2;
// <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(dest, &netValue, sizeof(uint16_t));
}
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_InterFix));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param values Ҫ<><D2AA><EFBFBD>õĶ<C3B5>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> (ushortֵ)
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_requestsetinterfixvalue_message_new(const std::vector<uint16_t>& value)
{
// <20><><EFBFBD><EFBFBD><E3BBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С: 3<>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + ÿ<><C3BF>ֵռ2<D5BC>ֽ<EFBFBD>
const size_t bufSize = 3 + value.size() * 2;
std::vector<unsigned char> dataBuf(bufSize, 0x00);
// <20><><EFBFBD>䶨ֵ<E4B6A8><D6B5><EFBFBD><EFBFBD>
for (size_t i = 0; i < value.size(); i++) {
// <20><>ֵת<D6B5><D7AA>Ϊ<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
uint16_t rawValue = value[i];
unsigned char* bytes = reinterpret_cast<unsigned char*>(&rawValue);
// <20><>ת<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>C#<23><>ReversalBuff<66><66>
std::swap(bytes[0], bytes[1]);
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>λ<EFBFBD><CEBB>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>3<EFBFBD>ֽ<EFBFBD>ͷ<EFBFBD><CDB7>)
unsigned char* dest = dataBuf.data() + 3 + i * 2;
// <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(dest, bytes, sizeof(uint16_t));
}
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD>
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_InterFix));
}
/**
* @brief <20><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>ȡָ<C8A1><EFBFBD><EEB1A8>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_machinestatus_message()
{
// <20><><EFBFBD><EFBFBD>10<31>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> DataBuf(10, 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33>ֵΪ1<CEAA><31><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD>ֽڣ<D6BD>
DataBuf[3] = 0x01;
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>14<31><34>Ӧװ<D3A6><D7B0>״̬<D7B4><CCAC>ȡ
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_RunningInformation));
}
/**
* @brief <20><><EFBFBD><EFBFBD>װ<EFBFBD>ð汾<C3B0><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>ȡָ<C8A1><EFBFBD><EEB1A8>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_machineversion_message()
{
// <20><><EFBFBD><EFBFBD>10<31>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> DataBuf(10, 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33>ֵΪ1<CEAA><31><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD>ֽڣ<D6BD>
DataBuf[3] = 0x02;
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>14<31><34>Ӧװ<D3A6><D7B0>״̬<D7B4><CCAC>ȡ
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_RunningInformation));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>ö<EFBFBD>ʱ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param time <20>·<EFBFBD><C2B7>Ķ<EFBFBD>ʱʱ<CAB1><CAB1> (tmֵ)
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<uint8_t> generate_righttime_message(const std::tm& time) {
std::vector<uint8_t> DataBuf(15, 0x00); // <20><><EFBFBD><EFBFBD>15<31>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
// ǰ3<C7B0>ֽ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ã<EFBFBD><C3A3>ѳ<EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
// ֱ<><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EBA3A8>ռ2<D5BC>ֽڣ<D6BD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint16_t year = static_cast<uint16_t>(time.tm_year + 1900);
DataBuf[3] = static_cast<uint8_t>((year >> 8) & 0xFF); // <20><><EFBFBD>ֽ<EFBFBD>
DataBuf[4] = static_cast<uint8_t>(year & 0xFF); // <20><><EFBFBD>ֽ<EFBFBD>
uint16_t month = static_cast<uint16_t>(time.tm_mon + 1);
DataBuf[5] = static_cast<uint8_t>((month >> 8) & 0xFF);
DataBuf[6] = static_cast<uint8_t>(month & 0xFF);
uint16_t day = static_cast<uint16_t>(time.tm_mday);
DataBuf[7] = static_cast<uint8_t>((day >> 8) & 0xFF);
DataBuf[8] = static_cast<uint8_t>(day & 0xFF);
uint16_t hour = static_cast<uint16_t>(time.tm_hour);
DataBuf[9] = static_cast<uint8_t>((hour >> 8) & 0xFF);
DataBuf[10] = static_cast<uint8_t>(hour & 0xFF);
uint16_t minute = static_cast<uint16_t>(time.tm_min);
DataBuf[11] = static_cast<uint8_t>((minute >> 8) & 0xFF);
DataBuf[12] = static_cast<uint8_t>(minute & 0xFF);
uint16_t second = static_cast<uint16_t>(time.tm_sec);
DataBuf[13] = static_cast<uint8_t>((second >> 8) & 0xFF);
DataBuf[14] = static_cast<uint8_t>(second & 0xFF);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>GetMsg<73><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>134(0x86)
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_RightTime));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
* @param Time1 <20><>ʼʱ<CABC><CAB1>
* @param Time2 <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
* @param eventType <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>ͣ<EFBFBD>Ĭ<EFBFBD><C4AC>2-<2D><>̬<EFBFBD>¼<EFBFBD> 4-<2D>澯ʱ<E6BEAF><CAB1>
* @param monitorPoint <20><><EFBFBD><EFBFBD><EFBFBD>㣬Ĭ<E3A3AC><C4AC>1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1 1-6 <20><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<uint8_t> generate_recallevent_message(const std::tm& Time1, const std::tm& Time2,
uint8_t eventType, uint8_t monitorPoint)
{
std::vector<uint8_t> DataBuf(25, 0x00); // <20><><EFBFBD><EFBFBD>25<32>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
// ǰ3<C7B0>ֽ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ã<EFBFBD><C3A3>ѳ<EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
DataBuf[3] = eventType; // 2-<2D><>̬<EFBFBD>¼<EFBFBD> 4-<2D><EFBFBD>¼<EFBFBD>
DataBuf[4] = monitorPoint; // 0-<2D><><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD>
// <20><>ʱ<EFBFBD><CAB1>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>ֽڸ<D6BD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E4B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint16_t year1 = static_cast<uint16_t>(Time1.tm_year + 1900);
DataBuf[5] = static_cast<uint8_t>((year1 >> 8) & 0xFF);
DataBuf[6] = static_cast<uint8_t>(year1 & 0xFF);
uint16_t month1 = static_cast<uint16_t>(Time1.tm_mon + 1);
DataBuf[7] = static_cast<uint8_t>((month1 >> 8) & 0xFF);
DataBuf[8] = static_cast<uint8_t>(month1 & 0xFF);
uint16_t day1 = static_cast<uint16_t>(Time1.tm_mday);
DataBuf[9] = static_cast<uint8_t>((day1 >> 8) & 0xFF);
DataBuf[10] = static_cast<uint8_t>(day1 & 0xFF);
uint16_t hour1 = static_cast<uint16_t>(Time1.tm_hour);
DataBuf[11] = static_cast<uint8_t>((hour1 >> 8) & 0xFF);
DataBuf[12] = static_cast<uint8_t>(hour1 & 0xFF);
uint16_t minute1 = static_cast<uint16_t>(Time1.tm_min);
DataBuf[13] = static_cast<uint8_t>((minute1 >> 8) & 0xFF);
DataBuf[14] = static_cast<uint8_t>(minute1 & 0xFF);
uint16_t year2 = static_cast<uint16_t>(Time2.tm_year + 1900);
DataBuf[15] = static_cast<uint8_t>((year2 >> 8) & 0xFF);
DataBuf[16] = static_cast<uint8_t>(year2 & 0xFF);
uint16_t month2 = static_cast<uint16_t>(Time2.tm_mon + 1);
DataBuf[17] = static_cast<uint8_t>((month2 >> 8) & 0xFF);
DataBuf[18] = static_cast<uint8_t>(month2 & 0xFF);
uint16_t day2 = static_cast<uint16_t>(Time2.tm_mday);
DataBuf[19] = static_cast<uint8_t>((day2 >> 8) & 0xFF);
DataBuf[20] = static_cast<uint8_t>(day2 & 0xFF);
uint16_t hour2 = static_cast<uint16_t>(Time2.tm_hour);
DataBuf[21] = static_cast<uint8_t>((hour2 >> 8) & 0xFF);
DataBuf[22] = static_cast<uint8_t>(hour2 & 0xFF);
uint16_t minute2 = static_cast<uint16_t>(Time2.tm_min);
DataBuf[23] = static_cast<uint8_t>((minute2 >> 8) & 0xFF);
DataBuf[24] = static_cast<uint8_t>(minute2 & 0xFF);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>GetMsg<73><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0x0D(<28>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>)
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_Event));
}

File diff suppressed because it is too large Load Diff

29
LFtid1056/boot/feservice Normal file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
export CLOUD_PATH=/home/pq/zwproject/LFtid1056
if [ -z "$CLOUD_PATH" ]; then
echo "Error: CLOUD_PATH is not set. Please set it first."
exit 1
fi
case "$1" in
'start')
$CLOUD_PATH/boot/start_fe.sh
;;
'stop')
$CLOUD_PATH/boot/stop_fe.sh
;;
'restart')
$CLOUD_PATH/boot/stop_fe.sh
$CLOUD_PATH/boot/start_fe.sh
;;
*)
echo "Usage: feservice start|stop|restart"
exit 1
;;
esac

62
LFtid1056/boot/ps_fe.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
# ========= 0. 获取脚本所在路径的上一层,设置为 FEP_ENV =========
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
FEP_ENV="$(dirname "$SCRIPT_DIR")"
export FEP_ENV
# ========= 1. 初始化软连接 =========
TEMP_LINK_CREATED=0
if [ ! -L "/FeProject" ]; then
if [ ! -e "/FeProject" ]; then
sudo ln -s "$FEP_ENV" /FeProject
TEMP_LINK_CREATED=1
echo "Temporary symlink /FeProject created."
else
echo "/FeProject exists but is not a symlink. Please check manually."
fi
fi
if [ -z "$FEP_ENV" ]; then
echo "Error: FEP_ENV is not set. Please set it first."
exit 1
fi
RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf"
while read LINE ; do
if [ -n "$LINE" ] ; then
if [ ${LINE:0:1} != "#" ]; then
BINPATH=`echo $LINE | awk -F '^' '{printf $1}'`
BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BINPATH
BIN=`echo $LINE | awk -F '^' '{printf $2}'`
BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BIN
SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'`
SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SPECIAL
SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'`
SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SLEEPSEC
STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'`
STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $STARTFLAG
# if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then
CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'"
BIN2=`echo $BIN`
ps -ef | grep "$BIN2" | grep -v 'grep'
# fi
fi
fi
done < $RUNTIME_CF_FILE
# ========= 4. 清理软链接(仅在本次脚本中创建) =========
if [ "$TEMP_LINK_CREATED" -eq 1 ]; then
if [ -L "/FeProject" ]; then
sudo rm -f /FeProject
echo "Temporary symlink /FeProject removed."
fi
fi

View File

@@ -0,0 +1,97 @@
#!/bin/bash
# ========= 0. <20><>ȡ<EFBFBD>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><E3A3AC><EFBFBD><EFBFBD>Ϊ FEP_ENV =========
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
FEP_ENV="$(dirname "$SCRIPT_DIR")"
export FEP_ENV
# ========= 1. <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> =========
TEMP_LINK_CREATED=0
if [ ! -L "/FeProject" ]; then
if [ ! -e "/FeProject" ]; then
sudo ln -s "$FEP_ENV" /FeProject
TEMP_LINK_CREATED=1
echo "Temporary symlink /FeProject created."
else
echo "/FeProject exists but is not a symlink. Please check manually."
fi
fi
if [ -z "$FEP_ENV" ]; then
echo "Error: FEP_ENV is not set. Please set it first."
exit 1
fi
# ========= 2. <20><>־<EFBFBD><D6BE>ת<EFBFBD><D7AA><EFBFBD><EFBFBD> =========
check_log_file() {
if [ -n "$1" ]; then
FILE_SIZE=$(du "$1" | awk '{print $1}')
if [ "$FILE_SIZE" -ge 5120 ]; then
[ -f "$1.3" ] && rm -f "$1.3"
[ -f "$1.2" ] && mv "$1.2" "$1.3"
[ -f "$1.1" ] && mv "$1.1" "$1.2"
mv "$1" "$1.1"
fi
fi
}
LOGFILE="$FEP_ENV/dat/log/start_fe.log"
check_log_file "$LOGFILE"
echo "" ; echo ""
echo "******* $(date "+%F %R:%S") Start Processes *******"
echo "" >>"$LOGFILE"
echo "" >>"$LOGFILE"
echo "******* $(date "+%F %R:%S") Start Processes *******" >>"$LOGFILE"
# ========= 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> =========
RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf"
echo "Using config file name: $RUNTIME_CF_FILE"
echo "Using config file name: $RUNTIME_CF_FILE" >>"$LOGFILE"
cd "$FEP_ENV/boot" || exit 1
CURDIR=$(pwd)
while read -r LINE; do
if [ -n "$LINE" ] && [[ ${LINE:0:1} != "#" ]]; then
BINPATH=$(echo "$LINE" | awk -F '^' '{print $1}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$BINPATH"
BIN=$(echo "$LINE" | awk -F '^' '{print $2}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$BIN"
SPECIAL=$(echo "$LINE" | awk -F '^' '{print $4}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$SPECIAL"
SLEEPSEC=$(echo "$LINE" | awk -F '^' '{print $5}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$SLEEPSEC"
STARTFLAG=$(echo "$LINE" | awk -F '^' '{print $7}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$STARTFLAG"
RESTARTFLAG=$(echo "$LINE" | awk -F '^' '{print $6}' | grep -o "[^ ]\+\( \+[^ ]\+\)*")
echo "$RESTARTFLAG"
if [ "$RESTARTFLAG" = "IGNORE_RESTART" ]; then
CMD_STR="sleep $SLEEPSEC"
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
eval "$CMD_STR"
CMD_STR="$BINPATH$BIN $SPECIAL"
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
eval "$CMD_STR" &>/dev/null
fi
fi
done < "$RUNTIME_CF_FILE"
cd "$CURDIR"
DT=$(date "+%F %R:%S.%N")
echo "******* ${DT:0:23} Start Processes Succcessfully *******"
echo "******* ${DT:0:23} Start Processes Succcessfully *******" >>"$LOGFILE"
# ========= 4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1>νű<CEBD><C5B1>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD> =========
if [ "$TEMP_LINK_CREATED" -eq 1 ]; then
if [ -L "/FeProject" ]; then
sudo rm -f /FeProject
echo "Temporary symlink /FeProject removed."
fi
fi

129
LFtid1056/boot/stop_fe.sh Normal file
View File

@@ -0,0 +1,129 @@
#!/bin/bash
# ========= 0. 获取脚本所在路径的上一层,设置为 FEP_ENV =========
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
FEP_ENV="$(dirname "$SCRIPT_DIR")"
export FEP_ENV
# ========= 1. 初始化软连接 =========
TEMP_LINK_CREATED=0
if [ ! -L "/FeProject" ]; then
if [ ! -e "/FeProject" ]; then
sudo ln -s "$FEP_ENV" /FeProject
TEMP_LINK_CREATED=1
echo "Temporary symlink /FeProject created."
else
echo "/FeProject exists but is not a symlink. Please check manually."
fi
fi
if [ -z "$FEP_ENV" ]; then
echo "Error: FEP_ENV is not set. Please set it first."
exit 1
fi
check_log_file()
{
if [ -n "$1" ] ; then
FILE_SIZE=0
FILE_SIZE=`du $1 | awk '{print $1}'`
if [ $FILE_SIZE -ge 5120 ]
then
if [ -f "$1".3 ]; then
rm -f "$1".3
fi
if [ -f "$1".2 ]; then
mv "$1".2 "$1".3
fi
if [ -f "$1".1 ]; then
mv "$1".1 "$1".2
fi
mv "$1" "$1".1
fi
fi
}
LOGFILE="$FEP_ENV/dat/log/start_fe.log"
check_log_file $LOGFILE
echo "" ; echo ""
echo "****** `date "+%F %R:%S"` Stop Processes ******"
echo "" >>"$LOGFILE"
echo "" >>"$LOGFILE"
echo "****** `date "+%F %R:%S"` Stop Processes ******" >>"$LOGFILE"
RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf"
#cat $RUNTIME_CF_FILE |tac > /tmp/runtime.cf
sed '1!G;h;$!d' $RUNTIME_CF_FILE > /tmp/runtime.cf
echo "Using config file name: $RUNTIME_CF_FILE"
echo "Using config file name: $RUNTIME_CF_FILE">>"$LOGFILE"
while read LINE ; do
if [ -n "$LINE" ] ; then
if [ ${LINE:0:1} != "#" ]; then
BINPATH=`echo $LINE | awk -F '^' '{printf $1}'`
BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BINPATH
BIN=`echo $LINE | awk -F '^' '{printf $2}'`
BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BIN
SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'`
SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SPECIAL
SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'`
SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SLEEPSEC
STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'`
STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $STARTFLAG
if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then
# echo ""
# echo "" >>"$LOGFILE"
CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'"
BIN2=`echo $BIN`
BIN3=`echo $BIN |awk '{print$1}'`
# CMD_STR="killall `echo $BIN | awk '{print$1}'` 2>&1 "
PIDSTR=`ps -ef | grep "$BIN2" | grep -v 'grep'`
if [ -n "$PIDSTR" ] ; then
if [ "$BIN3" == "fe_main" ]; then
CMD_STR=" sleep 3 "
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
$CMD_STR
fi
CMD_STR="kill -15 `echo $PIDSTR | awk '{print$2}'` "
echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`"
echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`" >>"$LOGFILE"
echo " Executing: $CMD_STR"
echo " Executing: $CMD_STR" >>"$LOGFILE"
CMD_RESULT=`$CMD_STR`
if [ -n "$CMD_RESULT" ] ; then
echo "$CMD_RESULT"
echo "$CMD_RESULT" >>"$LOGFILE"
fi
else
echo " Process \"$BIN\" not running."
fi
fi
fi
fi
done < /tmp/runtime.cf
DT=`date "+%F %R:%S.%N"`
echo "****** ${DT:0:23} Stop Processes Succcessfully ******"
echo "" >>"$LOGFILE"
echo "****** ${DT:0:23} Stop Processes Succcessfully ******" >>"$LOGFILE"
# ========= 4. 清理软链接(仅在本次脚本中创建) =========
if [ "$TEMP_LINK_CREATED" -eq 1 ]; then
if [ -L "/FeProject" ]; then
sudo rm -f /FeProject
echo "Temporary symlink /FeProject removed."
fi
fi

View File

@@ -7,6 +7,9 @@
#include <memory>
#include <mutex>
#include <unordered_map>
#include <sstream>
#include <algorithm>
#include <interface.h>
// 配置参数
constexpr int BASE_RECONNECT_DELAY = 20000; // 基础重连延迟(ms)
@@ -53,7 +56,7 @@ void ClientContext::init_tcp() {
void ClientContext::start_timer() {
if (!uv_is_active((uv_handle_t*)&timer)) {
uv_timer_start(&timer, on_timer, 5000,5000);
uv_timer_start(&timer, on_timer, 1000,1000);
}
}
@@ -248,7 +251,7 @@ void ClientContext::process_next_action() {
// 新增方法:发送当前状态对应的报文
void ClientContext::send_current_packet() {
if (!current_packet_.empty()) {
send_binary_data(this, current_packet_.data(), current_packet_.size());
safe_send_binary_data(this, current_packet_);
}
}
@@ -281,6 +284,37 @@ void ClientContext::clear_stat_cache() {
stat_packets_cache_.clear();
expected_total_packets_ = 0;
}
bool ClientContext::event_add_stat_packet(const std::vector<unsigned char>& packet, int current_packet, int total_packets) {
std::lock_guard<std::mutex> lock(event_stat_cache_mutex_);
// 如果是第一帧,初始化缓存
if (current_packet == 1) {
event_stat_packets_cache_.clear();
event_expected_total_packets_ = total_packets;
}
// 添加到缓存
event_stat_packets_cache_.push_back({ current_packet, packet });
// 检查是否收齐所有帧
return (event_stat_packets_cache_.size() >= event_expected_total_packets_);
}
std::vector<ClientContext::StatPacket> ClientContext::event_get_and_clear_stat_packets() {
std::lock_guard<std::mutex> lock(event_stat_cache_mutex_);
auto packets = std::move(event_stat_packets_cache_);
event_stat_packets_cache_.clear();
event_expected_total_packets_ = 0;
return packets;
}
void ClientContext::event_clear_stat_cache() {
std::lock_guard<std::mutex> lock(event_stat_cache_mutex_);
event_stat_packets_cache_.clear();
event_expected_total_packets_ = 0;
}
// 添加浮点数据到缓存
bool ClientContext::add_float_data(ushort point_id, int data_type, const tagPqData_Float& float_data) {
if (data_type < 0 || data_type > 3) return false;
@@ -312,6 +346,48 @@ void ClientContext::clear_float_cache() {
std::lock_guard<std::mutex> lock(float_cache_mutex_);
point_float_cache_.clear();
}
// 版本比较函数的辅助函数:分割字符串并转换为整数向量
std::vector<int> splitVersionString(const std::string& versionStr) {
std::vector<int> segments;
std::stringstream ss(versionStr);
std::string segment;
while (std::getline(ss, segment, '.')) {
segments.push_back(std::stoi(segment));
}
return segments;
}
// 版本比较函数
bool isVersionGreaterOrEqual(const std::string& version1, const std::string& version2) {
// 去除开头的'V'(如果存在)
std::string v1 = version1;
if (!v1.empty() && v1[0] == 'V') {
v1.erase(0, 1);
}
std::string v2 = version2;
if (!v2.empty() && v2[0] == 'V') {
v2.erase(0, 1);
}
// 分割版本号
std::vector<int> seg1 = splitVersionString(v1);
std::vector<int> seg2 = splitVersionString(v2);
// 逐段比较版本号
size_t maxSize = std::max(seg1.size(), seg2.size());
for (size_t i = 0; i < maxSize; ++i) {
int num1 = (i < seg1.size()) ? seg1[i] : 0;
int num2 = (i < seg2.size()) ? seg2[i] : 0;
if (num1 != num2) {
return num1 > num2;
}
}
return true; // 所有段都相等
}
/* 缓冲区分配回调 */
void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
buf->base = new char[suggested_size];
@@ -355,34 +431,88 @@ void on_write(uv_write_t* req, int status) {
}
/* 定时发送回调 */
//5秒执行一次定时器
//1秒执行一次定时器
void on_timer(uv_timer_t* handle) {
ClientContext* ctx = static_cast<ClientContext*>(handle->data);
if (ctx->state != ConnectionState::CONNECTED) {
return;
}
static int statequerytime = 0;//询问统计数据时间标志 20秒执行一次
// 检查状态超时 30秒状态未更新则重置为空闲状态
ctx->check_state_timeout();
//检查当前装置最新通讯时间是否超过1分钟如果1分钟内没有收到任何装置通讯消息则调整为未登录状态通讯状态设置为离线.
uint64_t timecheck = uv_now(ctx->loop);//当前时间戳
if (timecheck - ctx->get_cloudmessage_time >= 60000) {
ctx->get_cloudmessage_time = timecheck;
//不管原状态是什么,这里都设置装置登录状态为未登录
ClientManager::instance().set_cloud_status(ctx->device_info.device_id, 0);
}
// 装置登录成功后,只在空闲状态处理后续动作
if (ctx->cloudstatus == 1) {
uint64_t now = uv_now(ctx->loop);//当前时间戳
//20秒一次 执行统计数据时间询问
if (++statequerytime >= 4 && ctx->current_state_ == DeviceState::IDLE) {
statequerytime = 0;//重置计时
if (ctx->current_state_ == DeviceState::IDLE && now - ctx->last_state_query_time_ >= 20000) {
// 更新统计数据最后查询时间
ctx->last_state_query_time_ = now;
auto sendbuff = generate_statequerytime_message();//组装询问统计数据时间报文
ctx->add_action(DeviceState::READING_STATS_TIME, sendbuff);//将该状态以及待发送报文存入队列
}
//一秒一次 执行实时数据询问 仅执行指定次数
now = uv_now(ctx->loop);
if (ctx->current_state_ == DeviceState::IDLE && now - ctx->real_state_query_time_ >= 1000 && ctx->real_state_count > 0) {
// 更新实时数据执行时间和实时收发计数
ctx->real_state_query_time_ = now;
ctx->real_state_count--;
auto sendbuff = generate_realstat_message(static_cast<unsigned char>(ctx->real_point_id_), static_cast<unsigned char>(0x01), static_cast<unsigned char>(0x01));//组装询问实时数据报文
ctx->add_action(DeviceState::READING_REALSTAT, sendbuff);//将该状态以及待发送报文存入队列
}
//30分钟一次 读取装置运行信息
now = uv_now(ctx->loop);
if (ctx->current_state_ == DeviceState::IDLE && now - ctx->read_runninginformationMsg >= 60000 * 30)
{
// 更新运行信息最后读取时间
ctx->read_runninginformationMsg = now;
auto sendbuff = generate_machinestatus_message();//组装读取装置运行信息报文
ctx->add_action(DeviceState::READING_RUNNINGINFORMATION_2, sendbuff);//将该状态以及待发送报文存入队列
}
//30分钟一次 启动装置对时 仅在台账开启对时且云协议版本大于1.5时开启对时 60000 * 30
now = uv_now(ctx->loop);
if (ctx->current_state_ == DeviceState::IDLE && now - ctx->right_time >= 60000 * 30 && ctx->device_info.righttime && isVersionGreaterOrEqual(ctx->dev_CloudProtocolVer,"V1.5"))
{
// 更新对时功能最后运行时间
ctx->right_time = now;
// 获取当前时间
auto now = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(now);
std::tm tm_time = *std::localtime(&time);
auto sendbuff = generate_righttime_message(tm_time);//组装装置对时报文
ctx->add_action(DeviceState::SET_RIGHTTIME, sendbuff);//将该状态以及待发送报文存入队列
//auto sendbuff = generate_machinestatus_message();//组装读取装置运行信息报文
//ctx->add_action(DeviceState::READING_RUNNINGINFORMATION_2, sendbuff);//将该状态以及待发送报文存入队列
}
//处理后续工作队列的工作 取出一个并执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
}
else {
//装置登录状态异常,预备重发登录报文,检查最新登录报文发送时间,超过限制则重发登录报文
uint64_t now = uv_now(ctx->loop);//当前时间戳
if (now - ctx->login_cloud_time >= 60000) {
//更新最后一次登录报文发送时间
ctx->login_cloud_time = now;
//装置未登录且60秒内没有发送装置登录报文预备发送登录报文
auto binary_data = generate_frontlogin_message(ctx->device_info.mac);
safe_send_binary_data(ctx, binary_data);
}
}
}
/* 发送二进制报文函数 */
@@ -410,6 +540,37 @@ void send_binary_data(ClientContext* ctx, const unsigned char* data, size_t data
}
}
// 新增函数:在事件循环线程中安全发送数据
void safe_send_binary_data(ClientContext* ctx, std::vector<unsigned char> data) {
uv_work_t* req = new uv_work_t;
req->data = new std::pair<ClientContext*, std::vector<unsigned char>>(ctx, std::move(data));
uv_queue_work(ctx->loop, req, [](uv_work_t* req) {
// 在工作线程中不执行实际工作
}, [](uv_work_t* req, int status) {
// 在事件循环线程中执行实际发送
auto* pair = static_cast<std::pair<ClientContext*, std::vector<unsigned char>>*>(req->data);
ClientContext* ctx = pair->first;
const auto& data = pair->second;
if (ctx->state == ConnectionState::CONNECTED) {
// 实际发送逻辑(原 send_binary_data 的核心部分)
uv_buf_t buf = uv_buf_init(const_cast<char*>(reinterpret_cast<const char*>(data.data())), data.size());
uv_write_t* write_req = new uv_write_t;
write_req->data = new std::vector<unsigned char>(data); // 复制数据
int ret = uv_write(write_req, (uv_stream_t*)&ctx->client, &buf, 1, on_write);
if (ret < 0) {
// 错误处理
delete static_cast<std::vector<unsigned char>*>(write_req->data);
delete write_req;
}
}
delete pair;
delete req;
});
}
/* 连接关闭回调 */
void on_close(uv_handle_t* handle) {
ClientContext* ctx = static_cast<ClientContext*>(handle->data);
@@ -419,10 +580,11 @@ void on_close(uv_handle_t* handle) {
ctx->stop_timers();
// 清空缓存
ctx->clear_stat_cache();
ctx->event_clear_stat_cache();
// 清除浮点数据缓存
ctx->clear_float_cache();
ctx->cloudstatus = 0;
// 装置登录状态调整为离线
ClientManager::instance().set_cloud_status(ctx->device_info.device_id, 0);
{
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
ctx->current_state_ = DeviceState::IDLE; // 直接修改状态
@@ -489,11 +651,18 @@ void on_connect(uv_connect_t* req, int status) {
ctx->state = ConnectionState::CONNECTED;
ctx->reconnect_attempts = 0;
// 新增:初始化各个计时时间戳
ctx->last_state_query_time_ = uv_now(ctx->loop);//初始化统计数据时间戳
ctx->real_state_query_time_ = uv_now(ctx->loop);//初始化实时数据时间戳
ctx->read_runninginformationMsg = uv_now(ctx->loop);//初始化读取装置运行信息时间戳
ctx->right_time = uv_now(ctx->loop);//初始化对时时间戳
ctx->get_cloudmessage_time = uv_now(ctx->loop);//初始化最新装置通讯报文时间戳
ctx->login_cloud_time = uv_now(ctx->loop);//初始化装置登录报文超时发送时标
ctx->real_state_count = 0;//实时数据收发计数
//客户端连接完毕后,发送装置登陆消息
std::cout << "connected: " << ctx->device_info.mac << " send login msg!" << std::endl;
auto binary_data = generate_frontlogin_message(ctx->device_info.mac);
send_binary_data(ctx, binary_data.data(), binary_data.size());
safe_send_binary_data(ctx, binary_data);
uv_read_start((uv_stream_t*)&ctx->client, alloc_buffer, on_read);
ctx->start_timer();
@@ -613,30 +782,6 @@ void ClientManager::remove_device(const std::string& device_id) {
std::cout << "[Device " << device_id << "] Removed successfully\n";
}
bool ClientManager::send_to_device(const std::string& identifier,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
if (ctx->state == ConnectionState::CONNECTED) {
send_binary_data(ctx.get(), data, size);
return true;
}
std::cerr << "[Device " << identifier << "] Not connected\n";
return false;
}
}
std::cerr << "[Device " << identifier << "] Not found\n";
return false;
}
void ClientManager::stop_all() {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
@@ -688,6 +833,35 @@ void ClientManager::restart_device(const std::string& device_id) {
}
}
//设备运行情况判断
bool ClientManager::get_dev_status(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
if (ctx->cloudstatus == 1) {
//设备已登录
std::cout << "[Device " << identifier
<< "] online!" <<std::endl;
return true;
}
else{
//设备状态异常
//设备已登录
std::cout << "[Device " << identifier
<< "] offline!" << std::endl;
return false;
}
}
}
return false;
}
//修改客户端云前置登录状态
bool ClientManager::set_cloud_status(const std::string& identifier, int status) {
std::lock_guard<std::mutex> lock(mutex_);
@@ -698,6 +872,19 @@ bool ClientManager::set_cloud_status(const std::string& identifier, int status)
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
if (ctx->cloudstatus == 0 && status == 1) {
//设备从离线转换至在线,通知前台状态发生翻转
connect_status_update(identifier, status);
std::cout << "[Device " << identifier
<< "] ****Cloud status: " << ctx->cloudstatus << " updated to: " << status << std::endl;
}
else if (ctx->cloudstatus == 1 && status == 0) {
//设备从在线转换至离线,通知前台状态发生翻转
connect_status_update(identifier, status);
std::cout << "[Device " << identifier
<< "] ****Cloud status: " << ctx->cloudstatus << " updated to: " << status << std::endl;
}
// 修改云前置登录状态
ctx->cloudstatus = status;
std::cout << "[Device " << identifier
@@ -710,6 +897,48 @@ bool ClientManager::set_cloud_status(const std::string& identifier, int status)
return false;
}
//刷新客户端装置最新接收通讯报文时间
bool ClientManager::set_cloudmessage_time(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 修改云前置登录状态
ctx->get_cloudmessage_time = uv_now(ctx->loop);//刷新最新装置通讯报文时间戳
return true;
}
}
std::cerr << "[set_cloud_status] Device not found: " << identifier << std::endl;
return false;
}
//修改客户端读取到的配置信息:云协议版本
bool ClientManager::set_versioninformation(const std::string& identifier, string cloud_version) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 修改云前置登录状态
ctx->dev_CloudProtocolVer = cloud_version;
std::cout << "[Device " << identifier
<< "] Cloud version updated to: " << cloud_version << std::endl;
return true;
}
}
std::cerr << "[set_cloud_status] Device not found: " << identifier << std::endl;
return false;
}
bool ClientManager::add_action_to_device(const std::string& identifier,
DeviceState state,
const std::vector<unsigned char>& packet) {
@@ -890,6 +1119,52 @@ bool ClientManager::clear_stat_cache(const std::string& identifier) {
return false;
}
//保存多帧事件日志报文至缓存区等待收全
bool ClientManager::add_eventlog_packet_to_device(const std::string& identifier,
const std::vector<unsigned char>& packet,
int current_packet,
int total_packets) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->event_add_stat_packet(packet, current_packet, total_packets);
}
}
return false;
}
//获取缓存区内所有多帧事件日志报文并清空缓存
std::vector<ClientContext::StatPacket> ClientManager::get_and_clear_event_packets(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->event_get_and_clear_stat_packets();
}
}
return {};
}
//清空所有事件日志缓存区
bool ClientManager::clear_event_cache(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->event_clear_stat_cache();
return true;
}
}
return false;
}
// 获取pt和CT变比
bool ClientManager::get_pt_ct_ratio(const std::string& identifier,
int16_t nCpuNo,
@@ -928,6 +1203,25 @@ bool ClientManager::get_pt_ct_ratio(const std::string& identifier,
return false;
}
// 获取待补招测点序号
bool ClientManager::get_event_lineid(const std::string& identifier,int& nCpuNo) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
nCpuNo = ctx->event_lineNo;
return true;
}
}
std::cerr << "[get_pt_ct_ratio] Device not found: " << identifier << std::endl;
return false;
}
// 添加浮点数据到指定设备的缓存
bool ClientManager::add_float_data_to_device(const std::string& identifier,
ushort point_id,
@@ -973,4 +1267,506 @@ bool ClientManager::clear_float_cache(const std::string& identifier) {
}
}
return false;
}
//实时数据调用
bool ClientManager::set_real_state_count(const std::string& identifier, int count, ushort point_id) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 设置实时计数
ctx->real_state_count = count;
// 设置测点序号(如果提供了有效值)
if (point_id != 0) {
ctx->real_point_id_ = point_id;
}
std::cout << "[Device " << identifier
<< "] Real state params set - count: " << count
<< ", point_id: " << ctx->real_point_id_.load()
<< std::endl;
return true;
}
}
std::cerr << "[set_real_state_count] Device not found: " << identifier << std::endl;
return false;
}
//读取文件目录调用
bool ClientManager::add_file_menu_action_to_device(
const std::string& identifier,
const std::string& file_path)
{
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成文件目录读取报文
auto packet = generate_getfilemenu_message(file_path);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_FILEMENU, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//文件下载调用
bool ClientManager::add_file_download_action_to_device(
const std::string& identifier,
const std::string& file_path)
{
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成下载请求报文 (帧序号固定为1代表开始新文件的下载)
auto downloadMsg = generate_downloadfile_message(1, file_path);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_FILEDATA, downloadMsg);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//获取指定装置指定测点下的定值数据
bool ClientManager::get_fixedvalue_action_to_device(const std::string& identifier, ushort point_id) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值数据报文
auto packet = generate_requestFixValue_message(point_id);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_FIXEDVALUE, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//获取指定装置的定值描述
bool ClientManager::get_fixedvaluedes_action_to_device(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_requestFixDes_message();
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_FIXEDVALUEDES, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//设置指定测点定值配置
bool ClientManager::set_fixedvalue_action_to_device(const std::string& identifier, ushort point_id, const std::vector<float>& value) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_requestSetFixValue_message(point_id, value);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::SET_FIXEDVALUE, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//获取装置内部定值
bool ClientManager::get_interfixedvalue_action_to_device(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_requestinterfixvalue_message();
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_INTERFIXEDVALUE, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//获取装置内部定值控制字描述or内部定值描述 1-内部定值描述2-控制字位描述
bool ClientManager::get_fixedvalucontrolword_action_to_device(const std::string& identifier, unsigned char nDesCW) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_requestinterfixdes_message(nDesCW);
if (nDesCW == 1) {
// 添加内部定值描述
ctx->add_action(DeviceState::READING_INTERFIXEDVALUEDES, packet);
}
else {
// 添加控制字描述
ctx->add_action(DeviceState::READING_CONTROLWORD, packet);
}
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//设置装置内部定值配置
bool ClientManager::set_interfixedvalue_action_to_device(const std::string& identifier, const std::vector<uint16_t>& values) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_requestsetinterfixvalue_message(values);
//auto packet = generate_requestsetinterfixvalue_message_new(values);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::SET_INTERFIXEDVALUE, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//读取装置运行信息
bool ClientManager::read_runninginformation_action_to_device(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_machinestatus_message();
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_RUNNINGINFORMATION_1, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//读取装置版本配置信息
bool ClientManager::read_devversion_action_to_device(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
// 生成定值描述报文
auto packet = generate_machineversion_message();
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_DEVVERSION, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
/**
* @brief 补招事件日志动作
* @param Time1 起始时间
* @param Time2 结束时间
* @param eventType 事件类型默认2-暂态事件 4-告警时间
* @param monitorPoint 监测点默认1-监测点1 1-6 对应测点
* @return 调用成功或失败的结果
*/
bool ClientManager::read_eventlog_action_to_device(const std::string& identifier, const std::tm& Time1, const std::tm& Time2,
uint8_t eventType, uint8_t monitorPoint) {
std::lock_guard<std::mutex> lock(mutex_);
// 查找匹配的设备
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
ctx->event_lineNo = monitorPoint;
// 生成定值描述报文
auto packet = generate_recallevent_message(Time1, Time2, eventType, monitorPoint);
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::READING_EVENTLOG, packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false; // 设备未找到
}
//获取指定装置测点的电压等级与接线方式
bool ClientManager::get_point_scale_and_pttype(const std::string& identifier,
ushort nCpuNo,
std::string& out_scale,
int& out_pttype) {
std::lock_guard<std::mutex> lock(mutex_);
// 遍历所有客户端上下文
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 检查标识符是否匹配设备ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 在装置的测点列表中查找匹配的测点
for (const auto& point : ctx->device_info.points) {
if (point.nCpuNo == nCpuNo) {
out_scale = point.strScale;
out_pttype = point.nPTType;
return true;
}
}
// 测点未找到
std::cerr << "Point with nCpuNo " << nCpuNo
<< " not found for device: " << identifier << std::endl;
return false;
}
}
// 设备未找到
std::cerr << "Device not found: " << identifier << std::endl;
return false;
}
//修改待发送报文的帧序号(仅在暂态文件中使用)
bool ClientManager::update_current_packet_frame(const std::string& identifier, int next_frame) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier || ctx->device_info.mac == identifier) {
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
// 检查报文长度是否足够
if (ctx->current_packet_.size() < 16) {
std::cerr << "Packet too short to update frame number" << std::endl;
return false;
}
// 小端序写入新帧序号 (位置12-15字节)
ctx->current_packet_[12] = (next_frame >> 0) & 0xFF;
ctx->current_packet_[13] = (next_frame >> 8) & 0xFF;
ctx->current_packet_[14] = (next_frame >> 16) & 0xFF;
ctx->current_packet_[15] = (next_frame >> 24) & 0xFF;
return true;
}
}
return false;
}
bool ClientManager::parse_download_packet(const std::string& identifier, DownloadInfo& out_info) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 获取当前状态报文
std::vector<unsigned char> current_packet;
{
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
current_packet = ctx->current_packet_;
}
// 解析帧序号 (12-15字节小端序)
if (current_packet.size() >= 16) {
out_info.current_frame =
(static_cast<int>(current_packet[12])) |
(static_cast<int>(current_packet[13]) << 8) |
(static_cast<int>(current_packet[14]) << 16) |
(static_cast<int>(current_packet[15]) << 24);
// 解析文件名 (从偏移量16开始)
if (current_packet.size() > 16) {
const char* filename_start = reinterpret_cast<const char*>(current_packet.data()) + 16;
size_t filename_len = 128;
out_info.filename.assign(filename_start, filename_len);
return true;
}
}
}
}
return false;
}
bool ClientManager::add_file_packet_to_device(const std::string& identifier,
int frame_index,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->add_file_packet(frame_index, data, size);
return true;
}
}
return false;
}
std::vector<std::vector<unsigned char>>
ClientManager::get_and_clear_file_packets(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->get_and_clear_file_packets();
}
}
return {};
}
bool ClientManager::update_current_filename(const std::string& identifier,
const std::string& filename) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->set_current_filename(filename);
return true;
}
}
return false;
}
std::string ClientManager::get_current_filename(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->get_current_filename();
}
}
return "";
}

View File

@@ -20,6 +20,8 @@ struct PointInfo {
double PT2; // <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>2
double CT1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
double CT2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
std::string strScale; // <20><>ѹ<EFBFBD>ȼ<EFBFBD>
int nPTType; // <20><><EFBFBD>߷<EFBFBD>ʽ 0-<2D><><EFBFBD><EFBFBD> 1-<2D><><EFBFBD><EFBFBD>
};
// װ<><D7B0><EFBFBD><EFBFBD>Ϣ<EFBFBD>
@@ -30,6 +32,7 @@ struct DeviceInfo {
std::string mac; // װ<><D7B0>MAC<41><43>ַ
int status; // <20><><EFBFBD><EFBFBD>״̬ (0: <20><><EFBFBD><EFBFBD>, 1: <20><><EFBFBD><EFBFBD>)
std::vector<PointInfo> points; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool righttime; //<2F><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
};
enum class ConnectionState {
@@ -40,9 +43,26 @@ enum class ConnectionState {
// <20><><EFBFBD>ӵ<EFBFBD>״̬ö<CCAC><C3B6>
enum class DeviceState {
IDLE, // <20><><EFBFBD><EFBFBD>״̬
READING_STATS, // <20><>ȡͳ<C8A1><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
READING_STATS_TIME, // <20><>ȡͳ<C8A1><CDB3>ʱ<EFBFBD><CAB1>
IDLE, // <20><><EFBFBD><EFBFBD>״̬
READING_STATS, // <20><>ȡͳ<C8A1><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
READING_STATS_TIME, // <20><>ȡͳ<C8A1><CDB3>ʱ<EFBFBD><CAB1>
READING_REALSTAT, // <20><>ȡʵʱ<CAB5><CAB1><EFBFBD><EFBFBD>
READING_EVENTFILE, // <20><>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
READING_FILEMENU, // <20><>ȡ<EFBFBD>ļ<EFBFBD>Ŀ¼
READING_FILEDATA, // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
READING_FIXEDVALUE, // <20><>ȡ<EFBFBD><C8A1><EFBFBD>㶨ֵ
READING_FIXEDVALUEDES, // <20><>ȡ<EFBFBD><C8A1><EFBFBD>㶨ֵ<E3B6A8><D6B5><EFBFBD><EFBFBD>
SET_FIXEDVALUE, // <20><><EFBFBD>ò<EFBFBD><C3B2>㶨ֵ
READING_INTERFIXEDVALUE, // <20><>ȡ<EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ
READING_INTERFIXEDVALUEDES, // <20><>ȡ<EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>
READING_CONTROLWORD, // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SET_INTERFIXEDVALUE, // <20><><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ
READING_RUNNINGINFORMATION_1,// <20><>ȡװ<C8A1><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
READING_RUNNINGINFORMATION_2,// <20><>ȡװ<C8A1><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ(<28><>ʱִ<CAB1><D6B4>)
READING_DEVVERSION, // <20><>ȡװ<C8A1>ð汾<C3B0><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
SET_RIGHTTIME, // <20><><EFBFBD><EFBFBD>װ<EFBFBD>ö<EFBFBD>ʱ
READING_EVENTLOG, // <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־
READING_STATSFILE, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
// <20>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>Ӹ<EFBFBD><D3B8><EFBFBD>״̬
CUSTOM_ACTION // <20>Զ<EFBFBD><D4B6><EFBFBD><E5B6AF>
};
@@ -62,9 +82,18 @@ public:
ConnectionState state;
int reconnect_attempts;
volatile bool shutdown;
uint64_t last_state_query_time_ = 0; // ͳ<><CDB3><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>ʱʱ<CAB1><CAB1><EFBFBD><EFBFBD>
uint64_t real_state_query_time_ = 0; // ʵʱ<CAB5><CAB1><EFBFBD>ݼ<EFBFBD>ʱʱ<CAB1><CAB1><EFBFBD><EFBFBD>
std::atomic<int> real_state_count{ 0 };//ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD> ԭ<>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>̰߳<DFB3>ȫ
std::atomic<ushort> real_point_id_{ 1 }; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>ԭ<EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>
uint64_t read_runninginformationMsg = 0; // װ<>ö<EFBFBD>ʱ<EFBFBD><CAB1>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣʱ<CFA2><CAB1><EFBFBD><EFBFBD>
uint64_t right_time = 0; // װ<>ö<EFBFBD>ʱ<EFBFBD><CAB1>ʱʱ<CAB1><CAB1><EFBFBD><EFBFBD>
DeviceInfo device_info; // װ<><D7B0><EFBFBD><EFBFBD>Ϣ
int cloudstatus; // <20><>ǰ<EFBFBD>õ<EFBFBD>¼״̬<D7B4><CCAC>0<EFBFBD><30>δ<EFBFBD><CEB4>¼ 1<><31><EFBFBD>ѵ<EFBFBD>¼<EFBFBD><C2BC>
int cloudstatus = 0; // <20><>ǰ<EFBFBD>õ<EFBFBD>¼״̬<D7B4><CCAC>0<EFBFBD><30>δ<EFBFBD><CEB4>¼ 1<><31><EFBFBD>ѵ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ0
uint64_t get_cloudmessage_time = 0;//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>ͨѶ<CDA8><D1B6><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
uint64_t login_cloud_time = 0;//װ<>õ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD>ij<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
std::string dev_CloudProtocolVer = "V1.0";//װ<><D7B0><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><E6B1BE> <20><><EFBFBD><EFBFBD>V1.5<EFBFBD><EFBFBD>װ<EFBFBD>õ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡһ<EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж϶<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ΪV1.0
// <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա
DeviceState current_state_; // <20><>ǰװ<C7B0><D7B0>״̬
@@ -96,14 +125,21 @@ public:
std::vector<unsigned char> data;
};
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------------------------------------------------------------------------
std::vector<StatPacket> stat_packets_cache_; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
int expected_total_packets_ = 0; // Ԥ<><D4A4><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
std::mutex stat_cache_mutex_; // <20><><EFBFBD><EFBFBD><E6BBA5><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool add_stat_packet(const std::vector<unsigned char>& packet, int current_packet, int total_packets);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<StatPacket> get_and_clear_stat_packets();//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
void clear_stat_cache();//<2F><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-----------------------------------------------------------------
ushort event_lineNo = 1; // <20>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD>
std::vector<StatPacket> event_stat_packets_cache_; // <20>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
int event_expected_total_packets_ = 0; // <20>¼<EFBFBD><C2BC><EFBFBD>־Ԥ<D6BE><D4A4><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
std::mutex event_stat_cache_mutex_; // <20>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><E6BBA5><EFBFBD><EFBFBD>
bool event_add_stat_packet(const std::vector<unsigned char>& packet, int current_packet, int total_packets);//<2F>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<StatPacket> event_get_and_clear_stat_packets();//<2F>¼<EFBFBD><C2BC><EFBFBD>־ȡ<D6BE><C8A1><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
void event_clear_stat_cache();//<2F>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
// ͳ<><CDB3><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
struct PointFloatCache {
@@ -122,6 +158,94 @@ public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
void clear_float_cache();
// ʵʱ<CAB5><CAB1><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD>
struct RealtimePacket {
unsigned char packet_type;
std::vector<unsigned char> data;
};
std::vector<RealtimePacket> realtime_packets_cache_; // <20><><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݰ<EFBFBD>
std::mutex realtime_cache_mutex_; // <20><><EFBFBD><EFBFBD><E6BBA5><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void add_realtime_packet(unsigned char packet_type,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(realtime_cache_mutex_);
realtime_packets_cache_.push_back({
packet_type,
std::vector<unsigned char>(data, data + size)
});
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
std::vector<RealtimePacket> get_and_clear_realtime_packets() {
std::lock_guard<std::mutex> lock(realtime_cache_mutex_);
auto packets = std::move(realtime_packets_cache_);
realtime_packets_cache_.clear();
return packets;
}
// <20><><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void reset_realtime_data() {
std::lock_guard<std::mutex> lock(realtime_cache_mutex_);
realtime_packets_cache_.clear();
}
//<2F><>̬<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct FileDownloadPacket {
int frame_index;
std::vector<unsigned char> data;
};
std::vector<FileDownloadPacket> file_download_cache_; // <20>ļ<EFBFBD><C4BC><EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>
std::string current_filename_; // <20><>ǰ<EFBFBD><C7B0><EFBFBD>ص<EFBFBD><D8B5>ļ<EFBFBD><C4BC><EFBFBD>
std::mutex file_cache_mutex_; // <20><><EFBFBD><EFBFBD><E6BBA5><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void add_file_packet(int frame_index, const unsigned char* data, size_t size) {
std::lock_guard<std::mutex> lock(file_cache_mutex_);
file_download_cache_.push_back({ frame_index, std::vector<unsigned char>(data, data + size) });
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>з<EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<std::vector<unsigned char>> get_and_clear_file_packets() {
std::lock_guard<std::mutex> lock(file_cache_mutex_);
// <20><>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::sort(file_download_cache_.begin(), file_download_cache_.end(),
[](const FileDownloadPacket& a, const FileDownloadPacket& b) {
return a.frame_index < b.frame_index;
});
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
std::vector<std::vector<unsigned char>> packets;
for (const auto& pkt : file_download_cache_) {
packets.push_back(pkt.data);
}
// <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
file_download_cache_.clear();
return packets;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
void clear_file_cache() {
std::lock_guard<std::mutex> lock(file_cache_mutex_);
file_download_cache_.clear();
}
// <20><><EFBFBD>õ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ص<EFBFBD><D8B5>ļ<EFBFBD><C4BC><EFBFBD>
void set_current_filename(const std::string& filename) {
std::lock_guard<std::mutex> lock(file_cache_mutex_);
current_filename_ = filename;
}
// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD>ص<EFBFBD><D8B5>ļ<EFBFBD><C4BC><EFBFBD>
std::string get_current_filename() {
std::lock_guard<std::mutex> lock(file_cache_mutex_);
return current_filename_;
}
private:
int index_;
@@ -146,7 +270,6 @@ public:
void add_device(const DeviceInfo& device);//<2F><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void remove_device(const std::string& device_id);//ɾ<><C9BE>һ<EFBFBD><D2BB>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool send_to_device(const std::string& identifier, const unsigned char* data, size_t size);//ѡ<><D1A1>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>װ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void restart_device(const std::string& device_id);//<2F>ر<EFBFBD>ָ<EFBFBD><D6B8>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void stop_all();//ֹͣ<CDA3><D6B9><EFBFBD>пͻ<D0BF><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool set_cloud_status(const std::string& identifier, int status);//<2F>޸<EFBFBD><DEB8><EFBFBD>ǰ<EFBFBD>õ<EFBFBD>¼״̬
@@ -182,12 +305,27 @@ public:
//<2F><><EFBFBD>ն<EFBFBD>֡<EFBFBD><D6A1><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><E6BBBA><EFBFBD><EFBFBD>
bool clear_stat_cache(const std::string& identifier);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>ȫ
bool add_eventlog_packet_to_device(const std::string& identifier,
const std::vector<unsigned char>& packet,
int current_packet,
int total_packets);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>֡<EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
std::vector<ClientContext::StatPacket> get_and_clear_event_packets(const std::string& identifier);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool clear_event_cache(const std::string& identifier);
// <20><>ȡָ<C8A1><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PT<50><54>CT<43><54><EFBFBD><EFBFBD>ֵ
bool get_pt_ct_ratio(const std::string& identifier,
int16_t nCpuNo,
float& pt_ratio,
float& ct_ratio);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool get_event_lineid(const std::string& identifier, int& nCpuNo);
// <20><>ȡ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
size_t client_count() {
std::lock_guard<std::mutex> lock(mutex_);
@@ -207,6 +345,114 @@ public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><E3BBBA>
bool clear_float_cache(const std::string& identifier);
// <20><><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD>
bool add_realtime_packet_to_device(const std::string& identifier,
unsigned char packet_type,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->add_realtime_packet(packet_type, data, size);
return true;
}
}
return false;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
std::vector<ClientContext::RealtimePacket>
get_and_clear_realtime_packets(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->get_and_clear_realtime_packets();
}
}
return {};
}
// <20><>ȡָ<C8A1><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ѹ<EFBFBD>ȼ<EFBFBD><C8BC>ͽ<EFBFBD><CDBD>߷<EFBFBD>ʽ
bool get_point_scale_and_pttype(const std::string& identifier,
ushort nCpuNo,
std::string& out_scale,
int& out_pttype);
//<2F>޸<EFBFBD><DEB8><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ĵ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
bool update_current_packet_frame(const std::string& identifier, int next_frame);
//<2F><>ȡ<EFBFBD><C8A1>̬<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ϣ
struct DownloadInfo {
std::string filename;
int current_frame;
};
bool parse_download_packet(const std::string& identifier, DownloadInfo& out_info);
bool add_file_packet_to_device(const std::string& identifier,
int frame_index,
const unsigned char* data,
size_t size);
std::vector<std::vector<unsigned char>> get_and_clear_file_packets(const std::string& identifier);
bool update_current_filename(const std::string& identifier, const std::string& filename);
std::string get_current_filename(const std::string& identifier);
//ˢ<>¿ͻ<C2BF><CDBB><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD>ͨѶ<CDA8><D1B6><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
bool set_cloudmessage_time(const std::string& identifier);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>޸Ŀͻ<C4BF><CDBB>˵<EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>ά<EFBFBD><CEAC>Ϣ<EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0B9A6>ʹ<EFBFBD><CAB9>
bool set_versioninformation(const std::string& identifier, string cloud_version);
//<2F><>ȡ<EFBFBD>ļ<EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id + <20>ļ<EFBFBD>·<EFBFBD><C2B7>
bool add_file_menu_action_to_device(const std::string& identifier, const std::string& file_path);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD> ʵʱ<CAB5><CAB1><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id + ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool set_real_state_count(const std::string& identifier, int count, ushort point_id);
//<2F>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id + <20>ļ<EFBFBD>λ<EFBFBD><CEBB>
bool add_file_download_action_to_device(const std::string& identifier, const std::string& file_path);
//<2F><>ȡָ<C8A1><D6B8>װ<EFBFBD><D7B0>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µĶ<C2B5>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool get_fixedvalue_action_to_device(const std::string& identifier, ushort point_id);
//<2F><>ȡָ<C8A1><D6B8>װ<EFBFBD>ö<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id
bool get_fixedvaluedes_action_to_device(const std::string& identifier);
//<2F><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>mac/id + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> + <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
bool set_fixedvalue_action_to_device(const std::string& identifier, ushort point_id, const std::vector<float>& value);
//<2F><>ȡװ<C8A1><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ <20><><EFBFBD><EFBFBD>mac/id
bool get_interfixedvalue_action_to_device(const std::string& identifier);
//<2F><>ȡװ<C8A1><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>or<6F>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> 1-<2D>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
bool get_fixedvalucontrolword_action_to_device(const std::string& identifier, unsigned char nDesCW);
//<2F><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ֵ <20><><EFBFBD><EFBFBD>mac/id + <20>ڲ<EFBFBD><DAB2><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>
bool set_interfixedvalue_action_to_device(const std::string& identifier, const std::vector<uint16_t>& values);
//<2F><>ȡװ<C8A1><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
bool read_runninginformation_action_to_device(const std::string& identifier);
//<2F><>ȡװ<C8A1>ð汾<C3B0><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
bool read_devversion_action_to_device(const std::string& identifier);
//<2F><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
bool get_dev_status(const std::string& identifier);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
* @param Time1 <20><>ʼʱ<CABC><CAB1>
* @param Time2 <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
* @param eventType <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>ͣ<EFBFBD>Ĭ<EFBFBD><C4AC>2-<2D><>̬<EFBFBD>¼<EFBFBD> 4-<2D>澯ʱ<E6BEAF><CAB1>
* @param monitorPoint <20><><EFBFBD><EFBFBD><EFBFBD>㣬Ĭ<E3A3AC><C4AC>1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1 1-6 <20><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
* @return <20><><EFBFBD>óɹ<C3B3><C9B9><EFBFBD>ʧ<EFBFBD>ܵĽ<DCB5><C4BD><EFBFBD>
*/
bool read_eventlog_action_to_device(const std::string& identifier, const std::tm& Time1, const std::tm& Time2,uint8_t eventType = 2, uint8_t monitorPoint = 1);
private:
ClientManager() : loop_(nullptr) {}
std::unordered_map<std::string, std::unique_ptr<ClientContext>> clients_;
@@ -217,6 +463,7 @@ private:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void start_client_connect(const std::vector<DeviceInfo>& devices);
void send_binary_data(ClientContext* ctx, const unsigned char* data, size_t data_size);
void safe_send_binary_data(ClientContext* ctx, std::vector<unsigned char> data);
void on_timer(uv_timer_t* handle);
void try_reconnect(uv_timer_t* timer);
void on_connect(uv_connect_t* req, int status);

File diff suppressed because it is too large Load Diff

View File

@@ -48,9 +48,9 @@ std::vector<terminal_dev> terminal_devlist;
std::mutex ledgermtx;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern int g_front_seg_index;
extern int g_front_seg_num;
extern std::string FRONT_IP;
extern uint32_t g_node_id;
//筛选的终端状态:数组【0,1】筛选运行和在运
@@ -609,27 +609,27 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
dev.terminal_id = safe_str(item, "id");
dev.addr_str = safe_str(item, "ip");
dev.terminal_name = safe_str(item, "name");
dev.org_name = safe_str(item, "org_name");
dev.maint_name = safe_str(item, "maint_name");
dev.station_name = safe_str(item, "stationName");
dev.tmnl_factory = safe_str(item, "manufacturer");
dev.tmnl_status = safe_str(item, "status");
//dev.org_name = safe_str(item, "org_name");
//dev.maint_name = safe_str(item, "maint_name");
//dev.station_name = safe_str(item, "stationName");
//dev.tmnl_factory = safe_str(item, "manufacturer");
//dev.tmnl_status = safe_str(item, "status");
dev.dev_type = safe_str(item, "devType");
dev.dev_key = safe_str(item, "devKey");
dev.dev_series = safe_str(item, "series");
dev.port = safe_str(item, "port");
dev.timestamp = safe_str(item, "updateTime");
dev.processNo = safe_str(item, "processNo");
dev.maxProcessNum = safe_str(item, "maxProcessNum");
//dev.dev_key = safe_str(item, "devKey");
//dev.dev_series = safe_str(item, "series");
//dev.port = safe_str(item, "port");
//dev.timestamp = safe_str(item, "updateTime");
dev.processNo = safe_str(item, "node");
//dev.maxProcessNum = safe_str(item, "maxProcessNum");
dev.mac = safe_str(item, "mac");//添加mac
//dev.mac = safe_str(item, "mac");//添加mac
if (item.contains("monitorData") && item["monitorData"].is_array()) {
for (auto& mon : item["monitorData"]) {
if (dev.line.size() >= 10) break;
ledger_monitor m;
m.monitor_id = safe_str(mon, "id");
m.terminal_id = safe_str(mon, "terminal_id");
m.terminal_id = safe_str(mon, "deviceId");
m.monitor_name = safe_str(mon, "name");
m.logical_device_seq = safe_str(mon, "lineNo");
m.voltage_level = safe_str(mon, "voltageLevel");
@@ -637,10 +637,10 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
m.timestamp = safe_str(mon, "updateTime");
m.status = safe_str(mon, "status");
m.CT1 = mon.value("CT1", 0.0);
m.CT2 = mon.value("CT2", 0.0);
m.PT1 = mon.value("PT1", 0.0);
m.PT2 = mon.value("PT2", 0.0);
m.CT1 = mon.value("ct1", 0.0);
m.CT2 = mon.value("ct2", 0.0);
m.PT1 = mon.value("pt1", 0.0);
m.PT2 = mon.value("pt2", 0.0);
dev.line.push_back(m);
}
@@ -736,16 +736,43 @@ int parse_device_cfg_web()
if (IED_COUNT < count_cfg) {
std::cout << "!!!!!!!!!!single process can not add any ledger unless reboot!!!!!!!" << std::endl;
DIY_WARNLOG("process","【WARN】前置的%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账", g_front_seg_index, IED_COUNT);
//DIY_WARNLOG("process","【WARN】前置的%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账", g_front_seg_index, IED_COUNT);
} else {
DIY_INFOLOG("process","【NORMAL】前置的%d号进程根据配置文件中给单个进程配置的台账数量:%d来创建台账空间", g_front_seg_index, IED_COUNT);
//DIY_INFOLOG("process","【NORMAL】前置的%d号进程根据配置文件中给单个进程配置的台账数量:%d来创建台账空间", g_front_seg_index, IED_COUNT);
}
///////////////////////////////////////////////////////////////////////////////用例这里将局部的map拷贝到全局map后续根据协议台账修改
// 先清空全局 container再逐个拷贝 map 中的 terminal_dev
std::lock_guard<std::mutex> lock(ledgermtx);
terminal_devlist.clear();
for (const auto& kv : terminal_dev_map) {
terminal_devlist.push_back(kv.second); // kv.second 是对象,不用判断指针
terminal_dev dev = kv.second; // kv.second 是对象,不用判断指针
// ======= [新增] 对 terminal_dev 中 web 未返回/未设置字段做统一初始化,避免脏值 =======
dev.guid.clear(); // [新增] 业务 guid 初始为空
dev.busytype = 0; // [新增] 业务类型(状态机)默认 0
dev.isbusy = 0; // [新增] 未进行业务
dev.busytimecount = 0; // [新增] 业务计时清零
dev.internal_values.clear(); // [新增] 内部定值清空,等后续业务真实填充
dev.dz_internal_info_list.clear(); // [新增] 内部定值信息清空,等后续业务真实填充
// ------------------------------------------------------------------------------------
// ======= [新增] 对每个监测点做必要的内部结构初始化 =======
for (auto &mon : dev.line) {
// 暂态事件容器显式清理(虽然默认构造已空,但这里确保无脏数据)
mon.qvvrevent.qvvrdata.clear(); // [新增]
mon.qvvrevent.qvvrfile.clear(); // [新增]
// 定值列表清理,等待后续配置/采集填充
mon.set_values.clear(); // [新增]
mon.dz_info_list.clear(); // [新增]
}
// ------------------------------------------------------------------------------------
terminal_devlist.push_back(dev);
}
// 判断监测点接线类型
@@ -1149,32 +1176,24 @@ static void scanAndResendOfflineFiles(const std::string& dirPath)
}
}
int transfer_json_qvvr_data(unsigned int func_type, int monitor_id,
double mag, double dur, long long start_tm, long long end_tm, int dis_kind,
const std::string& uuid_cfg, const std::string& uuid_dat,
const std::string& mp_id, const std::string& Qvvr_rptname, const std::string& devtype) {
int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
double mag, double dur, long long start_tm, int dis_kind,int phase,
const std::string& wavepath) {
// 监测点日志的 key, lnk20250526
std::string full_key_m_c = "monitor." + mp_id + ".COM";
std::string full_key_m_d = "monitor." + mp_id + ".DATA";
std::string full_key_m_c = "monitor." + dev_id + "." + std::to_string(monitor_id) + ".COM";
std::string full_key_m_d = "monitor." + dev_id + "." + std::to_string(monitor_id) + ".DATA";
// 监测点日志的 key, lnk20250526
// 获取装置类型的映射配置
XmlConfig c_xmlcfg;
if (xmlinfo_list.count(devtype)) {
c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
} else {
c_xmlcfg = xmlcfg;
}
if (mp_id.empty()) {
std::cout << "mp_id is null" << std::endl;
if (dev_id.empty()) {
std::cout << "dev_id is null" << std::endl;
return 0;
}
// 构造 JSON 对象
json root;
root["monitorId"] = mp_id;
root["devId"] = dev_id;
root["CpuNo"] = monitor_id;
root["amplitude"] = mag;
root["duration"] = dur;
root["eventType"] = dis_kind;
@@ -1189,21 +1208,9 @@ int transfer_json_qvvr_data(unsigned int func_type, int monitor_id,
std::string start_time_str = start_time_stream.str();
root["startTime"] = start_time_str;
root["wavePath"] = uuid_dat; //接口提供了两个文件名入参,实际上名字一样只用一个,可优化
root["wavePath"] = wavepath;
root["phase"] = phase;
if (c_xmlcfg.WavePhasicFlag == "1") { //映射配置分相
if (Qvvr_rptname.find(c_xmlcfg.WavePhasicA) != std::string::npos) {
root["phase"] = "A";
} else if (Qvvr_rptname.find(c_xmlcfg.WavePhasicB) != std::string::npos) {
root["phase"] = "B";
} else if (Qvvr_rptname.find(c_xmlcfg.WavePhasicC) != std::string::npos) {
root["phase"] = "C";
} else {
root["phase"] = "unknow";
}
} else {
root["phase"] = "unknow"; //不分相
}
std::string json_string = root.dump(4);
std::cout << json_string << std::endl;
@@ -1212,28 +1219,28 @@ int transfer_json_qvvr_data(unsigned int func_type, int monitor_id,
std::string response;
SendJsonAPI_web(WEB_EVENT, "", json_string, response);
// ================ 插入新功能 =========================
// ================ 暂态重发功能 =========================
if (!response.empty()) {
try {
json j_r = json::parse(response);
// 有效响应,略过
} catch (...) {
// 响应异常,保存 json
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件", mp_id.c_str());
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口响应异常,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
std::string qvvrDir = FRONT_PATH + "/dat/qvvr/";
std::string fileName = qvvrDir + mp_id + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt";
std::string fileName = qvvrDir + dev_id + "-" + std::to_string(monitor_id) + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt";
writeJsonToFile(fileName, json_string);
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
}
} else {
// 无响应,保存 json
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件", mp_id.c_str());
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口无响应,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
std::string qvvrDir = FRONT_PATH + "/dat/qvvr/";
std::string fileName = qvvrDir + mp_id + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt";
std::string fileName = qvvrDir + dev_id + "-" + std::to_string(monitor_id) + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt";
writeJsonToFile(fileName, json_string);
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
return 1;
@@ -1254,13 +1261,9 @@ int transfer_json_qvvr_data(unsigned int func_type, int monitor_id,
void qvvr_test()
{
char uuid_cfg[] = {"/comtrade/"};
char uuid_dat[] = {"/comtrade/"};
char mp_id[] = {"qvvrtest123"};
char Qvvr_rptname[] = {"unknow"};
char devtype[] = {"01"};
transfer_json_qvvr_data(1, 123456789, 220, 180, 1730894400.123, 1730894580, 1210001,uuid_cfg,uuid_dat,mp_id,Qvvr_rptname,devtype);
transfer_json_qvvr_data("qvvrtest123", 6,
10.98, 1234, 1754566628692, 1,1,
"testwavepath");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////通用接口响应

View File

@@ -30,7 +30,7 @@ class Front;
///////////////////////////////////////////////////////////////////////////////////////////
//单条补招结构
//单条补招时间结构
class RecallInfo
{
public:
@@ -38,10 +38,109 @@ public:
long long endtime; //结束时间
};
//日志补招结构
//测点记录的补招结构
class RecallMonitor
{
public:
int recall_status; //补招状态 0-未补招 1-补招中 2-补招完成 3-补招失败
std::string StartTime; //数据补招起始时间
std::string EndTime; //数据补招结束时间
std::string STEADY; //补招历史统计数据标识 0-不补招1-补招
std::string VOLTAGE; //补招暂态事件标识 0-不补招1-补招
};
// ====== ★新增:下载/列目录阶段枚举与结果枚举 ======
enum class RecallPhase {
IDLE = 0,
LISTING, // 正在请求并等待“目录文件名列表”
DOWNLOADING // 正在按队列逐个下载
};
enum class ActionResult {
PENDING = -1, // 还未返回
FAIL = 0,
OK = 1
};
// ====== ★修改:扩展 RecallFile支持“多目录 + 文件筛选 + 串行下载”的状态机 ======
class RecallFile
{
public:
int recall_status; // 补招状态 0-未补招 1-补招中 2-补招完成 3-补招失败
std::string StartTime; // 数据补招起始时间yyyy-MM-dd HH:mm:ss
std::string EndTime; // 数据补招结束时间yyyy-MM-dd HH:mm:ss
std::string STEADY; // 补招历史统计数据标识 0-不补招1-补招
std::string VOLTAGE; // 补招暂态事件标识 0-不补招1-补招
//暂态文件用
bool direct_mode = false; // 直下文件开关true 表示不按时间窗,仅按目标文件名
std::string target_filename; // 直下文件名(不含目录)
std::list<std::string> file_paths; // 已下载/要上报的完整路径(用于最终结果)
// ★新增:按“目录名 -> 文件名列表”的映射;由“其他线程”在目录请求成功后回填
std::map<std::string, std::vector<tag_dir_info>> dir_files;
// ★新增:候选目录(可扩展)
std::vector<std::string> dir_candidates{
"/cf/COMTRADE",
"/bd0/COMTRADE",
"/sd0/COMTRADE",
"/sd0:1/COMTRADE"
};
// ★新增:状态机运行时变量
RecallPhase phase = RecallPhase::IDLE;
int cur_dir_index = 0; // 正在尝试的目录下标
std::string cur_dir; // 正在处理的目录
// ★新增:列目录/下载请求“回执位”,由其他线程置位
ActionResult list_result = ActionResult::PENDING; // 当前目录的列举结果
ActionResult download_result = ActionResult::PENDING; // 当前文件的下载结果
// ★新增:下载队列(已筛选出在时间窗内的文件,含完整路径)
std::list<std::string> download_queue;
std::string downloading_file; // 当前正在下载的文件(完整路径)
// ★新增:一个便捷复位
void reset_runtime(bool keep_direct = false)
{
phase = RecallPhase::IDLE;
cur_dir_index = 0;
cur_dir.clear();
list_result = ActionResult::PENDING;
download_result = ActionResult::PENDING;
download_queue.clear();
downloading_file.clear();
dir_files.clear();
// ★新增:按需保留直下文件开关和目标名
if (!keep_direct) {
direct_mode = false;
target_filename.clear();
}
}
};
enum class RecallStatus {
NOT_STARTED = 0, // 未补招
RUNNING = 1, // 补招中
DONE = 2, // 补招完成
FAILED = 3 // 补招失败
};
// 本轮要下发的一条任务(每个终端最多一条)
struct RecallTask {
std::string dev_id;
std::string start_time;
std::string end_time;
std::string monitor_index;
};
//日志补招结构类,当前不使用
class JournalRecall
{
public:
std::string DevID; //装置号
std::string MonitorID; //线路监测点号
std::string StartTime; //数据补招起始时间
std::string EndTime; //数据补招结束时间
@@ -49,30 +148,79 @@ public:
std::string VOLTAGE; //补招暂态事件标识 0-不补招1-补招
};
//录波文件和暂态事件
class qvvr_data
{
public:
bool used_status; //是否占用
int QVVR_type; //暂态类型
uint64_t QVVR_time; //暂态开始时间 unsigned longlong
double QVVR_PerTime; //暂态持续时间
double QVVR_Amg; //暂态幅值
int phase; //相别(仅瞬态上送)0-A 1-B 2-C 3-AB 4-BC 5-CA 其他-ABC/异常
};
class qvvr_file
{
public:
bool used_status;
int file_time_count; //组内文件下载时间计数第一个文件下载后十分钟内如果其他文件没下载全或者下载全了没匹配事件则将已下载的文件都移到备份区comtrade_bak
bool is_download; //文件是否下载完全,最后一个文件下载成功后对比成功则更新这个标志
bool is_pair; //文件是否和事件匹配从comtrade/mac/路径下取file_download中的cfg文件提取时间和持续时间来匹配匹配后接口发送这组file_download全部文件发送成功后删除这组文件然后更新事件中的文件列表
std::list<std::string> file_name; //文件列表(文件列表上送后就记录)
std::list<std::string> file_download; //文件已下载列表(每次列表上送会有多个文件多个文件都下载完全则开始匹配每次更新都去重并对比file_name
};
class qvvr_event
{
public:
std::vector<qvvr_data> qvvrdata; //暂态事件列表
std::vector<qvvr_file> qvvrfile; //暂态文件组列表
};
//监测点台账
class ledger_monitor
{
public:
std::string monitor_id; //监测点id
std::string terminal_id; //监测点
std::string terminal_id; //监测点的终端id
std::string monitor_name; //监测点名
std::string logical_device_seq; //监测点序号
std::string voltage_level; //监测点电压等级
std::string terminal_connect; //监测点接线方式
std::string timestamp; //更新时间
std::string status; //监测点状态
double PT1; // 电压变比1
double PT2; // 电压变比2
double CT1; // 电流变比1
double CT2; // 电流变比2
//暂态事件
qvvr_event qvvrevent;
//补招列表
std::list<RecallMonitor> recall_list; //事件
std::list<RecallFile> recall_list_static;//稳态文件
//定值list
std::list<float> set_values;
std::vector<DZ_TAB_STRUCT> dz_info_list; //定值信息列表
};
//终端台账
class terminal_dev
{
public:
std::string guid; //台账更新回复用
std::string guid; //正在进行的guid
int busytype; //业务类型,使用状态机
int isbusy; //业务进行标志
int busytimecount; //业务进行计时
//内部定值list
std::list<ushort> internal_values;
std::vector<NameFixValue> dz_internal_info_list; //内部定值信息列表
std::vector<DZ_kzz_bit> control_words;
std::string terminal_id;
std::string terminal_name;
@@ -84,13 +232,13 @@ public:
std::string dev_type;
std::string dev_key;
std::string dev_series;
std::string addr_str;
std::string port;
std::string addr_str; //装置ip
std::string port; //装置端口
std::string timestamp;
std::string processNo;
std::string maxProcessNum;
std::string mac; // 装置MAC地址
std::string mac; // 装置MAC地址接口中从addr_str获取因为ip和mac放同一位置
std::vector<ledger_monitor> line;
};
@@ -380,8 +528,8 @@ typedef struct {
// 单条 DataArray 数据
struct DataArrayItem {
int DataAttr;
int DataTimeSec;
int DataTimeUSec;
time_t DataTimeSec;
time_t DataTimeUSec;
int DataTag;
std::string Data;
};
@@ -397,6 +545,7 @@ struct MsgObj {
// 整体
struct FullObj {
std::string mac;
int Mid;
int Did;
int Pri;
@@ -409,11 +558,25 @@ void to_json(nlohmann::json& j, const DataArrayItem& d);
void to_json(nlohmann::json& j, const MsgObj& m);
void to_json(nlohmann::json& j, const FullObj& f);
/////////////////////////////////////////////////////////////////////云平台下发指令的解析
struct MsgParsed {
int type; // 指令编号
std::string name; // 文件名/目录名
int cldid; // 测点号
int datatype; // 指令细分
int operate; // 操作读写
std::vector<float> dataArray_f; // 定值写入,严格按照顺序
std::vector<uint16_t> dataArray_us; // 内部定值写入,严格按照顺序
bool ok;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////提供给通讯部分调用的函数
std::vector<DeviceInfo> GenerateDeviceInfoFromLedger(const std::vector<terminal_dev>& terminal_devlist);//接口读取台账后,再调用这个将台账拷贝过来
std::string generate_json( //构造装置主动上送数据的报文
const std::string mac,
int Mid, //需应答的报文订阅者收到后需以此ID应答无需应答填入“-1”
int Did, //设备唯一标识Ldid填入0代表Ndid。
int Pri, //报文处理的优先级
@@ -425,8 +588,120 @@ std::string generate_json( //构造装置主动上送数据的报文
const std::vector<DataArrayItem>& dataArray //数据数组。
);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//暂态事件接口
int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
double mag, double dur, long long start_tm, int dis_kind,int phase,
const std::string& wavepath);
//录波文件上传接口
void SOEFileWeb(std::string& localpath,std::string& cloudpath, std::string& wavepath);
//录波文件目录接口
bool assign_qvvr_file_list(const std::string& id, ushort nCpuNo, const std::vector<std::string>& file_list_raw);
//录波文件下载完成通知接口
bool update_qvvr_file_download(const std::string& filename_with_mac, const std::string& terminal_id);
//上送文件列表接口
bool send_file_list(const std::string &dev_id, const std::vector<tag_dir_info> &FileList);
//提取mac
std::string normalize_mac(const std::string& mac);
std::string get_mac_by_devid(const std::string &devid);
//暂态文件超时检测
void check_and_backup_qvvr_files();
//业务超时检查
void check_device_busy_timeout();
//业务上报
void send_reply_to_cloud(int reply_code, const std::string& dev_id, int type);
//查guid
std::string find_guid_index_from_dev_id(const std::string& dev_id);
//内部定值响应
bool send_internal_value_reply(const std::string &dev_id, const std::vector<DZ_kzz_bit> &control_words);
//定值响应
bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, const std::vector<DZ_TAB_STRUCT> &dz_info);
//保存内部定值描述
bool save_internal_info(const std::string &dev_id, const std::vector<NameFixValue> &fixValueList);
//保存内部定值数值
bool save_internal_value(const std::string &dev_id, const std::vector<ushort> &fabsf);
//保存定值数值
bool save_set_value(const std::string &dev_id, unsigned char mp_index, const std::vector<float> &fabsf);
//发送文件
void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath);
//状态翻转
void connect_status_update(const std::string& id, int status);
//业务停止
void clear_terminal_runtime_state(const std::string& id);
//业务响应
void on_device_response_minimal(int response_code,
const std::string& id,
unsigned char cid,
int device_state_int);
//处理补招的任务
void check_recall_event();
void check_recall_file();
//补招响应
void send_reply_to_kafka_recall(const std::string& guid, const std::string& step,int code, const std::string& result,const std::string& terminalId,const std::string& lineIndex,const std::string& recallStartDate,const std::string& recallEndDate);
//缓存目录信息
void filemenu_cache_put(const std::string& dev_id,
std::vector<tag_dir_info> FileList);
//提取目录信息
bool filemenu_cache_take(const std::string& dev_id, std::vector<tag_dir_info>& out);
//小工具
inline std::string trim_cstr(const char* s, size_t n) {
if (!s) return {};
size_t end = 0;
while (end < n && s[end] != '\0') ++end;
std::string out(s, s + end);
while (!out.empty() && (out.back() == ' ' || out.back() == '\t' || out.back() == '\r' || out.back() == '\n'))
out.pop_back();
return out;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern int g_front_seg_index;
extern std::string FRONT_IP;
extern std::string FRONT_PATH;
extern std::string WEB_FILEUPLOAD;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 响应码枚举
enum class ResponseCode : int {
OK = 200, // 请求成功
ACCEPTED = 201, // 请求被接受,开始处理
PROCESSING = 202, // 请求被接受,但是未处理完
BAD_REQUEST = 400, // 请求失败
UNAUTHORIZED = 401, // 请求未认证/认证错误(不支持的请求)
REJECTED_BUSY = 402, // 请求被拒绝,在处理同类命令
FORBIDDEN = 403, // 请求被拒绝(未知原因)
NOT_FOUND = 404, // 请求的资源不存在
BUSY = 405, // 当前忙,无法响应
TIMEOUT = 406, // 请求超出了等待时间
INTERNAL_ERROR = 500 // 其他错误
};
static inline bool is_ok(int rc) { return rc == static_cast<int>(ResponseCode::OK); }
static bool parse_datetime_tm(const std::string& s, std::tm& out) {
std::memset(&out, 0, sizeof(out));
return strptime(s.c_str(), "%Y-%m-%d %H:%M:%S", &out) != nullptr;
}
#endif

View File

@@ -50,19 +50,16 @@ extern std::string subdir;
//日志主题
extern std::string G_LOG_TOPIC;
//////////////////////////////////////////////////////////
/* log4.cpp 顶部 */
#if __cplusplus >= 201103L
thread_local int g_log_code_tls = 0;
#else
__thread int g_log_code_tls = 0;
#endif
////////////////////////////////////////////////////////辅助函数
/*std::string get_front_type_from_subdir() {
if (subdir == "cfg_3s_data")
return "realTime";
else if (subdir == "cfg_soe_comtrade")
return "comtrade";
else if (subdir == "cfg_recallhis_data")
return "recall";
else if (subdir == "cfg_stat_data")
return "stat";
else
return "unknown";
}*/
// 递归创建目录
bool create_directory_recursive(const std::string& path) {
@@ -145,6 +142,9 @@ protected:
else
level_str = "terminal";
// ★读取 TLS 中的 code在打日志的线程里由宏设定
int code = g_log_code_tls; // 若未显式传入,则为 0
if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) {
std::ostringstream oss;
oss << "{\"processNo\":\"" << std::to_string(g_front_seg_index)
@@ -154,6 +154,8 @@ protected:
<< "\",\"grade\":\"" << get_level_str(level)
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
<< "\",\"frontType\":\"" << "cloudfront"
// ★新增:输出 code 字段(整型)
<< "\",\"code\":\"" << code
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
std::string jsonString = oss.str();
@@ -334,8 +336,8 @@ void init_loggers_bydevid(const std::string& dev_id)
const ledger_monitor& monitor = term.line[j];
if (!monitor.monitor_id.empty()) {
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << monitor.monitor_id << ".COM";
mon_key_d << "monitor." << monitor.monitor_id << ".DATA";
mon_key_c << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".COM";
mon_key_d << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".DATA";
mon_path << device_dir << "/monitor" << j;
mon_name << monitor.monitor_id;
@@ -355,7 +357,7 @@ void init_loggers_bydevid(const std::string& dev_id)
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.monitor_id.c_str());
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
}
@@ -406,8 +408,8 @@ void init_loggers()
if (!monitor.monitor_id.empty()) {
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << monitor.monitor_id << ".COM";
mon_key_d << "monitor." << monitor.monitor_id << ".DATA";
mon_key_c << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".COM";
mon_key_d << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".DATA";
mon_path << device_dir << "/monitor" << i; // 用monitor+序号作为目录
mon_name << monitor.monitor_id;
@@ -425,7 +427,7 @@ void init_loggers()
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕",
monitor.monitor_name.c_str(), monitor.monitor_id.c_str());
monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
}

View File

@@ -1,6 +1,16 @@
#ifndef LOG4_H
#define LOG4_H
#if defined(__cplusplus) && __cplusplus >= 201103L
#define LOG_TLS_SPEC thread_local
#else
/* C 或旧编译器,走 GCC 扩展 */
#define LOG_TLS_SPEC __thread
#endif
/* ★统一的对外声明(别在其他头/源里再声明不同版本!) */
extern LOG_TLS_SPEC int g_log_code_tls;
#ifdef __cplusplus
#include <string>
@@ -88,7 +98,16 @@ void log_error(const char* key, const char* msg);
void send_reply_to_queue_c(const char* guid, const char* step, const char* result);
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
//宏定义
// ====================== ★新增:线程局部变量透传 code ======================
// 说明:使用编译器的 TLS__thread保存当前日志的 code 值。
// 在每次打日志前写入打完后恢复Appender 读取该值写入 JSON。
// ====================== ★新增结束 ======================
// ====================== 日志宏区域 ======================
// 原始不带 code 的实现(兼容/复用)
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
@@ -96,10 +115,52 @@ void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
LEVEL_FUNC(KEY, buf); \
} while (0)
#define DIY_ERRORLOG(KEY, ...) DIY_LOG(log_error, KEY, __VA_ARGS__)
#define DIY_WARNLOG(KEY, ...) DIY_LOG(log_warn, KEY, __VA_ARGS__)
#define DIY_INFOLOG(KEY, ...) DIY_LOG(log_info, KEY, __VA_ARGS__)
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG(log_debug, KEY, __VA_ARGS__)
// ★新增:带 code 的实现C/C++ 通用,使用 TLS 保存/恢复)
#define DIY_LOG_CODE(LEVEL_FUNC, KEY, CODE_INT, ...) \
do { \
int __old_code__ = g_log_code_tls; /* 备份旧值 */ \
g_log_code_tls = (int)(CODE_INT); /* 设置本次日志 code */ \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); /* 输出日志 */ \
g_log_code_tls = __old_code__; /* 恢复旧值 */ \
} while (0)
// ★修改:默认宏改为 code=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
typedef enum LogCode {
LOG_CODE_OTHER = 99, /* 其他类型 */
LOG_CODE_LEDGER = 100, /* 台账类型 */
LOG_CODE_RPTINIT = 101, /* 报告初始化 */
LOG_CODE_ICD_AND_DOWNLOAD = 200, /* ICD 和文件下载类型 */
LOG_CODE_TRANSIENT = 300, /* 暂态发生 */
LOG_CODE_TRANSIENT_COMM = 301, /* 暂态接口 */
LOG_CODE_COMTRADE_FILE = 302, /* 录波文件Comtrade */
LOG_CODE_MQ = 400, /* MQ发送 */
LOG_CODE_RT_DATA = 401, /* 实时数据 */
LOG_CODE_LEDGER_UPDATE = 402, /* 台账更新 */
LOG_CODE_PROCESS_CONTROL = 403, /* 进程控制 */
LOG_CODE_RECALL = 404, /* 补招相关 */
LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */
LOG_CODE_REPORT = 500, /* 报告处理 */
LOG_CODE_COMM = 600, /* 通讯状态 */
LOG_CODE_SPACE_ALARM = 700 /* 空间告警 */
} LogCode;
#ifdef __cplusplus

View File

@@ -215,7 +215,7 @@ std::string get_parent_directory() {
init_loggers();
//读取模型,下载模板文件
parse_model_cfg_web();
//parse_model_cfg_web();
//解析模板文件
//Set_xml_nodeinfo();
@@ -317,9 +317,12 @@ void Front::FrontThread() {
try {
while (!m_bIsFrontThreadCancle) {
check_3s_config(); // 实时数据触发
//create_recall_xml(); // 生成待补招xml文件
check_recall_file(); //处理补招文件-稳态和暂态
check_recall_event(); // 处理补招事件从list中读取然后直接调用接口,每一条可能都不同测点,每个测点自己做好记录
check_ledger_update(); // 触发台账更新
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} catch (const std::exception& e) {
std::cerr << "[FrontThread] Caught exception: " << e.what() << std::endl;
@@ -344,18 +347,32 @@ void Front::OnTimerThread()
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "OnTimerThread::run() is called ...... \n";
int counter = 0;
int hbCounter = 0; // 心跳计数
int backupCounter = 0; // 备份计数(分钟用)
send_heartbeat_to_queue("1");
while (!m_IsTimerCancel)
{
update_log_entries_countdown();
if (counter >= 30) {
//业务超时检查
check_device_busy_timeout();
// 每 30 秒发一次心跳
if (hbCounter >= 30) {
send_heartbeat_to_queue("1");
counter = 0;
hbCounter = 0;
}
counter++;
// 每 60 秒调用一次录波文件检查
if (backupCounter >= 60) {
check_and_backup_qvvr_files();
backupCounter = 0;
}
hbCounter++;
backupCounter++;
g_ontime_blocked_times = 0;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
@@ -366,7 +383,6 @@ void Front::OnTimerThread()
std::cerr << "[OnTimerThread] Caught unknown exception" << std::endl;
}
// 设置重启标志
{
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartTimerThread = true;
@@ -518,16 +534,35 @@ void Front::mqproducerThread()
extern thread_info_t thread_info[THREAD_CONNECTIONS];
void cleanup_args(ThreadArgs* args) {
for (int i = 0; i < args->argc; ++i) {
free(args->argv[i]); // strdup 分配的
}
delete[] args->argv;
delete args;
}
void* cloudfrontthread(void* arg) {
///////////////////////////////////////
ThreadArgs* args = static_cast<ThreadArgs*>(arg);
int argc = args->argc;
char **argv = args->argv;
printf("argc = %d, argv[0] = %s\n", argc, argv[0]);
printf("[cloudfrontthread] argc = %d\n", argc);
for (int i = 0; i < argc; ++i) {
printf(" argv[%d] = %s\n", i, argv[i]);
}
//添加线程处理
int index = *(int*)argv[0];
// 动态解析线程 index
int index = 0;
if (argc > 0 && argv[0]) {
try {
index = std::stoi(argv[0]);
} catch (...) {
std::cerr << "[cloudfrontthread] Failed to parse index from argv[0]: " << argv[0] << "\n";
return nullptr;
}
}
// 更新线程状态为运行中
pthread_mutex_lock(&thread_info[index].lock);
@@ -539,11 +574,12 @@ void* cloudfrontthread(void* arg) {
// 解析命令行参数
if(!parse_param(argc,argv)){
std::cerr << "process param error,exit" << std::endl;
cleanup_args(args);
return nullptr;
}
// 线程使用完后清理参数
delete args;
cleanup_args(args);
//路径获取
FRONT_PATH = get_parent_directory();

View File

@@ -37,6 +37,8 @@
#include "interface.h"
#include "front.h"
#include "../../client2.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
using namespace std;
@@ -60,7 +62,6 @@ static rocketmq::RocketMQProducer* g_producer = nullptr; //生产者
//前置进程
extern unsigned int g_node_id;
extern int g_front_seg_index;
extern std::string subdir;
extern std::string FRONT_INST;
@@ -76,7 +77,7 @@ extern std::vector<std::string> TESTARRAY;
////////////////////////////////////////////////////////////////////////////////////////////////////////外部文件函数声明
extern void execute_bash(std::string fun,int process_num,std::string type);
extern int recall_json_handle(const std::string& jstr);
extern int recall_json_handle_from_mq(const std::string& body);
//////////////////////////////////////////////////////////////////////////////////////////////////////本文件函数向前声明
@@ -339,6 +340,7 @@ void my_rocketmq_send(queue_data_t& data,rocketmq::RocketMQProducer* producer)
/////////////////////////////////////////////////////////////////////////////////////////////////查找台账下标
// 根据终端 ID 查找 terminal_devlist 中的索引,找不到返回 -1
int find_dev_index_from_dev_id(const std::string& dev_id) {
std::lock_guard<std::mutex> lock(ledgermtx);
for (size_t i = 0; i < terminal_devlist.size(); ++i) {
if (terminal_devlist[i].terminal_id == dev_id) {
return static_cast<int>(i);
@@ -348,6 +350,7 @@ int find_dev_index_from_dev_id(const std::string& dev_id) {
}
int find_mp_index_from_mp_id(const std::string& mp_id) {
std::lock_guard<std::mutex> lock(ledgermtx);
for (const auto& dev : terminal_devlist) {
for (size_t j = 0; j < dev.line.size(); ++j) {
if (dev.line[j].monitor_id == mp_id) {
@@ -358,65 +361,19 @@ int find_mp_index_from_mp_id(const std::string& mp_id) {
return -1; // 未找到
}
/////////////////////////////////////////////////////////////////////////////////////////////////回调函数的json处理
std::string parseJsonMessageRC(const std::string& inputJson) {
// 解析输入 JSON 字符串
json root;
try {
root = json::parse(inputJson);
} catch (const std::exception& e) {
std::cerr << "Error parsing JSON: " << e.what() << std::endl;
return "";
}
// 提取 "messageBody" 部分(它是一个字符串)
if (!root.contains("messageBody") || !root["messageBody"].is_string()) {
std::cerr << "'messageBody' is missing or is not a string" << std::endl;
return "";
}
std::string messageBodyStr = root["messageBody"].get<std::string>();
if (messageBodyStr.empty()) {
std::cerr << "'messageBody' is empty" << std::endl;
return "";
}
// 解析 messageBody 中的 JSON 字符串
json messageBody;
try {
messageBody = json::parse(messageBodyStr);
} catch (const std::exception& e) {
std::cerr << "Failed to parse 'messageBody' JSON: " << e.what() << std::endl;
return "";
}
// 提取 "guid" 部分
if (!messageBody.contains("guid") || !messageBody["guid"].is_string()) {
std::cerr << "'guid' is missing or is not a string" << std::endl;
return "";
}
std::string guid = messageBody["guid"].get<std::string>();
// 发送 guid 回复
send_reply_to_queue(guid, "1", "收到补招指令");
// 提取 "data" 部分
if (!messageBody.contains("data") || !messageBody["data"].is_array()) {
std::cerr << "'data' is missing or is not an array" << std::endl;
return "";
}
// 返回 "data" 数组的字符串形式
try {
return messageBody["data"].dump(); // 默认带缩进如需去除缩进dump(-1)
} catch (const std::exception& e) {
std::cerr << "Error converting 'data' to string: " << e.what() << std::endl;
return "";
std::string find_guid_index_from_dev_id(const std::string& dev_id) {
std::lock_guard<std::mutex> lock(ledgermtx);
for (size_t i = 0; i < terminal_devlist.size(); ++i) {
if (terminal_devlist[i].terminal_id == dev_id) {
return terminal_devlist[i].guid;
}
}
return ""; // 未找到
}
bool parseJsonMessageRT(const std::string& body,std::string& devSeries,std::string& line,bool& realData,bool& soeData,int& limit){
/////////////////////////////////////////////////////////////////////////////////////////////////回调函数的json处理
bool parseJsonMessageRT(const std::string& body,std::string& devSeries,ushort& line,bool& realData,bool& soeData,int& limit){
json root;
try {
root = json::parse(body);
@@ -459,7 +416,7 @@ bool parseJsonMessageRT(const std::string& body,std::string& devSeries,std::stri
try {
devSeries = messageBody["devSeries"].get<std::string>();
line = messageBody["line"].get<std::string>();
line = messageBody["line"].get<ushort>();
realData = messageBody["realData"].get<bool>();
soeData = messageBody["soeData"].get<bool>();
limit = messageBody["limit"].get<int>();
@@ -846,7 +803,8 @@ rocketmq::ConsumeStatus myMessageCallbackrtdata(const rocketmq::MQMessageExt& ms
}
// 消息解析
std::string devid, line;
std::string devid;
ushort line;
bool realData = false, soeData = false;
int limit = 0;
@@ -857,28 +815,24 @@ rocketmq::ConsumeStatus myMessageCallbackrtdata(const rocketmq::MQMessageExt& ms
}
// 加锁访问台账
int dev_index;
int mp_index;
if( !devid.empty() && !line.empty()){
std::lock_guard<std::mutex> lock(ledgermtx);
dev_index = find_dev_index_from_dev_id(devid);
mp_index = find_mp_index_from_mp_id(line);
if( !devid.empty() && line > 0){
//不再使用文件触发方式,直接调用接口向终端发起请求
//不注册guid直接将请求指令下发装置排队处理
//添加在线判断
if (ClientManager::instance().get_dev_status(devid) != 1) {
std::cout << "devid对应装置不在线: " << devid << std::endl;
// 记录日志不响应 web 端
DIY_ERRORLOG("process","【ERROR】前置的%d号进程处理topic:%s_%s的补招触发消息失败,装置%s不在线", g_front_seg_index,FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RT.c_str(),devid.c_str());
return rocketmq::CONSUME_SUCCESS;
}
ClientManager::instance().set_real_state_count(devid, 60, line);//一秒询问一次询问60次,下一次同一个测点调用的话就会刷新
}
else{
std::cerr << "rtdata is NULL." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%d号进程处理topic:%s_%s的补招触发消息失败,消息的json结构不正确", g_front_seg_index,FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RT.c_str());
}
if (dev_index == -1 || mp_index == -1) {
std::cerr << "dev index or mp index is not found" << std::endl;
return rocketmq::RECONSUME_LATER;
}
// 写入 XML
if (!createXmlFile(dev_index, mp_index, realData, soeData, limit, "new")) {
DIY_ERRORLOG("process", "【ERROR】前置无法创建实时数据触发文件");
std::cerr << "Failed to create the XML file." << std::endl;
return rocketmq::RECONSUME_LATER;
}
@@ -1003,18 +957,7 @@ rocketmq::ConsumeStatus myMessageCallbackrecall(const rocketmq::MQMessageExt& ms
}
// 解析 JSON 字符串
std::string result = parseJsonMessageRC(body); // 使用 std::string 接收解析结果
std::cout << "parseJsonMessageRC: " << result << std::endl;
if (!result.empty()) {
std::lock_guard<std::mutex> lock(ledgermtx);
recall_json_handle(result);
} else {
std::cerr << "recall data is NULL." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%d号进程处理topic:%s_%s的补招触发消息失败,消息的json结构不正确", g_front_seg_index,FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RC.c_str());
}
recall_json_handle_from_mq(body);//不再使用文件补招方式
return rocketmq::CONSUME_SUCCESS;
}
@@ -1613,3 +1556,464 @@ void rocketmq_test_rc(Front* front)//用来测试补招
queue_data_list.push_back(data);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////云前置新增功能
bool parseJsonMessageCLOUD(const std::string &body,
std::string &devid,
std::string &guid,
nlohmann::json &detailObj, // 这里返回整个 Detail
std::string &front_ip, // 新增:返回 FrontIP
int &node) // 新增:返回 Node
{
try {
auto j = nlohmann::json::parse(body);
// guid
if (j.contains("guid") && j["guid"].is_string()) {
guid = j["guid"].get<std::string>();
} else {
guid.clear();
}
// FrontIP
if (j.contains("FrontIP") && j["FrontIP"].is_string()) {
front_ip = j["FrontIP"].get<std::string>();
} else {
front_ip.clear();
}
// Node
if (j.contains("Node") && j["Node"].is_number_integer()) {
node = j["Node"].get<int>();
} else {
node = 0;
}
// Dev_id兼容字符串或数字
if (j.contains("Dev_id")) {
if (j["Dev_id"].is_string()) {
devid = j["Dev_id"].get<std::string>();
} else if (j["Dev_id"].is_number_integer()) {
devid = std::to_string(j["Dev_id"].get<long long>());
} else if (j["Dev_id"].is_number_unsigned()) {
devid = std::to_string(j["Dev_id"].get<unsigned long long>());
} else if (j["Dev_id"].is_number_float()) {
devid = std::to_string(j["Dev_id"].get<double>());
} else {
devid.clear();
}
} else {
devid.clear();
}
// Detail完整放入 detailObj
if (j.contains("Detail") && j["Detail"].is_object()) {
detailObj = j["Detail"]; // 直接保存整个 Detail
} else {
detailObj = nlohmann::json::object();
}
return true;
}
catch (const std::exception &e) {
std::cerr << "[parseJsonMessageCLOUD] JSON parse error: " << e.what() << "\n";
guid.clear();
devid.clear();
front_ip.clear();
node = 0;
detailObj = nlohmann::json::object();
return false;
}
}
int recordguid(const std::string &devid,
const std::string &guid,
int busytype,int busycount)
{
std::lock_guard<std::mutex> lock(ledgermtx);
for (auto &dev : terminal_devlist) {
if (dev.terminal_id == devid) {
if (dev.isbusy == 1) {
std::cout << "Dev is busybusytype is" << dev.busytype << std::endl;
//响应guid:正忙
return dev.busytype; // 正在忙,不能记录
}
dev.guid = guid;
dev.busytype = busytype;
dev.isbusy = busycount;
dev.busytimecount = 0;
return 0;
}
}
std::cout << "Dev not found" << std::endl;
//响应guid:失败
return -1; // 未找到对应的装置
}
// 按 type 解析 Msg
bool parsemsg(const std::string& devid, const std::string& guid, const nlohmann::json& detailObj) {
MsgParsed parsed;
nlohmann::json msgObj;
// 直接解析 detailObj 的 Type
if (detailObj.contains("Type")) {
if (detailObj["Type"].is_string()) {
try {
parsed.type = std::stoi(detailObj["Type"].get<std::string>(), nullptr, 0); // 支持 "0x2106" 格式
} catch (...) {
return false;
}
} else if (detailObj["Type"].is_number_integer()) {
parsed.type = detailObj["Type"].get<int>();
} else if (detailObj["Type"].is_number_unsigned()) {
parsed.type = static_cast<int>(detailObj["Type"].get<unsigned int>());
} else {
return false;
}
} else {
return false;
}
// 直接解析 detailObj 的 Msg
if (detailObj.contains("Msg") && detailObj["Msg"].is_object()) {
msgObj = detailObj["Msg"];
} else {
msgObj = nlohmann::json::object();
}
try {
switch (parsed.type) {
case 0x2131: { // 读取目录
if(!recordguid(devid,guid,static_cast<int>(DeviceState::READING_FILEMENU),1)){
return true;
}
if (!msgObj.contains("Name") || !msgObj["Name"].is_string()) return false;
parsed.name = msgObj["Name"].get<std::string>();
parsed.ok = true;
std::cout << "[dir parsemsg] Name: " << parsed.name << std::endl;
// 添加指令到队列当中
ClientManager::instance().add_file_menu_action_to_device(devid, parsed.name);
return true;
}
case 0x2132: { // 下载文件
if(!recordguid(devid,guid,static_cast<int>(DeviceState::READING_FILEDATA),1)){
return true;
}
if (!msgObj.contains("Name") || !msgObj["Name"].is_string()) return false;
parsed.name = msgObj["Name"].get<std::string>();
parsed.ok = true;
std::cout << "[file parsemsg] Name: " << parsed.name << std::endl;
// 下发指令
ClientManager::instance().add_file_download_action_to_device(devid, parsed.name);
return true;
}
case 0x2106: { // 定值/内部定值
if (!msgObj.contains("Cldid") || !msgObj["Cldid"].is_number_integer()) return false;
if (!msgObj.contains("DataType") || !msgObj["DataType"].is_number_integer()) return false;
if (!msgObj.contains("Operate") || !msgObj["Operate"].is_number_integer()) return false;
if (!msgObj.contains("DataArray")|| !msgObj["DataArray"].is_array()) return false;
parsed.cldid = msgObj["Cldid"].get<int>();
parsed.datatype = msgObj["DataType"].get<int>();
parsed.operate = msgObj["Operate"].get<int>();
// 调试打印
std::cout << "[parsemsg] Cldid=" << parsed.cldid
<< ", DataType=0x" << std::hex << parsed.datatype << std::dec
<< ", Operate=" << parsed.operate
<< std::endl;
// 先清空数组,避免复用对象时残留
parsed.dataArray_f.clear();
parsed.dataArray_us.clear();
switch (parsed.datatype) {
case 0x0C: { // 定值float 阵列)
for (const auto& v : msgObj["DataArray"]) {
if (!v.is_number()) return false;
// 统一按 double 取,再强转成 float 更稳妥
parsed.dataArray_f.push_back(static_cast<float>(v.get<double>()));
}
// 打印 DataArray
std::cout << "[0x0C] DataArray=[";
for (size_t i = 0; i < parsed.dataArray_f.size(); ++i) {
std::cout << parsed.dataArray_f[i] << (i + 1 < parsed.dataArray_f.size() ? ", " : "");
}
std::cout << "]" << std::endl;
parsed.ok = true;
// 根据 Operate 分流1=读2=写)
switch (parsed.operate) {
case 1: { // 读
if(!recordguid(devid,guid,static_cast<int>(DeviceState::READING_FIXEDVALUE),2)){
return true;
}
ClientManager::instance().get_fixedvalue_action_to_device(
devid, static_cast<uint16_t>(parsed.cldid)); // 获取装置测点定值数据
ClientManager::instance().get_fixedvaluedes_action_to_device(devid); // 获取装置定值描述 只有这一步可以响应成功和关闭
break;
}
case 2: { // 写
if(!recordguid(devid,guid,static_cast<int>(DeviceState::SET_FIXEDVALUE),1)){
return true;
}
ClientManager::instance().set_fixedvalue_action_to_device(
devid, static_cast<uint16_t>(parsed.cldid), parsed.dataArray_f); // 装置修改定值
break;
}
default:
return false;
}
break;
}
case 0x0D: { // 内部定值uint16_t 阵列)
for (const auto& v : msgObj["DataArray"]) {
if (!v.is_number_integer() && !v.is_number_unsigned()) return false;
// 范围校验 [0, 65535]
long long val = v.get<long long>();
if (val < 0 || val > 65535) return false;
parsed.dataArray_us.push_back(static_cast<uint16_t>(val));
}
// 打印 DataArray
std::cout << "[0x0D] DataArray=[";
for (size_t i = 0; i < parsed.dataArray_us.size(); ++i) {
std::cout << parsed.dataArray_us[i] << (i + 1 < parsed.dataArray_us.size() ? ", " : "");
}
std::cout << "]" << std::endl;
parsed.ok = true;
// 根据 Operate 分流1=读2=写)
switch (parsed.operate) {
case 1: { // 读
if(!recordguid(devid,guid,static_cast<int>(DeviceState::READING_INTERFIXEDVALUE),3)){
return true;
}
ClientManager::instance().get_interfixedvalue_action_to_device(devid); // 获取内部定值
ClientManager::instance().get_fixedvalucontrolword_action_to_device(devid, 1); // 1-内部定值描述
ClientManager::instance().get_fixedvalucontrolword_action_to_device(devid, 2); // 2-控制字描述 只有这一步可以响应成功和关闭
break;
}
case 2: { // 写
if(!recordguid(devid,guid,static_cast<int>(DeviceState::SET_INTERFIXEDVALUE),1)){
return true;
}
ClientManager::instance().set_interfixedvalue_action_to_device(devid, parsed.dataArray_us);
break;
}
default:
return false;
}
break;
}
default:
return false;
}
return true;
}
default:
return false;
}
} catch (const std::exception& e) {
std::cerr << "[parsemsg] exception: " << e.what() << std::endl;
return false;
} catch (...) {
std::cerr << "[parsemsg] unknown exception" << std::endl;
return false;
}
}
//心跳和其他响应
void send_reply_to_cloud(int reply_code, const std::string& dev_id, int type) {
try {
std::string guid = find_guid_index_from_dev_id(dev_id);
if(guid == "")
{
std::cerr << "dev: " << dev_id << " guid not found" << std::endl;
return;
}
// ---- 构造根 JSON ----
nlohmann::json obj;
obj["guid"] = guid;
obj["FrontIP"] = FRONT_IP;
obj["Node"] = g_front_seg_index;
// Dev_mac从台账取 addr_str 并规范化
std::string mac = get_mac_by_devid(dev_id);
obj["Dev_mac"] = mac;
// ---- 构造 Detail ----
nlohmann::json detail;
detail["Type"] = type;
// Msg
nlohmann::json msg;
msg["Time"] = static_cast<long long>(std::time(nullptr));
detail["Msg"] = std::move(msg);
// Code
detail["Code"] = reply_code;
obj["Detail"] = std::move(detail);
// ---- 入队发送 ----
queue_data_t connect_info;
connect_info.strTopic = Topic_Reply_Topic;
connect_info.strText = obj.dump(); // 序列化为字符串
{
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
queue_data_list.push_back(std::move(connect_info));
}
// 调试打印
std::cout << "[send_reply_to_cloud] queued: " << obj.dump() << std::endl;
}
catch (const std::exception& e) {
std::cerr << "send_reply_to_cloud exception: " << e.what() << std::endl;
}
}
//云前置功能
rocketmq::ConsumeStatus cloudMessageCallback(const rocketmq::MQMessageExt& msg) {
//未初始化不处理消费
if (INITFLAG != 1) {
return rocketmq::RECONSUME_LATER;
}
std::string body = msg.getBody();
std::string key = msg.getKeys();
if (body.empty()) {
std::cerr << "Message body is NULL or empty." << std::endl;
return rocketmq::RECONSUME_LATER;
}
// 日志记录
DIY_INFOLOG("process", "【NORMAL】前置消费topic:%s_%s的云前置控制消息",FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_CLOUD.c_str());
std::cout << "cloud Callback received message: " << body << std::endl;
if (!key.empty()) {
std::cout << "Message Key: " << key << std::endl;
} else {
std::cout << "Message Key: N/A" << std::endl;
}
// 消息解析
std::string guid;
std::string devid;
std::string FrontIP;
int Node;
nlohmann::json DetailObj;
if (!parseJsonMessageCLOUD(body, devid, guid, DetailObj,FrontIP,Node)) {
std::cerr << "Failed to parse the JSON message." << std::endl;
DIY_ERRORLOG("process", "【ERROR】前置消费topic:%s_%s的云前置控制消息失败,消息的json格式不正确", FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RT.c_str());
return rocketmq::RECONSUME_LATER;
}
// ====== 调试打印 ======
std::cout << "[CLOUD Msg Parsed] "
<< "guid=" << guid
<< ", devid=" << devid
<< ", FrontIP=" << FrontIP
<< ", Node=" << Node
<< std::endl;
if(FrontIP != FRONT_IP || Node != g_front_seg_index){
std::cout << "当前进程不消费这个消息" << std::endl;
return rocketmq::CONSUME_SUCCESS;
}
if(!parsemsg(devid,guid,DetailObj)){
std::cerr << "clouddata is error." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%d号进程处理topic:%s_%s的云前置控制消息失败,消息无法解析", g_front_seg_index,FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RT.c_str());
}
return rocketmq::CONSUME_SUCCESS;
}
void rocketmq_test_getdir(Front* front)//用来测试目录获取
{
if (!front || !front->m_producer) {
std::cerr << "front 或 producer 无效\n";
return;
}
rocketmq::RocketMQProducer* producer = front->m_producer;
queue_data_t data;
data.monitor_no = 123;
data.strTopic = G_MQCONSUMER_TOPIC_CLOUD;
std::ifstream file("getdir.txt"); // 文件中存储长字符串
std::stringstream buffer;
buffer << file.rdbuf(); // 读取整个文件内容
data.strText = std::string(buffer.str());
data.mp_id = "123123";
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
queue_data_list.push_back(data);
}
//状态翻转
void connect_status_update(const std::string& id, int status)
{
// 获取当前系统时间(格式: YYYY-MM-DD HH:MM:SS
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
localtime_r(&now_c, &tm_buf);
std::ostringstream datetime_ss;
datetime_ss << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S");
std::string datetime_str = datetime_ss.str();
// 构造 JSON 对象
nlohmann::json j;
j["id"] = id;
j["date"] = datetime_str;
j["status"] = std::to_string(status);
// 构造队列消息
queue_data_t connect_info;
connect_info.strTopic = G_CONNECT_TOPIC;
connect_info.strText = j.dump(); // 转成字符串
{
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
queue_data_list.push_back(std::move(connect_info));
}
// 调试打印
std::cout << "[connect_status_update] queued JSON:\n" << j.dump(4) << std::endl;
}

View File

@@ -86,6 +86,10 @@ extern std::string G_MQCONSUMER_TOPIC_LOG;
extern std::string G_MQCONSUMER_TAG_LOG;
extern std::string G_MQCONSUMER_KEY_LOG;
extern std::string G_MQCONSUMER_TOPIC_CLOUD;
extern std::string G_MQCONSUMER_TAG_CLOUD;
extern std::string G_MQCONSUMER_KEY_CLOUD;
extern std::string G_LOG_TOPIC;
extern std::string G_LOG_TAG;
extern std::string G_LOG_KEY;
@@ -336,7 +340,7 @@ void rocketmq_test_rc(Front* front);
void rocketmq_test_set(Front* front);
void rocketmq_test_ud(Front* front);
void rocketmq_test_rt(Front* front);
void rocketmq_test_getdir(Front* front);
void InitializeProducer(rocketmq::RocketMQProducer*& producer);
#endif // _ROCKETMQ_CLIENT_WRAPPER_H_

View File

@@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
@@ -294,6 +294,7 @@ extern bool normalOutputEnabled;
"G_TEST_NUM=<num> - Set the G_TEST_NUM\r\n"
"G_TEST_TYPE=<num> - Set the G_TEST_TYPE 0:use ledger,1:use number\r\n"
"LOG=<bool> - Set the LOG\r\n"
"dir - Execute rocketmq_test_getdir\r\n"
"rc - Execute rocketmq_test_rc\r\n"
"rt - Execute rocketmq_test_rt\r\n"
"ud - Execute rocketmq_test_ud\r\n"
@@ -325,6 +326,9 @@ extern bool normalOutputEnabled;
} else if (cmd == "rc") {
rocketmq_test_rc(m_front);
sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_rc\r\n");
} else if (cmd == "getdir") {
rocketmq_test_getdir(m_front);
sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_getdir\r\n");
} else if (cmd == "rt") {
rocketmq_test_rt(m_front);
sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_rt\r\n");
@@ -405,49 +409,203 @@ extern bool normalOutputEnabled;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////测试shell用的函数
void Worker::printLedgerinshell(const terminal_dev& dev, int fd) {
// —— 显示控制:最多打印的元素数量(防止过长)——
constexpr size_t MAX_ITEMS = 5; // 可按需调整或删除限制
std::ostringstream os;
os << "\r\x1B[K------------------------------------\n";
os << "\r\x1B[K|-- terminal_id: " << dev.terminal_id << "\n";
os << "\r\x1B[K|-- terminal_name: " << dev.terminal_name << "\n";
os << "\r\x1B[K|-- dev_ip: " << dev.addr_str << "\n";
os << "\r\x1B[K|-- dev_port: " << dev.port << "\n";
os << "\r\x1B[K|-- dev_type: " << dev.dev_type << "\n";
os << "\r\x1B[K|-- dev_key: " << dev.dev_key << "\n";
os << "\r\x1B[K|-- dev_series: " << dev.dev_series << "\n";
os << "\r\x1B[K|-- dev_processNo: " << dev.processNo << "\n";
os << "\r\x1B[K|-- maxProcessNum: " << dev.maxProcessNum << "\n";
os << "\r\x1B[K|-- org_name: " << dev.org_name << "\n";
os << "\r\x1B[K|-- maint_name: " << dev.maint_name << "\n";
os << "\r\x1B[K|-- station_name: " << dev.station_name << "\n";
os << "\r\x1B[K|-- tmnl_factory: " << dev.tmnl_factory << "\n";
os << "\r\x1B[K|-- tmnl_status: " << dev.tmnl_status << "\n";
os << "\r\x1B[K|-- timestamp: " << dev.timestamp << "\n";
os << "\r\x1B[K|-- terminal_id : " << dev.terminal_id << "\n";
os << "\r\x1B[K|-- terminal_name : " << dev.terminal_name << "\n";
os << "\r\x1B[K|-- dev_ip : " << dev.addr_str << "\n";
os << "\r\x1B[K|-- dev_port : " << dev.port << "\n";
os << "\r\x1B[K|-- dev_type : " << dev.dev_type << "\n";
os << "\r\x1B[K|-- dev_key : " << dev.dev_key << "\n";
os << "\r\x1B[K|-- dev_series : " << dev.dev_series << "\n";
os << "\r\x1B[K|-- dev_processNo : " << dev.processNo << "\n";
os << "\r\x1B[K|-- maxProcessNum : " << dev.maxProcessNum << "\n";
os << "\r\x1B[K|-- org_name : " << dev.org_name << "\n";
os << "\r\x1B[K|-- maint_name : " << dev.maint_name << "\n";
os << "\r\x1B[K|-- station_name : " << dev.station_name << "\n";
os << "\r\x1B[K|-- tmnl_factory : " << dev.tmnl_factory << "\n";
os << "\r\x1B[K|-- tmnl_status : " << dev.tmnl_status << "\n";
os << "\r\x1B[K|-- timestamp : " << dev.timestamp << "\n";
os << "\r\x1B[K|-- mac : " << dev.mac << "\n";
os << "\r\x1B[K|-- mac: " << dev.mac << "\n";
// ========================= 终端级 · 内部定值 =========================
// internal_valuesushort 列表)与 dz_internal_info_list 一一对应,仅展示前 MAX_ITEMS 条
os << "\r\x1B[K|-- Internal Values (" << dev.internal_values.size() << "):\n";
{
size_t idx = 0;
for (auto itv = dev.internal_values.begin();
itv != dev.internal_values.end() && idx < MAX_ITEMS;
++itv, ++idx) {
os << "\r\x1B[K |-- [" << idx << "] value: " << static_cast<unsigned>(*itv) << "\n";
}
if (dev.internal_values.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (dev.internal_values.size() - MAX_ITEMS) << " more)\n";
}
}
// dz_internal_info_listNameFixValue 描述,和 internal_values 对应)
os << "\r\x1B[K|-- Internal Value Descriptions (" << dev.dz_internal_info_list.size() << "):\n";
{
const size_t n = dev.dz_internal_info_list.size();
for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) {
const auto& nf = dev.dz_internal_info_list[i];
os << "\r\x1B[K |-- [" << i << "] "
<< "Name=" << trim_cstr(nf.sFixValueName, sizeof(nf.sFixValueName))
<< ", Type=" << nf.DataType
<< ", Unit=" << trim_cstr(nf.sDimension, sizeof(nf.sDimension))
<< ", Min=" << nf.MinValue
<< ", Max=" << nf.MaxValue
<< ", Default=" << nf.DefaultValue
<< "\n";
}
if (n > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n";
}
}
// control_words控制字描述
os << "\r\x1B[K|-- Control Words (" << dev.control_words.size() << "):\n";
{
const size_t n = dev.control_words.size();
for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) {
const DZ_kzz_bit& b = dev.control_words[i];
os << "\r\x1B[K |-- [" << i << "] "
<< "name=\"" << trim_cstr(b.kzz_bit, sizeof(b.kzz_bit)) << "\""
<< ", enable=" << static_cast<int>(b.bit_enable) << "\n";
}
if (n > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n";
}
}
// ========================= 监测点级 · line =========================
for (size_t i = 0; i < dev.line.size(); ++i) {
const auto& ld = dev.line[i];
if (ld.monitor_id.empty()) continue;
os << "\r\x1B[K|-- line[" << i << "]:\n";
os << "\r\x1B[K |-- monitor_id: " << ld.monitor_id << "\n";
os << "\r\x1B[K |-- monitor_name: " << ld.monitor_name << "\n";
os << "\r\x1B[K |-- logical_device_seq: " << ld.logical_device_seq << "\n";
os << "\r\x1B[K |-- terminal_id: " << ld.terminal_id << "\n";
os << "\r\x1B[K |-- voltage_level: " << ld.voltage_level << "\n";
os << "\r\x1B[K |-- terminal_connect: " << ld.terminal_connect << "\n";
os << "\r\x1B[K |-- status: " << ld.status << "\n";
os << "\r\x1B[K |-- timestamp: " << ld.timestamp << "\n";
os << "\r\x1B[K |-- monitor_id : " << ld.monitor_id << "\n";
os << "\r\x1B[K |-- monitor_name : " << ld.monitor_name << "\n";
os << "\r\x1B[K |-- logical_device_seq : " << ld.logical_device_seq << "\n";
os << "\r\x1B[K |-- terminal_id : " << ld.terminal_id << "\n";
os << "\r\x1B[K |-- voltage_level : " << ld.voltage_level << "\n";
os << "\r\x1B[K |-- terminal_connect : " << ld.terminal_connect << "\n";
os << "\r\x1B[K |-- status : " << ld.status << "\n";
os << "\r\x1B[K |-- timestamp : " << ld.timestamp << "\n";
os << "\r\x1B[K |-- CT1=" << ld.CT1 << ", CT2=" << ld.CT2
<< ", PT1=" << ld.PT1 << ", PT2=" << ld.PT2 << "\n";
os << "\r\x1B[K |-- CT1: " << ld.CT1 << "\n";
os << "\r\x1B[K |-- CT2: " << ld.CT2 << "\n";
os << "\r\x1B[K |-- PT1: " << ld.PT1 << "\n";
os << "\r\x1B[K |-- PT2: " << ld.PT2 << "\n";
// --- 监测点 · 定值set_values ---
os << "\r\x1B[K |-- Set Values (" << ld.set_values.size() << "):\n";
{
size_t idx = 0;
for (auto it = ld.set_values.begin();
it != ld.set_values.end() && idx < MAX_ITEMS;
++it, ++idx) {
os << "\r\x1B[K |-- [" << idx << "] " << *it << "\n";
}
if (ld.set_values.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (ld.set_values.size() - MAX_ITEMS) << " more)\n";
}
}
// --- 监测点 · 定值描述文件dz_info_list ---
os << "\r\x1B[K |-- DZ Table (" << ld.dz_info_list.size() << "):\n";
{
const size_t n = ld.dz_info_list.size();
for (size_t j = 0; j < n && j < MAX_ITEMS; ++j) {
const DZ_TAB_STRUCT& z = ld.dz_info_list[j];
os << "\r\x1B[K |-- [" << j << "] "
<< "LN=" << z.LN_Num
<< ", DZ=" << z.DZ_Num
<< ", Name=" << trim_cstr(z.DZ_Name, sizeof(z.DZ_Name))
<< ", Type=" << z.DZ_Type
<< ", Min=" << z.DZ_Min
<< ", Max=" << z.DZ_Max
<< ", Def=" << z.DZ_Default
<< ", Unit=" << trim_cstr(z.DZ_UNIT, sizeof(z.DZ_UNIT))
<< "\n";
}
if (n > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n";
}
}
// --- 监测点 · 暂态事件qvvrevent ---
os << "\r\x1B[K |-- QVVR Event:\n";
// 1) 暂态事件列表
os << "\r\x1B[K |-- Events (" << ld.qvvrevent.qvvrdata.size() << "):\n";
{
const size_t n = ld.qvvrevent.qvvrdata.size();
for (size_t k = 0; k < n && k < MAX_ITEMS; ++k) {
const qvvr_data& e = ld.qvvrevent.qvvrdata[k];
os << "\r\x1B[K |-- [" << k << "] "
<< "used=" << e.used_status
<< ", type=" << e.QVVR_type
<< ", time=" << static_cast<unsigned long long>(e.QVVR_time)
<< ", per=" << e.QVVR_PerTime
<< ", amp=" << e.QVVR_Amg
<< ", phase="<< e.phase
<< "\n";
}
if (n > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n";
}
}
// 2) 文件组列表
os << "\r\x1B[K |-- File Groups (" << ld.qvvrevent.qvvrfile.size() << "):\n";
{
const size_t n = ld.qvvrevent.qvvrfile.size();
for (size_t g = 0; g < n && g < MAX_ITEMS; ++g) {
const qvvr_file& fg = ld.qvvrevent.qvvrfile[g];
os << "\r\x1B[K |-- [" << g << "] "
<< "used=" << fg.used_status
<< ", tcount=" << fg.file_time_count
<< ", downloaded=" << fg.is_download
<< ", paired=" << fg.is_pair
<< "\n";
// 文件名列表file_name
os << "\r\x1B[K |-- file_name (" << fg.file_name.size() << "):\n";
{
size_t c = 0;
for (const auto& fn : fg.file_name) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << fn << "\n";
}
if (fg.file_name.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (fg.file_name.size() - MAX_ITEMS) << " more)\n";
}
}
// 已下载列表file_download
os << "\r\x1B[K |-- file_download (" << fg.file_download.size() << "):\n";
{
size_t c = 0;
for (const auto& fn : fg.file_download) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << fn << "\n";
}
if (fg.file_download.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (fg.file_download.size() - MAX_ITEMS) << " more)\n";
}
}
}
if (n > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n";
}
}
}
os << "\r\x1B[K------------------------------------\n";
sendStr(fd, os.str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////打印所有的终端列表
void Worker::ledger(const std::string& terminal_id, int fd) {
sendStr(fd, "\r\x1B[Kprint ledger in shell\n");
@@ -547,12 +705,54 @@ void Worker::handleViewLogCommand(const std::string& command, int clientFD) {
stopViewLog = false;
showinshellflag = true;
sendStr(clientFD, "\r\x1B[KViewing logs for level: " + level + " (Press '`' to exit)\r\n> ");
sendStr(clientFD, std::string("\r\x1B[KViewing logs for level: ") + level + " (Press '`' to exit)\r\n> ");
char inputBuf[16];
// --- 新增 begin: 目录创建 + 唯一文件名生成 + 打开文件 ---
// 递归创建目录的小工具(最小实现,按‘/’逐级创建)
auto ensure_dir = [](const std::string& path) -> bool {
if (path.empty()) return false;
std::string cur;
cur.reserve(path.size());
for (size_t i = 0; i < path.size(); ++i) {
cur.push_back(path[i]);
if (path[i] == '/' && cur.size() > 1) {
if (::access(cur.c_str(), F_OK) != 0) {
if (::mkdir(cur.c_str(), 0755) != 0 && errno != EEXIST) return false;
}
}
}
// 末级(若不以 / 结尾)
if (cur.back() != '/') {
if (::access(cur.c_str(), F_OK) != 0) {
if (::mkdir(cur.c_str(), 0755) != 0 && errno != EEXIST) return false;
}
}
return true;
};
const std::string logDir = "/FeProject/dat/log";
if (!ensure_dir(logDir)) {
sendStr(clientFD, "\r\x1B[KFailed to create log directory: /FeProject/dat/log\r\n> ");
return;
}
std::string filePath = logDir + "/temp.log";
int index = 1;
while (::access(filePath.c_str(), F_OK) == 0) {
filePath = logDir + "/temp_" + std::to_string(index++) + ".log";
}
std::ofstream logFile(filePath.c_str(), std::ios::out | std::ios::trunc);
if (!logFile.is_open()) {
sendStr(clientFD, "\r\x1B[KFailed to open log file for writing.\r\n> ");
return;
}
// --- 新增 end ---
while (!stopViewLog) {
// 1. 监听 shell 输入退出符号 `
// 1) 监听 shell 输入退出符号 `
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(clientFD, &read_fds);
@@ -564,31 +764,47 @@ void Worker::handleViewLogCommand(const std::string& command, int clientFD) {
int activity = select(clientFD + 1, &read_fds, nullptr, nullptr, &timeout);
if (activity > 0 && FD_ISSET(clientFD, &read_fds)) {
int n = recv(clientFD, inputBuf, sizeof(inputBuf), 0);
if (n > 0 && strchr(inputBuf, '`')) {
if (n > 0 && std::memchr(inputBuf, '`', static_cast<size_t>(n))) {
stopViewLog = true;
showinshellflag = false;
break;
}
}
// 2. 输出日志
std::string logEntry;
// --- 修改 begin: 批量获取日志swap 全取,减少加锁时间) ---
std::list<std::string> tempLogs;
{
std::lock_guard<std::mutex> lock(*logMutex);
if (!logList->empty()) {
logEntry = logList->front();
logList->pop_front();
tempLogs.swap(*logList); // 把 logList 中的内容全取出
}
}
// --- 修改 end ---
if (!logEntry.empty()) {
sendStr(clientFD, "\r\x1B[K" + logEntry + "\r\n");
if (!tempLogs.empty()) {
for (const auto& logEntry : tempLogs) {
if (!logEntry.empty()) {
sendStr(clientFD, std::string("\r\x1B[K") + logEntry + "\r\n");
// --- 新增 begin: 写入文件 + 及时落盘 ---
logFile << logEntry << '\n';
// --- 新增 end ---
}
}
// --- 新增 begin: 刷新文件缓冲,保证实时可见 ---
logFile.flush();
// --- 新增 end ---
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
// 3. 打印退出提示
// 3) 打印退出提示
sendStr(clientFD, "\r\x1B[K\nLog view stopped. Returning to shell.\r\n> ");
// --- 新增 begin: 关闭文件 ---
logFile.close();
// --- 新增 end ---
}

View File

@@ -0,0 +1,77 @@
[Queue]
BrokerList=
RTDataTopic=Real_Time_Data_Topic
HisTopic=njcnAppAutoDataTopic
PSTTopic=njcnAppAutoDataTopic
PLTTopic=njcnAppAutoDataTopic
AlmTopic=AlmTopic
SngTopic=SngTopic
QUEUE_TAG=stat
QUEUE_KEY=stat
[Flag]
FrontInst=
FrontIP=192.168.1.138
[Ledger]
TerminalStatus="[0]"
MonitorStatus="[1,2]"
IcdFlag=0
IedCount=300
[Http]
WebDevice=http://192.168.1.103:10220/icd/getLedgerInfo
WebEvent=http://192.168.1.103:10222/event/addCldEvent
WebFileupload=http://192.168.1.103:10207/file/upload
WebFiledownload=
[RocketMq]
producer=Group_producer
Ipport=192.168.1.24:9876
AccessKey=rmqroot
SecretKey=001@#njcnmq
Topic_Test=lnk_Topic
Tag_Test=Test_Tag
Key_Test=Test_Keys
Testflag=1
Testnum=0
Testtype=0
TestPort=11000
TestList=8ad28e2e36dfbd19906f9e2a4894b375
consumer=Group_consumer
ConsumerIpport=192.168.1.24:9876
ConsumerTopicRT=ask_real_data_topic
ConsumerTagRT=Test_Tag
ConsumerKeyRT=Test_Keys
ConsumerAccessKey=rmqroot
ConsumerSecretKey=001@#njcnmq
ConsumerChannel=
ConsumerTopicUD=control_Topic
ConsumerTagUD=Test_Tag
ConsumerKeyUD=Test_Keys
ConsumerTopicRC=recall_Topic
ConsumerTagRC=Test_Tag
ConsumerKeyRC=Test_Keys
ConsumerTopicSET=process_Topic
ConsumerTagSET=Test_Tag
ConsumerKeySET=Test_Keys
ConsumerTopicLOG=ask_log_Topic
ConsumerTagLOG=Test_Tag
ConsumerKeyLOG=Test_Keys
LOGTopic=log_Topic
LOGTag=Test_Tag
LOGKey=Test_Keys
CONNECTTopic=Device_Run_Flag_Topic
CONNECTTag=Test_Tag
CONNECTKey=Test_Keys
Heart_Beat_Topic=Heart_Beat_Topic
Heart_Beat_Tag=Test_Tag
Heart_Beat_Key=Test_Key
Topic_Reply_Topic=Topic_Reply_Topic
Topic_Reply_Tag=Test_Tag
Topic_Reply_Key=Test_Key

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}

View File

@@ -0,0 +1 @@
{"code":"A0000","message":"根据前置ip获取对应的终端台账信息,成功","data":[{"id":"175427bfa6ed1de818464e43dd09e04f","ip":"192.168.1.242","devType":"PQS882_B4_MMS(4U4I)","org_name":null,"port":"102","stationName":null,"name":"南昌终端_242","subName":"南昌变电站","updateTime":"2025-08-07 14:58:03","manufacturer":"南京灿能","status":"0","series":"","devKey":"","processNo":2,"maxProcessNum":3,"monitorData":[{"id":"4067998c0327a624b83610879c7de4c6","name":"监测点3","lineNo":"3","voltageLevel":"10kV","ptType":"0","status":"0"},{"id":"74203b186428c1684aa450ad05257b06","name":"监测点1","lineNo":"1","voltageLevel":"10kV","ptType":"0","status":"0"},{"id":"777737a13b16cf860d65d9f71e54f858","name":"监测点4","lineNo":"4","voltageLevel":"10kV","ptType":"0","status":"0"},{"id":"e07c34b721ac9ccd62e03d796a2f7fa8","name":"监测点2","lineNo":"2","voltageLevel":"10kV","ptType":"0","status":"0"}]},{"id":"438a3bc6cb9c04c91d572973b5760d25","ip":"192.168.1.234","devType":"PQS_882B4","org_name":null,"port":"102","stationName":null,"name":"宜春终端_234","subName":"宜春变电站","updateTime":"2025-08-07 14:58:02","manufacturer":"浪拜迪","status":"0","series":"","devKey":"","processNo":1,"maxProcessNum":3,"monitorData":[{"id":"5f99b9ba4e563439ec8490a0c598da8d","name":"监测点1","lineNo":"1","voltageLevel":"110kV","ptType":"0","status":"0"}]},{"id":"8cb7a1abcd70b26716358267ea517a22","ip":"192.168.1.238","devType":"NPQS_682","org_name":null,"port":"102","stationName":null,"name":"赣州终端_238","subName":"赣州变电站","updateTime":"2025-08-07 14:58:03","manufacturer":"浪拜迪","status":"0","series":"","devKey":"","processNo":1,"maxProcessNum":3,"monitorData":[{"id":"1b9cece8b66b100a52c4a31f469e8e0a","name":"监测点1","lineNo":"1","voltageLevel":"220kV","ptType":"0","status":"0"},{"id":"6072c5deecdae5d1b4dd5c475517444b","name":"监测点2","lineNo":"2","voltageLevel":"220kV","ptType":"0","status":"0"}]},{"id":"ad60520f9294864f41ca48b5acee62d6","ip":"192.168.1.229","devType":"PQS882_B4_MMS(4U4I)","org_name":null,"port":"102","stationName":null,"name":"南昌终端_229","subName":"南昌变电站","updateTime":"2025-08-07 11:43:07","manufacturer":"南京灿能","status":"0","series":"","devKey":"","processNo":1,"maxProcessNum":3,"monitorData":[{"id":"683e77d95099a315fb777b16113e34ae","name":"监测点3","lineNo":"3","voltageLevel":"10kV","ptType":"0","status":"0"},{"id":"824ab9440f0c9c279c2fc2080e19d07a","name":"监测点2","lineNo":"2","voltageLevel":"10kV","ptType":"0","status":"0"},{"id":"d446071b8bd8dd493687bae4746c02e5","name":"监测点1","lineNo":"1","voltageLevel":"10kV","ptType":"1","status":"0"},{"id":"fde41900cbaef358c9a9e23960ee2593","name":"监测点4","lineNo":"4","voltageLevel":"10kV","ptType":"0","status":"0"}]},{"id":"e8d14ec6395262c4984f1f8152a9135b","ip":"192.168.1.230","devType":"NPQS_681","org_name":null,"port":"102","stationName":null,"name":"上饶终端","subName":"上饶变电站","updateTime":"2025-08-07 11:43:07","manufacturer":"北京四方","status":"0","series":"5nfaNZS5ukTZ3L4rQiMinA==","devKey":"g/4565/nRBWbqxo7gZ8JZdg4ozz2DutoY/MaCC1PMIw=","processNo":1,"maxProcessNum":3,"monitorData":[{"id":"401a696fe9918bb4cce7d9393d0d5df7","name":"上饶监测点1","lineNo":"1","voltageLevel":"750kV","ptType":"0","status":"0"}]},{"id":"f3a02c4a89e75fe0cc377088fd1cb2f1","ip":"192.168.1.240","devType":"NPQS_882B4","org_name":null,"port":"102","stationName":null,"name":"九江终端_240","subName":"九江变电站","updateTime":"2025-08-07 14:58:03","manufacturer":"浪拜迪","status":"0","series":"","devKey":"","processNo":1,"maxProcessNum":3,"monitorData":[{"id":"cfc481a71953f85a23fd448c3cffc884","name":"监测点1","lineNo":"1","voltageLevel":"35kV","ptType":"0","status":"0"}]}]}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,585 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--注:#7#代表通配符,用于通配数据类型 采用8421码8-CP95、4-最小值、2-最大值、1-平均值-->
<!-- %2,50%代表通配符,用于通配谐波数据,采用范围编码,第一个数字表示谐波起始号,第二个数字谐波结束号-->
<!-- SEQ=后面的值采用8421码 8-T、4-C、2-B、1-A-->
<!--send类型0-不发送kafka、1-发送kafka-->
<!--type类型0-DataType、1-监测点、2-剔除标记、3-发生时刻毫秒、4-数据链表、5-相位、6-值索引、9-实时SOE事件-->
<!--nane:参数项、desc:参数描述、type:参数等级、DO:数据对象名、DA:数据属性名、Coefficient:数据系数、Offset:起始序号偏移量、PltFlag:长时闪变标志-->
<!--角型接线时相角为0不再进行DO、DA路径值扩展-->
<JSConfigTemplate version="2021-12-15" author="ww" SelectStat="JiangSu" SelectReal="Kafka Producer" desc="昆明长水机场增加谐波类数据配置">
<!--注:暂态事件解析规则配置 Flag0-不分相 1-分相 如果Flag=0 ABC配置成一样如果Flag=1ABC根据实际配置-->
<WavePhasic Flag="1" A="QVVR1" B="QVVR2" C="QVVR3" />
<!--暂态事件持续事件单位0-毫秒 1--->
<UnitOfTime Unit="1" />
<!--上送值的时间UTC-UTC时间 beijing-北京时间-->
<ValueOfTime Unit="UTC" />
<!--录波文件的时间UTC-UTC时间 beijing-北京时间-->
<ComtradeFile WaveTimeFlag="beijing" />
<IED name="PQMonitor" desc="电能质量监测装置" />
<LDevice Prefix="PQM" desc="监测点" />
<ReportMap>
<!--用于映射需要触发那些报告-->
<!--ReportControl:ID,RCBName,intgPd,dchg,qchg,dupd,period,gi,issuffixed,seqNum,timeStamp,reasonCode,dataSet,dataRef,bufOvfl,entryID,configRef,segmentation,FlickerFlag-->
<!--600/60秒即10分钟/1分钟-->
<!--0,0,0,1,0为周期触发报告-->
<!--1,0,0,0,0为变位触发报告-->
<ReportStat>
<Report ReportControl="LLN0$BR$brcbFlickerData,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,3,1" />
<Report ReportControl="LLN0$BR$brcbStatisticData,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,1,0" />
</ReportStat>
<ReportReal>
<Report ReportControl="LLN0$RP$urcbRealData,3,0,0,0,1,0,yes,1,1,1,1,1,0,1,1,1,3,2" />
</ReportReal>
<ReportEvent>
<Report ReportControl="LLN0$BR$brcbQVVR,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,8,1,0"/>
<Report ReportControl="LLN0$BR$brcbRDRE,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,8,1,0"/>
<Report ReportControl="LLN0$BR$brcbGGIO,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,8,1,0"/>
<Report ReportControl="LLN0$BR$brcbLPHD,60,1,0,0,0,0,yes,1,1,1,1,1,0,1,1,1,8,1,0"/>
</ReportEvent>
</ReportMap>
<Topic name="HISDATA" desc="历史稳态数据">
<DataType name="DATA_TYPE" value="02" desc="历史短时闪变数据" type="0">
<Monitor name="MONITOR" desc="监测点" type="1">
<Item name="FLAG" value="0" desc="剔除标记" type="2" />
<Item name="TIME" desc="发生时刻" type="3" />
<Item name="F_S" desc="短时闪变和波动" type="4" >
<Sequence name="SEQ" value="7" desc="相别" type="5" >
<Value name="PST" desc="短时闪变" type="6" DO="MFLK0$MX$PhPst" DA="phs*$cVal$mag$f" />
<Value name="FLUC" desc="电压波动幅度" type="6" DO="MFLK0$MX$PhFluc" DA="phs*$cVal$mag$f" />
<Value name="FLUCF" desc="电压波动频度" type="6" DO="MFLK0$MX$PhFlucf" DA="phs*$cVal$mag$f" />
</Sequence>
</Item>
</Monitor>
</DataType>
<DataType name="DATA_TYPE" value="03" desc="历史长时闪变数据" type="0">
<Monitor name="MONITOR" desc="监测点" type="1">
<Item name="FLAG" value="0" desc="剔除标记" type="2" />
<Item name="TIME" desc="发生时刻" type="3" />
<Item name="F_L" desc="闪变" type="4" >
<Sequence name="SEQ" value="7" desc="相别" type="5" >
<Value name="PLT" desc="长时闪变" type="6" DO="MFLK0$MX$PhPlt" DA="phs*$cVal$mag$f" />
</Sequence>
</Item>
</Monitor>
</DataType>
<DataType name="DATA_TYPE" value="04" desc="历史暂态数据" type="0" >
<Monitor name="MONITOR" desc="监测点" type="1" >
<Item name="VOLTAGE" desc="暂态指标" type="4" >
<Sequence name="SEQ" value="7" desc="相别" type="5">
<Value name="MAG" desc="残余电压" type="6" DO="QVVR0$MX$VVa" DA="mag$f" />
<Value name="DUR" desc="持续时间" type="6" DO="QVVR0$MX$VVaTm" DA="mag$f" />
<Value name="SEQ" desc="相别" type="6" DO="" DA="" />
<Value name="STARTTIME" desc="开始时间" type="6" DO="" DA="" />
<Value name="ENDTIME" desc="结束时间" type="6" DO="" DA="" />
<Value name="DISKIND" desc="暂降类型" type="6" DO="" DA="" />
<Value name="WAVEFILE" desc="波形文件名称" type="6" DO="" DA="" />
</Sequence>
</Item>
</Monitor>
</DataType>
<DataType name="DATA_TYPE" value="01" desc="历史稳态数据" type="0">
<Monitor name="MONITOR" desc="监测点" type="1">
<Item name="FLAG" value="0" desc="剔除标记" type="2" />
<Item name="TIME" desc="发生时刻" type="3" />
<Item name="V" desc="电压" type="4" >
<!--电压V部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<!--Coefficient 值系数转成kafka的时候乘以系数BaseFlag 基础数据标志 0或没有-非基础数据 1-基础数据LimitUp 数据合理上限,如果包含*%UN字符表示需要乘以电压等级电压如果包含*%U字符表示需要乘以电压等级/1.732电压例如220kV则相电压上限为1.5*220LimitDown 数据合理下限 如果包含*%U字符表示需要乘以电压等级电压-->
<Value name="G_DELTA_V" desc="电压偏差95值" type="6" DO="MMXU4$MX$PhVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="DELTA_V" desc="电压偏差平均值" type="6" DO="MMXU2$MX$PhVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="MAX_DELTA_V" desc="电压偏差最大值" type="6" DO="MMXU1$MX$PhVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="MIN_DELTA_V" desc="电压偏差最小值" type="6" DO="MMXU3$MX$PhVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="G_VRMS" desc="电压有效值95值" type="6" DO="MMXU4$MX$PhV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="VRMS" desc="电压有效值平均值" type="6" DO="MMXU2$MX$PhV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MAX_VRMS" desc="电压有效值最大值" type="6" DO="MMXU1$MX$PhV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MIN_VRMS" desc="电压有效值最小值" type="6" DO="MMXU3$MX$PhV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="G_VRMS_LVR" desc="线电压有效值95值" type="6" DO="MMXU4$MX$PPV" DA="l_phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="VRMS_LVR" desc="线电压有效值平均值" type="6" DO="MMXU2$MX$PPV" DA="l_phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MAX_VRMS_LVR" desc="线电压有效值最大值" type="6" DO="MMXU1$MX$PPV" DA="l_phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MIN_VRMS_LVR" desc="线电压有效值最小值" type="6" DO="MMXU3$MX$PPV" DA="l_phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="G_VTHD" desc="电压总谐波畸变率95值" type="6" DO="MHAI4$MX$ThdPhV" DA="phs*$cVal$mag$f" />
<Value name="VTHD" desc="电压总谐波畸变率平均值" type="6" DO="MHAI2$MX$ThdPhV" DA="phs*$cVal$mag$f" />
<Value name="MAX_VTHD" desc="电压总谐波畸变率最大值" type="6" DO="MHAI1$MX$ThdPhV" DA="phs*$cVal$mag$f" />
<Value name="MIN_VTHD" desc="电压总谐波畸变率最小值" type="6" DO="MHAI3$MX$ThdPhV" DA="phs*$cVal$mag$f" />
<Value name="G_VFUND_ANGLE" desc="基波电压相角95值" type="6" DO="MHAI4$MX$HFundPhV" DA="phs*$cVal$ang$f" />
<Value name="VFUND_ANGLE" desc="基波电压相角平均值" type="6" DO="MHAI2$MX$HFundPhV" DA="phs*$cVal$ang$f" />
<Value name="MAX_VFUND_ANGLE" desc="基波电压相角最大值" type="6" DO="MHAI1$MX$HFundPhV" DA="phs*$cVal$ang$f" />
<Value name="MIN_VFUND_ANGLE" desc="基波电压相角最小值" type="6" DO="MHAI3$MX$HFundPhV" DA="phs*$cVal$ang$f" />
<Value name="G_V1" desc="基波电压有效值95值" type="6" DO="MHAI4$MX$HFundPhV" DA="phs*$cVal$mag$f" />
<Value name="V1" desc="基波电压有效值平均值" type="6" DO="MHAI2$MX$HFundPhV" DA="phs*$cVal$mag$f" />
<Value name="MAX_V1" desc="基波电压有效值最大值" type="6" DO="MHAI1$MX$HFundPhV" DA="phs*$cVal$mag$f" />
<Value name="MIN_V1" desc="基波电压有效值最小值" type="6" DO="MHAI3$MX$HFundPhV" DA="phs*$cVal$mag$f" />
<Value name="G_SV_%0,49%" desc="间谐波电压含有率(f25-2475)95值" type="6" DO="MHAI9$MX$HRPhV" DA="phs*Har[%-0]$mag$f" />
<Value name="SV_%0,49%" desc="间谐波电压含有率(f25-2475)平均值" type="6" DO="MHAI7$MX$HRPhV" DA="phs*Har[%-0]$mag$f" />
<Value name="MAX_SV_%0,49%" desc="间谐波电压含有率(f25-2475)最大值" type="6" DO="MHAI6$MX$HRPhV" DA="phs*Har[%-0]$mag$f" />
<Value name="MIN_SV_%0,49%" desc="间谐波电压含有率(f25-2475)最小值" type="6" DO="MHAI8$MX$HRPhV" DA="phs*Har[%-0]$mag$f" />
<Value name="G_V%2,50%" desc="谐波电压含有率(2-50)95值" type="6" DO="MHAI4$MX$HRPhV" DA="phs*Har[%-2]$mag$f" />
<Value name="V%2,50%" desc="谐波电压含有率(2-50)平均值" type="6" DO="MHAI2$MX$HRPhV" DA="phs*Har[%-2]$mag$f" />
<Value name="MAX_V%2,50%" desc="谐波电压含有率(2-50)最大值" type="6" DO="MHAI1$MX$HRPhV" DA="phs*Har[%-2]$mag$f" />
<Value name="MIN_V%2,50%" desc="谐波电压含有率(2-50)最小值" type="6" DO="MHAI3$MX$HRPhV" DA="phs*Har[%-2]$mag$f" />
<Value name="G_VA%2,50%" desc="谐波电压相角(2-50)95值" type="6" DO="MHAI4$MX$HRPhV" DA="phs*Har[%-2]$ang$f" />
<Value name="VA%2,50%" desc="谐波电压相角(2-50)平均值" type="6" DO="MHAI2$MX$HRPhV" DA="phs*Har[%-2]$ang$f" />
<Value name="MAX_VA%2,50%" desc="谐波电压相角(2-50)最大值" type="6" DO="MHAI1$MX$HRPhV" DA="phs*Har[%-2]$ang$f" />
<Value name="MIN_VA%2,50%" desc="谐波电压相角(2-50)最小值" type="6" DO="MHAI3$MX$HRPhV" DA="phs*Har[%-2]$ang$f" />
</Sequence>
<!--电压V部分(A-C相)角型接线-->
<Sequence name="SEQ" value="112" desc="相别(A-C相)" type="5">
<!--Coefficient 值系数转成kafka的时候乘以系数BaseFlag 基础数据标志 0或没有-非基础数据 1-基础数据LimitUp 数据合理上限,如果包含*%UN字符表示需要乘以电压等级电压如果包含*%U字符表示需要乘以电压等级/1.732电压例如220kV则相电压上限为1.5*220LimitDown 数据合理下限 如果包含*%U字符表示需要乘以电压等级电压-->
<Value name="G_DELTA_V" desc="电压偏差95值" type="6" DO="MMXU4$MX$PPVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="DELTA_V" desc="电压偏差平均值" type="6" DO="MMXU2$MX$PPVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="MAX_DELTA_V" desc="电压偏差最大值" type="6" DO="MMXU1$MX$PPVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="MIN_DELTA_V" desc="电压偏差最小值" type="6" DO="MMXU3$MX$PPVDev" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="20" LimitDown="-20" Coefficient="1"/>
<Value name="G_VRMS_LVR" desc="电压有效值95值" type="6" DO="MMXU4$MX$PPV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="VRMS_LVR" desc="电压有效值平均值" type="6" DO="MMXU2$MX$PPV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MAX_VRMS_LVR" desc="电压有效值最大值" type="6" DO="MMXU1$MX$PPV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="MIN_VRMS_LVR" desc="电压有效值最小值" type="6" DO="MMXU3$MX$PPV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<Value name="G_VTHD" desc="电压总谐波畸变率95值" type="6" DO="MHAI4$MX$ThdPPV" DA="phs*$cVal$mag$f" />
<Value name="VTHD" desc="电压总谐波畸变率平均值" type="6" DO="MHAI2$MX$ThdPPV" DA="phs*$cVal$mag$f" />
<Value name="MAX_VTHD" desc="电压总谐波畸变率最大值" type="6" DO="MHAI1$MX$ThdPPV" DA="phs*$cVal$mag$f" />
<Value name="MIN_VTHD" desc="电压总谐波畸变率最小值" type="6" DO="MHAI3$MX$ThdPPV" DA="phs*$cVal$mag$f" />
<Value name="G_VFUND_ANGLE" desc="基波电压相角95值" type="6" DO="MHAI4$MX$HFundPPVAng" DA="phs*$cVal$ang$f" />
<Value name="VFUND_ANGLE" desc="基波电压相角平均值" type="6" DO="MHAI2$MX$HFundPPVAng" DA="phs*$cVal$ang$f" />
<Value name="MAX_VFUND_ANGLE" desc="基波电压相角最大值" type="6" DO="MHAI1$MX$HFundPPVAng" DA="phs*$cVal$ang$f" />
<Value name="MIN_VFUND_ANGLE" desc="基波电压相角最小值" type="6" DO="MHAI3$MX$HFundPPVAng" DA="phs*$cVal$ang$f" />
<Value name="G_V1" desc="基波电压有效值95值" type="6" DO="MHAI4$MX$HFundPPV" DA="phs*$cVal$mag$f" />
<Value name="V1" desc="基波电压有效值平均值" type="6" DO="MHAI2$MX$HFundPPV" DA="phs*$cVal$mag$f" />
<Value name="MAX_V1" desc="基波电压有效值最大值" type="6" DO="MHAI1$MX$HFundPPV" DA="phs*$cVal$mag$f" />
<Value name="MIN_V1" desc="基波电压有效值最小值" type="6" DO="MHAI3$MX$HFundPPV" DA="phs*$cVal$mag$f" />
<Value name="G_SV_%0,49%" desc="间谐波电压含有率(f25-2475)95值" type="6" DO="MHAI9$MX$HRPPV" DA="phs*Har[%-0]$mag$f" />
<Value name="SV_%0,49%" desc="间谐波电压含有率(f25-2475)平均值" type="6" DO="MHAI7$MX$HRPPV" DA="phs*Har[%-0]$mag$f" />
<Value name="MAX_SV_%0,49%" desc="间谐波电压含有率(f25-2475)最大值" type="6" DO="MHAI6$MX$HRPPV" DA="phs*Har[%-0]$mag$f" />
<Value name="MIN_SV_%0,49%" desc="间谐波电压含有率(f25-2475)最小值" type="6" DO="MHAI8$MX$HRPPV" DA="phs*Har[%-0]$mag$f" />
<Value name="G_V%2,50%" desc="谐波电压含有率(2-50)95值" type="6" DO="MHAI4$MX$HRPPV" DA="phs*Har[%-2]$mag$f" />
<Value name="V%2,50%" desc="谐波电压含有率(2-50)平均值" type="6" DO="MHAI2$MX$HRPPV" DA="phs*Har[%-2]$mag$f" />
<Value name="MAX_V%2,50%" desc="谐波电压含有率(2-50)最大值" type="6" DO="MHAI1$MX$HRPPV" DA="phs*Har[%-2]$mag$f" />
<Value name="MIN_V%2,50%" desc="谐波电压含有率(2-50)最小值" type="6" DO="MHAI3$MX$HRPPV" DA="phs*Har[%-2]$mag$f" />
<Value name="G_VA%2,50%" desc="谐波电压相角(2-50)95值" type="6" DO="MHAI4$MX$HRPPV" DA="phs*Har[%-2]$ang$f" />
<Value name="VA%2,50%" desc="谐波电压相角(2-50)平均值" type="6" DO="MHAI2$MX$HRPPV" DA="phs*Har[%-2]$ang$f" />
<Value name="MAX_VA%2,50%" desc="谐波电压相角(2-50)最大值" type="6" DO="MHAI1$MX$HRPPV" DA="phs*Har[%-2]$ang$f" />
<Value name="MIN_VA%2,50%" desc="谐波电压相角(2-50)最小值" type="6" DO="MHAI3$MX$HRPPV" DA="phs*Har[%-2]$ang$f" />
</Sequence>
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<!--电压V部分(T相)-->
<Value name="G_VNSEQ" desc="负序电压95值" type="6" DO="MSQI4$MX$SeqV" DA="c2$cVal$mag$f" />
<Value name="VNSEQ" desc="负序电压平均值" type="6" DO="MSQI2$MX$SeqV" DA="c2$cVal$mag$f" />
<Value name="MAX_VNSEQ" desc="负序电压最大值" type="6" DO="MSQI1$MX$SeqV" DA="c2$cVal$mag$f" />
<Value name="MIN_VNSEQ" desc="负序电压最小值" type="6" DO="MSQI3$MX$SeqV" DA="c2$cVal$mag$f" />
<Value name="G_V_UNBAN" desc="负序电压不平衡95值" type="6" DO="MSQI4$MX$ImbNgV" DA="mag$f" />
<Value name="V_UNBAN" desc="负序电压不平衡平均值" type="6" DO="MSQI2$MX$ImbNgV" DA="mag$f" />
<Value name="MAX_V_UNBAN" desc="负序电压不平衡最大值" type="6" DO="MSQI1$MX$ImbNgV" DA="mag$f" />
<Value name="MIN_V_UNBAN" desc="负序电压不平衡最小值" type="6" DO="MSQI3$MX$ImbNgV" DA="mag$f" />
<Value name="G_VZSEQ" desc="零序电压95值" type="6" DO="MSQI4$MX$SeqV" DA="c3$cVal$mag$f" />
<Value name="VZSEQ" desc="零序电压平均值" type="6" DO="MSQI2$MX$SeqV" DA="c3$cVal$mag$f" />
<Value name="MAX_VZSEQ" desc="零序电压最大值" type="6" DO="MSQI1$MX$SeqV" DA="c3$cVal$mag$f" />
<Value name="MIN_VZSEQ" desc="零序电压最小值" type="6" DO="MSQI3$MX$SeqV" DA="c3$cVal$mag$f" />
<Value name="G_VZSEQ_UNBAN" desc="零序电压不平衡95值" type="6" DO="MSQI4$MX$ImbZroV" DA="mag$f" />
<Value name="VZSEQ_UNBAN" desc="零序电压不平衡平均值" type="6" DO="MSQI2$MX$ImbZroV" DA="mag$f" />
<Value name="MAX_VZSEQ_UNBAN" desc="零序电压不平衡最大值" type="6" DO="MSQI1$MX$ImbZroV" DA="mag$f" />
<Value name="MIN_VZSEQ_UNBAN" desc="零序电压不平衡最小值" type="6" DO="MSQI3$MX$ImbZroV" DA="mag$f" />
<Value name="G_FREQ" desc="频率95值" type="6" DO="MMXU4$MX$Hz" DA="mag$f" />
<Value name="FREQ" desc="频率平均值" type="6" DO="MMXU2$MX$Hz" DA="mag$f" />
<Value name="MAX_FREQ" desc="频率最大值" type="6" DO="MMXU1$MX$Hz" DA="mag$f" />
<Value name="MIN_FREQ" desc="频率最小值" type="6" DO="MMXU3$MX$Hz" DA="mag$f" />
<Value name="G_DELTA_FREQ" desc="频率偏差95值" type="6" DO="MMXU4$MX$HzDev" DA="mag$f" />
<Value name="DELTA_FREQ" desc="频率偏差平均值" type="6" DO="MMXU2$MX$HzDev" DA="mag$f" />
<Value name="MAX_DELTA_FREQ" desc="频率偏差最大值" type="6" DO="MMXU1$MX$HzDev" DA="mag$f" />
<Value name="MIN_DELTA_FREQ" desc="频率偏差最小值" type="6" DO="MMXU3$MX$HzDev" DA="mag$f" />
<Value name="G_VPSEQ" desc="正序电压95值" type="6" DO="MSQI4$MX$SeqV" DA="c1$cVal$mag$f" />
<Value name="VPSEQ" desc="正序电压平均值" type="6" DO="MSQI2$MX$SeqV" DA="c1$cVal$mag$f" />
<Value name="MAX_VPSEQ" desc="正序电压最大值" type="6" DO="MSQI1$MX$SeqV" DA="c1$cVal$mag$f" />
<Value name="MIN_VPSEQ" desc="正序电压最小值" type="6" DO="MSQI3$MX$SeqV" DA="c1$cVal$mag$f" />
</Sequence>
</Item>
<Item name="I" desc="电流" type="4" >
<!--电流I部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<Value name="G_IRMS" desc="电流有效值95值" type="6" DO="MMXU4$MX$A" DA="phs*$cVal$mag$f" />
<Value name="IRMS" desc="电流有效值平均值" type="6" DO="MMXU2$MX$A" DA="phs*$cVal$mag$f" />
<Value name="MAX_IRMS" desc="电流有效值最大值" type="6" DO="MMXU1$MX$A" DA="phs*$cVal$mag$f" />
<Value name="MIN_IRMS" desc="电流有效值最小值" type="6" DO="MMXU3$MX$A" DA="phs*$cVal$mag$f" />
<Value name="G_I1" desc="基波电流有效值95值" type="6" DO="MHAI4$MX$HA" DA="phs*Har[0]$mag$f" />
<Value name="I1" desc="基波电流有效值平均值" type="6" DO="MHAI2$MX$HA" DA="phs*Har[0]$mag$f" />
<Value name="MAX_I1" desc="基波电流有效值最大值" type="6" DO="MHAI1$MX$HA" DA="phs*Har[0]$mag$f" />
<Value name="MIN_I1" desc="基波电流有效值最小值" type="6" DO="MHAI3$MX$HA" DA="phs*Har[0]$mag$f" />
<Value name="G_IFUND_ANGLE" desc="基波电流相角95值" type="6" DO="MHAI4$MX$HA" DA="phs*Har[0]$ang$f" />
<Value name="IFUND_ANGLE" desc="基波电流相角平均值" type="6" DO="MHAI2$MX$HA" DA="phs*Har[0]$ang$f" />
<Value name="MAX_IFUND_ANGLE" desc="基波电流相角最大值" type="6" DO="MHAI1$MX$HA" DA="phs*Har[0]$ang$f" />
<Value name="MIN_IFUND_ANGLE" desc="基波电流相角最小值" type="6" DO="MHAI3$MX$HA" DA="phs*Har[0]$ang$f" />
<Value name="G_SI_%0,49%" desc="间谐波电流幅值(f25-2475)95值" type="6" DO="MHAI9$MX$HA" DA="phs*Har[%-0]$mag$f" />
<Value name="SI_%0,49%" desc="间谐波电流幅值(f25-2475)平均值" type="6" DO="MHAI7$MX$HA" DA="phs*Har[%-0]$mag$f" />
<Value name="MAX_SI_%0,49%" desc="间谐波电流幅值(f25-2475)最大值" type="6" DO="MHAI6$MX$HA" DA="phs*Har[%-0]$mag$f" />
<Value name="MAX_SI_%0,49%" desc="间谐波电流幅值(f25-2475)最小值" type="6" DO="MHAI8$MX$HA" DA="phs*Har[%-0]$mag$f" />
<Value name="G_I%1,50%" desc="谐波电流幅值(2-50)95值" type="6" DO="MHAI4$MX$HA" DA="phs*Har[%-1]$mag$f" />
<Value name="I%1,50%" desc="谐波电流幅值(2-50)平均值" type="6" DO="MHAI2$MX$HA" DA="phs*Har[%-1]$mag$f" />
<Value name="MAX_I%1,50%" desc="谐波电流幅值(2-50)最大值" type="6" DO="MHAI1$MX$HA" DA="phs*Har[%-1]$mag$f" />
<Value name="MIN_I%1,50%" desc="谐波电流幅值(2-50)最小值" type="6" DO="MHAI3$MX$HA" DA="phs*Har[%-1]$mag$f" />
<Value name="G_IA%1,50%" desc="谐波电流相角(2-50)95值" type="6" DO="MHAI4$MX$HA" DA="phs*Har[%-1]$ang$f" />
<Value name="IA%1,50%" desc="谐波电流相角(2-50)平均值" type="6" DO="MHAI2$MX$HA" DA="phs*Har[%-1]$ang$f" />
<Value name="MAX_IA%1,50%" desc="谐波电流相角(2-50)最大值" type="6" DO="MHAI1$MX$HA" DA="phs*Har[%-1]$ang$f" />
<Value name="MIN_IA%1,50%" desc="谐波电流相角(2-50)最小值" type="6" DO="MHAI3$MX$HA" DA="phs*Har[%-1]$ang$f" />
<Value name="ITHD" desc="电流总谐波畸变率平均" type="6" DO="MHAI2$MX$ThdA" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="MAX_ITHD" desc="电流总谐波畸变率最大" type="6" DO="MHAI1$MX$ThdA" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="MIN_ITHD" desc="电流总谐波畸变率最小" type="6" DO="MHAI3$MX$ThdA" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="G_ITHD" desc="电流总谐波畸变率95" type="6" DO="MHAI4$MX$ThdA" DA="phs*$cVal$mag$f" Coefficient="1" />
</Sequence>
<!--电流I部分(T相)-->
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<Value name="G_INSEQ" desc="负序电流95值" type="6" DO="MSQI4$MX$SeqA" DA="c2$cVal$mag$f" />
<Value name="INSEQ" desc="负序电流平均值" type="6" DO="MSQI2$MX$SeqA" DA="c2$cVal$mag$f" />
<Value name="MAX_INSEQ" desc="负序电流最大值" type="6" DO="MSQI1$MX$SeqA" DA="c2$cVal$mag$f" />
<Value name="MIN_INSEQ" desc="负序电流最小值" type="6" DO="MSQI3$MX$SeqA" DA="c2$cVal$mag$f" />
<Value name="G_I_UNBAN" desc="负序电流不平衡95值" type="6" DO="MSQI4$MX$ImbNgA" DA="mag$f" />
<Value name="I_UNBAN" desc="负序电流不平衡平均值" type="6" DO="MSQI2$MX$ImbNgA" DA="mag$f" />
<Value name="MAX_I_UNBAN" desc="负序电流不平衡最大值" type="6" DO="MSQI1$MX$ImbNgA" DA="mag$f" />
<Value name="MIN_I_UNBAN" desc="负序电流不平衡最小值" type="6" DO="MSQI3$MX$ImbNgA" DA="mag$f" />
<Value name="G_IZSEQ" desc="零序电流95值" type="6" DO="MSQI4$MX$SeqA" DA="c3$cVal$mag$f" />
<Value name="IZSEQ" desc="零序电流平均值" type="6" DO="MSQI2$MX$SeqA" DA="c3$cVal$mag$f" />
<Value name="MAX_IZSEQ" desc="零序电流最大值" type="6" DO="MSQI1$MX$SeqA" DA="c3$cVal$mag$f" />
<Value name="MIN_IZSEQ" desc="零序电流最小值" type="6" DO="MSQI3$MX$SeqA" DA="c3$cVal$mag$f" />
<Value name="G_VZSEQ_UNBAN" desc="零序电流不平衡95值" type="6" DO="MSQI4$MX$ImbZroA" DA="mag$f" />
<Value name="VZSEQ_UNBAN" desc="零序电流不平衡平均值" type="6" DO="MSQI2$MX$ImbZroA" DA="mag$f" />
<Value name="MAX_IZSEQ_UNBAN" desc="零序电流不平衡最大值" type="6" DO="MSQI1$MX$ImbZroA" DA="mag$f" />
<Value name="MIN_IZSEQ_UNBAN" desc="零序电流不平衡最小值" type="6" DO="MSQI3$MX$ImbZroA" DA="mag$f" />
<Value name="G_IPSEQ" desc="正序电流95值" type="6" DO="MSQI4$MX$SeqA" DA="c1$cVal$mag$f" />
<Value name="IPSEQ" desc="正序电流平均值" type="6" DO="MSQI2$MX$SeqA" DA="c1$cVal$mag$f" />
<Value name="MAX_IPSEQ" desc="正序电流最大值" type="6" DO="MSQI1$MX$SeqA" DA="c1$cVal$mag$f" />
<Value name="MIN_IPSEQ" desc="正序电流最小值" type="6" DO="MSQI3$MX$SeqA" DA="c1$cVal$mag$f" />
</Sequence>
</Item>
<Item name="PQ" desc="功率" type="4" >
<!--功率PQ部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<Value name="G_PF" desc="功率因数95值" type="6" DO="MMXU4$MX$PF" DA="phs*$cVal$mag$f" />
<Value name="PF" desc="功率因数平均值" type="6" DO="MMXU2$MX$PF" DA="phs*$cVal$mag$f" />
<Value name="MAX_PF" desc="功率因数最大值" type="6" DO="MMXU1$MX$PF" DA="phs*$cVal$mag$f" />
<Value name="MIN_PF" desc="功率因数最小值" type="6" DO="MMXU3$MX$PF" DA="phs*$cVal$mag$f" />
<Value name="G_DF" desc="位移功率因数95值" type="6" DO="MMXU4$MX$DF" DA="phs*$cVal$mag$f" />
<Value name="DF" desc="位移功率因数平均值" type="6" DO="MMXU2$MX$DF" DA="phs*$cVal$mag$f" />
<Value name="MAX_DF" desc="位移功率因数最大值" type="6" DO="MMXU1$MX$DF" DA="phs*$cVal$mag$f" />
<Value name="MIN_DF" desc="位移功率因数最小值" type="6" DO="MMXU3$MX$DF" DA="phs*$cVal$mag$f" />
<Value name="G_P_FUND" desc="基波有功功率95值" type="6" DO="MHAI4$MX$HW" DA="phs*Har[0]$mag$f" />
<Value name="P_FUND" desc="基波有功功率平均值" type="6" DO="MHAI2$MX$HW" DA="phs*Har[0]$mag$f" />
<Value name="MAX_P_FUND" desc="基波有功功率最大值" type="6" DO="MHAI1$MX$HW" DA="phs*Har[0]$mag$f" />
<Value name="MIN_P_FUND" desc="基波有功功率最小值" type="6" DO="MHAI3$MX$HW" DA="phs*Har[0]$mag$f" />
<Value name="G_S" desc="视在功率95值" type="6" DO="MMXU4$MX$VA" DA="phs*$cVal$mag$f" />
<Value name="S" desc="视在功率平均值" type="6" DO="MMXU2$MX$VA" DA="phs*$cVal$mag$f" />
<Value name="MAX_S" desc="视在功率最大值" type="6" DO="MMXU1$MX$VA" DA="phs*$cVal$mag$f" />
<Value name="MIN_S" desc="视在功率最小值" type="6" DO="MMXU3$MX$VA" DA="phs*$cVal$mag$f" />
<Value name="G_Q" desc="无功功率95值" type="6" DO="MMXU4$MX$VAr" DA="phs*$cVal$mag$f" />
<Value name="Q" desc="无功功率平均值" type="6" DO="MMXU2$MX$VAr" DA="phs*$cVal$mag$f" />
<Value name="MAX_Q" desc="无功功率最大值" type="6" DO="MMXU1$MX$VAr" DA="phs*$cVal$mag$f" />
<Value name="MIN_Q" desc="无功功率最小值" type="6" DO="MMXU3$MX$VAr" DA="phs*$cVal$mag$f" />
<Value name="G_P%1,50%" desc="谐波有功功率(2-50)95值" type="6" DO="MHAI4$MX$HW" DA="phs*Har[%-1]$mag$f" />
<Value name="P%1,50%" desc="谐波有功功率(2-50)平均值" type="6" DO="MHAI2$MX$HW" DA="phs*Har[%-1]$mag$f" />
<Value name="MAX_P%1,50%" desc="谐波有功功率(2-50)最大值" type="6" DO="MHAI1$MX$HW" DA="phs*Har[%-1]$mag$f" />
<Value name="MIN_P%1,50%" desc="谐波有功功率(2-50)最小值" type="6" DO="MHAI3$MX$HW" DA="phs*Har[%-1]$mag$f" />
<Value name="G_Q%1,50%" desc="谐波无功功率(2-50)95值" type="6" DO="MHAI4$MX$HVAr" DA="phs*Har[%-1]$mag$f" />
<Value name="Q%1,50%" desc="谐波无功功率(2-50)平均值" type="6" DO="MHAI2$MX$HVAr" DA="phs*Har[%-1]$mag$f" />
<Value name="MAX_Q%1,50%" desc="谐波无功功率(2-50)最大值" type="6" DO="MHAI1$MX$HVAr" DA="phs*Har[%-1]$mag$f" />
<Value name="MIN_Q%1,50%" desc="谐波无功功率(2-50)最小值" type="6" DO="MHAI3$MX$HVAr" DA="phs*Har[%-1]$mag$f" />
<Value name="G_S%1,50%" desc="谐波视在功率(2-50)95值" type="6" DO="MHAI4$MX$HVA" DA="phs*Har[%-1]$mag$f" />
<Value name="S%1,50%" desc="谐波视在功率(2-50)平均值" type="6" DO="MHAI2$MX$HVA" DA="phs*Har[%-1]$mag$f" />
<Value name="MAX_S%1,50%" desc="谐波视在功率(2-50)最大值" type="6" DO="MHAI1$MX$HVA" DA="phs*Har[%-1]$mag$f" />
<Value name="MIN_S%1,50%" desc="谐波视在功率(2-50)最小值" type="6" DO="MHAI3$MX$HVA" DA="phs*Har[%-1]$mag$f" />
<Value name="G_P" desc="有功功率95值" type="6" DO="MMXU4$MX$W" DA="phs*$cVal$mag$f" />
<Value name="P" desc="有功功率平均值" type="6" DO="MMXU2$MX$W" DA="phs*$cVal$mag$f" />
<Value name="MAX_P" desc="有功功率最大值" type="6" DO="MMXU1$MX$W" DA="phs*$cVal$mag$f" />
<Value name="MIN_P" desc="有功功率最小值" type="6" DO="MMXU3$MX$W" DA="phs*$cVal$mag$f" />
</Sequence>
<!--功率PQ部分(T相)-->
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<Value name="G_PF" desc="功率因数95值" type="6" DO="MMXU4$MX$TotPF" DA="mag$f" />
<Value name="PF" desc="功率因数平均值" type="6" DO="MMXU2$MX$TotPF" DA="mag$f" />
<Value name="MAX_PF" desc="功率因数最大值" type="6" DO="MMXU1$MX$TotPF" DA="mag$f" />
<Value name="MIN_PF" desc="功率因数最小值" type="6" DO="MMXU3$MX$TotPF" DA="mag$f" />
<Value name="G_DF" desc="位移功率因数95值" type="6" DO="MMXU4$MX$TotDF" DA="mag$f" />
<Value name="DF" desc="位移功率因数平均值" type="6" DO="MMXU2$MX$TotDF" DA="mag$f" />
<Value name="MAX_DF" desc="位移功率因数最大值" type="6" DO="MMXU1$MX$TotDF" DA="mag$f" />
<Value name="MIN_DF" desc="位移功率因数最小值" type="6" DO="MMXU3$MX$TotDF" DA="mag$f" />
<Value name="G_S" desc="视在功率95值" type="6" DO="MMXU4$MX$TotVA" DA="mag$f" />
<Value name="S" desc="视在功率平均值" type="6" DO="MMXU2$MX$TotVA" DA="mag$f" />
<Value name="MAX_S" desc="视在功率最大值" type="6" DO="MMXU1$MX$TotVA" DA="mag$f" />
<Value name="MIN_S" desc="视在功率最小值" type="6" DO="MMXU3$MX$TotVA" DA="mag$f" />
<Value name="G_Q" desc="无功功率95值" type="6" DO="MMXU4$MX$TotVAr" DA="mag$f" />
<Value name="Q" desc="无功功率平均值" type="6" DO="MMXU2$MX$TotVAr" DA="mag$f" />
<Value name="MAX_Q" desc="无功功率最大值" type="6" DO="MMXU1$MX$TotVAr" DA="mag$f" />
<Value name="MIN_Q" desc="无功功率最小值" type="6" DO="MMXU3$MX$TotVAr" DA="mag$f" />
<Value name="G_P" desc="有功功率95值" type="6" DO="MMXU4$MX$TotW" DA="mag$f" />
<Value name="P" desc="有功功率平均值" type="6" DO="MMXU2$MX$TotW" DA="mag$f" />
<Value name="MAX_P" desc="有功功率最大值" type="6" DO="MMXU1$MX$TotW" DA="mag$f" />
<Value name="MIN_P" desc="有功功率最小值" type="6" DO="MMXU3$MX$TotW" DA="mag$f" />
</Sequence>
</Item>
</Monitor>
</DataType>
</Topic>
<Topic name="RTDATA" desc="实时数据">
<DataType name="DATA_TYPE" value="01" desc="实时稳态数据" send="1" type="0">
<Monitor name="-" desc="监测点" type="1">
<Item name="FLAG" value="0" desc="剔除标记" type="3" />
<Item name="TIME" desc="发生时刻" type="3" />
<Item name="V" desc="电压" type="4" >
<!--电压V部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<Value name="VRMS" desc="电压有效值" type="6" DO="MMXU0$MX$PhV" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="DELTA_V" desc="电压偏差" type="6" DO="MMXU0$MX$PhVDev" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="VTHD" desc="电压总谐波畸变率" type="6" DO="MHAI0$MX$ThdPhV" DA="phs*$cVal$mag$f" Coefficient="1" />
<!--icd101/102模型-->
<Value name="VFUND_ANGLE" desc="基波电压相角" type="6" DO="MHAI0$MX$HFundPhV" DA="phs*$cVal$ang$f" Coefficient="1" />
<Value name="VRMS_LVR" desc="线电压有效值" type="6" DO="MMXU0$MX$PPV" DA="l_phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" />
<!--icd100模型-->
<!--<Value name="V_ANGLE" desc="基波电压相角" type="6" DO="MMXU0$MX$PhV||MMXU0$MX$PPV" DA="phs*$cVal$ang$f||phs##$cVal$ang$f" Coefficient="1" /-->
<!--icd101/102模型-->
<Value name="V1" desc="基波电压有效值" type="6" DO="MHAI0$MX$HFundPhV" DA="phs*$cVal$mag$f" Coefficient="1" />
<!--icd100模型-->
<!--Value name="V1" desc="基波电压有效值" type="6" DO="MHAI2$MX$HFundPhV||MHAI2$MX$HFundPPV" DA="phs*$cVal$mag$f||phs##$cVal$mag$f" Coefficient="1" /-->
<Value name="V%2,50%" desc="2-50次谐波电压含有率" type="6" DO="MHAI0$MX$HRPhV" DA="phs*Har[%-2]$mag$f" Coefficient="1" Offset="0" />
<Value name="SV_%0,49%" desc="1-50次间谐波电压含有率" type="6" DO="MHAI5$MX$HRPhV" DA="phs*Har[%-0]$mag$f" Coefficient="1" Offset="0" />
<Value name="VA%2,50%" desc="谐波电压相角(2-50)" type="6" DO="MHAI5$MX$HRPhV" DA="phs*Har[%-2]$ang$f" />
</Sequence>
<!--电压V部分(A-C相)角型接线-->
<Sequence name="SEQ" value="112" desc="相别(A-C相)" type="5">
<!--Coefficient 值系数转成kafka的时候乘以系数BaseFlag 基础数据标志 0或没有-非基础数据 1-基础数据LimitUp 数据合理上限,如果包含*%UN字符表示需要乘以电压等级电压如果包含*%U字符表示需要乘以电压等级/1.732电压例如220kV则相电压上限为1.5*220LimitDown 数据合理下限 如果包含*%U字符表示需要乘以电压等级电压-->
<Value name="DELTA_V" desc="电压偏差" type="6" DO="MMXU0$MX$PPVDev" DA="phs*$cVal$mag$f" Coefficient="1"/>
<Value name="VRMS_LVR" desc="电压有效值" type="6" DO="MMXU0$MX$PPV" DA="phs*$cVal$mag$f" BaseFlag="1" LimitUp="0*%U" LimitDown="150*%U" Coefficient="1" />
<Value name="VTHD" desc="电压总谐波畸变率" type="6" DO="MHAI0$MX$ThdPPV" DA="phs*$cVal$mag$f" Coefficient="1"/>
<Value name="VFUND_ANGLE" desc="基波电压相角" type="6" DO="MHAI0$MX$HFundPPV" DA="phs*$cVal$ang$f" Coefficient="1" />
<Value name="V1" desc="基波电压有效值" type="6" DO="MHAI0$MX$HFundPPV" DA="phs*$cVal$mag$f" Coefficient="1"/>
<Value name="SV_%0,49%" desc="间谐波电压含有率(f25-2475)" type="6" DO="MHAI0$MX$HRPPV" DA="phs*Har[%-0]$mag$f" Coefficient="1" Offset="0" />
<Value name="V%2,50%" desc="谐波电压含有率(2-50)" type="6" DO="MHAI5$MX$HRPPV" DA="phs*Har[%-2]$mag$f" Coefficient="1" Offset="0" />
<Value name="VA%2,50%" desc="谐波电压相角(2-50)" type="6" DO="MHAI5$MX$HRPPV" DA="phs*Har[%-2]$ang$f" />
</Sequence>
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<!--电压V部分(T相)-->
<Value name="VNSEQ" desc="负序电压" type="6" DO="MSQI0$MX$SeqV" DA="c2$cVal$mag$f" Coefficient="1" />
<Value name="V_UNBAN" desc="负序电压不平衡" type="6" DO="MSQI0$MX$ImbNgV" DA="mag$f" Coefficient="1" />
<Value name="VZSEQ" desc="零序电压" type="6" DO="MSQI0$MX$SeqV" DA="c3$cVal$mag$f" Coefficient="1" />
<Value name="VZSEQ_UNBAN" desc="零序电压不平衡" type="6" DO="MSQI0$MX$ImbZroV" DA="mag$f" Coefficient="1" />
<Value name="FREQ" desc="频率" type="6" DO="MMXU0$MX$Hz" DA="mag$f" Coefficient="1" />
<Value name="DELTA_FREQ" desc="频率偏差" type="6" DO="MMXU0$MX$HzDev" DA="mag$f" Coefficient="1" />
<Value name="VPSEQ" desc="正序电压" type="6" DO="MSQI0$MX$SeqV" DA="c1$cVal$mag$f" Coefficient="1" />
</Sequence>
</Item>
<Item name="I" desc="电流" type="4" >
<!--电流I部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<Value name="IRMS" desc="电流有效值" type="6" DO="MMXU0$MX$A" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="I1" desc="基波电流有效值" type="6" DO="MHAI0$MX$HA" DA="phs*Har[0]$mag$f" Coefficient="1" />
<Value name="ITHD" desc="电流总谐波畸变率" type="6" DO="MHAI0$MX$ThdA" DA="phs*$cVal$mag$f" Coefficient="1" />
<!--icd101/102模型-->
<Value name="I_ANGLE" desc="基波电流相角" type="6" DO="MHAI0$MX$HA" DA="phs*Har[0]$ang$f" Coefficient="1" />
<!--icd100模型-->
<!--Value name="I_ANGLE" desc="基波电流相角" type="6" DO="MMXU0$MX$A" DA="phs*$cVal$ang$f" Coefficient="1" /-->
<Value name="I%2,50%" desc="2-50次谐波电流幅值" type="6" DO="MHAI0$MX$HA" DA="phs*Har[%-1]$mag$f" Coefficient="1" Offset="0" />
<Value name="SI_%0,49%" desc="1-50次间谐波电流含有率" type="6" DO="MHAI5$MX$HA" DA="phs*Har[%-0]$mag$f" Coefficient="1" Offset="0" />
<!--Value name="I%1,49%" desc="1-50次谐波电流含有率" type="6" DO="MHAI0$MX$HA" DA="phs*Har[%-2]$mag$f" Coefficient="1" Offset="1" /-->
</Sequence>
<!--电流I部分(T相)-->
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<Value name="INSEQ" desc="负序电流" type="6" DO="MSQI0$MX$SeqA" DA="c2$cVal$mag$f" Coefficient="1" />
<Value name="I_UNBAN" desc="负序电流不平衡" type="6" DO="MSQI0$MX$ImbNgA" DA="mag$f" Coefficient="1" />
<Value name="IZSEQ" desc="零序电流" type="6" DO="MSQI0$MX$SeqA" DA="c3$cVal$mag$f" Coefficient="1" />
<Value name="IZSEQ_UNBAN" desc="零序电流不平衡" type="6" DO="MSQI0$MX$ImbZroA" DA="mag$f" Coefficient="1" />
<Value name="IPSEQ" desc="正序电流" type="6" DO="MSQI0$MX$SeqA" DA="c1$cVal$mag$f" Coefficient="1" />
</Sequence>
</Item>
<Item name="PQ" desc="功率" type="4" >
<!--功率PQ部分(A-C相)-->
<Sequence name="SEQ" value="7" desc="相别(A-C相)" type="5">
<Value name="PF" desc="功率因数" type="6" DO="MMXU0$MX$PF" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="DF" desc="基波功率因数" type="6" DO="MMXU0$MX$DF" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="P_FUND" desc="基波有功功率" type="6" DO="MHAI0$MX$HW" DA="phs*Har[0]$mag$f" Coefficient="1" />
<Value name="S" desc="视在功率" type="6" DO="MMXU0$MX$VA" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="Q" desc="无功功率" type="6" DO="MMXU0$MX$VAr" DA="phs*$cVal$mag$f" Coefficient="1" />
<Value name="P" desc="有功功率" type="6" DO="MMXU0$MX$W" DA="phs*$cVal$mag$f" Coefficient="1" />
</Sequence>
<!--功率PQ部分(T相)-->
<Sequence name="SEQ" value="8" desc="相别(T相)" type="5">
<Value name="PF" desc="功率因数" type="6" DO="MMXU0$MX$TotPF" DA="mag$f" Coefficient="1" />
<Value name="DF" desc="基波功率因数" type="6" DO="MMXU0$MX$TotDF" DA="mag$f" Coefficient="1" />
<Value name="S" desc="视在功率" type="6" DO="MMXU0$MX$TotVA" DA="mag$f" Coefficient="1" />
<Value name="Q" desc="无功功率" type="6" DO="MMXU0$MX$TotVAr" DA="mag$f" Coefficient="1" />
<Value name="P" desc="有功功率" type="6" DO="MMXU0$MX$TotW" DA="mag$f" Coefficient="1" />
</Sequence>
</Item>
</Monitor>
</DataType>
<DataType name="DATA_TYPE" value="02" desc="实时闪变数据" send="0" type="0">
<Monitor name="MONITOR" desc="监测点" type="1">
<Item name="TIME" desc="发生时刻" type="3" />
<Item name="F" desc="闪变" type="4" >
<Sequence name="SEQ" value="7" desc="相别" type="5" >
<Value name="SF" desc="短时闪变" type="6" DO="MFLK0$MX$PhPst||MFLK0$MX$PPPst" DA="phs*$cVal$mag$f||phs##$cVal$mag$f" Coefficient="1" PltFlag="False" />
<Value name="LF" desc="长时闪变" type="6" DO="MFLK0$MX$PhPlt||MFLK0$MX$PPPlt" DA="phs*$cVal$mag$f||phs##$cVal$mag$f" Coefficient="1" PltFlag="True" />
</Sequence>
</Item>
</Monitor>
</DataType>
<DataType name="DATA_TYPE" value="03" desc="实时暂态事件" send="0" type="0" >
<Monitor name="MONITOR" desc="监测点" type="1" >
<Item name="VOLTAGE" desc="暂态指标" type="4" >
<Sequence name="SEQ" value="-" desc="相别" type="5">
<Value name="MAG" desc="残余电压" type="6" DO="QVVR0$MX$VVa" DA="mag$f" Coefficient="1" />
<Value name="DUR" desc="持续时间" type="6" DO="QVVR0$MX$VVaTm" DA="mag$f" Coefficient="1" />
<!--Value name="STARTTIME" desc="开始时间" type="6" DO="" DA="" Coefficient="1" />
<Value name="ENDTIME" desc="结束时间" type="6" DO="" DA="" Coefficient="1" />
<Value name="DISKIND" desc="暂降类型" type="6" DO="" DA="" Coefficient="1" />
<Value name="WAVEFILE" desc="波形文件名称" type="6" DO="" DA="" Coefficient="1" /-->
</Sequence>
</Item>
</Monitor>
</DataType>
</Topic>
<Topic name="RTDATASOE" desc="实时SOE事件">
<DataType name="DATA_TYPE" value="01" desc="稳态SOE事件" type="0" >
<SOE desc="频率偏差越上限" type="9" DO="GGIO0$ST$Alm1" DA="stVal" TriggerFlag="Alm1" />
<SOE desc="频率偏差越下限" type="9" DO="GGIO0$ST$Alm2" DA="stVal" TriggerFlag="Alm2" />
<SOE desc="电压偏差越上限" type="9" DO="GGIO0$ST$Alm3" DA="stVal" TriggerFlag="Alm3" />
<SOE desc="电压偏差越下限" type="9" DO="GGIO0$ST$Alm4" DA="stVal" TriggerFlag="Alm4" />
<SOE desc="短时闪变越限" type="9" DO="GGIO0$ST$Alm5" DA="stVal" TriggerFlag="Alm5" />
<SOE desc="长时闪变越限" type="9" DO="GGIO0$ST$Alm6" DA="stVal" TriggerFlag="Alm6" />
<SOE desc="电压波动越限" type="9" DO="GGIO0$ST$Alm7" DA="stVal" TriggerFlag="Alm7" />
<SOE desc="电压负序不平衡度越限" type="9" DO="GGIO0$ST$Alm8" DA="stVal" TriggerFlag="Alm8" />
<SOE desc="电压总谐波畸变率越限" type="9" DO="GGIO0$ST$Alm9" DA="stVal" TriggerFlag="Alm9" />
<SOE desc="2次谐波电压越限" type="9" DO="GGIO0$ST$Alm10" DA="stVal" TriggerFlag="Alm10" />
<SOE desc="3次谐波电压越限" type="9" DO="GGIO0$ST$Alm11" DA="stVal" TriggerFlag="Alm11" />
<SOE desc="4次谐波电压越限" type="9" DO="GGIO0$ST$Alm12" DA="stVal" TriggerFlag="Alm12" />
<SOE desc="5次谐波电压越限" type="9" DO="GGIO0$ST$Alm13" DA="stVal" TriggerFlag="Alm13" />
<SOE desc="6次谐波电压越限" type="9" DO="GGIO0$ST$Alm14" DA="stVal" TriggerFlag="Alm14" />
<SOE desc="7次谐波电压越限" type="9" DO="GGIO0$ST$Alm15" DA="stVal" TriggerFlag="Alm15" />
<SOE desc="8次谐波电压越限" type="9" DO="GGIO0$ST$Alm16" DA="stVal" TriggerFlag="Alm16" />
<SOE desc="9次谐波电压越限" type="9" DO="GGIO0$ST$Alm17" DA="stVal" TriggerFlag="Alm17" />
<SOE desc="10次谐波电压越限" type="9" DO="GGIO0$ST$Alm18" DA="stVal" TriggerFlag="Alm18" />
<SOE desc="11次谐波电压越限" type="9" DO="GGIO0$ST$Alm19" DA="stVal" TriggerFlag="Alm19" />
<SOE desc="12次谐波电压越限" type="9" DO="GGIO0$ST$Alm20" DA="stVal" TriggerFlag="Alm20" />
<SOE desc="13次谐波电压越限" type="9" DO="GGIO0$ST$Alm21" DA="stVal" TriggerFlag="Alm21" />
<SOE desc="14次谐波电压越限" type="9" DO="GGIO0$ST$Alm22" DA="stVal" TriggerFlag="Alm22" />
<SOE desc="15次谐波电压越限" type="9" DO="GGIO0$ST$Alm23" DA="stVal" TriggerFlag="Alm23" />
<SOE desc="16次谐波电压越限" type="9" DO="GGIO0$ST$Alm24" DA="stVal" TriggerFlag="Alm24" />
<SOE desc="17次谐波电压越限" type="9" DO="GGIO0$ST$Alm25" DA="stVal" TriggerFlag="Alm25" />
<SOE desc="18次谐波电压越限" type="9" DO="GGIO0$ST$Alm26" DA="stVal" TriggerFlag="Alm26" />
<SOE desc="19次谐波电压越限" type="9" DO="GGIO0$ST$Alm27" DA="stVal" TriggerFlag="Alm27" />
<SOE desc="20次谐波电压越限" type="9" DO="GGIO0$ST$Alm28" DA="stVal" TriggerFlag="Alm28" />
<SOE desc="21次谐波电压越限" type="9" DO="GGIO0$ST$Alm29" DA="stVal" TriggerFlag="Alm29" />
<SOE desc="22次谐波电压越限" type="9" DO="GGIO0$ST$Alm30" DA="stVal" TriggerFlag="Alm30" />
<SOE desc="23次谐波电压越限" type="9" DO="GGIO0$ST$Alm31" DA="stVal" TriggerFlag="Alm31" />
<SOE desc="24次谐波电压越限" type="9" DO="GGIO0$ST$Alm32" DA="stVal" TriggerFlag="Alm32" />
<SOE desc="25次谐波电压越限" type="9" DO="GGIO0$ST$Alm33" DA="stVal" TriggerFlag="Alm33" />
<SOE desc="26次谐波电压越限" type="9" DO="GGIO0$ST$Alm34" DA="stVal" TriggerFlag="Alm34" />
<SOE desc="27次谐波电压越限" type="9" DO="GGIO0$ST$Alm35" DA="stVal" TriggerFlag="Alm35" />
<SOE desc="28次谐波电压越限" type="9" DO="GGIO0$ST$Alm36" DA="stVal" TriggerFlag="Alm36" />
<SOE desc="29次谐波电压越限" type="9" DO="GGIO0$ST$Alm37" DA="stVal" TriggerFlag="Alm37" />
<SOE desc="30次谐波电压越限" type="9" DO="GGIO0$ST$Alm38" DA="stVal" TriggerFlag="Alm38" />
<SOE desc="31次谐波电压越限" type="9" DO="GGIO0$ST$Alm39" DA="stVal" TriggerFlag="Alm39" />
<SOE desc="32次谐波电压越限" type="9" DO="GGIO0$ST$Alm40" DA="stVal" TriggerFlag="Alm40" />
<SOE desc="33次谐波电压越限" type="9" DO="GGIO0$ST$Alm41" DA="stVal" TriggerFlag="Alm41" />
<SOE desc="34次谐波电压越限" type="9" DO="GGIO0$ST$Alm42" DA="stVal" TriggerFlag="Alm42" />
<SOE desc="35次谐波电压越限" type="9" DO="GGIO0$ST$Alm43" DA="stVal" TriggerFlag="Alm43" />
<SOE desc="36次谐波电压越限" type="9" DO="GGIO0$ST$Alm44" DA="stVal" TriggerFlag="Alm44" />
<SOE desc="37次谐波电压越限" type="9" DO="GGIO0$ST$Alm45" DA="stVal" TriggerFlag="Alm45" />
<SOE desc="38次谐波电压越限" type="9" DO="GGIO0$ST$Alm46" DA="stVal" TriggerFlag="Alm46" />
<SOE desc="39次谐波电压越限" type="9" DO="GGIO0$ST$Alm47" DA="stVal" TriggerFlag="Alm47" />
<SOE desc="40次谐波电压越限" type="9" DO="GGIO0$ST$Alm48" DA="stVal" TriggerFlag="Alm48" />
<SOE desc="41次谐波电压越限" type="9" DO="GGIO0$ST$Alm49" DA="stVal" TriggerFlag="Alm49" />
<SOE desc="42次谐波电压越限" type="9" DO="GGIO0$ST$Alm50" DA="stVal" TriggerFlag="Alm50" />
<SOE desc="43次谐波电压越限" type="9" DO="GGIO0$ST$Alm51" DA="stVal" TriggerFlag="Alm51" />
<SOE desc="44次谐波电压越限" type="9" DO="GGIO0$ST$Alm52" DA="stVal" TriggerFlag="Alm52" />
<SOE desc="45次谐波电压越限" type="9" DO="GGIO0$ST$Alm53" DA="stVal" TriggerFlag="Alm53" />
<SOE desc="46次谐波电压越限" type="9" DO="GGIO0$ST$Alm54" DA="stVal" TriggerFlag="Alm54" />
<SOE desc="47次谐波电压越限" type="9" DO="GGIO0$ST$Alm55" DA="stVal" TriggerFlag="Alm55" />
<SOE desc="48次谐波电压越限" type="9" DO="GGIO0$ST$Alm56" DA="stVal" TriggerFlag="Alm56" />
<SOE desc="49次谐波电压越限" type="9" DO="GGIO0$ST$Alm57" DA="stVal" TriggerFlag="Alm57" />
<SOE desc="50次谐波电压越限" type="9" DO="GGIO0$ST$Alm58" DA="stVal" TriggerFlag="Alm58" />
<SOE desc="2次谐波电流越限" type="9" DO="GGIO0$ST$Alm59" DA="stVal" TriggerFlag="Alm59" />
<SOE desc="3次谐波电流越限" type="9" DO="GGIO0$ST$Alm60" DA="stVal" TriggerFlag="Alm60" />
<SOE desc="4次谐波电流越限" type="9" DO="GGIO0$ST$Alm61" DA="stVal" TriggerFlag="Alm61" />
<SOE desc="5次谐波电流越限" type="9" DO="GGIO0$ST$Alm62" DA="stVal" TriggerFlag="Alm62" />
<SOE desc="6次谐波电流越限" type="9" DO="GGIO0$ST$Alm63" DA="stVal" TriggerFlag="Alm63" />
<SOE desc="7次谐波电流越限" type="9" DO="GGIO0$ST$Alm64" DA="stVal" TriggerFlag="Alm64" />
<SOE desc="8次谐波电流越限" type="9" DO="GGIO0$ST$Alm65" DA="stVal" TriggerFlag="Alm65" />
<SOE desc="9次谐波电流越限" type="9" DO="GGIO0$ST$Alm66" DA="stVal" TriggerFlag="Alm66" />
<SOE desc="10次谐波电流越限" type="9" DO="GGIO0$ST$Alm67" DA="stVal" TriggerFlag="Alm67" />
<SOE desc="11次谐波电流越限" type="9" DO="GGIO0$ST$Alm68" DA="stVal" TriggerFlag="Alm68" />
<SOE desc="12次谐波电流越限" type="9" DO="GGIO0$ST$Alm69" DA="stVal" TriggerFlag="Alm69" />
<SOE desc="13次谐波电流越限" type="9" DO="GGIO0$ST$Alm70" DA="stVal" TriggerFlag="Alm70" />
<SOE desc="14次谐波电流越限" type="9" DO="GGIO0$ST$Alm71" DA="stVal" TriggerFlag="Alm71" />
<SOE desc="15次谐波电流越限" type="9" DO="GGIO0$ST$Alm72" DA="stVal" TriggerFlag="Alm72" />
<SOE desc="16次谐波电流越限" type="9" DO="GGIO0$ST$Alm73" DA="stVal" TriggerFlag="Alm73" />
<SOE desc="17次谐波电流越限" type="9" DO="GGIO0$ST$Alm74" DA="stVal" TriggerFlag="Alm74" />
<SOE desc="18次谐波电流越限" type="9" DO="GGIO0$ST$Alm75" DA="stVal" TriggerFlag="Alm75" />
<SOE desc="19次谐波电流越限" type="9" DO="GGIO0$ST$Alm76" DA="stVal" TriggerFlag="Alm76" />
<SOE desc="20次谐波电流越限" type="9" DO="GGIO0$ST$Alm77" DA="stVal" TriggerFlag="Alm77" />
<SOE desc="21次谐波电流越限" type="9" DO="GGIO0$ST$Alm78" DA="stVal" TriggerFlag="Alm78" />
<SOE desc="22次谐波电流越限" type="9" DO="GGIO0$ST$Alm79" DA="stVal" TriggerFlag="Alm79" />
<SOE desc="23次谐波电流越限" type="9" DO="GGIO0$ST$Alm80" DA="stVal" TriggerFlag="Alm80" />
<SOE desc="24次谐波电流越限" type="9" DO="GGIO0$ST$Alm81" DA="stVal" TriggerFlag="Alm81" />
<SOE desc="25次谐波电流越限" type="9" DO="GGIO0$ST$Alm82" DA="stVal" TriggerFlag="Alm82" />
<SOE desc="26次谐波电流越限" type="9" DO="GGIO0$ST$Alm83" DA="stVal" TriggerFlag="Alm83" />
<SOE desc="27次谐波电流越限" type="9" DO="GGIO0$ST$Alm84" DA="stVal" TriggerFlag="Alm84" />
<SOE desc="28次谐波电流越限" type="9" DO="GGIO0$ST$Alm85" DA="stVal" TriggerFlag="Alm85" />
<SOE desc="29次谐波电流越限" type="9" DO="GGIO0$ST$Alm86" DA="stVal" TriggerFlag="Alm86" />
<SOE desc="30次谐波电流越限" type="9" DO="GGIO0$ST$Alm87" DA="stVal" TriggerFlag="Alm87" />
<SOE desc="31次谐波电流越限" type="9" DO="GGIO0$ST$Alm88" DA="stVal" TriggerFlag="Alm88" />
<SOE desc="32次谐波电流越限" type="9" DO="GGIO0$ST$Alm89" DA="stVal" TriggerFlag="Alm89" />
<SOE desc="33次谐波电流越限" type="9" DO="GGIO0$ST$Alm90" DA="stVal" TriggerFlag="Alm90" />
<SOE desc="34次谐波电流越限" type="9" DO="GGIO0$ST$Alm91" DA="stVal" TriggerFlag="Alm91" />
<SOE desc="35次谐波电流越限" type="9" DO="GGIO0$ST$Alm92" DA="stVal" TriggerFlag="Alm92" />
<SOE desc="36次谐波电流越限" type="9" DO="GGIO0$ST$Alm93" DA="stVal" TriggerFlag="Alm93" />
<SOE desc="37次谐波电流越限" type="9" DO="GGIO0$ST$Alm94" DA="stVal" TriggerFlag="Alm94" />
<SOE desc="38次谐波电流越限" type="9" DO="GGIO0$ST$Alm95" DA="stVal" TriggerFlag="Alm95" />
<SOE desc="39次谐波电流越限" type="9" DO="GGIO0$ST$Alm96" DA="stVal" TriggerFlag="Alm96" />
<SOE desc="40次谐波电流越限" type="9" DO="GGIO0$ST$Alm97" DA="stVal" TriggerFlag="Alm97" />
<SOE desc="41次谐波电流越限" type="9" DO="GGIO0$ST$Alm98" DA="stVal" TriggerFlag="Alm98" />
<SOE desc="42次谐波电流越限" type="9" DO="GGIO0$ST$Alm99" DA="stVal" TriggerFlag="Alm99" />
<SOE desc="43次谐波电流越限" type="9" DO="GGIO0$ST$Alm100" DA="stVal" TriggerFlag="Alm100" />
<SOE desc="44次谐波电流越限" type="9" DO="GGIO0$ST$Alm101" DA="stVal" TriggerFlag="Alm101" />
<SOE desc="45次谐波电流越限" type="9" DO="GGIO0$ST$Alm102" DA="stVal" TriggerFlag="Alm102" />
<SOE desc="46次谐波电流越限" type="9" DO="GGIO0$ST$Alm103" DA="stVal" TriggerFlag="Alm103" />
<SOE desc="47次谐波电流越限" type="9" DO="GGIO0$ST$Alm104" DA="stVal" TriggerFlag="Alm104" />
<SOE desc="48次谐波电流越限" type="9" DO="GGIO0$ST$Alm105" DA="stVal" TriggerFlag="Alm105" />
<SOE desc="49次谐波电流越限" type="9" DO="GGIO0$ST$Alm106" DA="stVal" TriggerFlag="Alm106" />
<SOE desc="50次谐波电流越限" type="9" DO="GGIO0$ST$Alm107" DA="stVal" TriggerFlag="Alm107" />
<SOE desc="电压越上限(自定义触发)" type="9" DO="GGIO0$ST$Alm108" DA="stVal" TriggerFlag="Alm108" />
<SOE desc="电压越下限(自定义触发)" type="9" DO="GGIO0$ST$Alm109" DA="stVal" TriggerFlag="Alm109" />
<SOE desc="电流越上限(自定义触发)" type="9" DO="GGIO0$ST$Alm110" DA="stVal" TriggerFlag="Alm110" />
<SOE desc="电流越下限(自定义触发)" type="9" DO="GGIO0$ST$Alm111" DA="stVal" TriggerFlag="Alm111" />
<SOE desc="电压变化量越限(自定义触发)" type="9" DO="GGIO0$ST$Alm112" DA="stVal" TriggerFlag="Alm112" />
<SOE desc="电流变化量越限(自定义触发)" type="9" DO="GGIO0$ST$Alm113" DA="stVal" TriggerFlag="Alm113" />
</DataType>
<DataType name="DATA_TYPE" value="02" desc="暂态SOE事件" type="0" >
</DataType>
<DataType name="DATA_TYPE" value="03" desc="状态SOE事件" type="0" >
<SOE desc="终端工作电源上电" type="9" DO="LPHD0$ST$PwrUp" DA="stVal" TriggerFlag="PwrUp" />
<SOE desc="终端工作电源掉电" type="9" DO="GGIO0$ST$PwrDn" DA="stVal" TriggerFlag="PwrDn" />
</DataType>
</Topic>
<Topic name="SOEDATA" desc="告警SOE">
<SOE name="ThdVVal" desc="电压总畸变率越限告警" type="9" DO="GGIO0$ST$Alm9" DA="stVal" />
<SOE name="ThdAVal" desc="电流总畸变率越限告警" type="9" DO="" DA="" />
<SOE name="HToddVVal" desc="奇次谐波电压含有率越限告警" type="9" DO="" DA="" />
<SOE name="HTeddVVal" desc="偶次谐波电压含有率越限告警" type="9" DO="" DA="" />
<SOE name="H2AVal" desc="2次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm59" DA="stVal" />
<SOE name="H3AVal" desc="3次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm60" DA="stVal" />
<SOE name="H4AVal" desc="4次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm61" DA="stVal" />
<SOE name="H5AVal" desc="5次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm62" DA="stVal" />
<SOE name="H7AVal" desc="7次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm64" DA="stVal" />
<SOE name="H9AVal" desc="9次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm66" DA="stVal" />
<SOE name="H11AVal" desc="11次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm68" DA="stVal" />
<SOE name="H13AVal" desc="13次谐波电流越限告警" type="9" DO="GGIO0$ST$Alm70" DA="" />
<SOE name="ImbNgVFVal" desc="电压负序不平衡度越限告警" type="9" DO="GGIO0$ST$Alm8" DA="stVal" />
<SOE name="ImbNgAFVal" desc="电流负序不平衡度越限告警" type="9" DO="" DA="" />
<SOE name="OvHzStrVal" desc="频率高越限告警" type="9" DO="GGIO0$ST$Alm1" DA="stVal" />
<SOE name="UnHzStrVal" desc="频率低越限告警" type="9" DO="GGIO0$ST$Alm2" DA="" />
<SOE name="LRVInterrup" desc="长期电压中断告警" type="9" DO="" DA="" />
<SOE name="LRVSwell" desc="电压上偏差越限告警" type="9" DO="GGIO0$ST$Alm3" DA="stVal" />
<SOE name="LRVSag" desc="电压下偏差越限告警" type="9" DO="GGIO0$ST$Alm4" DA="stVal" />
<SOE name="PhPstVal" desc="短时闪变越限告警" type="9" DO="GGIO0$ST$Alm5" DA="stVal" />
<SOE name="PhPltVal" desc="长时闪变越限告警" type="9" DO="GGIO0$ST$Alm6" DA="stVal" />
<SOE name="PhyStateFault" desc="终端运行状态:故障" type="9" DO="" DA="" />
<SOE name="PhyStateRun" desc="终端运行状态:运行" type="9" DO="" DA="" />
<SOE name="PwrUp" desc="终端上电" type="9" DO="" DA="" />
<SOE name="PwrDn" desc="终端掉电" type="9" DO="" DA="" />
<SOE name="CommInterrupt" desc="终端通信中断" type="9" DO="" DA="" />
<SOE name="CommResume" desc="终端通信恢复" type="9" DO="" DA="" />
</Topic>
</JSConfigTemplate>

6
LFtid1056/etc/runtime.cf Normal file
View File

@@ -0,0 +1,6 @@
# 文件名runtime.cf
# 执行程序路径 ^ 可执行程序名 启动参数 ^ 重启特有参数 ^ 首次启动特有参数 ^ 程序首次启动前的延时秒数 ^ 重启是否忽略 ^ 首次启动是否忽略
/home/pq/zwproject/LFtid1056/bin/ ^ cloud-front-test -s 3_3^ ^ ^ 1 ^ ^
/home/pq/zwproject/LFtid1056/bin/ ^ cloud-front-test -s 2_3^ ^ ^ 1 ^ ^
/home/pq/zwproject/LFtid1056/bin/ ^ cloud-front-test -s 1_3^ ^ ^ 1 ^ ^
/home/pq/zwproject/LFtid1056/bin/ ^ fe_watchdog -m 8192 ^ ^ ^ 1 ^ IGNORE_RESTART ^

View File

@@ -8,6 +8,8 @@
#include "cloudfront/code/interface.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
#if 0
@@ -32,6 +34,9 @@ typedef struct {
} thread_info_t;
#endif
extern int INITFLAG;//̨<>˵ȳ<CBB5>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD>־
extern void cleanup_args(ThreadArgs* args);
void init_daemon(void)
{
int pid;
@@ -108,6 +113,32 @@ std::vector<DeviceInfo> generate_test_devices(int count) {
return devices;
}
void PrintDevices(const std::vector<DeviceInfo>& devices) {
std::cout << "==== Devices List (" << devices.size() << ") ====\n";
for (const auto& dev : devices) {
std::cout << "Device ID : " << dev.device_id << "\n";
std::cout << "Name : " << dev.name << "\n";
std::cout << "Model : " << dev.model << "\n";
std::cout << "MAC : " << dev.mac << "\n";
std::cout << "Status : " << dev.status << "\n";
std::cout << "Points (" << dev.points.size() << "):\n";
for (const auto& pt : dev.points) {
std::cout << " Point ID : " << pt.point_id << "\n";
std::cout << " Name : " << pt.name << "\n";
std::cout << " Device ID : " << pt.device_id << "\n";
std::cout << " Cpu No : " << pt.nCpuNo << "\n";
std::cout << " PT1 : " << pt.PT1 << "\n";
std::cout << " PT2 : " << pt.PT2 << "\n";
std::cout << " CT1 : " << pt.CT1 << "\n";
std::cout << " CT2 : " << pt.CT2 << "\n";
std::cout << " Scale : " << pt.strScale << "\n";
std::cout << " PTType : " << pt.nPTType << "\n";
std::cout << "----------------------\n";
}
std::cout << "==========================\n";
}
}
/* <20>̹߳<DFB3><CCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0<><30><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>*/
/* <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD><EFBFBD>̺߳<DFB3><CCBA><EFBFBD>*/
void* client_manager_thread(void* arg) {
@@ -123,31 +154,35 @@ void* client_manager_thread(void* arg) {
printf("Started client connections\n");
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<PointInfo> points1 = {
{"P001", "Main Voltage", "D001",1 ,1, 1, 1, 1},
{"P002", "Backup Voltage", "D001",2 ,1, 1, 1, 1}
/*std::vector<PointInfo> points1 = {
{"P001", "Main Voltage", "D001",1 ,1, 1, 1, 1,"0.38k",0},
{"P002", "Backup Voltage", "D001",2 ,1, 1, 1, 1,"0.38k",0}
};
std::vector<PointInfo> points2 = {
{"P101", "Generator Output", "D002",1 ,1, 1, 1, 1}
};
//00-B7-8D-A8-00-D6
{"P003", "Main Voltage", "D002",1 ,1, 1, 1, 1,"0.38k",0},
{"P004", "Backup Voltage", "D002",2 ,1, 1, 1, 1,"0.38k",0}
};*/
//00B78DA800D6 00-B7-8D-01-79-06 00-B7-8D-A8-00-D6 00-B7-8D-01-71-09 00-B7-8D-01-88-7f
// <20><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>б<EFBFBD>
std::vector<DeviceInfo> devices = {
/*std::vector<DeviceInfo> devices = {
{
"D001", "Primary Device", "Model-X", "00-B7-8D-A8-00-D9",
1, points1
"D001", "Primary Device", "Model-X", "00-B7-8D-01-88-7f",
1, points1,true
},
{
"D002", "Backup Device", "Model-Y", "00-B7-8D-01-79-06",
1, points2
"D002", "Primary Device1", "Model-X1", "00-B7-8D-01-71-09",
1, points2,true
}
};
};*/
// <20><><EFBFBD><EFBFBD>100<30><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>
std::vector<DeviceInfo> test_devices = generate_test_devices(100);
//std::vector<DeviceInfo> test_devices = generate_test_devices(100);
//std::vector<DeviceInfo> devices = GenerateDeviceInfoFromLedger(terminal_devlist);//lnk<6E><6B><EFBFBD><EFBFBD>
//lnk<EFBFBD><EFBFBD>̨<EFBFBD>˶<EFBFBD>ȡ<EFBFBD>
std::vector<DeviceInfo> devices = GenerateDeviceInfoFromLedger(terminal_devlist);//lnk<6E><6B><EFBFBD><EFBFBD>
//̨<>˴<EFBFBD>ӡ
PrintDevices(devices);
// <20><><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
start_client_connect(devices);
@@ -215,7 +250,7 @@ void restart_thread(int index) {
int* new_index = (int*)malloc(sizeof(int));
*new_index = index;
if (index == 0) {
if (index == 1) {
// <20>ͻ<EFBFBD><CDBB>˹<EFBFBD><CBB9><EFBFBD><EFBFBD>߳<EFBFBD>
if (pthread_create(&thread_info[index].tid, NULL, client_manager_thread, new_index) != 0) {
pthread_mutex_lock(&global_lock);
@@ -225,7 +260,7 @@ void restart_thread(int index) {
free(new_index);
}
}
else if (index == 1) {
else if (index == 2) {
// <20><>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
if (pthread_create(&thread_info[index].tid, NULL, message_processor_thread, new_index) != 0) {
pthread_mutex_lock(&global_lock);
@@ -235,7 +270,7 @@ void restart_thread(int index) {
free(new_index);
}
}
else if (index == 2) {
else if (index == 0) {
// <20>ӿڣ<D3BF>mq
char* argv[] = { (char*)new_index };//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺Ų<CCBA><C5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ThreadArgs* args = new ThreadArgs{1, argv};
@@ -259,13 +294,23 @@ int is_thread_alive(pthread_t tid) {
return pthread_tryjoin_np(tid, NULL) == EBUSY; // EBUSY<53><59>ʾ<EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
//lnk<6E><6B><EFBFBD><EFBFBD>
ThreadArgs* make_thread_args_from_strs(const std::vector<std::string>& args_vec) {
char** argv = new char*[args_vec.size() + 1]; // <20><>һ<EFBFBD><D2BB> nullptr <20><>β
for (size_t i = 0; i < args_vec.size(); ++i) {
argv[i] = strdup(args_vec[i].c_str()); // strdup <20><> malloc <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
argv[args_vec.size()] = nullptr;
return new ThreadArgs{static_cast<int>(args_vec.size()), argv};
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
int main(int argc ,char** argv) {//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD>
if(!parse_param(argc,argv)){
std::cerr << "process param error,exit" << std::endl;
return 1;
}
//init_daemon();
init_daemon();
srand(time(NULL)); // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><>ʼ<EFBFBD><CABC><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD>
@@ -275,34 +320,46 @@ int main(int argc ,char** argv) {//
pthread_mutex_init(&thread_info[i].lock, NULL); // <20><>ʼ<EFBFBD><CABC>ÿ<EFBFBD><C3BF><EFBFBD>̵߳<DFB3><CCB5><EFBFBD>
}
//<2F>ӿں<D3BF>mq
ThreadArgs* args = make_thread_args_from_strs({ "0" });
if (pthread_create(&thread_info[0].tid, NULL, cloudfrontthread, args) != 0) {
printf("Failed to create message processor thread 0\n");
cleanup_args(args);
}
while(!INITFLAG){
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "waiting cloudfront initialize ..." << std::endl;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>߳<EFBFBD><DFB3><EFBFBD>
for (int i = 0; i < THREAD_CONNECTIONS; i++) {
for (int i = 1; i < THREAD_CONNECTIONS; i++) {
int* index = (int*)malloc(sizeof(int));
*index = i;
if (i == 0) {
if (i == 1) {
// <20>ͻ<EFBFBD><CDBB>˹<EFBFBD><CBB9><EFBFBD><EFBFBD>߳<EFBFBD>
if (pthread_create(&thread_info[i].tid, NULL, client_manager_thread, index) != 0) {
printf("Failed to create client manager thread %d\n", i);
free(index);
}
}
else if (i == 1) {
else if (i == 2) {
// <20><>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
if (pthread_create(&thread_info[i].tid, NULL, message_processor_thread, index) != 0) {
printf("Failed to create message processor thread %d\n", i);
free(index);
}
}
else if (i == 2){
//<2F>ӿں<D3BF>mq
else if (i == 3){
/*//<2F>ӿں<D3BF>mq
char* argv[] = { (char*)index };//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺Ų<CCBA><C5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ThreadArgs* args = new ThreadArgs{1, argv};
if (pthread_create(&thread_info[i].tid, NULL, cloudfrontthread, args) != 0) {
printf("Failed to create message processor thread %d\n", i);
delete args; // <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6>ͷ<EFBFBD>
free(index);
}
}*/
}
else {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
@@ -338,18 +395,33 @@ int main(int argc ,char** argv) {//
}
}
/*// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<PointInfo> points2 = {
{"P101", "Generator Output", "D002",1 ,1, 1, 1, 1,"0.38k",0}
};
//00B78DA800D6 00-B7-8D-01-79-06 00-B7-8D-A8-00-D6
// <20><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>б<EFBFBD>
std::vector<DeviceInfo> devices = {
{
"D002", "Backup Device", "Model-Y", "00-B7-8D-A8-00-D6",
1, points2,true
}
};*/
// <20><><EFBFBD><EFBFBD>socket<65><74><EFBFBD><EFBFBD>״̬
static int queue_monitor = 0;
//static int count = 3;
if (++queue_monitor >= 10) { // ÿ10<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>
if (++queue_monitor >= 20) { // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>
printf("Message queue size: %zu\n", message_queue.size());
queue_monitor = 0;
/*for (const auto& device : devices) {
//ClientManager::instance().add_device(device);
}*/
/*std::vector<DeviceInfo> test_devices = generate_test_devices(count);
count++;
for (const auto& device : test_devices) {
ClientManager::instance().add_device(device);
}
for (const auto& device : test_devices) {
ClientManager::instance().remove_device("D001");
}*/