This commit is contained in:
lnk
2025-09-22 16:46:33 +08:00
parent 169aa9b34a
commit db8aa8c07d
8 changed files with 358 additions and 252 deletions

View File

@@ -2976,29 +2976,41 @@ std::vector<DeviceInfo> GenerateDeviceInfoFromLedger(const std::vector<terminal_
////////////////////////////////////////////////////////////////////////////////////////////////////录波文件通知
bool assign_qvvr_file_list(const std::string& id, ushort nCpuNo, const std::vector<std::string>& file_list_raw) {
bool assign_qvvr_file_list(const std::string& id,
ushort nCpuNo,
const std::vector<std::string>& file_list_raw) {
// ★新增:台账加锁(若上层已有锁,可移除本行)
std::lock_guard<std::mutex> lk(ledgermtx);
std::vector<std::string> file_names;
// 1. 提取文件名部分
for (const auto& full_path : file_list_raw) {
for (const auto& full_path_raw : file_list_raw) {
std::string full_path = sanitize(full_path_raw); // ★修改:清洗入参路径
size_t pos = full_path.find_last_of("/\\");
if (pos != std::string::npos && pos + 1 < full_path.size()) {
file_names.push_back(full_path.substr(pos + 1));
} else {
file_names.push_back(full_path);
}
std::string name = (pos != std::string::npos && pos + 1 < full_path.size())
? full_path.substr(pos + 1)
: full_path;
name = sanitize(name); // ★修改:清洗提取的文件名
file_names.push_back(name);
}
// ★可选:去重(如果 file_list_raw 里可能有重复)
std::sort(file_names.begin(), file_names.end());
file_names.erase(std::unique(file_names.begin(), file_names.end()), file_names.end());
// 2. 遍历终端
for (auto& dev : terminal_devlist) {
if (dev.terminal_id == id) { // 根据终端id匹配终端
for (auto& monitor : dev.line) {
try {
ushort monitor_seq = static_cast<ushort>(std::stoi(monitor.logical_device_seq));
// ★修改:清洗 logical_device_seq 再进行转换
std::string seq_str = sanitize(monitor.logical_device_seq);
ushort monitor_seq = static_cast<ushort>(std::stoi(seq_str));
if (monitor_seq == nCpuNo) { // 根据监测点编号匹配监测点
// 构造 qvvr_file
qvvr_file qfile;
qfile.file_name.assign(file_names.begin(), file_names.end()); //终端文件列表
qfile.file_name.assign(file_names.begin(), file_names.end()); // 终端文件列表(已清洗)
qfile.is_download = false;
qfile.is_pair = false;
qfile.file_time_count = 0;
@@ -3017,7 +3029,6 @@ bool assign_qvvr_file_list(const std::string& id, ushort nCpuNo, const std::vect
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////下载成功通知
//提取下载路径的文件名
std::string extract_filename1(const std::string& path) {
@@ -3078,27 +3089,47 @@ bool SendAllQvvrFiles(qvvr_file& qfile, std::string& out_wavepath) {
}
//文件下载结束接口
bool update_qvvr_file_download(const std::string& filename_with_mac, const std::string& terminal_id) {
std::cout << "[update_qvvr_file_download] filename_with_mac=" << filename_with_mac
<< " terminal_id=" << terminal_id << std::endl;
bool update_qvvr_file_download(const std::string& filename_with_mac_in, const std::string& terminal_id) {
// ★ 先把原始入参清洗
std::string filename_with_mac = sanitize(filename_with_mac_in);
std::cout << "[update_qvvr_file_download] raw=" << filename_with_mac_in
<< " | sanitized=" << filename_with_mac
<< " | terminal_id=" << terminal_id << std::endl;
//台账加锁
std::lock_guard<std::mutex> lock(ledgermtx);
// 去除 mac 路径前缀,仅保留文件名
std::string filename = extract_filename1(filename_with_mac);
std::string filename = sanitize(extract_filename1(filename_with_mac));
// 提取逻辑序号(如 PQM1 → 1
size_t under_pos = filename.find('_');
if (under_pos == std::string::npos) return false;
// 提取逻辑序号(如 PQ_PQLD1 → 1
size_t under_pos1 = filename.find('_');
if (under_pos1 == std::string::npos) {
std::cout << "[DEBUG] 未找到 '_'filename=" << filename
<< "under_pos=npos返回 false\n";
return false;
}
size_t under_pos2 = filename.find('_', under_pos1 + 1);
std::string type_part = (under_pos2 == std::string::npos)
? filename.substr(0, under_pos1) // 兜底:只有一个下划线
: filename.substr(0, under_pos2); // 取到第二个下划线(得到 PQ_PQLD1
std::cout << "[DEBUG] type_part=" << type_part
<< " (under_pos1=" << under_pos1
<< ", under_pos2=" << under_pos2 << ")\n";
std::string type_part = filename.substr(0, under_pos); // PQMonitor_PQM1
size_t num_start = type_part.find_last_not_of("0123456789");
if (num_start == std::string::npos || num_start + 1 >= type_part.size()) return false;
if (num_start == std::string::npos || num_start + 1 >= type_part.size()) {
std::cout << "[DEBUG] 数字起始位置异常num_start=" << num_start
<< "type_part.size()=" << type_part.size()
<< "type_part=\"" << type_part << "\",返回 false\n";
return false;
}
std::string seq_str = type_part.substr(num_start + 1);
ushort logical_seq = static_cast<ushort>(std::stoi(seq_str)); // 逻辑序号
unsigned short logical_seq = static_cast<unsigned short>(std::stoul(seq_str));
std::cout << "[DEBUG] 解析到 logical_seq=" << logical_seq << "\n";
//找终端
for (auto& dev : terminal_devlist) {
@@ -3118,12 +3149,21 @@ bool update_qvvr_file_download(const std::string& filename_with_mac, const std::
// ★新增:不匹配时对比打印
std::cout << "[cmp-monitor-seq][NOT-MATCH]"
<< " monitor_id=" << monitor.monitor_id
<< " seq_in_ledger=\"" << seq_str << "\""
// ★ 这里之前打印的是 seq_str容易误导。改为 ledger 的原始串:
<< " seq_in_ledger_raw=\"" << monitor.logical_device_seq << "\""
<< " parsed=" << monitor_seq
<< " target_seq=" << logical_seq
<< std::endl;
continue;
}
else{
std::cout << "[cmp-monitor-seq][MATCH!!!]"
<< " monitor_id=" << monitor.monitor_id
<< " seq_in_ledger_raw=\"" << monitor.logical_device_seq << "\""
<< " parsed=" << monitor_seq
<< " target_seq=" << logical_seq
<< std::endl;
}
} catch (const std::exception& e) {
// ★新增:解析失败详细原因
std::cout << "[cmp-monitor-seq][PARSE-FAIL]"
@@ -3162,7 +3202,7 @@ bool update_qvvr_file_download(const std::string& filename_with_mac, const std::
std::set<std::string> s_name(qfile.file_name.begin(), qfile.file_name.end());
std::set<std::string> s_down;
for (const auto& path : qfile.file_download) {
s_down.insert(extract_filename1(path)); // 提取每个路径中的文件名
s_down.insert(sanitize(extract_filename1(path))); // 提取每个路径中的文件名
}
//打印s_name和s_down内容
@@ -4628,11 +4668,6 @@ void on_device_response_minimal(int response_code,
}
else {
// 准备日志用的 key
std::ostringstream mon_key_c, mon_key_d;
mon_key_c << "monitor." << matched_monitor->terminal_id << "." << matched_monitor->logical_device_seq << ".COM";
mon_key_d << "monitor." << matched_monitor->terminal_id << "." << matched_monitor->logical_device_seq << ".DATA";
// 2) 仅更新该监测点 recall_list 的首条,且要求处于 RUNNING
if (!matched_monitor->recall_list.empty()) {
RecallMonitor& front = matched_monitor->recall_list.front(); //取出首条
@@ -4651,7 +4686,7 @@ void on_device_response_minimal(int response_code,
<< " rc=" << response_code << std::endl; //错误响应码
//记录日志
DIY_ERRORLOG_CODE(mon_key_d.str().c_str(),static_cast<int>(LogCode::LOG_CODE_RECALL),"【ERROR】监测点:%s 补招数据失败 - 失败时间点:%lld 至 %lld",mon_key_d.str().c_str(),front.StartTime,front.EndTime);
DIY_ERRORLOG_CODE(matched_monitor->monitor_id.c_str(),2,static_cast<int>(LogCode::LOG_CODE_RECALL),"【ERROR】监测点:%s 补招数据失败 - 失败时间点:%lld 至 %lld",matched_monitor->monitor_id.c_str(),front.StartTime,front.EndTime);
}
updated = true;
} else { //首条不是 RUNNING 状态,不应该收到这条响应
@@ -4902,6 +4937,157 @@ void on_device_response_minimal(int response_code,
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////记录暂态事件到本地
// 将一条暂态数据更新/写入到指定终端ID与逻辑序号的监测点
// 返回 true 表示已写入更新或追加false 表示未找到对应终端/监测点。
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) // 相别
{
std::cout << "[append_qvvr_event] enter"
<< " tid=" << std::this_thread::get_id()
<< " terminal_id=" << terminal_id
<< " logical_seq=" << logical_seq
<< " type=" << nType
<< " per_s=" << fPersisstime_sec
<< " mag_pu=" << fMagnitude_pu
<< " time_ms=" << static_cast<unsigned long long>(triggerTimeMs)
<< " phase=" << phase
<< std::endl;
std::lock_guard<std::mutex> lk(ledgermtx);
std::cout << "[append_qvvr_event] lock acquired. terminal_devlist.size="
<< terminal_devlist.size() << std::endl;
// 1) 找终端
auto dev_it = std::find_if(terminal_devlist.begin(), terminal_devlist.end(),
[&](const terminal_dev& d){ return d.terminal_id == terminal_id; });
if (dev_it == terminal_devlist.end()) {
std::cout << "[append_qvvr_event][MISS] terminal not found: "
<< terminal_id << std::endl;
return false;
}
std::cout << "[append_qvvr_event][HIT] terminal_id=" << terminal_id
<< " monitors(line).size=" << dev_it->line.size()
<< std::endl;
// 2) 找监测点(按逻辑序号匹配:字符串等于 或 数值等于)
ledger_monitor* pMon = nullptr;
for (size_t i = 0; i < dev_it->line.size(); ++i) {
auto& m = dev_it->line[i];
bool eq_str = (m.logical_device_seq == std::to_string(logical_seq));
bool eq_num = false;
try {
if (!m.logical_device_seq.empty())
eq_num = (std::stoi(m.logical_device_seq) == logical_seq);
} catch (...) {
// 仅调试提示,不改变原逻辑
std::cout << "[append_qvvr_event][monitor #" << i
<< "] stoi fail, logical_device_seq=\""
<< m.logical_device_seq << "\"" << std::endl;
}
std::cout << "[append_qvvr_event][probe monitor #" << i
<< "] monitor_id=" << m.monitor_id
<< " logical_device_seq=\"" << m.logical_device_seq << "\""
<< " eq_str=" << eq_str << " eq_num=" << eq_num << std::endl;
if (eq_str || eq_num) { pMon = &m; break; }
}
if (!pMon) {
std::cout << "[append_qvvr_event][MISS] monitor not found by seq="
<< logical_seq << " in terminal_id=" << terminal_id << std::endl;
return false;
}
std::cout << "[append_qvvr_event][HIT] monitor_id=" << pMon->monitor_id
<< " logical_device_seq=" << pMon->logical_device_seq
<< " qvvrdata.size=" << pMon->qvvrevent.qvvrdata.size()
<< std::endl;
qvvr_event& qe = pMon->qvvrevent;
// 3) 先尝试“就地更新”(同类型 + 同时间戳 视为同一事件)
for (size_t i = 0; i < qe.qvvrdata.size(); ++i) {
auto& q = qe.qvvrdata[i];
if (q.QVVR_type == nType && q.QVVR_time == triggerTimeMs) {
std::cout << "[append_qvvr_event][UPDATE match idx=" << i << "]"
<< " old{used=" << q.used_status
<< ", per=" << q.QVVR_PerTime
<< ", mag=" << q.QVVR_Amg
<< ", phase=" << q.phase
<< "} -> new{used=true"
<< ", per=" << fPersisstime_sec
<< ", mag=" << fMagnitude_pu
<< ", phase=" << phase
<< "}" << std::endl;
q.used_status = true;
q.QVVR_PerTime = fPersisstime_sec;
q.QVVR_Amg = fMagnitude_pu;
q.phase = phase;
std::cout << "[append_qvvr_event] done(update)."
<< std::endl;
return true;
}
}
// 4) 复用空槽used_status=false
for (size_t i = 0; i < qe.qvvrdata.size(); ++i) {
auto& q = qe.qvvrdata[i];
if (!q.used_status) {
std::cout << "[append_qvvr_event][REUSE idx=" << i << "]"
<< " set{type=" << nType
<< ", time_ms=" << static_cast<unsigned long long>(triggerTimeMs)
<< ", per=" << fPersisstime_sec
<< ", mag=" << fMagnitude_pu
<< ", phase=" << phase
<< "}" << std::endl;
q.used_status = true;
q.QVVR_type = nType;
q.QVVR_time = triggerTimeMs;
q.QVVR_PerTime = fPersisstime_sec;
q.QVVR_Amg = fMagnitude_pu;
q.phase = phase;
std::cout << "[append_qvvr_event] done(reuse)."
<< std::endl;
return true;
}
}
// 5) 直接追加
qvvr_data q{};
q.used_status = true;
q.QVVR_type = nType;
q.QVVR_time = triggerTimeMs; // ms
q.QVVR_PerTime = fPersisstime_sec; // s
q.QVVR_Amg = fMagnitude_pu;
q.phase = phase;
qe.qvvrdata.push_back(q);
std::cout << "[append_qvvr_event][PUSH_BACK]"
<< " new_size=" << qe.qvvrdata.size()
<< " last_idx=" << (qe.qvvrdata.empty() ? -1 : (int)qe.qvvrdata.size()-1)
<< " {type=" << nType
<< ", time_ms=" << static_cast<unsigned long long>(triggerTimeMs)
<< ", per=" << fPersisstime_sec
<< ", mag=" << fMagnitude_pu
<< ", phase=" << phase
<< "}" << std::endl;
std::cout << "[append_qvvr_event] done(push_back)."
<< std::endl;
return true;
}

View File

@@ -1176,15 +1176,23 @@ static void scanAndResendOfflineFiles(const std::string& dirPath)
}
}
// 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 和其他任何值
}
}
int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
double mag, double dur, long long start_tm, int dis_kind,int phase,
const std::string& wavepath) {
// 监测点日志的 key, lnk20250526
std::string full_key_m_c = "monitor." + dev_id + "." + std::to_string(monitor_id) + ".COM";
std::string full_key_m_d = "monitor." + dev_id + "." + std::to_string(monitor_id) + ".DATA";
// 监测点日志的 key, lnk20250526
if (dev_id.empty()) {
std::cout << "qvvr send error ,dev_id is null" << std::endl;
return 1;
@@ -1220,7 +1228,7 @@ int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
root["startTime"] = start_time_str;
root["wavePath"] = wavepath;
root["phase"] = phase;
root["phase"] = phase_to_text(phase);
std::string json_string = root.dump(4);
@@ -1237,7 +1245,7 @@ int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
// 有效响应,略过
} catch (...) {
// 响应异常,保存 json
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口响应异常,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
DIY_ERRORLOG(mpid.c_str(), "【ERROR】暂态接口响应异常,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
std::string qvvrDir = FRONT_PATH + "/dat/qvvr/";
@@ -1247,7 +1255,7 @@ int transfer_json_qvvr_data(const std::string& dev_id, ushort monitor_id,
}
} else {
// 无响应,保存 json
DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口无响应,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
DIY_ERRORLOG(mpid.c_str(), "【ERROR】暂态接口无响应,无法上送装置%s监测点%s的暂态事件",dev_id, monitor_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
std::string qvvrDir = FRONT_PATH + "/dat/qvvr/";

View File

@@ -591,6 +591,13 @@ std::string generate_json( //构造装置主动上送数据的报文
);
//暂态事件接口
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);
@@ -682,6 +689,18 @@ inline std::string trim_cstr(const char* s, size_t n) {
return out;
}
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;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern int g_front_seg_index;
extern std::string FRONT_IP;

View File

@@ -152,8 +152,6 @@ protected:
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
<< "\",\"level\":\"" << level_str
<< "\",\"grade\":\"" << get_level_str(level)
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
<< "\",\"frontType\":\"" << "cloudfront"
// ★新增:输出 code 字段(整型)
<< "\",\"code\":\"" << code
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
@@ -311,12 +309,10 @@ void init_loggers_bydevid(const std::string& dev_id)
std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str;
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + dev_id + ".COM";
std::string device_key_d = std::string("terminal.") + dev_id + ".DATA";
std::string device_key = std::string("terminal.") + dev_id;
// 添加判断:终端日志 logger 是否已存在
if (logger_map.find(device_key_c) == logger_map.end() &&
logger_map.find(device_key_d) == logger_map.end()) {
if (logger_map.find(device_key) == logger_map.end()) {
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + dev_id + ".log";
@@ -325,27 +321,23 @@ void init_loggers_bydevid(const std::string& dev_id)
SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, dev_id, device_appender);
Logger device_logger_d = init_logger(device_key_d, device_dir, dev_id, device_appender);
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender);
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
DIY_WARNLOG(dev_id.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
}
// 初始化监测点日志monitor.<mp_id>.COM / .DATA
for (size_t j = 0; j < term.line.size(); ++j) {
const ledger_monitor& monitor = term.line[j];
if (!monitor.monitor_id.empty()) {
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".COM";
mon_key_d << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".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";
@@ -354,12 +346,10 @@ void init_loggers_bydevid(const std::string& dev_id)
SharedAppenderPtr monitor_appender(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
DIY_WARNLOG(monitor.monitor_id.c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
}
@@ -386,8 +376,7 @@ void init_loggers()
std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str;
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + term.terminal_id + ".COM";
std::string device_key_d = std::string("terminal.") + term.terminal_id + ".DATA";
std::string device_key = std::string("terminal.") + term.terminal_id;
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + term.terminal_id + ".log";
@@ -396,22 +385,19 @@ void init_loggers()
SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::unique_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, term.terminal_id, device_appender);
Logger device_logger_d = init_logger(device_key_d, device_dir, term.terminal_id, device_appender);
Logger device_logger = init_logger(device_key, device_dir, term.terminal_id, device_appender);
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
DIY_WARNLOG(term.terminal_id.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str());
// 初始化监测点日志
for (size_t i = 0; i < term.line.size(); ++i) {
const ledger_monitor& monitor = term.line[i];
if (!monitor.monitor_id.empty()) {
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".COM";
mon_key_d << "monitor." << term.terminal_id << "." << monitor.logical_device_seq << ".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;
@@ -422,13 +408,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_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕",
DIY_WARNLOG(mon_key.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕",
monitor.monitor_name.c_str(), monitor.logical_device_seq.c_str());
}
}
@@ -443,17 +427,11 @@ void remove_loggers_by_terminal_id(const std::string& terminal_id) {
if (term.terminal_id != terminal_id) continue;
// 删除终端日志 logger
std::string com_key = "terminal." + terminal_id + ".COM";
std::string data_key = "terminal." + terminal_id + ".DATA";
std::string terminal_key = "terminal." + terminal_id;
if (logger_map.count(com_key)) {
logger_map[com_key].logger.removeAllAppenders();
logger_map.erase(com_key);
}
if (logger_map.count(data_key)) {
logger_map[data_key].logger.removeAllAppenders();
logger_map.erase(data_key);
if (logger_map.count(terminal_key)) {
logger_map[terminal_key].logger.removeAllAppenders();
logger_map.erase(terminal_key);
}
// 删除监测点日志 logger
@@ -461,18 +439,13 @@ void remove_loggers_by_terminal_id(const std::string& terminal_id) {
const ledger_monitor& monitor = term.line[i];
if (!monitor.monitor_id.empty()) {
std::string mon_prefix = "monitor." + monitor.monitor_id;
std::string mon_com_key = mon_prefix + ".COM";
std::string mon_data_key = mon_prefix + ".DATA";
std::string mon_key = mon_prefix;
if (logger_map.count(mon_com_key)) {
logger_map[mon_com_key].logger.removeAllAppenders();
logger_map.erase(mon_com_key);
if (logger_map.count(mon_key)) {
logger_map[mon_key].logger.removeAllAppenders();
logger_map.erase(mon_key);
}
if (logger_map.count(mon_data_key)) {
logger_map[mon_data_key].logger.removeAllAppenders();
logger_map.erase(mon_data_key);
}
}
}

View File

@@ -105,44 +105,6 @@ void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
// ====================== ★新增结束 ======================
// ====================== 日志宏区域 ======================
// 原始不带 code 的实现(兼容/复用)
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); \
} while (0)
// ★新增:带 code 的实现C/C++ 通用,使用 TLS 保存/恢复)
#define DIY_LOG_CODE(LEVEL_FUNC, KEY, CODE_INT, ...) \
do { \
int __old_code__ = g_log_code_tls; /* 备份旧值 */ \
g_log_code_tls = (int)(CODE_INT); /* 设置本次日志 code */ \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); /* 输出日志 */ \
g_log_code_tls = __old_code__; /* 恢复旧值 */ \
} while (0)
// ★修改:默认宏改为 code=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
typedef enum LogCode {
LOG_CODE_OTHER = 99, /* 其他类型 */
LOG_CODE_LEDGER = 100, /* 台账类型 */
@@ -162,6 +124,73 @@ typedef enum LogCode {
LOG_CODE_SPACE_ALARM = 700 /* 空间告警 */
} LogCode;
// ====================== 日志宏区域 ======================
// 原始不带 code 的实现(兼容/复用)
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); \
} while (0)
// ★新增:带 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)
// ★修改:默认宏改为 code=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_error, KEY,LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
#ifdef __cplusplus
}

View File

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

View File

@@ -15,7 +15,7 @@ RT_TAG=rt
RT_KEY=rt
[Flag]
FrontInst=
FrontInst=914b94563ca7f272c90ee8580ed6adc6
FrontIP=192.168.1.138
[Ledger]
@@ -33,7 +33,7 @@ WebFiledownload=
[RocketMq]
producer=Group_producer
Ipport=192.168.1.24:9876
Ipport=192.168.1.103:9876
AccessKey=rmqroot
SecretKey=001@#njcnmq
@@ -44,10 +44,10 @@ Testflag=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

View File

@@ -163,6 +163,8 @@ void process_received_message(string mac, string id,const char* data, size_t len
<< ", ʱ<><CAB1><EFBFBD><EFBFBD>: " << record.triggerTimeMs << "ms" << std::endl;
//lnk20250805 <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>¼<EFBFBD><C2BC>¼<EFBFBD><C2BC><EFBFBD>ļ<EFBFBD><C4BC>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD><D9B8><EFBFBD><EFBFBD>ļ<EFBFBD>
append_qvvr_event(id,event.head.name,
record.nType,record.fPersisstime,record.fMagntitude,record.triggerTimeMs,record.phase);
transfer_json_qvvr_data(id,event.head.name,
record.fMagntitude,record.fPersisstime,record.triggerTimeMs,record.nType,record.phase,
"");