fix qvvr
This commit is contained in:
@@ -2976,36 +2976,48 @@ 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匹配终端
|
||||
if (dev.terminal_id == id) { // 根据终端id匹配终端
|
||||
for (auto& monitor : dev.line) {
|
||||
try {
|
||||
ushort monitor_seq = static_cast<ushort>(std::stoi(monitor.logical_device_seq));
|
||||
if (monitor_seq == nCpuNo) { //根据监测点编号匹配监测点
|
||||
// ★修改:清洗 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.is_download = false;
|
||||
qfile.is_pair = false;
|
||||
qfile.file_name.assign(file_names.begin(), file_names.end()); // 终端文件列表(已清洗)
|
||||
qfile.is_download = false;
|
||||
qfile.is_pair = false;
|
||||
qfile.file_time_count = 0;
|
||||
qfile.used_status =true;
|
||||
qfile.used_status = true;
|
||||
|
||||
// 添加到唯一的 qvvrevent
|
||||
monitor.qvvrevent.qvvrfile.push_back(std::move(qfile)); //记录暂态文件组
|
||||
monitor.qvvrevent.qvvrfile.push_back(std::move(qfile)); // 记录暂态文件组
|
||||
return true;
|
||||
}
|
||||
} catch (...) {
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user