From 44360bc2cdeee16be72f9cc4bfb42e0ac26b5b44 Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期一, 19 一月 2026 14:47:19 +0800
Subject: [PATCH] 1.修改优化
---
SourceCode/Bond/Servo/HsmsPassive.cpp | 2792 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 2,653 insertions(+), 139 deletions(-)
diff --git a/SourceCode/Bond/Servo/HsmsPassive.cpp b/SourceCode/Bond/Servo/HsmsPassive.cpp
index 77e607c..c2359b3 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.cpp
+++ b/SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -3,17 +3,78 @@
#include "Log.h"
#include "Model.h"
#include "Common.h"
+#include "RecipeManager.h"
#include <time.h>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string.h>
+#include <algorithm>
+#include <set>
#include <regex>
+#include <sstream>
+
+// ---- Encoding helpers ----
+static bool hasUtf8Bom(const std::string& s)
+{
+ return s.size() >= 3 &&
+ static_cast<unsigned char>(s[0]) == 0xEF &&
+ static_cast<unsigned char>(s[1]) == 0xBB &&
+ static_cast<unsigned char>(s[2]) == 0xBF;
+}
+
+static bool isLikelyUtf8(const std::string& s)
+{
+ // Simple heuristic: try to convert; if success without errors, treat as UTF-8.
+ int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), (int)s.size(), nullptr, 0);
+ return wlen > 0;
+}
+
+static CStringW Utf8ToWide(const char* psz)
+{
+ if (psz == nullptr) return L"";
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, psz, -1, nullptr, 0);
+ if (wlen <= 0) return L"";
+ CStringW ws;
+ LPWSTR buf = ws.GetBufferSetLength(wlen - 1);
+ MultiByteToWideChar(CP_UTF8, 0, psz, -1, buf, wlen);
+ ws.ReleaseBuffer();
+ return ws;
+}
+
+static CStringW AnsiToWide(const char* psz)
+{
+ if (psz == nullptr) return L"";
+ int wlen = MultiByteToWideChar(CP_ACP, 0, psz, -1, nullptr, 0);
+ if (wlen <= 0) return L"";
+ CStringW ws;
+ LPWSTR buf = ws.GetBufferSetLength(wlen - 1);
+ MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, wlen);
+ ws.ReleaseBuffer();
+ return ws;
+}
+// ---- End helpers ----
+
+// ControlState values (keep in sync with Model::ControlState / VariableList.txt)
+static constexpr uint8_t kControlStateOnlineRemote = 5;
const char ACK[2] = {0, 1};
const char* ACK0 = &ACK[0];
const char* ACK1 = &ACK[1];
+
+// Log SECS-II message briefly to avoid huge strings causing issues.
+static void LogSecsMessageBrief(const char* tag, IMessage* pMessage, size_t maxLen = 1024)
+{
+ if (pMessage == nullptr) return;
+ const char* msgStr = pMessage->toString();
+ if (msgStr == nullptr) return;
+ std::string buf(msgStr);
+ if (buf.size() > maxLen) {
+ buf = buf.substr(0, maxLen) + "...<truncated>";
+ }
+ LOGI("%s%s", tag, buf.c_str());
+}
unsigned __stdcall CimWorkThreadFunction(LPVOID lpParam)
{
@@ -46,8 +107,7 @@
m_listener.onEQOffLine = nullptr;
m_listener.onEQOnLine = nullptr;
m_listener.onCommand = nullptr;
- m_listener.onEQConstantRequest = nullptr;
- m_listener.onEQConstantSend = nullptr;
+ m_pActiveAction = nullptr;
InitializeCriticalSection(&m_criticalSection);
}
@@ -62,6 +122,10 @@
delete item;
}
m_listActionSent.clear();
+ for (auto item : m_listActionSpooling) {
+ delete item;
+ }
+ m_listActionSpooling.clear();
Unlock();
if (m_hCimWorkEvent != NULL) {
@@ -98,6 +162,55 @@
}
+void CHsmsPassive::addVariableValueToItem(ISECS2Item* pParent, SERVO::CVariable* pVariable)
+{
+ ASSERT(pParent);
+ ASSERT(pVariable);
+
+ std::string svNote("SV");
+ {
+ SERVO::CVariable* pDef = getVariable((int)pVariable->getVarialbleId());
+ if (pDef == nullptr) {
+ pDef = pVariable;
+ }
+ auto& name = pDef->getName();
+ if (!name.empty()) {
+ svNote += " -> ";
+ svNote += name;
+ }
+ }
+
+ ISECS2Item* pItemList;
+ SERVO::SVFromat format = pVariable->getFormat();
+ switch (format)
+ {
+ case SERVO::SVFromat::U1:
+ pParent->addU1Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
+ break;
+ case SERVO::SVFromat::U2:
+ pParent->addU2Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
+ break;
+ case SERVO::SVFromat::I2:
+ pParent->addI2Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
+ break;
+ case SERVO::SVFromat::A20:
+ case SERVO::SVFromat::A50:
+ pParent->addItem(pVariable->getValue().c_str(), svNote.c_str());
+ break;
+ case SERVO::SVFromat::L:
+ pItemList = pParent->addItem();
+ {
+ auto vars = pVariable->getVarsValue();
+ for (auto v : vars) {
+ addVariableValueToItem(pItemList, &v);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
void CHsmsPassive::linkEventReport(unsigned int CEID, unsigned int RPTID)
{
SERVO::CCollectionEvent* pEvent = getEvent(CEID);
@@ -109,23 +222,50 @@
void CHsmsPassive::unlinkEventReport(unsigned int CEID)
{
+ LOGI("<CHsmsPassive>unlinkEventReport enter");
SERVO::CCollectionEvent* pEvent = getEvent(CEID);
if (pEvent != nullptr) {
pEvent->setReport(nullptr);
+ LOGI("<CHsmsPassive>unlink Event Report.CEID=%d", CEID);
}
+}
+
+bool CHsmsPassive::shouldSpool(uint8_t streamId, uint8_t functionId) const
+{
+ // Comment: stream 1 is not spooled
+ if (streamId == 1) return false;
+
+ // Comment: m=0 turns off all streams and fns
+ if (!m_spoolingEnabled) return false;
+
+ // Blacklist semantics: in map => do NOT spool/cache.
+ // Not in map => allow spooling by default.
+ auto it = m_spoolBlacklistByStream.find(streamId);
+ if (it == m_spoolBlacklistByStream.end()) return true;
+
+ // Empty set => all functions in this stream
+ if (it->second.empty()) return true;
+
+ return it->second.find(functionId) == it->second.end();
}
SERVO::CReport* CHsmsPassive::defineReport(unsigned int RPTID, std::vector<unsigned int>& vids)
{
+ LOGI("<CHsmsPassive>defineReport enter");
// 娣诲姞瀹氫箟report
SERVO::CReport* pReport = new SERVO::CReport(RPTID, vids);
for (auto vid : vids) {
SERVO::CVariable* pVariable = getVariable(vid);
+ if (pVariable == nullptr) {
+ pVariable = getDataVariable(vid);
+ }
if (pVariable != nullptr) {
pReport->addVariable(pVariable);
+ LOGI("<CHsmsPassive>defineReport RPTID=%d", RPTID);
}
}
m_reports.push_back(pReport);
+ writeReportsToFile(m_strReportFilepath);
return pReport;
}
@@ -149,13 +289,26 @@
int CHsmsPassive::onRecvMsg(IMessage* pMessage)
{
- LOGI("onRecvMsg:%s", pMessage->toString());
+ // LOGI("onRecvMsg:%s", pMessage->toString());
+ Lock();
+ if (m_pActiveAction != nullptr &&
+ (m_pActiveAction->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes)) {
+ SetEvent(m_pActiveAction->getEvent());
+ LOGI("CHsmsPassive::褰撳墠绛夊緟鏈夊洖澶�");
+ TRACE("CHsmsPassive::褰撳墠绛夊緟鏈夊洖澶峔n");
+ Unlock();
+ return 0;
+ }
+ Unlock();
+
+
Lock();
CHsmsAction* pAction = nullptr;
for (auto iter = m_listActionSent.begin(); iter != m_listActionSent.end(); iter++) {
if ((*iter)->getSendMessage()->getHeader()->systemBytes == pMessage->getHeader()->systemBytes) {
LOGI("CHsmsPassive::鎵惧埌");
pAction = (*iter);
+ SetEvent(pAction->getEvent());
m_listActionSent.erase(iter);
break;
}
@@ -173,40 +326,133 @@
int CHsmsPassive::loadVarialbles(const char* pszFilepath)
{
- CStdioFile file;
- if (!file.Open(pszFilepath, CFile::modeRead)) {
+ m_strVariableFilepath = pszFilepath;
+ m_bVariableUtf8 = false;
+ m_bVariableUtf8Bom = false;
+ // 鍏堣鍘熷瀛楄妭锛屽悗缁啀鎸� UTF-8/BOM 鎴栨湰鍦扮紪鐮佽浆鎹�
+ CFile file;
+ if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
return -1;
}
- std::regex pattern("^\\d+,.*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+ const ULONGLONG nLen = file.GetLength();
+ if (nLen == 0) {
+ return -1;
+ }
+
+ std::string buffer;
+ buffer.resize(static_cast<size_t>(nLen));
+ file.Read(buffer.data(), static_cast<UINT>(nLen));
+ file.Close();
+
+ const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer.data());
+ size_t offset = 0;
+ CStringW content;
+
+ // UTF-8 BOM
+ if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
+ offset = 3;
+ m_bVariableUtf8 = true;
+ m_bVariableUtf8Bom = true;
+ }
+
+ // UTF-16 LE BOM
+ if (nLen >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
+ const wchar_t* wdata = reinterpret_cast<const wchar_t*>(buffer.data() + 2);
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ content.SetString(wdata, static_cast<int>(wlen));
+ }
+ // UTF-16 BE BOM
+ else if (nLen >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ std::wstring temp;
+ temp.reserve(wlen);
+ for (size_t i = 0; i < wlen; ++i) {
+ wchar_t ch = static_cast<wchar_t>(bytes[2 + i * 2] << 8 | bytes[2 + i * 2 + 1]);
+ temp.push_back(ch);
+ }
+ content = temp.c_str();
+ }
+ // 灏濊瘯 UTF-8锛堝惈鏃� BOM锛�
+ else {
+ auto tryUtf8 = [&](size_t off) -> bool {
+ int need = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), nullptr, 0);
+ if (need <= 0) return false;
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), temp.data(), need);
+ content = temp.c_str();
+ m_bVariableUtf8 = true;
+ return true;
+ };
+
+ if (!tryUtf8(offset)) {
+ // 鍥為��鍒版湰鍦颁唬鐮侀〉
+ int need = MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), nullptr, 0);
+ if (need > 0) {
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), temp.data(), need);
+ content = temp.c_str();
+ }
+ }
+ }
+
+ if (content.IsEmpty()) {
+ return -1;
+ }
+
+ std::wregex pattern(L"^\\d+,.+"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
std::vector<SERVO::CVariable*> variables;
int index, last;
- CString strLine;
- CString strId, strName, strFormat, strRemark;
- while (file.ReadString(strLine)) {
- if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+ CStringW strLine;
+ CStringW strId, strName, strFormat, strRemark;
+ std::wstringstream ss(content.GetString());
+ auto narrowFromW = [](const CStringW& s) -> std::string {
+ int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return {};
+ std::string out(static_cast<size_t>(need - 1), '\0');
+ WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
+ return out;
+ };
+ std::wstring line;
+ while (std::getline(ss, line, L'\n')) {
+ strLine = line.c_str();
+ strLine.Trim();
+ if (strLine.IsEmpty()) continue;
+ if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
continue;
}
last = 0;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strId = strLine.Left(index);
last = index + 1;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strName = strLine.Mid(last, index - last);
last = index + 1;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strFormat = strLine.Mid(last, index - last);
strRemark = strLine.Right(strLine.GetLength() - index - 1);
- strRemark.Replace(_T("\\r\\n"), _T("\r\n"));
+ strRemark.Replace(L"\\r\\n", L"\r\n");
+
+ std::string sId = narrowFromW(strId);
+ std::string sName = narrowFromW(strName);
+ std::string sFormat = narrowFromW(strFormat);
+ std::string sRemark = narrowFromW(strRemark);
SERVO::CVariable* pVarialble = new SERVO::CVariable(
- (LPTSTR)(LPCTSTR)strId, (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strFormat, (LPTSTR)(LPCTSTR)strRemark);
+ sId.c_str(),
+ sName.c_str(),
+ sFormat.c_str(),
+ sRemark.c_str());
variables.push_back(pVarialble);
}
@@ -217,14 +463,230 @@
}
}
+ return 0;
+}
+int CHsmsPassive::loadDataVarialbles(const char* pszFilepath)
+{
+ if (pszFilepath == NULL) {
+ return -1;
+ }
+ m_strDataVariableFilepath = pszFilepath;
+ m_bDataVariableUtf8 = false;
+ m_bDataVariableUtf8Bom = false;
+ CFile file;
+ if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
+ return -1;
+ }
+ const ULONGLONG nLen = file.GetLength();
+ if (nLen == 0) {
+ return -1;
+ }
+ std::string buffer;
+ buffer.resize(static_cast<size_t>(nLen));
+ file.Read(buffer.data(), static_cast<UINT>(nLen));
file.Close();
+
+ if (hasUtf8Bom(buffer)) {
+ m_bDataVariableUtf8 = true;
+ m_bDataVariableUtf8Bom = true;
+ buffer = buffer.substr(3);
+ }
+ else if (isLikelyUtf8(buffer)) {
+ m_bDataVariableUtf8 = true;
+ }
+ CStringW content = m_bDataVariableUtf8 ? Utf8ToWide(buffer.c_str()) : AnsiToWide(buffer.c_str());
+
+ // Regex: DVID,DV Name,DV Format,DV Remark
+ std::wregex pattern(L"^\\d+,[^,]*,[^,]*,.*");
+ std::vector<SERVO::CDataVariable*> dataVars;
+ int index;
+ CStringW strLine, strId, strName, strFormat, strRemark;
+ std::wstringstream ss(content.GetString());
+ auto narrowFromW = [](const CStringW& s) -> std::string {
+ int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return {};
+ std::string out(static_cast<size_t>(need - 1), '\0');
+ WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
+ return out;
+ };
+ std::wstring line;
+ while (std::getline(ss, line, L'\n')) {
+ strLine = line.c_str();
+ strLine.Trim();
+ if (strLine.IsEmpty()) continue;
+ if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
+ continue;
+ }
+ index = strLine.Find(L",", 0);
+ if (index < 0) continue;
+ strId = strLine.Left(index);
+
+ strLine = strLine.Right(strLine.GetLength() - index - 1);
+ index = strLine.Find(L",", 0);
+ if (index < 0) continue;
+ strName = strLine.Left(index);
+
+ strLine = strLine.Right(strLine.GetLength() - index - 1);
+ index = strLine.Find(L",", 0);
+ if (index < 0) continue;
+ strFormat = strLine.Left(index);
+
+ strRemark = strLine.Right(strLine.GetLength() - index - 1);
+ strRemark.Replace(L"\\r\\n", L"\r\n");
+
+ std::string sId = narrowFromW(strId);
+ std::string sName = narrowFromW(strName);
+ std::string sFormat = narrowFromW(strFormat);
+ std::string sRemark = narrowFromW(strRemark);
+
+ SERVO::CDataVariable* pVarialble = new SERVO::CDataVariable(
+ sId.c_str(),
+ sName.c_str(),
+ sFormat.c_str(),
+ sRemark.c_str());
+ dataVars.push_back(pVarialble);
+ }
+
+ if (!dataVars.empty()) {
+ clearAllDataVariabel();
+ for (auto item : dataVars) {
+ m_dataVariabels.push_back(item);
+ }
+ }
+
+ return 0;
+}
+
+int CHsmsPassive::loadEquipmentConstants(const char* pszFilepath)
+{
+ if (pszFilepath == NULL) return -1;
+ m_strEquipmentConstantFilepath = pszFilepath;
+ m_bEquipmentConstantUtf8 = false;
+ m_bEquipmentConstantUtf8Bom = false;
+
+ CFile file;
+ if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
+ return -1;
+ }
+ const ULONGLONG nLen = file.GetLength();
+ if (nLen == 0) {
+ return -1;
+ }
+ std::string buffer;
+ buffer.resize(static_cast<size_t>(nLen));
+ file.Read(buffer.data(), static_cast<UINT>(nLen));
+ file.Close();
+
+ if (hasUtf8Bom(buffer)) {
+ m_bEquipmentConstantUtf8 = true;
+ m_bEquipmentConstantUtf8Bom = true;
+ buffer = buffer.substr(3);
+ }
+ else if (isLikelyUtf8(buffer)) {
+ m_bEquipmentConstantUtf8 = true;
+ }
+ CStringW content = m_bEquipmentConstantUtf8 ? Utf8ToWide(buffer.c_str()) : AnsiToWide(buffer.c_str());
+ if (content.IsEmpty()) return -1;
+
+ std::wregex pattern(L"^\\d+,[^,]*,[^,]*,([^,]*),.*");
+ std::vector<EquipmentConstantEntry> constants;
+ CStringW strLine, strId, strName, strFormat, strRemark, strDefault;
+ std::wstringstream ss(content.GetString());
+ auto narrowFromW = [](const CStringW& s) -> std::string {
+ int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return {};
+ std::string out(static_cast<size_t>(need - 1), '\0');
+ WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
+ return out;
+ };
+ std::wstring line;
+ while (std::getline(ss, line, L'\n')) {
+ strLine = line.c_str();
+ strLine.Trim();
+ if (strLine.IsEmpty()) continue;
+ if (strLine.Find(L"ECID") == 0) continue; // skip header
+ if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
+ continue;
+ }
+ int last = 0;
+ int idx = strLine.Find(L",", last);
+ if (idx < 0) continue;
+ strId = strLine.Left(idx);
+ last = idx + 1;
+
+ idx = strLine.Find(L",", last);
+ if (idx < 0) continue;
+ strName = strLine.Mid(last, idx - last);
+ last = idx + 1;
+
+ idx = strLine.Find(L",", last);
+ if (idx < 0) continue;
+ strFormat = strLine.Mid(last, idx - last);
+ last = idx + 1;
+
+ idx = strLine.Find(L",", last);
+ if (idx < 0) continue;
+ strRemark = strLine.Mid(last, idx - last);
+ last = idx + 1;
+
+ strDefault = strLine.Right(strLine.GetLength() - last);
+
+ EquipmentConstantEntry entry;
+ entry.id = _wtoi(strId);
+ entry.name = narrowFromW(strName);
+ entry.format = narrowFromW(strFormat);
+ entry.remark = narrowFromW(strRemark);
+ entry.value = narrowFromW(strDefault);
+ constants.push_back(entry);
+ }
+
+ if (!constants.empty()) {
+ m_equipmentConstants = std::move(constants);
+ }
return 0;
}
std::vector<SERVO::CVariable*>& CHsmsPassive::getVariables()
{
return m_variabels;
+}
+
+std::vector<SERVO::CDataVariable*>& CHsmsPassive::getDataVariables()
+{
+ return m_dataVariabels;
+}
+
+unsigned int CHsmsPassive::getMaxVariableId() const
+{
+ unsigned int maxId = 0;
+ for (auto item : m_variabels) {
+ if (item && item->getVarialbleId() > maxId) {
+ maxId = item->getVarialbleId();
+ }
+ }
+ for (auto item : m_dataVariabels) {
+ if (item && item->getVarialbleId() > maxId) {
+ maxId = item->getVarialbleId();
+ }
+ }
+ return maxId;
+}
+
+unsigned int CHsmsPassive::getMaxDataVariableId() const
+{
+ unsigned int maxId = 0;
+ for (auto item : m_variabels) {
+ if (item && item->getVarialbleId() > maxId) {
+ maxId = item->getVarialbleId();
+ }
+ }
+ for (auto item : m_dataVariabels) {
+ if (item && item->getVarialbleId() > maxId) {
+ maxId = item->getVarialbleId();
+ }
+ }
+ return maxId;
}
SERVO::CVariable* CHsmsPassive::getVariable(int variableId)
@@ -238,6 +700,55 @@
return nullptr;
}
+SERVO::CVariable* CHsmsPassive::getVariable(const char* pszName)
+{
+ for (auto item : m_variabels) {
+ if (item->getName().compare(pszName) == 0) {
+ return item;
+ }
+ }
+ // try numeric id string
+ if (pszName != nullptr && *pszName) {
+ const int id = atoi(pszName);
+ if (id > 0) {
+ return getVariable(id);
+ }
+ }
+
+ return nullptr;
+}
+
+SERVO::CDataVariable* CHsmsPassive::getDataVariable(int dvid)
+{
+ for (auto item : m_dataVariabels) {
+ if (item->getVarialbleId() == (unsigned int)dvid) return item;
+ }
+ return nullptr;
+}
+
+SERVO::CDataVariable* CHsmsPassive::getDataVariable(const char* pszName)
+{
+ for (auto item : m_dataVariabels) {
+ if (item->getName().compare(pszName) == 0) return item;
+ }
+ return nullptr;
+}
+
+int CHsmsPassive::getCurrentControlState()
+{
+ auto v = getVariable("CurrentControlState");
+ if (v != nullptr) {
+ return static_cast<int>(v->getIntValue());
+ }
+ return 0;
+}
+
+bool CHsmsPassive::isHostCommandAllowed()
+{
+ // Only allow host control commands in OnlineRemote.
+ return getCurrentControlState() == kControlStateOnlineRemote;
+}
+
void CHsmsPassive::clearAllVariabel()
{
for (auto item : m_variabels) {
@@ -246,34 +757,447 @@
m_variabels.clear();
}
+void CHsmsPassive::clearAllDataVariabel()
+{
+ for (auto item : m_dataVariabels) {
+ delete item;
+ }
+ m_dataVariabels.clear();
+}
+
+CStringA WideToUtf8(const CStringW& ws)
+{
+ int need = WideCharToMultiByte(CP_UTF8, 0, ws, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return "";
+ CStringA out;
+ LPSTR buf = out.GetBufferSetLength(need - 1);
+ WideCharToMultiByte(CP_UTF8, 0, ws, -1, buf, need, nullptr, nullptr);
+ out.ReleaseBuffer();
+ return out;
+}
+
+CStringA WideToAnsi(const CStringW& ws)
+{
+ int need = WideCharToMultiByte(CP_ACP, 0, ws, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return "";
+ CStringA out;
+ LPSTR buf = out.GetBufferSetLength(need - 1);
+ WideCharToMultiByte(CP_ACP, 0, ws, -1, buf, need, nullptr, nullptr);
+ out.ReleaseBuffer();
+ return out;
+}
+
+static CStringA AnsiToUtf8(const std::string& s)
+{
+ int wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, nullptr, 0);
+ if (wlen <= 0) return "";
+ CStringW ws;
+ LPWSTR wbuf = ws.GetBufferSetLength(wlen - 1);
+ MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wbuf, wlen);
+ ws.ReleaseBuffer();
+ return WideToUtf8(ws);
+}
+
+int CHsmsPassive::deleteVariable(int variableId)
+{
+ Lock();
+ auto it = std::find_if(m_variabels.begin(), m_variabels.end(), [=](SERVO::CVariable* v) {
+ return v != nullptr && v->getVarialbleId() == variableId;
+ });
+ if (it == m_variabels.end()) {
+ Unlock();
+ return -1;
+ }
+ delete *it;
+ m_variabels.erase(it);
+ auto filepath = m_strVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -2;
+
+ return writeVariablesToFile(filepath);
+}
+
+void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
+{
+ // Protect variable list updates; multiple threads may set SVs.
+ Lock();
+ if (auto v = getVariable(pszName)) {
+ v->setValue(value);
+ }
+ else if (auto dv = getDataVariable(pszName)) {
+ dv->setValue(value);
+ }
+ Unlock();
+}
+
+void CHsmsPassive::setVariableValue(const char* pszName, const char* value)
+{
+ Lock();
+ if (auto v = getVariable(pszName)) {
+ v->setValue(value);
+ }
+ else if (auto dv = getDataVariable(pszName)) {
+ dv->setValue(value);
+ }
+ Unlock();
+}
+
+void CHsmsPassive::setVariableValue(const char* pszName, std::vector<SERVO::CVariable>& vars)
+{
+ Lock();
+ if (auto v = getVariable(pszName)) {
+ v->setValue(vars);
+ }
+ else if (auto dv = getDataVariable(pszName)) {
+ dv->setValue(vars);
+ }
+ Unlock();
+}
+
+void CHsmsPassive::withVariableLock(const std::function<void()>& fn)
+{
+ Lock();
+ if (fn) fn();
+ Unlock();
+}
+
+static bool isValidFormat(const std::string& fmt)
+{
+ static const std::set<std::string> allow = { "U1","U2","I2","A20","A50","L" };
+ return allow.count(fmt) > 0;
+}
+
+int CHsmsPassive::addVariable(const char* pszName, const char* pszFormat, const char* pszRemark, int& outId)
+{
+ if (pszName == nullptr || pszFormat == nullptr) return -1;
+ std::string fmt = pszFormat;
+ std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
+ if (!isValidFormat(fmt)) return -2;
+
+ Lock();
+ int maxId = 0;
+ for (auto v : m_variabels) {
+ if (v != nullptr && static_cast<int>(v->getVarialbleId()) > maxId) {
+ maxId = static_cast<int>(v->getVarialbleId());
+ }
+ }
+ outId = maxId + 1;
+
+ SERVO::CVariable* pNew = new SERVO::CVariable(std::to_string(outId).c_str(), pszName, fmt.c_str(), pszRemark ? pszRemark : "");
+ m_variabels.push_back(pNew);
+ auto filepath = m_strVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -3;
+ return writeVariablesToFile(filepath);
+}
+
+int CHsmsPassive::updateVariable(int variableId, const char* pszName, const char* pszFormat, const char* pszRemark)
+{
+ if (pszName == nullptr || pszFormat == nullptr) return -1;
+ std::string fmt = pszFormat;
+ std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
+ if (!isValidFormat(fmt)) return -2;
+
+ Lock();
+ auto it = std::find_if(m_variabels.begin(), m_variabels.end(), [=](SERVO::CVariable* v) {
+ return v != nullptr && v->getVarialbleId() == variableId;
+ });
+ if (it == m_variabels.end()) {
+ Unlock();
+ return -4;
+ }
+ (*it)->setName(pszName);
+ (*it)->setFormat(fmt.c_str());
+ (*it)->setRemark(pszRemark ? pszRemark : "");
+ auto filepath = m_strVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -3;
+ return writeVariablesToFile(filepath);
+}
+
+int CHsmsPassive::deleteDataVariable(int dvid)
+{
+ Lock();
+ auto it = std::find_if(m_dataVariabels.begin(), m_dataVariabels.end(), [=](SERVO::CDataVariable* v) {
+ return v != nullptr && v->getVarialbleId() == (unsigned int)dvid;
+ });
+ if (it == m_dataVariabels.end()) {
+ Unlock();
+ return -1;
+ }
+ delete *it;
+ m_dataVariabels.erase(it);
+ auto filepath = m_strDataVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -2;
+ return writeDataVariablesToFile(filepath);
+}
+
+int CHsmsPassive::addDataVariable(const char* pszName, const char* pszFormat, const char* pszRemark, int& outId)
+{
+ if (pszName == nullptr || pszFormat == nullptr) return -1;
+ std::string fmt = pszFormat;
+ std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
+ if (!isValidFormat(fmt)) return -2;
+
+ Lock();
+ int maxId = 0;
+ for (auto v : m_dataVariabels) {
+ if (v != nullptr && static_cast<int>(v->getVarialbleId()) > maxId) {
+ maxId = static_cast<int>(v->getVarialbleId());
+ }
+ }
+ outId = maxId + 1;
+
+ SERVO::CDataVariable* pNew = new SERVO::CDataVariable(std::to_string(outId).c_str(), pszName, fmt.c_str(), pszRemark ? pszRemark : "");
+ m_dataVariabels.push_back(pNew);
+ auto filepath = m_strDataVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -3;
+ return writeDataVariablesToFile(filepath);
+}
+
+int CHsmsPassive::updateDataVariable(int dvid, const char* pszName, const char* pszFormat, const char* pszRemark)
+{
+ if (pszName == nullptr || pszFormat == nullptr) return -1;
+ std::string fmt = pszFormat;
+ std::transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
+ if (!isValidFormat(fmt)) return -2;
+
+ Lock();
+ auto it = std::find_if(m_dataVariabels.begin(), m_dataVariabels.end(), [=](SERVO::CDataVariable* v) {
+ return v != nullptr && v->getVarialbleId() == (unsigned int)dvid;
+ });
+ if (it == m_dataVariabels.end()) {
+ Unlock();
+ return -4;
+ }
+ (*it)->setName(pszName);
+ (*it)->setFormat(fmt.c_str());
+ (*it)->setRemark(pszRemark ? pszRemark : "");
+ auto filepath = m_strDataVariableFilepath;
+ Unlock();
+
+ if (filepath.empty()) return -3;
+ return writeDataVariablesToFile(filepath);
+}
+
+int CHsmsPassive::writeVariablesToFile(const std::string& filepath)
+{
+ if (filepath.empty()) return -3;
+
+ CFile file;
+ if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
+ return -3;
+ }
+
+ // header
+ const std::string headerAnsi = "SVID,SV Name,SV Format,SV Remark\r\n";
+ if (m_bVariableUtf8) {
+ if (m_bVariableUtf8Bom) {
+ const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+ file.Write(bom, 3);
+ }
+ CStringA header = AnsiToUtf8(headerAnsi);
+ file.Write(header.GetString(), header.GetLength());
+ }
+ else {
+ file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+ }
+
+ for (auto v : m_variabels) {
+ if (v == nullptr) continue;
+ std::string lineAnsi;
+ lineAnsi.reserve(256);
+ lineAnsi += std::to_string(v->getVarialbleId());
+ lineAnsi.push_back(',');
+ lineAnsi += v->getName();
+ lineAnsi.push_back(',');
+ lineAnsi += SERVO::CVariable::formatToString(v->getFormat());
+ lineAnsi.push_back(',');
+ lineAnsi += v->getRemark();
+ lineAnsi.append("\r\n");
+
+ if (m_bVariableUtf8) {
+ CStringA outLine = AnsiToUtf8(lineAnsi);
+ file.Write(outLine.GetString(), outLine.GetLength());
+ }
+ else {
+ file.Write(lineAnsi.data(), (UINT)lineAnsi.size());
+ }
+ }
+ file.Close();
+
+ return 0;
+}
+
+int CHsmsPassive::writeDataVariablesToFile(const std::string& filepath)
+{
+ if (filepath.empty()) return -3;
+
+ CFile file;
+ if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
+ return -3;
+ }
+
+ const std::string headerAnsi = "DVID,DV Name,DV Format,DV Remark\r\n";
+ if (m_bDataVariableUtf8) {
+ if (m_bDataVariableUtf8Bom) {
+ const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+ file.Write(bom, 3);
+ }
+ CStringA header = AnsiToUtf8(headerAnsi);
+ file.Write(header.GetString(), header.GetLength());
+ }
+ else {
+ file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+ }
+
+ for (auto v : m_dataVariabels) {
+ if (v == nullptr) continue;
+ std::string lineAnsi;
+ lineAnsi.reserve(256);
+ lineAnsi += std::to_string(v->getVarialbleId());
+ lineAnsi.push_back(',');
+ lineAnsi += v->getName();
+ lineAnsi.push_back(',');
+ lineAnsi += SERVO::CVariable::formatToString(v->getFormat());
+ lineAnsi.push_back(',');
+ lineAnsi += v->getRemark();
+ lineAnsi.append("\r\n");
+
+ if (m_bDataVariableUtf8) {
+ CStringA outLine = AnsiToUtf8(lineAnsi);
+ file.Write(outLine.GetString(), outLine.GetLength());
+ }
+ else {
+ file.Write(lineAnsi.data(), (UINT)lineAnsi.size());
+ }
+ }
+ file.Close();
+ return 0;
+}
+
int CHsmsPassive::loadReports(const char* pszFilepath)
{
- CStdioFile file;
- if (!file.Open(pszFilepath, CFile::modeRead)) {
+ m_strReportFilepath = pszFilepath;
+ m_bReportUtf8 = false;
+ m_bReportUtf8Bom = false;
+ // 鍏煎 UTF-8/BOM 涓庢湰鍦扮紪鐮佽鍙�
+ CFile file;
+ if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
return -1;
}
- std::regex pattern("^\\d+,\\(\\d+(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+ const ULONGLONG nLen = file.GetLength();
+ if (nLen == 0) {
+ return -1;
+ }
+
+ std::string buffer;
+ buffer.resize(static_cast<size_t>(nLen));
+ file.Read(buffer.data(), static_cast<UINT>(nLen));
+ file.Close();
+
+ const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer.data());
+ size_t offset = 0;
+ CStringW content;
+
+ // UTF-8 BOM
+ if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
+ offset = 3;
+ m_bReportUtf8 = true;
+ m_bReportUtf8Bom = true;
+ }
+
+ // UTF-16 LE BOM
+ if (nLen >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
+ const wchar_t* wdata = reinterpret_cast<const wchar_t*>(buffer.data() + 2);
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ content.SetString(wdata, static_cast<int>(wlen));
+ }
+ // UTF-16 BE BOM
+ else if (nLen >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ std::wstring temp;
+ temp.reserve(wlen);
+ for (size_t i = 0; i < wlen; ++i) {
+ wchar_t ch = static_cast<wchar_t>(bytes[2 + i * 2] << 8 | bytes[2 + i * 2 + 1]);
+ temp.push_back(ch);
+ }
+ content = temp.c_str();
+ }
+ else {
+ auto tryUtf8 = [&](size_t off) -> bool {
+ int need = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), nullptr, 0);
+ if (need <= 0) return false;
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), temp.data(), need);
+ content = temp.c_str();
+ m_bReportUtf8 = true;
+ return true;
+ };
+
+ if (!tryUtf8(offset)) {
+ int need = MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), nullptr, 0);
+ if (need > 0) {
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), temp.data(), need);
+ content = temp.c_str();
+ }
+ }
+ }
+
+ if (content.IsEmpty()) {
+ return -1;
+ }
+
+ std::wregex pattern(L"^\\d+,\\(\\d+(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
std::vector<SERVO::CReport*> reports;
int index;
- CString strLine, strVariable;
- CString strId;
- while (file.ReadString(strLine)) {
- if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+ CStringW strLine, strVariable;
+ CStringW strId;
+ std::wstringstream ss(content.GetString());
+ auto narrowFromW = [](const CStringW& s) -> std::string {
+ int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return {};
+ std::string out(static_cast<size_t>(need - 1), '\0');
+ WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
+ return out;
+ };
+ std::wstring line;
+ while (std::getline(ss, line, L'\n')) {
+ strLine = line.c_str();
+ strLine.Trim();
+ if (strLine.IsEmpty()) continue;
+ if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
continue;
}
- index = strLine.Find(",", 0);
+ index = strLine.Find(L",", 0);
if (index < 0) continue;
strId = strLine.Left(index);
strVariable = strLine.Right(strLine.GetLength() - index - 1);
strVariable.Delete(0);
strVariable.Delete(strVariable.GetLength() - 1);
- auto vids = parseVidList(strVariable);
+ CString strVariableA(narrowFromW(strVariable).c_str());
+ auto vids = parseVidList(strVariableA);
- SERVO::CReport* pReport = new SERVO::CReport(atoi((LPTSTR)(LPCTSTR)strId), vids);
+ SERVO::CReport* pReport = new SERVO::CReport(_wtoi(strId), vids);
for (auto vid : vids) {
SERVO::CVariable* pVariable = getVariable(vid);
+ if (pVariable == nullptr) {
+ pVariable = getDataVariable(vid);
+ }
if (pVariable != nullptr) {
pReport->addVariable(pVariable);
}
@@ -290,13 +1214,23 @@
}
- file.Close();
return 0;
}
std::vector<SERVO::CReport*>& CHsmsPassive::getReports()
{
return m_reports;
+}
+
+unsigned int CHsmsPassive::getMaxReportId() const
+{
+ unsigned int maxId = 0;
+ for (auto item : m_reports) {
+ if (item && item->getReportId() > maxId) {
+ maxId = item->getReportId();
+ }
+ }
+ return maxId;
}
SERVO::CReport* CHsmsPassive::getReport(int rptid)
@@ -323,52 +1257,248 @@
return false;
}
-void CHsmsPassive::clearAllReport()
+int CHsmsPassive::deleteReport(int rptid)
{
+ LOGI("<CHsmsPassive>deleteReport enter");
+ if (!removeReport(rptid)) {
+ return -1;
+ }
+ LOGI("<CHsmsPassive>delete Report. rptid=%d", rptid);
+
+ return writeReportsToFile(m_strReportFilepath);
+}
+
+int CHsmsPassive::addReport(int rptid, const std::vector<unsigned int>& vids)
+{
+ if (getReport(rptid) != nullptr) {
+ return -1;
+ }
+ SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
+ for (auto vid : vids) {
+ SERVO::CVariable* pVariable = getVariable((int)vid);
+ if (pVariable == nullptr) {
+ pVariable = getDataVariable((int)vid);
+ }
+ if (pVariable != nullptr) {
+ pReport->addVariable(pVariable);
+ }
+ }
+ m_reports.push_back(pReport);
+ return writeReportsToFile(m_strReportFilepath);
+}
+
+int CHsmsPassive::updateReport(int rptid, const std::vector<unsigned int>& vids)
+{
+ for (auto iter = m_reports.begin(); iter != m_reports.end(); ++iter) {
+ if ((*iter)->getReportId() == rptid) {
+ delete (*iter);
+ SERVO::CReport* pReport = new SERVO::CReport(rptid, vids);
+ for (auto vid : vids) {
+ SERVO::CVariable* pVariable = getVariable((int)vid);
+ if (pVariable == nullptr) {
+ pVariable = getDataVariable((int)vid);
+ }
+ if (pVariable != nullptr) {
+ pReport->addVariable(pVariable);
+ }
+ }
+ *iter = pReport;
+ return writeReportsToFile(m_strReportFilepath);
+ }
+ }
+ return -1;
+}
+
+void CHsmsPassive::clearAllReport(BOOL bSave/* = FALSE*/)
+{
+ LOGI("<CHsmsPassive>clearAllReport enter");
for (auto item : m_reports) {
delete item;
}
m_reports.clear();
+
+ if(bSave)
+ writeReportsToFile(m_strReportFilepath);
+}
+
+int CHsmsPassive::writeReportsToFile(const std::string& filepath)
+{
+ if (filepath.empty()) return -1;
+
+ CFile file;
+ if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite)) {
+ return -1;
+ }
+
+ if (m_bReportUtf8 && m_bReportUtf8Bom) {
+ const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+ file.Write(bom, 3);
+ }
+
+ // header
+ const std::string headerAnsi = "RPTID,(VID1,VID2,...)\r\n";
+ if (m_bReportUtf8) {
+ CStringA header = AnsiToUtf8(headerAnsi);
+ file.Write(header.GetString(), header.GetLength());
+ }
+ else {
+ file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+ }
+
+ for (auto rpt : m_reports) {
+ if (rpt == nullptr) continue;
+ std::string line;
+ line.reserve(64);
+ line += std::to_string(rpt->getReportId());
+ line += ",(";
+
+ const auto& vids = rpt->getVids();
+ for (size_t i = 0; i < vids.size(); ++i) {
+ line += std::to_string(vids[i]);
+ if (i + 1 < vids.size()) {
+ line.push_back(',');
+ }
+ }
+ line += ")\r\n";
+
+ if (m_bReportUtf8) {
+ CStringA out = AnsiToUtf8(line);
+ file.Write(out.GetString(), out.GetLength());
+ }
+ else {
+ file.Write(line.data(), (UINT)line.size());
+ }
+ }
+
+ file.Close();
+ return 0;
}
int CHsmsPassive::loadCollectionEvents(const char* pszFilepath)
{
- CStdioFile file;
- if (!file.Open(pszFilepath, CFile::modeRead)) {
+ m_strCollectionEventFilepath = pszFilepath;
+ m_bCollectionUtf8 = false;
+ m_bCollectionUtf8Bom = false;
+ CFile file;
+ if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
return -1;
}
- std::regex pattern("^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+ const ULONGLONG nLen = file.GetLength();
+ if (nLen == 0) {
+ return -1;
+ }
+
+ std::string buffer;
+ buffer.resize(static_cast<size_t>(nLen));
+ file.Read(buffer.data(), static_cast<UINT>(nLen));
+ file.Close();
+
+ const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer.data());
+ size_t offset = 0;
+ CStringW content;
+
+ // UTF-8 BOM
+ if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
+ offset = 3;
+ m_bCollectionUtf8 = true;
+ m_bCollectionUtf8Bom = true;
+ }
+
+ // UTF-16 LE BOM
+ if (nLen >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
+ const wchar_t* wdata = reinterpret_cast<const wchar_t*>(buffer.data() + 2);
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ content.SetString(wdata, static_cast<int>(wlen));
+ }
+ // UTF-16 BE BOM
+ else if (nLen >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
+ const size_t wlen = (nLen - 2) / sizeof(wchar_t);
+ std::wstring temp;
+ temp.reserve(wlen);
+ for (size_t i = 0; i < wlen; ++i) {
+ wchar_t ch = static_cast<wchar_t>(bytes[2 + i * 2] << 8 | bytes[2 + i * 2 + 1]);
+ temp.push_back(ch);
+ }
+ content = temp.c_str();
+ }
+ else {
+ auto tryUtf8 = [&](size_t off) -> bool {
+ int need = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), nullptr, 0);
+ if (need <= 0) return false;
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
+ static_cast<int>(buffer.size() - off), temp.data(), need);
+ content = temp.c_str();
+ m_bCollectionUtf8 = true;
+ return true;
+ };
+
+ if (!tryUtf8(offset)) {
+ int need = MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), nullptr, 0);
+ if (need > 0) {
+ std::wstring temp;
+ temp.resize(need);
+ MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), temp.data(), need);
+ content = temp.c_str();
+ }
+ }
+ }
+
+ if (content.IsEmpty()) {
+ return -1;
+ }
+
+ // 鍏佽 Attached RPTID 涓虹┖锛�()
+ std::wregex pattern(L"^\\d+,[^,]*,[^,]*,\\(\\d*(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
std::vector<SERVO::CCollectionEvent*> events;
int index, last;
- CString strLine, strRPTIDs;
- CString strId, strName, strDescription;
- while (file.ReadString(strLine)) {
- if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
+ CStringW strLine, strRPTIDs;
+ CStringW strId, strName, strDescription;
+ std::wstringstream ss(content.GetString());
+ auto narrowFromW = [](const CStringW& s) -> std::string {
+ int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
+ if (need <= 0) return {};
+ std::string out(static_cast<size_t>(need - 1), '\0');
+ WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
+ return out;
+ };
+ std::wstring line;
+ while (std::getline(ss, line, L'\n')) {
+ strLine = line.c_str();
+ strLine.Trim();
+ if (strLine.IsEmpty()) continue;
+ if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
continue;
}
last = 0;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strId = strLine.Left(index);
last = index + 1;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strName = strLine.Mid(last, index - last);
last = index + 1;
- index = strLine.Find(",", last);
+ index = strLine.Find(L",", last);
if (index < 0) continue;
strDescription = strLine.Mid(last, index - last);
strRPTIDs = strLine.Right(strLine.GetLength() - index - 1);
strRPTIDs.Delete(0);
strRPTIDs.Delete(strRPTIDs.GetLength() - 1);
- auto prtids = parseVidList(strRPTIDs);
+ CString strRPTIDsA(narrowFromW(strRPTIDs).c_str());
+ auto prtids = parseVidList(strRPTIDsA);
+
+ std::string sName = narrowFromW(strName);
+ std::string sDesc = narrowFromW(strDescription);
SERVO::CCollectionEvent* pEvent = new SERVO::CCollectionEvent(
- atoi(strId), (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strDescription, prtids);
+ _wtoi(strId), sName.c_str(), sDesc.c_str(), prtids);
for (auto rptid : prtids) {
SERVO::CReport* pReport = getReport(rptid);
if (pReport != nullptr) {
@@ -384,15 +1514,70 @@
m_collectionEvents.push_back(item);
}
}
-
-
- file.Close();
return 0;
}
std::vector<SERVO::CCollectionEvent*>& CHsmsPassive::getCollectionEvents()
{
return m_collectionEvents;
+}
+
+unsigned int CHsmsPassive::getMaxCollectionEventId() const
+{
+ unsigned int maxId = 0;
+ for (auto item : m_collectionEvents) {
+ if (item && item->getEventId() > maxId) {
+ maxId = item->getEventId();
+ }
+ }
+ return maxId;
+}
+
+int CHsmsPassive::deleteCollectionEvent(unsigned short CEID)
+{
+ for (auto iter = m_collectionEvents.begin(); iter != m_collectionEvents.end(); ++iter) {
+ if ((*iter)->getEventId() == CEID) {
+ delete (*iter);
+ m_collectionEvents.erase(iter);
+ return writeCollectionEventsToFile(m_strCollectionEventFilepath);
+ }
+ }
+ return -1;
+}
+
+int CHsmsPassive::addCollectionEvent(unsigned int CEID, const char* name, const char* desc, const std::vector<unsigned int>& rptids)
+{
+ if (getEvent((unsigned short)CEID) != nullptr) {
+ return -1;
+ }
+ auto* pEvent = new SERVO::CCollectionEvent(CEID, name, desc, const_cast<std::vector<unsigned int>&>(rptids));
+ for (auto rptid : rptids) {
+ SERVO::CReport* pReport = getReport((int)rptid);
+ if (pReport != nullptr) {
+ pEvent->addReport(pReport);
+ }
+ }
+ m_collectionEvents.push_back(pEvent);
+ return writeCollectionEventsToFile(m_strCollectionEventFilepath);
+}
+
+int CHsmsPassive::updateCollectionEvent(unsigned int CEID, const char* name, const char* desc, const std::vector<unsigned int>& rptids)
+{
+ for (auto iter = m_collectionEvents.begin(); iter != m_collectionEvents.end(); ++iter) {
+ if ((*iter)->getEventId() == CEID) {
+ delete (*iter);
+ auto* pEvent = new SERVO::CCollectionEvent(CEID, name, desc, const_cast<std::vector<unsigned int>&>(rptids));
+ for (auto rptid : rptids) {
+ SERVO::CReport* pReport = getReport((int)rptid);
+ if (pReport != nullptr) {
+ pEvent->addReport(pReport);
+ }
+ }
+ *iter = pEvent;
+ return writeCollectionEventsToFile(m_strCollectionEventFilepath);
+ }
+ }
+ return -1;
}
void CHsmsPassive::clearAllCollectionEvent()
@@ -436,6 +1621,62 @@
return result;
}
+int CHsmsPassive::writeCollectionEventsToFile(const std::string& filepath)
+{
+ if (filepath.empty()) return -1;
+
+ CFile file;
+ if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite)) {
+ return -1;
+ }
+
+ if (m_bCollectionUtf8 && m_bCollectionUtf8Bom) {
+ const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+ file.Write(bom, 3);
+ }
+
+ const std::string headerAnsi = "CEID,CE Name,Descriptions,Attached RPTID\r\n";
+ if (m_bCollectionUtf8) {
+ CStringA header = AnsiToUtf8(headerAnsi);
+ file.Write(header.GetString(), header.GetLength());
+ }
+ else {
+ file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+ }
+
+ for (auto ev : m_collectionEvents) {
+ if (ev == nullptr) continue;
+ std::string line;
+ line.reserve(128);
+ line += std::to_string(ev->getEventId());
+ line.push_back(',');
+ line += ev->getName();
+ line.push_back(',');
+ line += ev->getDescription();
+ line.push_back(',');
+ line.push_back('(');
+ auto rptIds = ev->getReportIds();
+ for (size_t i = 0; i < rptIds.size(); ++i) {
+ line += std::to_string(rptIds[i]);
+ if (i + 1 < rptIds.size()) {
+ line.push_back(',');
+ }
+ }
+ line += ")\r\n";
+
+ if (m_bCollectionUtf8) {
+ CStringA out = AnsiToUtf8(line);
+ file.Write(out.GetString(), out.GetLength());
+ }
+ else {
+ file.Write(line.data(), (UINT)line.size());
+ }
+ }
+
+ file.Close();
+ return 0;
+}
+
int CHsmsPassive::init(CModel* pModel, const char* pszName, unsigned int port)
{
m_pModel = pModel;
@@ -459,18 +1700,18 @@
*/
};
auto onRecvSysMessage = [&](void* pFrom, IMessage* pMessage) -> void {
- LOGI("<HSMS>onRecvSysMessage:sessionId:%d, sType:%d systemBytes:%d",
- pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LOGI("<HSMS>[Received]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
onRecvMsg(pMessage);
if (MSG_LINKTEST_REQ == pMessage->getHeader()->sType) {
- /*
- Sleep(10);
- if (!m_bAreYouThereRequest) {
- m_bAreYouThereRequest = TRUE;
- requestYouThere();
- }
- */
+ /*
+ Sleep(10);
+ if (!m_bAreYouThereRequest) {
+ m_bAreYouThereRequest = TRUE;
+ requestYouThere();
}
+ */
+}
};
auto onError = [&](void* pFrom, int error) -> void {
@@ -486,10 +1727,22 @@
HEADER* pHeader = pMessage->getHeader();
int nStream = (pHeader->stream & 0x7F);
- LOGI("<HSMS>鏀跺埌娑堟伅 S%dF%d", nStream, pHeader->function);
+ LogSecsMessageBrief("<HSMS>[Received]", pMessage);
if (nStream == 1 && pHeader->function == 1) {
// S1F1
replyAreYouThere(pMessage);
+ }
+ else if (nStream == 1 && pHeader->function == 3) {
+ replySelectedEquipmentStatusData(pMessage);
+ }
+ else if (nStream == 1 && pHeader->function == 11) {
+ replyStatusVariableNamelistRequest(pMessage);
+ }
+ else if (nStream == 1 && pHeader->function == 21) {
+ replyDataVariableNamelistRequest(pMessage);
+ }
+ else if (nStream == 1 && pHeader->function == 23) {
+ replyCollectionEventNamelistRequest(pMessage);
}
else if (nStream == 1 && pHeader->function == 13) {
replyEstablishCommunications(pMessage);
@@ -521,14 +1774,35 @@
else if (nStream == 2 && pHeader->function == 41) {
replyCommand(pMessage);
}
+ else if (nStream == 2 && pHeader->function == 43) {
+ replyConfigureSpooling(pMessage);
+ }
+ else if (nStream == 3 && pHeader->function == 17) {
+ replyCarrierAction(pMessage);
+ }
else if (nStream == 5 && pHeader->function == 3) {
replyEanbleDisableAlarmReport(pMessage);
+ }
+ else if (nStream == 6 && pHeader->function == 23) {
+ replyPurgeSpooledData(pMessage);
}
else if (nStream == 7 && pHeader->function == 19) {
replyQueryPPIDList(pMessage);
}
+ else if (nStream == 7 && pHeader->function == 17) {
+ replyDeletePPID(pMessage);
+ }
+ else if (nStream == 7 && pHeader->function == 5) {
+ replyProcessProgramRequest(pMessage);
+ }
else if (nStream == 10 && pHeader->function == 3) {
replyTerminalDisplay(pMessage);
+ }
+ else if (nStream == 14 && pHeader->function == 9) {
+ replyCreateObj(pMessage);
+ }
+ else if (nStream == 16 && pHeader->function == 15) {
+ replyPRJobMultiCreate(pMessage);
}
};
@@ -549,6 +1823,47 @@
SetTimer(NULL, 1, 1000, (TIMERPROC)HsmsPassiveTimerProc);
return 0;
+}
+
+int CHsmsPassive::loadCacheFromFile(const char* pszFilepath)
+{
+ m_strCacheFilepath = pszFilepath;
+
+ CFile file;
+ if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeRead) ) {
+ return -1;
+ }
+
+ ULONGLONG len = file.GetLength();
+ if (len > INT_MAX) {
+ file.Close();
+ return -1;
+ }
+ int nBufSize = static_cast<int>(len);
+ char* pszBuffer = new char[nBufSize];
+ file.Read(pszBuffer, nBufSize);
+ file.Close();
+ int nRet = unserialize(pszBuffer, nBufSize);
+ delete[] pszBuffer;
+
+ return nRet;
+}
+
+int CHsmsPassive::saveCache()
+{
+ CFile file;
+ if (!file.Open(m_strCacheFilepath.c_str(), CFile::modeWrite | CFile::modeCreate)) {
+ return -1;
+ }
+
+ int nSize = serialize(nullptr, 0);
+ char* pszBuffer = new char[nSize];
+ int nRet = serialize(pszBuffer, nSize);
+ file.Write(pszBuffer, nSize);
+ file.Close();
+ delete[] pszBuffer;
+
+ return nRet;
}
int CHsmsPassive::term()
@@ -574,6 +1889,142 @@
return 0;
}
+int CHsmsPassive::serialize(char* pszBuffer, int nBufferSize)
+{
+ int index = 0;
+ const auto calcSpoolCfgSize = [&]() -> int {
+ // magic(4) + ver(2) + enabled(1) + mapSize(4) + entries...
+ int sz = 0;
+ sz += 4; // 'SPOL'
+ sz += 2; // version
+ sz += 1; // enabled
+ sz += 4; // map size
+ for (const auto& kv : m_spoolBlacklistByStream) {
+ sz += 2; // streamId (U16)
+ sz += 4; // fn count (U32)
+ sz += static_cast<int>(kv.second.size()) * 2; // fn ids (U16 each)
+ }
+ return sz;
+ };
+ if (pszBuffer == nullptr) {
+ index += sizeof(int);
+ for (auto item : m_listActionSpooling) {
+ index += item->serialize(pszBuffer, nBufferSize);
+ }
+
+ index += calcSpoolCfgSize();
+
+ return index;
+ }
+ else {
+ int nTemp, nRet;
+
+ nTemp = (int)m_listActionSpooling.size();
+ memcpy(&pszBuffer[index], &nTemp, sizeof(int));
+ index += sizeof(int);
+
+ for (auto item : m_listActionSpooling) {
+ nRet = item->serialize(&pszBuffer[index], nBufferSize);
+ if (nRet <= 0) break;
+ index += nRet;
+ }
+
+ // Append spooling config (backward compatible via magic+version)
+ auto writeU32 = [&](uint32_t v) {
+ memcpy(&pszBuffer[index], &v, sizeof(v));
+ index += sizeof(v);
+ };
+ auto writeU16 = [&](uint16_t v) {
+ memcpy(&pszBuffer[index], &v, sizeof(v));
+ index += sizeof(v);
+ };
+ auto writeU8 = [&](uint8_t v) {
+ memcpy(&pszBuffer[index], &v, sizeof(v));
+ index += sizeof(v);
+ };
+
+ const uint32_t magic = 0x4C4F5053; // 'SPOL' little-endian
+ writeU32(magic);
+ writeU16(1); // version
+ writeU8(m_spoolingEnabled ? 1 : 0);
+ writeU32(static_cast<uint32_t>(m_spoolBlacklistByStream.size()));
+ for (const auto& kv : m_spoolBlacklistByStream) {
+ writeU16(static_cast<uint16_t>(kv.first));
+ writeU32(static_cast<uint32_t>(kv.second.size()));
+ for (const auto& fn : kv.second) {
+ writeU16(static_cast<uint16_t>(fn));
+ }
+ }
+
+ return index;
+ }
+}
+
+int CHsmsPassive::unserialize(const char* pszBuffer, int nBufferSize)
+{
+ int index = 0, nTemp, nRet = 0;
+
+ if (index + sizeof(int) > nBufferSize) return -1;
+ memcpy(&nTemp, &pszBuffer[index], sizeof(int));
+ index += sizeof(int);
+
+ for (int i = 0; i < nTemp; i++) {
+ CHsmsAction* pAction = new CHsmsAction();
+ nRet = pAction->unserialize(&pszBuffer[index], nBufferSize - index);
+ if (nRet <= 0) break;
+ index += nRet;
+ m_listActionSpooling.push_back(pAction);
+ }
+
+ // Parse optional spooling config tail (magic+version). If absent, keep defaults.
+ const auto remaining = nBufferSize - index;
+ if (remaining >= 4) {
+ uint32_t magic = 0;
+ memcpy(&magic, &pszBuffer[index], sizeof(magic));
+ if (magic == 0x4C4F5053) { // 'SPOL'
+ index += 4;
+ if (nBufferSize - index >= 2 + 1 + 4) {
+ uint16_t ver = 0;
+ memcpy(&ver, &pszBuffer[index], sizeof(ver));
+ index += 2;
+ if (ver >= 1) {
+ uint8_t enabled = 1;
+ memcpy(&enabled, &pszBuffer[index], sizeof(enabled));
+ index += 1;
+ m_spoolingEnabled = (enabled != 0);
+
+ uint32_t mapSize = 0;
+ memcpy(&mapSize, &pszBuffer[index], sizeof(mapSize));
+ index += 4;
+
+ m_spoolBlacklistByStream.clear();
+ for (uint32_t mi = 0; mi < mapSize; ++mi) {
+ if (nBufferSize - index < 2 + 4) break;
+ uint16_t streamId = 0;
+ memcpy(&streamId, &pszBuffer[index], sizeof(streamId));
+ index += 2;
+ uint32_t fnCount = 0;
+ memcpy(&fnCount, &pszBuffer[index], sizeof(fnCount));
+ index += 4;
+
+ auto& setRef = m_spoolBlacklistByStream[streamId];
+ setRef.clear();
+ for (uint32_t fi = 0; fi < fnCount; ++fi) {
+ if (nBufferSize - index < 2) break;
+ uint16_t fn = 0;
+ memcpy(&fn, &pszBuffer[index], sizeof(fn));
+ index += 2;
+ setRef.insert(fn);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return index;
+}
+
unsigned CHsmsPassive::OnCimWork()
{
while (m_bCimWorking) {
@@ -590,19 +2041,48 @@
Unlock();
while (!list.empty()) {
+ CHsmsAction* pAction = nullptr;
Lock();
- CHsmsAction* pAction = list.front();
+ pAction = list.front();
Unlock();
list.pop_front();
- TRACE("OnCimWork 004.\n");
- IMessage* pMessage = pAction->getSendMessage();
- ASSERT(pMessage);
- m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ Lock();
+ const bool selected = (m_pPassive != NULL && STATE::SELECTED == m_pPassive->getState());
+ Unlock();
+ if (!selected) {
+ IMessage* pMsg = pAction->getSendMessage();
+ uint8_t streamId = 0;
+ uint8_t functionId = 0;
+ if (pMsg && pMsg->getHeader()) {
+ streamId = static_cast<uint8_t>(pMsg->getHeader()->stream & 0x7F);
+ functionId = static_cast<uint8_t>(pMsg->getHeader()->function & 0xFF);
+ }
+ if (shouldSpool(streamId, functionId)) {
+ Lock();
+ m_listActionSpooling.push_back(pAction);
+ Unlock();
+ }
+ else {
+ LOGI("<HSMS>spooling disabled for S%dF%d, drop action", (int)streamId, (int)functionId);
+ delete pAction;
+ }
+ continue;
+ }
+ TRACE("OnCimWork 004.\n");
if (pAction->isNeedWaitReply()) {
// 濡傛灉闇�瑕佺瓑寰呭洖澶�
+ Lock();
+ m_pActiveAction = pAction;
+ IMessage* pMessage = pAction->getSendMessage();
+ Unlock();
+
+ ASSERT(pMessage);
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+
int nRet = WaitForSingleObject(pAction->getEvent(), pAction->getTimeout() * 1000);
if (nRet == WAIT_TIMEOUT) {
TRACE("Timeout...\n");
@@ -613,18 +2093,23 @@
//pContext->setEvent();
}
}
-
- delete pAction;
- pAction = NULL;
- TRACE("delete m_pCurrentAction, next...\n");
+ Lock();
+ delete m_pActiveAction;
+ m_pActiveAction = nullptr;
+ Unlock();
}
else {
Lock();
m_listActionSent.push_back(pAction);
+ IMessage* pMessage = pAction->getSendMessage();
Unlock();
+
+ ASSERT(pMessage);
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+
}
-
-
}
TRACE("OnCimWork \n");
@@ -644,7 +2129,9 @@
ISECS2Item* pItem = pMessage->getBody();
pItem->setBinary((const char*)&ack, 1, pszAckName);
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S%dF%d (SysByte=%u)", s, f, systemBytes);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
HSMS_Destroy1Message(pMessage);
}
@@ -666,6 +2153,7 @@
SetEvent(m_hCimWorkEvent);
Unlock();
+
return ER_NOERROR;
}
@@ -684,7 +2172,9 @@
pItem->addItem(m_strEquipmentModelType.c_str(), "MDLN");
pItem->addItem(m_strSoftRev.c_str(), "SOFTREV");
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S1F2 (SysByte=%u)", pMessage->getHeader()->systemBytes);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
HSMS_Destroy1Message(pMessage);
return 0;
@@ -728,6 +2218,7 @@
return 0;
}
+// S1F13
int CHsmsPassive::replyEstablishCommunications(IMessage* pRecv)
{
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
@@ -744,10 +2235,320 @@
pList->addItem(m_strEquipmentModelType.c_str(), "MDLN");
pList->addItem(m_strSoftRev.c_str(), "SOFTREV");
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]%s", pMessage->toString());
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
HSMS_Destroy1Message(pMessage);
return 0;
+}
+
+// S1F3
+int CHsmsPassive::replySelectedEquipmentStatusData(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 1, 4, pRecv->getHeader()->systemBytes);
+ ASSERT(pMessage);
+
+ unsigned char SVU1 = 0;
+ unsigned short SVID = 0;
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::L) {
+ pMessage->getBody()->addU1Item(SVU1, "SV");
+ goto MYREPLY;
+ }
+ if (!pBody->getSubItemU2(0, SVID)) {
+ // also accept I2 or U4 to be tolerant with host implementations
+ if (!pBody->getSubItemI2(0, (short&)SVID)) {
+ unsigned int svidU4 = 0;
+ if (!pBody->getSubItemU4(0, svidU4)) {
+ pMessage->getBody()->addU1Item(SVU1, "SV");
+ goto MYREPLY;
+ }
+ SVID = static_cast<unsigned short>(svidU4);
+ }
+ }
+
+ SERVO::CVariable* pVariable = getVariable((int)SVID);
+ if (pVariable == nullptr) {
+ pMessage->getBody()->addU1Item(SVU1, "SV");
+ goto MYREPLY;
+ }
+ addVariableValueToItem(pMessage->getBody(), pVariable);
+
+MYREPLY:
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+
+
+ return 0;
+}
+
+// S1F11
+int CHsmsPassive::replyStatusVariableNamelistRequest(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ std::vector<unsigned short> reqIds;
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody != nullptr && pBody->getType() == SITYPE::L) {
+ const int sz = pBody->getSubItemSize();
+ for (int i = 0; i < sz; ++i) {
+ unsigned short id = 0;
+ if (pBody->getSubItemU2(i, id)) {
+ reqIds.push_back(id);
+ }
+ }
+ }
+
+ // Build response list items: {L:3 SVID, SVNAME, UNITS}
+ std::vector<unsigned short> svids;
+ std::set<unsigned short> requested(reqIds.begin(), reqIds.end());
+ Lock();
+ if (reqIds.empty()) {
+ for (auto v : m_variabels) {
+ svids.push_back(static_cast<unsigned short>(v->getVarialbleId()));
+ }
+ }
+ else {
+ // include requested IDs (existing + unknown marker)
+ for (auto id : requested) {
+ svids.push_back(id);
+ }
+ }
+ Unlock();
+
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 1, 12, pRecv->getHeader()->systemBytes);
+ ASSERT(pMessage);
+
+ ISECS2Item* pList = pMessage->getBody(); // Body is L[n] of {SVID, SVNAME, UNITS}
+ for (auto id : svids) {
+ ISECS2Item* pEntry = pList->addItem();
+ pEntry->addU2Item(id, "SVID");
+ SERVO::CVariable* v = getVariable((int)id);
+ if (v != nullptr) {
+ pEntry->addItem(v->getName().c_str(), "SVNAME");
+ // Use remark as UNITS if provided; empty string if none.
+ pEntry->addItem(v->getRemark().c_str(), "UNITS");
+ }
+ else {
+ // Unknown SVID: A:0 for name/units
+ pEntry->addItem("", "SVNAME");
+ pEntry->addItem("", "UNITS");
+ }
+ }
+
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return ER_NOERROR;
+}
+
+int CHsmsPassive::writeEquipmentConstantsToFile(const std::string& filepath)
+{
+ if (filepath.empty()) return -1;
+ CFile file;
+ if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
+ return -1;
+ }
+ const std::string headerAnsi = "ECID,EC Name,EC Format,EC Remark,Default Value\r\n";
+ if (m_bEquipmentConstantUtf8) {
+ if (m_bEquipmentConstantUtf8Bom) {
+ const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
+ file.Write(bom, 3);
+ }
+ CStringA header = AnsiToUtf8(headerAnsi);
+ file.Write(header.GetString(), header.GetLength());
+ }
+ else {
+ file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
+ }
+ for (const auto& e : m_equipmentConstants) {
+ std::string line;
+ line.reserve(128);
+ line += std::to_string(e.id);
+ line.push_back(',');
+ line += e.name;
+ line.push_back(',');
+ line += e.format;
+ line.push_back(',');
+ line += e.remark;
+ line.push_back(',');
+ line += e.value;
+ line.append("\r\n");
+ if (m_bEquipmentConstantUtf8) {
+ CStringA out = AnsiToUtf8(line);
+ file.Write(out.GetString(), out.GetLength());
+ }
+ else {
+ file.Write(line.data(), (UINT)line.size());
+ }
+ }
+ file.Close();
+ return 0;
+}
+// S1F21/S1F22 - Data Variable Namelist
+int CHsmsPassive::replyDataVariableNamelistRequest(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ std::vector<unsigned short> reqIds;
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody != nullptr && pBody->getType() == SITYPE::L) {
+ const int sz = pBody->getSubItemSize();
+ for (int i = 0; i < sz; ++i) {
+ unsigned short id = 0;
+ if (pBody->getSubItemU2(i, id)) {
+ reqIds.push_back(id);
+ }
+ }
+ }
+
+ std::vector<unsigned short> dvids;
+ std::set<unsigned short> requested(reqIds.begin(), reqIds.end());
+ Lock();
+ if (reqIds.empty()) {
+ for (auto v : m_dataVariabels) {
+ if (v) dvids.push_back(static_cast<unsigned short>(v->getVarialbleId()));
+ }
+ }
+ else {
+ for (auto id : requested) dvids.push_back(id);
+ }
+ Unlock();
+
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 1, 22, pRecv->getHeader()->systemBytes);
+ ASSERT(pMessage);
+
+ ISECS2Item* pList = pMessage->getBody(); // L[n] of {DVID, DVNAME, UNITS}
+ for (auto id : dvids) {
+ ISECS2Item* pEntry = pList->addItem();
+ pEntry->addU2Item(id, "DVID");
+ SERVO::CDataVariable* v = getDataVariable((int)id);
+ if (v != nullptr) {
+ pEntry->addItem(v->getName().c_str(), "DVNAME");
+ pEntry->addItem(v->getRemark().c_str(), "UNITS");
+ }
+ else {
+ pEntry->addItem("", "DVNAME");
+ pEntry->addItem("", "UNITS");
+ }
+ }
+
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return ER_NOERROR;
+}
+
+// S1F23
+int CHsmsPassive::replyCollectionEventNamelistRequest(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ std::vector<unsigned short> reqIds;
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody != nullptr && pBody->getType() == SITYPE::L) {
+ const int sz = pBody->getSubItemSize();
+ for (int i = 0; i < sz; ++i) {
+ unsigned short id = 0;
+ if (pBody->getSubItemU2(i, id)) {
+ reqIds.push_back(id);
+ }
+ }
+ }
+
+ struct CEInfo {
+ unsigned short id{ 0 };
+ std::string name;
+ std::vector<unsigned short> vids;
+ };
+ std::vector<CEInfo> ceInfos;
+ {
+ Lock();
+ if (reqIds.empty()) {
+ for (auto e : m_collectionEvents) {
+ if (e == nullptr) continue;
+ CEInfo info;
+ info.id = static_cast<unsigned short>(e->getEventId());
+ info.name = e->getName();
+ std::set<unsigned short> vidSet;
+ for (auto rpt : e->getReports()) {
+ if (rpt == nullptr) continue;
+ for (auto vid : rpt->getVids()) {
+ vidSet.insert(static_cast<unsigned short>(vid));
+ }
+ }
+ info.vids.assign(vidSet.begin(), vidSet.end());
+ ceInfos.push_back(std::move(info));
+ }
+ }
+ else {
+ for (auto id : reqIds) {
+ CEInfo info;
+ info.id = id;
+ SERVO::CCollectionEvent* e = getEvent(id);
+ if (e != nullptr) {
+ info.name = e->getName();
+ std::set<unsigned short> vidSet;
+ for (auto rpt : e->getReports()) {
+ if (rpt == nullptr) continue;
+ for (auto vid : rpt->getVids()) {
+ vidSet.insert(static_cast<unsigned short>(vid));
+ }
+ }
+ info.vids.assign(vidSet.begin(), vidSet.end());
+ }
+ ceInfos.push_back(std::move(info));
+ }
+ }
+ Unlock();
+ }
+
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 1, 24, pRecv->getHeader()->systemBytes);
+ ASSERT(pMessage);
+
+ ISECS2Item* pList = pMessage->getBody(); // Body is L[n] of {CEID, CENAME, L[VIDs]}
+ for (const auto& info : ceInfos) {
+ ISECS2Item* pEntry = pList->addItem();
+ pEntry->addU2Item(info.id, "CEID");
+ pEntry->addItem(info.name.c_str(), "CENAME"); // empty if unknown
+ ISECS2Item* pVidList = pEntry->addItem();
+ for (auto vid : info.vids) {
+ pVidList->addU2Item(vid, "VID");
+ }
+ }
+
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return ER_NOERROR;
}
// S2F13
@@ -758,32 +2559,42 @@
}
- // 瑕佽幏鍙栫殑甯搁噺琛ㄨ〃
- BOOL bCheckData = FALSE;
std::vector<EQConstant> eqcs;
{
ISECS2Item* pItem = pRecv->getBody();
- int ecidSize = pItem->getSubItemSize();
+ const int ecidSize = pItem ? pItem->getSubItemSize() : 0;
for (int i = 0; i < ecidSize; i++) {
- EQConstant eqc;
- unsigned short id;
- if (pItem->getSubItemU2(i, id)) {
+ EQConstant eqc{};
+ unsigned short id = 0;
+ if (pItem && pItem->getSubItemU2(i, id)) {
eqc.id = id;
eqcs.push_back(eqc);
}
}
}
-
-
- // 浜ょ敱涓婂眰搴旂敤鏉ヨ幏鍙栨満鍣ㄥ父閲忓��
- if (m_listener.onEQConstantRequest != nullptr) {
- m_listener.onEQConstantRequest(this, eqcs);
+ // 绌哄垪琛ㄨ〃绀鸿姹傚叏閮� ECID
+ if (eqcs.empty()) {
+ for (const auto& e : m_equipmentConstants) {
+ EQConstant eqc{};
+ eqc.id = e.id;
+ strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, e.value.c_str());
+ eqcs.push_back(eqc);
+ }
+ } else {
+ for (auto& item : eqcs) {
+ auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(),
+ [&](const EquipmentConstantEntry& e) { return e.id == item.id; });
+ if (it != m_equipmentConstants.end()) {
+ strcpy_s(item.szValue, EQCONSTANT_VALUE_MAX, it->value.c_str());
+ } else {
+ item.szValue[0] = '\0'; // unknown -> empty
+ }
+ }
}
-
// 鍥炲
IMessage* pMessage = NULL;
- HSMS_Create1Message(pMessage, m_nSessionId, 1, 14, pRecv->getHeader()->systemBytes);
+ HSMS_Create1Message(pMessage, m_nSessionId, 2, 14, pRecv->getHeader()->systemBytes);
ASSERT(pMessage);
ISECS2Item* pItem = pMessage->getBody();
for (auto& item : eqcs) {
@@ -791,7 +2602,9 @@
}
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S2F14 (SysByte=%u)", pMessage->getHeader()->systemBytes);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
HSMS_Destroy1Message(pMessage);
return 0;
@@ -805,33 +2618,38 @@
}
- // 瑕佽缃殑甯搁噺琛ㄨ〃
- BOOL bCheckData = FALSE;
+ // 瑕佽缃殑甯搁噺琛�
std::vector<EQConstant> eqcs;
{
ISECS2Item* pItem = pRecv->getBody();
- int ecidSize = pItem->getSubItemSize();
+ int ecidSize = pItem ? pItem->getSubItemSize() : 0;
for (int i = 0; i < ecidSize; i++) {
- ISECS2Item* pItemEqc = pItem->getSubItem(i);
- if (pItemEqc != nullptr) {
- EQConstant eqc;
- unsigned short eqcid;
- const char* pszValue;
- if (pItemEqc->getSubItemU2(0, eqcid)
- && pItemEqc->getSubItemString(1, pszValue)) {
- eqc.id = eqcid;
- strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue);
- eqcs.push_back(eqc);
- }
+ ISECS2Item* pItemEqc = pItem ? pItem->getSubItem(i) : nullptr;
+ if (pItemEqc == nullptr) continue;
+ EQConstant eqc{};
+ unsigned short eqcid = 0;
+ const char* pszValue = nullptr;
+ if (pItemEqc->getSubItemU2(0, eqcid)
+ && pItemEqc->getSubItemString(1, pszValue)) {
+ eqc.id = eqcid;
+ strcpy_s(eqc.szValue, EQCONSTANT_VALUE_MAX, pszValue);
+ eqcs.push_back(eqc);
}
}
}
-
- // 浜ょ敱涓婂眰搴旂敤鏉ヤ繚瀛樺拰璁剧疆鏈哄櫒甯搁噺鍊�
- std::vector<unsigned int> ecvs;
- if (m_listener.onEQConstantSend != nullptr) {
- m_listener.onEQConstantSend(this, eqcs);
+ // 鏇存柊鍐呭瓨琛ㄥ苟钀界洏
+ bool changed = false;
+ for (auto& item : eqcs) {
+ auto it = std::find_if(m_equipmentConstants.begin(), m_equipmentConstants.end(),
+ [&](const EquipmentConstantEntry& e) { return e.id == item.id; });
+ if (it != m_equipmentConstants.end()) {
+ it->value = item.szValue;
+ changed = true;
+ }
+ }
+ if (changed && !m_strEquipmentConstantFilepath.empty()) {
+ writeEquipmentConstantsToFile(m_strEquipmentConstantFilepath);
}
@@ -887,13 +2705,14 @@
ISECS2Item* pBody = pRecv->getBody();
ISECS2Item* defineItem, *rptListItem, * vidListItem;
- unsigned int dataId, rptid, vid;
+ unsigned short dataId;
+ unsigned int rptid, vid;
- if (!pBody->getSubItemU4(0, dataId)) goto MYREPLY;
+ if (!pBody->getSubItemU2(0, dataId)) goto MYREPLY;
rptListItem = pBody->getSubItem(1);
if (rptListItem == nullptr) goto MYREPLY;
if (rptListItem->getSubItemSize() == 0) {
- clearAllReport();
+ clearAllReport(TRUE);
goto MYREPLY;
}
@@ -913,8 +2732,10 @@
}
}
- removeReport(rptid);
- if (!vids.empty()) {
+ if (vids.empty()) {
+ deleteReport(rptid);
+ } else {
+ removeReport(rptid);
pReport = defineReport(rptid, vids);
}
@@ -943,8 +2764,10 @@
ISECS2Item* pBody = pRecv->getBody();
ISECS2Item* linkItem, *ceidListItem, *rptListItem;
- unsigned int dataId, ceid, rptid;
- if (!pBody->getSubItemU4(0, dataId)) goto MYREPLY;
+ unsigned short dataId;
+ unsigned int ceid, rptid;
+ bool bChanged = false;
+ if (!pBody->getSubItemU2(0, dataId)) goto MYREPLY;
ceidListItem = pBody->getSubItem(1);
if (ceidListItem == nullptr) goto MYREPLY;
for (int i = 0; i < ceidListItem->getSubItemSize(); i++) {
@@ -956,21 +2779,31 @@
int prtCount = rptListItem->getSubItemSize();
if (prtCount == 0) {
unlinkEventReport(ceid);
+ bChanged = true;
}
else {
for (int k = 0; k < prtCount; k++) {
if (rptListItem->getSubItemU4(k, rptid)) {
linkEventReport(ceid, rptid);
+ bChanged = true;
}
}
}
}
}
+ // 鎸佷箙鍖栧埌 CollectionEventList.txt锛堜究浜庝笅娆″惎鍔ㄤ粛淇濇寔 Link/Unlink 缁撴灉锛�
+ if (bChanged && !m_strCollectionEventFilepath.empty()) {
+ writeCollectionEventsToFile(m_strCollectionEventFilepath);
+ }
// 妫�楠岀粨鏋滄槸鍚︽纭�
for (auto item : m_collectionEvents) {
- LOGE("=== ceid:%d, prtid:%d", item->getEventId(), item->getPortID());
+ unsigned int reportId = item->getFirstReportID();
+ if(reportId != 0)
+ LOGI("=== ceid:%d, prtid:%d", item->getEventId(), reportId);
+ else
+ LOGI("=== ceid:%d, prtid:--", item->getEventId());
}
MYREPLY:
@@ -1067,6 +2900,122 @@
return 0;
}
+// S2F43
+int CHsmsPassive::replyConfigureSpooling(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR;
+
+ // 娓呯┖鎵�鏈�
+ if (pBody->getSubItemSize() == 0) {
+ LOGI("<CHsmsPassive>turns off all streams and fns");
+ m_spoolBlacklistByStream.clear();
+ m_spoolingEnabled = false;
+ goto MYREPLY;
+ }
+ m_spoolingEnabled = true;
+
+ // 渚濇閰嶇疆Stream
+ for (int i = 0; i < pBody->getSubItemSize(); i++) {
+ ISECS2Item* pStreamItem = pBody->getSubItem(i);
+ ASSERT(pStreamItem);
+ unsigned char STRID, FCNID;
+ pStreamItem->getSubItemU1(0, STRID);
+ ISECS2Item* pFcnItemList = pStreamItem->getSubItem(1);
+ if (pFcnItemList == nullptr || pFcnItemList->getSubItemSize() == 0) {
+ // No functions listed => blacklist the whole stream
+ m_spoolBlacklistByStream[STRID].clear();
+ }
+ else {
+ // Update blacklist for this stream
+ m_spoolBlacklistByStream[STRID].clear();
+ for (int j = 0; j < pFcnItemList->getSubItemSize(); j++) {
+ pFcnItemList->getSubItemU1(j, FCNID);
+ m_spoolBlacklistByStream[STRID].insert(FCNID);
+ }
+ }
+ }
+
+ // 鎵撳嵃楠岃瘉缁撴灉
+ for (auto s : m_spoolBlacklistByStream) {
+ LOGI("====> spool blacklist stream:%d", s.first);
+ if (s.second.empty()) {
+ LOGI("blacklist all functions");
+ }
+ else {
+ for (auto f : s.second) {
+ LOGI("blacklist function:%d", f);
+ }
+ }
+ }
+MYREPLY:
+ replyAck(2, 44, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
+ return 0;
+}
+
+// S3F17
+int CHsmsPassive::replyCarrierAction(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ unsigned char CAACK = CAACK_0;
+ unsigned int ERRCODE = 0;
+ std::string strError = "no error";
+ if (m_listener.onCarrierAction == nullptr) {
+ CAACK = 5;
+ ERRCODE = CAACK_5;
+ strError = "Not supported";
+ goto MYREPLY;
+ }
+
+ if (!isHostCommandAllowed()) {
+ CAACK = CAACK_5;
+ ERRCODE = CAACK_5;
+ strError = "rejected - ControlState not OnlineRemote";
+ goto MYREPLY;
+ }
+
+
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR;
+
+ unsigned short DATAID;
+ unsigned char PTN;
+ const char* pszCarrierAction, *pszCarrierId;
+ pBody->getSubItemU2(0, DATAID);
+ pBody->getSubItemString(1, pszCarrierAction);
+ pBody->getSubItemString(2, pszCarrierId);
+ pBody->getSubItemU1(3, PTN);
+ ERRCODE = m_listener.onCarrierAction(this,
+ DATAID,
+ pszCarrierAction,
+ pszCarrierId,
+ PTN,
+ strError);
+ CAACK = ERRCODE;
+
+ // 鍥炲
+MYREPLY:
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 3, 18, pRecv->getHeader()->systemBytes);
+ pMessage->getBody()->addU1Item(CAACK, "CAACK");
+ ISECS2Item* pErrItem = pMessage->getBody()->addItem();
+ pErrItem->addU4Item(ERRCODE, "ERRCODE");
+ pErrItem->addItem(strError.c_str(), "ERRTEXT");
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+ return 0;
+}
+
// S5F3
int CHsmsPassive::replyEanbleDisableAlarmReport(IMessage* pRecv)
{
@@ -1100,27 +3049,153 @@
return 0;
}
+// S6F23
+int CHsmsPassive::replyPurgeSpooledData(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::U1) ER_PARAM_ERROR;
+ unsigned char RSDC; // 0 - transmit; 1 - purge;
+ pBody->getU1(RSDC);
+ if (RSDC != 0 && RSDC != 1) ER_PARAM_ERROR;
+
+ BYTE ACK = 0; // 0 - ok; 1 - retryable busy; 2 - no spool data;
+ if (m_listActionSpooling.empty()) {
+ ACK = 2;
+ }
+ replyAck(6, 24, pRecv->getHeader()->systemBytes, ACK, "RSDA");
+
+
+ // 涓㈠純
+ if (RSDC == 1) {
+ LOGI("<CHsmsPassive>Purge Spooled Data.");
+ Lock();
+ for (auto item : m_listActionSpooling) {
+ delete item;
+ }
+ m_listActionSpooling.clear();
+ Unlock();
+ }
+ else {
+ LOGI("<CHsmsPassive>Request Spooled Data.");
+ Lock();
+ for (auto item : m_listActionSpooling) {
+ m_listAction.push_back(item);
+ }
+ m_listActionSpooling.clear();
+ Unlock();
+ SetEvent(m_hCimWorkEvent);
+ }
+
+ return 0;
+}
+
+// S7F17 Delete Process Program (PPID list) / S7F18
+int CHsmsPassive::replyDeletePPID(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+
+ bool allOk = true;
+ const bool deleteAll = (pRecv->getBody() == nullptr || pRecv->getBody()->getSubItemSize() == 0);
+ std::vector<std::string> ppids;
+ ISECS2Item* pBody = pRecv->getBody();
+ const int nCount = pBody ? pBody->getSubItemSize() : 0;
+ for (int i = 0; i < nCount; ++i) {
+ const char* pszPPID = nullptr;
+ if (pBody->getSubItemString(i, pszPPID) && pszPPID != nullptr) {
+ ppids.emplace_back(pszPPID);
+ }
+ else {
+ allOk = false;
+ }
+ }
+
+ if (deleteAll || !ppids.empty()) {
+ if (m_listener.onDeletePPID != nullptr) {
+ allOk = m_listener.onDeletePPID(this, ppids);
+ }
+ else {
+ // no handler provided; treat as failure
+ allOk = false;
+ LOGW("<HSMS>DeletePPID request ignored: no onDeletePPID listener");
+ }
+ }
+
+
+ replyAck(7, 18, pRecv->getHeader()->systemBytes, allOk ? BYTE(0) : BYTE(1), "ACKC7");
+ return 0;
+}
+
+// S7F5 Process Program Request -> reply S7F6 with PPID + PPBODY
+int CHsmsPassive::replyProcessProgramRequest(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+ ISECS2Item* pBody = pRecv->getBody();
+ const char* pszPPID = nullptr;
+ if (pBody == nullptr || !pBody->getString(pszPPID) || pszPPID == nullptr) {
+ return ER_PARAM_ERROR;
+ }
+ std::string ppid(pszPPID);
+ std::string ppbody;
+ // 绠�鍗曡仛鍚堬細浠� RecipeManager 鍙栬澶囬厤鏂癸紝鎷兼垚鏂囨湰
+ auto recipeInfo = RecipeManager::getInstance().getRecipeByPPID(ppid);
+ if (!recipeInfo.strPPID.empty()) {
+ for (const auto& dev : recipeInfo.vecDeviceList) {
+ if (!ppbody.empty()) ppbody.append("\n");
+ ppbody.append(dev.strDeviceName);
+ ppbody.append(",");
+ ppbody.append(std::to_string(dev.nRecipeID));
+ ppbody.append(",");
+ ppbody.append(dev.strRecipeName);
+ // 闄勫姞鍙傛暟澶у皬淇℃伅锛堢洰鍓嶇己灏戝叿浣撳弬鏁板垪琛級
+ ppbody.append(",paramsSize=");
+ ppbody.append(std::to_string(dev.paramsRawData.size()));
+ }
+ }
+
+ IMessage* pMessage = nullptr;
+ if (HSMS_Create1Message(pMessage, m_nSessionId, 7, 6, pRecv->getHeader()->systemBytes) != 0 || pMessage == nullptr) {
+ return ER_CREATED_MESSAGE;
+ }
+ ISECS2Item* pRspBody = pMessage->getBody(); // top-level L:2
+ pRspBody->addItem(ppid.c_str(), "PPID");
+ pRspBody->addItem(ppbody.c_str(), "PPBODY");
+ m_pPassive->sendMessage(pMessage);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+ return 0;
+}
+
// S7F19
int CHsmsPassive::replyQueryPPIDList(IMessage* pRecv)
{
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
return ER_NOTSELECT;
}
-
+ if (m_listener.onQueryPPIDList == nullptr) {
+ return ER_NO_PPID_LIST;
+ }
IMessage* pMessage = NULL;
HSMS_Create1Message(pMessage, m_nSessionId, 7, 20, pRecv->getHeader()->systemBytes);
ASSERT(pMessage);
ISECS2Item* pItem = pMessage->getBody();
- pItem->addItem("banana1", "PPID1");
- pItem->addItem("banana2", "PPID2");
- pItem->addF8Item(-123.45, "PPID2");
- pItem->addF4Item(-568.99f, "PPID2");
- pItem->addF8Item(456.456, "PPID2");
- pItem->addF4Item(123.123f, "PPID2");
+ auto ppids = m_listener.onQueryPPIDList(this);
+ for (auto item : ppids) {
+ pItem->addItem(item.c_str(), "PPID");
+ }
+
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S7F20 (SysByte=%u)", pMessage->getHeader()->systemBytes);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
HSMS_Destroy1Message(pMessage);
return 0;
@@ -1157,19 +3232,309 @@
return 0;
}
-// S5F1
-int CHsmsPassive::requestAlarmReport(int ALCD, int ALID, const char* ALTX)
+// S14F9
+int CHsmsPassive::replyCreateObj(IMessage* pRecv)
{
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
return ER_NOTSELECT;
}
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR;
+
+ // 鏄惁鍒涘缓鎴愬姛骞跺噯澶囧洖澶嶆姤鏂�
+ bool bCreateOk = false;
+ IMessage* pReply = NULL;
+ HSMS_Create1Message(pReply, m_nSessionId, 14, 10, ++m_nSystemByte);
+ ASSERT(pReply);
+
+
+
+ // 瑙i噴鏁版嵁锛屽緱鍒癈ontrolJob
+ ISECS2Item* pItemAttrs, * pItemAttr, *pItemAttrData;
+ const char* pszObjSpec, *pszObjType, *pszAttrId, *pszProcessJobId;
+ std::string strObjName, strObjId;
+ if (!pBody->getSubItemString(0, pszObjSpec)) return ER_PARAM_ERROR;
+ if (!pBody->getSubItemString(1, pszObjType)) return ER_PARAM_ERROR;
+
+ pReply->getBody()->addItem(pszObjSpec, "OBJSPEC");
+ ISECS2Item* pReplyItemAttrs = pReply->getBody()->addItem();
+ ISECS2Item* pReplyItemAcks = pReply->getBody()->addItem();
+ ISECS2Item* pReplyItemAck = pReplyItemAcks->addU1Item(0, "OBJACK");
+ ISECS2Item* pReplyItemErrs = pReplyItemAcks->addItem();
+
+ if (!isHostCommandAllowed()) {
+ ISECS2Item* pItemError = pReplyItemErrs->addItem();
+ pItemError->addU4Item(2001, "ERRCODE");
+ pItemError->addItem("rejected - ControlState not OnlineRemote", "ERRTEXT");
+ goto MYREPLY;
+ }
+
+ // 褰撳墠鍙鐞嗙被鍚勪负ControlJob
+ if (_strcmpi(pszObjType, "ControlJob") == 0) {
+
+ // 绫籭d
+ std::regex re("^([^:]+):([^>]+)>");
+ std::smatch match;
+ std::string strObjSpec(pszObjSpec);
+ if (!std::regex_search(strObjSpec, match, re)) {
+ ISECS2Item* pItemError = pReplyItemErrs->addItem();
+ pItemError->addU4Item(2001, "ERRCODE");
+ pItemError->addItem("鍙傛暟鎴栨姤鏂囦笉姝g‘", "ERRTEXT");
+ goto MYREPLY;
+ }
+
+ if (match[1].compare("ControlJob") != 0) {
+ ISECS2Item* pItemError = pReplyItemErrs->addItem();
+ pItemError->addU4Item(2001, "ERRCODE");
+ pItemError->addItem("涓嶆敮鎸佺殑OBJ", "ERRTEXT");
+ goto MYREPLY;
+ }
+ strObjId = match[2];
+
+ // 鍒涘缓绫籆ControlJob
+ SERVO::CControlJob controlJob(strObjId);
+
+ // 绫诲睘鎬�
+ pItemAttrs = pBody->getSubItem(2);
+ if (pItemAttrs == nullptr) return ER_PARAM_ERROR;
+ for (int i = 0; i < pItemAttrs->getSubItemSize(); i++) {
+ pItemAttr = pItemAttrs->getSubItem(i);
+ if (pItemAttr == nullptr) continue;
+ if (!pItemAttr->getSubItemString(0, pszAttrId)) continue;
+ if (_strcmpi(pszAttrId, CJ_ATTR_PRIORITY) == 0) {
+ uint8_t priority;
+ if (pItemAttr->getSubItemU1(1, priority)) {
+ controlJob.setPriority(priority);
+ }
+ }
+ else if (_strcmpi(pszAttrId, CJ_ATTR_PRJOBLIST) == 0) {
+ pItemAttrData = pItemAttr->getSubItem(1);
+ if (pItemAttrData != nullptr && pItemAttrData->getType() == SITYPE::L) {
+ for (int i = 0; i < pItemAttrData->getSubItemSize(); i++) {
+ if (pItemAttrData->getSubItemString(i, pszProcessJobId)) {
+ std::string strProcessJobId(pszProcessJobId);
+ controlJob.addPJ(strProcessJobId);
+ }
+ }
+ }
+ }
+ }
+
+
+ ASSERT(m_listener.onControlJobCreate != nullptr);
+ int nRet = m_listener.onControlJobCreate(this, controlJob);
+ bCreateOk = nRet == 0;
+
+ // 娣诲姞鏂板缓绫荤殑鍚勭灞炴�у埌鍥炲鎶ユ枃涓�
+ if(bCreateOk) {
+ {
+ ISECS2Item* pReplyItemAttr = pReplyItemAttrs->addItem();
+ pReplyItemAttr->addItem(CJ_ATTR_PRIORITY, "ATTRID");
+ pReplyItemAttr->addU1Item(controlJob.priority(), "ATTRDATA");
+ }
+
+ {
+ ISECS2Item* pReplyItemAttr = pReplyItemAttrs->addItem();
+ pReplyItemAttr->addItem(CJ_ATTR_PRJOBLIST, "ATTRID");
+ ISECS2Item* pItemPjs = pReplyItemAttr->addItem();
+ auto pjIds = controlJob.pjIds();
+ for (auto id : pjIds) {
+ pItemPjs->addItem(id.c_str(), "PRJOBID");
+ }
+ }
+ }
+ else {
+ auto issues = controlJob.issues();
+ for (auto i : issues) {
+ ISECS2Item* pItemError = pReplyItemErrs->addItem();
+ pItemError->addU4Item(i.code, "ERRCODE");
+ pItemError->addItem(i.text.c_str(), "ERRTEXT");
+ }
+ }
+ }
+
+
+ else {
+ ISECS2Item* pItemError = pReplyItemErrs->addItem();
+ pItemError->addU4Item(2001, "ERRCODE");
+ pItemError->addItem("涓嶆敮鎸佺殑OBJ", "ERRTEXT");
+ }
+
+
+ // 瀹屽杽鎶ユ枃骞跺洖澶�
+MYREPLY:
+ pReplyItemAck->setU1(bCreateOk ? 0 : 1, "OBJACK");
+ m_pPassive->sendMessage(pReply);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pReply->getHeader()->sessionId, pReply->getHeader()->sType, pReply->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pReply);
+ HSMS_Destroy1Message(pReply);
+
+
+ return 0;
+}
+
+// S16F15
+int CHsmsPassive::replyPRJobMultiCreate(IMessage* pRecv)
+{
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ return ER_NOTSELECT;
+ }
+ ISECS2Item* pBody = pRecv->getBody();
+ if (pBody == nullptr || pBody->getType() != SITYPE::L) ER_PARAM_ERROR;
+
+ if (!isHostCommandAllowed()) {
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 16, 16, ++m_nSystemByte);
+ ASSERT(pMessage);
+ ISECS2Item* pItemPrjobIds = pMessage->getBody()->addItem();
+ ISECS2Item* pItemErrors = pMessage->getBody()->addItem();
+ pItemErrors->addBoolItem(false, "ACKA");
+ ISECS2Item* pItemErrors2 = pItemErrors->addItem();
+ auto err = pItemErrors2->addItem();
+ err->addU4Item(2001, "ERRCODE");
+ err->addItem("rejected - ControlState not OnlineRemote", "ERRTEXT");
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+ return 0;
+ }
+
+
+ // 瑙i噴鏁版嵁锛屽緱鍒癈ProcessJob
+ // 瀹归噺鍓嶇疆妫�鏌ワ細褰撳墠瀹炵幇浠呮敮鎸佸崟鎵� PJ 闆嗗悎锛屽鏋滃凡鏈� PJ/CJ锛岀洿鎺ヨ繑鍥� ACKA=false
+ if (m_pModel != nullptr && !m_pModel->getMaster().isProcessJobsEmpty()) {
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 16, 16, ++m_nSystemByte);
+ ASSERT(pMessage);
+ pMessage->getBody()->addItem(); // PRJOBID list 涓虹┖
+ ISECS2Item* pItemErrors = pMessage->getBody()->addItem();
+ pItemErrors->addBoolItem(false, "ACKA");
+ ISECS2Item* pItemErrors2 = pItemErrors->addItem();
+ auto err = pItemErrors2->addItem();
+ err->addU4Item(1000, "ERRCODE");
+ err->addItem("PJobSpace=0 (existing ProcessJob/ControlJob)", "ERRTEXT");
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+ return 0;
+ }
+
+ ISECS2Item* pItemPjs, * pItemPj,* pItemCarriers, * pItemCarrier, *pItemSlots, *pItemRecipes;
+ unsigned short DATAID;
+ const char* pszPrjobid, *pszMF, *pszCarrierId, *pszRecipeName;
+ std::string strCarrierId;
+ unsigned int len;
+ unsigned char slot, PRRECIPEMETHOD;
+ std::vector<unsigned char> slots;
+ std::vector<SERVO::CProcessJob*> pjs;
+
+ if (!pBody->getSubItemU2(0, DATAID)) return ER_PARAM_ERROR;
+ pItemPjs = pBody->getSubItem(1);
+ if (pItemPjs == nullptr) return ER_PARAM_ERROR;
+ for (int i = 0; i < pItemPjs->getSubItemSize(); i++) {
+ pItemPj = pItemPjs->getSubItem(i);
+ if (pItemPj == nullptr) continue;
+ if (!pItemPj->getSubItemString(0, pszPrjobid)) continue;
+ if (!pItemPj->getSubItemBinary(1, pszMF, len)) continue;
+ pItemCarriers = pItemPj->getSubItem(2);
+ if (pItemCarriers == nullptr) continue;
+ pItemRecipes = pItemPj->getSubItem(3);
+ if (pItemRecipes == nullptr) continue;
+ SERVO::CProcessJob* pj = new SERVO::CProcessJob(pszPrjobid);
+ int size = pItemCarriers->getSubItemSize();
+ for (int j = 0; j < size; j++) {
+ pItemCarrier = pItemCarriers->getSubItem(j);
+ strCarrierId.clear();
+ if (pItemCarrier->getSubItemString(0, pszCarrierId)) {
+ strCarrierId = pszCarrierId;
+ }
+
+ slots.clear();
+ pItemSlots = pItemCarrier->getSubItem(1);
+ if (pItemSlots != nullptr) {
+ int size2 = pItemSlots->getSubItemSize();
+ for (int k = 0; k < size2; k++) {
+ if (pItemSlots->getSubItemU1(k, slot)) {
+ slots.push_back(slot);
+ }
+ }
+ }
+ pj->addCarrier(strCarrierId, slots);
+ }
+ if (pItemRecipes->getSubItemU1(0, PRRECIPEMETHOD)
+ && pItemRecipes->getSubItemString(1, pszRecipeName)) {
+ pj->setRecipe(SERVO::RecipeMethod(PRRECIPEMETHOD), std::string(pszRecipeName));
+ }
+
+ pjs.push_back(pj);
+ }
+
+
+ ASSERT(m_listener.onPRJobMultiCreate != nullptr);
+ int nRet = m_listener.onPRJobMultiCreate(this, pjs);
+
+
+ // 鍥炲鎶ユ枃锛堝湪鏍¢獙/钀藉簱鍚庡啀鍥炲锛屼互渚垮甫涓婄湡瀹炵殑 issues锛�
+ IMessage* pMessage = NULL;
+ HSMS_Create1Message(pMessage, m_nSessionId, 16, 16, ++m_nSystemByte);
+ ASSERT(pMessage);
+ ISECS2Item* pItemPrjobIds = pMessage->getBody()->addItem();
+ ISECS2Item* pItemErrors = pMessage->getBody()->addItem();
+ bool bHasError = false;
+ for (auto p : pjs) {
+ if (p->issues().empty()) {
+ pItemPrjobIds->addItem(p->id().c_str(), "PRJOBID");
+ }
+ else {
+ bHasError = true;
+ }
+ }
+ if (bHasError) {
+ pItemErrors->addBoolItem(false, "ACKA");
+ ISECS2Item* pItemErrors2 = pItemErrors->addItem();
+ for (auto p : pjs) {
+ if (!p->issues().empty()) {
+ ISECS2Item* pItemErr = pItemErrors2->addItem();
+ pItemErr->addU4Item(p->issues()[0].code, "ERRCODE");
+ pItemErr->addItem(("<" + p->id() + ">" + p->issues()[0].text).c_str(), "ERRTEXT");
+ }
+ }
+ }
+ else {
+ pItemErrors->addBoolItem(true, "ACKA");
+ pItemErrors->addItem(); // 绌哄垪琛�
+ }
+ m_pPassive->sendMessage(pMessage);
+ LOGI("<HSMS>[SEND]sessionId:%d, sType:%d systemBytes:%d",
+ pMessage->getHeader()->sessionId, pMessage->getHeader()->sType, pMessage->getHeader()->systemBytes);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
+ HSMS_Destroy1Message(pMessage);
+
+
+ // 閲婃斁鏈夐棶棰�(鏈坊鍔犲埌master)鐨勫唴瀛�
+ for (auto p : pjs) {
+ if(!p->issues().empty()) delete p;
+ }
+ pjs.clear();
+
+ return 0;
+}
+
+// S5F1
+int CHsmsPassive::requestAlarmReport(int ALCD, int ALID, const char* ALTX)
+{
char szALCD[1];
szALCD[0] = ALCD & 0xff;
Lock();
CHsmsAction* pAction = new CHsmsAction(ACTION_ALARM_REPORT, TRUE, m_nActionTimeout);
- m_listAction.push_back(pAction);
+
IMessage* pMessage = NULL;
HSMS_Create1Message(pMessage, m_nSessionId, 5 | REPLY, 1, ++m_nSystemByte);
ASSERT(pMessage);
@@ -1178,51 +3543,200 @@
pItem->addU4Item(ALID, "ALID");
pItem->addItem(ALTX, "ALTX");
pAction->setSendMessage(pMessage);
-
- SetEvent(m_hCimWorkEvent);
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ if (shouldSpool(5, 1)) {
+ m_listActionSpooling.push_back(pAction);
+ }
+ else {
+ LOGI("<HSMS>spooling disabled for S5F1, drop alarm report");
+ delete pAction;
+ }
+ }
+ else {
+ m_listAction.push_back(pAction);
+ SetEvent(m_hCimWorkEvent);
+ }
Unlock();
return ER_NOERROR;
}
// S6F11
-int CHsmsPassive::requestEventReportSend(unsigned int DATAID, unsigned int CEID, const std::vector<std::string>& values)
+static unsigned short DATAID = 0;
+int CHsmsPassive::requestEventReportSend(unsigned int CEID)
{
- if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- return ER_NOTSELECT;
- }
-
SERVO::CCollectionEvent* pEvent = getEvent(CEID);
if (pEvent == nullptr) {
return ER_NO_EVENT;
}
- if (pEvent == nullptr) {
- return ER_UNLINK_EVENT_REPORT;
+ // 瑙﹀彂 PauseEvent 妫�娴嬫々锛堢敱 Master 璐熻矗瀹為檯绛栫暐锛�
+ if (m_pModel != nullptr) {
+ m_pModel->getMaster().handleCollectionEvent(CEID);
}
+
+ SERVO::CReport* pReport = pEvent->getFirstReport();
+
Lock();
CHsmsAction* pAction = new CHsmsAction(ACTION_EVENT_REPORT, TRUE, m_nActionTimeout);
- m_listAction.push_back(pAction);
IMessage* pMessage = NULL;
HSMS_Create1Message(pMessage, m_nSessionId, 6 | REPLY, 11, ++m_nSystemByte);
ASSERT(pMessage);
ISECS2Item* pItem = pMessage->getBody();
- pItem->addU4Item(DATAID, "DATAID");
- pItem->addU4Item(CEID, "CEID");
- ISECS2Item* pItemList1 = pItem->addItem();
- ISECS2Item* pItemList2 = pItemList1->addItem();
- pItemList2->addU4Item(pEvent->getPortID(), "RPTID");
- ISECS2Item* pItemList3 = pItemList2->addItem();
- for (auto item : values) {
- pItemList3->addItem(item.c_str(), "V");
+ // pItem->addU2Item(++DATAID, "DATAID"); // 鏍规嵁鍒殑鏃ュ織鏄剧ずDATAID鎭掍负0锛屾墍浠ユ垜浠厛鐓т娇鐢�0
+ pItem->addU2Item(0, "DATAID");
+ std::string ceidNote("CEID");
+ if (pEvent != nullptr) {
+ auto& name = pEvent->getName();
+ if (!name.empty()) {
+ ceidNote += " -> ";
+ ceidNote += name;
+ }
+ }
+ pItem->addU4Item(CEID, ceidNote.c_str());
+ ISECS2Item* pItemList1 = pItem->addItem(); // L[n] reports
+ if (pReport != nullptr) {
+ ISECS2Item* pItemList2 = pItemList1->addItem();
+ pItemList2->addU4Item(pReport->getReportId(), "RPTID");
+ ISECS2Item* pItemList3 = pItemList2->addItem();
+
+ auto vars = pReport->getVariables();
+ for (auto var : vars) {
+ addVariableValueToItem(pItemList3, var);
+ }
}
pAction->setSendMessage(pMessage);
-
- SetEvent(m_hCimWorkEvent);
+ if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
+ if (shouldSpool(6, 11)) {
+ m_listActionSpooling.push_back(pAction);
+ }
+ else {
+ LOGI("<HSMS>spooling disabled for S6F11, drop event report (CEID=%u)", CEID);
+ delete pAction;
+ }
+ }
+ else {
+ m_listAction.push_back(pAction);
+ SetEvent(m_hCimWorkEvent);
+ }
Unlock();
return ER_NOERROR;
}
+int CHsmsPassive::requestEventReportSend(const char* pszEventName)
+{
+ SERVO::CCollectionEvent* pEvent = nullptr;
+ for (auto e : m_collectionEvents) {
+ if (e->getName().compare(pszEventName) == 0) {
+ pEvent = e;
+ break;
+ }
+ }
+ if (pEvent == nullptr) {
+ return ER_NO_EVENT;
+ }
+ return requestEventReportSend(pEvent->getEventId());
+}
+
+int CHsmsPassive::requestEventReportSend_CarrierID_Readed()
+{
+ return requestEventReportSend("CarrierID_Readed");
+}
+
+int CHsmsPassive::requestEventReportSend_CheckSlotMap()
+{
+ return requestEventReportSend("CheckSlotMap");
+}
+
+int CHsmsPassive::requestEventReportSend_SlotMapVerificationOK()
+{
+ return requestEventReportSend("SlotMapVerificationOK");
+}
+
+int CHsmsPassive::requestEventReportSend_SlotMapVerificationNG()
+{
+ return requestEventReportSend("SlotMapVerificationNG");
+}
+
+int CHsmsPassive::requestEventReportSend_Port_Unload_Ready()
+{
+ return requestEventReportSend("Port_Unload_Ready");
+}
+
+int CHsmsPassive::requestEventReportSend_Port_Load_Ready()
+{
+ return requestEventReportSend("Port_Load_Ready");
+}
+
+int CHsmsPassive::requestEventReportSend_Port_Ready_To_Release()
+{
+ return requestEventReportSend("Port_Ready_To_Release");
+}
+
+int CHsmsPassive::requestEventReportSend_Port_Blocked()
+{
+ return requestEventReportSend("Port_Blocked");
+}
+
+int CHsmsPassive::requestEventReportSend_PJ_Queued()
+{
+ return requestEventReportSend("PJ_Queued");
+}
+
+int CHsmsPassive::requestEventReportSend_PJ_Start()
+{
+ return requestEventReportSend("PJ_Start");
+}
+
+int CHsmsPassive::requestEventReportSend_PJ_End()
+{
+ return requestEventReportSend("PJ_End");
+}
+
+int CHsmsPassive::requestEventReportSend_CJ_Start()
+{
+ return requestEventReportSend("CJ_Start");
+}
+
+int CHsmsPassive::requestEventReportSend_CJ_End()
+{
+ return requestEventReportSend("CJ_End");
+}
+
+int CHsmsPassive::requestEventReportSend_Panel_Start()
+{
+ return requestEventReportSend("Panel_Start");
+}
+
+int CHsmsPassive::requestEventReportSend_Panel_End()
+{
+ return requestEventReportSend("Panel_End");
+}
+
+int CHsmsPassive::requestEventReportSend_OCR_PanelID_Read_OK()
+{
+ return requestEventReportSend("OCR_PanelID_Read_OK");
+}
+
+int CHsmsPassive::requestEventReportSend_LoadPortNotAssoc()
+{
+ return requestEventReportSend("LoadPortNotAssoc");
+}
+
+int CHsmsPassive::requestEventReportSend_ProcessDataReport()
+{
+ return requestEventReportSend("ProcessDataReport");
+}
+
+int CHsmsPassive::requestEventReportSend_SubEqpStart()
+{
+ return requestEventReportSend("SubEqpStart");
+}
+
+int CHsmsPassive::requestEventReportSend_SubEqpEnd()
+{
+ return requestEventReportSend("SubEqpEnd");
+}
--
Gitblit v1.9.3