LAPTOP-SNT8I5JK\Boounion
2025-05-27 e42e8364112e97d89eeaecd13f043dff42179949
SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp
@@ -23,9 +23,9 @@
#define LOG_DEBUG(msg)
#endif
// 初始化静态成员变量
// 初始化静态成员变量
std::unordered_map<int, std::string> CPerformanceMelsec::m_mapError = {
    // 板块SDK错误码
    // 板块SDK错误码
    {0, "No error, communication successful."},
    {1, "Driver not started. The driver is not running."},
    {2, "Timeout error (board response error). Request not completed within timeout."},
@@ -118,7 +118,7 @@
    {-28634, "Hardware self-diagnosis error."},
    {-28636, "Hardware self-diagnosis error."},
    // 自定义错误码
    // 自定义错误码
    {ERROR_CODE_UNKNOWN, "Error: Unknown error code."},
    {ERROR_CODE_NOT_CONNECTED, "Error: Not connected to the device."},
    {ERROR_CODE_INVALID_PARAM, "Error: Invalid parameter."},
@@ -137,26 +137,26 @@
    m_bConnected.store(false);
}
// 析构函数
// 析构函数
CPerformanceMelsec::~CPerformanceMelsec() {
    Disconnect();
}
// 获取最近的错误信息
// 获取最近的错误信息
std::string CPerformanceMelsec::GetLastError() const {
    return m_strLastError;
}
// 保存错误信息
// 保存错误信息
bool CPerformanceMelsec::SaveErrorInfoToFile(const std::string& filename) {
    // 打开文件
    // 打开文件
    std::ofstream file(filename);
    if (!file.is_open()) {
        std::cerr << "Failed to open file for saving: " << filename << std::endl;
        return false;
    }
    // 遍历静态成员变量 m_mapError 并将每个错误信息写入文件
    // 遍历静态成员变量 m_mapError 并将每个错误信息写入文件
    for (const auto& entry : m_mapError) {
        const int nCode = entry.first;
        const std::string& strMessage = entry.second;
@@ -167,7 +167,7 @@
    return true;
}
// 加载错误信息
// 加载错误信息
bool CPerformanceMelsec::LoadErrorInfoFromFile(const std::string& filename) {
    std::ifstream inFile(filename);
    if (!inFile.is_open()) {
@@ -183,7 +183,7 @@
        std::string strToken;
        std::string strMessage;
        // 使用分隔符 "|" 解析每一行
        // 使用分隔符 "|" 解析每一行
        if (std::getline(iss, strToken, '|')) {
            nCode = std::stoi(strToken);
        }
@@ -200,7 +200,7 @@
    return true;
}
// 连接到PLC
// 连接到PLC
int CPerformanceMelsec::Connect(const short nChannel, const short nMode) {
    std::lock_guard<std::mutex> lock(m_mtx);
@@ -214,12 +214,13 @@
        return ERROR_CODE_INVALID_PARAM;
    }
    // 连接PLC,显式类型转换以匹配 mdOpen 的签名
    // 连接PLC,显式类型转换以匹配 mdOpen 的签名
    const short nRet = mdOpen(nChannel, nMode, &m_nPath);
    if (nRet == 0) {
        m_bConnected.store(true);
        m_enBoardType = enBoardType;
    } else {
    }
    else {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
    }
@@ -227,7 +228,7 @@
    return nRet;
}
// 断开连接
// 断开连接
int CPerformanceMelsec::Disconnect() {
    std::lock_guard<std::mutex> lock(m_mtx);
@@ -244,7 +245,7 @@
    return nRet;
}
// 可编程控制器软元件信息表的初始化
// 可编程控制器软元件信息表的初始化
int CPerformanceMelsec::InitializeController() {
    std::lock_guard<std::mutex> lock(m_mtx);
@@ -262,15 +263,15 @@
    return nRet;
}
// 获取版本信息
// 获取版本信息
int CPerformanceMelsec::GetBoardVersion(BoardVersion& version) {
    if (!m_bConnected.load()) {
        UpdateLastError(ERROR_CODE_NOT_CONNECTED);
        return ERROR_CODE_NOT_CONNECTED;
    }
    // 获取版本信息
    short buf[32] = {0};
    // 获取版本信息
    short buf[32] = { 0 };
    const short nRet = mdBdVerRead(m_nPath, buf);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -278,7 +279,7 @@
        return nRet;
    }
    // 填充版本信息到结构体
    // 填充版本信息到结构体
    version.fixedValue[0] = static_cast<char>(buf[0] & 0xFF);
    version.fixedValue[1] = static_cast<char>((buf[0] >> 8) & 0xFF);
@@ -309,16 +310,16 @@
    return nRet;
}
// 读取目标站点CPU类型
// 读取目标站点CPU类型
int CPerformanceMelsec::ReadCPUCode(const StationIdentifier& station, short& nCPUCode) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        nCPUCode = 0;
        std::lock_guard<std::mutex> lock(m_mtx);
@@ -333,15 +334,15 @@
    return nRet;
}
// 板模式设置
// 板模式设置
int CPerformanceMelsec::SetBoardMode(const short nMode) {
    // 检查是否已经连接
    // 检查是否已经连接
    if (!m_bConnected.load()) {
        UpdateLastError(ERROR_CODE_NOT_CONNECTED);
        return ERROR_CODE_NOT_CONNECTED;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    short nRet = 0;
    {
        std::lock_guard<std::mutex> lock(m_mtx);
@@ -356,9 +357,9 @@
    return nRet;
}
// 获取板模式
// 获取板模式
int CPerformanceMelsec::GetBoardMode(short& nMode) {
    // 检查是否已经连接
    // 检查是否已经连接
    if (!m_bConnected.load()) {
        UpdateLastError(ERROR_CODE_NOT_CONNECTED);
        return ERROR_CODE_NOT_CONNECTED;
@@ -380,7 +381,7 @@
    return 0;
}
// 板复位
// 板复位
int CPerformanceMelsec::BoardReset() {
    std::lock_guard<std::mutex> lock(m_mtx);
    if (!m_bConnected.load()) {
@@ -397,7 +398,7 @@
    return nRet;
}
// 板LED读取
// 板LED读取
int CPerformanceMelsec::ReadBoardLed(std::vector<short>& vecLedBuffer) {
    std::lock_guard<std::mutex> lock(m_mtx);
    if (!m_bConnected.load()) {
@@ -405,11 +406,11 @@
        return ERROR_CODE_NOT_CONNECTED;
    }
    // 清空 LED 缓冲区
    // 清空 LED 缓冲区
    vecLedBuffer.clear();
    vecLedBuffer.resize(16, 0);
    // 调用 SDK 函数读取 LED 数据
    // 调用 SDK 函数读取 LED 数据
    const short nRet = mdBdLedRead(m_nPath, vecLedBuffer.data());
    if (nRet != 0) {
        UpdateLastError(ERROR_CODE_NOT_CONNECTED);
@@ -420,7 +421,7 @@
    return nRet;
}
// 获取板状态
// 获取板状态
int CPerformanceMelsec::GetBoardStatus(BoardStatus& status) {
    std::lock_guard<std::mutex> lock(m_mtx);
    if (!m_bConnected) {
@@ -428,36 +429,37 @@
        return ERROR_CODE_NOT_CONNECTED;
    }
    short buf[6] = {0};
    short buf[6] = { 0 };
    const short nRet = mdBdSwRead(m_nPath, buf);
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
    }
    // 将 buf 映射到结构体
    // 将 buf 映射到结构体
    status = BoardStatus::fromBuffer(buf);
    return 0;
}
// 通用读数据
int CPerformanceMelsec::ReadData(const StationIdentifier& station, const short nDevType, const short nDevNo, short nSize, std::vector<short>& vecData) {
    // 验证站点参数和数据有效性
// 通用读数据
int CPerformanceMelsec::ReadData(const StationIdentifier& station, const long nDevType, const long nDevNo, long nSize, std::vector<short>& vecData) {
    // 验证站点参数和数据有效性
    int nRet = ValidateStationAndSize(station, nSize);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 初始化读取缓冲区
    // 初始化读取缓冲区
    vecData.clear();
    vecData.resize(nSize);
    vecData.resize(nSize, 0);
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        std::lock_guard<std::mutex> lock(m_mtx);
        short* pData = vecData.data();
        nRet = mdReceive(m_nPath, CombineStation(station), nDevType, nDevNo, &nSize, pData);
        nSize *= sizeof(short);
        nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, (long)(unsigned short)nDevNo, &nSize, pData);
    }
    if (nRet != 0) {
@@ -466,38 +468,56 @@
    }
    if (nRet != 0) {
        vecData.clear(); // 如果读取失败,清空缓冲区
        vecData.clear(); // 如果读取失败,清空缓冲区
    }
    return nRet;
}
// 读取位数据
// 读取位数据
int CPerformanceMelsec::ReadBitData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nBitCount, BitContainer& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStationAndSize(station, nBitCount);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 计算需要读取的字节大小(按位对齐为字节数)
    if (nDevNo % 8 != 0) {
        nRet = -2;
        UpdateLastError(nRet);
        return nRet;
    }
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((nBitCount + 7) / 8);     // 向上取整
    std::vector<short> vecTempBuffer((nSize + 1) / 2, 0); // 临时缓冲区,字节对齐
    const auto nSize = static_cast<short>((static_cast<int>(nBitCount) + 15) / 16);  // 计算需要读取的字数量(向上取整)
    std::vector<short> vecTempBuffer(nSize, 0);
    nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer);
    if (nRet == 0) {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertShortToUint8(vecTempBuffer, vecData);
        vecData.clear();
        // 将字数据解析为位数据
        for (short nIdx = 0; nIdx < nSize; ++nIdx) {
            const short nCurrentValue = vecTempBuffer[nIdx];
            // 遍历当前 short 中的每一位
            for (int bitIdx = 0; bitIdx < 16; ++bitIdx) {
                bool bBit = (nCurrentValue & (1 << bitIdx)) != 0;
                vecData.push_back(bBit);
                if (vecData.size() >= nBitCount) {
                    return nRet;  // 如果已经读取完所需的位数,提前退出
                }
            }
        }
    }
    return nRet;
}
// 读取字数据
// 读取字数据
int CPerformanceMelsec::ReadWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nWordCount, WordContainer& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStationAndSize(station, nWordCount);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -516,47 +536,48 @@
    return nRet;
}
// 读取双字数据
// 读取双字数据
int CPerformanceMelsec::ReadDWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nDWordCount, DWordContainer& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStationAndSize(station, nDWordCount);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    const auto nSize = static_cast<short>(nDWordCount * 2); // 每个双字占两个字(每个双字占 4 字节)
    const auto nSize = static_cast<short>(nDWordCount * 2); // 每个双字占两个字(每个双字占 4 字节)
    const short nDevType = CalculateDeviceType(station, enDevType);
    std::vector<short> vecTempBuffer(nSize, 0);
    nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer);
    if (nRet == 0) {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertShortToUint32(vecTempBuffer, vecData);
    }
    return nRet;
}
// 通用写数据
int CPerformanceMelsec::WriteData(const StationIdentifier& station, const short nDevType, const short nDevNo, short nSize, short* pData) {
    // 验证站点参数
// 通用写数据
int CPerformanceMelsec::WriteData(const StationIdentifier& station, const long nDevType, const long nDevNo, long nSize, short* pData) {
    // 验证站点参数
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 数据有效性
    // 数据有效性
    if (nSize < 0 || pData == nullptr) {
        UpdateLastError(ERROR_CODE_INVALID_PARAM);
        return ERROR_CODE_INVALID_PARAM;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        std::lock_guard<std::mutex> lock(m_mtx);
        nRet = mdSend(m_nPath, CombineStation(station), nDevType, nDevNo, &nSize, pData);
        nSize *= sizeof(short);
        nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, pData);
    }
    if (nRet != 0) {
@@ -567,68 +588,81 @@
    return nRet;
}
// 写位数据
// 写位数据
int CPerformanceMelsec::WriteBitData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const BitContainer& vecData) {
    // 验证站点参数和数据有效性
    const int nRet = ValidateStationAndData(station, vecData);
    // 验证站点参数和数据有效性
    int nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 计算需要写入的字节数(位数据需要按 8 位对齐为字节数)
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((vecData.size() + 7) / 8);
    std::vector<short> vecBuffer(vecData.size() / 2 + vecData.size() % 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertUint8ToShort(vecData, vecBuffer);
    if (nDevNo % 8 != 0) {
        nRet = -2;
        UpdateLastError(nRet);
        return nRet;
    }
    return WriteData(station, nDevType, nDevNo, nSize, vecBuffer.data());
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16);  // 计算需要写入的字数量(向上取整)
    // 准备临时缓冲区来存储转换后的 16 位数据
    std::vector<short> vecTempBuffer(nSize, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        // 将位数据按字打包到临时缓冲区
        for (int i = 0; i < vecData.size(); ++i) {
            if (vecData[i]) {
                // 使用 & 0xFFFF 保证不会超过 16 位,防止溢出
                vecTempBuffer[i / 16] |= static_cast<short>((1 << (i % 16)) & 0xFFFF);
            }
        }
    }
    return WriteData(station, nDevType, nDevNo, nSize, vecTempBuffer.data());
}
// 写字数据
// 写字数据
int CPerformanceMelsec::WriteWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const WordContainer& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    const int nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 计算需要写入的字节数(每个字占 2 字节)
    // 计算需要写入的字节数(每个字占 2 字节)
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>(vecData.size() * sizeof(uint16_t));
    const auto nSize = static_cast<short>(vecData.size());
    const auto pData = const_cast<short*>(reinterpret_cast<const short*>(vecData.data()));
    return WriteData(station, nDevType, nDevNo, nSize, pData);
}
// 写双字数据
// 写双字数据
int CPerformanceMelsec::WriteDWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const DWordContainer& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    const int nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 计算需要写入的字节数(每个双字占 4 字节)
    // 计算需要写入的字节数(每个双字占 4 字节)
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>(vecData.size() * sizeof(uint32_t));
    std::vector<short> vecBuffer(vecData.size() * 2, 0);
    const auto nSize = static_cast<short>(vecData.size() * sizeof(short));
    std::vector<short> vecBuffer(nSize, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertUint32ToShort(vecData, vecBuffer);
    }
    return WriteData(station, nDevType, nDevNo, nSize, vecBuffer.data());
}
// 扩展读数据
// 扩展读数据
long CPerformanceMelsec::ReadDataEx(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<char>& vecData) {
    // 验证站点参数和读取大小是否有效
    // 验证站点参数和读取大小是否有效
    long nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -640,46 +674,48 @@
        return ERROR_CODE_INVALID_PARAM;
    }
    vecData.resize(nSize);
    long nActualSize = (nSize + 1) / 2;
    std::vector<short> vecBuffer(nActualSize, 0);
    nSize = nSize % 2 != 0 ? nSize + 1 : nSize;
    std::vector<short> vecBuffer(nSize / 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nActualSize, vecBuffer.data());
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data());
    }
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
    } else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
    }
    else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        vecData.resize(nSize);
        ConvertShortToChar(vecBuffer, vecData);
    }
    return 0;
}
// 扩展写数据
// 扩展写数据
long CPerformanceMelsec::WriteDataEx(const StationIdentifier& station, long nDevType, long nDevNo, const std::vector<char>& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    long nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 将 vecData 转换为 short 类型的缓冲区
    // 将 vecData 转换为 short 类型的缓冲区
    long nSize = static_cast<long>(vecData.size());
    std::vector<short> vecBuffer((nSize + 1) / 2, 0);
    nSize = nSize % 2 != 0 ? nSize + 1 : nSize;
    std::vector<short> vecBuffer(nSize / 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertCharToShort(vecData, vecBuffer);
        nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data());
    }
    // 错误处理和日志记录
    // 错误处理和日志记录
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
@@ -688,7 +724,7 @@
    return nRet;
}
// 扩展软元件随机读取
// 扩展软元件随机读取
long CPerformanceMelsec::ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData) {
    if (vecSoftElements.empty()) {
        UpdateLastError(ERROR_INVALID_PARAMETER);
@@ -696,48 +732,48 @@
        return ERROR_INVALID_PARAMETER;
    }
    // 准备 dev 数据
    std::vector<short> devBuffer(vecSoftElements.size() * 3 + 1, 0); // 每个软元件需要 3 个 short,外加一个计数器
    devBuffer[0] = static_cast<short>(vecSoftElements.size());                 // 第一个元素是软元件数量
    // 准备 dev 数据
    std::vector<short> devBuffer(vecSoftElements.size() * 3 + 1, 0); // 每个软元件需要 3 个 short,外加一个计数器
    devBuffer[0] = static_cast<short>(vecSoftElements.size());                 // 第一个元素是软元件数量
    for (size_t i = 0; i < vecSoftElements.size(); ++i) {
        const SoftElement& element = vecSoftElements[i];
        devBuffer[i * 3 + 1] = element.nType;                        // 软元件类型
        devBuffer[i * 3 + 2] = static_cast<short>(element.nStartNo); // 起始软元件编号
        devBuffer[i * 3 + 3] = element.nElementCount;                // 点数
        devBuffer[i * 3 + 1] = element.nType;                        // 软元件类型
        devBuffer[i * 3 + 2] = static_cast<short>(element.nStartNo); // 起始软元件编号
        devBuffer[i * 3 + 3] = element.nElementCount;                // 点数
    }
    // 计算读取数据所需缓冲区大小
    // 计算读取数据所需缓冲区大小
    long nBufferSize = 0;
    for (const auto& element : vecSoftElements) {
        nBufferSize += element.nElementCount * 2; // 每个点占用 2 个字节
        nBufferSize += element.nElementCount * 2; // 每个点占用 2 个字节
    }
    // 锁保护及调用 mdRandREx
    // 锁保护及调用 mdRandREx
    long nRet = 0;
    std::vector<short> vecBuffer(nBufferSize / 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 确保线程安全
        std::lock_guard<std::mutex> lock(m_mtx); // 确保线程安全
        nRet = mdRandREx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), nBufferSize);
    }
    // 错误处理和日志记录
    // 错误处理和日志记录
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
        return nRet;
    }
    // 将读取到的 short 数据转换为 char 数据
    // 将读取到的 short 数据转换为 char 数据
    vecData.resize(nBufferSize);
    for (size_t i = 0; i < vecBuffer.size(); ++i) {
        vecData[i * 2] = static_cast<char>(vecBuffer[i] & 0xFF);            // 低字节
        vecData[i * 2 + 1] = static_cast<char>((vecBuffer[i] >> 8) & 0xFF); // 高字节
        vecData[i * 2] = static_cast<char>(vecBuffer[i] & 0xFF);            // 低字节
        vecData[i * 2 + 1] = static_cast<char>((vecBuffer[i] >> 8) & 0xFF); // 高字节
    }
    return nRet;
}
// 扩展软元件随机写入(支持多个软元件)
// 扩展软元件随机写入(支持多个软元件)
long CPerformanceMelsec::WriteRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, const std::vector<char>& vecData) {
    if (vecSoftElements.empty() || vecData.empty()) {
        UpdateLastError(ERROR_INVALID_PARAMETER);
@@ -745,26 +781,26 @@
        return ERROR_INVALID_PARAMETER;
    }
    // 准备 dev 数据
    std::vector<long> devBuffer(vecSoftElements.size() * 3 + 1, 0); // 每个软元件需要 3 个 long,外加一个计数器
    devBuffer[0] = static_cast<long>(vecSoftElements.size());                 // 第一个元素是软元件数量
    // 准备 dev 数据
    std::vector<long> devBuffer(vecSoftElements.size() * 3 + 1, 0); // 每个软元件需要 3 个 long,外加一个计数器
    devBuffer[0] = static_cast<long>(vecSoftElements.size());                 // 第一个元素是软元件数量
    for (size_t i = 0; i < vecSoftElements.size(); ++i) {
        const SoftElement& element = vecSoftElements[i];
        devBuffer[i * 3 + 1] = static_cast<long>(element.nType);    // 软元件类型
        devBuffer[i * 3 + 2] = element.nStartNo;                    // 起始软元件编号(已经是 long 类型,无需转换)
        devBuffer[i * 3 + 3] = static_cast<long>(element.nElementCount); // 点数
        devBuffer[i * 3 + 1] = static_cast<long>(element.nType);    // 软元件类型
        devBuffer[i * 3 + 2] = element.nStartNo;                    // 起始软元件编号(已经是 long 类型,无需转换)
        devBuffer[i * 3 + 3] = static_cast<long>(element.nElementCount); // 点数
    }
    // 锁保护及调用 mdRandWEx
    // 锁保护及调用 mdRandWEx
    long nRet = 0;
    std::vector<short> vecBuffer(vecData.size() / 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 确保线程安全
        std::lock_guard<std::mutex> lock(m_mtx); // 确保线程安全
        ConvertCharToShort(vecData, vecBuffer);
        nRet = mdRandWEx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), static_cast<long>(vecBuffer.size()));
    }
    // 错误处理和日志记录
    // 错误处理和日志记录
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
@@ -773,9 +809,9 @@
    return nRet;
}
// 远程设备站/远程站的缓冲存储器读取
// 远程设备站/远程站的缓冲存储器读取
long CPerformanceMelsec::ReadRemoteBuffer(const StationIdentifier& station, long nOffset, long nSize, std::vector<char>& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -790,36 +826,37 @@
    long nActualSize = (nSize + 1) / 2;
    std::vector<short> vecBuffer(nActualSize, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        nRet = mdRemBufReadEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nActualSize, vecBuffer.data());
    }
    if (nRet != 0) {
        UpdateLastError(nRet); // 更新错误码
        UpdateLastError(nRet); // 更新错误码
        LOG_ERROR(m_strLastError);
    } else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
    }
    else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertShortToChar(vecBuffer, vecData);
    }
    return nRet;
}
// 远程设备站/远程站的缓冲存储器写入
// 远程设备站/远程站的缓冲存储器写入
long CPerformanceMelsec::WriteRemoteBuffer(const StationIdentifier& station, long nOffset, const std::vector<char>& vecData) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    long nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 将 vecData 转换为 short 类型的缓冲区
    // 将 vecData 转换为 short 类型的缓冲区
    long nSize = static_cast<long>(vecData.size());
    std::vector<short> vecBuffer((nSize + 1) / 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertCharToShort(vecData, vecBuffer);
        nRet = mdRemBufWriteEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nSize, vecBuffer.data());
    }
@@ -832,7 +869,7 @@
    return nRet;
}
// 远程站的缓冲存储器读取 对象站IP地址指定
// 远程站的缓冲存储器读取 对象站IP地址指定
long CPerformanceMelsec::ReadRemoteBufferByIp(const std::string& strIP, long nOffset, long nSize, std::vector<char>& vecData) {
    uint32_t nAddress = 0;
    if (nSize < 0 || !ConvertIpStringToUint32(strIP, nAddress)) {
@@ -840,29 +877,30 @@
        return ERROR_CODE_INVALID_PARAM;
    }
    // 将缓冲区大小调整为 nSize
    // 将缓冲区大小调整为 nSize
    vecData.resize(nSize, 0);
    std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转换为 short 类型
    std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转换为 short 类型
    // 调用底层 SDK
    // 调用底层 SDK
    long nRet = 0;
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        nRet = mdRemBufReadIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data());
    }
    if (nRet != 0) {
        UpdateLastError(nRet);
        LOG_ERROR(m_strLastError);
    } else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
    }
    else {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertShortToChar(vecBuffer, vecData);
    }
    return nRet;
}
// 远程站的缓冲存储器写入 对象站IP地址指定
// 远程站的缓冲存储器写入 对象站IP地址指定
long CPerformanceMelsec::WriteRemoteBufferByIp(const std::string& strIP, long nOffset, const std::vector<char>& vecData) {
    uint32_t nAddress = 0;
    if (vecData.empty() || !ConvertIpStringToUint32(strIP, nAddress)) {
@@ -870,13 +908,13 @@
        return ERROR_CODE_INVALID_PARAM;
    }
    // 转换 vecData 为 short 类型的缓冲区
    // 转换 vecData 为 short 类型的缓冲区
    long nSize = static_cast<long>(vecData.size());
    std::vector<short> vecBuffer((nSize + 1) / 2, 0);
    long nRet = 0;
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全
        ConvertCharToShort(vecData, vecBuffer);
        nRet = mdRemBufWriteIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data());
    }
@@ -889,18 +927,18 @@
    return nRet;
}
// 设置(ON)对象站的指定位软元件
// 设置(ON)对象站的指定位软元件
int CPerformanceMelsec::SetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo) {
    // 验证站点参数
    // 验证站点参数
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全
        const short nDevType = CalculateDeviceType(station, enDevType);
        nRet = mdDevSet(m_nPath, CombineStation(station), nDevType, nDevNo);
    }
@@ -913,16 +951,16 @@
    return nRet;
}
// 复位(OFF)对象站的指定位软元件
// 复位(OFF)对象站的指定位软元件
int CPerformanceMelsec::ResetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short enDevNo) {
    // 验证站点参数
    // 验证站点参数
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        std::lock_guard<std::mutex> lock(m_mtx);
        const short nDevType = CalculateDeviceType(station, enDevType);
@@ -937,11 +975,11 @@
    return nRet;
}
// 扩展位软元件设置
// 扩展位软元件设置
long CPerformanceMelsec::SetBitDeviceEx(const StationIdentifier& station, long nDevType, long nDevNo) {
    std::lock_guard<std::mutex> lock(m_mtx);
    // 检查参数有效性
    // 检查参数有效性
    long nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -957,11 +995,11 @@
    return nRet;
}
// 扩展位软元件复位
// 扩展位软元件复位
long CPerformanceMelsec::ResetBitDeviceEx(const StationIdentifier& station, long nDevType, long nDevNo) {
    std::lock_guard<std::mutex> lock(m_mtx);
    // 检查参数有效性
    // 检查参数有效性
    long nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
@@ -977,23 +1015,23 @@
    return nRet;
}
// 执行对象站的CPU
// 执行对象站的CPU
int CPerformanceMelsec::ControlCPU(const StationIdentifier& station, ControlCode enControlCode) {
    // 验证站点参数和数据有效性
    // 验证站点参数和数据有效性
    int nRet = ValidateStation(station);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 验证控制码是否合法
    // 验证控制码是否合法
    const auto nControlCode = static_cast<short>(enControlCode);
    if (nControlCode < 0 || nControlCode > 2) {
        UpdateLastError(ERROR_CODE_INVALID_PARAM); // 参数错误
        UpdateLastError(ERROR_CODE_INVALID_PARAM); // 参数错误
        return ERROR_CODE_INVALID_PARAM;
    }
    // 确保线程安全的最小锁定范围
    // 确保线程安全的最小锁定范围
    {
        std::lock_guard<std::mutex> lock(m_mtx);
        nRet = mdControl(m_nPath, CombineStation(station), nControlCode);
@@ -1007,7 +1045,7 @@
    return nRet;
}
// 事件等待
// 事件等待
int CPerformanceMelsec::WaitForBoardEvent(std::vector<short> vecEventNumbers, const int nTimeoutMs, EventDetails& details) {
    std::lock_guard<std::mutex> lock(m_mtx);
@@ -1021,12 +1059,12 @@
        return ERROR_CODE_INVALID_PARAM;
    }
    // 第 0 个元素存储数量,最大支持 64 个事件
    std::array<short, 65> eventno = {0};
    // 第 0 个元素存储数量,最大支持 64 个事件
    std::array<short, 65> eventno = { 0 };
    eventno[0] = static_cast<short>(vecEventNumbers.size());
    std::copy(vecEventNumbers.begin(), vecEventNumbers.end(), eventno.begin() + 1);
    // 初始化输出参数
    // 初始化输出参数
    details.nEventNo = 0;
    details.details.fill(0);
@@ -1039,99 +1077,100 @@
    return nRet;
}
//============================================辅助函数=======================================================
// 更新最近的错误信息
//============================================辅助函数=======================================================
// 更新最近的错误信息
void CPerformanceMelsec::UpdateLastError(const int nCode) {
    if (nCode == 0) {
        return;
    }
    // 检查错误码是否存在于映射表中
    // 检查错误码是否存在于映射表中
    const auto it = m_mapError.find(nCode);
    if (it != m_mapError.end()) {
        // 如果找到,直接返回对应语言的错误信息
        // 如果找到,直接返回对应语言的错误信息
        m_strLastError = it->second;
    } else {
        // 如果未找到,处理特殊范围
    }
    else {
        // 如果未找到,处理特殊范围
        m_strLastError = "Unknown error.";
        if (nCode == -28611 || nCode == -28612) {
            // 系统出错
            // 系统出错
            m_strLastError = "System error.";
        }
        if (nCode >= -20480 && nCode <= -16384) {
            // CC-Link 系统检测出的错误
            // CC-Link 系统检测出的错误
            m_strLastError = "Error detected in the CC-Link system.";
        }
        if (nCode >= -12288 && nCode <= -8193) {
            // CC-Link IE TSN 系统检测出的错误
            // CC-Link IE TSN 系统检测出的错误
            m_strLastError = "Error detected in the CC-Link IE TSN system.";
        }
        if (nCode >= -8192 && nCode <= -4097) {
            // CC-Link IE 控制网络系统检测出的错误
            // CC-Link IE 控制网络系统检测出的错误
            m_strLastError = "Error detected in the CC-Link IE control network system.";
        }
        if (nCode >= -4096 && nCode <= -257) {
            // MELSECNET/10 或 MELSECNET/网络系统错误范围
            // MELSECNET/10 或 MELSECNET/网络系统错误范围
            m_strLastError = "Errors detected in MELSECNET/10 or MELSECNET/network system.";
        }
        if (nCode >= 4096 && nCode <= 16383) {
            // MELSEC 数据链接库范围
            // MELSEC 数据链接库范围
            m_strLastError = "Internal error detected by MELSEC Data Link Library.";
        }
        if (nCode == 18944 || nCode == 18945) {
            // 链接关联出错
            // 链接关联出错
            m_strLastError = "Link association error: Network does not exist, unsupported CPU, or incorrect network No./station number.";
        }
        if (nCode >= 16384 && nCode <= 20479) {
            // PLC CPU 检测范围
            // PLC CPU 检测范围
            m_strLastError = "Errors detected by the programmable controller CPU in the target station.";
        }
        if (nCode >= 28416 && nCode <= 28671) {
            // 冗余功能模块范围
            // 冗余功能模块范围
            m_strLastError = "Error detected in the redundancy module of the target station.";
        }
    }
}
// 检查连接状态和站点参数有效性
// 检查连接状态和站点参数有效性
int CPerformanceMelsec::ValidateStation(const StationIdentifier& station) const {
    // 检查是否已连接
    // 检查是否已连接
    if (!m_bConnected.load()) {
        return ERROR_CODE_NOT_CONNECTED;
    }
    // 检查网络号和站点号范围
    // 检查网络号和站点号范围
    if (station.nNetNo < 0 || station.nNetNo > 239 || station.nStNo < 0 || station.nStNo > 255) {
        return ERROR_CODE_INVALID_PARAM;
    }
    return 0; // 参数有效
    return 0; // 参数有效
}
// 验证站点参数和数据有效性
// 验证站点参数和数据有效性
int CPerformanceMelsec::ValidateStationAndSize(const StationIdentifier& station, const short nCount) const {
    // 验证站点参数
    // 验证站点参数
    const int nRet = ValidateStation(station);
    if (nRet != 0) {
        return nRet; // 如果站点验证失败,返回对应错误码
        return nRet; // 如果站点验证失败,返回对应错误码
    }
    if (nCount <= 0) {
        return ERROR_CODE_INVALID_PARAM;
    }
    return 0; // 验证通过
    return 0; // 验证通过
}
// IP字符串转uint32_t
// IP字符串转uint32_t
bool CPerformanceMelsec::ConvertIpStringToUint32(const std::string& strIP, uint32_t& nIP) {
    nIP = 0;
    std::stringstream ss(strIP);
@@ -1150,173 +1189,181 @@
    return true;
}
//============================================静态辅助函数====================================================
// 延时,并且转发窗口消息
//============================================静态辅助函数====================================================
// 延时,并且转发窗口消息
void CPerformanceMelsec::Delay(const unsigned int nDelayMs) {
    MSG message;
    // 如果延迟时间为 0,仅处理一次消息队列
    // 如果延迟时间为 0,仅处理一次消息队列
    if (nDelayMs == 0) {
        // 非阻塞的检查消息队列
        // 非阻塞的检查消息队列
        if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
            TranslateMessage(&message);  // 将消息转化为有效的窗口消息
            DispatchMessage(&message);   // 派发消息给相应的窗口过程
            TranslateMessage(&message);  // 将消息转化为有效的窗口消息
            DispatchMessage(&message);   // 派发消息给相应的窗口过程
        }
        return;
    }
    DWORD finish;
    const DWORD start = GetTickCount();  // 获取当前的时间戳(从系统启动以来的毫秒数)
    const DWORD start = GetTickCount();  // 获取当前的时间戳(从系统启动以来的毫秒数)
    do {
        if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
            TranslateMessage(&message);  // 转换消息
            DispatchMessage(&message);   // 处理消息
            TranslateMessage(&message);  // 转换消息
            DispatchMessage(&message);   // 处理消息
        }
        Sleep(1);   // 暂停 1 毫秒,防止过度占用 CPU
        finish = GetTickCount(); // 获取当前的时间戳
    } while ((finish - start) < nDelayMs);  // 循环直到经过的时间大于指定的延迟时间
        Sleep(1);   // 暂停 1 毫秒,防止过度占用 CPU
        finish = GetTickCount(); // 获取当前的时间戳
    } while ((finish - start) < nDelayMs);  // 循环直到经过的时间大于指定的延迟时间
}
BoardType CPerformanceMelsec::FindBoardTypeByChannel(const int nChannel) {
    if (nChannel >= MELSECNET_CHANNEL(1) && nChannel <= MELSECNET_CHANNEL(4)) {
        return BoardType::MELSECNET_H;
    } else if (nChannel >= CC_LINK_CHANNEL(1) && nChannel <= CC_LINK_CHANNEL(4)) {
    }
    else if (nChannel >= CC_LINK_CHANNEL(1) && nChannel <= CC_LINK_CHANNEL(4)) {
        return BoardType::CC_LINK_VER_2;
    } else if (nChannel >= CC_LINK_IE_CONTROL_CHANNEL(1) && nChannel <= CC_LINK_IE_CONTROL_CHANNEL(4)) {
    }
    else if (nChannel >= CC_LINK_IE_CONTROL_CHANNEL(1) && nChannel <= CC_LINK_IE_CONTROL_CHANNEL(4)) {
        return BoardType::CC_LINK_IE_CONTROL;
    } else if (nChannel >= CC_LINK_IE_FIELD_CHANNEL(1) && nChannel <= CC_LINK_IE_FIELD_CHANNEL(4)) {
    }
    else if (nChannel >= CC_LINK_IE_FIELD_CHANNEL(1) && nChannel <= CC_LINK_IE_FIELD_CHANNEL(4)) {
        return BoardType::CC_LINK_IE_FIELD;
    } else if (nChannel >= CC_LINK_IE_TSN_CHANNEL(1) && nChannel <= CC_LINK_IE_TSN_CHANNEL(4)) {
    }
    else if (nChannel >= CC_LINK_IE_TSN_CHANNEL(1) && nChannel <= CC_LINK_IE_TSN_CHANNEL(4)) {
        return BoardType::CC_LINK_IE_TSN;
    }
    return BoardType::UNKNOWN;
}
// 合并网络号和站点号
// 合并网络号和站点号
short CPerformanceMelsec::CombineStation(const StationIdentifier& station) {
    return static_cast<short>(station.nStNo | ((station.nNetNo << 8) & 0xFF00));
}
// 计算软元件类型
// 计算软元件类型
short CPerformanceMelsec::CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType) {
    int nDevType = static_cast<int>(enDevType);
    // 根据软元件类型的特定规则进行计算
    // 根据软元件类型的特定规则进行计算
    if (enDevType == DeviceType::LX || enDevType == DeviceType::LY ||
        enDevType == DeviceType::LB || enDevType == DeviceType::LW ||
        enDevType == DeviceType::LSB || enDevType == DeviceType::LSW) {
        // 网络号加偏移
        // 网络号加偏移
        nDevType += station.nNetNo;
    } else if (enDevType == DeviceType::ER) {
        // 文件寄存器的块号加偏移
    }
    else if (enDevType == DeviceType::ER) {
        // 文件寄存器的块号加偏移
        nDevType += 0;
    } else if (enDevType == DeviceType::SPG) {
        // 起始 I/O No. ÷ 16 的值
    }
    else if (enDevType == DeviceType::SPG) {
        // 起始 I/O No. ÷ 16 的值
        nDevType += 0 / 16;
    }
    return static_cast<short>(nDevType);
}
// std::vector<char>转换为std::vector<short>
// std::vector<char>转换为std::vector<short>
void CPerformanceMelsec::ConvertCharToShort(const std::vector<char>& vecChar, std::vector<short>& vecShort) {
    vecShort.resize((vecChar.size() + 1) / 2, 0); // 调整 short 容器大小
    vecShort.resize((vecChar.size() + 1) / 2, 0); // 调整 short 容器大小
    for (size_t i = 0; i < vecChar.size(); i++) {
        if (i % 2 == 0) {
            vecShort[i / 2] = static_cast<unsigned char>(vecChar[i]);       // 低字节
        } else {
            vecShort[i / 2] |= static_cast<unsigned char>(vecChar[i]) << 8; // 高字节
            vecShort[i / 2] = static_cast<unsigned char>(vecChar[i]);       // 低字节
        }
        else {
            vecShort[i / 2] |= static_cast<unsigned char>(vecChar[i]) << 8; // 高字节
        }
    }
}
// std::vector<short>转换为std::vector<char>
// std::vector<short>转换为std::vector<char>
void CPerformanceMelsec::ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>& vecChar) {
    vecChar.resize(vecShort.size() * 2); // 调整 char 容器大小
    vecChar.resize(vecShort.size() * 2); // 调整 char 容器大小
    for (size_t i = 0; i < vecShort.size(); i++) {
        vecChar[i * 2] = static_cast<char>(vecShort[i] & 0xFF);             // 低字节
        vecChar[i * 2 + 1] = static_cast<char>((vecShort[i] >> 8) & 0xFF);  // 高字节
        vecChar[i * 2] = static_cast<char>(vecShort[i] & 0xFF);             // 低字节
        vecChar[i * 2 + 1] = static_cast<char>((vecShort[i] >> 8) & 0xFF);  // 高字节
    }
}
// std::vector<uint8_t>转换为std::vector<short>
// std::vector<uint8_t>转换为std::vector<short>
void CPerformanceMelsec::ConvertUint8ToShort(const std::vector<uint8_t>& vecUint8, std::vector<short>& vecShort) {
    vecShort.resize((vecUint8.size() + 1) / 2, 0); // 调整 short 容器大小
    vecShort.resize((vecUint8.size() + 1) / 2, 0); // 调整 short 容器大小
    for (size_t i = 0; i < vecUint8.size(); i++) {
        if (i % 2 == 0) {
            vecShort[i / 2] = static_cast<short>(vecUint8[i]);          // 低字节
        } else {
            vecShort[i / 2] |= static_cast<short>(vecUint8[i] << 8);    // 高字节
            vecShort[i / 2] = static_cast<short>(vecUint8[i]);          // 低字节
        }
        else {
            vecShort[i / 2] |= static_cast<short>(vecUint8[i] << 8);    // 高字节
        }
    }
}
// std::vector<short>转换为std::vector<uint8_t>
// std::vector<short>转换为std::vector<uint8_t>
void CPerformanceMelsec::ConvertShortToUint8(const std::vector<short>& vecShort, std::vector<uint8_t>& vecUint8) {
    vecUint8.resize(vecShort.size() * 2); // 调整 uint8_t 容器大小
    vecUint8.resize(vecShort.size() * 2); // 调整 uint8_t 容器大小
    for (size_t i = 0; i < vecShort.size(); i++) {
        vecUint8[i * 2] = static_cast<uint8_t>(vecShort[i] & 0xFF);             // 低字节
        vecUint8[i * 2 + 1] = static_cast<uint8_t>((vecShort[i] >> 8) & 0xFF);  // 高字节
        vecUint8[i * 2] = static_cast<uint8_t>(vecShort[i] & 0xFF);             // 低字节
        vecUint8[i * 2 + 1] = static_cast<uint8_t>((vecShort[i] >> 8) & 0xFF);  // 高字节
    }
}
// std::vector<uint32_t>转换为std::vector<short>
// std::vector<uint32_t>转换为std::vector<short>
void CPerformanceMelsec::ConvertUint32ToShort(const std::vector<uint32_t>& vecUint32, std::vector<short>& vecShort) {
    vecShort.resize(vecUint32.size() * 2); // 每个 uint32_t 转换为两个 short
    vecShort.resize(vecUint32.size() * 2); // 每个 uint32_t 转换为两个 short
    for (size_t i = 0; i < vecUint32.size(); i++) {
        vecShort[i * 2] = static_cast<short>(vecUint32[i] & 0xFFFF);             // 低16位
        vecShort[i * 2 + 1] = static_cast<short>((vecUint32[i] >> 16) & 0xFFFF); // 高16位
        vecShort[i * 2] = static_cast<short>(vecUint32[i] & 0xFFFF);             // 低16位
        vecShort[i * 2 + 1] = static_cast<short>((vecUint32[i] >> 16) & 0xFFFF); // 高16位
    }
}
// std::vector<short>转换为std::vector<uint32_t>
// std::vector<short>转换为std::vector<uint32_t>
void CPerformanceMelsec::ConvertShortToUint32(const std::vector<short>& vecShort, std::vector<uint32_t>& vecUint32) {
    vecUint32.resize((vecShort.size() + 1) / 2, 0); // 每两个 short 合并为一个 uint32_t
    vecUint32.resize((vecShort.size() + 1) / 2, 0); // 每两个 short 合并为一个 uint32_t
    for (size_t i = 0; i < vecUint32.size(); i++) {
        vecUint32[i] = (static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2 + 1])) << 16) | // 高16位
                       static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2]));              // 低16位
        vecUint32[i] = (static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2 + 1])) << 16) | // 高16位
            static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2]));              // 低16位
    }
}
//============================================模板辅助函数====================================================
// 验证站点参数和数据有效性
//============================================模板辅助函数====================================================
// 验证站点参数和数据有效性
template <typename T>
int CPerformanceMelsec::ValidateStationAndData(const StationIdentifier& station, const std::vector<T>& vecData) {
    // 验证站点参数
    // 验证站点参数
    const int nRet = ValidateStation(station);
    if (nRet != 0) {
        return nRet; // 如果站点验证失败,返回对应错误码
        return nRet; // 如果站点验证失败,返回对应错误码
    }
    // 验证数据是否为空
    // 验证数据是否为空
    if (vecData.empty()) {
        return ERROR_CODE_INVALID_PARAM;
    }
    return 0; // 验证通过
    return 0; // 验证通过
}
// 由低转高容器的模板(整型)
// 由低转高容器的模板(整型)
template <typename T, typename U>
void CPerformanceMelsec::ConvertLowToHigh(const std::vector<T>& vecLow, std::vector<U>& vecHigh) {
    static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types");
    // 自动计算 nGroupSize
    // 自动计算 nGroupSize
    constexpr size_t nGroupSize = sizeof(U) / sizeof(T);
    // 如果 T 和 U 的大小相等,直接转换
    // 如果 T 和 U 的大小相等,直接转换
    if (sizeof(T) == sizeof(U)) {
        vecHigh.assign(vecLow.begin(), vecLow.end());
        return;
    }
    // 如果 U 的大小是 T 的倍数,正常组合
    // 如果 U 的大小是 T 的倍数,正常组合
    static_assert(sizeof(U) > sizeof(T), "Size of U must be greater than or equal to size of T");
    // 计算完整组的数量
    size_t nHighSize = (vecLow.size() + nGroupSize - 1) / nGroupSize; // 向上取整
    // 计算完整组的数量
    size_t nHighSize = (vecLow.size() + nGroupSize - 1) / nGroupSize; // 向上取整
    vecHigh.resize(nHighSize, 0);
    // 合并低位数据到高位数据
    // 合并低位数据到高位数据
    for (size_t i = 0; i < vecLow.size(); i++) {
        vecHigh[i / nGroupSize] |= (static_cast<U>(vecLow[i]) << ((i % nGroupSize) * CHAR_BIT * sizeof(T)));
    }
@@ -1324,27 +1371,27 @@
    return vecHigh;
}
// 由高转低容器的模板(整型)
// 由高转低容器的模板(整型)
template <typename T, typename U>
void CPerformanceMelsec::ConvertHighToLow(const std::vector<T>& vecHigh, std::vector<U>& vecLow) {
    static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types");
    // 自动计算 nGroupSize
    // 自动计算 nGroupSize
    constexpr size_t nGroupSize = sizeof(T) / sizeof(U);
    // 如果 T 和 U 的大小相等,直接转换
    // 如果 T 和 U 的大小相等,直接转换
    if (sizeof(T) == sizeof(U)) {
        vecLow.assign(vecHigh.begin(), vecHigh.end());
        return;
    }
    // 如果 T 的大小是 U 的倍数,正常分解
    // 如果 T 的大小是 U 的倍数,正常分解
    static_assert(sizeof(T) > sizeof(U), "Size of T must be greater than or equal to size of U");
    size_t nLowSize = vecHigh.size() * nGroupSize; // 低容器的大小
    size_t nLowSize = vecHigh.size() * nGroupSize; // 低容器的大小
    vecLow.resize(nLowSize, 0);
    // 分解高位数据到低位数据
    // 分解高位数据到低位数据
    for (size_t i = 0; i < vecHigh.size(); i++) {
        for (size_t j = 0; j < nGroupSize; j++) {
            vecLow[i * nGroupSize + j] = static_cast<U>((vecHigh[i] >> (j * CHAR_BIT * sizeof(U))) & ((1ULL << (CHAR_BIT * sizeof(U))) - 1));