This commit is contained in:
lnk
2025-10-28 20:59:05 +08:00
parent f69a6d2105
commit 06a2f3a75b
4 changed files with 926 additions and 144 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,8 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <unordered_set>
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
@@ -78,15 +80,13 @@ public:
//暂态文件用 //暂态文件用
bool direct_mode = false; // 直下文件开关true 表示不按时间窗,仅按目标文件名 bool direct_mode = false; // 直下文件开关true 表示不按时间窗,仅按目标文件名
std::vector<std::string> target_filetimes; // 直下文件匹配时间 std::string target_filetimes; // 直下文件匹配时间yyyyMMdd_HHmmss仅 direct_mode=true 时有效
std::list<std::string> file_paths; // 已下载/要上报的完整路径(用于最终结果)
// ★新增:按“目录名 -> 文件名列表”的映射;由“其他线程”在目录请求成功后回填 // ★新增:按“目录名 -> 文件名列表”的映射;由“其他线程”在目录请求成功后回填
std::map<std::string, std::vector<tag_dir_info>> dir_files; std::map<std::string, std::vector<tag_dir_info>> dir_files;
// ★新增:候选目录(可扩展) // ★新增:候选目录(可扩展)
std::vector<std::string> dir_candidates{ std::vector<std::string> dir_candidates{
"/cf/COMTRADE", "/cf/COMTRADE",
"/bd0/COMTRADE", "/bd0/COMTRADE",
"/sd0/COMTRADE", "/sd0/COMTRADE",
@@ -103,9 +103,12 @@ public:
ActionResult download_result = ActionResult::PENDING; // 当前文件的下载结果 ActionResult download_result = ActionResult::PENDING; // 当前文件的下载结果
// ★新增:下载队列(已筛选出在时间窗内的文件,含完整路径) // ★新增:下载队列(已筛选出在时间窗内的文件,含完整路径)
std::list<std::string> download_queue; std::list<std::string> download_queue; //一个时间可能对应多个文件
std::string downloading_file; // 当前正在下载的文件(完整路径) 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) void reset_runtime(bool keep_direct = false)
{ {
@@ -117,6 +120,10 @@ public:
download_queue.clear(); download_queue.clear();
downloading_file.clear(); downloading_file.clear();
dir_files.clear(); dir_files.clear();
required_files.clear();
file_success.clear();
// ★新增:按需保留直下文件开关和目标名 // ★新增:按需保留直下文件开关和目标名
if (!keep_direct) { if (!keep_direct) {
direct_mode = false; direct_mode = false;
@@ -807,6 +814,12 @@ inline void print_terminal(const update_dev& tmnl) { print_terminal_common(tmnl)
inline void print_terminal(const terminal_dev& tmnl) { print_terminal_common(tmnl); } inline void print_terminal(const terminal_dev& tmnl) { print_terminal_common(tmnl); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////小工具 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////小工具
// 小工具:判断 s 是否以 suffix 结尾
static 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 std::string trim_cstr(const char* s, size_t n) { inline std::string trim_cstr(const char* s, size_t n) {
if (!s) return {}; if (!s) return {};
size_t end = 0; size_t end = 0;
@@ -817,6 +830,15 @@ inline std::string trim_cstr(const char* s, size_t n) {
return out; 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) { inline std::string sanitize(std::string s) {
// 截断第一个 NUL 及其后内容 // 截断第一个 NUL 及其后内容
size_t z = s.find('\0'); size_t z = s.find('\0');
@@ -844,6 +866,22 @@ inline std::string now_yyyy_mm_dd_hh_mm_ss() {
return oss.str(); 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 映射) === // === 专用锁 + 数据表(仅管实时 idx 映射) ===
extern std::mutex devidx_lock; // 新锁(不要用 ledgermtx extern std::mutex devidx_lock; // 新锁(不要用 ledgermtx
@@ -924,4 +962,35 @@ static bool parse_datetime_tm(const std::string& s, std::tm& out) {
} }
#endif #endif
/////////////////////////////////////////////////////////////////////////////补招文件记录
// 记录 (guid, monitorId) -> 文件完整路径
extern std::mutex g_recall_file_mtx;
extern std::map<std::pair<std::string,std::string>, std::string> g_recall_file_index;
// 初始化 / 追加 / 删除
bool init_recall_record_file(const std::string& guid,
const std::string& terminalId,
const std::string& monitorId,
const std::string& start,
const std::string& end);
bool append_recall_record_line(const std::string& guid,
const std::string& monitorId,
const std::string& msg);
bool delete_recall_record_file(const std::string& guid,
const std::string& monitorId);
bool get_recall_record_fields_by_guid_monitor(const std::string& guid,
const std::string& monitorId,
std::string& outGuid,
std::string& terminalId,
std::string& outMonitorId,
std::string& startTime,
std::string& endTime,
std::string& msg);
bool SendFileWebAuto(const std::string& id,
const std::string& local_path,
const std::string& remote_path,
std::string& out_filename);

View File

@@ -684,16 +684,9 @@ void Worker::printLedgerinshell(const terminal_dev& dev, int fd) {
// ★新增:直下模式与目标时间列表 // ★新增:直下模式与目标时间列表
os << "\r\x1B[K |-- direct_mode=" << (rf.direct_mode ? "true" : "false") os << "\r\x1B[K |-- direct_mode=" << (rf.direct_mode ? "true" : "false")
<< ", target_filetimes(" << rf.target_filetimes.size() << ")\n"; << ", target_filetimes(" << rf.target_filetimes << ")\n";
{ {
size_t c = 0; os << "\r\x1B[K |.. " << rf.target_filetimes << "\n";
for (const auto& t : rf.target_filetimes) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << t << "\n";
}
if (rf.target_filetimes.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (rf.target_filetimes.size() - MAX_ITEMS) << " more)\n";
}
} }
// ★新增:状态机运行态 // ★新增:状态机运行态
@@ -747,19 +740,6 @@ void Worker::printLedgerinshell(const terminal_dev& dev, int fd) {
if (!rf.downloading_file.empty()) { if (!rf.downloading_file.empty()) {
os << "\r\x1B[K |-- downloading: " << rf.downloading_file << "\n"; os << "\r\x1B[K |-- downloading: " << rf.downloading_file << "\n";
} }
// ★新增:已下载/待上报的完整路径file_paths
os << "\r\x1B[K |-- file_paths(" << rf.file_paths.size() << ")\n";
{
size_t c = 0;
for (const auto& p : rf.file_paths) {
if (c++ >= MAX_ITEMS) break;
os << "\r\x1B[K |-- " << p << "\n";
}
if (rf.file_paths.size() > MAX_ITEMS) {
os << "\r\x1B[K |.. (+" << (rf.file_paths.size() - MAX_ITEMS) << " more)\n";
}
}
} }
if (ld.recall_list_static.size() > MAX_ITEMS) { 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 |.. (+" << (ld.recall_list_static.size() - MAX_ITEMS) << " more)\n";

View File

@@ -785,6 +785,8 @@ void process_received_message(string mac, string id,const char* data, size_t len
//send_file_list(id,FileList);//lnk20250813 //send_file_list(id,FileList);//lnk20250813
filemenu_cache_put(id,FileList); filemenu_cache_put(id,FileList);
on_device_response_minimal(static_cast<int>(ResponseCode::OK), id, 0, static_cast<int>(DeviceState::READING_FILEMENU));
// 处理完成后重置状态 // 处理完成后重置状态
ClientManager::instance().change_device_state(id, DeviceState::IDLE); ClientManager::instance().change_device_state(id, DeviceState::IDLE);
} }
@@ -873,7 +875,7 @@ void process_received_message(string mac, string id,const char* data, size_t len
//使用接口上送文件lnk20250826 //使用接口上送文件lnk20250826
std::string filename; std::string filename;
SendFileWeb(WEB_FILEUPLOAD, file_path, file_path, filename);//如果是补招文件的下载,下载后也是直接上传,上传成功后更新补招状态即可 SendFileWebAuto(id, file_path, file_path, filename);//如果是补招文件的下载,下载后也是直接上传,上传成功后更新补招状态即可
std::cout << "File upload: " << filename << std::endl; std::cout << "File upload: " << filename << std::endl;
//通知文件上传 //通知文件上传
@@ -2078,9 +2080,9 @@ void process_received_message(string mac, string id,const char* data, size_t len
<< ", 特征幅值: " << record.fMagntitude << " pu" << ", 特征幅值: " << record.fMagntitude << " pu"
<< ", 时间戳: " << record.triggerTimeMs << "ms" << std::endl; << ", 时间戳: " << record.triggerTimeMs << "ms" << std::endl;
//记录补招上来的暂态事件 //记录补招上来的暂态事件,如果需要前置自行下载波形才需要这个接口
append_qvvr_event(id,event.head.name, /*append_qvvr_event(id,event.head.name,
record.nType,record.fPersisstime,record.fMagntitude,record.triggerTimeMs,record.phase); record.nType,record.fPersisstime,record.fMagntitude,record.triggerTimeMs,record.phase);*/
//直接发走暂态事件 //直接发走暂态事件
transfer_json_qvvr_data(id,event.head.name, transfer_json_qvvr_data(id,event.head.name,
record.fMagntitude,record.fPersisstime,record.triggerTimeMs,record.nType,record.phase,""); record.fMagntitude,record.fPersisstime,record.triggerTimeMs,record.nType,record.phase,"");
@@ -2145,7 +2147,7 @@ void process_received_message(string mac, string id,const char* data, size_t len
else { else {
//其余错误码代表异常情况 //其余错误码代表异常情况
//lnk20251023 //lnk20251023
on_device_response_minimal(static_cast<int>(ResponseCode::BAD_REQUEST), id, 0, static_cast<int>(DeviceState::CUSTOM_ACTION)); on_device_response_minimal(static_cast<int>(ResponseCode::BAD_REQUEST), id, 0, static_cast<int>(DeviceState::READING_EVENTLOG));
} }
// 装置否定 // 装置否定
// 补招装置日志失败,调整为空闲状态,处理下一项工作。 // 补招装置日志失败,调整为空闲状态,处理下一项工作。