chenluhua1980
2026-01-26 d7c88780e1df54f34563d60bd7fa01011d2eef03
SourceCode/Bond/Servo/CMaster.cpp
@@ -62,6 +62,7 @@
      m_ullStartTime = 0;
      m_ullRunTime = 0;
      m_state = MASTERSTATE::READY;
      m_curveMode = CurveMode::Production;
      m_pActiveRobotTask = nullptr;
      m_nLastError = ER_CODE_NOERROR;
      m_isCompareMapsBeforeProceeding = FALSE;
@@ -117,6 +118,7 @@
         ::CloseHandle(m_hEventDispatchThreadExit[1]);
         m_hEventDispatchThreadExit[1] = nullptr;
      }
      DeleteCriticalSection(&m_criticalSection);
   }
@@ -280,6 +282,36 @@
      return 0;
   }
   void CMaster::setCurveMode(CurveMode mode)
   {
      if (m_curveMode == mode) {
         return;
      }
      m_curveMode = mode;
      if (m_pCollector != nullptr) {
         const uint32_t mids[] = {
            MID_Bonder1, MID_Bonder2,
            MID_VacuumBakeA, MID_VacuumBakeB,
            MID_BakeCoolingA, MID_BakeCoolingB
         };
         for (uint32_t mid : mids) {
            if (mode == CurveMode::EmptyChamber) {
               m_pCollector->batchStart(mid, "EMPTY_CHAMBER", 30 * 60 * 1000ULL); // 空腔模式:启动采样批次
            }
            else {
               m_pCollector->batchStop(mid);
               m_pCollector->buffersClear(mid); // 切回生产模式,清掉空腔数据
            }
         }
      }
      LOGI("<Master>CurveMode=%s", mode == CurveMode::EmptyChamber ? "EmptyChamber" : "Production");
   }
   CurveMode CMaster::getCurveMode() const
   {
      return m_curveMode;
   }
   int CMaster::term()
   {
      SetEvent(m_hEventReadBitsThreadExit[0]);
@@ -305,6 +337,13 @@
      }
      m_listEquipment.clear();
      // release manual-remove buffer before glass pool is torn down
      for (auto* pGlass : m_bufGlass) {
         if (pGlass != nullptr) {
            pGlass->release();
         }
      }
      m_bufGlass.clear();
      if (m_pCollector != nullptr) {
         m_pCollector->stopLoop();
@@ -1699,7 +1738,8 @@
               m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER ||
               m_state == MASTERSTATE::RUNNING_BATCH ||
               m_state == MASTERSTATE::STARTING);
         if (!allowSvLog) {
         const bool allowCurve = allowSvLog || (m_curveMode == CurveMode::EmptyChamber);
         if (!allowCurve) {
            return;
         }
         CSVData* pSVData = (CSVData*)pData;
@@ -1753,18 +1793,23 @@
               int paramIndex = mapping.first;
               int channel = mapping.second;
               if (paramIndex < params.size() && channel - 1 < vacuumbakeTypes.size()) {
               if (paramIndex < params.size()) {
                  auto& param = params.at(paramIndex);
                  double value = param.getDoubleValue();
                  const std::string& dataType = vacuumbakeTypes[channel - 1];
                  const std::string& paramName = param.getName();
                  const char slotTag = !paramName.empty() ? paramName[0] : '\0';
                  const int typeIndex = (slotTag == 'B') ? (channel - 8) : (channel - 1);
                  if (typeIndex < 0 || typeIndex >= (int)vacuumbakeTypes.size()) {
                     continue;
                  }
                  const int pushChannel = typeIndex + 1;
                  const std::string& dataType = vacuumbakeTypes[typeIndex];
                  if (m_pCollector != nullptr) {
                     if (slotTag == 'A')
                        m_pCollector->buffersPush(SlotToMid(eqid, 1), channel, ts, value);
                        m_pCollector->buffersPush(SlotToMid(eqid, 1), pushChannel, ts, value);
                     else if (slotTag == 'B')
                        m_pCollector->buffersPush(SlotToMid(eqid, 2), channel, ts, value);
                        m_pCollector->buffersPush(SlotToMid(eqid, 2), pushChannel, ts, value);
                  }
                  // 根据腔体前缀写入对应 Slot 的玻璃
@@ -1798,20 +1843,25 @@
               int paramIndex = mapping.first;
               int channel = mapping.second;
               if (paramIndex < params.size() && channel - 1 < coolingTypes.size()) {
               if (paramIndex < params.size()) {
                  auto& param = params.at(paramIndex);
                  double value = param.getDoubleValue();
                  const std::string& dataType = coolingTypes[channel - 1];
                  const std::string& paramName = param.getName();
                  const char slotTag = !paramName.empty() ? paramName[0] : '\0';
                  const bool paramIsBake = paramName.find("烘烤") != std::string::npos;
                  const bool paramIsCooling = paramName.find("冷却") != std::string::npos;
                  const int typeIndex = (slotTag == 'B') ? (channel - 7) : (channel - 1);
                  if (typeIndex < 0 || typeIndex >= (int)coolingTypes.size()) {
                     continue;
                  }
                  const int pushChannel = typeIndex + 1;
                  const std::string& dataType = coolingTypes[typeIndex];
                  if (m_pCollector != nullptr && paramIsBake) {
                     if (slotTag == 'A')
                        m_pCollector->buffersPush(SlotToMid(eqid, 1), channel, ts, value);
                        m_pCollector->buffersPush(SlotToMid(eqid, 1), pushChannel, ts, value);
                     else if (slotTag == 'B')
                        m_pCollector->buffersPush(SlotToMid(eqid, 3), channel, ts, value);
                        m_pCollector->buffersPush(SlotToMid(eqid, 3), pushChannel, ts, value);
                  }
                  if (!dataType.empty()) {
@@ -3519,6 +3569,15 @@
      if (pSlot == nullptr) return false;
      CGlass* pGlass = (CGlass*)pSlot->getContext();
      if (pGlass == nullptr) return false;
      // Buffer 上限为 1:新搬出时丢弃旧的
      if (!m_bufGlass.empty()) {
         for (auto* oldGlass : m_bufGlass) {
            if (oldGlass != nullptr) oldGlass->release();
         }
         m_bufGlass.clear();
      }
      m_bufGlass.push_back(pGlass);
      pGlass->addRef();
      pSlot->setContext(nullptr);
@@ -3622,6 +3681,17 @@
            m_pCollector->buffersSetChannelName(MID_BakeCoolingA, i + 1, coolingTypes[i].c_str());
            m_pCollector->buffersSetChannelName(MID_BakeCoolingB, i + 1, coolingTypes[i].c_str());
         }
         if (m_curveMode == CurveMode::EmptyChamber) {
            const uint32_t mids[] = {
               MID_Bonder1, MID_Bonder2,
               MID_VacuumBakeA, MID_VacuumBakeB,
               MID_BakeCoolingA, MID_BakeCoolingB
            };
            for (uint32_t mid : mids) {
               m_pCollector->batchStart(mid, "EMPTY_CHAMBER", 10 * 60 * 1000ULL);
            }
         }
      }
   }