add event fun
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "curl/curl.h"
|
||||
#include "log4cplus/log4.h" //关键上送日志
|
||||
#include "log4.h" //关键上送日志
|
||||
#include "interface.h" //台账结构
|
||||
#include "tinyxml2.h"
|
||||
#include "rocketmq.h"
|
||||
@@ -560,6 +560,17 @@ double sGetMsTime() {
|
||||
return static_cast<double>(ms);
|
||||
}
|
||||
|
||||
//秒时间转为标准时间字符串
|
||||
// ★新增:将 epoch 秒级时间转成 "YYYY-MM-DD HH:MM:SS"
|
||||
static std::string epoch_to_datetime_str(long long epoch_sec) {
|
||||
char buf[20];
|
||||
std::tm tm{};
|
||||
time_t t = static_cast<time_t>(epoch_sec);
|
||||
localtime_r(&t, &tm);
|
||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////实时触发部分
|
||||
|
||||
//获取实时触发文件
|
||||
@@ -781,7 +792,7 @@ void check_3s_config() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////补招部分
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////补招文件部分
|
||||
|
||||
//将文件内容读取到结构中
|
||||
void parse_recall(recall_xml_t* recall_xml, const std::string& parentTag, const std::map<std::string, std::string>& attributes, const std::string& id) {
|
||||
@@ -1030,7 +1041,7 @@ void create_recall_xml()
|
||||
CreateRecallXml();
|
||||
//}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////补招部分
|
||||
// 工具函数:将时间字符串转为 time_t(秒级)
|
||||
static long long parse_time_to_epoch(const std::string& time_str) {
|
||||
std::tm tm = {};
|
||||
@@ -1084,7 +1095,6 @@ int recall_json_handle(const std::string& jstr) {
|
||||
int stat = 0;
|
||||
int voltage = 0;
|
||||
try {
|
||||
std::vector<JournalRecall> recallParams;
|
||||
|
||||
// 1. 解析 JSON 数组
|
||||
auto json_root = nlohmann::json::parse(jstr);
|
||||
@@ -1096,7 +1106,9 @@ int recall_json_handle(const std::string& jstr) {
|
||||
// 2. 遍历每个补招项
|
||||
for (auto& item : json_root) {
|
||||
// 获取必需字段
|
||||
if (!item.contains("monitorId") ||
|
||||
// ★修改:强制要求 terminalId;
|
||||
if (!item.contains("terminalId") ||
|
||||
!item.contains("monitor") ||
|
||||
!item.contains("timeInterval") ||
|
||||
!item.contains("dataType"))
|
||||
{
|
||||
@@ -1104,131 +1116,115 @@ int recall_json_handle(const std::string& jstr) {
|
||||
return 10000;
|
||||
}
|
||||
|
||||
// ★新增:读取 terminalId(必填)
|
||||
std::string terminalId = item["terminalId"].get<std::string>();
|
||||
if (terminalId.empty()) {
|
||||
std::cout << "terminalId为空" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2.1 解析 dataType
|
||||
std::string datatype = item["dataType"].get<std::string>();
|
||||
if (!datatype.empty()) {
|
||||
stat = (datatype == "0") ? 1 : 0; // 稳态
|
||||
voltage = (datatype == "1") ? 1 : 0; // 暂态
|
||||
// ★修改:仅保留稳态/暂态
|
||||
if (datatype == "0" || datatype == "稳态" || datatype == "steady" || datatype == "STEADY") {
|
||||
stat = 1; voltage = 0; // 稳态
|
||||
} else if (datatype == "1" || datatype == "暂态" || datatype == "voltage" || datatype == "VOLTAGE") {
|
||||
stat = 0; voltage = 1; // 暂态
|
||||
} else {
|
||||
stat = voltage = 1; // 其他情况按全补
|
||||
}
|
||||
} else {
|
||||
stat = voltage = 1; // 全补
|
||||
stat = voltage = 1; // 全补
|
||||
}
|
||||
|
||||
// 2.2 处理 monitorId 数组
|
||||
auto& midArr = item["monitorId"];
|
||||
auto& tiArr = item["timeInterval"];
|
||||
if (midArr.is_array() && tiArr.is_array() && !midArr.empty()) {
|
||||
for (auto& idItem : midArr) {
|
||||
std::string monitorId = idItem.get<std::string>();
|
||||
// ★新增:定位并校验该 terminal 是否归属当前进程
|
||||
std::lock_guard<std::mutex> lock(ledgermtx);
|
||||
|
||||
// 判断此监测点是否归属当前进程
|
||||
bool mppair = false;
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
// 只处理本进程对应的终端
|
||||
if (std::stoi(dev.processNo) != g_front_seg_index &&
|
||||
g_front_seg_index != 0) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& mon : dev.line) {
|
||||
if (mon.monitor_id.empty()) continue;
|
||||
if (mon.monitor_id == monitorId) {
|
||||
mppair = true;
|
||||
std::cout << "Matched monitorId " << monitorId
|
||||
<< " in terminal " << dev.terminal_id
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mppair) break;
|
||||
}
|
||||
if (!mppair) continue;
|
||||
|
||||
// 遍历 timeInterval 数组
|
||||
for (auto& timeItem : tiArr) {
|
||||
std::string ti = timeItem.get<std::string>();
|
||||
auto pos = ti.find('~');
|
||||
std::string start = ti.substr(0, pos);
|
||||
std::string end = ti.substr(pos + 1);
|
||||
|
||||
JournalRecall param;
|
||||
param.MonitorID = monitorId;
|
||||
param.StartTime = start;
|
||||
param.EndTime = end;
|
||||
param.STEADY = std::to_string(stat);
|
||||
param.VOLTAGE = std::to_string(voltage);
|
||||
recallParams.push_back(param);
|
||||
}
|
||||
const terminal_dev* targetDev = nullptr;
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
// 只处理本进程对应的终端
|
||||
if (dev.terminal_id == terminalId) {
|
||||
targetDev = &dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 2.3 monitorId 数组存在但为空 -> 补招所有监测点
|
||||
else if (midArr.is_array() && midArr.empty()) {
|
||||
std::cout << "monitorIdArray is null,补招所有监测点" << std::endl;
|
||||
for (const auto& dev : terminal_devlist) {
|
||||
if (std::stoi(dev.processNo) != g_front_seg_index &&
|
||||
g_front_seg_index != 0) {
|
||||
if (!targetDev) {
|
||||
std::cout << "terminalId未匹配当前进程内装置: " << terminalId << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ★新增:按新结构解析 monitor 层级
|
||||
auto& monitors = item["monitor"];
|
||||
if (!monitors.is_array() || monitors.empty()) {
|
||||
std::cout << "monitor数组为空或非数组类型" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto& mobj : monitors) {
|
||||
if (!mobj.contains("monitorId") || !mobj.contains("timeInterval")) {
|
||||
std::cout << "monitor项缺少 monitorId 或 timeInterval" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string monitorId = mobj["monitorId"].get<std::string>();
|
||||
if (monitorId.empty()) continue;
|
||||
|
||||
// 不只是判断存在,还要拿到指针 lm 以便后续 push_back
|
||||
ledger_monitor* lm = nullptr;
|
||||
for (auto& mon : const_cast<terminal_dev*>(targetDev)->line) {
|
||||
if (!mon.monitor_id.empty() && mon.monitor_id == monitorId) {
|
||||
lm = &mon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lm) {
|
||||
std::cout << "monitorId未在terminal内找到: " << monitorId
|
||||
<< " @ " << terminalId << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& tiArr = mobj["timeInterval"];
|
||||
if (!tiArr.is_array() || tiArr.empty()) {
|
||||
std::cout << "timeInterval为空或非数组类型: monitorId=" << monitorId << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 这里拆分时间段并 push 到 lm->recall_list
|
||||
for (auto& timeItem : tiArr) {
|
||||
std::string ti = timeItem.get<std::string>();
|
||||
auto pos = ti.find('~');
|
||||
if (pos == std::string::npos) {
|
||||
std::cout << "timeInterval格式错误: " << ti << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (const auto& mon : dev.line) {
|
||||
if (mon.monitor_id.empty()) continue;
|
||||
for (auto& timeItem : tiArr) {
|
||||
std::string ti = timeItem.get<std::string>();
|
||||
auto pos = ti.find('~');
|
||||
std::string start = ti.substr(0, pos);
|
||||
std::string end = ti.substr(pos + 1);
|
||||
|
||||
JournalRecall param;
|
||||
param.MonitorID = mon.monitor_id;
|
||||
param.StartTime = start;
|
||||
param.EndTime = end;
|
||||
param.STEADY = std::to_string(stat);
|
||||
param.VOLTAGE = std::to_string(voltage);
|
||||
recallParams.push_back(param);
|
||||
}
|
||||
std::string start = ti.substr(0, pos);
|
||||
std::string end = ti.substr(pos + 1);
|
||||
|
||||
// 拆分时间段为 1 小时一段,并存入 recall_list
|
||||
std::vector<RecallInfo> recallinfo_list_hour;
|
||||
Get_Recall_Time_Char(start, end, recallinfo_list_hour);
|
||||
|
||||
for (auto& info : recallinfo_list_hour) {
|
||||
RecallMonitor rm;
|
||||
rm.recall_status = 0; // 初始状态:未补招
|
||||
rm.StartTime = epoch_to_datetime_str(info.starttime); // 需要你已有的工具函数
|
||||
rm.EndTime = epoch_to_datetime_str(info.endtime);
|
||||
rm.STEADY = std::to_string(stat);
|
||||
rm.VOLTAGE = std::to_string(voltage);
|
||||
|
||||
lm->recall_list.push_back(std::move(rm)); // ★逐一压入
|
||||
|
||||
// 可选:调试打印
|
||||
std::cout << "[recall_json_handle] terminal=" << terminalId
|
||||
<< " monitor=" << monitorId
|
||||
<< " start=" << lm->recall_list.back().StartTime
|
||||
<< " end=" << lm->recall_list.back().EndTime
|
||||
<< " steady="<< lm->recall_list.back().STEADY
|
||||
<< " voltage="<< lm->recall_list.back().VOLTAGE
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "monitorIdArray 不存在或类型不正确" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 生成具体补招记录
|
||||
for (auto& rp : recallParams) {
|
||||
std::string start_time = rp.StartTime;
|
||||
std::string end_time = rp.EndTime;
|
||||
|
||||
std::cout << "mp_id " << rp.MonitorID
|
||||
<< " start_time " << start_time
|
||||
<< " end_time " << end_time
|
||||
<< " stat " << rp.STEADY
|
||||
<< " voltage " << rp.VOLTAGE
|
||||
<< std::endl;
|
||||
|
||||
std::vector<RecallInfo> recallinfo_list_hour;
|
||||
Get_Recall_Time_Char(start_time, end_time, recallinfo_list_hour);
|
||||
|
||||
for (auto& info : recallinfo_list_hour) {
|
||||
JournalRecall jr;
|
||||
jr.MonitorID = rp.MonitorID;
|
||||
|
||||
// 转换 starttime
|
||||
char buf[20];
|
||||
std::tm tm{};
|
||||
time_t st = static_cast<time_t>(info.starttime);
|
||||
localtime_r(&st, &tm);
|
||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
|
||||
jr.StartTime = buf;
|
||||
|
||||
// 转换 endtime
|
||||
std::tm tm2{};
|
||||
time_t et = static_cast<time_t>(info.endtime);
|
||||
localtime_r(&et, &tm2);
|
||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm2);
|
||||
jr.EndTime = buf;
|
||||
|
||||
jr.STEADY = rp.STEADY;
|
||||
jr.VOLTAGE = rp.VOLTAGE;
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_StatisticLackList_list_mutex);
|
||||
g_StatisticLackList.push_back(jr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3764,4 +3760,400 @@ bool send_internal_value_reply(const std::string &dev_id, const std::vector<DZ_k
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////清空运行状态
|
||||
// 清理指定 terminal_id 的运行时状态
|
||||
void clear_terminal_runtime_state(const std::string& id) {
|
||||
std::lock_guard<std::mutex> lock(ledgermtx); // 加锁保证线程安全
|
||||
|
||||
for (auto& dev : terminal_devlist) {
|
||||
if (dev.terminal_id == id) {
|
||||
dev.guid.clear(); // 清空 guid
|
||||
dev.busytype = 0; // 业务类型归零
|
||||
dev.isbusy = 0; // 清空业务标志
|
||||
dev.busytimecount = 0; // 计时归零
|
||||
std::cout << "[clear_terminal_runtime_state] Cleared runtime state for terminal_id="
|
||||
<< id << std::endl;
|
||||
break; // 找到后跳出
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////处理补招逻辑
|
||||
// ===== 一次遍历可下发“多个终端的一条” =====
|
||||
void check_recall_event() {
|
||||
|
||||
std::vector<RecallTask> tasks; // 本轮要发送的“每终端一条”
|
||||
std::vector<std::string> empty_devs_to_clear; // 本轮发现已无任务的终端,解锁后统一清理
|
||||
|
||||
{ //锁作用域
|
||||
std::lock_guard<std::mutex> lock(ledgermtx);
|
||||
|
||||
// 遍历所有 terminal —— 每个 terminal 只挑一条
|
||||
for (auto& dev : terminal_devlist) {
|
||||
// 1) 先弹掉首条为 DONE/FAILED 的记录(所有 monitor 都要处理首条)
|
||||
bool any_non_empty = false;
|
||||
for (auto& lm : dev.line) {
|
||||
while (!lm.recall_list.empty()) {
|
||||
const RecallMonitor& front = lm.recall_list.front();
|
||||
if (front.recall_status == static_cast<int>(RecallStatus::DONE)) {
|
||||
std::cout << "[check_recall_work] DONE dev=" << dev.terminal_id
|
||||
<< " monitor=" << lm.monitor_id
|
||||
<< " " << front.StartTime << " ~ " << front.EndTime << std::endl;
|
||||
|
||||
//调用reply接口通知web端补招完成
|
||||
|
||||
|
||||
lm.recall_list.pop_front(); // 弹掉首条
|
||||
} else if (front.recall_status == static_cast<int>(RecallStatus::FAILED)) {
|
||||
std::cout << "[check_recall_work] FAILED dev=" << dev.terminal_id
|
||||
<< " monitor=" << lm.monitor_id
|
||||
<< " " << front.StartTime << " ~ " << front.EndTime << std::endl;
|
||||
|
||||
//调用reply接口通知web端补招失败
|
||||
|
||||
|
||||
lm.recall_list.pop_front(); // 弹掉首条
|
||||
} else {
|
||||
break; // 首条不是 2/3,停
|
||||
}
|
||||
}
|
||||
if (!lm.recall_list.empty()) any_non_empty = true; // 处理了成功和失败的以后只要有一条非空就标记,可能是待处理或者正在处理的补招
|
||||
}
|
||||
|
||||
if (!any_non_empty) {
|
||||
// 该终端本轮已无任何补招条目,等解锁后清空运行态
|
||||
empty_devs_to_clear.push_back(dev.terminal_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2) 若任一 monitor 的首条为 RUNNING,则该终端正在补招中 -> 跳过该终端
|
||||
bool has_running = false;
|
||||
for (auto& lm : dev.line) {
|
||||
if (!lm.recall_list.empty() &&
|
||||
lm.recall_list.front().recall_status == static_cast<int>(RecallStatus::RUNNING)) {
|
||||
has_running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_running) continue;
|
||||
|
||||
// 3) 选择该终端的“第一条 NOT_STARTED(0)”作为本终端本轮任务
|
||||
bool picked = false;
|
||||
for (auto& lm : dev.line) {
|
||||
if (lm.recall_list.empty()) continue;
|
||||
|
||||
RecallMonitor& front = lm.recall_list.front();
|
||||
if (front.recall_status == static_cast<int>(RecallStatus::NOT_STARTED)) {
|
||||
// 标记为 RUNNING,并设置终端忙状态
|
||||
front.recall_status = static_cast<int>(RecallStatus::RUNNING);
|
||||
|
||||
dev.isbusy = 1;
|
||||
dev.busytype = static_cast<int>(DeviceState::READING_EVENTLOG);
|
||||
dev.busytimecount = 0;
|
||||
// 如需 guid,可在此生成 dev.guid = new_guid();
|
||||
|
||||
// 记录任务(每终端只取这一条)
|
||||
tasks.push_back(RecallTask{
|
||||
dev.terminal_id,
|
||||
front.StartTime,
|
||||
front.EndTime,
|
||||
lm.monitor_id
|
||||
});
|
||||
picked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 若该终端没有 NOT_STARTED 的首条(可能剩下的都是 RUNNING 或内部已经被清空),
|
||||
// 就留待下一轮;不要清空运行态,直到所有条目被处理为止。
|
||||
}
|
||||
} // 解锁
|
||||
|
||||
// 先处理“已空终端”的运行态清理,如果在上面循环中直接清理,可能会与正在处理的补招冲突。而且就算上面解锁后写了新的补招,也会在下一轮被执行。
|
||||
for (const auto& id : empty_devs_to_clear) {
|
||||
clear_terminal_runtime_state(id);
|
||||
}
|
||||
|
||||
// 对于本轮挑选到的任务,逐终端下发一条,这些终端的状态都已设为补招
|
||||
for (const auto& t : tasks) {
|
||||
std::tm tm1{}, tm2{};
|
||||
if (!parse_datetime_tm(t.start_time, tm1) || !parse_datetime_tm(t.end_time, tm2)) {
|
||||
std::cout << "[check_recall_event] parse time fail: "
|
||||
<< t.start_time << " ~ " << t.end_time << std::endl;
|
||||
// 视情况:标记失败/弹出/继续下一个
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t mp = 1; // 默认
|
||||
try {
|
||||
mp = static_cast<uint8_t>(std::stoi(t.monitor_index));
|
||||
} catch (...) { /* 保持默认1或根据需要处理 */ }
|
||||
|
||||
ClientManager::instance().read_eventlog_action_to_device(
|
||||
t.dev_id, tm1, tm2, 2, mp);//2是暂态事件
|
||||
|
||||
std::cout << "[check_recall_event] SEND dev=" << t.dev_id
|
||||
<< " monitor=" << mp
|
||||
<< " start=" << t.start_time
|
||||
<< " end=" << t.end_time
|
||||
<< " action(2)" << std::endl;
|
||||
}
|
||||
|
||||
// 重要:本函数不把 RUNNING 改成 DONE/FAILED;
|
||||
// 应由设备回调/结果处理逻辑在完成后调用通知函数,把对应 monitor.front().recall_status 从1置为 2/3,
|
||||
// 下一轮本函数会弹掉 2/3,并在该终端所有 recall_list 全部清空后调用 clear_terminal_runtime_state()。
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////通讯响应处理
|
||||
void on_device_response_minimal(int response_code,
|
||||
const std::string& id,
|
||||
unsigned char cid,
|
||||
int device_state_int)
|
||||
{
|
||||
const bool ok = is_ok(response_code);
|
||||
DeviceState state = static_cast<DeviceState>(device_state_int);
|
||||
|
||||
switch (state) {
|
||||
// ================= 特殊:补招事件日志 =================
|
||||
case DeviceState::READING_EVENTLOG: {
|
||||
std::lock_guard<std::mutex> lk(ledgermtx);
|
||||
|
||||
terminal_dev* dev = nullptr;
|
||||
for (auto& d : terminal_devlist) {
|
||||
if (d.terminal_id == id) { dev = &d; break; }
|
||||
}
|
||||
if (!dev) {
|
||||
std::cout << "[RESP][EVENTLOG] dev not found, id=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 找到“首条 RUNNING”的补招条目,按 rc==200 成功/失败标记
|
||||
bool updated = false;
|
||||
|
||||
// 1) 找到 logical_device_seq 与 cid 匹配的 monitor
|
||||
ledger_monitor* matched_monitor = nullptr;
|
||||
|
||||
// 将 cid 转成十进制字符串用于直接比较
|
||||
const std::string cid_str = std::to_string(static_cast<int>(cid));
|
||||
|
||||
for (auto& lm : dev->line) {
|
||||
// 直接字符串相等
|
||||
if (lm.logical_device_seq == cid_str) {
|
||||
matched_monitor = &lm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched_monitor) { //没有匹配的监测点
|
||||
std::cout << "[RESP][EVENTLOG][WARN] dev=" << id
|
||||
<< " cannot find monitor by cid=" << static_cast<int>(cid)
|
||||
<< " (no logical_device_seq match)" << std::endl;
|
||||
}
|
||||
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(); //取出首条
|
||||
if (front.recall_status == static_cast<int>(RecallStatus::RUNNING)) { //正在补招
|
||||
if (ok) { //补招成功
|
||||
front.recall_status = static_cast<int>(RecallStatus::DONE); //标记为完成,补招任务会执行下一条
|
||||
std::cout << "[RESP][EVENTLOG][OK] dev=" << id
|
||||
<< " mon=" << matched_monitor->monitor_id
|
||||
<< " " << front.StartTime << "~" << front.EndTime
|
||||
<< std::endl;
|
||||
} else { //补招失败
|
||||
front.recall_status = static_cast<int>(RecallStatus::FAILED);
|
||||
std::cout << "[RESP][EVENTLOG][FAIL] dev=" << id
|
||||
<< " mon=" << matched_monitor->monitor_id
|
||||
<< " " << front.StartTime << "~" << front.EndTime
|
||||
<< " 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);
|
||||
}
|
||||
updated = true;
|
||||
} else { //首条不是 RUNNING 状态,不应该收到这条响应
|
||||
std::cout << "[RESP][EVENTLOG][WARN] dev=" << id
|
||||
<< " mon=" << matched_monitor->monitor_id
|
||||
<< " first item not RUNNING (status="
|
||||
<< front.recall_status << ")" << std::endl; //打印调试
|
||||
}
|
||||
} else { //补招列表为空,不应该收到这条响应
|
||||
std::cout << "[RESP][EVENTLOG][WARN] dev=" << id
|
||||
<< " mon=" << matched_monitor->monitor_id
|
||||
<< " recall_list empty" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!updated) {//不更新补招列表
|
||||
std::cout << "[RESP][EVENTLOG][WARN] no RUNNING item, dev=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// ================= 特殊:读取文件目录 =================
|
||||
case DeviceState::READING_FILEMENU: {
|
||||
std::lock_guard<std::mutex> lk(ledgermtx);
|
||||
|
||||
// 1) 找到对应终端
|
||||
terminal_dev* dev = nullptr;
|
||||
for (auto& d : terminal_devlist) {
|
||||
if (d.terminal_id == id) { dev = &d; break; }
|
||||
}
|
||||
if (!dev) {
|
||||
std::cout << "[RESP][FILEMENU] dev not found, id=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 2) 按该终端当前 busytype 分支处理
|
||||
const int bt = dev->busytype;
|
||||
if (bt == static_cast<int>(DeviceState::READING_FILEMENU)) {
|
||||
// ====== 分支 A:当前业务就是“读取文件目录” ======
|
||||
if (ok) {
|
||||
// 成功:复位
|
||||
dev->guid.clear();
|
||||
dev->isbusy = 0;
|
||||
dev->busytype = 0;
|
||||
dev->busytimecount = 0;
|
||||
std::cout << "[RESP][FILEMENU->FILEMENU][OK] dev=" << id << std::endl;
|
||||
} else {
|
||||
// 失败:响应web并复位为空闲
|
||||
send_reply_to_cloud(response_code, id, static_cast<int>(DeviceState::READING_FILEMENU));
|
||||
|
||||
dev->guid.clear();
|
||||
dev->isbusy = 0;
|
||||
dev->busytype = 0;
|
||||
dev->busytimecount = 0;
|
||||
std::cout << "[RESP][FILEMENU->FILEMENU][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
bt == static_cast<int>(DeviceState::READING_EVENTFILE)
|
||||
|| bt == static_cast<int>(DeviceState::READING_STATSFILE)
|
||||
) {
|
||||
// ====== 分支 B:当前业务为“下载事件文件/统计文件”(两者处理相同) ======
|
||||
if (ok) {
|
||||
// 成功:通常紧接着进入读取文件数据阶段
|
||||
|
||||
std::cout << "[RESP][FILEMENU->FILEDATA][OK] dev=" << id << std::endl;
|
||||
} else {
|
||||
// 失败:尝试下一个目录
|
||||
|
||||
std::cout << "[RESP][FILEMENU->(EVENT/STATS)FILE][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ====== 分支 C:其他业务场景下收到 FILEMENU 响应,统一处理 打印提示======
|
||||
if (ok) {
|
||||
// 成功:
|
||||
|
||||
std::cout << "[unknown][RESP][FILEMENU->OTHER][OK] dev=" << id
|
||||
<< " keep busytype=" << bt << std::endl;
|
||||
} else {
|
||||
// 失败:
|
||||
|
||||
std::cout << "[unknown][RESP][FILEMENU->OTHER][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << " prev busytype=" << bt << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ================= 特殊:下载文件 =================
|
||||
case DeviceState::READING_FILEDATA: {
|
||||
std::lock_guard<std::mutex> lk(ledgermtx);
|
||||
|
||||
// 1) 找到对应终端
|
||||
terminal_dev* dev = nullptr;
|
||||
for (auto& d : terminal_devlist) {
|
||||
if (d.terminal_id == id) { dev = &d; break; }
|
||||
}
|
||||
if (!dev) {
|
||||
std::cout << "[RESP][FILEDATA] dev not found, id=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 2) 按该终端当前 busytype 分支处理
|
||||
const int bt = dev->busytype;
|
||||
if (bt == static_cast<int>(DeviceState::READING_FILEDATA)) {
|
||||
// ====== 分支 A:当前业务就是“读取文件数据” ======
|
||||
if (ok) {
|
||||
// 成功:复位
|
||||
send_reply_to_cloud(static_cast<int>(ResponseCode::OK), id, static_cast<int>(DeviceState::READING_FILEDATA));
|
||||
|
||||
dev->guid.clear();
|
||||
dev->isbusy = 0;
|
||||
dev->busytype = 0;
|
||||
dev->busytimecount = 0;
|
||||
std::cout << "[RESP][FILEDATA->FILEDATA][OK] dev=" << id << std::endl;
|
||||
} else {
|
||||
// 失败:响应web并复位
|
||||
send_reply_to_cloud(response_code, id, static_cast<int>(DeviceState::READING_FILEDATA));
|
||||
|
||||
dev->guid.clear();
|
||||
dev->isbusy = 0;
|
||||
dev->busytype = 0;
|
||||
dev->busytimecount = 0;
|
||||
std::cout << "[RESP][FILEDATA->FILEDATA][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
bt == static_cast<int>(DeviceState::READING_EVENTFILE)
|
||||
|| bt == static_cast<int>(DeviceState::READING_STATSFILE)
|
||||
) {
|
||||
// ====== 分支 B:当前业务为“下载事件文件/统计文件”(两者处理相同) ======
|
||||
if (ok) {
|
||||
// 成功:通常紧接着进入读取文件数据阶段
|
||||
|
||||
std::cout << "[RESP][FILEDATA->(EVENT/STATS)FILE][OK] dev=" << id << std::endl;
|
||||
} else {
|
||||
// 失败:尝试下一个目录
|
||||
|
||||
std::cout << "[RESP][FILEDATA->(EVENT/STATS)FILE][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ====== 分支 C:其他业务场景下收到 FILEDATA 响应,统一处理 打印提示======
|
||||
if (ok) {
|
||||
// 成功:
|
||||
|
||||
std::cout << "[unknown][RESP][FILEDATA->OTHER][OK] dev=" << id
|
||||
<< " keep busytype=" << bt << std::endl;
|
||||
} else {
|
||||
// 失败:
|
||||
|
||||
std::cout << "[unknown][RESP][FILEDATA->OTHER][FAIL] dev=" << id
|
||||
<< " rc=" << response_code << " prev busytype=" << bt << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ================= 其它状态统一处理 =================
|
||||
default: {
|
||||
|
||||
//直接根据输入响应mq
|
||||
send_reply_to_cloud(response_code, id, device_state_int);
|
||||
|
||||
//其他的错误和成功都会结束业务
|
||||
clear_terminal_runtime_state(id);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user