From 93def18fbddac0b28f966cad09775ad48313f828 Mon Sep 17 00:00:00 2001 From: zhangwen <3466561528@qq.com> Date: Thu, 5 Mar 2026 20:56:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=A3=85=E7=BD=AE?= =?UTF-8?q?=E9=A2=84=E5=8D=87=E7=BA=A7=E6=A0=A1=E9=AA=8C=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LFtid1056/PQSMsg.cpp | 19 +++- LFtid1056/PQSMsg.h | 5 ++ LFtid1056/client2.cpp | 51 ++++++++++- LFtid1056/client2.h | 23 +++++ LFtid1056/dealMsg.cpp | 178 +++++++++++++++++++++++++++++++++++--- LFtid1056/main_thread.cpp | 2 +- 6 files changed, 264 insertions(+), 14 deletions(-) diff --git a/LFtid1056/PQSMsg.cpp b/LFtid1056/PQSMsg.cpp index 5c4bec6..c9620d3 100644 --- a/LFtid1056/PQSMsg.cpp +++ b/LFtid1056/PQSMsg.cpp @@ -658,13 +658,29 @@ std::vector generate_machineversion_message() // 创建10字节数据缓冲区,初始化为0 std::vector DataBuf(10, 0x00); - // 设置索引3的值为1(第4个字节) + // 设置索引3的值为2(第4个字节) DataBuf[3] = 0x02; // 调用通用报文生成函数,功能码14对应装置状态读取 return GetMsg(DataBuf, static_cast(MsgRequestType::Request_Read_RunningInformation)); } +/** + * @brief 生成预升级报文 + * @return 包含完整报文的字节向量 + */ +std::vector generate_preupgrade_message() +{ + // 创建10字节数据缓冲区,初始化为0 + std::vector DataBuf(10, 0x00); + + // 设置索引3的值为4(第4个字节) + DataBuf[3] = 0x04; + + // 调用通用报文生成函数,功能码14对应装置状态读取 + return GetMsg(DataBuf, static_cast(MsgRequestType::Request_Read_RunningInformation)); +} + /** * @brief 生成设置装置对时的报文 * @param time 下发的对时时间 (tm值) @@ -796,3 +812,4 @@ std::vector generate_control_message(uint8_t type, uint8_t ctrlfl return GetMsg(DataBuf, static_cast(MsgRequestType::Request_Ctrl)); } + diff --git a/LFtid1056/PQSMsg.h b/LFtid1056/PQSMsg.h index 1f44b8e..602c7aa 100644 --- a/LFtid1056/PQSMsg.h +++ b/LFtid1056/PQSMsg.h @@ -2411,6 +2411,11 @@ std::vector generate_machinestatus_message(); * @return 包含完整报文的字节向量 */ std::vector generate_machineversion_message(); +/** + * @brief 生成预升级报文 + * @return 包含完整报文的字节向量 + */ +std::vector generate_preupgrade_message(); /** * @brief 生成设置装置对时的报文 * @param time 下发的对时时间 (tm值) diff --git a/LFtid1056/client2.cpp b/LFtid1056/client2.cpp index 0824a88..aadaaa7 100644 --- a/LFtid1056/client2.cpp +++ b/LFtid1056/client2.cpp @@ -1713,10 +1713,10 @@ bool ClientManager::read_devversion_action_to_device(const std::string& identifi if (ctx->device_info.device_id == identifier || ctx->device_info.mac == identifier) { - // 鐢熸垚瀹氬兼弿杩版姤鏂 + // 鐢熸垚鐗堟湰閰嶇疆鎶ユ枃 auto packet = generate_machineversion_message(); - // 娣诲姞鍔ㄤ綔鍒伴槦鍒 (鐘舵: 璇诲彇鏂囦欢鐩綍) + // 娣诲姞鍔ㄤ綔鍒伴槦鍒 (鐘舵: 璇诲彇瑁呯疆鐗堟湰淇℃伅) ctx->add_action(DeviceState::READING_DEVVERSION, packet); // 濡傛灉褰撳墠绌洪棽鍒欑珛鍗虫墽琛 @@ -1730,6 +1730,39 @@ bool ClientManager::read_devversion_action_to_device(const std::string& identifi return false; // 璁惧鏈壘鍒 } +/** + * @brief 鐢熸垚棰勫崌绾ф牎楠屾姤鏂 + * @param path 棰勬牎楠屾枃浠惰矾寰 + * @return 鍖呭惈瀹屾暣鎶ユ枃鐨勫瓧鑺傚悜閲 + */ +bool ClientManager::set_preupgrade_action_to_device(const std::string& identifier, const std::string& path) { + 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->set_preupgrade_filepath(path); + // 鐢熸垚棰勫崌绾ф姤鏂 + auto packet = generate_preupgrade_message(); + + // 娣诲姞鍔ㄤ綔鍒伴槦鍒 (鐘舵: 棰勫崌绾ф牎楠) + ctx->add_action(DeviceState::SET_PREUPGRADE, packet); + + // 濡傛灉褰撳墠绌洪棽鍒欑珛鍗虫墽琛 + if (ctx->current_state_ == DeviceState::IDLE) { + ctx->process_next_action(); + } + + return true; // 鎴愬姛娣诲姞 + } + } + return false; // 璁惧鏈壘鍒 +} + /** * @brief 鐢熸垚瑁呯疆鎺у埗鍛戒护鎶ユ枃 * @param type 鍛戒护绫诲瀷 1-瑁呯疆澶嶄綅锛2-鍚姩褰曟尝锛3-鍚姩200ms鏁版嵁璁板綍锛4-鍚姩3绉掓暟鎹褰 @@ -1940,6 +1973,7 @@ bool ClientManager::update_current_filename(const std::string& identifier, return false; } +//鑾峰彇褰撳墠姝e湪涓嬭浇鐨勬枃浠跺悕 std::string ClientManager::get_current_filename(const std::string& identifier) { std::lock_guard lock(mutex_); for (auto& pair : clients_) { @@ -1950,4 +1984,17 @@ std::string ClientManager::get_current_filename(const std::string& identifier) { } } return ""; +} + +//鑾峰彇鐢ㄤ簬棰勬牎楠岀殑鏂囦欢璺緞 +std::string ClientManager::get_preupgrade_filepath(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->get_preupgrade_filepath(); + } + } + return ""; } \ No newline at end of file diff --git a/LFtid1056/client2.h b/LFtid1056/client2.h index 4ff2b8b..84bcdf7 100644 --- a/LFtid1056/client2.h +++ b/LFtid1056/client2.h @@ -66,6 +66,7 @@ enum class DeviceState { READING_EVENTLOG, // 补招事件日志 READING_STATSFILE, // 补招稳态数据文件 SET_CTRL, // 设置装置控制命令 + SET_PREUPGRADE, // 装置预升级校验 // 可根据需要添加更多状态 CUSTOM_ACTION // 自定义动作 }; @@ -204,6 +205,7 @@ public: std::vector file_download_cache_; // 文件分片缓存 std::string current_filename_; // 当前下载的文件名 + std::string preupgrade_filepath_; // 预升级校验文件路径 std::mutex file_cache_mutex_; // 缓存互斥锁 // 添加文件分片到缓存 @@ -250,6 +252,18 @@ public: std::lock_guard lock(file_cache_mutex_); return current_filename_; } + + //设置预升级校验文件路径 + void set_preupgrade_filepath(const std::string& filepath) { + std::lock_guard lock(file_cache_mutex_); + preupgrade_filepath_ = filepath; + } + + // 获取预升级校验文件路径 + std::string get_preupgrade_filepath() { + std::lock_guard lock(file_cache_mutex_); + return preupgrade_filepath_; + } private: int index_; @@ -406,6 +420,8 @@ public: bool update_current_filename(const std::string& identifier, const std::string& filename); std::string get_current_filename(const std::string& identifier); + //获取用于预校验的文件路径 + std::string get_preupgrade_filepath(const std::string& identifier); //刷新客户端装置最新接收通讯报文时间 bool set_cloudmessage_time(const std::string& identifier); @@ -449,6 +465,13 @@ public: //装置主动对时动作 bool set_righttime_action_to_device(const std::string& identifier); + /** + * @brief 生成预升级校验报文 + * @param path 预校验文件路径 + * @return 包含完整报文的字节向量 + */ + bool set_preupgrade_action_to_device(const std::string& identifier, const std::string& path); + //设备运行情况判断 bool get_dev_status(const std::string& identifier); /** diff --git a/LFtid1056/dealMsg.cpp b/LFtid1056/dealMsg.cpp index 59a7bff..607967b 100644 --- a/LFtid1056/dealMsg.cpp +++ b/LFtid1056/dealMsg.cpp @@ -49,23 +49,89 @@ 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); +// 鐢熸垚涓 C# CreateNormalCrc32Table 瀹屽叏瀵瑰簲鐨勮〃 +static std::array CreateNormalCrc32Table(uint32_t poly) +{ + std::array table{}; + + for (int i = 0; i < 256; ++i) + { + uint32_t data = static_cast(i) << 24; + for (int j = 0; j < 8; ++j) + { + bool flag = (data & 0x80000000u) == 0x80000000u; + if (flag) + { + data = (data << 1) ^ poly; } - else { - crc = (uint16_t)(crc >> 1); + else + { + data <<= 1; } } + table[i] = data; } + + return table; +} + +// 涓 C# CalcNoemalCrc32 瀹屽叏瀵瑰簲 +static uint32_t CalcNormalCrc32(const std::vector& bytes, uint32_t poly) +{ + auto table = CreateNormalCrc32Table(poly); + + uint32_t crc = 0xFFFFFFFFu; + for (size_t i = 0; i < bytes.size(); ++i) + { + crc = (crc << 8) ^ table[((crc >> 24) & 0xFFu) ^ bytes[i]]; + } + return crc; } +/* 鐢熸垚棰勫崌绾ф牎楠屾枃浠 绠楁硶 */ +int new_tcp_pre_upgrade_message_create(uint8_t* buf, uint32_t len) +{ + uint16_t i, j; + uint16_t value = 0xFFFF; + uint16_t factor = 0xA001; + + if (len > 10 * 1024) { + len = 10 * 1024; + } + + for (i = 0; i < len; i++) + { + value = value ^ static_cast(i + 1); + for (j = 0; j < 8; j++) + { + if ((value & 1) == 1) { + value = static_cast((value >> 1) ^ factor); + } + else { + value = static_cast(value >> 1); + } + } + buf[i] = static_cast(value & 0xFF); + } + + return static_cast(len); +} + +//鐢熸垚棰勫崌绾ф牎楠屾枃浠 +std::vector GeneratePreUpgradeFileFromLengthBytes(uint32_t fileLen) +{ + if (fileLen > 10 * 1024) { + throw std::runtime_error("Pre-upgrade file length exceeds maximum allowed size."); + } + + std::vector fileData(fileLen); + int actualLen = new_tcp_pre_upgrade_message_create(fileData.data(), fileLen); + fileData.resize(actualLen); + + return fileData; +} + //娑堟伅澶勭悊閫昏緫 void process_received_message(string mac, string id,const char* data, size_t length) { // 瀹為檯鐨勬秷鎭鐞嗛昏緫 @@ -94,6 +160,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().set_preupgrade_action_to_device(id, "");//瑁呯疆鍗囩骇棰勬牎楠屾祦绋 鏍¢獙鏂囦欢鑷姩鐢熸垚 褰撳墠濉┖ //ClientManager::instance().set_ctrl_action_to_device(id,0x01,0x00);//灏濊瘯瑁呯疆閲嶅惎鎸囦护锛佺涓姝ユ牎楠 //ClientManager::instance().set_ctrl_action_to_device(id, 0x01, 0x01);//灏濊瘯瑁呯疆閲嶅惎鎸囦护锛佹牎楠屽畬姣曞悗灏濊瘯鎵ц閲嶅惎鎸囦护 @@ -2269,6 +2336,97 @@ void process_received_message(string mac, string id,const char* data, size_t len } break; + case DeviceState::SET_PREUPGRADE: + //瑁呯疆棰勫崌绾ф牎楠 + if (udata[8] == static_cast(MsgResponseType::Response_Read_RunningInformation)) { + // 鑾峰彇瑙f瀽鍚庣殑鏁版嵁浣 + std::vector& recvData = parser.RecvData; + + // 妫鏌ユ暟鎹暱搴︽槸鍚﹁冻澶 + if (recvData.size() < 2) { + //瑁呯疆涓婇佺殑棰勬牎楠屾枃浠跺紓甯革紒棰勬牎楠屽け璐ワ紒 + std::cerr << "Invalid running information data: too short (" + << recvData.size() << " bytes)" << std::endl; + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // 鎻愬彇鏈夋晥杞借嵎闀垮害 + size_t payloadLength = recvData.size() - 2; + + // 澶嶅埗鏈夋晥杞借嵎鏁版嵁 + std::vector payloadBytes(payloadLength); + if (recvData.size() >= 2 + payloadLength) { + std::copy(recvData.begin() + 2, recvData.begin() + 2 + payloadLength, payloadBytes.begin()); + } + else { + //瑁呯疆涓婇佺殑棰勬牎楠屾枃浠跺紓甯革紒棰勬牎楠屽け璐ワ紒 + std::cerr << "Invalid payload length: " << payloadLength + << ", available: " << (recvData.size() - 2) << std::endl; + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // payload 鑷冲皯瑕佹湁 4 涓瓧鑺傦紝鎵嶈兘鍙栧墠鍥涗綅浣滀负 32 浣嶆暣鏁 + if (payloadBytes.size() < 4) { + //瑁呯疆涓婇佺殑棰勬牎楠屾枃浠跺紓甯革紒棰勬牎楠屽け璐ワ紒 + std::cerr << "Invalid payloadBytes: too short to extract int32 (" + << payloadBytes.size() << " bytes)" << std::endl; + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // 鍙栧墠 4 涓瓧鑺傚苟杞崲涓 32 浣嶆暣鏁帮紙鎸夊ぇ绔簭锛 + int32_t dataLength = + (static_cast(payloadBytes[0]) << 24) | + (static_cast(payloadBytes[1]) << 16) | + (static_cast(payloadBytes[2]) << 8) | + (static_cast(payloadBytes[3])); + + // 鍘绘帀鍓 4 涓瓧鑺傦紝鍙栧嚭鍓╀綑閮ㄥ垎 + std::vector realPayload(payloadBytes.begin() + 4, payloadBytes.end()); + + // 妫鏌ュ墿浣欓儴鍒嗛暱搴︽槸鍚︿笌鍓嶉潰鐨 32 浣嶆暣鏁颁竴鑷 + if (dataLength < 0 || realPayload.size() != static_cast(dataLength)) { + std::cerr << "Payload length mismatch: expected " << dataLength + << ", actual " << realPayload.size() << std::endl; + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // 鍒拌繖閲岃鏄庯細 + // 1. 鍓4瀛楄妭宸茬粡瑙f瀽鎴 int32_t dataLength + // 2. 鍓╀綑鏁版嵁淇濆瓨鍦 realPayload 涓 + // 3. realPayload.size() == dataLength + std::cout << "********* wait crc *********" << std::endl; + // 鐢ㄥ墠4瀛楄妭鐢熸垚鏈湴鈥滄爣鍑嗘枃浠跺唴瀹光 + std::vector localFile = GeneratePreUpgradeFileFromLengthBytes(dataLength); + + // 璁$畻 CRC + uint32_t crc = CalcNormalCrc32(realPayload, 0x04C11DB7u); + uint32_t generatedCrc = CalcNormalCrc32(localFile, 0x04C11DB7u); + + std::cout << "Generated CRC = 0x" << std::hex << std::uppercase << generatedCrc << std::endl; + std::cout << "Received CRC = 0x" << std::hex << std::uppercase << crc << std::endl; + std::cout << std::dec; + + if (generatedCrc != crc) { + //crc 鏍¢獙澶辫触 鍚庣画鍗囩骇鍋滄锛 + std::cerr << "CRC verify failed." << std::endl; + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + break; + } + + // 棰勫崌绾ф牎楠岀粨鏉熸垚鍔燂紝璋冩暣涓虹┖闂诧紝澶勭悊鍚庣画宸ヤ綔銆 + ClientManager::instance().change_device_state(id, DeviceState::IDLE); + } + else { + // 瑁呯疆绛旈潪鎵闂紓甯 + // 棰勫崌绾ф牎楠屽け璐ワ紝璋冩暣涓虹┖闂茬姸鎬侊紝澶勭悊涓嬩竴椤瑰伐浣溿 + 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 af43e85..24cff9a 100644 --- a/LFtid1056/main_thread.cpp +++ b/LFtid1056/main_thread.cpp @@ -380,7 +380,7 @@ int main(int argc ,char** argv) {// std::cerr << "process param error,exit" << std::endl; return 1; } - init_daemon(); + //init_daemon(); srand(time(NULL)); // 初始化随机数种子 // 初始化线程数组