#include #include #include #include #include #include #include #include #include "client2.h" // 辅助转换函数 float IntToFloat(int num) { return static_cast(num) / 65536.0f; } float ShorToFloat100(short num) { return static_cast(num) / 100.0f; } float ShorToFloat1000(short num) { return static_cast(num) / 1000.0f; } float ShorToFloat10000(short num) { return static_cast(num) / 10000.0f; } // 辅助函数:解析MAC地址并填充到缓冲区 void GetMAC(const std::string& strMAC, std::vector& packet, size_t startIndex) { // 移除所有空格和短横线 std::string cleanedMAC = strMAC; cleanedMAC.erase(std::remove(cleanedMAC.begin(), cleanedMAC.end(), ' '), cleanedMAC.end()); cleanedMAC.erase(std::remove(cleanedMAC.begin(), cleanedMAC.end(), '-'), cleanedMAC.end()); // 验证长度 if (cleanedMAC.length() != 12) { throw std::invalid_argument("MAC地址长度必须为12个字符"); } try { // 解析每两个字符作为十六进制字节 for (int i = 0; i < 6; i++) { // 提取两个字符的子串 std::string byteStr = cleanedMAC.substr(i * 2, 2); // 转换为十六进制字节 unsigned char byte = static_cast( std::stoi(byteStr, nullptr, 16) ); // 填充到指定位置 if (startIndex + i < packet.size()) { packet[startIndex + i] = byte; } } // 剩余部分填0 (总共需要64字节,但MAC只占6字节) for (int i = 6; i < 64; i++) { if (startIndex + i < packet.size()) { packet[startIndex + i] = 0; } } } catch (const std::exception& e) { throw std::invalid_argument("无效的MAC地址: " + std::string(e.what())); } } // CRC计算函数 unsigned char GetCrcSum(const std::vector& Check, int nOffset, int nLen) { unsigned char reg_b = 0x00; for (int i = 0; i < nLen; ++i) { if (static_cast(i + nOffset) >= Check.size()) { throw std::out_of_range("Index out of range in GetCrcSum"); } reg_b += Check[i + nOffset]; } return reg_b; } // 主函数:组装二进制报文 std::vector GetMsg(const std::vector& SrcData, unsigned char nType) { // 参数检查 if (SrcData.empty() || ((nType < 0x01 || nType > 0xA4) && nType != 0xFF)) { return {}; } try { // 计算总长度:报文头(6) + 额外字段(2) + 功能码(1) + 数据体 + CRC+结束符(2) const size_t total_len = 6 + 2 + 1 + SrcData.size() + 2; std::vector msg(total_len); // 组装报文头 (6字节) msg[0] = 0xEB; // 报文头 msg[1] = 0x90; // 报文头 msg[2] = 0x00; // 备用 msg[3] = 0x00; // 备用 // 设置长度字段(数据体长度+功能码) uint16_t data_len = static_cast(SrcData.size() + 1); msg[4] = static_cast(data_len >> 8); // 长度高字节 msg[5] = static_cast(data_len & 0xFF); // 长度低字节 // 额外字段 (2字节) msg[6] = 0x00; // 备用 msg[7] = 0xFF; // 备用 // 功能码 msg[8] = nType; // 复制数据体 if (!SrcData.empty()) { std::copy(SrcData.begin(), SrcData.end(), msg.begin() + 9); } // 计算CRC(从索引8开始,长度 = 功能码+数据体) unsigned char crc = GetCrcSum(msg, 8, 1 + SrcData.size()); msg[msg.size() - 2] = crc; msg[msg.size() - 1] = 0x16; // 结束符 return msg; } catch (const std::exception& ex) { throw std::runtime_error(std::string("Exception in GetMsg: ") + ex.what()); } catch (...) { throw std::runtime_error("Unknown exception in GetMsg"); } } // 生成装置云服务登录报文 std::vector generate_frontlogin_message(const std::string& strMac) { const size_t packetSize = 150; // 报文总长150 数据体+帧序号140 std::vector packet(packetSize, 0); // 初始化为全0 // 协议头 packet[0] = 0xEB; // 起始标志1 packet[1] = 0x90; packet[2] = 0xEB; // 起始标志2 packet[3] = 0x90; packet[4] = 0x8C; // 数据体长度 (140 = 0x008C) packet[5] = 0x00; // [6-7] 随机码 (保持为0) // [8-9] 功能码 (保持为0) // [10-11] 帧序号 (保持为0) // 数据体1 packet[12] = 'F'; packet[13] = 'T'; packet[14] = 'I'; packet[15] = 'D'; // [16-19] 数据体2 (保持为0) // 填充MAC地址 (从位置20开始,64字节) GetMAC(strMac, packet, 20); // 计算校验和 (从偏移8到137) unsigned char checksum = 0; for (size_t i = 8; i < packetSize - 2; i++) { checksum += packet[i]; } packet[packetSize - 2] = checksum; // 结束符 packet[packetSize - 1] = 0x16; return packet; } //询问统计数据时间报文 std::vector generate_statequerytime_message() { // 创建2字节数据缓冲区(初始化为0) std::vector DataBuf(2, 0x00); // 调用GetMsg生成完整报文 return GetMsg(DataBuf, static_cast(MsgRequestType::Request_StatTime)); } //询问统计数据报文 std::vector generate_statequerystat_message(tagTime time, uint16_t nDeviceNo, uint16_t nDataType) { // 计算总大小:3(备用) + 2(nDeviceNo) + 2(nDataType) + time结构大小 const size_t totalSize = 3 + 2 * sizeof(uint16_t) + time.GetSize(); std::vector DataBuf(totalSize, 0x00); // 初始化为全0 size_t offset = 0; // 1. 跳过3字节备用区(已初始化为0) offset += 3; // 2. 写入nDeviceNo(网络字节序) uint16_t netDeviceNo = htons(nDeviceNo); memcpy(DataBuf.data() + offset, &netDeviceNo, sizeof(uint16_t)); offset += sizeof(uint16_t); // 3. 写入nDataType(网络字节序) uint16_t netDataType = htons(nDataType); memcpy(DataBuf.data() + offset, &netDataType, sizeof(uint16_t)); offset += sizeof(uint16_t); // 4. 写入time结构(内部已处理网络字节序) time.GetStructBuf(DataBuf.data(), DataBuf.size(), offset); // 生成完整报文 return GetMsg(DataBuf, static_cast(MsgRequestType::Request_Stat)); } //询问实时数据报文 测点1-6 数据类型1-11 谐波次数0-2 std::vector generate_realstat_message(unsigned char nCpuNo, unsigned char StaTtype, unsigned char flag) { // 计算总大小:3(备用) + 1(nCpuNo) + 1(StaTtype) + 1(固定值) + 1(flag) const size_t totalSize = 7; std::vector DataBuf(totalSize, 0x00); // 初始化为全0 size_t offset = 0; // 1. 跳过3字节备用区(已初始化为0) offset += 3; // 2. 写入nCpuNo(1字节) 监测点序号 1-6 memcpy(DataBuf.data() + offset, &nCpuNo, sizeof(unsigned char)); offset += sizeof(unsigned char); // 3. 写入StaTtype(1字节) 数据类型 1-11 一般仅读 1-6 memcpy(DataBuf.data() + offset, &StaTtype, sizeof(unsigned char)); offset += sizeof(unsigned char); // 4. 写入固定值1(1字节) 3秒实时数据仅有1 表示平均值 const unsigned char fixedValue = 1; memcpy(DataBuf.data() + offset, &fixedValue, sizeof(unsigned char)); offset += sizeof(unsigned char); // 5. 写入flag(1字节) 标志位 0-2 谐波次数 25 50 100次 memcpy(DataBuf.data() + offset, &flag, sizeof(unsigned char)); // 生成完整报文 return GetMsg(DataBuf, static_cast(MsgRequestType::Request_New_3S)); }