Files
front_linux/LFtid1056/PQSMsg.cpp

240 lines
7.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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));
}
//询问实时数据报文 测点1-6 数据类型1-11 谐波次数0-2
std::vector<unsigned char> 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<unsigned char> DataBuf(totalSize, 0x00); // 初始化为全0
size_t offset = 0;
// 1. 跳过3字节备用区已初始化为0
offset += 3;
// 2. 写入nCpuNo1字节 监测点序号 1-6
memcpy(DataBuf.data() + offset, &nCpuNo, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 3. 写入StaTtype1字节 数据类型 1-11 一般仅读 1-6
memcpy(DataBuf.data() + offset, &StaTtype, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 4. 写入固定值11字节 3秒实时数据仅有1 表示平均值
const unsigned char fixedValue = 1;
memcpy(DataBuf.data() + offset, &fixedValue, sizeof(unsigned char));
offset += sizeof(unsigned char);
// 5. 写入flag1字节 标志位 0-2 谐波次数 25 50 100次
memcpy(DataBuf.data() + offset, &flag, sizeof(unsigned char));
// 生成完整报文
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_New_3S));
}