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 | 1550 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 1,438 insertions(+), 112 deletions(-)
diff --git a/SourceCode/Bond/Servo/HsmsPassive.cpp b/SourceCode/Bond/Servo/HsmsPassive.cpp
index 722eacd..c2359b3 100644
--- a/SourceCode/Bond/Servo/HsmsPassive.cpp
+++ b/SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -3,6 +3,7 @@
#include "Log.h"
#include "Model.h"
#include "Common.h"
+#include "RecipeManager.h"
#include <time.h>
#include <iostream>
#include <time.h>
@@ -11,11 +12,69 @@
#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)
{
@@ -48,8 +107,6 @@
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);
}
@@ -110,23 +167,35 @@
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(), "SV");
+ pParent->addU1Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
break;
case SERVO::SVFromat::U2:
- pParent->addU2Item((unsigned char)pVariable->getIntValue(), "SV");
+ pParent->addU2Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
break;
case SERVO::SVFromat::I2:
- pParent->addI2Item((unsigned char)pVariable->getIntValue(), "SV");
+ pParent->addI2Item((unsigned char)pVariable->getIntValue(), svNote.c_str());
break;
case SERVO::SVFromat::A20:
case SERVO::SVFromat::A50:
- pParent->addItem(pVariable->getValue().c_str(), "SV");
+ pParent->addItem(pVariable->getValue().c_str(), svNote.c_str());
break;
case SERVO::SVFromat::L:
pItemList = pParent->addItem();
@@ -153,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;
}
@@ -193,7 +289,7 @@
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)) {
@@ -370,15 +466,222 @@
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();
}
@@ -404,8 +707,46 @@
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()
@@ -414,6 +755,14 @@
delete item;
}
m_variabels.clear();
+}
+
+void CHsmsPassive::clearAllDataVariabel()
+{
+ for (auto item : m_dataVariabels) {
+ delete item;
+ }
+ m_dataVariabels.clear();
}
CStringA WideToUtf8(const CStringW& ws)
@@ -471,26 +820,46 @@
void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
{
- auto v = getVariable(pszName);
- if (v != nullptr) {
+ // 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)
{
- auto v = getVariable(pszName);
- if (v != nullptr) {
+ 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)
{
- auto v = getVariable(pszName);
- if (v != nullptr) {
+ 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)
@@ -509,8 +878,8 @@
Lock();
int maxId = 0;
for (auto v : m_variabels) {
- if (v != nullptr && v->getVarialbleId() > maxId) {
- maxId = v->getVarialbleId();
+ if (v != nullptr && static_cast<int>(v->getVarialbleId()) > maxId) {
+ maxId = static_cast<int>(v->getVarialbleId());
}
}
outId = maxId + 1;
@@ -547,6 +916,75 @@
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)
@@ -595,6 +1033,53 @@
}
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;
}
@@ -710,6 +1195,9 @@
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);
}
@@ -732,6 +1220,17 @@
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)
@@ -760,18 +1259,66 @@
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);
}
-void CHsmsPassive::clearAllReport()
+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)
@@ -829,6 +1376,9 @@
int CHsmsPassive::loadCollectionEvents(const char* pszFilepath)
{
+ m_strCollectionEventFilepath = pszFilepath;
+ m_bCollectionUtf8 = false;
+ m_bCollectionUtf8Bom = false;
CFile file;
if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
return -1;
@@ -851,6 +1401,8 @@
// 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
@@ -880,6 +1432,7 @@
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;
};
@@ -898,7 +1451,8 @@
return -1;
}
- std::wregex pattern(L"^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
+ // 鍏佽 Attached RPTID 涓虹┖锛�()
+ std::wregex pattern(L"^\\d+,[^,]*,[^,]*,\\(\\d*(,\\d+)*\\).*"); // 鍖归厤浠ユ暟瀛�+閫楀彿寮�澶寸殑瀛楃涓�
std::vector<SERVO::CCollectionEvent*> events;
int index, last;
CStringW strLine, strRPTIDs;
@@ -968,6 +1522,64 @@
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()
{
for (auto item : m_collectionEvents) {
@@ -1009,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;
@@ -1032,7 +1700,7 @@
*/
};
auto onRecvSysMessage = [&](void* pFrom, IMessage* pMessage) -> void {
- LOGI("<HSMS>onRecvSysMessage:sessionId:%d, sType:%d systemBytes:%d",
+ 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) {
@@ -1059,13 +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);
@@ -1112,6 +1789,12 @@
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);
}
@@ -1151,7 +1834,12 @@
return -1;
}
- int nBufSize = file.GetLength();
+ 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();
@@ -1204,11 +1892,27 @@
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;
}
@@ -1223,6 +1927,33 @@
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;
@@ -1245,7 +1976,53 @@
m_listActionSpooling.push_back(pAction);
}
- return index + nRet;
+ // 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()
@@ -1264,15 +2041,34 @@
Unlock();
while (!list.empty()) {
+ CHsmsAction* pAction = nullptr;
Lock();
- CHsmsAction* pAction = list.front();
- if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- m_listActionSpooling.push_back(pAction);
- Unlock();
- continue;
- }
+ pAction = list.front();
Unlock();
list.pop_front();
+
+ 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()) {
@@ -1284,7 +2080,8 @@
ASSERT(pMessage);
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ 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) {
@@ -1309,7 +2106,8 @@
ASSERT(pMessage);
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS> [SEND] SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ LOGI("<HSMS>[SEND]SysByte=%u sessionId:%d", pMessage->getHeader()->systemBytes, pMessage->getHeader()->sessionId);
+ LogSecsMessageBrief("<HSMS>[SEND]", pMessage);
}
}
@@ -1331,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);
}
@@ -1372,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;
@@ -1433,7 +2235,9 @@
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;
@@ -1451,18 +2255,25 @@
ASSERT(pMessage);
unsigned char SVU1 = 0;
- unsigned int SVID = 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->getSubItemU4(0, SVID)) {
- 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(SVID);
+ SERVO::CVariable* pVariable = getVariable((int)SVID);
if (pVariable == nullptr) {
pMessage->getBody()->addU1Item(SVU1, "SV");
goto MYREPLY;
@@ -1471,12 +2282,273 @@
MYREPLY:
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;
+}
+
+// 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
@@ -1487,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) {
@@ -1520,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;
@@ -1534,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);
}
@@ -1616,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;
}
@@ -1642,8 +2732,10 @@
}
}
- removeReport(rptid);
- if (!vids.empty()) {
+ if (vids.empty()) {
+ deleteReport(rptid);
+ } else {
+ removeReport(rptid);
pReport = defineReport(rptid, vids);
}
@@ -1672,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++) {
@@ -1685,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->getFirstPortID());
+ unsigned int reportId = item->getFirstReportID();
+ if(reportId != 0)
+ LOGI("=== ceid:%d, prtid:%d", item->getEventId(), reportId);
+ else
+ LOGI("=== ceid:%d, prtid:--", item->getEventId());
}
MYREPLY:
@@ -1807,9 +2911,12 @@
// 娓呯┖鎵�鏈�
if (pBody->getSubItemSize() == 0) {
- m_spoolingConfig.clear();
+ 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++) {
@@ -1818,26 +2925,34 @@
unsigned char STRID, FCNID;
pStreamItem->getSubItemU1(0, STRID);
ISECS2Item* pFcnItemList = pStreamItem->getSubItem(1);
- if (pFcnItemList->getSubItemSize() == 0) {
- m_spoolingConfig[STRID].clear();
+ 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_spoolingConfig[STRID].insert(FCNID);
+ m_spoolBlacklistByStream[STRID].insert(FCNID);
}
}
}
// 鎵撳嵃楠岃瘉缁撴灉
- for (auto s : m_spoolingConfig) {
- LOGI("====> stream:%d", s.first);
- for (auto f : s.second) {
- LOGI("function:%d", f);
+ 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, 42, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
+ replyAck(2, 44, pRecv->getHeader()->systemBytes, BYTE(0), "ERACK");
return 0;
}
@@ -1858,14 +2973,21 @@
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 int DATAID;
+ unsigned short DATAID;
unsigned char PTN;
const char* pszCarrierAction, *pszCarrierId;
- pBody->getSubItemU4(0, DATAID);
+ pBody->getSubItemU2(0, DATAID);
pBody->getSubItemString(1, pszCarrierAction);
pBody->getSubItemString(2, pszCarrierId);
pBody->getSubItemU1(3, PTN);
@@ -1886,7 +3008,9 @@
pErrItem->addU4Item(ERRCODE, "ERRCODE");
pErrItem->addItem(strError.c_str(), "ERRTEXT");
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S3F18 (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;
@@ -1946,6 +3070,7 @@
// 涓㈠純
if (RSDC == 1) {
+ LOGI("<CHsmsPassive>Purge Spooled Data.");
Lock();
for (auto item : m_listActionSpooling) {
delete item;
@@ -1954,6 +3079,7 @@
Unlock();
}
else {
+ LOGI("<CHsmsPassive>Request Spooled Data.");
Lock();
for (auto item : m_listActionSpooling) {
m_listAction.push_back(item);
@@ -1963,6 +3089,86 @@
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;
}
@@ -1987,7 +3193,9 @@
}
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;
@@ -2054,6 +3262,13 @@
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) {
@@ -2151,7 +3366,9 @@
MYREPLY:
pReplyItemAck->setU1(bCreateOk ? 0 : 1, "OBJACK");
m_pPassive->sendMessage(pReply);
- LOGI("<HSMS>[SECS Msg SEND]S14F10 (SysByte=%u)", pReply->getHeader()->systemBytes);
+ 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);
@@ -2167,10 +3384,49 @@
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 int DATAID;
+ unsigned short DATAID;
const char* pszPrjobid, *pszMF, *pszCarrierId, *pszRecipeName;
std::string strCarrierId;
unsigned int len;
@@ -2178,7 +3434,7 @@
std::vector<unsigned char> slots;
std::vector<SERVO::CProcessJob*> pjs;
- if (!pBody->getSubItemU4(0, DATAID)) return ER_PARAM_ERROR;
+ 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++) {
@@ -2219,11 +3475,12 @@
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);
@@ -2249,8 +3506,14 @@
}
}
}
+ else {
+ pItemErrors->addBoolItem(true, "ACKA");
+ pItemErrors->addItem(); // 绌哄垪琛�
+ }
m_pPassive->sendMessage(pMessage);
- LOGI("<HSMS>[SECS Msg SEND]S16F16 (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);
@@ -2281,7 +3544,13 @@
pItem->addItem(ALTX, "ALTX");
pAction->setSendMessage(pMessage);
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- m_listActionSpooling.push_back(pAction);
+ 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);
@@ -2293,18 +3562,19 @@
}
// S6F11
-static unsigned int DATAID = 1;
+static unsigned short DATAID = 0;
int CHsmsPassive::requestEventReportSend(unsigned int CEID)
{
SERVO::CCollectionEvent* pEvent = getEvent(CEID);
if (pEvent == nullptr) {
return ER_NO_EVENT;
}
+ // 瑙﹀彂 PauseEvent 妫�娴嬫々锛堢敱 Master 璐熻矗瀹為檯绛栫暐锛�
+ if (m_pModel != nullptr) {
+ m_pModel->getMaster().handleCollectionEvent(CEID);
+ }
SERVO::CReport* pReport = pEvent->getFirstReport();
- if (pReport == nullptr) {
- return ER_UNLINK_EVENT_REPORT;
- }
Lock();
@@ -2313,20 +3583,37 @@
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(pReport->getReportId(), "RPTID");
- ISECS2Item* pItemList3 = pItemList2->addItem();
+ // 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);
+ auto vars = pReport->getVariables();
+ for (auto var : vars) {
+ addVariableValueToItem(pItemList3, var);
+ }
}
pAction->setSendMessage(pMessage);
if (m_pPassive == NULL || STATE::SELECTED != m_pPassive->getState()) {
- m_listActionSpooling.push_back(pAction);
+ 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);
@@ -2357,6 +3644,21 @@
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");
@@ -2365,6 +3667,11 @@
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()
@@ -2412,5 +3719,24 @@
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