93 Commits

Author SHA1 Message Date
lnk
44852a0846 fix mq log control 2025-12-15 10:55:58 +08:00
lnk
50f82af3f3 add mq log control 2025-12-15 10:29:46 +08:00
lnk
2c48d7ae0a fix data race 2025-12-11 15:07:54 +08:00
lnk
7dbd4593fa remove useless code 2025-12-11 09:26:08 +08:00
lnk
e615188bb1 fix memleak 2025-12-09 16:29:55 +08:00
lnk
b4ce0fa5f9 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-12-08 15:34:53 +08:00
lnk
56382e9ccd modify threads 2025-12-08 15:34:46 +08:00
0c239be9a7 正负零分量调整 2025-12-08 15:21:15 +08:00
b08c632de4 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-12-02 10:53:52 +08:00
a1d8a55357 统计数据转换结构调整 2025-12-02 10:52:06 +08:00
lnk
93143fcba6 modify recall 2025-11-05 15:24:59 +08:00
lnk
02d2b021cd fix recall 2025-11-04 15:42:40 +08:00
lnk
beedb9aeca modify timeout 2025-11-04 10:00:29 +08:00
lnk
ba142d3fd3 fix single recall wave 2025-11-03 15:39:29 +08:00
lnk
c02f0cbbdd fix recall 2025-10-31 10:59:30 +08:00
lnk
5e63adc8f9 fix recall 2025-10-30 20:57:19 +08:00
lnk
06a2f3a75b fix wave 2025-10-28 20:59:05 +08:00
lnk
f69a6d2105 fix recall 2025-10-24 17:07:51 +08:00
lnk
07ac84d612 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-10-24 08:51:01 +08:00
lnk
fdd6a30fe2 modify recall 2025-10-24 08:50:54 +08:00
5ebb179c44 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-10-24 08:46:29 +08:00
fdbefa50ac 取消了测试告警的代码 2025-10-24 08:46:24 +08:00
lnk
a755c6faab recall modify 2025-10-22 15:57:50 +08:00
c7e7cd9078 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-10-16 15:04:28 +08:00
ff67e5320f 调整了设备移除函数,现在不会异常崩溃了 2025-10-16 15:04:22 +08:00
lnk
c55f2ab1af modify recall 2025-10-15 16:29:54 +08:00
24e1bf0125 Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2 2025-10-15 13:36:36 +08:00
8fb922e8c6 调整了设备的移除机制 2025-10-15 13:36:31 +08:00
lnk
4e15ffff06 fix ledger update 2025-10-14 10:46:30 +08:00
lnk
fbbb96a64a fix ledger update 2025-10-11 15:57:22 +08:00
lnk
987dba34dc finish git rebase 2025-10-11 10:31:39 +08:00
lnk
a43afb15c5 fix bash 2025-10-11 10:26:23 +08:00
lnk
c494225b38 fix some error and add some fun 2025-10-11 10:26:23 +08:00
lnk
35231baae7 modify ledger update and rtdata 2025-10-11 10:26:22 +08:00
lnk
caf3c308c1 add ledger update 2025-10-11 10:26:22 +08:00
lnk
5616d9096a add rtdata idx 2025-10-11 10:26:22 +08:00
lnk
a6127f0d28 add rtdata idx 2025-10-11 10:26:18 +08:00
lnk
4fe8aee149 modify logs 2025-10-11 10:23:18 +08:00
lnk
e997c88d82 fix deadlock 2025-10-11 10:19:04 +08:00
zw
b976795573 完成实时数据拆分 2025-09-30 08:40:18 +08:00
zw
1b00804522 添加了装置告警 2025-09-23 14:03:11 +08:00
lnk
0f16968452 fix file upload 2025-09-23 10:19:53 +08:00
lnk
db8aa8c07d fix qvvr 2025-09-22 16:46:33 +08:00
lnk
169aa9b34a add tag and key 2025-09-22 13:26:52 +08:00
lnk
825315440d fix qvvr 2025-09-16 16:42:15 +08:00
lnk
016caeb07c use tag 2025-09-16 11:15:04 +08:00
zw
7183cc1673 Merge branch '测试2' of http://192.168.1.22:3000/zw/Linux_Front1056 into 测试2 2025-09-16 11:11:49 +08:00
zw
cc5d5e2f81 调整了实时上送个数 2025-09-16 11:11:40 +08:00
lnk
0638b1dbf8 add comments 2025-09-16 11:07:10 +08:00
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
105 changed files with 13671 additions and 1208 deletions

View File

@@ -127,6 +127,8 @@
"cinttypes": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp"
}
"variant": "cpp",
"unordered_set": "cpp"
},
"cmake.sourceDirectory": "D:/canneng/云前置移植项目/zw/Linux_Front1056/LFtid1056/lib/libuv-v1.51.0"
}

BIN
LFtid1056.rar Normal file

Binary file not shown.

View File

@@ -147,7 +147,6 @@
<ClInclude Include="cloudfront\code\log4cplus\internal\internal.h" />
<ClInclude Include="cloudfront\code\log4cplus\internal\socket.h" />
<ClInclude Include="cloudfront\code\log4cplus\layout.h" />
<ClInclude Include="cloudfront\code\log4cplus\log4.h" />
<ClInclude Include="cloudfront\code\log4cplus\log4cplus.h" />
<ClInclude Include="cloudfront\code\log4cplus\log4judpappender.h" />
<ClInclude Include="cloudfront\code\log4cplus\logger.h" />

View File

@@ -169,9 +169,6 @@
<ClInclude Include="cloudfront\code\nlohmann\thirdparty\hedley\hedley_undef.hpp">
<Filter>cloudfront\code\nlohmann\thirdparty\hedley</Filter>
</ClInclude>
<ClInclude Include="cloudfront\code\log4cplus\log4.h">
<Filter>cloudfront\code\log4cplus</Filter>
</ClInclude>
<ClInclude Include="cloudfront\code\log4cplus\logger.h">
<Filter>cloudfront\code\log4cplus</Filter>
</ClInclude>

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=/FeProject
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

File diff suppressed because it is too large Load Diff

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

@@ -94,6 +94,11 @@ public:
std::atomic<bool> m_bIsFrontThreadCancle{false};
std::atomic<bool> m_IsMQConsumerCancel{false};
std::atomic<bool> m_frontRunning{false};
std::atomic<bool> m_consumerRunning{false};
std::atomic<bool> m_producerRunning{false};
std::atomic<bool> m_timerRunning{false};
std::mutex m_threadCheckMutex;
std::atomic<bool> m_needRestartFrontThread{false};
std::atomic<bool> m_needRestartConsumerThread{false};
@@ -110,6 +115,12 @@ public:
void StartMQProducerThread();
void StartTimerThread();
// [ADD] 统一的停止接口(便于重启前先停干净)
void StopFrontThread();
void StopMQConsumerThread();
void StopMQProducerThread();
void StopTimerThread();
void FrontThread();
void mqconsumerThread();
void mqproducerThread();

View File

@@ -25,7 +25,7 @@
#include "interface.h"
#include "rocketmq.h"
#include "nlohmann/json.hpp"
#include "log4cplus/log4.h"
#include "log4.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -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】筛选运行和在运
@@ -181,14 +181,14 @@ void handleUploadResponse(const std::string& response, std::string& wavepath) {
std::cout << "File URL: " << url << std::endl;
// 找到最后一个 '.'
size_t pos = fileName.find_last_of('.');
size_t pos = name.find_last_of('.');
std::string nameWithoutExt;
if (pos != std::string::npos) {
// 截取去掉后缀的部分
nameWithoutExt = fileName.substr(0, pos);
nameWithoutExt = name.substr(0, pos);
} else {
// 如果没有后缀,直接使用原文件名
nameWithoutExt = fileName;
nameWithoutExt = name;
}
// 拷贝到 wavepath
@@ -200,9 +200,28 @@ void handleUploadResponse(const std::string& response, std::string& wavepath) {
//上传文件
void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath) {
// 基本存在性检查
if (access(localpath.c_str(), F_OK) != 0) {
std::cerr << "Local file does not exist: " << localpath << std::endl;
return;
}
// ★新增stat 打印大小,便于快速确认读源
struct stat st {};
if (stat(localpath.c_str(), &st) != 0) {
perror("stat");
} else {
std::cout << "[debug] upload file: " << localpath
<< ", size=" << static_cast<long long>(st.st_size) << " bytes\n";
}
// 初始化 curl
CURL* curl = curl_easy_init();
if (curl) {
// ★新增:错误缓冲,便于看到更具体的错误
char errbuf[CURL_ERROR_SIZE] = {0};
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); // ★新增
// 设置请求 URL 和 POST 请求
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1);
@@ -211,21 +230,16 @@ void SendFileWeb(const std::string& strUrl, const std::string& localpath, const
curl_httppost* formpost = nullptr;
curl_httppost* lastptr = nullptr;
if (access(localpath.c_str(), F_OK) != 0) {
std::cerr << "Local file does not exist: " << localpath << std::endl;
return;
}
// 添加文件字段,直接从本地路径读取文件内容
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, localpath,
CURLFORM_FILE, localpath.c_str(),
CURLFORM_END);
// 添加 `path` 字段
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "path",
CURLFORM_COPYCONTENTS, cloudpath,
CURLFORM_COPYCONTENTS, cloudpath.c_str(),
CURLFORM_END);
// 添加 `isReserveName` 字段
@@ -238,13 +252,14 @@ void SendFileWeb(const std::string& strUrl, const std::string& localpath, const
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
// 设置头信息
struct curl_slist* header_list = nullptr;
header_list = curl_slist_append(header_list, "Content-Type: multipart/form-data");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
//struct curl_slist* header_list = nullptr;
//header_list = curl_slist_append(header_list, "Content-Type: multipart/form-data");
//curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
// 设置超时时间
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); // ★新增:避免多线程环境下超时触发信号
// 设置写入响应数据的函数
std::string resPost0;
@@ -254,7 +269,8 @@ void SendFileWeb(const std::string& strUrl, const std::string& localpath, const
// 执行请求
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "http web failed: " << curl_easy_strerror(res) << std::endl;
const char* em = errbuf[0] ? errbuf : curl_easy_strerror(res);
std::cerr << "http web failed: " << em << std::endl;
DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath);
} else {
std::cout << "http web success, response: " << resPost0 << std::endl;
@@ -263,7 +279,7 @@ void SendFileWeb(const std::string& strUrl, const std::string& localpath, const
// 清理
curl_formfree(formpost); // 释放表单数据
curl_slist_free_all(header_list); // 释放头部列表
//curl_slist_free_all(header_list); // 释放头部列表
curl_easy_cleanup(curl);
} else {
std::cerr << ">>> curl init failed" << std::endl;
@@ -408,8 +424,8 @@ void download_xml_for_icd(const std::string& MODEL_ID,
//读最新本地台账
std::string read_latest_ledger_file() {
const char* dir = std::string(FRONT_PATH + "/dat/ledger").c_str();
DIR* dp = opendir(dir);
std::string dir = FRONT_PATH + "/dat/ledger";
DIR* dp = opendir(dir.c_str());
if (!dp) return "";
struct dirent* entry;
@@ -500,7 +516,7 @@ int get_max_stat_data_index(const std::string& filepath) {
while (std::getline(file, line)) {
// 查找符合要求的行
if (line.find("pt61850netd_pqfe -d cfg_stat_data -s") != std::string::npos) {
if (line.find("cloud-front") != std::string::npos) {
// 找到 -s 参数位置
std::size_t pos = line.find("-s");
if (pos != std::string::npos) {
@@ -609,38 +625,39 @@ 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.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.Righttime = safe_str(item, "Righttime");
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");
m.terminal_connect = safe_str(mon, "ptType");
m.timestamp = safe_str(mon, "updateTime");
//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);
}
@@ -687,7 +704,7 @@ int parse_device_cfg_web()
// 1. 构造入参 JSON
std::string input_jstr = "{";
input_jstr += "\"ip\":\"" + FRONT_IP + "\",";
input_jstr += "\"id\":\"" + FRONT_INST + "\",";
input_jstr += "\"runFlag\":" + TERMINAL_STATUS;
input_jstr += "}";
@@ -735,17 +752,53 @@ int parse_device_cfg_web()
DIY_DEBUGLOG("process", "【DEBUG】前置的%d号进程调用获取到的台账的数量为:%d", g_front_seg_index, count_cfg);
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);
std::cout << "!!!!!!!!!!single process has ledger count more than config!!!!!!!" << std::endl;
//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();
int idx = 0;
for (const auto& kv : terminal_dev_map) {
terminal_devlist.push_back(kv.second); // kv.second 是对象,不用判断指针
terminal_dev dev = kv.second; // kv.second 是对象,不用判断指针
//dev.dev_index = static_cast<int>(idx++);
// ======= [新增] 对 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(); // [新增] 内部定值信息清空,等后续业务真实填充
dev.control_words.clear();
// ------------------------------------------------------------------------------------
// ======= [新增] 对每个监测点做必要的内部结构初始化 =======
for (auto &mon : dev.line) {
// 暂态事件容器显式清理(虽然默认构造已空,但这里确保无脏数据)
mon.qvvrevent.qvvrdata.clear(); // [新增]
mon.qvvrevent.qvvrfile.clear(); // [新增]
// 定值列表清理,等待后续配置/采集填充
mon.set_values.clear(); // [新增]
mon.dz_info_list.clear(); // [新增]
//补招列表清理
mon.recall_list.clear();
mon.recall_list_static.clear();
}
// ------------------------------------------------------------------------------------
terminal_devlist.push_back(dev);
}
// 判断监测点接线类型
@@ -1149,32 +1202,43 @@ 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) {
// 监测点日志的 key, lnk20250526
std::string full_key_m_c = "monitor." + mp_id + ".COM";
std::string full_key_m_d = "monitor." + mp_id + ".DATA";
// 监测点日志的 key, lnk20250526
// 获取装置类型的映射配置
XmlConfig c_xmlcfg;
if (xmlinfo_list.count(devtype)) {
c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
} else {
c_xmlcfg = xmlcfg;
// 0->"A", 1->"B", 2->"C", 3->"AB", 4->"BC", 5->"CA", 6/其它->"ABC"
inline std::string phase_to_text(int phase) {
switch (phase) {
case 0: return "A";
case 1: return "B";
case 2: return "C";
case 3: return "AB";
case 4: return "BC";
case 5: return "CA";
default: return "ABC"; // 包含 6 和其他任何值
}
}
if (mp_id.empty()) {
std::cout << "mp_id is null" << std::endl;
return 0;
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) {
if (dev_id.empty()) {
std::cout << "qvvr send error ,dev_id is null" << std::endl;
return 1;
}
// 构造 JSON 对象
json root;
root["monitorId"] = mp_id;
//找监测点id
std::string mpid;
get_monitor_id_by_dev_and_seq(dev_id, monitor_id, mpid);
if(mpid.empty()) {
std::cout << "qvvr send error ,monitorId is null" << std::endl;
return 1;
}
root["monitorId"] = mpid;
root["devId"] = dev_id;
root["CpuNo"] = monitor_id;
root["amplitude"] = mag;
root["duration"] = dur;
root["eventType"] = dis_kind;
@@ -1189,21 +1253,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_to_text(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 +1264,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(mpid.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(mpid.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 +1306,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");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////通用接口响应
@@ -1298,3 +1346,36 @@ void handleCommentResponse(const std::string& response) {
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////找监测点id
bool get_monitor_id_by_dev_and_seq(const std::string& terminal_id,
unsigned short logical_seq,
std::string& out_monitor_id)
{
std::lock_guard<std::mutex> lk(ledgermtx);
for (const auto& dev : terminal_devlist) {
if (dev.terminal_id != terminal_id) continue;
// 命中该装置后,仅遍历它的监测点
for (const auto& mon : dev.line) {
try {
// logical_device_seq 存在台账里是字符串,转成数值再比对
unsigned long v = std::stoul(mon.logical_device_seq);
unsigned short seq = static_cast<unsigned short>(v);
if (seq == logical_seq) {
out_monitor_id = mon.monitor_id;
return true;
}
} catch (...) {
// 非法数值(空/非数字等)直接跳过
continue;
}
}
break; // 已找到对应装置,没必要再看其它装置
}
return false;
}

View File

@@ -7,6 +7,10 @@
#include <array>
#include <map>
#include <mutex>
#include <sstream>
#include <iostream>
#include <unordered_set>
///////////////////////////////////////////////////////////////////////////////////////////
@@ -30,7 +34,7 @@ class Front;
///////////////////////////////////////////////////////////////////////////////////////////
//单条补招结构
//单条补招时间结构
class RecallInfo
{
public:
@@ -38,10 +42,117 @@ public:
long long endtime; //结束时间
};
//日志补招结构
//测点记录的补招结构
class RecallMonitor
{
public:
std::string recall_guid; // 本次补招的唯一标识 GUID
int recall_status; //补招状态 0-未补招 1-补招中 2-补招完成 3-补招失败 4-无数据
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:
std::string recall_guid; // 本次补招的唯一标识 GUID
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_filetimes; // 直下文件匹配时间点yyyyMMdd_HHmmss仅 direct_mode=true 时有效
// ★新增:按“目录名 -> 文件名列表”的映射;由“其他线程”在目录请求成功后回填
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; // 当前正在下载的文件(完整路径)
std::unordered_set<std::string> required_files; // 本次应当下载成功的文件全集
std::unordered_set<std::string> file_success; // 已下载成功的文件集合
// ★新增:一个便捷复位
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();
required_files.clear();
file_success.clear();
// ★新增:按需保留直下文件开关和目标名
if (!keep_direct) {
direct_mode = false;
target_filetimes.clear(); // ▲列表清空
}
}
};
enum class RecallStatus {
NOT_STARTED = 0, // 未补招
RUNNING = 1, // 补招中
DONE = 2, // 补招完成
FAILED = 3, // 补招失败
EMPTY = 4 // 无补招数据
};
// 本轮要下发的一条任务(每个终端最多一条)
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 +160,62 @@ public:
std::string VOLTAGE; //补招暂态事件标识 0-不补招1-补招
};
//监测点台账
class ledger_monitor
//录波文件和暂态事件
class qvvr_data
{
public:
bool is_pair;
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 update_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
};
//终端台账
class terminal_dev
class update_dev
{
public:
std::string guid; //台账更新回复用
std::string guid; // ★新增:供发送回复使
std::string terminal_id;
std::string terminal_name;
@@ -84,13 +227,82 @@ public:
std::string dev_type;
std::string dev_key;
std::string dev_series;
std::string addr_str;
std::string port;
std::string timestamp;
std::string addr_str; //装置ip
std::string port; //装置端口
std::string timestamp; //更新时间
std::string Righttime; //对时
std::string processNo;
std::string maxProcessNum;
std::string mac; // 装置MAC地址接口中从addr_str获取因为ip和mac放同一位置
std::string mac; // 装置MAC地址
std::vector<update_monitor> line;
};
////////////////////////////////////////////////////////////////////台账更新用
//监测点台账
class ledger_monitor
{
public:
std::string monitor_id; //监测点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:
//int dev_index;
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;
std::string org_name;
std::string maint_name;
std::string station_name;
std::string tmnl_factory;
std::string tmnl_status;
std::string dev_type;
std::string dev_key;
std::string dev_series;
std::string addr_str; //装置ip
std::string port; //装置端口
std::string timestamp; //更新时间
std::string Righttime; //对时
std::string processNo;
std::string maxProcessNum;
std::string mac; // 装置MAC地址接口中从addr_str获取因为ip和mac放同一位置
std::vector<ledger_monitor> line;
};
@@ -117,8 +329,17 @@ public:
std::string strTopic; //发送topic
std::string strText; //发送的json字符串
std::string mp_id; //监测点id
std::string tag; //消息tag
std::string key; // 消息key
};
//台账更新回复
struct DeviceReply {
std::string deviceId;
int code;
std::string result;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SOE 事件类
@@ -248,10 +469,10 @@ public:
#define MAX_UPDATEA_NUM 10
typedef struct trigger_update_xml_t trigger_update_xml_t;
struct trigger_update_xml_t {
std::vector<terminal_dev> new_updates;
std::vector<terminal_dev> modify_updates;
std::vector<terminal_dev> delete_updates;
std::vector<terminal_dev> work_updates;
std::vector<update_dev> new_updates;
std::vector<update_dev> modify_updates;
std::vector<update_dev> delete_updates;
std::vector<update_dev> work_updates;
trigger_update_xml_t() = default;
};
@@ -328,7 +549,6 @@ std::string get_current_time();
bool is_blank(const std::string& str);
void print_terminal(const terminal_dev& tmnl);
void printTerminalDevMap(const std::map<std::string, terminal_dev>& terminal_dev_map);
void upload_data_test();
@@ -380,8 +600,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 +617,7 @@ struct MsgObj {
// 整体
struct FullObj {
std::string mac;
int Mid;
int Did;
int Pri;
@@ -409,11 +630,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 +660,349 @@ std::string generate_json( //构造装置主动上送数据的报文
const std::vector<DataArrayItem>& dataArray //数据数组。
);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//暂态事件接口
bool append_qvvr_event(const std::string& terminal_id,
int logical_seq, // 监测点序号(如 1
int nType, // 事件类型
double fPersisstime_sec, // 持续时间(秒)
double fMagnitude_pu, // 幅值pu
uint64_t triggerTimeMs, // 触发时间(毫秒)
int phase);
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(terminal_dev* dev, const std::vector<tag_dir_info> &FileList);
//提取mac
std::string normalize_mac(const std::string& mac);
//暂态文件超时检测
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, const std::string& guid, const std::string& mac);
void send_batch_reply_to_queue(const std::string& guid,
const std::vector<DeviceReply>& replies);
//内部定值响应
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 on_device_response_minimal(int response_code,
const std::string& id,
unsigned char cid,
int device_state_int);
//找监测点id
bool get_monitor_id_by_dev_and_seq(const std::string& terminal_id,
unsigned short logical_seq,
std::string& out_monitor_id);
//处理补招的任务
void check_recall_event();
void check_recall_file();
//补招响应
void send_reply_to_kafka_recall(const std::string& guid, int 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);
//清空装置台账
size_t erase_one_terminals_by_id(const std::string& terminal_id);
//转换结构
DeviceInfo make_device_from_terminal(const terminal_dev& t);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////模板打印
// ===== 通用打印实现(模板) =====
template <typename Mon>
inline void print_monitor_common(const Mon& mon) {
auto safe = [](const std::string& s) -> const std::string& {
static const std::string NA = "N/A";
return s.empty() ? NA : s;
};
std::cout << "Monitor ID: " << safe(mon.monitor_id) << "\n";
std::cout << "Terminal ID: " << safe(mon.terminal_id) << "\n";
std::cout << "Monitor Name: " << safe(mon.monitor_name) << "\n";
std::cout << "Logical Device Sequence: " << safe(mon.logical_device_seq) << "\n";
std::cout << "Voltage Level: " << safe(mon.voltage_level) << "\n";
std::cout << "Terminal Connect: " << safe(mon.terminal_connect) << "\n";
std::cout << "Timestamp: " << safe(mon.timestamp) << "\n";
std::cout << "Status: " << safe(mon.status) << "\n";
std::cout << "CT1: " << mon.CT1 << "\n";
std::cout << "CT2: " << mon.CT2 << "\n";
std::cout << "PT1: " << mon.PT1 << "\n";
std::cout << "PT2: " << mon.PT2 << "\n";
}
template <typename Dev>
inline void print_terminal_common(const Dev& tmnl) {
auto safe = [](const std::string& s) -> const std::string& {
static const std::string NA = "N/A";
return s.empty() ? NA : s;
};
std::cout << "GUID: " << safe(tmnl.guid) << "\n";
std::cout << "Terminal ID: " << safe(tmnl.terminal_id) << "\n";
std::cout << "Terminal Code: " << safe(tmnl.terminal_name) << "\n";
std::cout << "Organization Name: "<< safe(tmnl.org_name) << "\n";
std::cout << "Maintenance Name: " << safe(tmnl.maint_name) << "\n";
std::cout << "Station Name: " << safe(tmnl.station_name) << "\n";
std::cout << "Factory Name: " << safe(tmnl.tmnl_factory) << "\n";
std::cout << "Terminal Status: " << safe(tmnl.tmnl_status) << "\n";
std::cout << "Device Type: " << safe(tmnl.dev_type) << "\n";
std::cout << "Device Key: " << safe(tmnl.dev_key) << "\n";
std::cout << "Device Series: " << safe(tmnl.dev_series) << "\n";
std::cout << "Address: " << safe(tmnl.addr_str) << "\n";
std::cout << "Port: " << safe(tmnl.port) << "\n";
std::cout << "Timestamp: " << safe(tmnl.timestamp) << "\n";
std::cout << "Righttime: " << safe(tmnl.Righttime) << "\n";
std::cout << "mac: " << safe(tmnl.mac) << "\n";
// 安全遍历最多前 10 个测点(不越界),且跳过空 monitor_id 的项
const size_t n = std::min<size_t>(tmnl.line.size(), 10);
for (size_t i = 0; i < n; ++i) {
if (tmnl.line[i].monitor_id.empty()) continue;
std::cout << " Monitor " << (i + 1) << ":\n";
print_monitor_common(tmnl.line[i]); // 模板会自动匹配 update/ledger 的 monitor
}
}
// ===== 薄包装重载(保持原有函数名不变)=====
inline void print_monitor(const update_monitor& mon) { print_monitor_common(mon); }
inline void print_monitor(const ledger_monitor& mon) { print_monitor_common(mon); }
inline void print_terminal(const update_dev& tmnl) { print_terminal_common(tmnl); }
inline void print_terminal(const terminal_dev& tmnl) { print_terminal_common(tmnl); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////小工具
// 小工具:判断 s 是否以 suffix 结尾
inline bool has_suffix(const std::string& s, const std::string& suffix) {
if (suffix.size() > s.size()) return false;
return std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
}
// 小工具:替换前缀
inline bool replace_prefix(std::string& s, const std::string& from, const std::string& to) {
if (s.rfind(from, 0) == 0) { // 以 from 为前缀
s.replace(0, from.size(), to);
return true;
}
return false;
}
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;
}
// 去首尾空格
inline std::string trim_copy(const std::string& s) {
size_t b = s.find_first_not_of(" \t\r\n");
if (b == std::string::npos) return "";
size_t e = s.find_last_not_of(" \t\r\n");
return s.substr(b, e - b + 1);
}
//清洗字符串
inline std::string sanitize(std::string s) {
// 截断第一个 NUL 及其后内容
size_t z = s.find('\0');
if (z != std::string::npos) s.erase(z);
// 去掉尾部不可打印字符(含 \r \n 等)
while (!s.empty()) {
unsigned char c = static_cast<unsigned char>(s.back());
if (c >= 32 && c != 127) break;
s.pop_back();
}
return s;
}
// 当前本地时间,格式 "YYYY-MM-DD HH:MM:SS"
inline std::string now_yyyy_mm_dd_hh_mm_ss() {
std::time_t t = std::time(nullptr);
std::tm tmv;
#if defined(_WIN32)
localtime_s(&tmv, &t); // Windows 线程安全
#else
localtime_r(&t, &tmv); // POSIX 线程安全
#endif
std::ostringstream oss;
oss << std::put_time(&tmv, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
// 简单键值提取(兼容半角/全角冒号)
inline bool parse_kv_line(const std::string& line,
const std::string& key,
std::string& out) {
std::string k1 = key + ":";
std::string k2 = key + "";
if (line.compare(0, k1.size(), k1) == 0) {
out = trim_copy(line.substr(k1.size()));
return true;
} else if (line.compare(0, k2.size(), k2) == 0) {
out = trim_copy(line.substr(k2.size()));
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////实时数据用
// === 专用锁 + 数据表(仅管实时 idx 映射) ===
extern std::mutex devidx_lock; // 新锁(不要用 ledgermtx
extern std::unordered_map<std::string,int> devIdxMap; // id -> idx一对一
// === 常用操作:全部用这把锁保护 ===
inline void devidx_set(const std::string& id, int idx) {
std::lock_guard<std::mutex> lk(devidx_lock);
devIdxMap[id] = idx; // 覆盖更新
}
inline bool devidx_get(const std::string& id, int& out_idx) {
std::lock_guard<std::mutex> lk(devidx_lock);
auto it = devIdxMap.find(id);
if (it == devIdxMap.end()) return false;
out_idx = it->second;
return true;
}
void enqueue_realtime_pq(const RealtagPqDate_float& realdata,
int nPTType,
unsigned char cid,
const std::string& mac,
const std::string& devid);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////统计数据
void enqueue_stat_pq(const std::string& max_base64Str,
const std::string& min_base64Str,
const std::string& avg_base64Str,
const std::string& cp95_base64Str,
time_t data_time,
const std::string& mac,
short cid);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern int g_front_seg_index;
extern std::string FRONT_INST;
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 // 其他错误
};
inline std::string ResponseCodeToString(int code) {
switch (code) {
case 200: return "请求成功";
case 201: return "请求被接受,开始处理";
case 202: return "请求处理中";
case 400: return "请求失败,参数错误";
case 401: return "未认证或认证错误";
case 402: return "请求被拒绝:正在处理同类命令";
case 403: return "请求被拒绝";
case 404: return "资源不存在";
case 405: return "当前忙,无法响应";
case 406: return "请求超时";
case 500: return "内部错误";
default: return "未知响应码";
}
}
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
/////////////////////////////////////////////////////////////////////////////补招文件记录
// 记录 (guid, monitorId) -> 文件完整路径
extern std::mutex g_recall_file_mtx;
extern std::map<std::pair<std::string,std::string>, std::string> g_recall_file_index;
// 初始化 / 追加 / 删除
bool init_recall_record_file(const std::string& guid,
const std::string& terminalId,
const std::string& monitorId,
const std::string& start,
const std::string& end);
bool append_recall_record_line(const std::string& guid,
const std::string& monitorId,
const std::string& msg);
bool delete_recall_record_file(const std::string& guid,
const std::string& monitorId);
bool get_recall_record_fields_by_guid_monitor(const std::string& guid,
const std::string& monitorId,
std::string& outGuid,
std::string& terminalId,
std::string& outMonitorId,
std::string& startTime,
std::string& endTime,
std::string& msg);
bool SendFileWebAuto(const std::string& id,
const std::string& local_path,
const std::string& remote_path,
std::string& out_filename);
void cleanup_old_unpaired_qvvr_events();

View File

@@ -24,12 +24,11 @@
#include "log4cplus/fileappender.h"
#include "log4cplus/layout.h"
#include "log4cplus/ndc.h"
#include "log4cplus/log4.h"
#include "log4cplus/spi/loggingevent.h"
#include "rocketmq.h"
#include "interface.h"
#include "log4cplus/log4.h"
#include "log4.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//log4命名空间
@@ -50,19 +49,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,15 +141,19 @@ 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)
<< "\",\"nodeId\":\"" << FRONT_INST
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
<< "\",\"level\":\"" << level_str
<< "\",\"time\":\"" << now_yyyy_mm_dd_hh_mm_ss()
<< "\",\"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();
@@ -161,6 +161,8 @@ protected:
queue_data_t connect_info;
connect_info.strTopic = G_LOG_TOPIC;
connect_info.strText = jsonString;
connect_info.tag = G_LOG_TAG;
connect_info.key = G_LOG_KEY;
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
queue_data_list.push_back(connect_info);
@@ -307,12 +309,10 @@ void init_loggers_bydevid(const std::string& dev_id)
std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str;
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + dev_id + ".COM";
std::string device_key_d = std::string("terminal.") + dev_id + ".DATA";
std::string device_key = std::string("terminal.") + dev_id;
// 添加判断:终端日志 logger 是否已存在
if (logger_map.find(device_key_c) == logger_map.end() &&
logger_map.find(device_key_d) == logger_map.end()) {
if (logger_map.find(device_key) == logger_map.end()) {
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + dev_id + ".log";
@@ -321,27 +321,23 @@ void init_loggers_bydevid(const std::string& dev_id)
SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, dev_id, device_appender);
Logger device_logger_d = init_logger(device_key_d, device_dir, dev_id, device_appender);
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender);
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
//DIY_WARNLOG(dev_id.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
}
// 初始化监测点日志monitor.<mp_id>.COM / .DATA
for (size_t j = 0; j < term.line.size(); ++j) {
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";
std::ostringstream mon_key, mon_path, mon_name;
mon_key << "monitor." << monitor.monitor_id;
mon_path << device_dir << "/monitor" << j;
mon_name << monitor.monitor_id;
// 判断监测点 logger 是否已存在
if (logger_map.find(mon_key_c.str()) == logger_map.end() &&
logger_map.find(mon_key_d.str()) == logger_map.end()) {
if (logger_map.find(mon_key.str()) == logger_map.end()) {
// 所有监测点日志com 和 data写到同一个 monitor 日志文件中
std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log";
@@ -350,12 +346,10 @@ void init_loggers_bydevid(const std::string& dev_id)
SharedAppenderPtr monitor_appender(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key.str()] = TypedLogger(mon_logger, 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(monitor.monitor_id.c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
}
@@ -382,8 +376,7 @@ void init_loggers()
std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str;
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + term.terminal_id + ".COM";
std::string device_key_d = std::string("terminal.") + term.terminal_id + ".DATA";
std::string device_key = std::string("terminal.") + term.terminal_id;
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + term.terminal_id + ".log";
@@ -392,22 +385,19 @@ void init_loggers()
SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, term.terminal_id, device_appender);
Logger device_logger_d = init_logger(device_key_d, device_dir, term.terminal_id, device_appender);
Logger device_logger = init_logger(device_key, device_dir, term.terminal_id, device_appender);
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
//DIY_WARNLOG(term.terminal_id.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
// 初始化监测点日志
for (size_t i = 0; i < term.line.size(); ++i) {
const ledger_monitor& monitor = term.line[i];
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";
std::ostringstream mon_key, mon_path, mon_name;
mon_key << "monitor." << monitor.monitor_id;
mon_path << device_dir << "/monitor" << i; // 用monitor+序号作为目录
mon_name << monitor.monitor_id;
@@ -418,14 +408,12 @@ void init_loggers()
SharedAppenderPtr monitor_appender(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
logger_map[mon_key.str()] = TypedLogger(mon_logger, 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.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕",
//monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
}
@@ -439,17 +427,11 @@ void remove_loggers_by_terminal_id(const std::string& terminal_id) {
if (term.terminal_id != terminal_id) continue;
// 删除终端日志 logger
std::string com_key = "terminal." + terminal_id + ".COM";
std::string data_key = "terminal." + terminal_id + ".DATA";
std::string terminal_key = "terminal." + terminal_id;
if (logger_map.count(com_key)) {
logger_map[com_key].logger.removeAllAppenders();
logger_map.erase(com_key);
}
if (logger_map.count(data_key)) {
logger_map[data_key].logger.removeAllAppenders();
logger_map.erase(data_key);
if (logger_map.count(terminal_key)) {
logger_map[terminal_key].logger.removeAllAppenders();
logger_map.erase(terminal_key);
}
// 删除监测点日志 logger
@@ -457,18 +439,13 @@ void remove_loggers_by_terminal_id(const std::string& terminal_id) {
const ledger_monitor& monitor = term.line[i];
if (!monitor.monitor_id.empty()) {
std::string mon_prefix = "monitor." + monitor.monitor_id;
std::string mon_com_key = mon_prefix + ".COM";
std::string mon_data_key = mon_prefix + ".DATA";
std::string mon_key = mon_prefix;
if (logger_map.count(mon_com_key)) {
logger_map[mon_com_key].logger.removeAllAppenders();
logger_map.erase(mon_com_key);
if (logger_map.count(mon_key)) {
logger_map[mon_key].logger.removeAllAppenders();
logger_map.erase(mon_key);
}
if (logger_map.count(mon_data_key)) {
logger_map[mon_data_key].logger.removeAllAppenders();
logger_map.erase(mon_data_key);
}
}
}
@@ -504,22 +481,28 @@ extern "C" {
void log_warn (const char* key, const char* msg) { log4_log_with_level(key, msg, 2); }
void log_error(const char* key, const char* msg) { log4_log_with_level(key, msg, 3); }
void send_reply_to_queue_c(const char* guid, const char* step, const char* result) {
send_reply_to_queue(std::string(guid), std::string(step), std::string(result));
}
//标准化日志接口
// #define LOGMSG_WITH_TS // 需要时间时再打开
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) {
if (!buf || buf_size == 0) return;
buf[0] = '\0';
if (!fmt) return;
va_list args;
va_start(args, fmt);
#ifdef LOGMSG_WITH_TS
// 写入时间
time_t now = time(NULL);
struct tm tm_info;
localtime_r(&now, &tm_info);
strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S ", &tm_info); // 时间+空格
// 处理可变参数并写入剩余内容
va_list args;
va_start(args, fmt);
vsnprintf(buf + strlen(buf), buf_size - strlen(buf), fmt, args);
size_t n = strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S ", &tm_info);
if (n < buf_size) {
vsnprintf(buf + n, buf_size - n, fmt, args);
}
#else
vsnprintf(buf, buf_size, fmt, args);
#endif
va_end(args);
}

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>
@@ -51,7 +61,7 @@ struct DebugSwitch {
extern std::map<std::string, TypedLogger> logger_map;
extern DebugSwitch g_debug_switch;
extern void send_reply_to_queue(const std::string& guid, const std::string& step, const std::string& result);
extern void send_reply_to_queue(const std::string& guid, const int code, const std::string& result);
//std::string get_front_type_from_subdir();
@@ -84,23 +94,95 @@ void log_debug(const char* key, const char* msg);
void log_info(const char* key, const char* msg);
void log_warn(const char* key, const char* msg);
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, ...);
//宏定义
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); \
// ====================== ★新增:线程局部变量透传 code ======================
// 说明:使用编译器的 TLS__thread保存当前日志的 code 值。
// 在每次打日志前写入打完后恢复Appender 读取该值写入 JSON。
// ====================== ★新增结束 ======================
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, /* 空间告警 */
LOG_CODE_DEV_ALARM = 800 /* 设备告警 */
} LogCode;
// ====================== 日志宏区域 ======================
// ★新增:带 code 的实现C/C++ 通用,使用 TLS 保存/恢复)
#define DIY_LOG_CODE(LEVEL_FUNC, KEY, LEVEL_INT, CODE_INT, ...) \
do { \
/* 备份并设置本次日志 code */ \
int __old_code__ = g_log_code_tls; \
g_log_code_tls = static_cast<int>(CODE_INT); \
\
/* 组装消息 */ \
char __msg_buf__[256]; \
format_log_msg(__msg_buf__, sizeof(__msg_buf__), __VA_ARGS__); \
\
/* 将 KEY 规范化为字符串(兼容 const char* / std::string 等) */ \
std::ostringstream __oss_key__; \
__oss_key__ << (KEY); \
std::string __key_raw__ = __oss_key__.str(); \
\
/* 根据 LEVEL_INT 构造最终 key */ \
char __key_buf__[256]; \
switch (static_cast<int>(LEVEL_INT)) { \
case 0: \
std::snprintf(__key_buf__, sizeof(__key_buf__), "process"); \
break; \
case 1: \
std::snprintf(__key_buf__, sizeof(__key_buf__), \
"terminal.%s", __key_raw__.c_str()); \
break; \
case 2: \
std::snprintf(__key_buf__, sizeof(__key_buf__), \
"monitor.%s", __key_raw__.c_str()); \
break; \
default: \
std::snprintf(__key_buf__, sizeof(__key_buf__), "%s", \
__key_raw__.c_str()); \
break; \
} \
\
/* 输出日志 */ \
LEVEL_FUNC(__key_buf__, __msg_buf__); \
\
/* 恢复旧值 */ \
g_log_code_tls = __old_code__; \
} 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=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
#ifdef __cplusplus
}

View File

@@ -1,111 +0,0 @@
#ifndef LOG4_H
#define LOG4_H
#ifdef __cplusplus
#include <string>
#include <map>
//防止#include <log4cplus/logger.h>里的冲突
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
//防止#include <log4cplus/logger.h>里的冲突
#include "logger.h"
#include <set>
#include "loggingmacros.h"
#include "appender.h"
#define LOGTYPE_COM 1
#define LOGTYPE_DATA 2
struct TypedLogger {
log4cplus::Logger logger;
int logtype;
TypedLogger();
TypedLogger(const log4cplus::Logger& l, int t);
};
struct DebugSwitch {
bool debug_open;
std::set<std::string> targets;
int min_level;
std::map<int, bool> type_enable;
DebugSwitch();
void open();
void close();
void set_target(const std::string& name);
void set_level(int level);
void enable_type(int type);
void disable_type(int type);
bool match(const std::string& logger_name, int level, int logtype);
};
extern std::map<std::string, TypedLogger> logger_map;
extern DebugSwitch g_debug_switch;
extern void send_reply_to_queue(const std::string& guid, const std::string& step, const std::string& result);
//std::string get_front_type_from_subdir();
// 不带 Appender 的版本
log4cplus::Logger init_logger(const std::string& full_name,
const std::string& file_dir,
const std::string& base_file);
// 带 Appender 的版本
log4cplus::Logger init_logger(const std::string& full_name,
const std::string& file_dir,
const std::string& base_file,
log4cplus::SharedAppenderPtr fileAppender);
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str);
void update_log_entries_countdown();
extern "C" {
#endif
void remove_loggers_by_terminal_id(const std::string& terminal_id_cstr);
void init_logger_process();
void init_loggers();
void init_loggers_bydevid(const std::string& dev_id);
void log_debug(const char* key, const char* msg);
void log_info(const char* key, const char* msg);
void log_warn(const char* key, const char* msg);
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, ...);
//宏定义
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
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__)
#ifdef __cplusplus
}
#endif
#endif // LOG4_H

View File

@@ -29,7 +29,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "interface.h" //用于访问接口
#include "log4cplus/log4.h" //用于日志
#include "log4.h" //用于日志
#include "curl/curl.h" //用于访问接口
#include "nlohmann/json.hpp" //用于构造json
#include "worker.h" //shell接口
@@ -37,7 +37,27 @@
#include "rocketmq/MQClientException.h"
#include "front.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////命名空间
//lnk 20251211
namespace {
std::mutex g_streamMutex;
void safe_out_str(const std::string& s) {
std::lock_guard<std::mutex> lk(g_streamMutex);
std::cout << s << std::flush;
}
void safe_out_line(const std::string& s) {
std::lock_guard<std::mutex> lk(g_streamMutex);
std::cout << s << std::endl;
}
void safe_err_line(const std::string& s) {
std::lock_guard<std::mutex> lk(g_streamMutex);
std::cerr << s << std::endl;
}
}
using json = nlohmann::json;
@@ -49,7 +69,7 @@ std::string FRONT_PATH;
//初始化标志
int INITFLAG = 0;
std::atomic<int> INITFLAG{0};
//前置标置
std::string subdir = "cloudfrontproc"; //子目录
@@ -85,6 +105,18 @@ std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// 把“今天”做成年月日整数YYYYMMDD用于“每天只清理一次”的判定
static inline int local_ymd_today() {
std::time_t now = std::time(nullptr);
std::tm local_tm{};
#if defined(_WIN32) || defined(_WIN64)
localtime_s(&local_tm, &now);
#else
local_tm = *std::localtime(&now);
#endif
return (local_tm.tm_year + 1900) * 10000 + (local_tm.tm_mon + 1) * 100 + local_tm.tm_mday;
}
//处理参数
bool parse_param(int argc, char* argv[]) {
for (int i = 1; i < argc; ++i) {
@@ -138,35 +170,6 @@ bool parse_param(int argc, char* argv[]) {
return true;
}
//获取前置类型
/*void init_global_function_enable() {
if (subdir == "cfg_stat_data") { // 历史稳态
g_node_id = STAT_DATA_BASE_NODE_ID;
auto_register_report_enabled = 1;
} else if (subdir == "cfg_3s_data") { // 实时
g_node_id = THREE_SECS_DATA_BASE_NODE_ID;
three_secs_enabled = 1;
} else if (subdir == "cfg_soe_comtrade") { // 告警、录波、暂态
g_node_id = SOE_COMTRADE_BASE_NODE_ID;
} else if (subdir == "cfg_recallhis_data") { // 补招
g_node_id = RECALL_HIS_DATA_BASE_NODE_ID;
}
}*/
//获取功能名称
/*std::string get_front_msg_from_subdir() {
if (subdir.find("cfg_3s_data") != std::string::npos)
return "实时数据进程";
else if (subdir.find("cfg_soe_comtrade") != std::string::npos)
return "暂态和告警进程";
else if (subdir.find("cfg_recallhis_data") != std::string::npos)
return "稳态补招进程";
else if (subdir.find("cfg_stat_data") != std::string::npos)
return "稳态统计进程";
else
return "unknown";
}*/
//获取前置路径
std::string get_parent_directory() {
// 获取当前工作目录
@@ -215,7 +218,7 @@ std::string get_parent_directory() {
init_loggers();
//读取模型,下载模板文件
parse_model_cfg_web();
//parse_model_cfg_web();
//解析模板文件
//Set_xml_nodeinfo();
@@ -246,7 +249,7 @@ std::string get_parent_directory() {
}
// ============ 关闭所有运行中的线程============
void Front::FormClosing() {
/*void Front::FormClosing() {
//确保testshell关闭
m_worker.stopServer();
@@ -286,11 +289,19 @@ std::string get_parent_directory() {
m_MQConsumerThread.join();
}
}*/
void Front::FormClosing() {
m_worker.stopServer();
StopFrontThread();
StopTimerThread();
StopMQProducerThread();
StopMQConsumerThread();
}
//============ 线程函数 ============
void Front::StartFrontThread() {
/*void Front::StartFrontThread() {
m_bIsFrontThreadCancle = false;
m_FrontThread = std::thread(&Front::FrontThread, this);
}
@@ -308,23 +319,155 @@ std::string get_parent_directory() {
void Front::StartTimerThread() {
m_IsTimerCancel = false;
m_TimerThread = std::thread(&Front::OnTimerThread, this);
}
} */
void Front::StartFrontThread() {
bool expected = false;
if (!m_frontRunning.compare_exchange_strong(expected, true)) {
std::cout << "[FrontThread] already running, skip\n";
return;
}
if (m_FrontThread.joinable()) m_FrontThread.join();
m_bIsFrontThreadCancle = false;
m_FrontThread = std::thread([this]{
try {
this->FrontThread();
} catch (const std::exception& e) {
std::cerr << "[FrontThread] exception: " << e.what() << "\n";
} catch (...) {
std::cerr << "[FrontThread] unknown exception\n";
}
m_frontRunning = false; // 线程真正退出后复位
});
}
void Front::StartMQConsumerThread() {
bool expected = false;
if (!m_consumerRunning.compare_exchange_strong(expected, true)) {
std::cout << "[MQConsumer] already running, skip\n";
return;
}
if (m_MQConsumerThread.joinable()) m_MQConsumerThread.join();
m_IsMQConsumerCancel = false;
m_MQConsumerThread = std::thread([this]{
try {
this->mqconsumerThread();
} catch (const std::exception& e) {
std::cerr << "[mqconsumerThread] exception: " << e.what() << "\n";
} catch (...) {
std::cerr << "[mqconsumerThread] unknown exception\n";
}
m_consumerRunning = false;
});
}
void Front::StartMQProducerThread() {
bool expected = false;
if (!m_producerRunning.compare_exchange_strong(expected, true)) {
std::cout << "[MQProducer] already running, skip\n";
return;
}
if (m_MQProducerThread.joinable()) m_MQProducerThread.join();
m_IsMQProducerCancel = false;
m_MQProducerThread = std::thread([this]{
try {
this->mqproducerThread();
} catch (const std::exception& e) {
std::cerr << "[mqproducerThread] exception: " << e.what() << "\n";
} catch (...) {
std::cerr << "[mqproducerThread] unknown exception\n";
}
m_producerRunning = false;
});
}
void Front::StartTimerThread() {
bool expected = false;
if (!m_timerRunning.compare_exchange_strong(expected, true)) {
std::cout << "[Timer] already running, skip StartTimerThread\n";
return; // 已有定时线程在跑,直接跳过
}
// 若有旧线程尚未 join先回收
if (m_TimerThread.joinable()) {
m_TimerThread.join();
}
m_IsTimerCancel.store(false, std::memory_order_relaxed);
m_TimerThread = std::thread([this]{
try {
this->OnTimerThread();
} catch (const std::exception& e) {
std::cerr << "[Timer] exception: " << e.what() << "\n";
} catch (...) {
std::cerr << "[Timer] unknown exception\n";
}
m_timerRunning.store(false); // 线程真正退出后复位
});
}
void Front::StopFrontThread() {
if (!m_frontRunning.load()) return;
m_bIsFrontThreadCancle = true;
if (m_FrontThread.joinable()) m_FrontThread.join();
m_frontRunning = false;
}
void Front::StopMQConsumerThread() {
if (!m_consumerRunning.load()) return;
m_IsMQConsumerCancel = true; // 你的线程函数可能不轮询此标志,但先置上
// 关闭 MQ 对象(避免内部阻塞线程仍在)
if (m_mqConsumer) {
try { m_mqConsumer->shutdown(); } catch (...) {}
m_mqConsumer.reset();
}
m_listener.reset();
if (m_MQConsumerThread.joinable()) m_MQConsumerThread.join();
m_consumerRunning = false;
}
void Front::StopMQProducerThread() {
if (!m_producerRunning.load()) return;
m_IsMQProducerCancel = true;
if (m_MQProducerThread.joinable()) m_MQProducerThread.join();
m_producerRunning = false;
// 如需销毁/关闭 producer对应你的初始化方式
// if (m_producer) { ShutdownProducer(m_producer); m_producer = nullptr; }
}
void Front::StopTimerThread() {
if (!m_timerRunning.load()) return; // 没跑就不处理
m_IsTimerCancel.store(true);
if (m_TimerThread.joinable()) {
m_TimerThread.join(); // 等它退出
}
m_timerRunning.store(false);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////主功能线程
void Front::FrontThread() {
std::cout << "FrontThread::run() is called ...... \n";
safe_out_line("FrontThread::run() is called ...... \n");
try {
while (!m_bIsFrontThreadCancle) {
check_3s_config(); // 实时数据触发
//create_recall_xml(); // 生成待补招xml文件
check_ledger_update(); // 触发台账更新
check_recall_event(); // 处理补招事件从list中读取然后直接调用接口,每一条可能都不同测点,每个测点自己做好记录
check_recall_file(); //处理补招文件-稳态和暂态
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} catch (const std::exception& e) {
std::cerr << "[FrontThread] Caught exception: " << e.what() << std::endl;
safe_err_line(std::string("[FrontThread] Caught exception: ") + e.what());
} catch (...) {
std::cerr << "[FrontThread] Caught unknown exception" << std::endl;
safe_err_line("[FrontThread] Caught unknown exception");
}
// 设置重启标志
@@ -333,7 +476,7 @@ void Front::FrontThread() {
m_needRestartFrontThread = true;
}
std::cout << "[FrontThread] exited, will be restarted by monitor\n";
safe_out_line("[FrontThread] exited, will be restarted by monitor\n");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////定时任务
@@ -342,37 +485,65 @@ void Front::OnTimerThread()
{
try {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "OnTimerThread::run() is called ...... \n";
safe_out_line("OnTimerThread::run() is called ...... \n");
int counter = 0;
int hbCounter = 0; // 心跳计数
int backupCounter = 0; // 备份计数(分钟用)
send_heartbeat_to_queue("1");
//记录“上次做日清理”的日期YYYYMMDD确保每天只做一次
static int s_lastCleanupYMD = -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;
}
// 按天清理 —— 发现“日期变更”则执行一次清理
{
const int todayYMD = local_ymd_today(); // YYYYMMDD本地时区
if (todayYMD != s_lastCleanupYMD) {
// 说明进入了新的一天:执行清理(删除前日及更早的未配对事件)
safe_out_line("[OnTimerThread] daily cleanup start, today=" + std::to_string(todayYMD) + "\n");
cleanup_old_unpaired_qvvr_events(); // 调用清理内存的暂态事件
s_lastCleanupYMD = todayYMD;
safe_out_line("[OnTimerThread] daily cleanup done\n");
}
}
hbCounter++;
backupCounter++;
g_ontime_blocked_times = 0;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
} catch (const std::exception& e) {
std::cerr << "[OnTimerThread] Caught exception: " << e.what() << std::endl;
safe_err_line(std::string("[OnTimerThread] Caught exception: ") + e.what());
} catch (...) {
std::cerr << "[OnTimerThread] Caught unknown exception" << std::endl;
safe_err_line("[OnTimerThread] Caught unknown exception");
}
// 设置重启标志
{
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartTimerThread = true;
}
std::cout << "[OnTimerThread] exited, will be restarted by monitor\n";
safe_out_line("[OnTimerThread] exited, will be restarted by monitor\n");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////消费者线程
@@ -385,16 +556,23 @@ void Front::mqconsumerThread()
std::vector<rocketmq::Subscription> subscriptions;
//if (g_node_id == THREE_SECS_DATA_BASE_NODE_ID) {
subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_RT, G_MQCONSUMER_TAG_RT, myMessageCallbackrtdata);
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_RT, FRONT_INST, myMessageCallbackrtdata);
//}
subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_UD, G_MQCONSUMER_TAG_UD, myMessageCallbackupdate);
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_UD, FRONT_INST, myMessageCallbackupdate);
//if (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID) {
subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_RC, G_MQCONSUMER_TAG_RC, myMessageCallbackrecall);
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_RC, FRONT_INST, myMessageCallbackrecall);
//}
subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_SET, G_MQCONSUMER_TAG_SET, myMessageCallbackset);
subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_LOG, G_MQCONSUMER_TAG_LOG, myMessageCallbacklog);
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_SET, FRONT_INST, myMessageCallbackset);
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_LOG, FRONT_INST, myMessageCallbacklog);
m_mqConsumer = make_unique<rocketmq::DefaultMQPushConsumer>(consumerGroup);
// ✅ 必须在 start() 之前设置
//m_mqConsumer->setLogPath("/data/logs/rocketmq"); // 目录
m_mqConsumer->setLogLevel(rocketmq::eLOG_LEVEL_ERROR); // 级别error
m_mqConsumer->setLogFileSizeAndNum(5, 50); // 5 个文件,每个 50MB
m_mqConsumer->setNamesrvAddr(nameServer);
m_mqConsumer->setSessionCredentials(G_MQCONSUMER_ACCESSKEY, G_MQCONSUMER_SECRETKEY, G_MQCONSUMER_CHANNEL);
m_mqConsumer->setInstanceName("inst_" + std::to_string(sGetMsTime()));
@@ -405,37 +583,37 @@ void Front::mqconsumerThread()
std::string key = sub.topic + ":" + sub.tag;
callbackMap.emplace(key, sub.callback);
m_mqConsumer->subscribe(sub.topic, sub.tag);
std::cout << "[mqconsumerThread] 已订阅 Topic=\"" << sub.topic << "\", Tag=\"" << sub.tag << "\"" << std::endl;
safe_out_line("[mqconsumerThread] 已订阅 Topic=\"" + sub.topic + "\", Tag=\"" + sub.tag + "\"\n");
}
m_listener = std::make_shared<rocketmq::SubscriberListener>(callbackMap);
m_mqConsumer->registerMessageListener(m_listener.get());
m_mqConsumer->start();
std::cout << "[mqconsumerThread] Consumer 已启动,等待消息..." << std::endl;
safe_out_line("[mqconsumerThread] Consumer 已启动,等待消息...\n");
// ✳️ 保持线程不主动退出,由 RocketMQ 内部驱动执行回调
// 如果 RocketMQ 内部机制失败或意外退出线程,就走 catch
}
catch (const rocketmq::MQClientException& e) {
std::cerr << "[mqconsumerThread] MQClientException: " << e.what() << std::endl;
safe_err_line(std::string("[mqconsumerThread] MQClientException: ") + e.what());
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartConsumerThread = true;
return;
} catch (const std::exception& e) {
std::cerr << "[mqconsumerThread] std::exception: " << e.what() << std::endl;
safe_err_line(std::string("[mqconsumerThread] std::exception: ") + e.what());
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartConsumerThread = true;
return;
} catch (...) {
std::cerr << "[mqconsumerThread] Unknown exception" << std::endl;
safe_err_line("[mqconsumerThread] Unknown exception");
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartConsumerThread = true;
return;
}
// 程序运行中,消费者会通过回调处理消息,线程保持存活即可
std::cout << "[mqconsumerThread] Consumer 线程正在运行,等待消息到达..." << std::endl;
safe_out_line("[mqconsumerThread] Consumer 线程正在运行,等待消息到达...");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////生产者线程
@@ -445,7 +623,7 @@ void Front::mqproducerThread()
try {
// 1. 初始化生产者
InitializeProducer(m_producer);
std::cout << "\n[mqproducerThread] is running ...... \n\n";
safe_out_line("\n[mqproducerThread] is running ...... \n\n");
uint32_t count = 0;
@@ -464,49 +642,60 @@ void Front::mqproducerThread()
}
if (data_gotten) {
auto now = std::chrono::system_clock::now();
auto ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
auto time_t_part = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
localtime_r(&time_t_part, &tm_buf);
char timeStr[32];
std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf);
{
auto now = std::chrono::system_clock::now();
auto ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
auto time_t_part = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
localtime_r(&time_t_part, &tm_buf);
char timeStr[32];
std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf);
std::cout << "BEGIN my_queue_send no." << count
<< " >>>> " << timeStr
<< "." << std::setw(3) << std::setfill('0') << ms_part.count()
<< std::endl;
std::ostringstream oss;
oss << "BEGIN my_queue_send no." << count
<< " >>>> " << timeStr
<< "." << std::setw(3) << std::setfill('0') << ms_part.count();
// 线程安全输出
safe_out_line(oss.str());
}
// 调用实际发送
my_rocketmq_send(data, m_producer);
now = std::chrono::system_clock::now();
ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
time_t_part = std::chrono::system_clock::to_time_t(now);
localtime_r(&time_t_part, &tm_buf);
std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf);
{
auto now = std::chrono::system_clock::now();
auto ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
auto time_t_part = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
localtime_r(&time_t_part, &tm_buf);
char timeStr[32];
std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf);
std::cout << "END my_queue_send no." << count++
<< " >>>> " << timeStr
<< "." << std::setw(3) << std::setfill('0') << ms_part.count()
<< "\n\n";
std::ostringstream oss;
oss << "END my_queue_send no." << count
<< " <<<< " << timeStr
<< "." << std::setw(3) << std::setfill('0') << ms_part.count();
safe_out_line(oss.str());
}
}
g_mqproducer_blocked_times = 0;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::cout << "[mqproducerThread] 正常退出\n";
safe_out_line("[mqproducerThread] 正常退出\n");
}
catch (const std::exception& e) {
std::cerr << "[mqproducerThread] std::exception: " << e.what() << std::endl;
safe_err_line(std::string("[mqproducerThread] std::exception: ") + e.what());
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartProducerThread = true;
}
catch (...) {
std::cerr << "[mqproducerThread] unknown exception\n";
safe_err_line("[mqproducerThread] unknown exception\n");
std::lock_guard<std::mutex> lock(m_threadCheckMutex);
m_needRestartProducerThread = true;
}
@@ -518,49 +707,71 @@ 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);
//不再需要入参20251208
/*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;
}
}*/
(void)arg;
const int index = 0;
// 更新线程状态为运行中
pthread_mutex_lock(&thread_info[index].lock);
printf("cloudfrontthread %d started\n", index);
safe_out_line(std::string("cloudfrontthread") + std::to_string(index) + " started\n");
thread_info[index].state = THREAD_RUNNING;
pthread_mutex_unlock(&thread_info[index].lock);
///////////////////////////////////////
// 解析命令行参数
/*// 解析命令行参数
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();
std::cout << "FRONT_PATH:" << FRONT_PATH << std::endl;
safe_out_line("FRONT_PATH:" + FRONT_PATH + "\n");
//声明前置
std::unique_ptr<Front> FrontProcess;
FrontProcess = make_unique<Front>();
std::cout << "[Main] Program running in background.\n";
safe_out_line("[Main] Program running in background.\n");
// 5) 主线程保持后台运行
while(running) {
{
std::lock_guard<std::mutex> lock(FrontProcess->m_threadCheckMutex);
if (FrontProcess->m_needRestartFrontThread) {
/*if (FrontProcess->m_needRestartFrontThread) {
std::cout << "[Monitor] Restarting FrontThread..." << std::endl;
FrontProcess->StartFrontThread();
FrontProcess->m_needRestartFrontThread = false;
@@ -582,12 +793,46 @@ void* cloudfrontthread(void* arg) {
std::cout << "[Monitor] Restarting TimerThread..." << std::endl;
FrontProcess->StartTimerThread();
FrontProcess->m_needRestartTimerThread = false;
}*/
if (FrontProcess->m_needRestartFrontThread) {
safe_out_line("[Monitor] Restarting FrontThread...\n");
FrontProcess->StopFrontThread();
FrontProcess->StartFrontThread();
FrontProcess->m_needRestartFrontThread = false;
}
if (FrontProcess->m_needRestartConsumerThread) {
safe_out_line("[Monitor] Restarting MQConsumerThread...\n");
FrontProcess->StopMQConsumerThread();
FrontProcess->StartMQConsumerThread();
FrontProcess->m_needRestartConsumerThread = false;
}
if (FrontProcess->m_needRestartProducerThread) {
safe_out_line("[Monitor] Restarting MQProducerThread...\n");
FrontProcess->StopMQProducerThread();
FrontProcess->StartMQProducerThread();
FrontProcess->m_needRestartProducerThread = false;
}
if (FrontProcess->m_needRestartTimerThread) {
safe_out_line("[Monitor] Restarting TimerThread...\n");
FrontProcess->StopTimerThread(); // 先停
FrontProcess->StartTimerThread(); // 再启
FrontProcess->m_needRestartTimerThread = false;
}
}
std::this_thread::sleep_for(std::chrono::seconds(60));//每分钟检测一次
}
// 退出前标记为 STOPPED方便监控线程判断并重启
pthread_mutex_lock(&thread_info[index].lock);
thread_info[index].state = THREAD_STOPPED;
safe_out_line(std::string("cloudfrontthread ") + std::to_string(index) + " stopped\n");
pthread_mutex_unlock(&thread_info[index].lock);
return nullptr;
}

File diff suppressed because it is too large Load Diff

View File

@@ -60,6 +60,10 @@ extern std::string TOPIC_RTDATA;
extern std::string G_ROCKETMQ_TAG;
extern std::string G_ROCKETMQ_KEY;
//添加rt的tagkey
extern std::string G_RT_TAG;
extern std::string G_RT_KEY;
extern std::string G_ROCKETMQ_CONSUMER;
extern std::string G_MQCONSUMER_IPPORT;
extern std::string G_MQCONSUMER_ACCESSKEY;
@@ -86,6 +90,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 +344,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>
@@ -35,7 +35,7 @@
#include "worker.h"
#include "interface.h"
#include "rocketmq.h"
#include "log4cplus/log4.h"
#include "log4.h"
#include "front.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,12 +49,13 @@ extern std::list<std::string> errorList, warnList, normalList;
extern std::mutex errorListMutex, warnListMutex, normalListMutex;
extern int IED_COUNT;
extern int INITFLAG;
extern std::atomic<int> INITFLAG;
extern int g_front_seg_index;
extern std::string subdir;
extern int G_TEST_NUM;
extern int G_TEST_TYPE;
extern int LEDGER_MAX_ITEMS;
extern bool errorOutputEnabled;
extern bool warnOutputEnabled;
@@ -259,6 +260,11 @@ extern bool normalOutputEnabled;
G_TEST_TYPE = type;
}
void Worker::setMaxItems(int items) {
std::lock_guard<std::mutex> locker(testMutex);
LEDGER_MAX_ITEMS = items;
}
// 日志控制
void Worker::setTestlog(bool flag) {
redirectErrorOutput(flag);
@@ -294,6 +300,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"
@@ -322,9 +329,17 @@ extern bool normalOutputEnabled;
int flag = std::atoi(cmd.substr(4).c_str());
setTestlog(flag);
sendStr(clientFD, "\r\x1B[KLOG updated\r\n");
} else if (cmd == "rc") {
}else if (cmd.find("MAX=") == 0) {
int flag = std::atoi(cmd.substr(4).c_str());
setMaxItems(flag);
sendStr(clientFD, "\r\x1B[KMAX_ITEMS updated\r\n");
}
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 +420,338 @@ extern bool normalOutputEnabled;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////测试shell用的函数
void Worker::printLedgerinshell(const terminal_dev& dev, int fd) {
// —— 显示控制:最多打印的元素数量(防止过长)——
const size_t MAX_ITEMS = static_cast<size_t>(LEDGER_MAX_ITEMS); // 非 constexpr
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|-- mac: " << dev.mac << "\n";
os << "\r\x1B[K|-- guid : " << dev.guid << "\n";
os << "\r\x1B[K|-- busytype : " << dev.busytype << "\n";
os << "\r\x1B[K|-- isbusy : " << dev.isbusy << "\n";
os << "\r\x1B[K|-- busytimecount : " << dev.busytimecount << "\n";
//os << "\r\x1B[K|-- dev_index : " << dev.dev_index << "\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|-- Righttime : " << dev.Righttime << "\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";
}
}
// ========================= ★新增:补招打印 =========================
// ★新增:小工具—把状态/阶段枚举转成可读字符串
auto recallStatusStr = [](int st) -> const char* {
switch (st) {
case 0: return "NOT_STARTED(0)";
case 1: return "RUNNING(1)";
case 2: return "DONE(2)";
case 3: return "FAILED(3)";
case 4: return "EMPTY(4)";
default: return "UNKNOWN";
}
};
auto phaseStr = [](RecallPhase p) -> const char* {
switch (p) {
case RecallPhase::IDLE: return "IDLE";
case RecallPhase::LISTING: return "LISTING";
case RecallPhase::DOWNLOADING: return "DOWNLOADING";
}
return "UNKNOWN";
};
auto resultStr = [](ActionResult r) -> const char* {
switch (r) {
case ActionResult::PENDING: return "PENDING";
case ActionResult::FAIL: return "FAIL";
case ActionResult::OK: return "OK";
}
return "UNKNOWN";
};
// --- ★新增事件补招RecallMonitor ---
os << "\r\x1B[K |-- Recall(Event) (" << ld.recall_list.size() << "):\n";
{
size_t idx = 0;
for (const auto& r : ld.recall_list) {
if (idx++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- [" << (idx-1) << "] "
<< "status=" << recallStatusStr(r.recall_status)
<< ", StartTime=" << r.StartTime
<< ", EndTime=" << r.EndTime
<< ", STEADY=" << r.STEADY
<< ", VOLTAGE=" << r.VOLTAGE
<< "\n";
}
if (ld.recall_list.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (ld.recall_list.size() - MAX_ITEMS) << " more)\n";
}
}
// --- ★新增稳态补招RecallFile+ 状态机信息 ---
os << "\r\x1B[K |-- Recall(Static Files) (" << ld.recall_list_static.size() << "):\n";
{
size_t idx = 0;
for (const auto& rf : ld.recall_list_static) {
if (idx++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- [" << (idx-1) << "] "
<< "status=" << recallStatusStr(rf.recall_status)
<< ", StartTime=" << rf.StartTime
<< ", EndTime=" << rf.EndTime
<< ", STEADY=" << rf.STEADY
<< ", VOLTAGE=" << rf.VOLTAGE
<< "\n";
// ★新增:直下模式与目标时间列表
os << "\r\x1B[K |-- direct_mode=" << (rf.direct_mode ? "true" : "false")
<< ", target_filetimes(" << rf.target_filetimes << ")\n";
{
os << "\r\x1B[K |.. " << rf.target_filetimes << "\n";
}
// ★新增:状态机运行态
os << "\r\x1B[K |-- phase=" << phaseStr(rf.phase)
<< ", cur_dir_index=" << rf.cur_dir_index
<< ", cur_dir=" << rf.cur_dir << "\n";
os << "\r\x1B[K |-- list_result=" << resultStr(rf.list_result)
<< ", download_result=" << resultStr(rf.download_result) << "\n";
// ★新增:候选目录
os << "\r\x1B[K |-- dir_candidates(" << rf.dir_candidates.size() << ")\n";
{
size_t c = 0;
for (const auto& d : rf.dir_candidates) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << d << "\n";
}
if (rf.dir_candidates.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (rf.dir_candidates.size() - MAX_ITEMS) << " more)\n";
}
}
// ★新增:目录 -> 文件名列表(仅概要)
os << "\r\x1B[K |-- dir_files(" << rf.dir_files.size() << " dirs)\n";
{
size_t c = 0;
for (const auto& kv : rf.dir_files) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- [" << (c-1) << "] dir=" << kv.first
<< " files=" << kv.second.size() << "\n";
}
if (rf.dir_files.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (rf.dir_files.size() - MAX_ITEMS) << " more)\n";
}
}
// ★新增:下载队列(概要)
os << "\r\x1B[K |-- download_queue(" << rf.download_queue.size() << ")\n";
{
size_t c = 0;
for (const auto& path : rf.download_queue) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << path << "\n";
}
if (rf.download_queue.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (rf.download_queue.size() - MAX_ITEMS) << " more)\n";
}
}
// ★新增:当前下载中文件
if (!rf.downloading_file.empty()) {
os << "\r\x1B[K |-- downloading: " << rf.downloading_file << "\n";
}
}
if (ld.recall_list_static.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (ld.recall_list_static.size() - 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 +851,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 +910,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

@@ -59,6 +59,7 @@ private:
void sendBytes(int fd, const char* buf, int len);
void setTestNum(int num);
void setTestType(int type);
void setMaxItems(int items);
void setTestlog(bool flag);
void doPeriodicTask();
void processCommand(const std::string &cmd, int clientFD);

View File

@@ -2,18 +2,21 @@
BrokerList=
RTDataTopic=Real_Time_Data_Topic
HisTopic=LN_Topic
PSTTopic=LN_Topic
PLTTopic=LN_Topic
HisTopic=njcnAppAutoDataTopic
PSTTopic=njcnAppAutoDataTopic
PLTTopic=njcnAppAutoDataTopic
AlmTopic=AlmTopic
SngTopic=SngTopic
QUEUE_TAG=Test_Tag
QUEUE_KEY=Test_Keys
QUEUE_TAG=stat
QUEUE_KEY=stat
RT_TAG=rt
RT_KEY=rt
[Flag]
FrontInst=22de160455a30cc2154890e5502d6433
FrontIP=192.168.1.67
FrontInst=914b94563ca7f272c90ee8580ed6adc6
FrontIP=192.168.1.138
[Ledger]
TerminalStatus="[0]"
@@ -22,35 +25,34 @@ IcdFlag=0
IedCount=300
[Http]
WebDevice=http://192.168.1.67:10202/nodeDevice/nodeDeviceList
WebIcd=http://192.168.1.67:10202/icd/icdPathList
WebEvent=http://192.168.1.67:10203/event/addEventDetail
WebFileupload=http://192.168.1.67:10207/file/upload
WebFiledownload=http://192.168.1.67:10207/file/download
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=rmquser
SecretKey=001njcnmq
Ipport=192.168.1.103:9876
AccessKey=rmqroot
SecretKey=001@#njcnmq
Topic_Test=LN_Topic
Topic_Test=lnk_Topic
Tag_Test=Test_Tag
Key_Test=Test_Keys
Testflag=1
Testnum=400
Testtype=1
Testnum=0
Testtype=0
TestPort=11000
TestList=8ad28e2e36dfbd19906f9e2a4894b375
TestList=
consumer=Group_consumer
ConsumerIpport=192.168.1.24:9876
ConsumerIpport=192.168.1.103:9876
ConsumerTopicRT=ask_real_data_topic
ConsumerTagRT=Test_Tag
ConsumerKeyRT=Test_Keys
ConsumerAccessKey=rmquser
ConsumerSecretKey=001njcnmq
ConsumerAccessKey=rmqroot
ConsumerSecretKey=001@#njcnmq
ConsumerChannel=
ConsumerTopicUD=control_Topic
ConsumerTagUD=Test_Tag

View File

@@ -0,0 +1,80 @@
[Queue]
BrokerList=
RTDataTopic=Real_Time_Data_Topic
HisTopic=njcnAppAutoDataTopic
PSTTopic=njcnAppAutoDataTopic
PLTTopic=njcnAppAutoDataTopic
AlmTopic=AlmTopic
SngTopic=SngTopic
QUEUE_TAG=stat
QUEUE_KEY=stat
RT_TAG=rt
RT_KEY=rt
[Flag]
FrontInst=914b94563ca7f272c90ee8580ed6adc6
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.103: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=
consumer=Group_consumer
ConsumerIpport=192.168.1.103: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

Some files were not shown because too many files have changed in this diff Show More