mrDarker
2025-09-12 49cab6105eccb35d8b18a12f8ea29c05a857471b
SourceCode/Bond/SGMeasurement/CCLinkPerformance/PerformanceMelsec.h
@@ -12,151 +12,151 @@
#include <sstream>
#include <unordered_map>
// 连接参数
#define PLC_MAX_RETRY 3        // 最大重试次数:在与PLC通信时,如果发生通信错误,将最多重试3次
#define PLC_TIMEOUT 500        // 超时时间(毫秒):每次通信操作的超时等待时间为500毫秒
// 连接参数
#define PLC_MAX_RETRY 3        // 最大重试次数:在与PLC通信时,如果发生通信错误,将最多重试3次
#define PLC_TIMEOUT 500        // 超时时间(毫秒):每次通信操作的超时等待时间为500毫秒
/*
 * 网络通道:指定通信所使用的网络通道号,通常在多通道通信中设置
 * 51 到 54 是 MELSECNET/H 的 1-4 通道
 * 81 到 84 是 CC-Link 的 1-4 通道
 * 151 到 154 是 CC-Link IE 控制器网络的 1-4 通道
 * 181 到 184 是 CC-Link IE 现场网络的 1-4 通道
 * 281 到 284 是 CC-Link IE TSN 网络的 1-4 通道
 * 网络通道:指定通信所使用的网络通道号,通常在多通道通信中设置
 * 51 到 54 是 MELSECNET/H 的 1-4 通道
 * 81 到 84 是 CC-Link 的 1-4 通道
 * 151 到 154 是 CC-Link IE 控制器网络的 1-4 通道
 * 181 到 184 是 CC-Link IE 现场网络的 1-4 通道
 * 281 到 284 是 CC-Link IE TSN 网络的 1-4 通道
 **/
#define MELSECNET_CHANNEL(x) (50 + (x))           // x 范围:1~4
#define CC_LINK_CHANNEL(x) (80 + (x))           // x 范围:1~4
#define CC_LINK_IE_CONTROL_CHANNEL(x) (150 + (x)) // x 范围:1~4
#define CC_LINK_IE_FIELD_CHANNEL(x) (180 + (x))   // x 范围:1~4
#define CC_LINK_IE_TSN_CHANNEL(x) (280 + (x))     // x 范围:1~4
#define MELSECNET_CHANNEL(x) (50 + (x))           // x 范围:1~4
#define CC_LINK_CHANNEL(x) (80 + (x))           // x 范围:1~4
#define CC_LINK_IE_CONTROL_CHANNEL(x) (150 + (x)) // x 范围:1~4
#define CC_LINK_IE_FIELD_CHANNEL(x) (180 + (x))   // x 范围:1~4
#define CC_LINK_IE_TSN_CHANNEL(x) (280 + (x))     // x 范围:1~4
 // 自定义错误码
#define ERROR_CODE_UNKNOWN            0x00010000 // δ֪
#define ERROR_CODE_NOT_CONNECTED      0x00020000 // 未连接
#define ERROR_CODE_INVALID_PARAM      0x00030000 // 参数无效
#define ERROR_CODE_INVALID_DATA         0x00040000 // 数据无效
#define ERROR_CODE_STATION_OUT_OF_RANGE 0x00050000 // 站号超出范围
#define ERROR_CODE_GROUP_OUT_OF_RANGE   0x00060000 // 组号超出范围
#define ERROR_CODE_NETWORK_OUT_OF_RANGE 0x00070000 // 网络号超出范围
 // 自定义错误码
#define ERROR_CODE_UNKNOWN            0x00010000 // 未知
#define ERROR_CODE_NOT_CONNECTED      0x00020000 // 未连接
#define ERROR_CODE_INVALID_PARAM      0x00030000 // 参数无效
#define ERROR_CODE_INVALID_DATA         0x00040000 // 数据无效
#define ERROR_CODE_STATION_OUT_OF_RANGE 0x00050000 // 站号超出范围
#define ERROR_CODE_GROUP_OUT_OF_RANGE   0x00060000 // 组号超出范围
#define ERROR_CODE_NETWORK_OUT_OF_RANGE 0x00070000 // 网络号超出范围
// 板块类型
// 板块类型
enum class BoardType {
   UNKNOWN = -1,                              // 未知类型
   UNKNOWN = -1,                              // 未知类型
   MELSECNET_H = MELSECNET_CHANNEL(1),               // MELSECNET/H
   CC_LINK_VER_2 = CC_LINK_CHANNEL(1),               // CC-Link Ver. 2
   CC_LINK_IE_CONTROL = CC_LINK_IE_CONTROL_CHANNEL(1),   // CC-Link IE 控制网络
   CC_LINK_IE_FIELD = CC_LINK_IE_FIELD_CHANNEL(1),     // CC-Link IE 现场网络
   CC_LINK_IE_CONTROL = CC_LINK_IE_CONTROL_CHANNEL(1),   // CC-Link IE 控制网络
   CC_LINK_IE_FIELD = CC_LINK_IE_FIELD_CHANNEL(1),     // CC-Link IE 现场网络
   CC_LINK_IE_TSN = CC_LINK_IE_TSN_CHANNEL(1)          // CC-Link IE TSN
};
// 软元件类型枚举
// 软元件类型枚举
enum class DeviceType {
   /*
    * ER、LX、LY、LB、LW、LSB、LSW和SPG软元件都是范围型
    * ER:DevER0~256
    * LX:DevLX1~255,DevLX(x)   (DevX*1000+(x))
    * LY:DevLY1~255,DevLY(x)   (DevY*1000+(x))
    * LB:DevLB1~255,DevLB(x)   (DevB*1000+(x))
    * LW:DevLW1~255,DevLW(x)   (DevW*1000+(x))
    * LSB:DevLSB1~255,DevLSB(x) (DevQSB*1000+(x))
    * LSW:DevLSW1~255,DevLSW(x) (DevQSW*1000+(x))
    * SPG:DevSPG0~255,DevSPG(x) (29*1000+(x))
    * 扩展文件寄存器代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定块No.(0~256)
    * 链接直接软元件代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定网络No.(1~255)
    * 智能功能模块软元件代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定(起始I/ONo.÷16)的值
    * 扩展文件寄存器和链接直接软元件在随机读取(mdRandR、mdRandREx)函数中,即使指定实际不存在的软元件也有可能正常结束
    * MAIL和MAILMC在SEND功能及RECV功能中,与软元件访问一样,指定各功能对应的软元件类型,进行数据的发送(mdSend、mdSendEx)或数据的读取(mdReceive、mdReceiveEx)
    * ER、LX、LY、LB、LW、LSB、LSW和SPG软元件都是范围型
    * ER:DevER0~256
    * LX:DevLX1~255,DevLX(x)   (DevX*1000+(x))
    * LY:DevLY1~255,DevLY(x)   (DevY*1000+(x))
    * LB:DevLB1~255,DevLB(x)   (DevB*1000+(x))
    * LW:DevLW1~255,DevLW(x)   (DevW*1000+(x))
    * LSB:DevLSB1~255,DevLSB(x) (DevQSB*1000+(x))
    * LSW:DevLSW1~255,DevLSW(x) (DevQSW*1000+(x))
    * SPG:DevSPG0~255,DevSPG(x) (29*1000+(x))
    * 扩展文件寄存器代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定块No.(0~256)
    * 链接直接软元件代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定网络No.(1~255)
    * 智能功能模块软元件代码指定(10进制数)的后3位数及软元件名指定的数值中,应指定(起始I/ONo.÷16)的值
    * 扩展文件寄存器和链接直接软元件在随机读取(mdRandR、mdRandREx)函数中,即使指定实际不存在的软元件也有可能正常结束
    * MAIL和MAILMC在SEND功能及RECV功能中,与软元件访问一样,指定各功能对应的软元件类型,进行数据的发送(mdSend、mdSendEx)或数据的读取(mdReceive、mdReceiveEx)
    **/
   X = 0x0001,      // 输入 (位)
   Y = 0x0002,      // 输出 (位)
   L = 0x0003,      // 锁存继电器 (位)
   M = 0x0004,      // 内部继电器 (位)
   SM = 0x0005,     // 特殊继电器 (位)
   F = 0x0006,      // 报警器 (位)
   TT = 0x0007,     // 定时器 (触点) (位)
   TC = 0x0008,     // 计数器 (线圈) (位)
   CT = 0x0009,     // 计数器 (触点) (位)
   CC = 0x000A,     // 计数器 (线圈) (字)
   TN = 0x000B,     // 定时器 (当前值) (字)
   CN = 0x000C,     // 计数器 (当前值) (字)
   D = 0x000D,      // 数据寄存器 (字)
   SD = 0x000E,     // 特殊寄存器 (字)
   TM = 0x000F,     // 定时器 (设置值主) (字)
   TS = 0x0010,     // 定时器 (设置值主1) (字)
   TS2 = 0x3E82,    // 定时器 (设置值主2) (字)
   TS3 = 0x3E83,    // 定时器 (设置值主3) (字)
   CM = 0x0011,     // 计数器 (设置值主) (字)
   CS = 0x0012,     // 计数器 (设置值主1) (字)
   CS2 = 0x4652,    // 计数器 (设置值主2) (字)
   CS3 = 0x4653,    // 计数器 (设置值主3) (字)
   A = 0x0013,      // 累加器 (字)
   Z = 0x0014,      // 变址寄存器 (字)
   V = 0x0015,      // 变址寄存器 (字)
   R = 0x0016,      // 文件寄存器 (块切换方式) (字)
   ER = 0x55F0,     // 扩展文件寄存器 (块切换方式) (0x55F0~0x56F0) (字) (在随机读取(mdRandR、mdRandREx)函数中,即使指定实际不存在的软元件也有可能正常结束。(读取数据不正确。))
   ZR = 0x00DC,     // 文件寄存器 (连号访问方式) (字)
   B = 0x0017,      // 链接继电器 (位)
   W = 0x0018,      // 链接寄存器 (字)
   QSB = 0x0019,    // 链接特殊继电器 (位)
   STT = 0x001A,    // 累计定时器 (触点) (位)
   STC = 0x001B,    // 累计定时器 (线圈) (位)
   QSW = 0x001C,    // 链接特殊寄存器 (字)
   QV = 0x001E,     // 变址继电器 (位)
   MRB = 0x0021,    // 随机访问缓冲 (字)
   STN = 0x0023,    // 累计定时器 (当前值) (字)
   LZ = 0x0026,     // 超长变址寄存器 (双字)
   RD = 0x0027,     // 刷新数据寄存器 (字)
   LTT = 0x0029,    // 超长定时器 (触点) (位)
   LTC = 0x002A,    // 超长定时器 (线圈) (位)
   LTN = 0x002B,    // 超长定时器 (当前值) (双字)
   LCT = 0x002C,    // 超长计数器 (触点) (位)
   LCC = 0x002D,    // 超长计数器 (线圈) (位)
   LCN = 0x002E,    // 超长计数器 (当前值) (双字)
   LSTT = 0x002F,   // 超长累计定时器 (触点) (位)
   LSTC = 0x0030,   // 超长累计定时器 (线圈) (位)
   LSTN = 0x0031,   // 超长累计定时器 (当前值) (双字)
   SPB = 0x0032,    // 缓冲存储器 (字)
   MAIL = 0x0065,   // 特殊软元件类型:邮件类型 (10进制 101)
   MAILMC = 0x0066, // 特殊软元件类型:无确认邮件 (10进制 102)
   LX = 0x03E8,     // 链接直接软元件 (链接输入) (0x03E9~0x04E7) (位)
   LY = 0x07D0,     // 链接直接软元件 (链接输出) (0x07D1~0x08CF) (位)
   LB = 0x59D8,     // 链接直接软元件 (链接继电器) (0x59D9~0x5AD7) (位)
   LW = 0x5DC0,     // 链接直接软元件 (链接寄存器) (0x5DC1~0x5EBF) (字)
   LSB = 0x61A8,    // 链接直接软元件 (链接特殊继电器) (0x61A9~0x62A7) (位)
   LSW = 0x6D60,    // 链接直接软元件 (链接特殊寄存器) (0x6D61~0x6E5F) (字)
   SPG = 0x7147,    // 智能功能模块软元件 (0x7148~0x7247) (字)
   X = 0x0001,      // 输入 (位)
   Y = 0x0002,      // 输出 (位)
   L = 0x0003,      // 锁存继电器 (位)
   M = 0x0004,      // 内部继电器 (位)
   SM = 0x0005,     // 特殊继电器 (位)
   F = 0x0006,      // 报警器 (位)
   TT = 0x0007,     // 定时器 (触点) (位)
   TC = 0x0008,     // 计数器 (线圈) (位)
   CT = 0x0009,     // 计数器 (触点) (位)
   CC = 0x000A,     // 计数器 (线圈) (字)
   TN = 0x000B,     // 定时器 (当前值) (字)
   CN = 0x000C,     // 计数器 (当前值) (字)
   D = 0x000D,      // 数据寄存器 (字)
   SD = 0x000E,     // 特殊寄存器 (字)
   TM = 0x000F,     // 定时器 (设置值主) (字)
   TS = 0x0010,     // 定时器 (设置值主1) (字)
   TS2 = 0x3E82,    // 定时器 (设置值主2) (字)
   TS3 = 0x3E83,    // 定时器 (设置值主3) (字)
   CM = 0x0011,     // 计数器 (设置值主) (字)
   CS = 0x0012,     // 计数器 (设置值主1) (字)
   CS2 = 0x4652,    // 计数器 (设置值主2) (字)
   CS3 = 0x4653,    // 计数器 (设置值主3) (字)
   A = 0x0013,      // 累加器 (字)
   Z = 0x0014,      // 变址寄存器 (字)
   V = 0x0015,      // 变址寄存器 (字)
   R = 0x0016,      // 文件寄存器 (块切换方式) (字)
   ER = 0x55F0,     // 扩展文件寄存器 (块切换方式) (0x55F0~0x56F0) (字) (在随机读取(mdRandR、mdRandREx)函数中,即使指定实际不存在的软元件也有可能正常结束。(读取数据不正确。))
   ZR = 0x00DC,     // 文件寄存器 (连号访问方式) (字)
   B = 0x0017,      // 链接继电器 (位)
   W = 0x0018,      // 链接寄存器 (字)
   QSB = 0x0019,    // 链接特殊继电器 (位)
   STT = 0x001A,    // 累计定时器 (触点) (位)
   STC = 0x001B,    // 累计定时器 (线圈) (位)
   QSW = 0x001C,    // 链接特殊寄存器 (字)
   QV = 0x001E,     // 变址继电器 (位)
   MRB = 0x0021,    // 随机访问缓冲 (字)
   STN = 0x0023,    // 累计定时器 (当前值) (字)
   LZ = 0x0026,     // 超长变址寄存器 (双字)
   RD = 0x0027,     // 刷新数据寄存器 (字)
   LTT = 0x0029,    // 超长定时器 (触点) (位)
   LTC = 0x002A,    // 超长定时器 (线圈) (位)
   LTN = 0x002B,    // 超长定时器 (当前值) (双字)
   LCT = 0x002C,    // 超长计数器 (触点) (位)
   LCC = 0x002D,    // 超长计数器 (线圈) (位)
   LCN = 0x002E,    // 超长计数器 (当前值) (双字)
   LSTT = 0x002F,   // 超长累计定时器 (触点) (位)
   LSTC = 0x0030,   // 超长累计定时器 (线圈) (位)
   LSTN = 0x0031,   // 超长累计定时器 (当前值) (双字)
   SPB = 0x0032,    // 缓冲存储器 (字)
   MAIL = 0x0065,   // 特殊软元件类型:邮件类型 (10进制 101)
   MAILMC = 0x0066, // 特殊软元件类型:无确认邮件 (10进制 102)
   LX = 0x03E8,     // 链接直接软元件 (链接输入) (0x03E9~0x04E7) (位)
   LY = 0x07D0,     // 链接直接软元件 (链接输出) (0x07D1~0x08CF) (位)
   LB = 0x59D8,     // 链接直接软元件 (链接继电器) (0x59D9~0x5AD7) (位)
   LW = 0x5DC0,     // 链接直接软元件 (链接寄存器) (0x5DC1~0x5EBF) (字)
   LSB = 0x61A8,    // 链接直接软元件 (链接特殊继电器) (0x61A9~0x62A7) (位)
   LSW = 0x6D60,    // 链接直接软元件 (链接特殊寄存器) (0x6D61~0x6E5F) (字)
   SPG = 0x7147,    // 智能功能模块软元件 (0x7148~0x7247) (字)
};
// 数据类型
// 数据类型
enum class DataType {
   BIT = 1,   // λ (1λ)
   WORD = 2,  // 字 (16位)
   DWORD = 4  // 双字 (32位)
   BIT = 1,   // 位 (1位)
   WORD = 2,  // 字 (16位)
   DWORD = 4  // 双字 (32位)
};
// 控制代码
// 控制代码
enum class ControlCode {
   RUN = 0,   // 远程 RUN
   STOP = 1,  // 远程 STOP
   PAUSE = 2  // 远程 PAUSE
   RUN = 0,   // 远程 RUN
   STOP = 1,  // 远程 STOP
   PAUSE = 2  // 远程 PAUSE
};
// 版本信息
// 版本信息
struct BoardVersion {
   char fixedValue[2];       // 固定值
   char checksum[2];         // 校验和
   char swVersion[2];        // 软件版本
   char date[6];             // 日期 (格式 YYMMDD)
   uint32_t reserved;        // 保留区域 (4 字节)
   char swModel[16];         // 软件型号
   char hwModel[16];         // 硬件型号
   char twoPortMemory[2];    // 两端口存储器占用容量
   char twoPortAttribute[2]; // 两端口属性
   char availableBias[2];    // 可使用偏置
   char moduleType[10];      // 机型类型
   char fixedValue[2];       // 固定值
   char checksum[2];         // 校验和
   char swVersion[2];        // 软件版本
   char date[6];             // 日期 (格式 YYMMDD)
   uint32_t reserved;        // 保留区域 (4 字节)
   char swModel[16];         // 软件型号
   char hwModel[16];         // 硬件型号
   char twoPortMemory[2];    // 两端口存储器占用容量
   char twoPortAttribute[2]; // 两端口属性
   char availableBias[2];    // 可使用偏置
   char moduleType[10];      // 机型类型
   // 输出结构体内容为字符串 (便于调试)
   // 输出结构体内容为字符串 (便于调试)
   std::string toString() const {
      std::ostringstream oss;
      oss << "Fixed Value: " << fixedValue[0] << fixedValue[1] << "\n"
@@ -174,18 +174,18 @@
   }
};
// 站点标识符,默认使用本站
// 站点标识符,默认使用本站
struct StationIdentifier {
   /*
    * [Network No.]
    * 0 表示本站
    * 1~239 表示普通网络号
    * 0 表示本站
    * 1~239 表示普通网络号
    **/
    /*
     * [Station No.]
     * MELSECNET/H:1~64 表示其他站点,255 表示本站
     * CC-Link 系列网络的范围类似,区别在于站号的取值范围
     * MELSECNET/H:1~64 表示其他站点,255 表示本站
     * CC-Link 系列网络的范围类似,区别在于站号的取值范围
     * MELSECNET/H             : 1~64(Other stations),255(Own station)
     * CC-Link                 : 0~63(Other stations),255(Own station)
     * CC-Link IE Controller   : 1~120(Other stations),255(Own station)
@@ -194,15 +194,15 @@
     **/
     /*
      * 高 8 位(网络号): 指定设备所属的网络
      * 低 8 位(站点号): 指定设备在网络中的编号
      * 用一个参数传递设备的网络号和站点号时: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00);
      * 高 8 位(网络号): 指定设备所属的网络
      * 低 8 位(站点号): 指定设备在网络中的编号
      * 用一个参数传递设备的网络号和站点号时: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00);
      **/
   short nNetNo = 0;    // 网络编号:PLC所连接的网络编号,0表示默认网络
   short nStNo = 255;   // 站点编号:指定与PLC连接的站点编号,255通常表示广播或所有站点
   short nNetNo = 0;    // 网络编号:PLC所连接的网络编号,0表示默认网络
   short nStNo = 255;   // 站点编号:指定与PLC连接的站点编号,255通常表示广播或所有站点
   // 自定义构造函数,覆盖默认值
   // 自定义构造函数,覆盖默认值
   explicit StationIdentifier(const short net, const short st) : nNetNo(net), nStNo(st) {}
   StationIdentifier() 
@@ -211,24 +211,24 @@
      nStNo = 255;
   }
   // 将“网络号”和“站点号”组合成一个最终编码
   // 将“网络号”和“站点号”组合成一个最终编码
   short StationIdentifier::toNetworkStationCode() const {
      return static_cast<short>(nStNo | ((nNetNo << 8) & 0xFF00));
   }
   // 重载 < 运算符(用于排序或比较,通常用于 map 或 set 中作为 key)
   // 重载 < 运算符(用于排序或比较,通常用于 map 或 set 中作为 key)
   bool operator<(const StationIdentifier& other) const {
      return std::tie(nNetNo, nStNo) <
         std::tie(other.nNetNo, other.nStNo);
   }
   // 重载 == 运算符(用于相等比较)
   // 重载 == 运算符(用于相等比较)
   bool operator==(const StationIdentifier& other) const {
      return std::tie(nNetNo, nStNo) ==
         std::tie(other.nNetNo, other.nStNo);
   }
   // 重载 = 运算符(用于赋值)
   // 重载 = 运算符(用于赋值)
   StationIdentifier& operator=(const StationIdentifier& other) {
      if (this != &other) {
         nNetNo = other.nNetNo;
@@ -238,16 +238,16 @@
   }
};
// 板状态
// 板状态
struct BoardStatus {
   short nStationValue = 0;    // 站号的设备值 (buf[0])
   short nGroupValue = 0;      // 组 No. 的设备值 (buf[1])
   short nNetworkValue = 0;    // 网络 No. 的设备值 (buf[2])
   short nReserved1 = 0;       // 保留字段 (buf[3])
   short nReserved2 = 0;       // 保留字段 (buf[4])
   short nReserved3 = 0;       // 保留字段 (buf[5])
   short nStationValue = 0;    // 站号的设备值 (buf[0])
   short nGroupValue = 0;      // 组 No. 的设备值 (buf[1])
   short nNetworkValue = 0;    // 网络 No. 的设备值 (buf[2])
   short nReserved1 = 0;       // 保留字段 (buf[3])
   short nReserved2 = 0;       // 保留字段 (buf[4])
   short nReserved3 = 0;       // 保留字段 (buf[5])
   // 将数组映射到结构体
   // 将数组映射到结构体
   static BoardStatus fromBuffer(const short buf[6]) {
      return {
         buf[0],
@@ -259,7 +259,7 @@
      };
   }
   // 将结构体内容映射到数组
   // 将结构体内容映射到数组
   void toBuffer(short buf[6]) const {
      buf[0] = nStationValue;
      buf[1] = nGroupValue;
@@ -269,7 +269,7 @@
      buf[5] = nReserved3;
   }
   // 调试输出
   // 调试输出
   std::string toString() const {
      std::ostringstream oss;
      oss << "Station Value: " << nStationValue << "\n"
@@ -282,12 +282,12 @@
   }
};
// 事件详情
// 事件详情
struct EventDetails {
   short nEventNo;                 // 发生的事件号
   std::array<short, 4> details;       // 存储事件详情信息
   short nEventNo;                 // 发生的事件号
   std::array<short, 4> details;       // 存储事件详情信息
   // 解析事件详情,返回格式化字符串
   // 解析事件详情,返回格式化字符串
   std::string toString() const {
      std::ostringstream oss;
      oss << "Details[0]: " << details[0] << ", "
@@ -298,33 +298,33 @@
   }
};
// SoftElement 结构体定义
// SoftElement 结构体定义
struct SoftElement {
   short nType;         // 软元件类型
   short nElementCount; // 点数
   long nStartNo;       // 起始软元件编号
   short nType;         // 软元件类型
   short nElementCount; // 点数
   long nStartNo;       // 起始软元件编号
};
// 错误信息
// 错误信息
struct ErrorInfo {
   int nErrorCode = 0;              // 错误码
   std::string strErrorMessageCn;   // 中文描述
   std::string strErrorMessageEn;   // 英文描述
   int nErrorCode = 0;              // 错误码
   std::string strErrorMessageCn;   // 中文描述
   std::string strErrorMessageEn;   // 英文描述
   // 将结构体序列化为字符串
   // 将结构体序列化为字符串
   std::string toString() const {
      std::ostringstream oss;
      oss << nErrorCode << "|" << strErrorMessageCn << "|" << strErrorMessageEn;
      return oss.str();
   }
   // 从字符串反序列化为结构体
   // 从字符串反序列化为结构体
   static ErrorInfo fromString(const std::string& line) {
      ErrorInfo info;
      std::istringstream iss(line);
      std::string token;
      // 使用分隔符 "|" 解析字符串
      // 使用分隔符 "|" 解析字符串
      std::getline(iss, token, '|');
      info.nErrorCode = std::stoi(token);
@@ -338,47 +338,47 @@
   }
};
using BitContainer = std::vector<bool>;         // 每个元素存储 1  位
using WordContainer = std::vector<uint16_t>;   // 每个元素存储 16 位
using DWordContainer = std::vector<uint32_t>;   // 每个元素存储 32 位
using BitContainer = std::vector<bool>;         // 每个元素存储 1  位
using WordContainer = std::vector<uint16_t>;   // 每个元素存储 16 位
using DWordContainer = std::vector<uint32_t>;   // 每个元素存储 32 位
// CPerformanceMelsec 类声明
// CPerformanceMelsec 类声明
class CPerformanceMelsec {
public:
   // 获取最近的错误信息
   // 获取最近的错误信息
   std::string GetLastError() const;
   // 错误信息加载与保存接口
   static bool LoadErrorInfoFromFile(const std::string& filename);  // 从文件加载错误信息
   static bool SaveErrorInfoToFile(const std::string& filename);    // 保存错误信息到文件
   // 错误信息加载与保存接口
   static bool LoadErrorInfoFromFile(const std::string& filename);  // 从文件加载错误信息
   static bool SaveErrorInfoToFile(const std::string& filename);    // 保存错误信息到文件
   // 连接/断开
   // 连接/断开
   int Connect(short nChannel, short nMode = -1);
   int Disconnect();
   // 初始化可编程控制器软元件信息表
   // 初始化可编程控制器软元件信息表
   int InitializeController();
   //   获取版本信息
   //   获取版本信息
   int GetBoardVersion(BoardVersion& version);
   // 板复位
   // 板复位
   int BoardReset();
   // 板LED读取
   // 板LED读取
   int ReadBoardLed(std::vector<short>& vecLedBuffer);
   // 读取目标站点CPU类型
   // 读取目标站点CPU类型
   int ReadCPUCode(const StationIdentifier& station, short& nCPUCode);
   // 板模式获取/设置
   // 板模式获取/设置
   int SetBoardMode(short nMode);
   int GetBoardMode(short& nMode);
   // 获取板状态
   // 获取板状态
   int GetBoardStatus(BoardStatus& status);
   // 读写数据
   // 读写数据
   int ReadData(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<short>& vecData);
   int ReadBitData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, short nBitCount, BitContainer& vecData);
   int ReadWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, short nWordCount, WordContainer& vecData);
@@ -388,7 +388,7 @@
   int WriteWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, const WordContainer& vecData);
   int WriteDWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, const DWordContainer& vecData);
   // 扩展读写数据
   // 扩展读写数据
   long ReadDataEx(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<char>& vecData);
   long ReadBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nBitCount, BitContainer& vecData);
   long ReadWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nWordCount, WordContainer& vecData);
@@ -398,56 +398,56 @@
   long WriteWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const WordContainer& vecData);
   long WriteDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const DWordContainer& vecData);
   // 扩展软元件随机读写(支持多个软元件)
   // 扩展软元件随机读写(支持多个软元件)
   long ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData);
   long WriteRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, const std::vector<char>& vecData);
   // 远程设备站/远程站的缓冲存储器读写
   // 远程设备站/远程站的缓冲存储器读写
   long ReadRemoteBuffer(const StationIdentifier& station, long nOffset, long nSize, std::vector<char>& vecData);
   long WriteRemoteBuffer(const StationIdentifier& station, long nOffset, const std::vector<char>& vecData);
   long ReadRemoteBufferByIp(const std::string& strIP, long nOffset, long nSize, std::vector<char>& vecData);
   long WriteRemoteBufferByIp(const std::string& strIP, long nOffset, const std::vector<char>& vecData);
   // 设置/复位对象站的指定位软元件
   // 设置/复位对象站的指定位软元件
   int SetBitDevice(const StationIdentifier& station, DeviceType enDevType, short nDevNo);
   int ResetBitDevice(const StationIdentifier& station, DeviceType enDevType, short enDevNo);
   // 扩展设置/复位对象站的指定位软元件
   // 扩展设置/复位对象站的指定位软元件
   long SetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo);
   long ResetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo);
   // 执行对象站的CPU
   // 执行对象站的CPU
   int ControlCPU(const StationIdentifier& station, ControlCode enControlCode);
   // 事件等待,vecEventNumbers[0, 64],nTimeoutMs[-1, 2147483647]
   // 同时发生了多个事件的情况下,首先检测出其中一个事件。 再次执行了本函数的情况下检测出其它事件。
   // 事件等待,vecEventNumbers[0, 64],nTimeoutMs[-1, 2147483647]
   // 同时发生了多个事件的情况下,首先检测出其中一个事件。 再次执行了本函数的情况下检测出其它事件。
   int WaitForBoardEvent(std::vector<short> vecEventNumbers, int nTimeoutMs, EventDetails& details);
private:
   // 锁定与解锁(多线程同步保护)
   // 锁定与解锁(多线程同步保护)
   void Lock() { m_mtx.lock(); }
   void Unlock() { m_mtx.unlock(); }
protected:
   // 构造函数/析构函数
   // 构造函数/析构函数
   explicit CPerformanceMelsec(BoardType enBoardType);
   virtual ~CPerformanceMelsec();
   // 辅助函数
   void UpdateLastError(int nCode);                         // 更新最近的错误信息
   int ValidateStation(const StationIdentifier& station) const;    // 检查连接状态和站点参数有效性
   // 辅助函数
   void UpdateLastError(int nCode);                         // 更新最近的错误信息
   int ValidateStation(const StationIdentifier& station) const;    // 检查连接状态和站点参数有效性
   int ValidateStationAndSize(const StationIdentifier& station, short nCount) const;
   // 静态辅助函数
   static void Delay(unsigned int nDelayMs);                  // 延时,并且转发窗口消息
   static BoardType FindBoardTypeByChannel(int nChannel);         // 查找板块类型
   static short CombineStation(const StationIdentifier& station);  // 合并网络号和站点号
   static short CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType); // 计算软元件类型
   // 静态辅助函数
   static void Delay(unsigned int nDelayMs);                  // 延时,并且转发窗口消息
   static BoardType FindBoardTypeByChannel(int nChannel);         // 查找板块类型
   static short CombineStation(const StationIdentifier& station);  // 合并网络号和站点号
   static short CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType); // 计算软元件类型
   // IP转换
   // IP转换
   static bool ConvertIpStringToUint32(const std::string& strIP, uint32_t& nIP);
   // 容器转换
   // 容器转换
   static void ConvertCharToShort(const std::vector<char>& vecChar, std::vector<short>& vecShort);
   static void ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>& vecChar);
   static void ConvertUint8ToShort(const std::vector<uint8_t>& vecUint8, std::vector<short>& vecShort);
@@ -455,7 +455,7 @@
   static void ConvertUint32ToShort(const std::vector<uint32_t>& vecUint32, std::vector<short>& vecShort);
   static void ConvertShortToUint32(const std::vector<short>& vecShort, std::vector<uint32_t>& vecUint32);
   // 模板辅助函数
   // 模板辅助函数
   template <typename T>
   int ValidateStationAndData(const StationIdentifier& station, const std::vector<T>& vecData);
@@ -465,15 +465,15 @@
   template <typename T, typename U>
   void ConvertHighToLow(const std::vector<T>& vecHigh, std::vector<U>& vecLow);
   // 成员变量
   std::mutex m_mtx;                       // 互斥锁保护
   BoardType m_enBoardType;            // 板块类型
   long m_nPath;                           // 通信路径
   std::atomic<bool> m_bConnected;         // 是否已连接
   std::string m_strLastError;             // 最近一次错误信息
   // 成员变量
   std::mutex m_mtx;                       // 互斥锁保护
   BoardType m_enBoardType;            // 板块类型
   long m_nPath;                           // 通信路径
   std::atomic<bool> m_bConnected;         // 是否已连接
   std::string m_strLastError;             // 最近一次错误信息
   // 静态成员变量
   static std::unordered_map<int, std::string> m_mapError; // 错误码映射表
   // 静态成员变量
   static std::unordered_map<int, std::string> m_mapError; // 错误码映射表
};
#endif // PERFORMANCE_MELSEC_H