add qvvr interface

This commit is contained in:
lnk
2025-08-05 20:00:20 +08:00
parent 0eab1e6fb5
commit afc079465e
3 changed files with 151 additions and 70 deletions

View File

@@ -2703,7 +2703,26 @@ bool extract_timestamp_from_cfg_file(const std::string& cfg_path, long long& sta
return start_tm > 0 && trig_tm > 0;
}
bool compare_qvvr_and_file(const std::string& cfg_path, const std::vector<qvvr_data>& data_list) {
long long start_tm = 0;
long long trig_tm = 0;
// 提取 .cfg 文件中的时间戳
if (!extract_timestamp_from_cfg_file(cfg_path, start_tm, trig_tm)) {
std::cerr << "Failed to extract timestamp from cfg file: " << cfg_path << "\n";
return false;
}
// 遍历所有暂态事件,查找与 trig_tm 匹配的
for (const auto& data : data_list) {
long long diff = static_cast<long long>(data.QVVR_time) - trig_tm;
if (std::abs(diff) <= 1) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////数据转换函数
// DataArrayItem to_json
void to_json(nlohmann::json& j, const DataArrayItem& d) {
@@ -2844,7 +2863,7 @@ bool assign_qvvr_file_list(const std::string& id, ushort nCpuNo, const std::vect
qfile.is_download = false;
qfile.is_pair = false;
qfile.file_time_count = 0;
qfile.file_start =false;
qfile.used_status =true;
// 添加到唯一的 qvvrevent
monitor.qvvrevent.qvvrfile.push_back(std::move(qfile)); //记录暂态文件组
@@ -2861,72 +2880,158 @@ bool assign_qvvr_file_list(const std::string& id, ushort nCpuNo, const std::vect
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////下载成功通知
//提取下载路径的文件名
std::string extract_filename(const std::string& path) {
size_t pos = path.find_last_of("/\\");
return (pos != std::string::npos) ? path.substr(pos + 1) : path;
}
//发送匹配的所有录波文件
bool SendAllQvvrFiles(qvvr_file& qfile, std::string& out_wavepath) {
std::vector<std::string> wavepaths;
std::string first_wavepath;
bool send_success = true;
for (const auto& file_localpath : qfile.file_download) {
std::string file_cloudpath = "comtrade/" + file_localpath;
std::string wavepath_result;
// 发送本地文件到远端,返回 wavepath
SOEFileWeb(const_cast<std::string&>(file_localpath), file_cloudpath, wavepath_result);
// 如果失败,重发一次
if (wavepath_result.empty()) {
std::cerr << "[SOEFileWeb] Warning: first send failed for file: " << file_localpath << ", retrying...\n";
SOEFileWeb(const_cast<std::string&>(file_localpath), file_cloudpath, wavepath_result);
}
if (wavepath_result.empty()) {
send_success = false;
std::cerr << "[SOEFileWeb] Failed: wavepath empty for file: " << file_localpath << "\n";
break;
}
if (wavepaths.empty()) {
first_wavepath = wavepath_result;
} else if (wavepath_result != first_wavepath) {
send_success = false;
std::cerr << "[SOEFileWeb] Mismatch wavepath: " << wavepath_result
<< " vs " << first_wavepath << "\n";
break;
}
wavepaths.push_back(wavepath_result);
}
// 检查数量是否一致
if (!send_success || wavepaths.size() != qfile.file_download.size()) {
std::cerr << "[SOEFileWeb] Failed to send all qvvr files. "
<< "Sent: " << wavepaths.size()
<< ", Expected: " << qfile.file_download.size() << "\n";
return false;
}
out_wavepath = first_wavepath; // 返回统一的 wavepath
std::cout << "[SOEFileWeb] Success: all files sent for qfile. Wavepath = "
<< first_wavepath << "\n";
return true;
}
//文件下载结束接口
bool update_qvvr_file_download(const std::string& filename_with_mac, const std::string& terminal_id) {
// 去除 mac 路径前缀
size_t pos = filename_with_mac.find_last_of("/\\");
std::string filename = (pos != std::string::npos) ? filename_with_mac.substr(pos + 1) : filename_with_mac;
// 去除 mac 路径前缀,仅保留文件名
std::string filename = extract_filename(filename_with_mac);
// 提取逻辑序号(如 PQM1 → 1
size_t under_pos = filename.find('_');
if (under_pos == std::string::npos) return false;
std::string type_part = filename.substr(0, under_pos); //PQMonitor_PQM1
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;
std::string seq_str = type_part.substr(num_start + 1);
ushort logical_seq = static_cast<ushort>(std::stoi(seq_str));
ushort logical_seq = static_cast<ushort>(std::stoi(seq_str)); // 逻辑序号
for (auto& dev : terminal_devlist) {
if (dev.terminal_id != terminal_id) continue;
for (auto& monitor : dev.line) {
try {
// 将监测点台账中的 logical_device_seq 转换为数字进行匹配
ushort monitor_seq = static_cast<ushort>(std::stoi(monitor.logical_device_seq));
if (monitor_seq != logical_seq) continue;
} catch (...) {
continue;
continue; // logical_device_seq 非法,跳过
}
// 匹配监测点下 qvvrfile 中的 file_name
for (auto& qfile : monitor.qvvrevent.qvvrfile) {
// file_name 中是文件名,需与提取的 filename 比较
auto it = std::find(qfile.file_name.begin(), qfile.file_name.end(), filename);
if (it != qfile.file_name.end()) {
// 添加到 file_download去重
if (std::find(qfile.file_download.begin(), qfile.file_download.end(), filename) == qfile.file_download.end()) {
qfile.file_download.push_back(filename);
// 添加到 file_download记录完整路径,避免重复
if (std::find(qfile.file_download.begin(), qfile.file_download.end(), filename_with_mac) == qfile.file_download.end()) {
qfile.file_download.push_back(filename_with_mac);
}
qfile.file_time_count = 0;
qfile.file_start = true; //开始下载文件
qfile.file_time_count = 0; // 文件下载开始后,计时归零
// 检查 file_download 是否与 file_name 完全一致(集合相同)//每次下载都会对比
// file_download 中是完整路径,需提取文件名后与 file_name 做集合比较
std::set<std::string> s_name(qfile.file_name.begin(), qfile.file_name.end());
std::set<std::string> s_down(qfile.file_download.begin(), qfile.file_download.end());
std::set<std::string> s_down;
for (const auto& path : qfile.file_download) {
s_down.insert(extract_filename(path)); // 提取每个路径中的文件名
}
// 检查 file_download 是否与 file_name 完全一致(集合相同)
if (s_name == s_down) {
qfile.is_download = true; //全部下载完成
qfile.is_download = true; // 全部下载完成
// 找到其中的 .cfg 文件进行匹配
for (const auto& f : qfile.file_download) {
if (f.size() >= 4 && f.substr(f.size() - 4) == ".cfg") {
if (compare_qvvr_and_file(f)) {//提取文件时标和监测点事件的时标匹配
qfile.is_pair = true;
//发送所有文件
for (const auto& fpath : qfile.file_download) {
std::string fname = extract_filename(fpath);
if (fname.size() >= 4 && fname.substr(fname.size() - 4) == ".cfg") {
// 提取文件时标和监测点事件的时标匹配
if (compare_qvvr_and_file(fpath, monitor.qvvrevent.qvvrdata)) {
qfile.is_pair = true; // 文件与事件匹配成功
//发送暂态事件
// 发送所有文件(已下载完成)
std::string wavepath;
if (SendAllQvvrFiles(qfile, wavepath)) {
//文件发送成功后更新事件
transfer_json_qvvr_data(terminal_id,
logical_seq,
monitor.qvvrevent.qvvrdata.QVVR_Amg,
monitor.qvvrevent.qvvrdata.QVVR_PerTime,
monitor.qvvrevent.qvvrdata.QVVR_time,
monitor.qvvrevent.qvvrdata.QVVR_type,
monitor.qvvrevent.qvvrdata.phase,
wavepath);
// 清除暂态数据
monitor.qvvrevent.qvvrfile.clear();
monitor.qvvrevent.qvvrdata.clear();
// 删除上传成功的文件
for (const auto& uploaded_file : qfile.file_download) {
if (std::remove(uploaded_file.c_str()) != 0) {
std::cerr << "[Cleanup] Failed to delete file: " << uploaded_file << "\n";
} else {
std::cout << "[Cleanup] Deleted uploaded file: " << uploaded_file << "\n";
}
}
}
}
break; // 只处理第一个 cfg 文件
}
}
}
return true;
return true; // 当前文件处理成功
}
}
}
}
return false;
return false; // 未匹配到终端ID或逻辑序号对应的监测点
}