| | |
| | | #include "CMaster.h" |
| | | #include <future> |
| | | #include <vector> |
| | | #include <algorithm> |
| | | #include "RecipeManager.h" |
| | | #include <fstream> |
| | | #include "SerializeUtil.h" |
| | |
| | | unlock(); |
| | | } |
| | | }; |
| | | listener.onProcessStateChanged = [&](void* pEquipment, int slotNo, PROCESS_STATE state) -> void { |
| | | listener.onProcessStateChanged = [&](void* pEquipment, int slotNo, PROCESS_STATE prevState, PROCESS_STATE state) -> void { |
| | | ASSERT(1 <= slotNo && slotNo <= 8); |
| | | int eqid = ((CEquipment*)pEquipment)->getID(); |
| | | CGlass* pGlass = ((CEquipment*)pEquipment)->getGlassFromSlot(slotNo); |
| | |
| | | } |
| | | |
| | | if (m_listener.onProcessStateChanged != nullptr) { |
| | | m_listener.onProcessStateChanged(this, (CEquipment*)pEquipment, slotNo, state); |
| | | m_listener.onProcessStateChanged(this, (CEquipment*)pEquipment, slotNo, prevState, state); |
| | | } |
| | | }; |
| | | listener.onProcessDataReport = [&](void* pEquipment, const std::vector<CParam>& params) { |
| | | if (m_listener.onProcessDataReport != nullptr) { |
| | | m_listener.onProcessDataReport(this, (CEquipment*)pEquipment, params); |
| | | } |
| | | }; |
| | | listener.onMapMismatch = [&](void* pEquipment, short scanMap, short downMap) { |
| | |
| | | strOut.append(szBuffer); |
| | | } |
| | | LOGD("<CMaster-%s>SVDataReport:%s", ((CEquipment*)pEquipment)->getName().c_str(), strOut.c_str()); |
| | | |
| | | if (m_listener.onSVDataReport != nullptr) { |
| | | m_listener.onSVDataReport(this, (CEquipment*)pEquipment, params); |
| | | } |
| | | }; |
| | | listener.onPanelDataReport = [&](void* pEquipment, void* pContext) { |
| | | LOGD("<CMaster-%s>onPanelDataReport", ((CEquipment*)pEquipment)->getName().c_str()); |
| | |
| | | } |
| | | } |
| | | |
| | | }; |
| | | listener.onReceivedJob = [&](void* pEquipment, int port, CJobDataS* pJobDataS) { |
| | | if (m_listener.onJobReceived != nullptr) { |
| | | m_listener.onJobReceived(this, (CEquipment*)pEquipment, port, pJobDataS); |
| | | } |
| | | }; |
| | | pEquipment->setListener(listener); |
| | | pEquipment->setCcLink(&m_cclink); |
| | |
| | | static bool inited = false; |
| | | static SERVO::CGlass simGlass; |
| | | static SERVO::CVcrEventReport simVcr; |
| | | static SERVO::CProcessJob simPj("SIM_PJ_001"); |
| | | static SERVO::CControlJob simCj("SIM_CJ_001"); |
| | | static SERVO::CProcessJob simPj("PJ1001"); |
| | | static SERVO::CControlJob simCj("CJ5007"); |
| | | |
| | | if (!inited) { |
| | | inited = true; |
| | |
| | | } |
| | | }; |
| | | auto fireProcessState = [&](SERVO::CEquipment* pEq, int slotNo, SERVO::PROCESS_STATE st) { |
| | | if (m_listener.onProcessStateChanged != nullptr && pEq != nullptr) { |
| | | m_listener.onProcessStateChanged(this, pEq, slotNo, st); |
| | | // Drive equipment state so listeners receive prev/current states consistently. |
| | | if (pEq != nullptr) { |
| | | pEq->fireSetProcessState(slotNo, st); |
| | | } |
| | | }; |
| | | |
| | |
| | | fireLoadPortStatus(PORT_LOAD_READY); |
| | | fireLoadPortStatus(PORT_EMPTY); // will also raise LoadPortNotAssoc via Model |
| | | break; |
| | | case 24: { // 模拟 SV Data(示例:Bonder1) |
| | | SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1); |
| | | if (pEq != nullptr && m_listener.onSVDataReport != nullptr) { |
| | | static int counter = 0; |
| | | ++counter; |
| | | std::vector<CParam> params; |
| | | params.emplace_back("MockSV_Temp", "1", "C", 25 + (counter % 5)); |
| | | params.emplace_back("MockSV_Pressure", "2", "kPa", 100 + (counter % 3)); |
| | | params.emplace_back("MockSV_Speed", "3", "mm/s", 50 + (counter % 7)); |
| | | m_listener.onSVDataReport(this, pEq, params); |
| | | LOGI("<Master>SIM_EAP step24: mock SVData (Bonder1), params=%zu", params.size()); |
| | | } |
| | | break; |
| | | } |
| | | case 25: { // 模拟 Process Data(示例:Bonder1) |
| | | SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1); |
| | | if (pEq != nullptr && m_listener.onProcessDataReport != nullptr) { |
| | | static int counter = 0; |
| | | ++counter; |
| | | std::vector<CParam> params; |
| | | params.emplace_back("MockProc_CycleTime", "1", "s", 30 + (counter % 4)); |
| | | params.emplace_back("MockProc_MaxTemp", "2", "C", 200 + (counter % 6)); |
| | | params.emplace_back("MockProc_Result", "3", "", (counter % 2) ? 1 : 0); |
| | | m_listener.onProcessDataReport(this, pEq, params); |
| | | LOGI("<Master>SIM_EAP step25: mock ProcessData (Bonder1), params=%zu", params.size()); |
| | | } |
| | | break; |
| | | } |
| | | default: |
| | | break; |
| | | } |
| | |
| | | |
| | | |
| | | this->saveState(); |
| | | if (m_listener.onControlJobChanged) { |
| | | m_listener.onControlJobChanged(this); |
| | | } |
| | | |
| | | return (int)m_processJobs.size(); |
| | | } |
| | |
| | | |
| | | bool CMaster::ceidDefined(uint32_t ceid) const |
| | | { |
| | | return true; |
| | | if (m_allowedCeids.empty()) return true; // backward compatible: treat as all allowed when not configured |
| | | return m_allowedCeids.find(ceid) != m_allowedCeids.end(); |
| | | } |
| | | |
| | | void CMaster::handleCollectionEvent(uint32_t ceid) |
| | | { |
| | | // 遍历当前 PJ,命中 pauseEvents 时可在此扩展暂停动作 |
| | | for (auto pj : m_processJobs) { |
| | | if (pj == nullptr) continue; |
| | | const auto& pauseList = pj->pauseEvents(); |
| | | if (std::find(pauseList.begin(), pauseList.end(), ceid) != pauseList.end()) { |
| | | LOGW("<Master>PauseEvent hit: CEID=%u, PJ=%s, state=%d", ceid, pj->id().c_str(), (int)pj->state()); |
| | | // TODO: 衔接具体暂停策略(如暂停 PJ/CJ、停止调度/搬送),此处仅留桩位 |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CMaster::setAllowedCeids(const std::vector<unsigned int>& ceids) |
| | | { |
| | | m_allowedCeids.clear(); |
| | | m_allowedCeids.reserve(ceids.size()); |
| | | for (auto id : ceids) { |
| | | m_allowedCeids.insert(id); |
| | | } |
| | | } |
| | | |
| | | bool CMaster::saveState() const |