208 lines
6.1 KiB
C++
208 lines
6.1 KiB
C++
#include <vector>
|
||
#include <cstdint>
|
||
#include <cstring>
|
||
#include <string>
|
||
#include <stdexcept>
|
||
#include <algorithm>
|
||
#include <cctype>
|
||
#include <cstdlib>
|
||
#include "client2.h"
|
||
// 辅助转换函数
|
||
float IntToFloat(int num) {
|
||
return static_cast<float>(num) / 65536.0f;
|
||
}
|
||
|
||
float ShorToFloat100(short num) {
|
||
return static_cast<float>(num) / 100.0f;
|
||
}
|
||
|
||
float ShorToFloat1000(short num) {
|
||
return static_cast<float>(num) / 1000.0f;
|
||
}
|
||
|
||
float ShorToFloat10000(short num) {
|
||
return static_cast<float>(num) / 10000.0f;
|
||
}
|
||
// 辅助函数:解析MAC地址并填充到缓冲区
|
||
void GetMAC(const std::string& strMAC, std::vector<unsigned char>& 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<unsigned char>(
|
||
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<unsigned char>& Check, int nOffset, int nLen) {
|
||
unsigned char reg_b = 0x00;
|
||
for (int i = 0; i < nLen; ++i) {
|
||
if (static_cast<size_t>(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<unsigned char> GetMsg(const std::vector<unsigned char>& 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<unsigned char> msg(total_len);
|
||
|
||
// 组装报文头 (6字节)
|
||
msg[0] = 0xEB; // 报文头
|
||
msg[1] = 0x90; // 报文头
|
||
msg[2] = 0x00; // 备用
|
||
msg[3] = 0x00; // 备用
|
||
|
||
// 设置长度字段(数据体长度+功能码)
|
||
uint16_t data_len = static_cast<uint16_t>(SrcData.size() + 1);
|
||
msg[4] = static_cast<unsigned char>(data_len >> 8); // 长度高字节
|
||
msg[5] = static_cast<unsigned char>(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<unsigned char> generate_frontlogin_message(const std::string& strMac)
|
||
{
|
||
const size_t packetSize = 150; // 报文总长150 数据体+帧序号140
|
||
std::vector<unsigned char> 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<unsigned char> generate_statequerytime_message() {
|
||
// 创建2字节数据缓冲区(初始化为0)
|
||
std::vector<unsigned char> DataBuf(2, 0x00);
|
||
|
||
// 调用GetMsg生成完整报文
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_StatTime));
|
||
}
|
||
|
||
//询问统计数据报文
|
||
std::vector<unsigned char> 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<unsigned char> 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<unsigned char>(MsgRequestType::Request_Stat));
|
||
}
|
||
|
||
|
||
|