From 9dc138a617e4e7b8a3df61fb18d1d11cbe1fcc6b Mon Sep 17 00:00:00 2001 From: lnk Date: Fri, 5 Sep 2025 16:28:26 +0800 Subject: [PATCH] finish dz function --- LFtid1056/cloudfront/code/cfg_parser.cpp | 210 +++++++++++++++++++---- LFtid1056/cloudfront/code/interface.cpp | 2 + LFtid1056/cloudfront/code/interface.h | 38 +++- LFtid1056/cloudfront/code/rocketmq.cpp | 30 +--- LFtid1056/cloudfront/code/worker.cpp | 210 ++++++++++++++++++++--- LFtid1056/dealMsg.cpp | 39 ++++- 6 files changed, 431 insertions(+), 98 deletions(-) diff --git a/LFtid1056/cloudfront/code/cfg_parser.cpp b/LFtid1056/cloudfront/code/cfg_parser.cpp index cb068cc..88fa405 100644 --- a/LFtid1056/cloudfront/code/cfg_parser.cpp +++ b/LFtid1056/cloudfront/code/cfg_parser.cpp @@ -2737,34 +2737,34 @@ bool compare_qvvr_and_file(const std::string& cfg_path, const std::vector &fabsf) { +bool save_internal_value(const std::string &dev_id, const std::vector &fabsf) { // 找到对应 terminal_dev std::lock_guard lock(ledgermtx); @@ -3474,6 +3474,12 @@ bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, con return false; } + //将dz_info存入监测点 + pMon->dz_info_list.clear(); + for (const auto &dz : dz_info) { + pMon->dz_info_list.push_back(dz); + } + // 4) 取该监测点的 set_values,严格按顺序用于 DZ_Value std::vector ordered_vals; ordered_vals.reserve(pMon->set_values.size()); @@ -3565,47 +3571,175 @@ bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, con return true; } -bool send_internal_value_reply(const std::string &dev_id, const std::vector &control_words) { +/////////////////////////////////////////////////////////////////////////////////////////////////////////回复内部定值响应读取 + + +bool send_internal_value_reply(const std::string &dev_id, const std::vector &control_words) +{ std::lock_guard lock(ledgermtx); // 1) 找终端 auto it = std::find_if(terminal_devlist.begin(), terminal_devlist.end(), [&](const terminal_dev &d) { return d.terminal_id == dev_id; }); if (it == terminal_devlist.end()) { - std::cerr << "[send_set_value_reply] device not found: " << dev_id << std::endl; + std::cerr << "[send_internal_value_reply] device not found: " << dev_id << std::endl; return false; } terminal_dev &dev = *it; - // 2) 校验状态:发送“定值读取结果”回复,应处于 READING_INTERFIXEDVALUE;isbusy == 1 - if (dev.isbusy != 1 || dev.busytype != static_cast(DeviceState::READING_INTERFIXEDVALUE)) { //定值读取 - std::cerr << "[send_set_value_reply] device not in READING_INTERFIXEDVALUE state." << std::endl; + // 2) 校验状态:发送“内部定值读取结果”回复,应处于 READING_INTERFIXEDVALUE;isbusy == 1 + if (dev.isbusy != 1 || dev.busytype != static_cast(DeviceState::READING_INTERFIXEDVALUE)) { + std::cerr << "[send_internal_value_reply] device not in READING_INTERFIXEDVALUE state." << std::endl; return false; } - // 5) 生成 JSON(结构严格贴合你给的样例) - nlohmann::json j; + //将control_words存入dev + dev.control_words.clear(); + for (const auto &cw : control_words) { + dev.control_words.push_back(cw); + } - // 顶层 + // -------------------- [新增] 建立 internal_values 与 dz_internal_info_list 的一一对应 -------------------- + // 说明:按索引次序一一对应(第 i 个 NameFixValue 对应 internal_values 的第 i 个) + // 若数量不同,按 min 对齐,忽略多出来的一边并告警。 + std::vector internal_vals; // [新增] + internal_vals.reserve(dev.internal_values.size()); // [新增] + for (float v : dev.internal_values) internal_vals.push_back(v); // [新增] + + const size_t n_dz = dev.dz_internal_info_list.size(); // [新增] + const size_t n_val = internal_vals.size(); // [新增] + const size_t n_use = std::min(n_dz, n_val); // [新增] + if (n_dz != n_val) { // [新增] + std::cerr << "[send_internal_value_reply] WARN: dz_internal_info_list size(" + << n_dz << ") != internal_values size(" << n_val + << "), will use min(" << n_use << ")." << std::endl; + } + // ------------------------------------------------------------------------------------------------------ + + // 3) 组包顶层 + nlohmann::json j; j["guid"] = dev.guid; - j["FrontIP"] = FRONT_IP; // 你的前置机 IP(项目已有常量/变量) - j["Node"] = g_front_seg_index; // 节点号(项目已有变量) + j["FrontIP"] = FRONT_IP; + j["Node"] = g_front_seg_index; j["Dev_mac"] = normalize_mac(dev.addr_str); - // Detail nlohmann::json detail; detail["Type"] = 0x2106; // 设备数据 - - // Msg nlohmann::json msg; - msg["DataType"] = 0x0D; //内部定值 + msg["DataType"] = 0x0D; // 内部定值 - // DataArray(对象数组):逐个填充,DZ_Value 严格按 set_values 顺序 - nlohmann::json dataArray = nlohmann::json::array(); + // 4) === 将 C# 的拼接逻辑移植为 DataArray === + // C# 变量对应关系: + // DevInfo.nDevIndex -> 这里用 1 + // DevInfo.strGuId -> 这里用 装置id + // DevInfo.controlwordlist -> 这里用参数 control_words(DZ_kzz_bit 含 kzz_bit/bit_enable) + // + // NameFixValue 列表:使用 dev.dz_internal_info_list + // + // 关键逻辑: + // - 遍历每个 NameFixValue,k 从 1 递增,nStep 每个定值递增 1 + // - 若 DataType == 1:将 Max/Min/Default 都 /100,并 property 输出一个空对象 [{}](保持与 C# 一致) + // - 否则:为该定值构建 property 位数组,范围 [nStep*16, (nStep+1)*16), + // 名称为空则提前结束本定值的 property;flag = (DefaultValue >> j) & 0x01 + // - //拼接逻辑 + nlohmann::json dataArray = nlohmann::json::array(); // [新增] - // 6) 入队发送 + int nStep = 0; // [新增] 每个 NameFixValue 递增 + int kSort = 1; // [新增] 排序号,从 1 开始 + + // 保护:dz_internal_info_list 是引用成员,确保不会因并发被改动(当前已在 ledgermtx 下) + //for (const auto& nf : dev.dz_internal_info_list) { // [新增] + for (size_t idxNF = 0; idxNF < n_use; ++idxNF) { // [修改] 使用 idxNF 控制索引 + const auto& nf = dev.dz_internal_info_list[idxNF]; + // 取字段 + const uint16_t dataType = nf.DataType; + const uint16_t minRaw = nf.MinValue; + const uint16_t maxRaw = nf.MaxValue; + const uint16_t defaultRaw = nf.DefaultValue; + const std::string unit = trim_cstr(nf.sDimension, sizeof(nf.sDimension)); + const std::string name = trim_cstr(nf.sFixValueName, sizeof(nf.sFixValueName)); + + // 取对应内部值 + const float internal_v_raw = internal_vals[idxNF]; // [新增] + const double internal_v_out = static_cast(internal_v_raw); // [新增] 直接转 double 输出,不缩放 + + // 构造一条记录 + nlohmann::json one; + one["cpu_no"] = 1; // [新增] C#: DevInfo.nDevIndex 填设备号,固定为1 + one["dev_type"] = dev_id; // [新增] C#: DevInfo.strGuId 填装置id + one["type"] = 90; // [新增] 固定 "90" + one["unit"] = unit; // [新增] + one["describe"] = name; // [新增] + one["sort"] = kSort; // [新增] + one["Internal_Value"] = internal_v_out; // [新增] 精确对应 internal_values 的值(含必要缩放) + + // 数值:DataType == 1 时缩放 /100 + if (dataType == 1) { // [新增] 缩放分支 + int ChangeMaxValue = static_cast(maxRaw) / 100; + int ChangeMinValue = static_cast(minRaw) / 100; + int ChangeDefaultValue = static_cast(defaultRaw) / 100; + + one["maxvalue"] = ChangeMaxValue; + one["minvalue"] = ChangeMinValue; + one["defaultvalue"] = ChangeDefaultValue; + one["value"] = ChangeDefaultValue; + + // C# 在该分支 property 写成 [{ }](一个空对象的数组) + nlohmann::json prop = nlohmann::json::array(); + prop.push_back(nlohmann::json::object()); // [{}] + one["property"] = std::move(prop); + } else { // [新增] 未缩放分支 + property 位描述 + one["maxvalue"] = static_cast(maxRaw); + one["minvalue"] = static_cast(minRaw); + one["defaultvalue"] = static_cast(defaultRaw); + one["value"] = static_cast(defaultRaw); + + // 构建 property:16 位窗口,从 nStep*16 到 (nStep+1)*16 - 1 + nlohmann::json prop = nlohmann::json::array(); + bool hasAny = false; + + const int begin = nStep * 16; + const int end = (nStep + 1) * 16; // 不含 end + + for (int idx = begin, jbit = 0; idx < end; ++idx, ++jbit) { + if (idx < 0 || static_cast(idx) >= control_words.size()) break; + + // 名称空则提前退出(仿 C#:temp=="" break) + const std::string cw_name = trim_cstr(control_words[idx].kzz_bit, sizeof(control_words[idx].kzz_bit)); + if (cw_name.empty()) { + // 注意:C# 如果 j==0 则设置了 flag2=1,仅用于逗号处理,这里不需要 + break; + } + + int flag = (defaultRaw >> jbit) & 0x01; // 取该位默认值 + nlohmann::json bitItem; + bitItem["type_num"] = jbit; + bitItem["bit0"] = ""; // 保持与 C# 一致 + bitItem["bit1"] = ""; + bitItem["describe"] = cw_name; + bitItem["flag"] = (flag ? "1" : "0"); // C# 用字符串 + prop.push_back(std::move(bitItem)); + hasAny = true; + } + + if (!hasAny) { + // 与 C# 对齐:如果一个都没有,就给 [{}] 以避免 "property":[] 的结构差异 + prop.push_back(nlohmann::json::object()); + } + one["property"] = std::move(prop); + } + + dataArray.push_back(std::move(one)); // [新增] + ++nStep; // [新增] 进入下一个 16 位窗口 + ++kSort; // [新增] + } + + msg["DataArray"] = std::move(dataArray); // [新增] + detail["Msg"] = std::move(msg); + j["Detail"] = std::move(detail); + + // 5) 入队发送(保持你的队列逻辑) queue_data_t connect_info; connect_info.strTopic = Topic_Reply_Topic; connect_info.strText = j.dump(); // 序列化为字符串 @@ -3618,15 +3752,15 @@ bool send_internal_value_reply(const std::string &dev_id, const std::vector 0) { dev.isbusy--; } if (dev.isbusy == 0) { dev.guid.clear(); dev.busytype = 0; - dev.internal_values.clear();//清理本次定值记录 - dev.dz_internal_info_list.clear();//清理本次定值描述记录 + dev.internal_values.clear(); // 清理本次定值记录 + dev.dz_internal_info_list.clear(); // 清理本次定值描述记录(注意:如果这是引用成员,确保其实际容器存在) } return true; diff --git a/LFtid1056/cloudfront/code/interface.cpp b/LFtid1056/cloudfront/code/interface.cpp index ba75ae3..cd2d288 100644 --- a/LFtid1056/cloudfront/code/interface.cpp +++ b/LFtid1056/cloudfront/code/interface.cpp @@ -757,6 +757,7 @@ int parse_device_cfg_web() dev.isbusy = 0; // [新增] 未进行业务 dev.busytimecount = 0; // [新增] 业务计时清零 dev.internal_values.clear(); // [新增] 内部定值清空,等后续业务真实填充 + dev.dz_internal_info_list.clear(); // [新增] 内部定值信息清空,等后续业务真实填充 // ------------------------------------------------------------------------------------ // ======= [新增] 对每个监测点做必要的内部结构初始化 ======= @@ -767,6 +768,7 @@ int parse_device_cfg_web() // 定值列表清理,等待后续配置/采集填充 mon.set_values.clear(); // [新增] + mon.dz_info_list.clear(); // [新增] } // ------------------------------------------------------------------------------------ diff --git a/LFtid1056/cloudfront/code/interface.h b/LFtid1056/cloudfront/code/interface.h index f91fdf3..7cb6b14 100644 --- a/LFtid1056/cloudfront/code/interface.h +++ b/LFtid1056/cloudfront/code/interface.h @@ -96,11 +96,13 @@ public: double CT1; // 电流变比1 double CT2; // 电流变比2 - qvvr_event qvvrevent; //暂态事件 + //暂态事件 + qvvr_event qvvrevent; //定值list std::list set_values; std::vector dz_info_list; //定值信息列表 + }; //终端台账 @@ -113,8 +115,8 @@ public: int busytimecount; //业务进行计时 //内部定值list - std::list internal_values; - std::vector &dz_internal_info_list; //内部定值信息列表 + std::list internal_values; + std::vector dz_internal_info_list; //内部定值信息列表 std::vector control_words; std::string terminal_id; @@ -515,7 +517,35 @@ void send_reply_to_cloud(int reply_code, const std::string& dev_id, int type); //查guid std::string find_guid_index_from_dev_id(const std::string& dev_id); -// +//内部定值响应 +bool send_internal_value_reply(const std::string &dev_id, const std::vector &control_words); + +//定值响应 +bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, const std::vector &dz_info); + +//保存内部定值描述 +bool save_internal_info(const std::string &dev_id, const std::vector &fixValueList); + +//保存内部定值数值 +bool save_internal_value(const std::string &dev_id, const std::vector &fabsf); + +//保存定值数值 +bool save_set_value(const std::string &dev_id, unsigned char mp_index, const std::vector &fabsf); + +//发送文件 +void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath); + +//小工具 +inline std::string trim_cstr(const char* s, size_t n) { + if (!s) return {}; + size_t end = 0; + while (end < n && s[end] != '\0') ++end; + std::string out(s, s + end); + while (!out.empty() && (out.back() == ' ' || out.back() == '\t' || out.back() == '\r' || out.back() == '\n')) + out.pop_back(); + return out; +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// extern int g_front_seg_index; extern std::string FRONT_IP; diff --git a/LFtid1056/cloudfront/code/rocketmq.cpp b/LFtid1056/cloudfront/code/rocketmq.cpp index caaf4e9..c93e361 100644 --- a/LFtid1056/cloudfront/code/rocketmq.cpp +++ b/LFtid1056/cloudfront/code/rocketmq.cpp @@ -429,7 +429,7 @@ std::string parseJsonMessageRC(const std::string& inputJson) { } } -bool parseJsonMessageRT(const std::string& body,std::string& devSeries,std::string& line,bool& realData,bool& soeData,int& limit){ +bool parseJsonMessageRT(const std::string& body,std::string& devSeries,ushort& line,bool& realData,bool& soeData,int& limit){ json root; try { root = json::parse(body); @@ -472,7 +472,7 @@ bool parseJsonMessageRT(const std::string& body,std::string& devSeries,std::stri try { devSeries = messageBody["devSeries"].get(); - line = messageBody["line"].get(); + line = messageBody["line"].get(); realData = messageBody["realData"].get(); soeData = messageBody["soeData"].get(); limit = messageBody["limit"].get(); @@ -859,7 +859,8 @@ rocketmq::ConsumeStatus myMessageCallbackrtdata(const rocketmq::MQMessageExt& ms } // 消息解析 - std::string devid, line; + std::string devid; + ushort line; bool realData = false, soeData = false; int limit = 0; @@ -870,33 +871,16 @@ rocketmq::ConsumeStatus myMessageCallbackrtdata(const rocketmq::MQMessageExt& ms } // 加锁访问台账 - int dev_index; - int mp_index; - if( !devid.empty() && !line.empty()){ - std::lock_guard lock(ledgermtx); - dev_index = find_dev_index_from_dev_id(devid); - mp_index = find_mp_index_from_mp_id(line); + if( !devid.empty() && line > 0){ + //不再使用文件触发方式,直接调用接口向终端发起请求 + ClientManager::instance().set_real_state_count(devid, 60, line);//一秒询问一次,询问60次,下一次同一个测点调用的话就会刷新 } else{ std::cerr << "rtdata is NULL." << std::endl; DIY_ERRORLOG("process","【ERROR】前置的%d号进程处理topic:%s_%s的补招触发消息失败,消息的json结构不正确", g_front_seg_index,FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_RT.c_str()); - } - - - if (dev_index == -1 || mp_index == -1) { - std::cerr << "dev index or mp index is not found" << std::endl; return rocketmq::RECONSUME_LATER; } - // 写入 XML - /*if (!createXmlFile(dev_index, mp_index, realData, soeData, limit, "new")) { - DIY_ERRORLOG("process", "【ERROR】前置无法创建实时数据触发文件"); - std::cerr << "Failed to create the XML file." << std::endl; - return rocketmq::RECONSUME_LATER; - }*/ - //不再使用文件触发方式,直接调用接口向终端发起请求 - ClientManager::instance().set_real_state_count(devid, 60,mp_index);//一秒询问一次,询问60次 - return rocketmq::CONSUME_SUCCESS; } diff --git a/LFtid1056/cloudfront/code/worker.cpp b/LFtid1056/cloudfront/code/worker.cpp index 5a055f2..ce69d66 100644 --- a/LFtid1056/cloudfront/code/worker.cpp +++ b/LFtid1056/cloudfront/code/worker.cpp @@ -409,49 +409,203 @@ extern bool normalOutputEnabled; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////测试shell用的函数 void Worker::printLedgerinshell(const terminal_dev& dev, int fd) { + // —— 显示控制:最多打印的元素数量(防止过长)—— + constexpr size_t MAX_ITEMS = 5; // 可按需调整或删除限制 + std::ostringstream os; os << "\r\x1B[K------------------------------------\n"; - os << "\r\x1B[K|-- terminal_id: " << dev.terminal_id << "\n"; - os << "\r\x1B[K|-- terminal_name: " << dev.terminal_name << "\n"; - os << "\r\x1B[K|-- dev_ip: " << dev.addr_str << "\n"; - os << "\r\x1B[K|-- dev_port: " << dev.port << "\n"; - os << "\r\x1B[K|-- dev_type: " << dev.dev_type << "\n"; - os << "\r\x1B[K|-- dev_key: " << dev.dev_key << "\n"; - os << "\r\x1B[K|-- dev_series: " << dev.dev_series << "\n"; - os << "\r\x1B[K|-- dev_processNo: " << dev.processNo << "\n"; - os << "\r\x1B[K|-- maxProcessNum: " << dev.maxProcessNum << "\n"; - os << "\r\x1B[K|-- org_name: " << dev.org_name << "\n"; - os << "\r\x1B[K|-- maint_name: " << dev.maint_name << "\n"; - os << "\r\x1B[K|-- station_name: " << dev.station_name << "\n"; - os << "\r\x1B[K|-- tmnl_factory: " << dev.tmnl_factory << "\n"; - os << "\r\x1B[K|-- tmnl_status: " << dev.tmnl_status << "\n"; - os << "\r\x1B[K|-- timestamp: " << dev.timestamp << "\n"; + os << "\r\x1B[K|-- terminal_id : " << dev.terminal_id << "\n"; + os << "\r\x1B[K|-- terminal_name : " << dev.terminal_name << "\n"; + os << "\r\x1B[K|-- dev_ip : " << dev.addr_str << "\n"; + os << "\r\x1B[K|-- dev_port : " << dev.port << "\n"; + os << "\r\x1B[K|-- dev_type : " << dev.dev_type << "\n"; + os << "\r\x1B[K|-- dev_key : " << dev.dev_key << "\n"; + os << "\r\x1B[K|-- dev_series : " << dev.dev_series << "\n"; + os << "\r\x1B[K|-- dev_processNo : " << dev.processNo << "\n"; + os << "\r\x1B[K|-- maxProcessNum : " << dev.maxProcessNum << "\n"; + os << "\r\x1B[K|-- org_name : " << dev.org_name << "\n"; + os << "\r\x1B[K|-- maint_name : " << dev.maint_name << "\n"; + os << "\r\x1B[K|-- station_name : " << dev.station_name << "\n"; + os << "\r\x1B[K|-- tmnl_factory : " << dev.tmnl_factory << "\n"; + os << "\r\x1B[K|-- tmnl_status : " << dev.tmnl_status << "\n"; + os << "\r\x1B[K|-- timestamp : " << dev.timestamp << "\n"; + os << "\r\x1B[K|-- mac : " << dev.mac << "\n"; - os << "\r\x1B[K|-- mac: " << dev.mac << "\n"; + // ========================= 终端级 · 内部定值 ========================= + // internal_values(ushort 列表)与 dz_internal_info_list 一一对应,仅展示前 MAX_ITEMS 条 + os << "\r\x1B[K|-- Internal Values (" << dev.internal_values.size() << "):\n"; + { + size_t idx = 0; + for (auto itv = dev.internal_values.begin(); + itv != dev.internal_values.end() && idx < MAX_ITEMS; + ++itv, ++idx) { + os << "\r\x1B[K |-- [" << idx << "] value: " << static_cast(*itv) << "\n"; + } + if (dev.internal_values.size() > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (dev.internal_values.size() - MAX_ITEMS) << " more)\n"; + } + } + // dz_internal_info_list(NameFixValue 描述,和 internal_values 对应) + os << "\r\x1B[K|-- Internal Value Descriptions (" << dev.dz_internal_info_list.size() << "):\n"; + { + const size_t n = dev.dz_internal_info_list.size(); + for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) { + const auto& nf = dev.dz_internal_info_list[i]; + os << "\r\x1B[K |-- [" << i << "] " + << "Name=" << trim_cstr(nf.sFixValueName, sizeof(nf.sFixValueName)) + << ", Type=" << nf.DataType + << ", Unit=" << trim_cstr(nf.sDimension, sizeof(nf.sDimension)) + << ", Min=" << nf.MinValue + << ", Max=" << nf.MaxValue + << ", Default=" << nf.DefaultValue + << "\n"; + } + if (n > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n"; + } + } + + // control_words(控制字描述) + os << "\r\x1B[K|-- Control Words (" << dev.control_words.size() << "):\n"; + { + const size_t n = dev.control_words.size(); + for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) { + const DZ_kzz_bit& b = dev.control_words[i]; + os << "\r\x1B[K |-- [" << i << "] " + << "name=\"" << trim_cstr(b.kzz_bit, sizeof(b.kzz_bit)) << "\"" + << ", enable=" << static_cast(b.bit_enable) << "\n"; + } + if (n > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n"; + } + } + + // ========================= 监测点级 · line ========================= for (size_t i = 0; i < dev.line.size(); ++i) { const auto& ld = dev.line[i]; if (ld.monitor_id.empty()) continue; + os << "\r\x1B[K|-- line[" << i << "]:\n"; - os << "\r\x1B[K |-- monitor_id: " << ld.monitor_id << "\n"; - os << "\r\x1B[K |-- monitor_name: " << ld.monitor_name << "\n"; - os << "\r\x1B[K |-- logical_device_seq: " << ld.logical_device_seq << "\n"; - os << "\r\x1B[K |-- terminal_id: " << ld.terminal_id << "\n"; - os << "\r\x1B[K |-- voltage_level: " << ld.voltage_level << "\n"; - os << "\r\x1B[K |-- terminal_connect: " << ld.terminal_connect << "\n"; - os << "\r\x1B[K |-- status: " << ld.status << "\n"; - os << "\r\x1B[K |-- timestamp: " << ld.timestamp << "\n"; + os << "\r\x1B[K |-- monitor_id : " << ld.monitor_id << "\n"; + os << "\r\x1B[K |-- monitor_name : " << ld.monitor_name << "\n"; + os << "\r\x1B[K |-- logical_device_seq : " << ld.logical_device_seq << "\n"; + os << "\r\x1B[K |-- terminal_id : " << ld.terminal_id << "\n"; + os << "\r\x1B[K |-- voltage_level : " << ld.voltage_level << "\n"; + os << "\r\x1B[K |-- terminal_connect : " << ld.terminal_connect << "\n"; + os << "\r\x1B[K |-- status : " << ld.status << "\n"; + os << "\r\x1B[K |-- timestamp : " << ld.timestamp << "\n"; + os << "\r\x1B[K |-- CT1=" << ld.CT1 << ", CT2=" << ld.CT2 + << ", PT1=" << ld.PT1 << ", PT2=" << ld.PT2 << "\n"; - os << "\r\x1B[K |-- CT1: " << ld.CT1 << "\n"; - os << "\r\x1B[K |-- CT2: " << ld.CT2 << "\n"; - os << "\r\x1B[K |-- PT1: " << ld.PT1 << "\n"; - os << "\r\x1B[K |-- PT2: " << ld.PT2 << "\n"; + // --- 监测点 · 定值(set_values) --- + os << "\r\x1B[K |-- Set Values (" << ld.set_values.size() << "):\n"; + { + size_t idx = 0; + for (auto it = ld.set_values.begin(); + it != ld.set_values.end() && idx < MAX_ITEMS; + ++it, ++idx) { + os << "\r\x1B[K |-- [" << idx << "] " << *it << "\n"; + } + if (ld.set_values.size() > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (ld.set_values.size() - MAX_ITEMS) << " more)\n"; + } + } + // --- 监测点 · 定值描述文件(dz_info_list) --- + os << "\r\x1B[K |-- DZ Table (" << ld.dz_info_list.size() << "):\n"; + { + const size_t n = ld.dz_info_list.size(); + for (size_t j = 0; j < n && j < MAX_ITEMS; ++j) { + const DZ_TAB_STRUCT& z = ld.dz_info_list[j]; + os << "\r\x1B[K |-- [" << j << "] " + << "LN=" << z.LN_Num + << ", DZ=" << z.DZ_Num + << ", Name=" << trim_cstr(z.DZ_Name, sizeof(z.DZ_Name)) + << ", Type=" << z.DZ_Type + << ", Min=" << z.DZ_Min + << ", Max=" << z.DZ_Max + << ", Def=" << z.DZ_Default + << ", Unit=" << trim_cstr(z.DZ_UNIT, sizeof(z.DZ_UNIT)) + << "\n"; + } + if (n > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n"; + } + } + + // --- 监测点 · 暂态事件(qvvrevent) --- + os << "\r\x1B[K |-- QVVR Event:\n"; + + // 1) 暂态事件列表 + os << "\r\x1B[K |-- Events (" << ld.qvvrevent.qvvrdata.size() << "):\n"; + { + const size_t n = ld.qvvrevent.qvvrdata.size(); + for (size_t k = 0; k < n && k < MAX_ITEMS; ++k) { + const qvvr_data& e = ld.qvvrevent.qvvrdata[k]; + os << "\r\x1B[K |-- [" << k << "] " + << "used=" << e.used_status + << ", type=" << e.QVVR_type + << ", time=" << static_cast(e.QVVR_time) + << ", per=" << e.QVVR_PerTime + << ", amp=" << e.QVVR_Amg + << ", phase="<< e.phase + << "\n"; + } + if (n > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n"; + } + } + + // 2) 文件组列表 + os << "\r\x1B[K |-- File Groups (" << ld.qvvrevent.qvvrfile.size() << "):\n"; + { + const size_t n = ld.qvvrevent.qvvrfile.size(); + for (size_t g = 0; g < n && g < MAX_ITEMS; ++g) { + const qvvr_file& fg = ld.qvvrevent.qvvrfile[g]; + os << "\r\x1B[K |-- [" << g << "] " + << "used=" << fg.used_status + << ", tcount=" << fg.file_time_count + << ", downloaded=" << fg.is_download + << ", paired=" << fg.is_pair + << "\n"; + + // 文件名列表(file_name) + os << "\r\x1B[K |-- file_name (" << fg.file_name.size() << "):\n"; + { + size_t c = 0; + for (const auto& fn : fg.file_name) { + if (c++ >= MAX_ITEMS) break; + os << "\r\x1B[K |-- " << fn << "\n"; + } + if (fg.file_name.size() > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (fg.file_name.size() - MAX_ITEMS) << " more)\n"; + } + } + + // 已下载列表(file_download) + os << "\r\x1B[K |-- file_download (" << fg.file_download.size() << "):\n"; + { + size_t c = 0; + for (const auto& fn : fg.file_download) { + if (c++ >= MAX_ITEMS) break; + os << "\r\x1B[K |-- " << fn << "\n"; + } + if (fg.file_download.size() > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (fg.file_download.size() - MAX_ITEMS) << " more)\n"; + } + } + } + if (n > MAX_ITEMS) { + os << "\r\x1B[K |.. (+" << (n - MAX_ITEMS) << " more)\n"; + } + } } os << "\r\x1B[K------------------------------------\n"; sendStr(fd, os.str()); } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////打印所有的终端列表 void Worker::ledger(const std::string& terminal_id, int fd) { sendStr(fd, "\r\x1B[Kprint ledger in shell\n"); diff --git a/LFtid1056/dealMsg.cpp b/LFtid1056/dealMsg.cpp index fb2cee9..d2fc7b8 100644 --- a/LFtid1056/dealMsg.cpp +++ b/LFtid1056/dealMsg.cpp @@ -582,6 +582,7 @@ void process_received_message(string mac, string id,const char* data, size_t len } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_REALSTAT)); // ʵʱݴ󣬵Ϊ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -668,6 +669,10 @@ void process_received_message(string mac, string id,const char* data, size_t len else { std::cerr << "Failed to save file: " << file_path << ", Error: " << strerror(errno) << std::endl; + + // ļʧܣ֪ͨƶ + send_reply_to_cloud(static_cast(ResponseCode::BAD_REQUEST), + id, static_cast(DeviceState::READING_EVENTFILE)); } //ǰļϣΪдһļȴأһѾȴеȺˣɿ״ֱ̬ӾͻῪʼļع @@ -676,6 +681,7 @@ void process_received_message(string mac, string id,const char* data, size_t len } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_EVENTFILE)); // ղļݴ󣬵Ϊ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -719,6 +725,7 @@ void process_received_message(string mac, string id,const char* data, size_t len } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_FILEMENU)); // Ŀ¼ݴ󣬵Ϊ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -800,7 +807,7 @@ void process_received_message(string mac, string id,const char* data, size_t len //ʹýӿļlnk20250826 std::string filename; - //SendFileWeb(WEB_FILEUPLOAD, file_path, file_path, filename); + SendFileWeb(WEB_FILEUPLOAD, file_path, file_path, filename); std::cout << "File upload: " << filename << std::endl; } @@ -810,12 +817,13 @@ void process_received_message(string mac, string id,const char* data, size_t len } //ǰļϣΪдһļȴأһѾȴеȺˣɿ״ֱ̬ӾͻῪʼļع - ClientManager::instance().change_device_state(id, DeviceState::IDLE); + ClientManager::instance().change_device_state(id, DeviceState::READING_FILEDATA); } } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_FILEDATA)); // ļݴ󣬵Ϊ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -878,7 +886,7 @@ void process_received_message(string mac, string id,const char* data, size_t len } //洢ֵlnk20250827 - //save_internal_value(id, monitor_index, fList); + save_set_value(id, monitor_index, fList); //Զֵ޸Ĺ //ClientManager::instance().set_fixedvalue_action_to_device(id, monitor_index, fList); @@ -888,6 +896,8 @@ void process_received_message(string mac, string id,const char* data, size_t len } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR),id,static_cast(DeviceState::READING_FIXEDVALUE)); + // ȡֵ󣬵Ϊ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -965,13 +975,15 @@ void process_received_message(string mac, string id,const char* data, size_t len // ȡ (һֽ) uint8_t monitor_index = parser.RecvData[0]; std::cout << "Monitor Index: " << static_cast(monitor_index) << std::endl; - //send_set_value_reply(id, monitor_index, dz_list); + send_set_value_reply(id, monitor_index, dz_list); //ֵȡϣΪУ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR),id,static_cast(DeviceState::READING_FIXEDVALUEDES)); + // ȡֵΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -1044,7 +1056,7 @@ void process_received_message(string mac, string id,const char* data, size_t len } //洢ֵlnk20250827 - //save_internal_value(id, fList); + save_internal_value(id, fList); //ڲֵ޸IJ //ClientManager::instance().set_interfixedvalue_action_to_device(id, fList); @@ -1054,6 +1066,9 @@ void process_received_message(string mac, string id,const char* data, size_t len } else { // װô쳣 + + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_INTERFIXEDVALUE)); + // ȡװڲֵʧܣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -1122,11 +1137,17 @@ void process_received_message(string mac, string id,const char* data, size_t len } } + //lnk20250905 + save_internal_info(id, fixValueList); + //ڲֵȡϣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else { // װô쳣 + + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_INTERFIXEDVALUEDES)); + // ȡװڲֵʧܣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -1182,11 +1203,14 @@ void process_received_message(string mac, string id,const char* data, size_t len << ", enable: " << static_cast(dz_info.bit_enable) << std::endl; } + send_internal_value_reply(id, control_words); + // ȡϣΪУ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::READING_CONTROLWORD)); // ȡװÿʧܣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } @@ -1197,6 +1221,8 @@ void process_received_message(string mac, string id,const char* data, size_t len if (udata[8] == static_cast(MsgResponseType::Response_NewACK)) { std::cout << "set success" << mac << std::endl; //ڲֵóɹΪУ + send_reply_to_cloud(static_cast(ResponseCode::OK), id, static_cast(DeviceState::SET_INTERFIXEDVALUE)); + ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else if (udata[8] == static_cast(MsgResponseType::Response_NewNACK)) { @@ -1205,11 +1231,14 @@ void process_received_message(string mac, string id,const char* data, size_t len std::cout << "reason code: " << static_cast(udata[8]) << "-" << static_cast(udata[9]) << "-" << static_cast(udata[10]) << "-" << static_cast(udata[11]) << std::endl; // װ÷Ӧڲֵʧ + send_reply_to_cloud(static_cast(ResponseCode::BAD_REQUEST), id, static_cast(DeviceState::SET_INTERFIXEDVALUE)); + // װڲֵʧܣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else { // װô쳣 + send_reply_to_cloud(static_cast(ResponseCode::INTERNAL_ERROR), id, static_cast(DeviceState::SET_INTERFIXEDVALUE)); // װڲֵʧܣΪ״̬һ ClientManager::instance().change_device_state(id, DeviceState::IDLE); }