| | |
| | | } |
| | | m_pControlJob->abort(description); |
| | | |
| | | // 先上报一次状态变化(便于 PrJobAbort 触发) |
| | | if (m_listener.onControlJobChanged) { |
| | | notifyControlJobChanged(); |
| | | } |
| | | |
| | | |
| | | // 释放Job相关 |
| | | for (auto item : m_processJobs) { |
| | |
| | | { |
| | | // 1) 刷新派生 SV |
| | | refreshDerivedSVs(); |
| | | // 2) 上报 CJ 状态事件(同一 CJID,RPTID=31000) |
| | | static SERVO::CJState s_prevState = SERVO::CJState::NoState; |
| | | static std::string s_prevCjId; |
| | | SERVO::CControlJob* pCj = m_master.getControlJob(); |
| | | if (pCj == nullptr) { |
| | | if (!s_prevCjId.empty()) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("CJID", s_prevCjId.c_str()); |
| | | m_hsmsPassive.requestEventReportSend("CJobDeleted"); |
| | | }); |
| | | s_prevCjId.clear(); |
| | | s_prevState = SERVO::CJState::NoState; |
| | | } |
| | | } |
| | | else { |
| | | const std::string& cjId = pCj->id(); |
| | | const SERVO::CJState state = pCj->state(); |
| | | if (s_prevCjId != cjId) { |
| | | s_prevCjId = cjId; |
| | | s_prevState = SERVO::CJState::NoState; |
| | | } |
| | | if (state != s_prevState) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("CJID", cjId.c_str()); |
| | | if (state == SERVO::CJState::Queued) { |
| | | m_hsmsPassive.requestEventReportSend("CJobQueued"); |
| | | } |
| | | else if (state == SERVO::CJState::Executing) { |
| | | if (s_prevState == SERVO::CJState::Paused) { |
| | | m_hsmsPassive.requestEventReportSend("CJobResume"); |
| | | } |
| | | else { |
| | | m_hsmsPassive.requestEventReportSend("CJobExecuting"); |
| | | } |
| | | } |
| | | else if (state == SERVO::CJState::Paused) { |
| | | m_hsmsPassive.requestEventReportSend("CJobPaused"); |
| | | } |
| | | else if (state == SERVO::CJState::Completed) { |
| | | m_hsmsPassive.requestEventReportSend("CJobCompleted"); |
| | | } |
| | | else if (state == SERVO::CJState::Aborted || state == SERVO::CJState::Failed) { |
| | | m_hsmsPassive.requestEventReportSend("CJobAbort"); |
| | | } |
| | | }); |
| | | s_prevState = state; |
| | | } |
| | | } |
| | | // 3) 上报 PJ 状态事件(PrJob*) |
| | | emitPjStateEvents(); |
| | | // 2) 通知上层 UI(RX_CODE_CONTROLJOB_CHANGED) |
| | | notify(RX_CODE_CONTROLJOB_CHANGED); |
| | | } |
| | | |
| | | void CModel::emitPjStateEvents() |
| | | { |
| | | // 当前 PJ 列表 |
| | | std::map<std::string, SERVO::PJState> current; |
| | | for (auto pj : m_master.getProcessJobs()) { |
| | | if (pj == nullptr) continue; |
| | | current[pj->id()] = pj->state(); |
| | | } |
| | | |
| | | // 已删除的 PJ |
| | | for (auto it = m_prevPjStates.begin(); it != m_prevPjStates.end(); ) { |
| | | if (current.find(it->first) == current.end()) { |
| | | const std::string pjId = it->first; |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("PJID", pjId.c_str()); |
| | | m_hsmsPassive.requestEventReportSend("PrJobDeleted"); |
| | | }); |
| | | it = m_prevPjStates.erase(it); |
| | | continue; |
| | | } |
| | | ++it; |
| | | } |
| | | |
| | | // 状态变更事件 |
| | | for (const auto& kv : current) { |
| | | const std::string& pjId = kv.first; |
| | | const SERVO::PJState state = kv.second; |
| | | auto prevIt = m_prevPjStates.find(pjId); |
| | | if (prevIt == m_prevPjStates.end()) { |
| | | // 新 PJ:由 onPRJobMultiCreate 负责上报 PrJobPooled,这里只缓存 |
| | | m_prevPjStates[pjId] = state; |
| | | continue; |
| | | } |
| | | const SERVO::PJState prevState = prevIt->second; |
| | | if (state == prevState) continue; |
| | | |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("PJID", pjId.c_str()); |
| | | if (state == SERVO::PJState::InProcess) { |
| | | if (prevState == SERVO::PJState::Paused) { |
| | | m_hsmsPassive.requestEventReportSend("PrJobResume"); |
| | | } |
| | | else { |
| | | m_hsmsPassive.requestEventReportSend("PrJobProcessing"); |
| | | } |
| | | } |
| | | else if (state == SERVO::PJState::Paused) { |
| | | m_hsmsPassive.requestEventReportSend("PrJobPaused"); |
| | | } |
| | | else if (state == SERVO::PJState::Completed) { |
| | | m_hsmsPassive.requestEventReportSend("PrJobCompleted"); |
| | | } |
| | | else if (state == SERVO::PJState::Aborted || state == SERVO::PJState::Failed || state == SERVO::PJState::Aborting) { |
| | | m_hsmsPassive.requestEventReportSend("PrJobAbort"); |
| | | } |
| | | }); |
| | | m_prevPjStates[pjId] = state; |
| | | } |
| | | } |
| | | |
| | | bool CModel::raiseSoftAlarm(int alarmId, |
| | |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("PJQueued", vars); |
| | | m_hsmsPassive.requestEventReportSend_PJ_Queued(); |
| | | for (auto pj : processJobs) { |
| | | if (pj == nullptr) continue; |
| | | m_hsmsPassive.setVariableValue("PJID", pj->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend("PrJobPooled"); |
| | | m_prevPjStates[pj->id()] = pj->state(); |
| | | } |
| | | }); |
| | | return nRet; |
| | | }; |
| | |
| | | glassId = g2; |
| | | } |
| | | const int slotNo = pJobDataS->getTargetSlotNo(); |
| | | const int sourceSlotNo = pJobDataS->getSourceSlotNo(); |
| | | const int sourcePortNo = pJobDataS->getSourcePortNo(); |
| | | std::string sourceCarrier; |
| | | if (sourcePortNo > 0) { |
| | | if (auto* pLoadPort = (SERVO::CLoadPort*)m_master.getEquipment(EQ_ID_LOADPORT1 + sourcePortNo - 1)) { |
| | | sourceCarrier = pLoadPort->getCassetteId(); |
| | | } |
| | | } |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("SubEqpName", pEquipment->getName().c_str()); |
| | | m_hsmsPassive.setVariableValue("SubEqpSlot", slotNo); |
| | | m_hsmsPassive.setVariableValue("MaterialId", glassId.c_str()); |
| | | m_hsmsPassive.setVariableValue("SourceCarrier", sourceCarrier.c_str()); |
| | | m_hsmsPassive.setVariableValue("SourceSlot", (__int64)sourceSlotNo); |
| | | m_hsmsPassive.setVariableValue("SourcePanelID", glassId.c_str()); |
| | | m_hsmsPassive.requestEventReportSend("GlassReceivedJob"); |
| | | }); |
| | | } |
| | |
| | | glassId = g2; |
| | | } |
| | | const int slotNo = pJobDataS->getSourceSlotNo(); |
| | | const int targetSlotNo = pJobDataS->getTargetSlotNo(); |
| | | const int targetPortNo = pJobDataS->getTargetPortNo(); |
| | | std::string targetCarrier; |
| | | if (targetPortNo > 0) { |
| | | if (auto* pLoadPort = (SERVO::CLoadPort*)m_master.getEquipment(EQ_ID_LOADPORT1 + targetPortNo - 1)) { |
| | | targetCarrier = pLoadPort->getCassetteId(); |
| | | } |
| | | } |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("SubEqpName", pEquipment->getName().c_str()); |
| | | m_hsmsPassive.setVariableValue("SubEqpSlot", slotNo); |
| | | m_hsmsPassive.setVariableValue("MaterialId", glassId.c_str()); |
| | | m_hsmsPassive.setVariableValue("TargetCarrier", targetCarrier.c_str()); |
| | | m_hsmsPassive.setVariableValue("TargetSlot", (__int64)targetSlotNo); |
| | | m_hsmsPassive.setVariableValue("TargetPanelID", glassId.c_str()); |
| | | m_hsmsPassive.requestEventReportSend("GlassSentOutJob"); |
| | | }); |
| | | }; |
| | |
| | | }; |
| | | masterListener.onCjStart = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("CJStartID", ((SERVO::CControlJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.setVariableValue("CJID", ((SERVO::CControlJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_CJ_Start(); |
| | | }); |
| | | }; |
| | | masterListener.onCjEnd = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("CJEndID", ((SERVO::CControlJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.setVariableValue("CJID", ((SERVO::CControlJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_CJ_End(); |
| | | }); |
| | | |
| | |
| | | }; |
| | | masterListener.onPjStart = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("PJStartID", ((SERVO::CProcessJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.setVariableValue("PJID", ((SERVO::CProcessJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_PJ_Start(); |
| | | }); |
| | | emitPjStateEvents(); |
| | | }; |
| | | masterListener.onPjEnd = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | | m_hsmsPassive.setVariableValue("PJEndID", ((SERVO::CProcessJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.setVariableValue("PJID", ((SERVO::CProcessJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_PJ_End(); |
| | | }); |
| | | emitPjStateEvents(); |
| | | }; |
| | | masterListener.onPanelStart = [&](void* pMaster, void* pPanel) { |
| | | m_hsmsPassive.withVariableLock([&] { |
| | |
| | | #include "HsmsPassive.h" |
| | | #include "CMaster.h" |
| | | #include "CGlassPool.h" |
| | | #include "ProcessJob.h" |
| | | #include <cstdint> |
| | | #include <map> |
| | | #include <string> |
| | | |
| | | enum class ControlState : uint8_t { |
| | |
| | | private: |
| | | void refreshDerivedSVs(); |
| | | void notifyControlJobChanged(); |
| | | void emitPjStateEvents(); |
| | | |
| | | public: |
| | | int notify(int code); |
| | |
| | | |
| | | private: |
| | | ControlState m_currentControlState{ ControlState::OfflineEquipment }; |
| | | std::map<std::string, SERVO::PJState> m_prevPjStates; |
| | | }; |
| | |
| | | 20000,GlassSlotStart,,(20000) |
| | | 20001,GlassSlotCompleted,,(20000) |
| | | 30000,PrJobPooled,,(30000) |
| | | 30001,PrJobAbort,,(30000) |
| | | 30010,PrJobProcessing,,(30000) |
| | | 30011,PrJobCompleted,,(30000) |
| | | 30013,PrJobPaused,,(30000) |
| | | 30014,PrJobResume,,(30000) |
| | | 30020,PrJobDeleted,,(30000) |
| | | 30001,PJ_Queued,,(50001) |
| | | 30002,PJ_Start,,(50002) |
| | | 30003,PrJobProcessing,,(30000) |
| | | 30004,PrJobPaused,,(30000) |
| | | 30005,PrJobResume,,(30000) |
| | | 30006,PrJobCompleted,,(30000) |
| | | 30007,PJ_End,,(50003) |
| | | 30008,PrJobAbort,,(30000) |
| | | 30009,PrJobDeleted,,(30000) |
| | | 31000,CJobQueued,,(31000) |
| | | 31001,CJobAbort,,(31000) |
| | | 31010,CJobExecuting,,(31000) |
| | | 31020,CJobCompleted,,(31000) |
| | | 31021,CJobDeleted,,(31000) |
| | | 31031,CJobPaused,,(31000) |
| | | 31032,CJobResume,,(31000) |
| | | 31001,CJ_Start,,(31000) |
| | | 31002,CJobExecuting,,(31000) |
| | | 31003,CJobPaused,,(31000) |
| | | 31004,CJobResume,,(31000) |
| | | 31005,CJobCompleted,,(31000) |
| | | 31006,CJ_End,,(31000) |
| | | 31007,CJobAbort,,(31000) |
| | | 31008,CJobDeleted,,(31000) |
| | | 40000,E90_SPSM_NoState_To_NeedsProcessing,,(40000) |
| | | 40001,E90_SPSM_InProcess_To_ProcessCompleted,,(40000) |
| | | 50000,CarrierID_Readed,,(50000) |
| | | 50001,PJ_Queued,,(50001) |
| | | 50002,PJ_Start,,(50002) |
| | | 50003,PJ_End,,(50003) |
| | | 50004,Panel_Start,,(50004) |
| | | 50005,Panel_End,,(50005) |
| | | 50006,CJ_Start,,(50006) |
| | | 50007,CJ_End,,(50007) |
| | | 50008,Port_Unload_Ready,,(50008) |
| | | 50009,Port_Load_Ready,,(50009) |
| | | 50010,Port_Blocked,,(50010) |
| | |
| | | 10072,(1,10000,10001,10002,10003,10100,10203,20000,20001) |
| | | 10080,(1,10000,10001,10002,10003,10100) |
| | | 20000,(1,5018,5019,10000,10001,10002,10003,10203) |
| | | 30000,(1,30000,30001) |
| | | 31000,(1,31000,31001) |
| | | 30000,(5004) |
| | | 31000,(5008) |
| | | 40000,(1,10203,20000) |
| | | 50000,(5000) |
| | | 50001,(5003) |
| | | 50002,(5004) |
| | | 50003,(5005) |
| | | 50003,(5004) |
| | | 50004,(5006) |
| | | 50005,(5007) |
| | | 50006,(5008) |
| | | 50007,(5009) |
| | | 50008,(5022) |
| | | 50009,(5022) |
| | | 50010,(5022) |
| | |
| | | 50013,(5022) |
| | | 50014,(5022) |
| | | 50020,(500,5022,5021) |
| | | 50021,(5018,5019,5023) |
| | | 50022,(5018,5019,5023) |
| | | 50021,(5018,5019,5028,5029,5030) |
| | | 50022,(5018,5019,5025,5026,5027) |
| | | 60000,(500,5018,5019,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018) |
| | | 61000,(500,5018,5019,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121) |
| | | 62000,(500,5018,5019,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217) |
| | |
| | | SVID,SV Name,SV Format,SV Remark |
| | | 10000,CarrierID_P1,A50,Carrier ID for Port 1 |
| | | 10001,CarrierID_P2,A50,Carrier ID for Port 2 |
| | | 10002,CarrierID_P3,A50,Carrier ID for Port 3 |
| | | 10003,CarrierID_P4,A50,Carrier ID for Port 4 |
| | | 100,PortTransferState_P1,U1,1=LoadReady;2=Loaded;3=InUse;4=UnloadReady;5=Empty;6=Blocked |
| | | 101,PortTransferState_P2,U1,1=LoadReady;2=Loaded;3=InUse;4=UnloadReady;5=Empty;6=Blocked |
| | | 102,PortTransferState_P3,U1,1=LoadReady;2=Loaded;3=InUse;4=UnloadReady;5=Empty;6=Blocked |
| | | 103,PortTransferState_P4,U1,1=LoadReady;2=Loaded;3=InUse;4=UnloadReady;5=Empty;6=Blocked |
| | | 300,AccessMode_P1,U1,0=OutOfService;1=TransferBlocked;2=ReadyToLoad;3=ReadyToUnload;4=InService;5=TransferReady |
| | | 301,AccessMode_P2,U1,0=OutOfService;1=TransferBlocked;2=ReadyToLoad;3=ReadyToUnload;4=InService;5=TransferReady |
| | | 302,AccessMode_P3,U1,0=OutOfService;1=TransferBlocked;2=ReadyToLoad;3=ReadyToUnload;4=InService;5=TransferReady |
| | | 303,AccessMode_P4,U1,0=OutOfService;1=TransferBlocked;2=ReadyToLoad;3=ReadyToUnload;4=InService;5=TransferReady |
| | | 500,Clock,A50,Current timestamp string |
| | | 600,CurrentControlState,U1,0=OfflineEquipment;1=OfflineAttempt;2=Online;3=OfflineHost;4=OnlineLocal;5=OnlineRemote |
| | | 601,PreviousControlState,U1,Previous control state (same code set as CurrentControlState) |
| | | 700,CurrentProcessState,U1,0=Ready;1=Processing;2=Complete;3=Error |
| | | 701,PreviousProcessState,U1,Previous process state (0=Ready;1=Processing;2=Complete;3=Error) |
| | | 800,EFEMPPExecName,A20,Current PPExec name from EFEM |
| | | 801,EQPPExecName,A20,Current PPExec name from equipment |
| | | 8100,Bonder1CurrentRecipe,A50,Current recipe for Bonder1 |
| | | 8101,Bonder2CurrentRecipe,A50,Current recipe for Bonder2 |
| | | 8102,VacuumBakeCurrentRecipe,A50,Current recipe for VacuumBake |
| | | 8103,BakeCoolingCurrentRecipe,A50,Current recipe for BakeCooling |
| | | 8104,MeasurementCurrentRecipe,A50,Current recipe for Measurement |
| | | 8105,EFEMCurrentRecipe,A50,Current recipe for EFEM |
| | | 5001,CJobSpace,U1,CJ Space |
| | | 5002,PJobSpace,U1,PJ Space |
| | | 5003,PJQueued,L,PJ queued list (IDs) |
| | | 5004,PJStartID,A20,PJ start ID |
| | | 5005,PJEndID,A20,PJ end ID |
| | | 5004,PJID,A20,Process job ID (PJ)
|
| | | 5006,PanelStartID,A20,Panel start ID |
| | | 5007,PanelEndID,A20,Panel end ID |
| | | 5008,CJStartID,A20,CJ start ID |
| | | 5009,CJEndID,A20,CJ end ID |
| | | 5008,CJID,A20,Control job ID (CJ)
|
| | | 5014,VCRPanelID,A20,Panel ID from reader |
| | | 5017,ProcessDataReportText,A50,EV_PROCESS_DATA_REPORT payload (placeholder) |
| | | 5018,SubEqpName,A20,Sub equipment name (SubEqp/Unit/Process/SV/ProcessData events) |
| | | 5019,SubEqpSlot,U1,Slot number for SubEqp/Unit; 0 when not applicable |
| | | 5021,PortState,U1,Port transfer/state code for PortStateChange |
| | | 5022,PortId,U1,Unified port ID for all Port events |
| | | 5023,MaterialId,A50,Material/Glass ID for Received/SentOut events |
| | | 5024,EquipmentStatus,U1,Equipment status (SubEqpStateChange): 1=PM;2=Down(BM);3=Pause;4=Idle;5=Run;6=Job Change;7=ETC |
| | | |
| | | 5025,TargetCarrier,A50,Target carrier ID for SentOutJob
|
| | | 5026,TargetSlot,U1,Target slot number for SentOutJob
|
| | | 5027,TargetPanelID,A50,Target panel/glass ID for SentOutJob
|
| | | 5028,SourceCarrier,A50,Source carrier ID for ReceivedJob
|
| | | 5029,SourceSlot,U1,Source slot number for ReceivedJob
|
| | | 5030,SourcePanelID,A50,Source panel/glass ID for ReceivedJob
|
| | | 8100,Bonder1CurrentRecipe,A50,Current recipe for Bonder1
|
| | | 8101,Bonder2CurrentRecipe,A50,Current recipe for Bonder2
|
| | | 8102,VacuumBakeCurrentRecipe,A50,Current recipe for VacuumBake
|
| | | 8103,BakeCoolingCurrentRecipe,A50,Current recipe for BakeCooling
|
| | | 8104,MeasurementCurrentRecipe,A50,Current recipe for Measurement
|
| | | 8105,EFEMCurrentRecipe,A50,Current recipe for EFEM
|
| | | 10000,CarrierID_P1,A50,Carrier ID for Port 1
|
| | | 10001,CarrierID_P2,A50,Carrier ID for Port 2
|
| | | 10002,CarrierID_P3,A50,Carrier ID for Port 3
|
| | | 10003,CarrierID_P4,A50,Carrier ID for Port 4
|