chenluhua1980
2026-01-13 155cb7fe0dcb564729c6aecdb65815f3f0ed24e2
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -107,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);
}
@@ -258,6 +256,9 @@
   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);
@@ -557,6 +558,95 @@
   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;
@@ -714,6 +804,9 @@
   if (auto v = getVariable(pszName)) {
      v->setValue(value);
   }
   else if (auto dv = getDataVariable(pszName)) {
      dv->setValue(value);
   }
   Unlock();
}
@@ -723,6 +816,9 @@
   if (auto v = getVariable(pszName)) {
      v->setValue(value);
   }
   else if (auto dv = getDataVariable(pszName)) {
      dv->setValue(value);
   }
   Unlock();
}
@@ -731,6 +827,9 @@
   Lock();
   if (auto v = getVariable(pszName)) {
      v->setValue(vars);
   }
   else if (auto dv = getDataVariable(pszName)) {
      dv->setValue(vars);
   }
   Unlock();
}
@@ -1006,6 +1105,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);
         }
@@ -1084,6 +1186,9 @@
   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);
      }
@@ -1100,6 +1205,9 @@
         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);
            }
@@ -2160,6 +2268,49 @@
   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)
{
@@ -2318,32 +2469,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) {
@@ -2367,18 +2528,17 @@
   }
   // 要设置的常量表表
   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;
         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;
@@ -2387,13 +2547,19 @@
            }
         }
      }
   // 更新内存表并落盘
   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;
   }
   // 交由上层应用来保存和设置机器常量值
   std::vector<unsigned int> ecvs;
   if (m_listener.onEQConstantSend != nullptr) {
      m_listener.onEQConstantSend(this, eqcs);
   }
   if (changed && !m_strEquipmentConstantFilepath.empty()) {
      writeEquipmentConstantsToFile(m_strEquipmentConstantFilepath);
   }