LAPTOP-SNT8I5JK\Boounion
2025-08-21 549decf91ef988814913cddc86f5c4e006b277e7
SourceCode/Bond/Servo/CMaster.cpp
@@ -3,6 +3,9 @@
#include "CMaster.h"
#include <future>
#include <vector>
#include "RecipeManager.h"
#include <fstream>
#include "SerializeUtil.h"
namespace SERVO {
@@ -57,11 +60,22 @@
      m_bContinuousTransfer = false;
      m_nContinuousTransferCount = 0;
      m_nContinuousTransferStep = CTStep_Unknow;
      m_pControlJob = nullptr;
      InitializeCriticalSection(&m_criticalSection);
   }
   CMaster::~CMaster()
   {
      // 释放Job相关
      for (auto item : m_processJobs) {
         delete item;
      }
      m_processJobs.clear();
      if (m_pControlJob != nullptr) {
         delete m_pControlJob;
         m_pControlJob = nullptr;
      }
      if (m_hEventReadBitsThreadExit[0] != nullptr) {
         ::CloseHandle(m_hEventReadBitsThreadExit[0]);
         m_hEventReadBitsThreadExit[0] = nullptr;
@@ -825,7 +839,7 @@
            if ((m_nContinuousTransferStep == CTStep_Unknow || m_nContinuousTransferStep == CTStep_Aligner_Fliper)
               &&!rmd.armState[0] && !pBonder1->hasBondClass()) {
               m_pActiveRobotTask = createTransferTask_continuous_transfer(pFliper,
                  0, pBonder1, 1, 2);
                  0, pBonder1, 1);
               if (m_pActiveRobotTask != nullptr) {
                  m_nContinuousTransferStep = CTStep_Fliper_Bonder1;
                  LOGI("<ContinuousTransfer>千传测试,开始搬送任务(Fliper(G2) -> Bonder1)...");
@@ -1146,6 +1160,15 @@
   }
   CEquipment* CMaster::getEquipment(int id)
   {
      for (auto item : m_listEquipment) {
         if (item->getID() == id) return item;
      }
      return nullptr;
   }
   CEquipment* CMaster::getEquipment(int id) const
   {
      for (auto item : m_listEquipment) {
         if (item->getID() == id) return item;
@@ -1831,4 +1854,202 @@
   {
      m_nContinuousTransferCount = round;
   }
   int CMaster::setProcessJobs(std::vector<CProcessJob*>& pjs)
   {
      std::vector<SERVO::CProcessJob*> temp;
      for (auto p : pjs) {
         if (p->validate(*this)) {
            p->queue();
            temp.push_back(p);
         }
      }
      m_processJobs = temp;
      this->saveState();
      return m_processJobs.size();
   }
   std::vector<CProcessJob*>& CMaster::getProcessJobs()
   {
      return m_processJobs;
   }
   CProcessJob* CMaster::getProcessJob(const std::string& id)
   {
      for (auto item : m_processJobs) {
         if (item->id().compare(id) == 0) return item;
      }
      return nullptr;
   }
   int CMaster::setControlJob(CControlJob& controlJob)
   {
      // 回调:是否参创建ControlJob
      auto canCreateCjFn = [&](uint32_t& cc, std::string& mm) -> bool {
         if (m_pControlJob != nullptr) {
            cc = 1100;
            mm = "当前ControlJob未结批,不能创建新的ControlJob";
            return false;
         }
         return true;
      };
      // 回调:是否存在
      auto pjExists = [&](const std::string& id) -> bool {
         return getProcessJob(id) != nullptr;
      };
      // 回调:是否可加入 CJ(这里定义:必须是 Queued)
      auto pjJoinable = [&](const std::string& id) -> bool {
         auto pj = getProcessJob(id);
         if (pj == nullptr) return false;
         return pj->state() == PJState::Queued;
      };
      bool bRet = controlJob.validateForCreate(canCreateCjFn, pjExists, pjJoinable);
      if (!bRet) return -1;
      std::vector<CProcessJob*> temps;
      m_pControlJob = new CControlJob(controlJob);
      auto pjIds = controlJob.pjIds();
      for (auto id : pjIds) {
         auto pj = getProcessJob(id);
         if (pj != nullptr) {
            temps.push_back(pj);
         }
      }
      m_pControlJob->setPJs(temps);
      this->saveState();
      return 0;
   }
   CLoadPort* CMaster::getPortWithCarrierId(const std::string& carrierId) const
   {
      CLoadPort* pPort;
      int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4};
      for (int i = 0; i < 4; i++) {
         pPort = (CLoadPort*)getEquipment(eqid[i]);
         ASSERT(pPort);
         if (pPort->getCassetteId().compare(carrierId) == 0) return pPort;
      }
      return nullptr;
   }
   bool CMaster::isProcessJobsEmpty() const
   {
      return m_processJobs.empty();
   }
   bool CMaster::recipeExists(const std::string& ppid) const
   {
      std::vector<std::string> vecRecipe = RecipeManager::getInstance().getAllPPID();
      bool exists = std::find(vecRecipe.begin(), vecRecipe.end(), ppid) != vecRecipe.end();
      return exists;
   }
   bool CMaster::carrierPresent(const std::string& carrierId) const
   {
      CLoadPort* pPort = getPortWithCarrierId(carrierId);
      return pPort != nullptr;
   }
   bool CMaster::slotUsable(const std::string& carrierId, uint16_t slot) const
   {
      CLoadPort* pPort = getPortWithCarrierId(carrierId);
      if(pPort == nullptr) return false;
      CSlot* pSlot = pPort->getSlot(slot);
      if (pSlot == nullptr) return false;
      return pSlot->isEnable();
   }
   bool CMaster::ceidDefined(uint32_t ceid) const
   {
      return true;
   }
   bool CMaster::saveState() const
   {
      std::ofstream ofs(m_strStatePath, std::ios::binary);
      if (!ofs) return false;
      // 文件头
      uint32_t magic = 0x4D415354; // 'MAST'
      uint16_t version = 1;
      ofs.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
      ofs.write(reinterpret_cast<const char*>(&version), sizeof(version));
      // 保存 ControlJob
      bool hasCJ = (m_pControlJob != nullptr);
      ofs.write(reinterpret_cast<const char*>(&hasCJ), sizeof(hasCJ));
      if (hasCJ) {
         m_pControlJob->serialize(ofs);
      }
      // 保存 ProcessJob 列表
      uint32_t count = static_cast<uint32_t>(m_processJobs.size());
      ofs.write(reinterpret_cast<const char*>(&count), sizeof(count));
      for (const auto& job : m_processJobs) {
         job->serialize(ofs);
      }
      // 以后可以在这里追加新字段
      return true;
   }
   bool CMaster::loadState(const std::string& path)
   {
      // 保存文件路径
      m_strStatePath = path;
      std::ifstream ifs(path, std::ios::binary);
      if (!ifs) return false;
      // 文件头
      uint32_t magic = 0;
      uint16_t version = 0;
      ifs.read(reinterpret_cast<char*>(&magic), sizeof(magic));
      ifs.read(reinterpret_cast<char*>(&version), sizeof(version));
      if (magic != 0x4D415354) {
         // 文件不合法
         return false;
      }
      if (m_pControlJob != nullptr) {
         delete m_pControlJob;
         m_pControlJob = nullptr;
      }
      // 读取 ControlJob
      bool hasCJ = false;
      ifs.read(reinterpret_cast<char*>(&hasCJ), sizeof(hasCJ));
      if (hasCJ) {
         m_pControlJob = new CControlJob();
         if (!CControlJob::deserialize(ifs, *m_pControlJob)) return false;
      }
      // 读取 ProcessJob 列表
      uint32_t count = 0;
      ifs.read(reinterpret_cast<char*>(&count), sizeof(count));
      m_processJobs.clear();
      for (uint32_t i = 0; i < count; i++) {
         CProcessJob* pProcessJob = new CProcessJob();
         if (!CProcessJob::deserialize(ifs, *pProcessJob)) return false;
         m_processJobs.push_back(pProcessJob);
      }
      // 如果版本升级,可在这里判断 version 来加载新字段
      return true;
   }
}