From bea6407b376a4e426f0b120bae569fba6ab867db Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期六, 08 十一月 2025 17:55:47 +0800
Subject: [PATCH] 1.CMaster.cpp 第 1644/1667/1691 行在记录 SV 曲线时通过 getGlassFromSlot(0) 取玻璃,而各设备的 initSlots() 都是从 1 开始编号(例如 CBonder.cpp (line 408)、CVacuumBake.cpp (line 415) 等)。槽位 0 永远不存在,所以 pGlass 始终是 nullptr,pGlass->addSVData(...) 的分支从未执行。结果 SERVO::CGlass::m_svDatas 里没有任何曲线数据,GlassJson::ToPrettyString 生成的 pretty 字符串也就没有 sv_datas,导出 CSV 时自然读不到曲线。 同一段代码还有一个潜在 Bug:虽然判断了 channel - 1 < bonderTypes.size(),但真正索引却用的是 bonderTypes[channel]。索引偏移会导致数据类型错位,最后一个通道甚至可能越界。即使修正了槽位,这里也需要同步改成 bonderTypes[channel - 1](另外两处 vacuumbakeTypes、coolingTypes 也一样)。

---
 SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 171 insertions(+), 1 deletions(-)

diff --git a/SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp b/SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp
index 7bc469d..0f11149 100644
--- a/SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp
+++ b/SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp
@@ -9,7 +9,7 @@
 
 #ifdef _DEBUG
 #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
+static char* THIS_FILE = __FILE__;
 #define new DEBUG_NEW
 #endif
 
@@ -695,6 +695,100 @@
     return 0;
 }
 
+// 扩展读取位数据
+long CPerformanceMelsec::ReadBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nBitCount, BitContainer& vecData) {
+    long nRet = ValidateStationAndSize(station, nBitCount);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    if (nDevNo % 8 != 0) {
+        UpdateLastError(ERROR_CODE_INVALID_PARAM);
+        return ERROR_CODE_INVALID_PARAM;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    const long nWordCount = (nBitCount + 15) / 16;
+    const long nByteSize = nWordCount * sizeof(short);
+
+    std::vector<char> vecRaw;
+    nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw);
+    if (nRet != 0) {
+        return nRet;
+    }
+
+    vecData.clear();
+    for (long i = 0; i < nWordCount; ++i) {
+        short word = static_cast<unsigned char>(vecRaw[i * 2]) |
+            (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8);
+        for (int j = 0; j < 16; ++j) {
+            vecData.push_back((word & (1 << j)) != 0);
+            if (vecData.size() >= static_cast<size_t>(nBitCount)) {
+                return 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+// 扩展读取字数据
+long CPerformanceMelsec::ReadWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nWordCount, WordContainer& vecData) {
+    long nRet = ValidateStationAndSize(station, nWordCount);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    const long nByteSize = nWordCount * sizeof(short);
+
+    std::vector<char> vecRaw;
+    nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw);
+    if (nRet != 0) {
+        return nRet;
+    }
+
+    vecData.clear();
+    for (long i = 0; i < nWordCount; ++i) {
+        short value = static_cast<unsigned char>(vecRaw[i * 2]) |
+            (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8);
+        vecData.push_back(value);
+    }
+
+    return 0;
+}
+
+// 扩展读取双字数据
+long CPerformanceMelsec::ReadDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nDWordCount, DWordContainer& vecData) {
+    long nRet = ValidateStationAndSize(station, nDWordCount);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    const long nByteSize = nDWordCount * sizeof(uint32_t);
+
+    std::vector<char> vecRaw;
+    nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw);
+    if (nRet != 0) {
+        return nRet;
+    }
+
+    vecData.clear();
+    for (long i = 0; i < nDWordCount; ++i) {
+        uint32_t val = static_cast<unsigned char>(vecRaw[i * 4 + 0]) |
+            (static_cast<unsigned char>(vecRaw[i * 4 + 1]) << 8) |
+            (static_cast<unsigned char>(vecRaw[i * 4 + 2]) << 16) |
+            (static_cast<unsigned char>(vecRaw[i * 4 + 3]) << 24);
+        vecData.push_back(val);
+    }
+
+    return 0;
+}
+
 // 扩展写数据
 long CPerformanceMelsec::WriteDataEx(const StationIdentifier& station, long nDevType, long nDevNo, const std::vector<char>& vecData) {
     // 验证站点参数和数据有效性
@@ -724,6 +818,82 @@
     return nRet;
 }
 
+// 扩展写位数据
+long CPerformanceMelsec::WriteBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const BitContainer& vecData) {
+    long nRet = ValidateStationAndData(station, vecData);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    if (nDevNo % 8 != 0) {
+        UpdateLastError(ERROR_CODE_INVALID_PARAM);
+        return ERROR_CODE_INVALID_PARAM;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    const size_t nWordCount = (vecData.size() + 15) / 16;
+
+    std::vector<short> vecWordBuffer(nWordCount, 0);
+    for (size_t i = 0; i < vecData.size(); ++i) {
+        if (vecData[i]) {
+            vecWordBuffer[i / 16] |= (1 << (i % 16));
+        }
+    }
+
+    // 转换 short -> char
+    std::vector<char> vecByteBuffer;
+    vecByteBuffer.resize(nWordCount * sizeof(short));
+    for (size_t i = 0; i < nWordCount; ++i) {
+        vecByteBuffer[i * 2] = static_cast<char>(vecWordBuffer[i] & 0xFF);
+        vecByteBuffer[i * 2 + 1] = static_cast<char>((vecWordBuffer[i] >> 8) & 0xFF);
+    }
+
+    return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer);
+}
+
+// 扩展写字数据
+long CPerformanceMelsec::WriteWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const WordContainer& vecData) {
+    long nRet = ValidateStationAndData(station, vecData);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    std::vector<char> vecByteBuffer;
+    vecByteBuffer.resize(vecData.size() * sizeof(short));
+
+    for (size_t i = 0; i < vecData.size(); ++i) {
+        vecByteBuffer[i * 2] = static_cast<char>(vecData[i] & 0xFF);
+        vecByteBuffer[i * 2 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF);
+    }
+
+    return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer);
+}
+
+// 扩展写双字数据
+long CPerformanceMelsec::WriteDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const DWordContainer& vecData) {
+    long nRet = ValidateStationAndData(station, vecData);
+    if (nRet != 0) {
+        UpdateLastError(nRet);
+        return nRet;
+    }
+
+    const short nDevType = CalculateDeviceType(station, enDevType);
+    std::vector<char> vecByteBuffer;
+    vecByteBuffer.resize(vecData.size() * sizeof(uint32_t));
+
+    for (size_t i = 0; i < vecData.size(); ++i) {
+        vecByteBuffer[i * 4] = static_cast<char>(vecData[i] & 0xFF);
+        vecByteBuffer[i * 4 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF);
+        vecByteBuffer[i * 4 + 2] = static_cast<char>((vecData[i] >> 16) & 0xFF);
+        vecByteBuffer[i * 4 + 3] = static_cast<char>((vecData[i] >> 24) & 0xFF);
+    }
+
+    return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer);
+}
+
 // 扩展软元件随机读取
 long CPerformanceMelsec::ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData) {
     if (vecSoftElements.empty()) {

--
Gitblit v1.9.3