diff --git a/LFtid1056/PQSMsg.cpp b/LFtid1056/PQSMsg.cpp index 5c06d94..7a8bac5 100644 --- a/LFtid1056/PQSMsg.cpp +++ b/LFtid1056/PQSMsg.cpp @@ -702,4 +702,67 @@ std::vector generate_righttime_message(const std::tm& time) { // 调用已有的GetMsg函数生成完整报文,功能码134(0x86) return GetMsg(DataBuf, static_cast(MsgRequestType::Request_RightTime)); +} + +/** + * @brief 生成暂降事件补招报文 + * @param Time1 起始时间 + * @param Time2 结束时间 + * @param eventType 事件类型,默认2-暂态事件 4-告警时间 + * @param monitorPoint 监测点,默认1-监测点1 1-6 对应测点 + * @return 包含完整报文的字节向量 + */ +std::vector generate_recallevent_message(const std::tm& Time1, const std::tm& Time2, + uint8_t eventType, uint8_t monitorPoint) +{ + std::vector DataBuf(25, 0x00); // 创建25字节缓冲区并初始化为0 + + // 前3字节为备用,已初始化为0 + + DataBuf[3] = eventType; // 2-暂态事件 4-告警事件 + DataBuf[4] = monitorPoint; // 0-所有监测点 + + // 将时间转换为大端序2字节格式并填充到缓冲区 + uint16_t year1 = static_cast(Time1.tm_year + 1900); + DataBuf[5] = static_cast((year1 >> 8) & 0xFF); + DataBuf[6] = static_cast(year1 & 0xFF); + + uint16_t month1 = static_cast(Time1.tm_mon + 1); + DataBuf[7] = static_cast((month1 >> 8) & 0xFF); + DataBuf[8] = static_cast(month1 & 0xFF); + + uint16_t day1 = static_cast(Time1.tm_mday); + DataBuf[9] = static_cast((day1 >> 8) & 0xFF); + DataBuf[10] = static_cast(day1 & 0xFF); + + uint16_t hour1 = static_cast(Time1.tm_hour); + DataBuf[11] = static_cast((hour1 >> 8) & 0xFF); + DataBuf[12] = static_cast(hour1 & 0xFF); + + uint16_t minute1 = static_cast(Time1.tm_min); + DataBuf[13] = static_cast((minute1 >> 8) & 0xFF); + DataBuf[14] = static_cast(minute1 & 0xFF); + + uint16_t year2 = static_cast(Time2.tm_year + 1900); + DataBuf[15] = static_cast((year2 >> 8) & 0xFF); + DataBuf[16] = static_cast(year2 & 0xFF); + + uint16_t month2 = static_cast(Time2.tm_mon + 1); + DataBuf[17] = static_cast((month2 >> 8) & 0xFF); + DataBuf[18] = static_cast(month2 & 0xFF); + + uint16_t day2 = static_cast(Time2.tm_mday); + DataBuf[19] = static_cast((day2 >> 8) & 0xFF); + DataBuf[20] = static_cast(day2 & 0xFF); + + uint16_t hour2 = static_cast(Time2.tm_hour); + DataBuf[21] = static_cast((hour2 >> 8) & 0xFF); + DataBuf[22] = static_cast(hour2 & 0xFF); + + uint16_t minute2 = static_cast(Time2.tm_min); + DataBuf[23] = static_cast((minute2 >> 8) & 0xFF); + DataBuf[24] = static_cast(minute2 & 0xFF); + + // 调用已有的GetMsg函数生成完整报文,功能码0x0D(事件补招功能码) + return GetMsg(DataBuf, static_cast(MsgRequestType::Request_Read_Event)); } \ No newline at end of file diff --git a/LFtid1056/PQSMsg.h b/LFtid1056/PQSMsg.h index 4fbc9a2..cb6e6d7 100644 --- a/LFtid1056/PQSMsg.h +++ b/LFtid1056/PQSMsg.h @@ -43,7 +43,9 @@ enum class MsgRequestType : unsigned char { //询问装置运行信息 Request_Read_RunningInformation = 0x0e, //设置装置对时 - Request_RightTime = 0x86 + Request_RightTime = 0x86, + //补招事件日志 + Request_Read_Event = 0x0D }; // 接收报文功能码枚举 enum class MsgResponseType : unsigned char { @@ -77,6 +79,8 @@ enum class MsgResponseType : unsigned char { Response_Read_RunningInformation = 0x8e, //设置装置对时(未使用,采用默认肯定与否定应答) Response_RightTime = 0x86, + //补招事件日志 + Response_Read_Event = 0x8D, //默认肯定应答 Response_NewACK = 0x40, //默认否定应答 @@ -2189,4 +2193,13 @@ std::vector generate_machineversion_message(); * @param time 下发的对时时间 (tm值) * @return 包含完整报文的字节向量 */ -std::vector generate_righttime_message(const std::tm& time); \ No newline at end of file +std::vector generate_righttime_message(const std::tm& time); +/** + * @brief 生成暂降事件补招报文 + * @param Time1 起始时间 + * @param Time2 结束时间 + * @param eventType 事件类型,默认2-暂态事件 4-告警时间 + * @param monitorPoint 监测点,默认1-监测点1 1-6 对应测点 + * @return 包含完整报文的字节向量 + */ +std::vector generate_recallevent_message(const std::tm& Time1, const std::tm& Time2, uint8_t eventType = 2, uint8_t monitorPoint = 1); \ No newline at end of file diff --git a/LFtid1056/client2.cpp b/LFtid1056/client2.cpp index 9edabc9..f0b59ab 100644 --- a/LFtid1056/client2.cpp +++ b/LFtid1056/client2.cpp @@ -283,6 +283,37 @@ void ClientContext::clear_stat_cache() { stat_packets_cache_.clear(); expected_total_packets_ = 0; } + +bool ClientContext::event_add_stat_packet(const std::vector& packet, int current_packet, int total_packets) { + std::lock_guard lock(event_stat_cache_mutex_); + + // 濡傛灉鏄涓甯э紝鍒濆鍖栫紦瀛 + if (current_packet == 1) { + event_stat_packets_cache_.clear(); + event_expected_total_packets_ = total_packets; + } + + // 娣诲姞鍒扮紦瀛 + event_stat_packets_cache_.push_back({ current_packet, packet }); + + // 妫鏌ユ槸鍚︽敹榻愭墍鏈夊抚 + return (event_stat_packets_cache_.size() >= event_expected_total_packets_); +} + +std::vector ClientContext::event_get_and_clear_stat_packets() { + std::lock_guard lock(event_stat_cache_mutex_); + auto packets = std::move(event_stat_packets_cache_); + event_stat_packets_cache_.clear(); + event_expected_total_packets_ = 0; + return packets; +} + +void ClientContext::event_clear_stat_cache() { + std::lock_guard lock(event_stat_cache_mutex_); + event_stat_packets_cache_.clear(); + event_expected_total_packets_ = 0; +} + // 娣诲姞娴偣鏁版嵁鍒扮紦瀛 bool ClientContext::add_float_data(ushort point_id, int data_type, const tagPqData_Float& float_data) { if (data_type < 0 || data_type > 3) return false; @@ -548,6 +579,7 @@ void on_close(uv_handle_t* handle) { ctx->stop_timers(); // 娓呯┖缂撳瓨 ctx->clear_stat_cache(); + ctx->event_clear_stat_cache(); // 娓呴櫎娴偣鏁版嵁缂撳瓨 ctx->clear_float_cache(); // 瑁呯疆鐧诲綍鐘舵佽皟鏁翠负绂荤嚎 @@ -1055,6 +1087,52 @@ bool ClientManager::clear_stat_cache(const std::string& identifier) { return false; } +//淇濆瓨澶氬抚浜嬩欢鏃ュ織鎶ユ枃鑷崇紦瀛樺尯绛夊緟鏀跺叏 +bool ClientManager::add_eventlog_packet_to_device(const std::string& identifier, + const std::vector& packet, + int current_packet, + int total_packets) { + std::lock_guard lock(mutex_); + + for (auto& pair : clients_) { + auto& ctx = pair.second; + if (ctx->device_info.device_id == identifier || + ctx->device_info.mac == identifier) { + return ctx->event_add_stat_packet(packet, current_packet, total_packets); + } + } + return false; +} + +//鑾峰彇缂撳瓨鍖哄唴鎵鏈夊甯т簨浠舵棩蹇楁姤鏂囧苟娓呯┖缂撳瓨 +std::vector ClientManager::get_and_clear_event_packets(const std::string& identifier) { + std::lock_guard lock(mutex_); + + for (auto& pair : clients_) { + auto& ctx = pair.second; + if (ctx->device_info.device_id == identifier || + ctx->device_info.mac == identifier) { + return ctx->event_get_and_clear_stat_packets(); + } + } + return {}; +} + +//娓呯┖鎵鏈変簨浠舵棩蹇楃紦瀛樺尯 +bool ClientManager::clear_event_cache(const std::string& identifier) { + std::lock_guard lock(mutex_); + + for (auto& pair : clients_) { + auto& ctx = pair.second; + if (ctx->device_info.device_id == identifier || + ctx->device_info.mac == identifier) { + ctx->event_clear_stat_cache(); + return true; + } + } + return false; +} + // 鑾峰彇pt鍜孋T鍙樻瘮 bool ClientManager::get_pt_ct_ratio(const std::string& identifier, int16_t nCpuNo, @@ -1093,6 +1171,25 @@ bool ClientManager::get_pt_ct_ratio(const std::string& identifier, return false; } +// 鑾峰彇寰呰ˉ鎷涙祴鐐瑰簭鍙 +bool ClientManager::get_event_lineid(const std::string& identifier,int& nCpuNo) { + std::lock_guard lock(mutex_); + + for (auto& pair : clients_) { + auto& ctx = pair.second; + // 鍖归厤瑁呯疆ID鎴朚AC鍦板潃 + if (ctx->device_info.device_id == identifier || + ctx->device_info.mac == identifier) { + + nCpuNo = ctx->event_lineNo; + return true; + } + } + + std::cerr << "[get_pt_ct_ratio] Device not found: " << identifier << std::endl; + return false; +} + // 娣诲姞娴偣鏁版嵁鍒版寚瀹氳澶囩殑缂撳瓨 bool ClientManager::add_float_data_to_device(const std::string& identifier, ushort point_id, @@ -1451,6 +1548,43 @@ bool ClientManager::read_devversion_action_to_device(const std::string& identifi } return false; // 璁惧鏈壘鍒 } + +/** + * @brief 琛ユ嫑浜嬩欢鏃ュ織鍔ㄤ綔 + * @param Time1 璧峰鏃堕棿 + * @param Time2 缁撴潫鏃堕棿 + * @param eventType 浜嬩欢绫诲瀷锛岄粯璁2-鏆傛佷簨浠 4-鍛婅鏃堕棿 + * @param monitorPoint 鐩戞祴鐐癸紝榛樿1-鐩戞祴鐐1 1-6 瀵瑰簲娴嬬偣 + * @return 璋冪敤鎴愬姛鎴栧け璐ョ殑缁撴灉 + */ +bool ClientManager::read_eventlog_action_to_device(const std::string& identifier, const std::tm& Time1, const std::tm& Time2, + uint8_t eventType, uint8_t monitorPoint) { + std::lock_guard lock(mutex_); + + // 鏌ユ壘鍖归厤鐨勮澶 + for (auto& pair : clients_) { + auto& ctx = pair.second; + if (ctx->device_info.device_id == identifier || + ctx->device_info.mac == identifier) + { + ctx->event_lineNo = monitorPoint; + // 鐢熸垚瀹氬兼弿杩版姤鏂 + auto packet = generate_recallevent_message(Time1, Time2, eventType, monitorPoint); + + // 娣诲姞鍔ㄤ綔鍒伴槦鍒 (鐘舵: 璇诲彇鏂囦欢鐩綍) + ctx->add_action(DeviceState::READING_EVENTLOG, packet); + + // 濡傛灉褰撳墠绌洪棽鍒欑珛鍗虫墽琛 + if (ctx->current_state_ == DeviceState::IDLE) { + ctx->process_next_action(); + } + + return true; // 鎴愬姛娣诲姞 + } + } + return false; // 璁惧鏈壘鍒 +} + //鑾峰彇鎸囧畾瑁呯疆娴嬬偣鐨勭數鍘嬬瓑绾т笌鎺ョ嚎鏂瑰紡 bool ClientManager::get_point_scale_and_pttype(const std::string& identifier, ushort nCpuNo, diff --git a/LFtid1056/client2.h b/LFtid1056/client2.h index 6476a58..353c43f 100644 --- a/LFtid1056/client2.h +++ b/LFtid1056/client2.h @@ -61,6 +61,7 @@ enum class DeviceState { READING_RUNNINGINFORMATION_2,// 读取装置运行信息(定时执行) READING_DEVVERSION, // 读取装置版本配置信息 SET_RIGHTTIME, // 设置装置对时 + READING_EVENTLOG, // 补招事件日志 // 可根据需要添加更多状态 CUSTOM_ACTION // 自定义动作 }; @@ -123,14 +124,21 @@ public: std::vector data; }; + // 新增缓存管理方法------------------------------------------------------------------------ std::vector stat_packets_cache_; // 缓存分帧报文 int expected_total_packets_ = 0; // 预期总帧数 std::mutex stat_cache_mutex_; // 缓存互斥锁 - - // 新增缓存管理方法 bool add_stat_packet(const std::vector& packet, int current_packet, int total_packets);//插入多帧缓存数据 std::vector get_and_clear_stat_packets();//取出所有缓存数据并清空缓存 void clear_stat_cache();//清空缓存 + // 新增事件日志缓存管理方法----------------------------------------------------------------- + ushort event_lineNo = 1; // 事件日志待补招测点 + std::vector event_stat_packets_cache_; // 事件日志缓存分帧报文 + int event_expected_total_packets_ = 0; // 事件日志预期总帧数 + std::mutex event_stat_cache_mutex_; // 事件日志缓存互斥锁 + bool event_add_stat_packet(const std::vector& packet, int current_packet, int total_packets);//事件日志插入多帧缓存数据 + std::vector event_get_and_clear_stat_packets();//事件日志取出所有缓存数据并清空缓存 + void event_clear_stat_cache();//事件日志清空缓存 // 统计数据缓存 struct PointFloatCache { @@ -296,12 +304,27 @@ public: //清空多帧报文保存缓存区 bool clear_stat_cache(const std::string& identifier); + //保存多帧事件日志报文至缓存区等待收全 + bool add_eventlog_packet_to_device(const std::string& identifier, + const std::vector& packet, + int current_packet, + int total_packets); + + //获取缓存区内所有多帧事件日志报文并清空缓存 + std::vector get_and_clear_event_packets(const std::string& identifier); + + //清空所有事件日志缓存区 + bool clear_event_cache(const std::string& identifier); + // 获取指定测点的PT和CT变比值 bool get_pt_ct_ratio(const std::string& identifier, int16_t nCpuNo, float& pt_ratio, float& ct_ratio); + // 获取待补招测点序号 + bool get_event_lineid(const std::string& identifier, int& nCpuNo); + // 获取客户端数量 size_t client_count() { std::lock_guard lock(mutex_); @@ -417,6 +440,16 @@ public: //读取装置版本配置信息 bool read_devversion_action_to_device(const std::string& identifier); + + /** + * @brief 补招事件日志动作 + * @param Time1 起始时间 + * @param Time2 结束时间 + * @param eventType 事件类型,默认2-暂态事件 4-告警时间 + * @param monitorPoint 监测点,默认1-监测点1 1-6 对应测点 + * @return 调用成功或失败的结果 + */ + bool read_eventlog_action_to_device(const std::string& identifier, const std::tm& Time1, const std::tm& Time2,uint8_t eventType = 2, uint8_t monitorPoint = 1); private: ClientManager() : loop_(nullptr) {} std::unordered_map> clients_; diff --git a/LFtid1056/dealMsg.cpp b/LFtid1056/dealMsg.cpp index cfdcb3a..1335b56 100644 --- a/LFtid1056/dealMsg.cpp +++ b/LFtid1056/dealMsg.cpp @@ -47,6 +47,23 @@ std::string extract_filename(const std::string& path) { return path; } +//文件crc校验函数 +uint16_t crc_16_new(const uint8_t* buf, uint32_t len) { + uint16_t crc = 0xffff; + for (uint32_t i = 0; i < len; i++) { + crc = (uint16_t)(crc ^ buf[i]); + for (int j = 0; j < 8; j++) { + if (crc & 1) { + crc = (uint16_t)((crc >> 1) ^ 0xA001); + } + else { + crc = (uint16_t)(crc >> 1); + } + } + } + return crc; +} + //消息处理逻辑 void process_received_message(string mac, string id,const char* data, size_t length) { // 实际的消息处理逻辑 @@ -73,7 +90,7 @@ void process_received_message(string mac, string id,const char* data, size_t len //装置登录成功 ClientManager::instance().set_cloud_status(id, 1); //设置了云前置登录状态为已登录 ClientManager::instance().read_devversion_action_to_device(id);//主动触发,读取装置版本配置信息,仅在装置登录后执行一次,当前获取版本信息确认对时报文结构。 - + ClientManager::instance().add_file_menu_action_to_device(id, "/etcc"); //ClientManager::instance().set_real_state_count("D002", 1,1);//登录后测试实时 //ClientManager::instance().add_file_menu_action_to_device("D002","/etc");//测试文件目录读取 //ClientManager::instance().add_file_download_action_to_device("D002", "/etc/NPQS570_VX_ZJ_2(V103).icd");//测试文件下载 @@ -85,7 +102,24 @@ void process_received_message(string mac, string id,const char* data, size_t len //ClientManager::instance().set_interfixedvalue_action_to_device();装置修改内部定值测试(参数由外部提供) //ClientManager::instance().read_runninginformation_action_to_device(id);//主动触发,读取装置运行信息 - + //// 设置起始时间: 2025年9月1日 10:30:45 + //std::tm start_time = {}; + //start_time.tm_year = 2025 - 1900; // 年份从1900开始计算 + //start_time.tm_mon = 8 - 1; // 月份从0开始 (0=一月) + //start_time.tm_mday = 20; + //start_time.tm_hour = 1; + //start_time.tm_min = 1; + //start_time.tm_sec = 1; + + //// 设置结束时间: 2025年9月4日 12:15:30 + //std::tm end_time = {}; + //end_time.tm_year = 2025 - 1900; + //end_time.tm_mon = 8 - 1; + //end_time.tm_mday = 25; + //end_time.tm_hour = 1; + //end_time.tm_min = 1; + //end_time.tm_sec = 1; + //ClientManager::instance().read_eventlog_action_to_device(id, start_time, end_time,2,1); } if (udata[19] == 0x00) { std::cout << "cloud login: " << mac << " state: fail!" << std::endl; @@ -718,6 +752,7 @@ void process_received_message(string mac, string id,const char* data, size_t len ClientManager::instance().change_device_state(id, DeviceState::IDLE); } else { + std::cout << "reason code: " << static_cast(udata[8]) << "-" << static_cast(udata[9]) << "-" << static_cast(udata[10]) << "-" << static_cast(udata[11]) << std::endl; // 装置答非所问异常 // 接收目录数据错误,调整为空闲状态,处理下一项工作。 ClientManager::instance().change_device_state(id, DeviceState::IDLE); @@ -1758,7 +1793,7 @@ void process_received_message(string mac, string id,const char* data, size_t len ClientManager::instance().set_versioninformation(id, versionInfo.CloudProtocolVer); } // 打印解析结果 - /*std::cout << "Device Version Info (" << mac << "):\n" + std::cout << "Device Version Info (" << mac << "):\n" << " Base Model: " << versionInfo.BaseModel << "\n" << " Cloud Protocol: " << versionInfo.CloudProtocolVer << "\n" << " App Version: " << versionInfo.AppVersion << "\n" @@ -1768,7 +1803,7 @@ void process_received_message(string mac, string id,const char* data, size_t len << " Wave File Types: " << versionInfo.WaveFileTypeCount << "\n" << " Comm Protocols: 0x" << std::hex << versionInfo.CommProtocols << "\n" << " Time Sync Methods: 0x" << versionInfo.TimeSyncMethods << "\n" - << " Device Functions: 0x" << versionInfo.DeviceFunctions << std::dec << "\n";*/ + << " Device Functions: 0x" << versionInfo.DeviceFunctions << std::dec << "\n"; //读取装置版本配置信息成功,调整为空闲,处理后续工作。 ClientManager::instance().change_device_state(id, DeviceState::IDLE); @@ -1803,6 +1838,234 @@ void process_received_message(string mac, string id,const char* data, size_t len } break; + case DeviceState::READING_EVENTLOG: + //补招装置日志 + if (udata[8] == static_cast(MsgResponseType::Response_Read_Event)) { + std::cout << "set success" << mac << std::endl; + + std::cout << "reason code: " << static_cast(udata[8]) << "-" << static_cast(udata[9]) << "-" << static_cast(udata[10]) << "-" << static_cast(udata[11]) << std::endl; + + if (parser.RecvData.size() >= 14) { + // 提取当前帧 + int current_frame = 0; + if (parser.RecvData.size() >= 4) { + std::vector frame_data(parser.RecvData.begin(), parser.RecvData.begin() + 4); + std::reverse(frame_data.begin(), frame_data.end()); // 字节反转 + current_frame = *reinterpret_cast(frame_data.data()); + } + + // 提取总帧数 + int total_frames = 0; + if (parser.RecvData.size() >= 8) { + std::vector total_frame_data(parser.RecvData.begin() + 4, parser.RecvData.begin() + 8); + std::reverse(total_frame_data.begin(), total_frame_data.end()); // 字节反转 + total_frames = *reinterpret_cast(total_frame_data.data()); + } + + // 提取文件总大小 + int file_size = 0; + if (parser.RecvData.size() >= 12) { + std::vector size_data(parser.RecvData.begin() + 8, parser.RecvData.begin() + 12); + std::reverse(size_data.begin(), size_data.end()); // 字节反转 + file_size = *reinterpret_cast(size_data.data()); + } + + // 提取CRC校验码 + uint16_t crc = 0; + if (parser.RecvData.size() >= 14) { + std::vector crc_data(parser.RecvData.begin() + 12, parser.RecvData.begin() + 14); + std::reverse(crc_data.begin(), crc_data.end()); // 字节反转 + crc = *reinterpret_cast(crc_data.data()); + } + + // 提取文件数据 + std::vector file_data; + if (parser.RecvData.size() > 14) { + file_data.assign(parser.RecvData.begin() + 14, parser.RecvData.end()); + } + + // 将数据添加到缓存(使用类似READING_STATS的逻辑) + bool complete = ClientManager::instance().add_eventlog_packet_to_device( + id, file_data, current_frame, total_frames + ); + std::cout << "event log:" << current_frame << "/" << total_frames << std::endl; + // 检查是否收全所有帧 + if (complete) { + // 1. 获取并清空缓存数据包 + auto packets = ClientManager::instance().get_and_clear_event_packets(id); + + // 2. 按帧序号排序 + std::sort(packets.begin(), packets.end(), + [](const ClientContext::StatPacket& a, const ClientContext::StatPacket& b) { + return a.packet_index < b.packet_index; + }); + + // 3. 解析每帧数据并提取数据体 + std::vector full_data; + + for (const auto& packet : packets) { + // 将数据体添加到完整序列 + full_data.insert(full_data.end(), + packet.data.begin(), + packet.data.end()); + } + + //确认待补招序号 // 获取测点参数 + int event_lineid = 0; + std::string strScale;//电压等级 + int nPTType;//接线方式 + float fPT = 1.0f; + float fCT = 1.0f; + + if (!ClientManager::instance().get_event_lineid(id, event_lineid)) { + //取出补招序号失败!暂态补招结束 + //补招装置日志获取完毕,调整为空闲状态,处理下一项工作。 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + if (!ClientManager::instance().get_point_scale_and_pttype( + id, + event_lineid, + strScale, + nPTType) || !ClientManager::instance().get_pt_ct_ratio(id, event_lineid, fPT, fCT)) { + //取出解析方式,PTCT,电压等级失败!暂态补招结束 + //补招装置日志获取完毕,调整为空闲状态,处理下一项工作。 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // ========== 新增:解析full_data中的NewTaglogbuffer对象列表 ========== + std::list eventList; + size_t offset = 0; + const size_t headSize = sizeof(NewHeadTaglogbuffer); + const size_t bodyItemSize = sizeof(NewBodyTaglogbuffer); + + while (offset + headSize <= full_data.size()) { + // 读取头部 + NewHeadTaglogbuffer head; + memcpy(&head, full_data.data() + offset, headSize); + head.convertByteOrder(); // 转换字节序 + + uint32_t logParaNum = head.LogParaNum; + // 计算身体部分在full_data中占用的空间(最少4个身体项的空间) + size_t bodySpace; + if (logParaNum <= 4) { + bodySpace = 4 * bodyItemSize; + } + else { + bodySpace = logParaNum * bodyItemSize; + } + + // 检查剩余数据是否足够 + if (offset + headSize + bodySpace > full_data.size()) { + std::cerr << "Insufficient data for event body at offset " << offset << std::endl; + break; + } + + // 创建事件对象并设置头部 + NewTaglogbuffer event; + event.head = head; + event.bodyList.resize(logParaNum); + + // 解析身体部分 + const uint8_t* bodyData = full_data.data() + offset + headSize; + for (uint32_t i = 0; i < logParaNum; ++i) { + memcpy(&event.bodyList[i], bodyData, bodyItemSize); + event.bodyList[i].convertByteOrder(); + bodyData += bodyItemSize; + } + + //当前解析事件和待补招测点一致,则加入队列 + if (event.head.name == event_lineid) { + eventList.push_back(event); + } + + // 移动偏移量,跳过头部和身体占用空间(包括填充) + offset += headSize + bodySpace; + } + + // 现在eventList中包含所有解析的事件对象,可以在这里进行处理 + std::cout << "Parsed " << eventList.size() << " events from event log." << std::endl; + + std::list recordlist; + for (const auto& event : eventList) { + + QVVRRecord record = DynamicLog_GetQVVRRecordFromLogBuffer( + strScale, nPTType, fPT, event); + // 使用记录数据(示例:打印到控制台) + std::cout << "事件类型: " << record.nType + << ", 持续时间: " << record.fPersisstime << "s" + << ", 特征幅值: " << record.fMagntitude << " pu" + << ", 时间戳: " << record.triggerTimeMs << "ms" << std::endl; + + recordlist.push_back(record); + } + + + + + //暂时移除CRC校验相关 + //// ========== 新增 CRC 验证 ========== + //if (!full_data.empty()) { + // // 计算接收数据的 CRC + // uint16_t calculated_crc = crc_16_new(full_data.data(), full_data.size()); + + // // 比较计算出的 CRC 和从报文中提取的 CRC + // if (calculated_crc == crc) { + // std::cout << "CRC verification passed for event log data." << std::endl; + // // 这里可以继续处理完整数据 + // } + // else { + // std::cerr << "CRC verification failed! Expected: " << crc + // << ", Calculated: " << calculated_crc << std::endl; + // // 处理 CRC 校验失败的情况 + // } + //} + //else { + // //收取缓存文件异常,结束补招处理 + // std::cerr << "No data received for event log." << std::endl; + //} + + } + else { + //未收全则直接结束处理,等待后续报文应答 + return; + } + } + + //补招装置日志获取完毕,调整为空闲状态,处理下一项工作。 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + } + else if (udata[8] == static_cast(MsgResponseType::Response_NewNACK)) { + std::cout << "set error" << mac << std::endl; + + std::cout << "reason code: " << static_cast(udata[8]) << "-" << static_cast(udata[9]) << "-" << static_cast(udata[10]) << "-" << static_cast(udata[11]) << std::endl; + + if (udata[10] == static_cast(0x0c)) { + //0x0c错误码代表询问暂态数据不存在,通知前台当前时间段无暂态 + std::cout << "not find event " << mac << std::endl; + } + else if (udata[10] == static_cast(0x06)) { + //0x0c错误码代表补招方法参数错误,通知前台参数异常 + } + else { + //其余错误码代表异常情况 + } + // 装置否定 + // 补招装置日志失败,调整为空闲状态,处理下一项工作。 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + } + else { + std::cout << "set unknow error" << mac << std::endl; + + std::cout << "reason code: " << static_cast(udata[8]) << "-" << static_cast(udata[9]) << "-" << static_cast(udata[10]) << "-" << static_cast(udata[11]) << std::endl; + // 装置答非所问异常 + // 补招装置日志失败,调整为空闲状态,处理下一项工作。 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + } + break; + case DeviceState::CUSTOM_ACTION: // 自定义动作状态 std::cout << "CUSTOM_ACTION state: Processing custom response from " << mac << std::endl; diff --git a/LFtid1056/main_thread.cpp b/LFtid1056/main_thread.cpp index 86f6b9f..6e33a0e 100644 --- a/LFtid1056/main_thread.cpp +++ b/LFtid1056/main_thread.cpp @@ -158,11 +158,11 @@ void* client_manager_thread(void* arg) { {"P001", "Main Voltage", "D001",1 ,1, 1, 1, 1,"0.38k",0}, {"P002", "Backup Voltage", "D001",2 ,1, 1, 1, 1,"0.38k",0} }; - //00B78DA800D6 00-B7-8D-01-79-06 00-B7-8D-A8-00-D6 + //00B78DA800D6 00-B7-8D-01-79-06 00-B7-8D-A8-00-D6 00-B7-8D-01-71-09 00-B7-8D-01-88-7f // 创建装置列表 std::vector devices = { { - "D001", "Primary Device", "Model-X", "00-B7-8D-01-79-06", + "D001", "Primary Device", "Model-X", "00-B7-8D-01-88-7f", 1, points1,true } };