Compare commits
131 Commits
fix-lost
...
ea176eceaf
| Author | SHA1 | Date | |
|---|---|---|---|
| ea176eceaf | |||
| 2dab1369f3 | |||
| b11105f91c | |||
| dfe0f2e5e2 | |||
| 15cbbd1c24 | |||
| 69accad937 | |||
| 8e41e3f4d8 | |||
| af937a8360 | |||
| 3d589c5042 | |||
| f727f9ee9c | |||
| 93def18fbd | |||
| bf1eccf436 | |||
| 852245f8ac | |||
| d460816195 | |||
| 9559f288ca | |||
| 7312bc68d7 | |||
| 2b4c939b79 | |||
| 787d1f20be | |||
| 6f0ee17da2 | |||
| 529abd4d55 | |||
| a4cd9cf62f | |||
| 1c76a9a1ce | |||
| 3e05e627d3 | |||
| c97b83d83d | |||
| a87504cee9 | |||
| 709fdfc284 | |||
| c538161074 | |||
| d18eb0d157 | |||
| df9760c1a7 | |||
| 7c676162ef | |||
| cab2ab3453 | |||
| 02127869c0 | |||
| be068fab40 | |||
| a71735b983 | |||
| 7725fd2d87 | |||
| dd01a31a77 | |||
| 1014aeafbc | |||
| c5ded4c032 | |||
| 44852a0846 | |||
| 50f82af3f3 | |||
| 2c48d7ae0a | |||
| 7dbd4593fa | |||
| e615188bb1 | |||
| b4ce0fa5f9 | |||
| 56382e9ccd | |||
| 0c239be9a7 | |||
| b08c632de4 | |||
| a1d8a55357 | |||
| 93143fcba6 | |||
| 02d2b021cd | |||
| beedb9aeca | |||
| ba142d3fd3 | |||
| c02f0cbbdd | |||
| 5e63adc8f9 | |||
| 06a2f3a75b | |||
| f69a6d2105 | |||
| 07ac84d612 | |||
| fdd6a30fe2 | |||
| 5ebb179c44 | |||
| fdbefa50ac | |||
| a755c6faab | |||
| c7e7cd9078 | |||
| ff67e5320f | |||
| c55f2ab1af | |||
| 24e1bf0125 | |||
| 8fb922e8c6 | |||
| 4e15ffff06 | |||
| fbbb96a64a | |||
| 987dba34dc | |||
| a43afb15c5 | |||
| c494225b38 | |||
| 35231baae7 | |||
| caf3c308c1 | |||
| 5616d9096a | |||
| a6127f0d28 | |||
| 4fe8aee149 | |||
| e997c88d82 | |||
| b976795573 | |||
| 1b00804522 | |||
| 0f16968452 | |||
| db8aa8c07d | |||
| 169aa9b34a | |||
| 825315440d | |||
| 016caeb07c | |||
| 7183cc1673 | |||
| cc5d5e2f81 | |||
| 0638b1dbf8 | |||
| 6056ea167a | |||
| 729a6b8fda | |||
| c301de5aab | |||
| 03a1ae4583 | |||
| f27d208959 | |||
| a298ff847a | |||
| e434f66986 | |||
| 58ffb3a6aa | |||
| 5d20597993 | |||
| 124df41911 | |||
| 2ef5b69dd8 | |||
| 8dd6b1f0ea | |||
| d526ffe415 | |||
| 374dd3e7b0 | |||
| 1e2dcf76a0 | |||
| 9dc138a617 | |||
| 869189d18e | |||
| 722512fad6 | |||
| bf805e1238 | |||
| f4c74c7d67 | |||
| 24fc98407f | |||
| 0af8d02bb2 | |||
| 077c3f45a2 | |||
| 13e0bc18b3 | |||
| e0b2c6d356 | |||
| f310cb49a3 | |||
| 16ccb567d0 | |||
| 83986c35cb | |||
| ee6d9c2689 | |||
| afc079465e | |||
| 81667f3b0d | |||
| 5539c10c0d | |||
| 0eab1e6fb5 | |||
| 868de7a909 | |||
| 78938827f7 | |||
| cc9d651b5a | |||
| fff1312c6e | |||
| 95cd3049a7 | |||
| 900569e5de | |||
| 8e4e45ce31 | |||
| 3fb8ac84f5 | |||
| b1963098eb | |||
| 7cfcdd0c5a | |||
| 3ae8ba5900 |
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -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
BIN
LFtid1056.rar
Normal file
Binary file not shown.
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,600 @@ 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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>
|
||||
* @param data <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param sendCount <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
|
||||
* @param count <20><>֡<EFBFBD><D6A1>
|
||||
* @param fileSize <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
|
||||
* @param crc CRCУ<43><D0A3>ֵ
|
||||
* @param filedir <20><><EFBFBD><EFBFBD>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_sendfile_message(const std::vector<unsigned char>& data,
|
||||
std::uint32_t sendCount,
|
||||
std::uint32_t count,
|
||||
std::uint32_t fileSize,
|
||||
std::uint16_t crc,
|
||||
const std::string& filedir) {
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> 17+128 <20>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
|
||||
std::vector<unsigned char> DataBuf(17 + 128 + data.size(), 0x00);
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嵽17+128<32>ֽ<EFBFBD>ͷ<EFBFBD><CDB7>֮<EFBFBD><D6AE>
|
||||
std::copy(data.begin(), data.end(), DataBuf.begin() + 17 + 128);
|
||||
|
||||
DataBuf[0] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// 4<>ֽڵ<D6BD>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
|
||||
DataBuf[3] = static_cast<unsigned char>(((sendCount + 1) >> 24) & 0xFF);
|
||||
DataBuf[4] = static_cast<unsigned char>(((sendCount + 1) >> 16) & 0xFF);
|
||||
DataBuf[5] = static_cast<unsigned char>(((sendCount + 1) >> 8) & 0xFF);
|
||||
DataBuf[6] = static_cast<unsigned char>((sendCount + 1) & 0xFF);
|
||||
|
||||
// 4<>ֽ<EFBFBD><D6BD><EFBFBD>֡<EFBFBD><D6A1>
|
||||
DataBuf[7] = static_cast<unsigned char>((count >> 24) & 0xFF);
|
||||
DataBuf[8] = static_cast<unsigned char>((count >> 16) & 0xFF);
|
||||
DataBuf[9] = static_cast<unsigned char>((count >> 8) & 0xFF);
|
||||
DataBuf[10] = static_cast<unsigned char>(count & 0xFF);
|
||||
|
||||
// 4<>ֽ<EFBFBD><D6BD>ܴ<EFBFBD>С
|
||||
DataBuf[11] = static_cast<unsigned char>((fileSize >> 24) & 0xFF);
|
||||
DataBuf[12] = static_cast<unsigned char>((fileSize >> 16) & 0xFF);
|
||||
DataBuf[13] = static_cast<unsigned char>((fileSize >> 8) & 0xFF);
|
||||
DataBuf[14] = static_cast<unsigned char>(fileSize & 0xFF);
|
||||
|
||||
// 2<>ֽ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>
|
||||
DataBuf[15] = static_cast<unsigned char>((crc >> 8) & 0xFF);
|
||||
DataBuf[16] = static_cast<unsigned char>(crc & 0xFF);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>17<31><37>ʼ<EFBFBD><CABC>
|
||||
size_t copyLen = std::min(filedir.size(), static_cast<size_t>(128));
|
||||
if (copyLen > 0) {
|
||||
memcpy(DataBuf.data() + 17, filedir.c_str(), copyLen);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>8<EFBFBD><38>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_File_Send));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param filedir ɾ<><C9BE><EFBFBD>ļ<EFBFBD>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_deletefile_message(const std::string& filedir) {
|
||||
// <20><><EFBFBD><EFBFBD> 3 <20>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
|
||||
std::vector<unsigned char> DataBuf(3 + 128, 0x00);
|
||||
|
||||
DataBuf[0] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// <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>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>9<EFBFBD><39>Ӧɾ<D3A6><C9BE><EFBFBD>ļ<EFBFBD>
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_File_Del));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param filedir Ŀ¼ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_setmenu_message(const std::string& filedir) {
|
||||
// <20><><EFBFBD><EFBFBD> 3 <20>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
|
||||
std::vector<unsigned char> DataBuf(3 + 128, 0x00);
|
||||
|
||||
DataBuf[0] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// <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>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>11<31><31>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>Ŀ¼
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Menu_Set));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD>Ŀ¼ɾ<C2BC><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param filedir Ŀ¼ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_delmenu_message(const std::string& filedir) {
|
||||
// <20><><EFBFBD><EFBFBD> 3 <20>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
|
||||
std::vector<unsigned char> DataBuf(3 + 128, 0x00);
|
||||
|
||||
DataBuf[0] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// <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>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>12<31><32>Ӧɾ<D3A6><C9BE>Ŀ¼
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Menu_Del));
|
||||
}
|
||||
|
||||
// <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>ֵΪ2<CEAA><32><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><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_preupgrade_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>ֵΪ4<CEAA><34><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD>ֽڣ<D6BD>
|
||||
DataBuf[3] = 0x04;
|
||||
|
||||
// <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><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param data <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param updateCount <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
|
||||
* @param updateSize <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
|
||||
* @param count <20><>֡<EFBFBD><D6A1>
|
||||
* @param crc CRCУ<43><D0A3>ֵ
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_upgrade_start_message(const std::vector<unsigned char>& data,
|
||||
std::uint32_t updateCount,
|
||||
std::uint32_t updateSize,
|
||||
std::uint32_t count,
|
||||
std::uint32_t crc)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD>44<34>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
|
||||
std::vector<unsigned char> DataBuf(44 + data.size(), 0x00);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嵽44<34>ֽ<EFBFBD>ͷ<EFBFBD><CDB7>֮<EFBFBD><D6AE>
|
||||
std::copy(data.begin(), data.end(), DataBuf.begin() + 44);
|
||||
|
||||
DataBuf[0] = 0x00; // У<>鷽ʽ 0-crcУ<63><D0A3> 1-md5У<35><D0A3>
|
||||
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// 4<>ֽڵ<D6BD>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
|
||||
DataBuf[3] = static_cast<unsigned char>(((updateCount + 1) >> 24) & 0xFF);
|
||||
DataBuf[4] = static_cast<unsigned char>(((updateCount + 1) >> 16) & 0xFF);
|
||||
DataBuf[5] = static_cast<unsigned char>(((updateCount + 1) >> 8) & 0xFF);
|
||||
DataBuf[6] = static_cast<unsigned char>((updateCount + 1) & 0xFF);
|
||||
|
||||
// 4<>ֽ<EFBFBD><D6BD><EFBFBD>֡<EFBFBD><D6A1>
|
||||
DataBuf[7] = static_cast<unsigned char>((count >> 24) & 0xFF);
|
||||
DataBuf[8] = static_cast<unsigned char>((count >> 16) & 0xFF);
|
||||
DataBuf[9] = static_cast<unsigned char>((count >> 8) & 0xFF);
|
||||
DataBuf[10] = static_cast<unsigned char>(count & 0xFF);
|
||||
|
||||
// 4<>ֽ<EFBFBD><D6BD>ܴ<EFBFBD>С
|
||||
DataBuf[11] = static_cast<unsigned char>((updateSize >> 24) & 0xFF);
|
||||
DataBuf[12] = static_cast<unsigned char>((updateSize >> 16) & 0xFF);
|
||||
DataBuf[13] = static_cast<unsigned char>((updateSize >> 8) & 0xFF);
|
||||
DataBuf[14] = static_cast<unsigned char>(updateSize & 0xFF);
|
||||
|
||||
// 4<>ֽ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>
|
||||
DataBuf[15] = static_cast<unsigned char>((crc >> 24) & 0xFF);
|
||||
DataBuf[16] = static_cast<unsigned char>((crc >> 16) & 0xFF);
|
||||
DataBuf[17] = static_cast<unsigned char>((crc >> 8) & 0xFF);
|
||||
DataBuf[18] = static_cast<unsigned char>(crc & 0xFF);
|
||||
|
||||
DataBuf[19] = 0x00; // ѹ<><D1B9><EFBFBD><EFBFBD>ʽ <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// DataBuf[20]~DataBuf[27] Ϊ0<CEAA><30>ѹǰ<D1B9><C7B0>С/ѹǰУ<C7B0>鱸<EFBFBD><E9B1B8>
|
||||
// DataBuf[28]~DataBuf[43] Ϊ0<CEAA><30>16<31>ֽ<EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// vector <20><>ʼ<EFBFBD><CABC>ʱ<EFBFBD>Ѿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>ֵ
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>38<33><38>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Upgrade));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_upgrade_end_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);
|
||||
|
||||
DataBuf[0] = 0x55;//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>38<33><38>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Upgrade));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><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>
|
||||
*/
|
||||
std::vector<unsigned char> generate_requestHeartBeat_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_HeartBeat));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>װ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB1A8>
|
||||
* @param type <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1-װ<>ø<EFBFBD>λ<EFBFBD><CEBB>2-<2D><><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>3-<2D><><EFBFBD><EFBFBD>200ms<6D><73><EFBFBD>ݼ<EFBFBD>¼<EFBFBD><C2BC>4-<2D><><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>¼
|
||||
* @param ctrlflag <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3> <20>״δ<D7B4><CEB4><EFBFBD>0 <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD> 0x01ִ<31><D6B4> 0x02ȡ<32><C8A1>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
std::vector<unsigned char> generate_control_message(uint8_t type, uint8_t ctrlflag) {
|
||||
// <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
||||
std::vector<unsigned char> DataBuf(3, 0x00);
|
||||
|
||||
DataBuf[0] = type; // 1-װ<>ø<EFBFBD>λ<EFBFBD><CEBB>2-<2D><><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>3-<2D><><EFBFBD><EFBFBD>200ms<6D><73><EFBFBD>ݼ<EFBFBD>¼<EFBFBD><C2BC>4-<2D><><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>¼
|
||||
DataBuf[1] = ctrlflag; // 0x01ִ<31><D6B4> 0x02ȡ<32><C8A1>
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Ctrl));
|
||||
}
|
||||
|
||||
|
||||
1739
LFtid1056/PQSMsg.h
1739
LFtid1056/PQSMsg.h
File diff suppressed because it is too large
Load Diff
29
LFtid1056/boot/feservice
Normal file
29
LFtid1056/boot/feservice
Normal 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
62
LFtid1056/boot/ps_fe.sh
Normal 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
|
||||
97
LFtid1056/boot/start_fe.sh
Normal file
97
LFtid1056/boot/start_fe.sh
Normal 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
129
LFtid1056/boot/stop_fe.sh
Normal 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
|
||||
@@ -49,11 +49,11 @@ fi
|
||||
|
||||
# 判断是否为 debug 版本
|
||||
if [[ "$1" == "debug" ]]; then
|
||||
CXXFLAGS="-std=c++11 -g -O0"
|
||||
CXXFLAGS="-std=c++11 -g -O0 -Wformat -Wformat-security -Werror=format"
|
||||
TARGET="${TARGET}d"
|
||||
echo "🟢 编译调试版本 (-g -O0)"
|
||||
else
|
||||
CXXFLAGS="-std=c++11 -O2 -static-libstdc++ -static-libgcc"
|
||||
CXXFLAGS="-std=c++11 -O2 -static-libstdc++ -static-libgcc -Wformat -Wformat-security -Werror=format"
|
||||
echo "🔵 编译正式版本 (-O2 -static)"
|
||||
fi
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,35 @@ enum class ConnectionState {
|
||||
|
||||
// <20><><EFBFBD>ӵ<EFBFBD>״̬ö<CCAC><C3B6>
|
||||
enum class DeviceState {
|
||||
IDLE, // <20><><EFBFBD><EFBFBD>״̬
|
||||
READING_STATS, // <EFBFBD><EFBFBD>ȡͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
READING_STATS_TIME, // <20><>ȡͳ<C8A1><CDB3>ʱ<EFBFBD><EFBFBD>
|
||||
IDLE, // <20><><EFBFBD><EFBFBD>״̬
|
||||
HEART_BEAT, // װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>Ŀ¼
|
||||
SEND_FILE, // <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
DEL_FILE, // <20>ļ<EFBFBD>ɾ<EFBFBD><C9BE>
|
||||
SEND_MENU, // Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD>
|
||||
DEL_MENU, // Ŀ¼ɾ<C2BC><C9BE>
|
||||
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>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʱִ<CAB1>У<EFBFBD>
|
||||
SET_RIGHTTIME_2, // <20><><EFBFBD><EFBFBD>װ<EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>
|
||||
SET_CTRL, // <20><><EFBFBD><EFBFBD>װ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
SET_PREUPGRADE, // װ<><D7B0>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>У<EFBFBD><D0A3>
|
||||
SET_UPGRADE, // װ<><D7B0><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 +91,19 @@ public:
|
||||
ConnectionState state;
|
||||
int reconnect_attempts;
|
||||
volatile bool shutdown;
|
||||
|
||||
uint64_t heartbeat_time = 0;// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʱʱ<CAB1><CAB1><EFBFBD><EFBFBD>
|
||||
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 +135,106 @@ 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>
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
|
||||
struct UpgradeTask
|
||||
{
|
||||
std::vector<unsigned char> file_data; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
uint32_t file_size = 0; // <20>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
|
||||
uint32_t file_crc = 0; // <20>ļ<EFBFBD>CRC32
|
||||
uint32_t frame_payload_size = 0; // <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
uint32_t total_frames = 0; // <20><>֡<EFBFBD><D6A1>
|
||||
uint32_t next_frame_index = 0; // <20><>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>(0-based)
|
||||
bool active = false; // <20><>ǰ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
mutable std::mutex upgrade_mutex_;
|
||||
UpgradeTask upgrade_task_;
|
||||
/**
|
||||
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
||||
* @param file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
* @param frame_payload_size <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool prepare_upgrade_task(const std::vector<unsigned char>& file, uint32_t frame_payload_size);
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
|
||||
* @param out_packet <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param finished <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool build_next_upgrade_packet(std::vector<unsigned char>& out_packet, bool& finished);
|
||||
void clear_upgrade_task();
|
||||
bool has_active_upgrade_task() const;
|
||||
/**
|
||||
* @brief <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
|
||||
* @param current_frame_index <20><>ǰ֡
|
||||
* @param total_frames <20><>֡<EFBFBD><D6A1>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool get_upgrade_progress(uint32_t& current_frame_index, uint32_t& total_frames) const;
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
|
||||
|
||||
// <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
|
||||
struct SendFileTask
|
||||
{
|
||||
std::vector<unsigned char> file_data; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
uint32_t file_size = 0; // <20>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
|
||||
uint16_t file_crc = 0; // <20>ļ<EFBFBD>CRC16
|
||||
uint32_t frame_payload_size = 0; // <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
uint32_t total_frames = 0; // <20><>֡<EFBFBD><D6A1>
|
||||
uint32_t next_frame_index = 0; // <20><>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>(0-based)
|
||||
std::string dest_file_path; // װ<>ö<EFBFBD>Ŀ<EFBFBD><C4BF>ȫ·<C8AB><C2B7>
|
||||
bool active = false; // <20><>ǰ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
mutable std::mutex send_file_mutex_;
|
||||
SendFileTask send_file_task_;
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
||||
* @param file <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param frame_payload_size <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD>
|
||||
* @param dest_file_path װ<>ö<EFBFBD>Ŀ<EFBFBD><C4BF>ȫ·<C8AB><C2B7>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>ɹ<EFBFBD>
|
||||
*/
|
||||
bool prepare_send_file_task(const std::vector<unsigned char>& file,
|
||||
uint32_t frame_payload_size,
|
||||
const std::string& dest_file_path);
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
|
||||
* @param out_packet <20><><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>
|
||||
* @param finished <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool build_next_send_file_packet(std::vector<unsigned char>& out_packet, bool& finished);
|
||||
|
||||
void clear_send_file_task();
|
||||
bool has_active_send_file_task() const;
|
||||
|
||||
/**
|
||||
* @brief <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>͵ĵ<CDB5>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
|
||||
* @param current_frame_index <20><>ǰ֡
|
||||
* @param total_frames <20><>֡<EFBFBD><D6A1>
|
||||
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool get_send_file_progress(uint32_t& current_frame_index, uint32_t& total_frames) const;
|
||||
// <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
|
||||
|
||||
// ͳ<><CDB3><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
|
||||
struct PointFloatCache {
|
||||
@@ -122,6 +253,107 @@ 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::string preupgrade_filepath_; // Ԥ<><D4A4><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
|
||||
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_;
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
|
||||
void set_preupgrade_filepath(const std::string& filepath) {
|
||||
std::lock_guard<std::mutex> lock(file_cache_mutex_);
|
||||
preupgrade_filepath_ = filepath;
|
||||
}
|
||||
|
||||
// <20><>ȡԤ<C8A1><D4A4><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
|
||||
std::string get_preupgrade_filepath() {
|
||||
std::lock_guard<std::mutex> lock(file_cache_mutex_);
|
||||
return preupgrade_filepath_;
|
||||
}
|
||||
private:
|
||||
int index_;
|
||||
|
||||
@@ -146,7 +378,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 +413,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 +453,202 @@ 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);
|
||||
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ԤУ<D4A4><D0A3><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
|
||||
std::string get_preupgrade_filepath(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);
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>װ<EFBFBD><D7B0><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param file_path <20>ļ<EFBFBD>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool add_file_delete_action_to_device(const std::string& identifier, const std::string& file_path);
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD>ɴ<EFBFBD><C9B4><EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD>
|
||||
* @param file_path <20>ļ<EFBFBD>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool add_menu_set_action_to_device(const std::string& identifier, const std::string& file_path);
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD>
|
||||
* @param file_path <20>ļ<EFBFBD>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool add_menu_del_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);
|
||||
|
||||
//װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
|
||||
bool set_righttime_action_to_device(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>У<EFBFBD>鱨<EFBFBD><E9B1A8>
|
||||
* @param path ԤУ<D4A4><D0A3><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool set_preupgrade_action_to_device(const std::string& identifier, const std::string& path);
|
||||
/**
|
||||
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ͳ<EFBFBD>ʼ֡
|
||||
* @param file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
* @param sin_length <20><><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool send_upgrade_action_to_device(const std::string& identifier, const std::vector<unsigned char>& file, int sin_length);
|
||||
/**
|
||||
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
|
||||
* @param identifier װ<>ñ<EFBFBD>ʶ<EFBFBD><CAB6>device_id <20><> mac<61><63>
|
||||
* @param current_frame_index <20><>ȡ<EFBFBD><C8A1>ǰ֡(0-based<65><64><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1>)
|
||||
* @param total_frames <20><>ȡ<EFBFBD><C8A1>֡<EFBFBD><D6A1>
|
||||
* @param all_sent <20>Ƿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param packet <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
|
||||
* @return <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool try_get_next_upgrade_packet_to_device(const std::string& identifier,
|
||||
uint32_t& current_frame_index,
|
||||
uint32_t& total_frames,
|
||||
bool& all_sent,
|
||||
std::vector<unsigned char>& packet);
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> <20><><EFBFBD>ͳ<EFBFBD>ʼ֡
|
||||
* @param file <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param sin_length <20><><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
||||
* @param dest_file_path װ<>ö<EFBFBD>Ŀ<EFBFBD><C4BF>ȫ·<C8AB><C2B7>
|
||||
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
|
||||
*/
|
||||
bool send_file_action_to_device(const std::string& identifier,
|
||||
const std::vector<unsigned char>& file,
|
||||
int sin_length,
|
||||
const std::string& dest_file_path);
|
||||
|
||||
/**
|
||||
* @brief <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> <20><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
|
||||
* @param identifier װ<>ñ<EFBFBD>ʶ<EFBFBD><CAB6>device_id <20><> mac<61><63>
|
||||
* @param current_frame_index <20><>ȡ<EFBFBD><C8A1>ǰ֡(0-based<65><64><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1>)
|
||||
* @param total_frames <20><>ȡ<EFBFBD><C8A1>֡<EFBFBD><D6A1>
|
||||
* @param all_sent <20>Ƿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param packet <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
|
||||
* @return <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool try_get_next_send_file_packet_to_device(const std::string& identifier,
|
||||
uint32_t& current_frame_index,
|
||||
uint32_t& total_frames,
|
||||
bool& all_sent,
|
||||
std::vector<unsigned char>& packet);
|
||||
|
||||
//<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);
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>װ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB1A8>
|
||||
* @param type <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1-װ<>ø<EFBFBD>λ<EFBFBD><CEBB>2-<2D><><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>3-<2D><><EFBFBD><EFBFBD>200ms<6D><73><EFBFBD>ݼ<EFBFBD>¼<EFBFBD><C2BC>4-<2D><><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>¼
|
||||
* @param ctrlflag <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3> <20>״δ<D7B4><CEB4><EFBFBD>0x00 <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD> 0x01ִ<31><D6B4> 0x02ȡ<32><C8A1>
|
||||
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
bool set_ctrl_action_to_device(const std::string& identifier, uint8_t type, uint8_t ctrlflag);
|
||||
private:
|
||||
ClientManager() : loop_(nullptr) {}
|
||||
std::unordered_map<std::string, std::unique_ptr<ClientContext>> clients_;
|
||||
@@ -217,6 +659,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
@@ -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();
|
||||
|
||||
@@ -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】筛选运行和在运
|
||||
@@ -133,10 +133,85 @@ void SendJsonAPI_web(const std::string& strUrl, //接口路径
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////下载文件流式接口
|
||||
size_t req_reply_file_web(void* ptr, size_t size, size_t nmemb, void* userdata)
|
||||
{
|
||||
std::ofstream* out = static_cast<std::ofstream*>(userdata);
|
||||
size_t total = size * nmemb;
|
||||
|
||||
if (out && out->is_open()) {
|
||||
out->write(static_cast<const char*>(ptr), total);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
bool DownloadFileAPI_web(const std::string& strUrl, // 接口路径
|
||||
const std::string& code, // URL参数
|
||||
const std::string& json, // POST body,可为空
|
||||
const std::string& save_path)// 本地保存路径
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode res;
|
||||
|
||||
if (!curl) {
|
||||
std::cerr << ">>> web curl init failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ofstream outFile(save_path.c_str(), std::ios::out | std::ios::binary);
|
||||
if (!outFile.is_open()) {
|
||||
std::cerr << ">>> open file failed: " << save_path << std::endl;
|
||||
curl_easy_cleanup(curl);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string fullUrl = strUrl + "?" + code;
|
||||
std::cout << ">>>file " << fullUrl << std::endl;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_file_web);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outFile);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
|
||||
|
||||
if (!json.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
|
||||
}
|
||||
|
||||
struct curl_slist* headers = nullptr;
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
long http_code = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
outFile.close();
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
std::cerr << "web failed, res code: " << curl_easy_strerror(res) << std::endl;
|
||||
remove(save_path.c_str()); // 下载失败删除残文件
|
||||
return false;
|
||||
}
|
||||
|
||||
if (http_code != 200) {
|
||||
std::cerr << "web http failed, http_code: " << http_code << std::endl;
|
||||
remove(save_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << ">>> file download success: " << save_path << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////上传文件接口
|
||||
|
||||
//处理文件上传响应
|
||||
void handleUploadResponse(const std::string& response, std::string& wavepath) {
|
||||
void handleUploadResponse(const std::string& response, std::string& wavepath, int type) {
|
||||
|
||||
using nlohmann::json; //把 nlohmann::json 这个名字带到当前作用域
|
||||
|
||||
@@ -147,14 +222,14 @@ void handleUploadResponse(const std::string& response, std::string& wavepath) {
|
||||
}
|
||||
catch (const json::parse_error& e) {
|
||||
std::cerr << "Error parsing response: " << e.what() << std::endl;
|
||||
DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息不是json格式");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_JSON, "文件上传接口响应异常,上传文件失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 提取字段
|
||||
if (!json_data.contains("code") || !json_data.contains("data")) {
|
||||
std::cerr << "Error: Missing expected fields in JSON response." << std::endl;
|
||||
DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_JSON, "文件上传接口响应异常,上传文件失败");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,7 +242,7 @@ void handleUploadResponse(const std::string& response, std::string& wavepath) {
|
||||
auto& data = json_data["data"];
|
||||
if (!data.contains("name") || !data.contains("fileName") || !data.contains("url")) {
|
||||
std::cerr << "Error: Missing expected fields in JSON data object." << std::endl;
|
||||
DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_JSON, "文件上传接口响应异常,上传文件失败");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,28 +256,56 @@ 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);
|
||||
} else {
|
||||
// 如果没有后缀,直接使用原文件名
|
||||
nameWithoutExt = fileName;
|
||||
if(1 == type) {
|
||||
if (pos != std::string::npos) {
|
||||
// 截取去掉后缀的部分
|
||||
nameWithoutExt = name.substr(0, pos); //去掉路径后缀的名
|
||||
} else {
|
||||
// 如果没有后缀,直接使用原文件名
|
||||
nameWithoutExt = name;
|
||||
}
|
||||
}
|
||||
else if(2 == type) {
|
||||
nameWithoutExt = name;//带路径全名
|
||||
}
|
||||
else{
|
||||
nameWithoutExt = fileName;//没有路径的全名
|
||||
}
|
||||
|
||||
|
||||
// 拷贝到 wavepath
|
||||
wavepath = nameWithoutExt;
|
||||
|
||||
std::cout << "wavepath: " << wavepath << std::endl;
|
||||
DIY_INFOLOG("process", "【NORMAL】前置上传暂态录波文件成功,远端文件名:%s", wavepath.c_str());
|
||||
DIY_INFOLOG_CODE("process",0,LOG_CODE_FILE, "上传文件成功,远端文件名:%s", wavepath.c_str());
|
||||
}
|
||||
|
||||
//上传文件
|
||||
void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath) {
|
||||
void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath, int type) {
|
||||
|
||||
// 基本存在性检查
|
||||
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 +314,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 +336,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,16 +353,17 @@ 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;
|
||||
DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath);
|
||||
const char* em = errbuf[0] ? errbuf : curl_easy_strerror(res);
|
||||
std::cerr << "http web failed: " << em << std::endl;
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_CONFIG, "通过文件接口上传文件 %s 失败",localpath.c_str());
|
||||
} else {
|
||||
std::cout << "http web success, response: " << resPost0 << std::endl;
|
||||
handleUploadResponse(resPost0, wavepath); // 处理响应
|
||||
handleUploadResponse(resPost0, wavepath, type); // 处理响应
|
||||
}
|
||||
|
||||
// 清理
|
||||
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;
|
||||
@@ -273,7 +373,7 @@ void SendFileWeb(const std::string& strUrl, const std::string& localpath, const
|
||||
//上传暂态文件
|
||||
void SOEFileWeb(std::string& localpath,std::string& cloudpath, std::string& wavepath)
|
||||
{
|
||||
SendFileWeb(WEB_FILEUPLOAD,localpath,cloudpath,wavepath);
|
||||
SendFileWeb(WEB_FILEUPLOAD,localpath,cloudpath,wavepath,1);
|
||||
}
|
||||
|
||||
//上传文件测试函数
|
||||
@@ -286,6 +386,105 @@ void Fileupload_test()
|
||||
std::cout << "wavepath:" << wavepath << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////下载文件接口通用
|
||||
// 下载文件:从远端路径下载到本地,并返回本地文件路径
|
||||
// 入参:dev(设备)、remote_path(远端完整路径)
|
||||
// 返回:本地保存路径(失败返回空字符串)
|
||||
std::string getfilefromweb(const std::string& devid, const std::string& remote_path)
|
||||
{
|
||||
try {
|
||||
terminal_dev* dev = nullptr;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(ledgermtx);
|
||||
for (auto& d : terminal_devlist) {
|
||||
if (d.terminal_id == devid) {
|
||||
dev = &d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
std::cerr << "[getfile][ERROR] dev not found, id=" << devid << std::endl;
|
||||
return "";
|
||||
}
|
||||
//【1】清洗远端路径(防止 \0 问题)
|
||||
std::string clean_remote = sanitize(remote_path);
|
||||
|
||||
//【2】提取文件名(去掉路径,只保留最后一段)
|
||||
auto get_filename = [](const std::string& path) -> std::string {
|
||||
size_t pos1 = path.find_last_of('/');
|
||||
size_t pos2 = path.find_last_of('\\');
|
||||
size_t pos = std::string::npos;
|
||||
|
||||
if (pos1 == std::string::npos) pos = pos2;
|
||||
else if (pos2 == std::string::npos) pos = pos1;
|
||||
else pos = std::max(pos1, pos2);
|
||||
|
||||
return (pos == std::string::npos) ? path : path.substr(pos + 1);
|
||||
};
|
||||
|
||||
std::string filename = get_filename(clean_remote);
|
||||
|
||||
//【3】构造本地保存路径
|
||||
std::string mac = sanitize(normalize_mac(dev->addr_str));
|
||||
std::string save_dir = std::string(FRONT_PATH) + "/bin/upload/" + mac + "/";
|
||||
|
||||
if (!create_directory_recursive(save_dir)) {
|
||||
std::cerr << "[getfile][ERROR] create dir failed: " << save_dir << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string save_path = save_dir + filename;
|
||||
|
||||
std::cout << "[getfile] remote: " << clean_remote
|
||||
<< " -> local: " << save_path << std::endl;
|
||||
|
||||
//【4】构造接口入参
|
||||
//std::string fileContent;
|
||||
std::string fullPath = "filePath=" + clean_remote;
|
||||
|
||||
std::cout << "[getfile] request param: " << fullPath << std::endl;
|
||||
|
||||
//【5】调用下载接口
|
||||
if (!DownloadFileAPI_web(WEB_FILEDOWNLOAD, fullPath, "", save_path)) {
|
||||
std::cerr << "[getfile][ERROR] download failed: " << clean_remote << std::endl;
|
||||
return "";
|
||||
}
|
||||
/*SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", fileContent);
|
||||
|
||||
|
||||
//【6】判断返回
|
||||
if (fileContent.empty()) {
|
||||
std::cerr << "[getfile][ERROR] download failed, empty content" << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
//【7】写文件
|
||||
std::ofstream outFile(save_path, std::ios::out | std::ios::binary);
|
||||
if (!outFile.is_open()) {
|
||||
std::cerr << "[getfile][ERROR] cannot open file: " << save_path << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
outFile.write(fileContent.c_str(), fileContent.size());
|
||||
outFile.close();*/
|
||||
|
||||
std::cout << "[getfile] File saved successfully: " << save_path << std::endl;
|
||||
|
||||
//【8】返回本地路径
|
||||
return save_path;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "[getfile][EXCEPTION] " << e.what() << std::endl;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "[getfile][EXCEPTION] unknown error" << std::endl;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////映射文件下载接口
|
||||
void download_xml_for_icd(const std::string& MODEL_ID,
|
||||
const std::string& TMNL_TYPE,
|
||||
@@ -373,7 +572,7 @@ void download_xml_for_icd(const std::string& MODEL_ID,
|
||||
std::cout << "remote file name:" << remote_file_name << "local save name:" << save_name << std::endl;
|
||||
|
||||
// mq日志
|
||||
DIY_WARNLOG("process","【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name);
|
||||
|
||||
|
||||
std::string fileContent;
|
||||
std::string fullPath = std::string("filePath=") + filepath; //填写远端路径作为入参
|
||||
@@ -393,14 +592,14 @@ void download_xml_for_icd(const std::string& MODEL_ID,
|
||||
outFile.close();
|
||||
|
||||
std::cout << "File saved successfully!" << std::endl;
|
||||
DIY_WARNLOG("process","【WARN】前置下载映射文件%s成功",save_name);
|
||||
|
||||
} else {
|
||||
std::cerr << "Error: Unable to open file for writing." << std::endl;
|
||||
DIY_ERRORLOG("process","【ERROR】前置写入本地映射文件%s失败",save_name);
|
||||
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Error: Unable to download file." << std::endl;
|
||||
DIY_ERRORLOG("process","【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,8 +607,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 +699,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) {
|
||||
@@ -534,7 +733,7 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
|
||||
{
|
||||
if (inputstring.empty()) {
|
||||
std::cerr << "Error: inputstring is empty\n";
|
||||
DIY_ERRORLOG("process","【ERROR】前置的%d号进程调用web台账接口的入参为空", g_front_seg_index);
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_CONFIG,"调用台账接口的入参为空,无法获取台账信息");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -553,7 +752,7 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
|
||||
break;
|
||||
}
|
||||
std::cerr << "data 无效或为空数组,重试\n";
|
||||
DIY_ERRORLOG("process","【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",inputparm.c_str());
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_JSON,"从台账接口中获取到的台账信息为无效信息,台账初始化失败");
|
||||
} catch (const nlohmann::json::parse_error& e) {
|
||||
std::cerr << "parse error: " << e.what() << ", retrying...\n";
|
||||
}
|
||||
@@ -563,6 +762,7 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
|
||||
|
||||
if (++retry > 3) {
|
||||
std::cerr << "web error after 3 retry, fallback to local file\n";
|
||||
DIY_WARNLOG_CODE("process",0,LOG_CODE_CONFIG, "无法从台账接口获取台账,将从本地读取上一次缓存的台账");
|
||||
std::string ledger = read_latest_ledger_file();
|
||||
if (!ledger.empty()) {
|
||||
try {
|
||||
@@ -570,7 +770,7 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
|
||||
if (json_data.contains("data") && json_data["data"].is_array() && !json_data["data"].empty()) {
|
||||
break;
|
||||
}
|
||||
DIY_ERRORLOG("process", "【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",inputparm.c_str());
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_JSON,"从本地台账中获取到的台账信息为无效信息,台账初始化失败");
|
||||
} catch (const nlohmann::json::parse_error& e) {
|
||||
std::cerr << "local parse error: " << e.what() << "\n";
|
||||
}
|
||||
@@ -584,7 +784,7 @@ int terminal_ledger_web(std::map<std::string, terminal_dev>& terminal_dev_map,
|
||||
|
||||
// 2. 安全读取 code/msg
|
||||
std::string code = json_data.value("code", "not found");
|
||||
std::string msg = json_data.value("msg", "not found");
|
||||
std::string msg = json_data.value("message", "not found");
|
||||
std::cout << "code: " << code << "\n";
|
||||
std::cout << "msg : " << msg << "\n";
|
||||
|
||||
@@ -609,38 +809,41 @@ 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.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.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.DevLogLevel = safe_str(item, "devLogLevel");
|
||||
//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.LineLogLevel = safe_str(mon, "lineLogLevel");
|
||||
//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,12 +890,12 @@ 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 += "}";
|
||||
|
||||
std::cout << "input_jstr: " << input_jstr << std::endl;
|
||||
DIY_DEBUGLOG("process","【DEBUG】前置的%d号进程调用web接口获取台账使用的请求输入为:%s", g_front_seg_index, input_jstr.c_str());
|
||||
DIY_DEBUGLOG_CODE("process",0,LOG_CODE_LEDGER,"台账接口输入:%s", input_jstr.c_str());
|
||||
|
||||
// 2. 调用接口
|
||||
std::map<std::string, terminal_dev> terminal_dev_map;
|
||||
@@ -721,10 +924,10 @@ int parse_device_cfg_web()
|
||||
|
||||
if (max_process_num != max_index) {
|
||||
if (max_process_num >= 1 && max_process_num <= 9) {
|
||||
DIY_WARNLOG("process", "【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num, max_index);
|
||||
DIY_WARNLOG_CODE("process",0,LOG_CODE_CONFIG, "从台账获取到的进程数:%d和原有的进程数:%d不一致,将按照从台账获取到的进程数重置进程",max_process_num, max_index);
|
||||
execute_bash("reset", max_process_num, "all");
|
||||
} else {
|
||||
DIY_ERRORLOG("process","【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num);
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_CONFIG, "从台账获取到的总进程数:%d不符合范围1~9,不会重置进程",max_process_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -732,29 +935,68 @@ int parse_device_cfg_web()
|
||||
// 5. 台账数量与配置比对
|
||||
int count_cfg = static_cast<int>(terminal_dev_map.size());
|
||||
std::cout << "terminal_ledger_num: " << count_cfg << std::endl;
|
||||
DIY_DEBUGLOG("process", "【DEBUG】前置的%d号进程调用获取到的台账的数量为:%d", g_front_seg_index, count_cfg);
|
||||
DIY_DEBUGLOG_CODE("process",0,LOG_CODE_LEDGER,"获取到台账数量:%d",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;
|
||||
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
//记录所有logger等级
|
||||
refresh_log_level_cache_locked();
|
||||
|
||||
// 判断监测点接线类型
|
||||
for (auto& dev : terminal_devlist) {
|
||||
for (auto& mon : dev.line) {
|
||||
if (!mon.terminal_connect.empty() && mon.terminal_connect != "0") {
|
||||
isdelta_flag = 1;
|
||||
std::cout << "monitor_id " << mon.monitor_id<< " v_wiring_type: " << mon.terminal_connect << " is delta wiring: " << isdelta_flag << std::endl;
|
||||
DIY_WARNLOG("process","【WARN】前置连接的监测点%s是角形接线,对应终端为%s 终端类型是%s",mon.monitor_id.c_str(),dev.terminal_id.c_str(),dev.dev_type.c_str());
|
||||
//DIY_WARNLOG_CODE("process",0,LOG_CODE_WIRETYPE,"装置:%s - 监测点: %s 是角形接线",dev.terminal_name.c_str(),mon.monitor_name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -885,7 +1127,7 @@ int parse_model_cfg_web()
|
||||
// 3. 调用接口
|
||||
std::map<std::string, icd_model*> icd_model_map;
|
||||
if (parse_model_web(&icd_model_map, input_jstr)) {
|
||||
DIY_ERRORLOG("process", "【ERROR】前置的%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", g_front_seg_index);
|
||||
|
||||
// 确保释放 map
|
||||
for (auto& kv : icd_model_map) delete kv.second;
|
||||
return 0;
|
||||
@@ -939,7 +1181,7 @@ std::string parse_model_cfg_web_one(const std::string& terminal_type)
|
||||
// 2. 拉取并解析
|
||||
if (parse_model_web(&icd_model_map, input_jstr) != 0) {
|
||||
std::cerr << "parse_model_web failed for type: " << terminal_type << std::endl;
|
||||
DIY_ERRORLOG("process","【ERROR】前置的%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", g_front_seg_index);
|
||||
|
||||
// 清理(即使 map 为空,也安全)
|
||||
for (auto& kv : icd_model_map) delete kv.second;
|
||||
return "";
|
||||
@@ -1001,7 +1243,7 @@ static void writeJsonToFile(const std::string& filePath, const std::string& json
|
||||
{
|
||||
FILE* fp = fopen(filePath.c_str(), "w");
|
||||
if (!fp) {
|
||||
DIY_ERRORLOG("process", "【ERROR】无法将暂态事件写入本地缓存");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM, "无法将暂态事件写入本地缓存,暂态事件保存失败");
|
||||
std::cerr << "Failed to write in file : " << filePath << std::endl;
|
||||
return;
|
||||
}
|
||||
@@ -1113,7 +1355,7 @@ static void scanAndResendOfflineFiles(const std::string& dirPath)
|
||||
// 读取 JSON 文件内容
|
||||
std::ifstream inFile(file.fileName.c_str());
|
||||
if (!inFile) {
|
||||
DIY_ERRORLOG("process", "【ERROR】无法打开本地缓存的暂态事件");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM, "无法打开本地缓存的暂态事件,暂态事件重发失败");
|
||||
std::cerr << "fail to open existing file: " << file.fileName << std::endl;
|
||||
continue;
|
||||
}
|
||||
@@ -1132,14 +1374,14 @@ static void scanAndResendOfflineFiles(const std::string& dirPath)
|
||||
try {
|
||||
json j_r = json::parse(response);
|
||||
|
||||
DIY_WARNLOG("process", "【WARN】前置重发暂态事件成功");
|
||||
DIY_WARNLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM, "重发暂态事件成功");
|
||||
std::cout << "old file send success, remove it" << std::endl;
|
||||
|
||||
std::remove(file.fileName.c_str());
|
||||
} catch (...) {
|
||||
std::cout << "old file send fail (response parse failed)" << std::endl;
|
||||
|
||||
DIY_WARNLOG("process", "【WARN】前置重发暂态事件失败");
|
||||
DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM, "暂态接口响应异常,重发暂态事件失败");
|
||||
handleCommentResponse(response); // 仍然处理文本响应
|
||||
}
|
||||
} else {
|
||||
@@ -1149,61 +1391,80 @@ 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;
|
||||
|
||||
//找测点名称
|
||||
std::string mpname;
|
||||
|
||||
//找装置名称
|
||||
std::string devname;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
get_terminal_name_by_terminal_id(dev_id, devname);
|
||||
get_monitor_name_by_monitor_id(mpid, mpname);
|
||||
|
||||
const char* showName_d = devname.empty() ? dev_id.c_str() : devname.c_str();
|
||||
const char* showName_m = devname.empty() ? mpid.c_str() : mpname.c_str();
|
||||
|
||||
root["monitorId"] = mpid;
|
||||
root["devId"] = dev_id;
|
||||
root["CpuNo"] = monitor_id;
|
||||
root["amplitude"] = mag;
|
||||
root["duration"] = dur;
|
||||
root["eventType"] = dis_kind;
|
||||
|
||||
// 时间处理
|
||||
time_t start_sec = start_tm / 1000; //毫秒级取秒
|
||||
/*time_t start_sec = start_tm / 1000; //毫秒级取秒
|
||||
struct tm* time_info = localtime(&start_sec);
|
||||
char time_buf[32];
|
||||
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", time_info);
|
||||
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", time_info);*/
|
||||
time_t start_sec = start_tm / 1000;
|
||||
struct tm tm_info;
|
||||
localtime_r(&start_sec, &tm_info);
|
||||
char time_buf[32];
|
||||
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &tm_info);
|
||||
|
||||
|
||||
|
||||
std::ostringstream start_time_stream;
|
||||
start_time_stream << time_buf << "." << std::setfill('0') << std::setw(3) << (start_tm % 1000);//构造成年月日时分秒.毫秒
|
||||
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 +1473,46 @@ 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);
|
||||
// 有效响应,略过
|
||||
// =====【新增:业务失败也当异常处理】=====
|
||||
if (j_r.contains("code")
|
||||
&& j_r["code"].is_string()
|
||||
&& j_r["code"].get<std::string>() != "A0000") {
|
||||
|
||||
DIY_ERRORLOG_CODE(mpid.c_str(),2,LOG_CODE_TRANSIENT_COMM,"暂态接口业务失败(code=%s),无法上送暂态事件",j_r["code"].get<std::string>().c_str());
|
||||
|
||||
std::cout << "qvvr send fail ,store in local" << std::endl;
|
||||
std::string qvvrDir = FRONT_PATH + "/dat/qvvr/";
|
||||
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);
|
||||
}
|
||||
// =====【新增结束】=====
|
||||
|
||||
} catch (...) {
|
||||
// 响应异常,保存 json
|
||||
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件", mp_id.c_str());
|
||||
DIY_ERRORLOG_CODE(mpid.c_str(),2,LOG_CODE_JSON, "暂态接口响应异常,无法上送暂态事件");
|
||||
|
||||
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_CODE(mpid.c_str(),2,LOG_CODE_TRANSIENT_COMM,"暂态接口无响应,无法上送暂态事件");
|
||||
|
||||
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 +1533,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 +1573,119 @@ 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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string normalize_id(std::string s)
|
||||
{
|
||||
// 去首尾空白和 CRLF
|
||||
auto is_space = [](char c) {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
};
|
||||
|
||||
// trim left
|
||||
size_t start = 0;
|
||||
while (start < s.size() && is_space(s[start])) ++start;
|
||||
|
||||
// trim right
|
||||
size_t end = s.size();
|
||||
while (end > start && is_space(s[end - 1])) --end;
|
||||
|
||||
s = s.substr(start, end - start);
|
||||
|
||||
// 如有需要可统一大小写(terminal_id 一般是 hex)
|
||||
// std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool get_terminal_name_by_terminal_id(const std::string& terminal_id,
|
||||
std::string& out_terminal_name)
|
||||
{
|
||||
std::string key = normalize_id(terminal_id);
|
||||
|
||||
std::lock_guard<std::mutex> lk(ledgermtx);
|
||||
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
std::string dev_id = normalize_id(dev.terminal_id);
|
||||
if (dev_id == key) {
|
||||
out_terminal_name = dev.terminal_name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ 没找到,打印诊断日志(只在失败时)
|
||||
std::ostringstream oss;
|
||||
oss << "terminal_id not found: '" << terminal_id
|
||||
<< "' (normalized='" << key << "'), existing ids: ";
|
||||
|
||||
int cnt = 0;
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
if (cnt++ >= 5) { oss << "..."; break; } // 防止日志过长
|
||||
oss << "'" << dev.terminal_id << "' ";
|
||||
}
|
||||
|
||||
std::cerr << "[LEDGER] " << oss.str() << std::endl;
|
||||
|
||||
out_terminal_name.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool get_monitor_name_by_monitor_id(const std::string& monitor_id,
|
||||
std::string& out_monitor_name)
|
||||
{
|
||||
std::string key = normalize_id(monitor_id);
|
||||
|
||||
std::lock_guard<std::mutex> lk(ledgermtx);
|
||||
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
for (const auto& mon : dev.line) {
|
||||
std::string mon_id = normalize_id(mon.monitor_id);
|
||||
if (mon_id == key) {
|
||||
out_monitor_name = mon.monitor_name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ 诊断输出
|
||||
std::ostringstream oss;
|
||||
oss << "monitor_id not found: '" << monitor_id
|
||||
<< "' (normalized='" << key << "')";
|
||||
|
||||
std::cerr << "[LEDGER] " << oss.str() << std::endl;
|
||||
|
||||
out_monitor_name.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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,136 @@ 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; //监测点状态
|
||||
|
||||
std::string LineLogLevel; //监测点日志级别
|
||||
double PT1; // 电压变比1
|
||||
double PT2; // 电压变比2
|
||||
double CT1; // 电流变比1
|
||||
double CT2; // 电流变比2
|
||||
|
||||
};
|
||||
|
||||
//终端台账
|
||||
class update_dev
|
||||
{
|
||||
public:
|
||||
std::string guid; // ★新增:供发送回复使用
|
||||
|
||||
std::string DevLogLevel; //装置日志级别
|
||||
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<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 LineLogLevel; //监测点日志级别
|
||||
std::string timestamp; //更新时间
|
||||
std::string status; //监测点状态
|
||||
double PT1; // 电压变比1
|
||||
double PT2; // 电压变比2
|
||||
double CT1; // 电流变比1
|
||||
double CT2; // 电流变比2
|
||||
|
||||
//暂态事件
|
||||
qvvr_event qvvrevent;
|
||||
|
||||
//补招列表
|
||||
std::list<RecallMonitor> recall_list; //事件
|
||||
std::list<RecallFile> recall_list_static;//稳态文件
|
||||
|
||||
//定值list
|
||||
std::list<float> set_values;
|
||||
std::vector<DZ_TAB_STRUCT> dz_info_list; //定值信息列表
|
||||
|
||||
};
|
||||
|
||||
//终端台账
|
||||
class terminal_dev
|
||||
{
|
||||
public:
|
||||
std::string guid; //台账更新回复用
|
||||
//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 DevLogLevel; //装置日志级别
|
||||
|
||||
std::string terminal_id;
|
||||
std::string terminal_name;
|
||||
@@ -84,13 +301,13 @@ 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地址
|
||||
std::string mac; // 装置MAC地址,接口中从addr_str获取,因为ip和mac放同一位置
|
||||
|
||||
std::vector<ledger_monitor> line;
|
||||
};
|
||||
@@ -117,8 +334,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 +474,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 +554,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 +605,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 +622,7 @@ struct MsgObj {
|
||||
|
||||
// 整体
|
||||
struct FullObj {
|
||||
std::string mac;
|
||||
int Mid;
|
||||
int Did;
|
||||
int Pri;
|
||||
@@ -409,11 +635,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 +665,408 @@ 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);
|
||||
std::string getfilefromweb(const std::string& devid, const std::string& remote_path);
|
||||
//提取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,int Type);
|
||||
|
||||
//状态翻转
|
||||
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);
|
||||
bool get_monitor_name_by_monitor_id(const std::string& monitor_id,
|
||||
std::string& out_monitor_name);
|
||||
bool get_terminal_name_by_terminal_id(const std::string& terminal_id,
|
||||
std::string& out_terminal_name);
|
||||
|
||||
|
||||
//处理补招的任务
|
||||
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;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////补招文件记录
|
||||
// 记录 (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();
|
||||
|
||||
// 运行信息
|
||||
struct RunningInformation {
|
||||
std::string Time;
|
||||
std::string CpuLoad;
|
||||
std::string FreeMemory;
|
||||
std::string TotalMemory;
|
||||
std::string FreeStorage;
|
||||
std::string TotalStorage;
|
||||
std::string HardTimeSync;
|
||||
std::string SntpTimeSync;
|
||||
std::string CloudTimeSync;
|
||||
std::string SignalStrength;
|
||||
};
|
||||
|
||||
// 版本信息
|
||||
struct DeviceVersionInfo {
|
||||
std::string BaseModel; // 1
|
||||
std::string CloudProtocolVer; // 2
|
||||
std::string AppVersion; // 3
|
||||
std::string AppDate; // 4
|
||||
std::string AppChecksum; // 5
|
||||
std::string VoltageWiring; // 6
|
||||
std::string CurrentBSynthetic; // 7
|
||||
int DataStatInterval = 0; // 8
|
||||
float RatedVoltage = 0.0f; // 9
|
||||
float PTRatio = 0.0f; // 10
|
||||
float CTRatio = 0.0f; // 11
|
||||
std::string SntpIP; // 12
|
||||
int SntpPort = 0; // 13
|
||||
int SntpInterval = 0; // 14
|
||||
int WebPort = 0; // 15
|
||||
int FtpPort = 0; // 16
|
||||
int PqdifInterval = 0; // 17
|
||||
int WaveFileTypeCount = 0; // 18
|
||||
std::string SpecialVersion; // 19
|
||||
std::string DeviceModel; // 20
|
||||
int HarmonicEnergyFlag = 0; // 21
|
||||
std::string PhysicalName; // 22
|
||||
std::string WaveLDName; // 23
|
||||
int HighFreqHarmonicFlag = 0; // 24
|
||||
unsigned int CommProtocols = 0; // 51
|
||||
unsigned int TimeSyncMethods = 0;// 52
|
||||
unsigned int DeviceFunctions = 0;// 53
|
||||
};
|
||||
|
||||
void runninginfo_cache_put(const std::string& dev_id, const RunningInformation& info);
|
||||
bool runninginfo_cache_take(const std::string& dev_id, RunningInformation& out);
|
||||
void versioninfo_cache_put(const std::string& dev_id, const DeviceVersionInfo& info);
|
||||
bool versioninfo_cache_take(const std::string& dev_id, DeviceVersionInfo& out);
|
||||
|
||||
#endif
|
||||
@@ -17,19 +17,20 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "log4cplus/logger.h"
|
||||
#include "log4cplus/configurator.h"
|
||||
#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命名空间
|
||||
@@ -49,32 +50,77 @@ extern std::string subdir;
|
||||
|
||||
//日志主题
|
||||
extern std::string G_LOG_TOPIC;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const int LOGTYPE_DEFAULT = LOG_CODE_OTHER;
|
||||
|
||||
static const int LOGTYPE_WILDCARD = 999; // logtype 通配号码
|
||||
static const char* ID_WILDCARD = "all"; // id 通配字段
|
||||
|
||||
std::map<std::string, TypedLogger> logger_map;
|
||||
DebugSwitch g_debug_switch;
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
|
||||
// 原子指针:append 线程只读它,不加锁
|
||||
std::shared_ptr<LogLevelCache> g_level_cache_sp;
|
||||
///////////////////////////////////////////////////////////////
|
||||
//用来控制日志上送的结构
|
||||
struct LOGEntry {
|
||||
std::string id; //测点和装置需要的id
|
||||
std::string level; // terminal / measurepoint /process
|
||||
int logtype; // 日志类型
|
||||
int min_grade; // DEBUG / INFO / WARN / ERROR
|
||||
int countdown; // 倒计时,单位秒
|
||||
};
|
||||
|
||||
//日志上送map管理
|
||||
std::map<std::string, LOGEntry> g_log_entries;
|
||||
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
std::string build_debug_key(const std::string& id, const std::string& level, int logtype);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
#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) {
|
||||
size_t pos = 0;
|
||||
bool create_directory_recursive(const std::string& path)
|
||||
{
|
||||
if (path.empty()) return false;
|
||||
|
||||
std::string current;
|
||||
while (pos != std::string::npos) {
|
||||
pos = path.find('/', pos + 1);
|
||||
current = path.substr(0, pos);
|
||||
if (!current.empty() && access(current.c_str(), F_OK) != 0) {
|
||||
if (mkdir(current.c_str(), 0755) != 0) {
|
||||
perror(("mkdir failed: " + current).c_str());
|
||||
return false;
|
||||
current.reserve(path.size());
|
||||
|
||||
for (size_t i = 0; i < path.size(); ++i) {
|
||||
current += path[i];
|
||||
|
||||
// 遇到 '/' 或最后一个字符时创建
|
||||
if (path[i] == '/' || i == path.size() - 1) {
|
||||
if (current.empty()) continue;
|
||||
|
||||
// 去掉末尾 '/'
|
||||
std::string dir = current;
|
||||
if (dir.back() == '/' && dir.size() > 1) {
|
||||
dir.pop_back();
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(dir.c_str(), &st) != 0) {
|
||||
if (mkdir(dir.c_str(), 0755) != 0) {
|
||||
// 如果已经存在(并发场景),忽略
|
||||
if (errno != EEXIST) {
|
||||
perror(("mkdir failed: " + dir).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +144,26 @@ std::string get_level_str(int level) {
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char* loglevel_to_str(int lv) {
|
||||
switch (lv) {
|
||||
case DEBUG_LOG_LEVEL: return "DEBUG";
|
||||
case INFO_LOG_LEVEL: return "NORMAL";
|
||||
case WARN_LOG_LEVEL: return "WARN";
|
||||
case ERROR_LOG_LEVEL: return "ERROR";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static int str_to_loglevel(const std::string& s, int default_level = WARN_LOG_LEVEL)
|
||||
{
|
||||
if (s == "DEBUG") return DEBUG_LOG_LEVEL;
|
||||
if (s == "NORMAL") return INFO_LOG_LEVEL; // NORMAL 当 INFO
|
||||
if (s == "INFO") return INFO_LOG_LEVEL;
|
||||
if (s == "WARN") return WARN_LOG_LEVEL;
|
||||
if (s == "ERROR") return ERROR_LOG_LEVEL;
|
||||
return default_level; // 空/非法都兜底
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
TypedLogger::TypedLogger() {}
|
||||
TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), logtype(t) {}
|
||||
@@ -125,18 +191,160 @@ bool DebugSwitch::match(const std::string& logger_name, int level, int logtype)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
static LogLevelCache* build_cache_unlocked()
|
||||
{
|
||||
LogLevelCache* nc = new LogLevelCache;
|
||||
nc->term_min.reserve(terminal_devlist.size());
|
||||
|
||||
std::map<std::string, TypedLogger> logger_map;
|
||||
DebugSwitch g_debug_switch;
|
||||
for (const terminal_dev& t : terminal_devlist) {
|
||||
const int t_lv = str_to_loglevel(t.DevLogLevel, WARN_LOG_LEVEL);
|
||||
|
||||
if (!t.terminal_id.empty())
|
||||
nc->term_min[t.terminal_id] = t_lv;
|
||||
|
||||
for (const ledger_monitor& m : t.line) {
|
||||
if (m.monitor_id.empty()) continue;
|
||||
|
||||
// 监测点优先;空/非法自动兜底到终端 t_lv
|
||||
const int m_lv = str_to_loglevel(m.LineLogLevel, t_lv);
|
||||
nc->mp_min[m.monitor_id] = m_lv;
|
||||
}
|
||||
}
|
||||
return nc;
|
||||
}
|
||||
|
||||
void refresh_log_level_cache_locked()
|
||||
{
|
||||
std::shared_ptr<LogLevelCache> nc(build_cache_unlocked());
|
||||
std::atomic_store_explicit(&g_level_cache_sp, nc, std::memory_order_release);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SendAppender : public Appender {
|
||||
private:
|
||||
struct RateState {
|
||||
uint64_t hit_count = 0; // 同一条日志累计命中次数
|
||||
std::chrono::steady_clock::time_point last_emit =
|
||||
std::chrono::steady_clock::time_point::min();
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string, RateState> s_rate_map; //频率map
|
||||
static std::mutex s_rate_mutex;
|
||||
|
||||
// 定义“同一条日志”的规则:logger + level + code + msg //原来只区分了日志登记名和等级,现在具体到每一条日志
|
||||
static std::string make_key(const std::string& logger_name, int level, int code, const std::string& msg) {
|
||||
std::ostringstream oss;
|
||||
oss << logger_name << "|" << level << "|" << code << "|" << msg;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// 前 3 次:1 秒一次;第 3 次起:300 秒一次,一小时恢复
|
||||
static bool should_emit(const std::string& key) {
|
||||
using namespace std::chrono;
|
||||
const auto now = steady_clock::now();
|
||||
|
||||
std::lock_guard<std::mutex> lk(s_rate_mutex);
|
||||
RateState& st = s_rate_map[key];
|
||||
|
||||
// 超过恢复时间,重置计数
|
||||
const int RESET_SEC = 3600; // 一小时
|
||||
if (st.last_emit != steady_clock::time_point::min()) {
|
||||
auto idle = duration_cast<seconds>(now - st.last_emit).count();
|
||||
if (idle >= RESET_SEC) {
|
||||
st.hit_count = 0; // 恢复为“新日志”
|
||||
}
|
||||
}
|
||||
|
||||
st.hit_count++;
|
||||
|
||||
const int period_sec = (st.hit_count > 3) ? 300 : 1;
|
||||
|
||||
if (st.last_emit == steady_clock::time_point::min()) {
|
||||
st.last_emit = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
|
||||
if (elapsed >= period_sec) {
|
||||
st.last_emit = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool find_entry_allow(const std::string& key, int level_val) { //通配方式查找
|
||||
std::map<std::string, LOGEntry>::iterator it = g_log_entries.find(key);
|
||||
if (it == g_log_entries.end() || it->second.countdown <= 0) return false;
|
||||
return level_val >= it->second.min_grade;
|
||||
}
|
||||
|
||||
static bool allow_low_level_send(const std::string& id,
|
||||
const std::string& level_str,//层级
|
||||
int logtype,
|
||||
int level_val) {//告警等级
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
|
||||
// 1) 精确匹配:id + level + logtype //这个id指定日志种类指定级别的日志
|
||||
if (find_entry_allow(build_debug_key(id, level_str, logtype), level_val)) {
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) logtype 通配:id + level + -1 //这个id指定日志级别的所有日志
|
||||
if (find_entry_allow(build_debug_key(id, level_str, LOGTYPE_WILDCARD), level_val)) {
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) id 通配:* + level + logtype //这个id的指定级别的日志
|
||||
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, logtype), level_val)) {
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4) 双通配:* + level + -1 //所有指定级别的日志,即根据台账的等级来上送所有日志
|
||||
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, LOGTYPE_WILDCARD), level_val)) {
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////添加台账日志控制
|
||||
|
||||
static int get_min_send_level_cached(const std::string& level_str, const std::string& logger_name)
|
||||
{
|
||||
const int DEFAULT_LEVEL = WARN_LOG_LEVEL;
|
||||
if (level_str == "process") return DEFAULT_LEVEL;
|
||||
|
||||
const std::string id = extract_logger_id(logger_name);
|
||||
if (id.empty()) return DEFAULT_LEVEL;
|
||||
|
||||
std::shared_ptr<LogLevelCache> c =
|
||||
std::atomic_load_explicit(&g_level_cache_sp, std::memory_order_acquire);
|
||||
if (!c) return DEFAULT_LEVEL;
|
||||
|
||||
if (level_str == "terminal") {
|
||||
auto it = c->term_min.find(id);
|
||||
return (it != c->term_min.end()) ? it->second : DEFAULT_LEVEL;
|
||||
}
|
||||
if (level_str == "measurepoint") {
|
||||
auto it = c->mp_min.find(id);
|
||||
return (it != c->mp_min.end()) ? it->second : DEFAULT_LEVEL;
|
||||
}
|
||||
return DEFAULT_LEVEL;
|
||||
}
|
||||
|
||||
protected:
|
||||
void append(const spi::InternalLoggingEvent& event) {
|
||||
void append(const spi::InternalLoggingEvent& event) override {
|
||||
std::string logger_name = event.getLoggerName();
|
||||
int level = event.getLogLevel();
|
||||
std::string msg = event.getMessage();
|
||||
|
||||
int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA;
|
||||
std::string level_str;
|
||||
if (logger_name.find("process") == 0)
|
||||
level_str = "process";
|
||||
@@ -145,70 +353,109 @@ protected:
|
||||
else
|
||||
level_str = "terminal";
|
||||
|
||||
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
|
||||
<< "\",\"grade\":\"" << get_level_str(level)
|
||||
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
|
||||
<< "\",\"frontType\":\"" << "cloudfront"
|
||||
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
|
||||
// TLS code
|
||||
int code = g_log_code_tls;
|
||||
|
||||
std::string jsonString = oss.str();
|
||||
const int safe_logtype = code; // 使用 code 作为 logtype
|
||||
|
||||
queue_data_t connect_info;
|
||||
connect_info.strTopic = G_LOG_TOPIC;
|
||||
connect_info.strText = jsonString;
|
||||
bool allow_send = false;
|
||||
|
||||
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
|
||||
queue_data_list.push_back(connect_info);
|
||||
int min_send_level = get_min_send_level_cached(level_str, logger_name);
|
||||
|
||||
std::cout << "[LOG] logger: " << logger_name
|
||||
<< ", level_str: " << level_str
|
||||
<< ", level: " << level
|
||||
<< ", min_send_level: " << min_send_level << std::endl;
|
||||
|
||||
// ① 高于“台账阈值”的日志:直接上送
|
||||
if (level >= min_send_level) {
|
||||
allow_send = true;
|
||||
} else {
|
||||
// NORMAL/DEBUG 默认不上送,必须命令打开
|
||||
std::string ctrl_level = level_str; // "process" / "terminal" / "measurepoint"
|
||||
|
||||
std::string ctrl_id;
|
||||
if (ctrl_level == "process") {
|
||||
ctrl_id = "process"; // process 用固定 id
|
||||
} else {
|
||||
ctrl_id = extract_logger_id(logger_name); // terminal.<id> / monitor.<id>
|
||||
if (ctrl_id.empty()) {
|
||||
// 没解析出 id,就不给低等级上送(避免误发)
|
||||
allow_send = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctrl_id.empty()) {
|
||||
allow_send = allow_low_level_send(ctrl_id, ctrl_level, safe_logtype, level);
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow_send) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ★新增:限频判断(同一条日志前 5 次 1 秒一次;之后 300 秒一次)
|
||||
const std::string key = make_key(logger_name, level, code, msg);
|
||||
if (!should_emit(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
// ★建议:code 用数字(不是字符串)
|
||||
<< "\",\"code\":" << code
|
||||
<< ",\"log\":\"" << escape_json(msg) << "\"}";
|
||||
|
||||
queue_data_t connect_info;
|
||||
connect_info.strTopic = G_LOG_TOPIC;
|
||||
connect_info.strText = oss.str();
|
||||
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);
|
||||
}
|
||||
|
||||
std::string escape_json(const std::string& input) {
|
||||
std::ostringstream ss;
|
||||
for (unsigned int i = 0; i < input.size(); ++i) {
|
||||
for (size_t i = 0; i < input.size(); ++i) {
|
||||
switch (input[i]) {
|
||||
case '\\': ss << "\\\\"; break;
|
||||
case '"': ss << "\\\""; break;
|
||||
case '\n': ss << "\\n"; break;
|
||||
case '\r': ss << "\\r"; break;
|
||||
case '\t': ss << "\\t"; break;
|
||||
default: ss << input[i]; break;
|
||||
case '"': ss << "\\\""; break;
|
||||
case '\n': ss << "\\n"; break;
|
||||
case '\r': ss << "\\r"; break;
|
||||
case '\t': ss << "\\t"; break;
|
||||
default: ss << input[i]; break;
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual void close() {
|
||||
void close() override {
|
||||
// 可空实现
|
||||
}
|
||||
|
||||
public:
|
||||
SendAppender() {}
|
||||
virtual ~SendAppender() {
|
||||
destructorImpl(); // 重要!释放 log4cplus 基类资源
|
||||
destructorImpl();
|
||||
}
|
||||
};
|
||||
|
||||
//用来控制日志上送的结构
|
||||
struct LOGEntry {
|
||||
std::string id;
|
||||
std::string level; // terminal / measurepoint
|
||||
int logtype; // com / data
|
||||
int min_grade;
|
||||
int countdown;
|
||||
};
|
||||
|
||||
//日志上送map管理
|
||||
std::map<std::string, LOGEntry> g_log_entries;
|
||||
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
//用来控制日志上送的静态变量定义
|
||||
std::unordered_map<std::string, SendAppender::RateState> SendAppender::s_rate_map;
|
||||
std::mutex SendAppender::s_rate_mutex;
|
||||
|
||||
// 生成唯一 key
|
||||
std::string build_debug_key(const std::string& id, const std::string& level, int logtype) {
|
||||
return id + "|" + level + "|" + (logtype == 1 ? "COM" : "DATA");
|
||||
std::ostringstream oss;
|
||||
oss << id << "|" << level << "|" << logtype;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// 外部线程中调用:每秒更新所有倒计时,0 则删除
|
||||
@@ -229,20 +476,19 @@ void update_log_entries_countdown() {
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
}
|
||||
|
||||
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str) {
|
||||
if (level != "terminal" && level != "measurepoint") return;
|
||||
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, int logtype) {
|
||||
if (level != "terminal" && level != "measurepoint" && level != "process") return;
|
||||
|
||||
int type = (logtype_str == "com") ? LOGTYPE_COM : LOGTYPE_DATA;
|
||||
int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL;
|
||||
|
||||
std::string key = build_debug_key(id, level, type);
|
||||
std::string key = build_debug_key(id, level, logtype);
|
||||
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
|
||||
LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有
|
||||
entry.id = id;
|
||||
entry.level = level;
|
||||
entry.logtype = type;
|
||||
entry.logtype = logtype;
|
||||
entry.min_grade = grade_level;
|
||||
entry.countdown = 60; // 重置倒计时
|
||||
|
||||
@@ -281,7 +527,7 @@ log4cplus::Logger init_logger(const std::string& full_name,
|
||||
//进程的日志
|
||||
void init_logger_process() {
|
||||
std::string base_dir = FRONT_PATH + "/" + subdir + "/processNo" + std::to_string(g_front_seg_index) + "/log";
|
||||
logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DATA);
|
||||
logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DEFAULT);
|
||||
std::cout << "process log init ok" << std::endl;
|
||||
}
|
||||
|
||||
@@ -307,41 +553,35 @@ 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 日志文件中
|
||||
// 所有终端日志写到同一个 device 日志文件中
|
||||
std::string file_path_t = device_dir + "/" + dev_id + ".log";
|
||||
|
||||
// 共用一个 appender 实例
|
||||
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_DEFAULT);
|
||||
|
||||
DIY_WARNLOG(device_key_d.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 +590,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_DEFAULT);
|
||||
|
||||
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.monitor_id.c_str());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -382,8 +620,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 +629,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_DEFAULT);
|
||||
|
||||
DIY_WARNLOG(device_key_d.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 +652,11 @@ 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_DEFAULT);
|
||||
|
||||
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕",
|
||||
monitor.monitor_name.c_str(), monitor.monitor_id.c_str());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,17 +670,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 +682,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,7 +706,11 @@ extern "C" {
|
||||
// 公共函数
|
||||
void log4_log_with_level(const char* key, const char* msg, int level) {
|
||||
std::map<std::string, TypedLogger>::iterator it = logger_map.find(key);
|
||||
if (it == logger_map.end()) return;
|
||||
if (it == logger_map.end()) {
|
||||
std::cout << "[LOG][MISS] logger not found, key="
|
||||
<< (key ? key : "NULL") << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Logger logger = it->second.logger;
|
||||
switch (level) {
|
||||
@@ -504,22 +728,29 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -22,9 +32,22 @@
|
||||
|
||||
#include "appender.h"
|
||||
|
||||
#define LOGTYPE_COM 1
|
||||
#define LOGTYPE_DATA 2
|
||||
/////////////////////////////////////////////入参验证
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define PRINTF_LIKE(fmt_index, first_arg) __attribute__((format(printf, fmt_index, first_arg)))
|
||||
#else
|
||||
# define PRINTF_LIKE(fmt_index, first_arg)
|
||||
#endif
|
||||
/////////////////////////////////////////
|
||||
|
||||
struct LogLevelCache { //日志等级缓存
|
||||
// terminal_id -> min_level
|
||||
std::unordered_map<std::string, int> term_min;
|
||||
// monitor_id -> min_level
|
||||
std::unordered_map<std::string, int> mp_min;
|
||||
};
|
||||
|
||||
////////////////////////////////////
|
||||
struct TypedLogger {
|
||||
log4cplus::Logger logger;
|
||||
int logtype;
|
||||
@@ -51,11 +74,10 @@ 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);
|
||||
|
||||
|
||||
//std::string get_front_type_from_subdir();
|
||||
extern void send_reply_to_queue(const std::string& guid, const int code, const std::string& result);
|
||||
|
||||
extern std::shared_ptr<LogLevelCache> g_level_cache_sp;
|
||||
const char* loglevel_to_str(int lv);
|
||||
|
||||
// 不带 Appender 的版本
|
||||
log4cplus::Logger init_logger(const std::string& full_name,
|
||||
@@ -68,11 +90,15 @@ log4cplus::Logger init_logger(const std::string& full_name,
|
||||
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 process_log_command(const std::string& id, const std::string& level, const std::string& grade, int logtype);
|
||||
|
||||
|
||||
void update_log_entries_countdown();
|
||||
|
||||
void refresh_log_level_cache_locked();
|
||||
|
||||
bool create_directory_recursive(const std::string& path);
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
void remove_loggers_by_terminal_id(const std::string& terminal_id_cstr);
|
||||
@@ -84,23 +110,105 @@ 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 format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
|
||||
//带验证
|
||||
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) PRINTF_LIKE(3,4);
|
||||
|
||||
void send_reply_to_queue_c(const char* guid, const char* step, const char* result);
|
||||
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
|
||||
// ====================== ★新增:线程局部变量透传 code ======================
|
||||
// 说明:使用编译器的 TLS(__thread)保存当前日志的 code 值。
|
||||
// 在每次打日志前写入,打完后恢复,Appender 读取该值写入 JSON。
|
||||
|
||||
//宏定义
|
||||
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
|
||||
do { \
|
||||
char buf[256]; \
|
||||
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
|
||||
LEVEL_FUNC(KEY, buf); \
|
||||
|
||||
// ====================== ★新增结束 ======================
|
||||
|
||||
typedef enum LogCode {
|
||||
LOG_CODE_WIRETYPE = 96, /* 接线类型 */
|
||||
LOG_CODE_CONFIG = 97, /* 配置相关 */
|
||||
LOG_CODE_JSON = 98, /* JSON结构 */
|
||||
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_FILE = 302, /* 文件上传 */
|
||||
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_CLOUD = 406, /* 云前置控制 */
|
||||
|
||||
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, "监测点:%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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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() {
|
||||
// 获取当前工作目录
|
||||
@@ -206,7 +209,7 @@ std::string get_parent_directory() {
|
||||
|
||||
//启动进程日志
|
||||
init_logger_process();
|
||||
DIY_WARNLOG("process","【WARN】前置的%d号进程 进程级日志初始化完毕", g_front_seg_index);
|
||||
|
||||
|
||||
//读取台账
|
||||
parse_device_cfg_web();
|
||||
@@ -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();
|
||||
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,25 @@ 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);
|
||||
|
||||
subscriptions.emplace_back(G_MQCONSUMER_TOPIC_CLOUD, FRONT_INST, cloudMessageCallback);
|
||||
|
||||
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 +585,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 +625,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 +644,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 +709,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 +795,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
@@ -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,14 @@ 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 Cloud_Reply_Topic;
|
||||
extern std::string Cloud_Reply_Tag;
|
||||
extern std::string Cloud_Reply_Key;
|
||||
|
||||
extern std::string G_LOG_TOPIC;
|
||||
extern std::string G_LOG_TAG;
|
||||
extern std::string G_LOG_KEY;
|
||||
@@ -328,6 +340,7 @@ rocketmq::ConsumeStatus myMessageCallbackrtdata(const rocketmq::MQMessageExt& ms
|
||||
rocketmq::ConsumeStatus myMessageCallbackupdate(const rocketmq::MQMessageExt& msg);
|
||||
rocketmq::ConsumeStatus myMessageCallbackset(const rocketmq::MQMessageExt& msg);
|
||||
rocketmq::ConsumeStatus myMessageCallbacklog(const rocketmq::MQMessageExt& msg);
|
||||
rocketmq::ConsumeStatus cloudMessageCallback(const rocketmq::MQMessageExt& msg);
|
||||
|
||||
void send_heartbeat_to_queue(const std::string& status);
|
||||
|
||||
@@ -336,9 +349,11 @@ 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);
|
||||
|
||||
void rocketmq_test_ud_batch(Front* front, int processNo, int start, int count);
|
||||
|
||||
#endif // _ROCKETMQ_CLIENT_WRAPPER_H_
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -293,7 +299,11 @@ extern bool normalOutputEnabled;
|
||||
"Available commands:\r\n"
|
||||
"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"
|
||||
"TESTLEDGER <processNo>,<start>,<count> - Batch send UD ledger updates (e.g. TESTLEDGER 3,1,50)\r\n"
|
||||
"LOG=<bool> - Set the LOG\r\n"
|
||||
"LOGLIST - List all registered loggers\r\n"
|
||||
"MAX=<int> - Set the MAX_ITEMS\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"
|
||||
@@ -307,24 +317,103 @@ extern bool normalOutputEnabled;
|
||||
"exit - Exit the shell\r\n"
|
||||
"help - Show this help message\r\n";
|
||||
sendStr(clientFD, "\r\x1B[K" + helpText);
|
||||
} else if (cmd.find("TESTLEDGER") == 0) {
|
||||
// 支持:TESTLEDGER 3,1,50(中间允许空格)
|
||||
size_t pos = cmd.find(' ');
|
||||
if (pos == std::string::npos || pos + 1 >= cmd.size()) {
|
||||
sendStr(clientFD, "\r\x1B[KUsage: TESTLEDGER <processNo>,<start>,<count>\r\n");
|
||||
} else {
|
||||
std::string args = cmd.substr(pos + 1);
|
||||
|
||||
// 去掉可能的空格
|
||||
for (size_t i = 0; i < args.size(); ) {
|
||||
if (args[i] == ' ' || args[i] == '\t' || args[i] == '\r' || args[i] == '\n')
|
||||
args.erase(i, 1);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
// 解析三个整数
|
||||
int processNo = 0, start = 0, count = 0;
|
||||
size_t c1 = args.find(',');
|
||||
size_t c2 = (c1 == std::string::npos) ? std::string::npos : args.find(',', c1 + 1);
|
||||
|
||||
if (c1 == std::string::npos || c2 == std::string::npos) {
|
||||
sendStr(clientFD, "\r\x1B[KUsage: TESTLEDGER <processNo>,<start>,<count> (e.g. TESTLEDGER 3,1,50)\r\n");
|
||||
} else {
|
||||
processNo = std::atoi(args.substr(0, c1).c_str());
|
||||
start = std::atoi(args.substr(c1 + 1, c2 - (c1 + 1)).c_str());
|
||||
count = std::atoi(args.substr(c2 + 1).c_str());
|
||||
|
||||
if (processNo <= 0 || start <= 0 || count <= 0) {
|
||||
sendStr(clientFD, "\r\x1B[KInvalid args. Need >0. Example: TESTLEDGER 3,1,50\r\n");
|
||||
} else {
|
||||
// 调用批量发送(每条间隔1秒的逻辑在函数内部)
|
||||
rocketmq_test_ud_batch(m_front, processNo, start, count);
|
||||
sendStr(clientFD, "\r\x1B[KExecuted TESTLEDGER batch send\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cmd.find("viewlog") == 0) {
|
||||
showinshellflag = true;
|
||||
handleViewLogCommand(cmd, clientFD);
|
||||
} else if (cmd.find("G_TEST_NUM=") == 0) {
|
||||
int num = std::atoi(cmd.substr(9).c_str());
|
||||
int num = std::atoi(cmd.substr(11).c_str());
|
||||
setTestNum(num);
|
||||
sendStr(clientFD, "\r\x1B[KTEST_NUM updated\r\n");
|
||||
} else if (cmd.find("G_TEST_TYPE=") == 0) {
|
||||
int type = std::atoi(cmd.substr(10).c_str());
|
||||
int type = std::atoi(cmd.substr(12).c_str());
|
||||
setTestType(type);
|
||||
sendStr(clientFD, "\r\x1B[KTEST_TYPE updated\r\n");
|
||||
} else if (cmd.find("LOG=") == 0) {
|
||||
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 == "LOGLIST" || cmd == "loglist") {
|
||||
std::ostringstream oss;
|
||||
|
||||
// 1️⃣ 打印 logger_map
|
||||
oss << "\r\x1B[KRegistered loggers (" << logger_map.size() << "):\r\n";
|
||||
for (const auto& it : logger_map) {
|
||||
oss << " " << it.first << "\r\n";
|
||||
}
|
||||
|
||||
// 2️⃣ 打印 LogLevelCache(原子只读)
|
||||
std::shared_ptr<LogLevelCache> cache =
|
||||
std::atomic_load_explicit(&g_level_cache_sp, std::memory_order_acquire);
|
||||
|
||||
if (!cache) {
|
||||
oss << "\r\x1B[K[LogLevelCache] <EMPTY>\r\n";
|
||||
} else {
|
||||
oss << "\r\x1B[K[LogLevelCache] terminal levels ("
|
||||
<< cache->term_min.size() << "):\r\n";
|
||||
|
||||
for (const auto& kv : cache->term_min) {
|
||||
oss << " terminal." << kv.first
|
||||
<< " -> " << loglevel_to_str(kv.second) << "\r\n";
|
||||
}
|
||||
|
||||
oss << "\r\x1B[K[LogLevelCache] monitor levels ("
|
||||
<< cache->mp_min.size() << "):\r\n";
|
||||
|
||||
for (const auto& kv : cache->mp_min) {
|
||||
oss << " monitor." << kv.first
|
||||
<< " -> " << loglevel_to_str(kv.second) << "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
sendStr(clientFD, oss.str());
|
||||
}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 +494,340 @@ 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";
|
||||
os << "\r\x1B[K|-- loglevel : " << dev.DevLogLevel << "\n";
|
||||
|
||||
// ========================= 终端级 · 内部定值 =========================
|
||||
// internal_values(ushort 列表)与 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_list(NameFixValue 描述,和 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 |-- loglevel : " << ld.LineLogLevel << "\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 +927,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 +986,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 ---
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
80
LFtid1056/config/front.cfg
Normal file
80
LFtid1056/config/front.cfg
Normal 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
|
||||
1
LFtid1056/dat/095a84f23ec7e283a9ffe8e182708f04.xml
Normal file
1
LFtid1056/dat/095a84f23ec7e283a9ffe8e182708f04.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/0b53c730f88d4b69a73f239475fc3876.xml
Normal file
1
LFtid1056/dat/0b53c730f88d4b69a73f239475fc3876.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/0c6e1be36f19fb4d809836ed96f7796f.xml
Normal file
1
LFtid1056/dat/0c6e1be36f19fb4d809836ed96f7796f.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/0fc2e86ded1ed4cbbda8830acd331314.xml
Normal file
1
LFtid1056/dat/0fc2e86ded1ed4cbbda8830acd331314.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/112e261cb8e804600104ffebfd9cbefd.xml
Normal file
1
LFtid1056/dat/112e261cb8e804600104ffebfd9cbefd.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/134e25eb59a22cc8394ff3bc1dde554c.xml
Normal file
1
LFtid1056/dat/134e25eb59a22cc8394ff3bc1dde554c.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/148f24a2664fa054ede4f686fd984292.xml
Normal file
1
LFtid1056/dat/148f24a2664fa054ede4f686fd984292.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/14e2078291f3a2f800480a6ca699fbcd.xml
Normal file
1
LFtid1056/dat/14e2078291f3a2f800480a6ca699fbcd.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/1654a86f7cb25a322573bbf3571b1765.xml
Normal file
1
LFtid1056/dat/1654a86f7cb25a322573bbf3571b1765.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/180735bfe2c59f4d8e1d85bd2a1984ef.xml
Normal file
1
LFtid1056/dat/180735bfe2c59f4d8e1d85bd2a1984ef.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/1f2c42ee0e8d689005b3f58967054e5c.xml
Normal file
1
LFtid1056/dat/1f2c42ee0e8d689005b3f58967054e5c.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/1ff4038a4574dbc52ccf005bef20041b.xml
Normal file
1
LFtid1056/dat/1ff4038a4574dbc52ccf005bef20041b.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/2bd3d80c86e078d77f8482e48c3b3f99.xml
Normal file
1
LFtid1056/dat/2bd3d80c86e078d77f8482e48c3b3f99.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/35d62f0ad688a14583290a0ba0fc2b42.xml
Normal file
1
LFtid1056/dat/35d62f0ad688a14583290a0ba0fc2b42.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/38c2ec0e305b07c04674ddbb4c972a2a.xml
Normal file
1
LFtid1056/dat/38c2ec0e305b07c04674ddbb4c972a2a.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/393c172bcd297f8cd68a41f202f78b2f.xml
Normal file
1
LFtid1056/dat/393c172bcd297f8cd68a41f202f78b2f.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/3ef998435d692c62f58a8dc26dec99cc.xml
Normal file
1
LFtid1056/dat/3ef998435d692c62f58a8dc26dec99cc.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/49dd3d79e7cdd27597ba2526858c372e.xml
Normal file
1
LFtid1056/dat/49dd3d79e7cdd27597ba2526858c372e.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/4b1e55fba360f30a5e91bcf6fae63d82.xml
Normal file
1
LFtid1056/dat/4b1e55fba360f30a5e91bcf6fae63d82.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/4fd8f3fb39c8333e525aad2cfed8d4ba.xml
Normal file
1
LFtid1056/dat/4fd8f3fb39c8333e525aad2cfed8d4ba.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/52f48442032e85d8257b9e6e409ae727.xml
Normal file
1
LFtid1056/dat/52f48442032e85d8257b9e6e409ae727.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/5c26d1a34a996a64645334cf36fc65cd.xml
Normal file
1
LFtid1056/dat/5c26d1a34a996a64645334cf36fc65cd.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/5d623f8d16d2f66473c4ae04661fc995.xml
Normal file
1
LFtid1056/dat/5d623f8d16d2f66473c4ae04661fc995.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/5ff7ad05e7bcd2cc2f540b5e06849776.xml
Normal file
1
LFtid1056/dat/5ff7ad05e7bcd2cc2f540b5e06849776.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/62f1441d04b665b1b598974b411d45eb.xml
Normal file
1
LFtid1056/dat/62f1441d04b665b1b598974b411d45eb.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/63a5b90766f86a484c84f22c9ce29e44.xml
Normal file
1
LFtid1056/dat/63a5b90766f86a484c84f22c9ce29e44.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/63cb5f7437e1922be7f0b606b12679ce.xml
Normal file
1
LFtid1056/dat/63cb5f7437e1922be7f0b606b12679ce.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/643f3997e9c31173d8c93cc38c1d5129.xml
Normal file
1
LFtid1056/dat/643f3997e9c31173d8c93cc38c1d5129.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/64992cafdb7bf7e94b0ae3556c6dd2b3.xml
Normal file
1
LFtid1056/dat/64992cafdb7bf7e94b0ae3556c6dd2b3.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/669466052823ae6ce09cd6bc575176be.xml
Normal file
1
LFtid1056/dat/669466052823ae6ce09cd6bc575176be.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/66aac8de119b48126ae0fa3fd28b8499.xml
Normal file
1
LFtid1056/dat/66aac8de119b48126ae0fa3fd28b8499.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/68d618ae6a52e34483c90bb7642ef353.xml
Normal file
1
LFtid1056/dat/68d618ae6a52e34483c90bb7642ef353.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/69d6bebce232d3949d9f1d75c66d90c4.xml
Normal file
1
LFtid1056/dat/69d6bebce232d3949d9f1d75c66d90c4.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/6a9b0cae90ca3ea6b750f1117e93816b.xml
Normal file
1
LFtid1056/dat/6a9b0cae90ca3ea6b750f1117e93816b.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/6cd6498c079396e9d42d6764bdad21ab.xml
Normal file
1
LFtid1056/dat/6cd6498c079396e9d42d6764bdad21ab.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/74a0fe58192a690f2037dab8bcff5e25.xml
Normal file
1
LFtid1056/dat/74a0fe58192a690f2037dab8bcff5e25.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/7677814fc1e2bc194ca2d82a62f3dd1d.xml
Normal file
1
LFtid1056/dat/7677814fc1e2bc194ca2d82a62f3dd1d.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/7a0fb4cc2013497797dc46d50526d1b1.xml
Normal file
1
LFtid1056/dat/7a0fb4cc2013497797dc46d50526d1b1.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/7be60bf2c9265b2f91ff11a21c62edbb.xml
Normal file
1
LFtid1056/dat/7be60bf2c9265b2f91ff11a21c62edbb.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/824cf5433d2d8c82eaf816a28f9a232d.xml
Normal file
1
LFtid1056/dat/824cf5433d2d8c82eaf816a28f9a232d.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/82c0ffe9b6a6e54ff6768aa4b151759d.xml
Normal file
1
LFtid1056/dat/82c0ffe9b6a6e54ff6768aa4b151759d.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/895f951309513397852cafbe846c9298.xml
Normal file
1
LFtid1056/dat/895f951309513397852cafbe846c9298.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/8c84b8c0ae99b17afa0c79c0e2e848e3.xml
Normal file
1
LFtid1056/dat/8c84b8c0ae99b17afa0c79c0e2e848e3.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/8dd12600976ac6c95e18c5980400eee3.xml
Normal file
1
LFtid1056/dat/8dd12600976ac6c95e18c5980400eee3.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/8e051a07f6fc2ff03487bc87cb3e4d91.xml
Normal file
1
LFtid1056/dat/8e051a07f6fc2ff03487bc87cb3e4d91.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/942b70650cb8d099401c01446d3c08de.xml
Normal file
1
LFtid1056/dat/942b70650cb8d099401c01446d3c08de.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/950c2c11da36897552766fd7a02af6d5.xml
Normal file
1
LFtid1056/dat/950c2c11da36897552766fd7a02af6d5.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/9667fe63920c038605911d88b0f9e9a2.xml
Normal file
1
LFtid1056/dat/9667fe63920c038605911d88b0f9e9a2.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/a25d58d7780a51de20223c7ffffa3219.xml
Normal file
1
LFtid1056/dat/a25d58d7780a51de20223c7ffffa3219.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/ab5204b5e2222712f70233741ff7bfb0.xml
Normal file
1
LFtid1056/dat/ab5204b5e2222712f70233741ff7bfb0.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/b3f054b07c0cd6eae366c3f7c0178dc8.xml
Normal file
1
LFtid1056/dat/b3f054b07c0cd6eae366c3f7c0178dc8.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/b59349bf7d426611102acd7ef65f8861.xml
Normal file
1
LFtid1056/dat/b59349bf7d426611102acd7ef65f8861.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/ba674fe68e95b86478683610ad7790df.xml
Normal file
1
LFtid1056/dat/ba674fe68e95b86478683610ad7790df.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/c1c0d4bbf50a11e76c378ce5ac116f5f.xml
Normal file
1
LFtid1056/dat/c1c0d4bbf50a11e76c378ce5ac116f5f.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/c6ec71e6dcd9e9c2aae7eb5eddd59099.xml
Normal file
1
LFtid1056/dat/c6ec71e6dcd9e9c2aae7eb5eddd59099.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/c8a4b43c08da8a44b3d08ee730dc5d56.xml
Normal file
1
LFtid1056/dat/c8a4b43c08da8a44b3d08ee730dc5d56.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/c9a030d97e42865d4fc24b4424e87ad0.xml
Normal file
1
LFtid1056/dat/c9a030d97e42865d4fc24b4424e87ad0.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/ca16b843d971cb760168c797e24e81f9.xml
Normal file
1
LFtid1056/dat/ca16b843d971cb760168c797e24e81f9.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/ca42aa3651b65244924374397fbffa80.xml
Normal file
1
LFtid1056/dat/ca42aa3651b65244924374397fbffa80.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/caf9a220fe671f9e82d282c88edad459.xml
Normal file
1
LFtid1056/dat/caf9a220fe671f9e82d282c88edad459.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/cb5275b81d36cf6fc7069fafa121d734.xml
Normal file
1
LFtid1056/dat/cb5275b81d36cf6fc7069fafa121d734.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/d2526e08196f7dfdc4ca81c67264c0c1.xml
Normal file
1
LFtid1056/dat/d2526e08196f7dfdc4ca81c67264c0c1.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/dab107086ada2504be4f40a158858838.xml
Normal file
1
LFtid1056/dat/dab107086ada2504be4f40a158858838.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/dab72e86a7b30990285976169c0dfb3f.xml
Normal file
1
LFtid1056/dat/dab72e86a7b30990285976169c0dfb3f.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/dc0a7739bdeb18d6c82b493bcd49d5d3.xml
Normal file
1
LFtid1056/dat/dc0a7739bdeb18d6c82b493bcd49d5d3.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/dc9bef9ba55574c5e7d1d3c78afa2c45.xml
Normal file
1
LFtid1056/dat/dc9bef9ba55574c5e7d1d3c78afa2c45.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/deba4e29af5efbf756557661ec254ec3.xml
Normal file
1
LFtid1056/dat/deba4e29af5efbf756557661ec254ec3.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/e6585f5e6837be74ba04350f133340d9.xml
Normal file
1
LFtid1056/dat/e6585f5e6837be74ba04350f133340d9.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/eeaa3bdc02c4e50b48eb92716d5c14db.xml
Normal file
1
LFtid1056/dat/eeaa3bdc02c4e50b48eb92716d5c14db.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/f0386b207f416a1bf7948d478087a0fb.xml
Normal file
1
LFtid1056/dat/f0386b207f416a1bf7948d478087a0fb.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/fa1050bdce7efd63508e881536157058.xml
Normal file
1
LFtid1056/dat/fa1050bdce7efd63508e881536157058.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/fc205e2c998c64fc5afb8ec62b54129a.xml
Normal file
1
LFtid1056/dat/fc205e2c998c64fc5afb8ec62b54129a.xml
Normal file
@@ -0,0 +1 @@
|
||||
{"code":"A00555","message":"下载文件,文件服务器下载文件流为空","data":null}
|
||||
1
LFtid1056/dat/ledger/20250807185343_ledger.txt
Normal file
1
LFtid1056/dat/ledger/20250807185343_ledger.txt
Normal 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"}]}]}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user