768 lines
24 KiB
C++
768 lines
24 KiB
C++
#include <vector>
|
||
#include <cstdint>
|
||
#include <cstring>
|
||
#include <string>
|
||
#include <stdexcept>
|
||
#include <algorithm>
|
||
#include <cctype>
|
||
#include <cstdlib>
|
||
#include "client2.h"
|
||
#include <iostream>
|
||
|
||
// 辅助转换函数
|
||
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;
|
||
}
|
||
|
||
// 字节序转换函数
|
||
void ReversalBuff(uint8_t* buff, int start, int length) {
|
||
for (int i = 0; i < length / 2; i++) {
|
||
std::swap(buff[start + i], buff[start + length - 1 - i]);
|
||
}
|
||
}
|
||
|
||
// 辅助函数:解析MAC地址并填充到缓冲区
|
||
//lnk20250808
|
||
static inline int hex_nibble(char c) {
|
||
if (c >= '0' && c <= '9') return c - '0';
|
||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
|
||
return -1;
|
||
}
|
||
|
||
// 安全版:不抛异常,返回 true/false
|
||
bool GetMAC(const std::string& strMAC,
|
||
std::vector<unsigned char>& packet,
|
||
size_t startIndex,
|
||
std::string* err = nullptr) {
|
||
// 1) 规范化:去掉 '-', ':', ' '
|
||
std::string s;
|
||
s.reserve(strMAC.size());
|
||
for (char c : strMAC) {
|
||
if (c == '-' || c == ':' || c == ' ') continue;
|
||
s.push_back(c);
|
||
}
|
||
|
||
// 2) 长度校验
|
||
if (s.size() != 12) {
|
||
if (err) *err = "MAC长度必须为12个十六进制字符";
|
||
return false;
|
||
}
|
||
|
||
// 3) 十六进制校验 + 解析
|
||
std::array<unsigned char, 6> mac{};
|
||
for (int i = 0; i < 6; ++i) {
|
||
int hi = hex_nibble(s[2*i]);
|
||
int lo = hex_nibble(s[2*i + 1]);
|
||
if (hi < 0 || lo < 0) {
|
||
if (err) *err = "MAC含非法字符(必须是0-9或A-F)";
|
||
return false;
|
||
}
|
||
mac[i] = static_cast<unsigned char>((hi << 4) | lo);
|
||
}
|
||
|
||
// 4) 确保缓冲区足够写入64字节(MAC 6字节 + 其后补零)
|
||
const size_t need = startIndex + 64;
|
||
if (packet.size() < need) packet.resize(need, 0);
|
||
|
||
// 5) 写入MAC
|
||
for (int i = 0; i < 6; ++i) {
|
||
packet[startIndex + i] = mac[i];
|
||
}
|
||
|
||
// 6) 其余位置补零(若 resize 过,这里基本已是0,但保证一下)
|
||
for (size_t i = 6; i < 64; ++i) {
|
||
packet[startIndex + i] = 0;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
/*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;
|
||
}
|
||
|
||
// 时间转换函数(TagMsTime -> 毫秒时间戳)
|
||
uint64_t convertTagMsTimeToMsTimestamp(const TagMsTime& t) {
|
||
struct tm tm_time = {};
|
||
tm_time.tm_year = t.Year - 1900;
|
||
tm_time.tm_mon = t.Month - 1;
|
||
tm_time.tm_mday = t.Day;
|
||
tm_time.tm_hour = t.Hour;
|
||
tm_time.tm_min = t.Min;
|
||
tm_time.tm_sec = t.Sec;
|
||
tm_time.tm_isdst = -1; // 自动判断夏令时
|
||
|
||
// 转换为时间戳(秒)
|
||
time_t seconds = mktime(&tm_time);
|
||
if (seconds == -1) return 0;
|
||
|
||
// 加上毫秒
|
||
return static_cast<uint64_t>(seconds) * 1000 + t.Ms;
|
||
}
|
||
|
||
// 解析日志生成QVVRRecord
|
||
QVVRRecord DynamicLog_GetQVVRRecordFromLogBuffer(
|
||
const std::string& strScale,
|
||
uint32_t nPTType,
|
||
float fPT,
|
||
const NewTaglogbuffer& log) {
|
||
|
||
QVVRRecord record;
|
||
|
||
try {
|
||
// 转换时间
|
||
record.triggerTimeMs = convertTagMsTimeToMsTimestamp(log.head.Devtime);
|
||
|
||
// 提取参数
|
||
float fParam1 = 0.0f; // 持续时间
|
||
float fParam2 = 0.0f; // 特征幅值
|
||
float fParam3 = 0.0f; // 浮动门槛值
|
||
|
||
for (const auto& body : log.bodyList) {
|
||
switch (body.ParaCode) {
|
||
case 0: // 特征幅值(暂态单独使用)
|
||
fParam2 = static_cast<float>(body.ParaValue) / 65536.0f;
|
||
break;
|
||
case 1: // 持续时间(瞬态和暂态公用)
|
||
fParam1 = static_cast<float>(body.ParaValue) / 65536.0f;
|
||
break;
|
||
case 25: // 浮动门槛值(瞬态和暂态公用)
|
||
fParam3 = static_cast<float>(body.ParaValue) / 65536.0f;
|
||
break;
|
||
case 3: //电压幅度(瞬态单独使用)
|
||
record.fMagntitude = (static_cast<float>(body.ParaValue) / 65536.0f) / 100.0f;
|
||
break;
|
||
case 5: //相别(瞬态单独使用)
|
||
record.phase = static_cast<float>(body.ParaValue) / 65536.0f;
|
||
break;
|
||
case 6: //瞬变幅度(瞬态单独使用)
|
||
record.transientValue = (static_cast<float>(body.ParaValue) / 65536.0f) / 100.0f;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
record.fPersisstime = fParam1;
|
||
|
||
// 计算基准值fBase
|
||
float fBase = 0.0f;
|
||
if (fParam3 < 50.0f) { // 未上送浮动门槛
|
||
if (fPT != 1.0f) { // 变比不为1
|
||
fBase = (nPTType == 0) ? 57.74f : 100.0f;
|
||
}
|
||
else {
|
||
std::string strTemp = strScale;
|
||
std::transform(strTemp.begin(), strTemp.end(), strTemp.begin(), ::tolower);
|
||
size_t pos = strTemp.find('k');
|
||
if (pos != std::string::npos) {
|
||
std::string numPart = strTemp.substr(0, pos);
|
||
try {
|
||
float fTemp = std::stof(numPart) * 1000.0f;
|
||
fBase = (nPTType == 0) ? (fTemp / std::sqrt(3.0f)) : fTemp;
|
||
}
|
||
catch (...) {
|
||
fBase = (nPTType == 0) ? 57.74f : 100.0f;
|
||
}
|
||
}
|
||
else {
|
||
fBase = (nPTType == 0) ? 57.74f : 100.0f;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
fBase = fParam3; // 使用浮动门槛值
|
||
}
|
||
|
||
// 设置事件类型
|
||
switch (log.head.LogCode) {
|
||
case 0: case 26: case 40: case 54: case 68: case 82:
|
||
record.nType = 3;
|
||
break;
|
||
case 1: case 27: case 41: case 55: case 69: case 83:
|
||
record.nType = 1;
|
||
break;
|
||
case 13: case 36: case 50: case 64: case 78: case 92:
|
||
record.nType = 2;
|
||
break;
|
||
case 24:
|
||
// 手动启动录波,保持默认类型0
|
||
break;
|
||
case 100:
|
||
record.nType = 1; // 模拟电压暂降
|
||
break;
|
||
case 3:
|
||
record.nType = 4; // 瞬态事件
|
||
default:
|
||
// 未知类型保持0
|
||
break;
|
||
}
|
||
|
||
// 特殊处理:中断事件且幅值较大
|
||
if (record.nType == 3 && fParam2 > fBase * 0.1f) {
|
||
fParam2 /= 100.0f;
|
||
}
|
||
|
||
// 计算特征幅值(标幺值)
|
||
record.fMagntitude = fParam2 / fBase;
|
||
}
|
||
catch (...) {
|
||
// 异常时返回空记录
|
||
record = QVVRRecord{};
|
||
}
|
||
|
||
return record;
|
||
}
|
||
|
||
// 主函数:组装二进制报文
|
||
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);
|
||
//lnk20250808
|
||
std::string err;
|
||
if (!GetMAC(strMac, packet, 20, &err)) {
|
||
std::cerr << "[GetMAC] parse failed: " << err << "\n";
|
||
// 做降级或返回
|
||
}
|
||
|
||
// 计算校验和 (从偏移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;
|
||
|
||
//lnk20250808
|
||
// ======= 调试输出报文 =======
|
||
std::cout << "[generate_frontlogin_message] Packet (" << packet.size() << " bytes):\n";
|
||
for (size_t i = 0; i < packet.size(); ++i) {
|
||
printf("%02X ", packet[i]);
|
||
if ((i + 1) % 16 == 0) printf("\n");
|
||
}
|
||
if (packet.size() % 16 != 0) printf("\n");
|
||
|
||
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. 写入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<unsigned char>(MsgRequestType::Request_New_3S));
|
||
}
|
||
|
||
// 生成文件下载请求报文 当前帧序号+文件名
|
||
std::vector<unsigned char> generate_downloadfile_message(int frameIndex, const std::string& fileName) {
|
||
// 数据体大小: 3(备用) + 4(帧序号) + 128(文件名) = 135字节
|
||
std::vector<unsigned char> dataBuf(135, 0x00);
|
||
|
||
// 写入帧序号 (4字节,大端序)
|
||
//uint32_t netFrameIndex = htonl(static_cast<uint32_t>(frameIndex));
|
||
//memcpy(dataBuf.data() + 3, &netFrameIndex, sizeof(uint32_t));
|
||
// 移除htonl转换,直接使用原始帧序号(小端序)
|
||
uint32_t rawFrameIndex = static_cast<uint32_t>(frameIndex);
|
||
memcpy(dataBuf.data() + 3, &rawFrameIndex, sizeof(uint32_t));
|
||
|
||
// 写入文件名 (最多128字节)
|
||
size_t copyLen = std::min(fileName.size(), static_cast<size_t>(128));
|
||
if (copyLen > 0) {
|
||
memcpy(dataBuf.data() + 7, fileName.c_str(), copyLen);
|
||
}
|
||
|
||
// 调用GetMsg生成完整报文
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_File_Download));
|
||
}
|
||
|
||
//文件目录读取报文 传入需要读取的文件路径
|
||
std::vector<unsigned char> generate_getfilemenu_message(const std::string& filedir) {
|
||
// 创建固定131字节缓冲区 (3 + 128),初始化为0
|
||
std::vector<unsigned char> dataBuf(131, 0x00);
|
||
|
||
// 复制文件名到缓冲区(偏移量3开始)
|
||
size_t copyLen = std::min(filedir.size(), static_cast<size_t>(128));
|
||
if (copyLen > 0) {
|
||
memcpy(dataBuf.data() + 3, filedir.c_str(), copyLen);
|
||
}
|
||
|
||
// 调用GetMsg生成完整报文
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_FileDir));
|
||
}
|
||
|
||
// 请求定值报文 传入测点号
|
||
std::vector<unsigned char> generate_requestFixValue_message(unsigned char nCpuNo) {
|
||
// 参数检查
|
||
if (nCpuNo < 1 || nCpuNo > 6)
|
||
return std::vector<unsigned char>();
|
||
|
||
// 创建4字节缓冲区并初始化
|
||
std::vector<unsigned char> DataBuf(4, 0x00);
|
||
DataBuf[3] = nCpuNo; // CPU编号放在第4字节
|
||
|
||
// 生成完整报文
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_FixValue));
|
||
}
|
||
|
||
// 请求定值描述报文
|
||
std::vector<unsigned char> generate_requestFixDes_message() {
|
||
// 创建3字节缓冲区并初始化
|
||
std::vector<unsigned char> DataBuf(3, 0x00);
|
||
|
||
// 生成完整报文
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_FixDes));
|
||
}
|
||
|
||
// 设置定值报文 传入测点号+修改的定值数据队列
|
||
std::vector<unsigned char> generate_requestSetFixValue_message(
|
||
unsigned char nCpuNo,
|
||
const std::vector<float>& value)
|
||
{
|
||
// 参数检查
|
||
if (nCpuNo < 1 || nCpuNo > 6)
|
||
return std::vector<unsigned char>();
|
||
|
||
// 计算缓冲区大小: 4(头部) + 浮点数组长度*4
|
||
const size_t bufSize = 4 + value.size() * 4;
|
||
std::vector<unsigned char> DataBuf(bufSize, 0x00);
|
||
DataBuf[3] = nCpuNo; // CPU编号放在第4字节
|
||
|
||
// 处理每个浮点值
|
||
for (size_t i = 0; i < value.size(); i++) {
|
||
// 将float转换为网络字节序
|
||
uint32_t intValue;
|
||
memcpy(&intValue, &value[i], sizeof(float));
|
||
uint32_t netValue = htonl(intValue);
|
||
|
||
// 将转换后的值复制到缓冲区
|
||
unsigned char* dest = DataBuf.data() + 4 + i * 4;
|
||
memcpy(dest, &netValue, sizeof(uint32_t));
|
||
}
|
||
|
||
// 生成完整报文
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_Fix));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成请求装置内部定值的报文
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<unsigned char> generate_requestinterfixvalue_message()
|
||
{
|
||
// 创建3字节数据缓冲区并初始化为0
|
||
std::vector<unsigned char> dataBuf(3, 0x00);
|
||
|
||
// 调用通用报文生成函数
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_InterFix));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成请求装置内部定值描述的报文
|
||
* @param nDesCW 描述类型 (1-内部定值描述, 2-控制字描述)
|
||
* @return 包含完整报文的字节向量,参数无效时返回空向量
|
||
*/
|
||
std::vector<unsigned char> generate_requestinterfixdes_message(unsigned char nDesCW)
|
||
{
|
||
// 参数有效性检查
|
||
if (nDesCW < 1 || nDesCW > 2) {
|
||
return std::vector<unsigned char>();
|
||
}
|
||
|
||
// 创建3字节数据缓冲区
|
||
std::vector<unsigned char> dataBuf(3, 0x00);
|
||
|
||
// 设置描述类型
|
||
dataBuf[0] = nDesCW;
|
||
|
||
// 调用通用报文生成函数
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_InterFixDes));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成设置装置内部定值的报文
|
||
* @param values 要设置的定值数组 (ushort值)
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<unsigned char> generate_requestsetinterfixvalue_message(const std::vector<uint16_t>& values)
|
||
{
|
||
// 计算缓冲区大小: 3字节头部 + 每个值占2字节
|
||
const size_t bufSize = 3 + values.size() * 2;
|
||
std::vector<unsigned char> dataBuf(bufSize, 0x00);
|
||
|
||
// 填充定值数据
|
||
for (size_t i = 0; i < values.size(); i++) {
|
||
// 将ushort值转换为网络字节序 (大端)
|
||
uint16_t netValue = htons(values[i]);
|
||
|
||
// 计算目标位置偏移量 (跳过3字节头部)
|
||
unsigned char* dest = dataBuf.data() + 3 + i * 2;
|
||
|
||
// 复制转换后的值到缓冲区
|
||
memcpy(dest, &netValue, sizeof(uint16_t));
|
||
}
|
||
|
||
// 调用通用报文生成函数
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_InterFix));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成设置装置内部定值的报文
|
||
* @param values 要设置的定值数组 (ushort值)
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<unsigned char> generate_requestsetinterfixvalue_message_new(const std::vector<uint16_t>& value)
|
||
{
|
||
// 计算缓冲区大小: 3字节头部 + 每个值占2字节
|
||
const size_t bufSize = 3 + value.size() * 2;
|
||
std::vector<unsigned char> dataBuf(bufSize, 0x00);
|
||
|
||
// 填充定值数据
|
||
for (size_t i = 0; i < value.size(); i++) {
|
||
// 将值转换为字节数组
|
||
uint16_t rawValue = value[i];
|
||
unsigned char* bytes = reinterpret_cast<unsigned char*>(&rawValue);
|
||
|
||
// 反转字节序(模拟C#的ReversalBuff)
|
||
std::swap(bytes[0], bytes[1]);
|
||
|
||
// 计算目标位置偏移量 (跳过3字节头部)
|
||
unsigned char* dest = dataBuf.data() + 3 + i * 2;
|
||
|
||
// 复制转换后的值到缓冲区
|
||
memcpy(dest, bytes, sizeof(uint16_t));
|
||
}
|
||
|
||
// 调用通用报文生成函数
|
||
return GetMsg(dataBuf, static_cast<unsigned char>(MsgRequestType::Request_Set_InterFix));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成装置运行信息读取指令报文
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<unsigned char> generate_machinestatus_message()
|
||
{
|
||
// 创建10字节数据缓冲区,初始化为0
|
||
std::vector<unsigned char> DataBuf(10, 0x00);
|
||
|
||
// 设置索引3的值为1(第4个字节)
|
||
DataBuf[3] = 0x01;
|
||
|
||
// 调用通用报文生成函数,功能码14对应装置状态读取
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_RunningInformation));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成装置版本配置信息读取指令报文
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<unsigned char> generate_machineversion_message()
|
||
{
|
||
// 创建10字节数据缓冲区,初始化为0
|
||
std::vector<unsigned char> DataBuf(10, 0x00);
|
||
|
||
// 设置索引3的值为1(第4个字节)
|
||
DataBuf[3] = 0x02;
|
||
|
||
// 调用通用报文生成函数,功能码14对应装置状态读取
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_RunningInformation));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成设置装置对时的报文
|
||
* @param time 下发的对时时间 (tm值)
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<uint8_t> generate_righttime_message(const std::tm& time) {
|
||
std::vector<uint8_t> DataBuf(15, 0x00); // 创建15字节缓冲区并初始化为0
|
||
|
||
// 前3字节为备用,已初始化为0
|
||
|
||
// 直接填充年月日时分秒(各占2字节,大端序)
|
||
uint16_t year = static_cast<uint16_t>(time.tm_year + 1900);
|
||
DataBuf[3] = static_cast<uint8_t>((year >> 8) & 0xFF); // 高字节
|
||
DataBuf[4] = static_cast<uint8_t>(year & 0xFF); // 低字节
|
||
|
||
uint16_t month = static_cast<uint16_t>(time.tm_mon + 1);
|
||
DataBuf[5] = static_cast<uint8_t>((month >> 8) & 0xFF);
|
||
DataBuf[6] = static_cast<uint8_t>(month & 0xFF);
|
||
|
||
uint16_t day = static_cast<uint16_t>(time.tm_mday);
|
||
DataBuf[7] = static_cast<uint8_t>((day >> 8) & 0xFF);
|
||
DataBuf[8] = static_cast<uint8_t>(day & 0xFF);
|
||
|
||
uint16_t hour = static_cast<uint16_t>(time.tm_hour);
|
||
DataBuf[9] = static_cast<uint8_t>((hour >> 8) & 0xFF);
|
||
DataBuf[10] = static_cast<uint8_t>(hour & 0xFF);
|
||
|
||
uint16_t minute = static_cast<uint16_t>(time.tm_min);
|
||
DataBuf[11] = static_cast<uint8_t>((minute >> 8) & 0xFF);
|
||
DataBuf[12] = static_cast<uint8_t>(minute & 0xFF);
|
||
|
||
uint16_t second = static_cast<uint16_t>(time.tm_sec);
|
||
DataBuf[13] = static_cast<uint8_t>((second >> 8) & 0xFF);
|
||
DataBuf[14] = static_cast<uint8_t>(second & 0xFF);
|
||
|
||
// 调用已有的GetMsg函数生成完整报文,功能码134(0x86)
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_RightTime));
|
||
}
|
||
|
||
/**
|
||
* @brief 生成暂降事件补招报文
|
||
* @param Time1 起始时间
|
||
* @param Time2 结束时间
|
||
* @param eventType 事件类型,默认2-暂态事件 4-告警时间
|
||
* @param monitorPoint 监测点,默认1-监测点1 1-6 对应测点
|
||
* @return 包含完整报文的字节向量
|
||
*/
|
||
std::vector<uint8_t> generate_recallevent_message(const std::tm& Time1, const std::tm& Time2,
|
||
uint8_t eventType, uint8_t monitorPoint)
|
||
{
|
||
std::vector<uint8_t> DataBuf(25, 0x00); // 创建25字节缓冲区并初始化为0
|
||
|
||
// 前3字节为备用,已初始化为0
|
||
|
||
DataBuf[3] = eventType; // 2-暂态事件 4-告警事件
|
||
DataBuf[4] = monitorPoint; // 0-所有监测点
|
||
|
||
// 将时间转换为大端序2字节格式并填充到缓冲区
|
||
uint16_t year1 = static_cast<uint16_t>(Time1.tm_year + 1900);
|
||
DataBuf[5] = static_cast<uint8_t>((year1 >> 8) & 0xFF);
|
||
DataBuf[6] = static_cast<uint8_t>(year1 & 0xFF);
|
||
|
||
uint16_t month1 = static_cast<uint16_t>(Time1.tm_mon + 1);
|
||
DataBuf[7] = static_cast<uint8_t>((month1 >> 8) & 0xFF);
|
||
DataBuf[8] = static_cast<uint8_t>(month1 & 0xFF);
|
||
|
||
uint16_t day1 = static_cast<uint16_t>(Time1.tm_mday);
|
||
DataBuf[9] = static_cast<uint8_t>((day1 >> 8) & 0xFF);
|
||
DataBuf[10] = static_cast<uint8_t>(day1 & 0xFF);
|
||
|
||
uint16_t hour1 = static_cast<uint16_t>(Time1.tm_hour);
|
||
DataBuf[11] = static_cast<uint8_t>((hour1 >> 8) & 0xFF);
|
||
DataBuf[12] = static_cast<uint8_t>(hour1 & 0xFF);
|
||
|
||
uint16_t minute1 = static_cast<uint16_t>(Time1.tm_min);
|
||
DataBuf[13] = static_cast<uint8_t>((minute1 >> 8) & 0xFF);
|
||
DataBuf[14] = static_cast<uint8_t>(minute1 & 0xFF);
|
||
|
||
uint16_t year2 = static_cast<uint16_t>(Time2.tm_year + 1900);
|
||
DataBuf[15] = static_cast<uint8_t>((year2 >> 8) & 0xFF);
|
||
DataBuf[16] = static_cast<uint8_t>(year2 & 0xFF);
|
||
|
||
uint16_t month2 = static_cast<uint16_t>(Time2.tm_mon + 1);
|
||
DataBuf[17] = static_cast<uint8_t>((month2 >> 8) & 0xFF);
|
||
DataBuf[18] = static_cast<uint8_t>(month2 & 0xFF);
|
||
|
||
uint16_t day2 = static_cast<uint16_t>(Time2.tm_mday);
|
||
DataBuf[19] = static_cast<uint8_t>((day2 >> 8) & 0xFF);
|
||
DataBuf[20] = static_cast<uint8_t>(day2 & 0xFF);
|
||
|
||
uint16_t hour2 = static_cast<uint16_t>(Time2.tm_hour);
|
||
DataBuf[21] = static_cast<uint8_t>((hour2 >> 8) & 0xFF);
|
||
DataBuf[22] = static_cast<uint8_t>(hour2 & 0xFF);
|
||
|
||
uint16_t minute2 = static_cast<uint16_t>(Time2.tm_min);
|
||
DataBuf[23] = static_cast<uint8_t>((minute2 >> 8) & 0xFF);
|
||
DataBuf[24] = static_cast<uint8_t>(minute2 & 0xFF);
|
||
|
||
// 调用已有的GetMsg函数生成完整报文,功能码0x0D(事件补招功能码)
|
||
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_Event));
|
||
} |