From 2a21061d88d5533065dc57cfae0b1f2c1952e06f Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期五, 22 八月 2025 16:01:32 +0800
Subject: [PATCH] 1.PorcessJob和Glass关系绑定; 2.对话框显示ProcessJob、Glass等数据;
---
SourceCode/Bond/Servo/CControlJobDlg.cpp | 30 +++++--
SourceCode/Bond/Servo/ProcessJob.h | 6 +
SourceCode/Bond/Servo/ProcessJob.cpp | 11 ++
SourceCode/Bond/Servo/CGlass.cpp | 123 ++++++++++++++++++++++++++++++
SourceCode/Bond/Servo/CGlass.h | 46 +++++++++++
SourceCode/Bond/Servo/Servo.rc | 0
SourceCode/Bond/Servo/CMaster.cpp | 21 +++++
SourceCode/Bond/Servo/CLoadPort.cpp | 2
8 files changed, 227 insertions(+), 12 deletions(-)
diff --git a/SourceCode/Bond/Servo/CControlJobDlg.cpp b/SourceCode/Bond/Servo/CControlJobDlg.cpp
index a372529..7365c3d 100644
--- a/SourceCode/Bond/Servo/CControlJobDlg.cpp
+++ b/SourceCode/Bond/Servo/CControlJobDlg.cpp
@@ -58,10 +58,12 @@
HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
m_listCtrl.ModifyStyle(0, LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS);
- m_listCtrl.InsertColumn(0, _T("鍚嶇О"), LVCFMT_LEFT, 180);
- m_listCtrl.InsertColumn(1, _T("鐘舵��"), LVCFMT_LEFT, 120);
- m_listCtrl.InsertColumn(2, _T("鎻忚堪"), LVCFMT_LEFT, 260);
- m_listCtrl.InsertColumn(3, _T("閰嶆柟"), LVCFMT_LEFT, 180);
+ m_listCtrl.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 180);
+ m_listCtrl.InsertColumn(1, _T("绫诲瀷"), LVCFMT_LEFT, 120);
+ m_listCtrl.InsertColumn(2, _T("鐘舵��"), LVCFMT_LEFT, 120);
+ m_listCtrl.InsertColumn(3, _T("閰嶆柟"), LVCFMT_LEFT, 120);
+ m_listCtrl.InsertColumn(4, _T("Port / Carrier / Slot"), LVCFMT_LEFT, 180);
+ m_listCtrl.InsertColumn(5, _T("鎻忚堪"), LVCFMT_LEFT, 220);
// 鎺т欢鐘舵��
@@ -135,15 +137,27 @@
m_listCtrl.DeleteAllItems();
if (m_pControlJob != nullptr) {
- auto* root1 = m_listCtrl.InsertRoot({ m_pControlJob->id().c_str(),
+ auto* root1 = m_listCtrl.InsertRoot({ m_pControlJob->id().c_str(), _T("ControlJob"),
m_pControlJob->getStateText().c_str(), _T("") });
auto pjs = m_pControlJob->getPjs();
for (auto pj : pjs) {
- auto* root2 = m_listCtrl.InsertChild(root1, {pj->id().c_str(),
- pj->getStateText().c_str(), _T(""), pj->recipeSpec().c_str()});
+ auto* root2 = m_listCtrl.InsertChild(root1, {pj->id().c_str(), _T("ProcessJob"),
+ pj->getStateText().c_str(), pj->recipeSpec().c_str(), _T(""), _T(""), _T("") });
auto cs = pj->carriers();
for (auto c : cs) {
- m_listCtrl.InsertChild(root2, {c.carrierId.c_str(), _T(""), _T("") });
+ for (auto g : c.contexts) {
+ SERVO::CGlass* pGlass = (SERVO::CGlass*)g;
+ if (pGlass != nullptr) {
+ int port, slot;
+ pGlass->getOrginPort(port, slot);
+ std::string carrier = c.carrierId + " / Port" + std::to_string(port + 1) + " / Slot" + std::to_string(slot + 1);
+ m_listCtrl.InsertChild(root2, { pGlass->getID().c_str(), _T("Glass"),
+ pGlass->getStateText().c_str(), _T(""), carrier.c_str(), _T("") });
+ }
+ else {
+ m_listCtrl.InsertChild(root2, { "Null", _T("Glass"), _T(""), _T(""), c.carrierId.c_str(), _T("") });
+ }
+ }
}
root2->expanded = true;
}
diff --git a/SourceCode/Bond/Servo/CGlass.cpp b/SourceCode/Bond/Servo/CGlass.cpp
index 6c1b30f..974859c 100644
--- a/SourceCode/Bond/Servo/CGlass.cpp
+++ b/SourceCode/Bond/Servo/CGlass.cpp
@@ -11,6 +11,7 @@
m_nOriginPort = 0;
m_nOriginSlot = 0;
m_bScheduledForProcessing = FALSE;
+ m_pProcessJob = nullptr;
}
CGlass::~CGlass()
@@ -89,6 +90,16 @@
void CGlass::setScheduledForProcessing(BOOL bProcessing)
{
m_bScheduledForProcessing = bProcessing;
+ }
+
+ CProcessJob* CGlass::getProcessJob()
+ {
+ return m_pProcessJob;
+ }
+
+ void CGlass::setProcessJob(CProcessJob* pProcessJob)
+ {
+ m_pProcessJob = pProcessJob;
}
CPath* CGlass::getPath()
@@ -246,4 +257,116 @@
return pPath->getInspResult();
}
+
+ std::string CGlass::getStateText()
+ {
+ switch (m_state)
+ {
+ case SERVO::GlsState::NoState:
+ return "NoState";
+ break;
+ case SERVO::GlsState::Queued:
+ return "Queued";
+ break;
+ case SERVO::GlsState::InProcess:
+ return "InProcess";
+ break;
+ case SERVO::GlsState::Paused:
+ return "Queued";
+ break;
+ case SERVO::GlsState::Completed:
+ return "Queued";
+ break;
+ case SERVO::GlsState::Aborted:
+ return "Aborted";
+ break;
+ case SERVO::GlsState::Failed:
+ return "Failed";
+ break;
+ default:
+ break;
+ }
+
+ return "";
+ }
+
+ bool CGlass::queue() {
+ if (m_state != GlsState::NoState) return false;
+ markQueued();
+ return true;
+ }
+
+ bool CGlass::start() {
+ if (m_state != GlsState::Queued && m_state != GlsState::Paused)
+ return false;
+ if (!m_tStart.has_value()) markStart();
+ m_state = GlsState::InProcess;
+ return true;
+ }
+
+ bool CGlass::pause() {
+ if (m_state != GlsState::InProcess) return false;
+ m_state = GlsState::Paused;
+ return true;
+ }
+
+ bool CGlass::resume() {
+ if (m_state != GlsState::Paused) return false;
+ m_state = GlsState::InProcess;
+ return true;
+ }
+
+ bool CGlass::complete() {
+ if (m_state != GlsState::InProcess && m_state != GlsState::Paused) return false;
+ m_state = GlsState::Completed;
+ markEnd();
+ return true;
+ }
+
+ bool CGlass::abort() {
+ if (m_state == GlsState::Completed || m_state == GlsState::Aborted || m_state == GlsState::Failed)
+ return false;
+ m_state = GlsState::Aborted;
+ markEnd();
+ return true;
+ }
+
+ bool CGlass::fail(std::string reason)
+ {
+ m_failReason = trimCopy(reason);
+ clampString(m_failReason, 128);
+ m_state = GlsState::Failed;
+ markEnd();
+ return true;
+ }
+
+ std::string CGlass::trimCopy(std::string s)
+ {
+ auto notspace = [](int ch) { return !std::isspace(ch); };
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace));
+ s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end());
+ return s;
+ }
+
+ void CGlass::clampString(std::string& s, size_t maxLen)
+ {
+ if (s.size() > maxLen) s.resize(maxLen);
+ }
+
+ // —— 时间戳 & 工具 ——
+ void CGlass::markQueued()
+ {
+ m_state = GlsState::Queued;
+ m_tQueued = std::chrono::system_clock::now();
+ }
+
+ void CGlass::markStart()
+ {
+ m_tStart = std::chrono::system_clock::now();
+ }
+
+ void CGlass::markEnd()
+ {
+ m_tEnd = std::chrono::system_clock::now();
+ }
}
diff --git a/SourceCode/Bond/Servo/CGlass.h b/SourceCode/Bond/Servo/CGlass.h
index 844822b..21aaf34 100644
--- a/SourceCode/Bond/Servo/CGlass.h
+++ b/SourceCode/Bond/Servo/CGlass.h
@@ -7,9 +7,21 @@
#include "CJobDataC.h"
#include "CJobDataS.h"
#include "ServoCommo.h"
+#include "ProcessJob.h"
namespace SERVO {
+ /// PJ 生命周期(贴近 E40 常见状态)
+ enum class GlsState : uint8_t {
+ NoState = 0,
+ Queued,
+ InProcess,
+ Paused,
+ Completed,
+ Aborted,
+ Failed
+ };
+
class CGlass : public CContext
{
public:
@@ -28,6 +40,8 @@
void getOrginPort(int& port, int& slot);
BOOL isScheduledForProcessing();
void setScheduledForProcessing(BOOL bProcessing);
+ CProcessJob* getProcessJob();
+ void setProcessJob(CProcessJob* pProcessJob);
CPath* getPathWithEq(unsigned int nEqId, unsigned int nUnit);
CPath* getPath();
void addPath(unsigned int nEqId, unsigned int nUnit);
@@ -44,6 +58,37 @@
int setInspResult(unsigned int nEqId, unsigned int nUnit, InspResult result);
InspResult getInspResult(unsigned int nEqId, unsigned int nUnit);
+ public:
+ // 新增状态
+ GlsState state() const noexcept { return m_state; }
+ std::string getStateText();
+ GlsState m_state{ GlsState::NoState };
+ static void clampString(std::string& s, size_t maxLen);
+ static std::string trimCopy(std::string s);
+ std::string m_failReason;
+
+ // —— 状态机(带守卫)——
+ bool queue(); // NoState -> Queued
+ bool start(); // Queued -> InProcess
+ bool pause(); // InProcess -> Paused
+ bool resume(); // Paused -> InProcess
+ bool complete(); // InProcess -> Completed
+ bool abort(); // Any (未终态) -> Aborted
+ bool fail(std::string reason); // 任意态 -> Failed(记录失败原因)
+
+ // 时间戳
+ std::optional<std::chrono::system_clock::time_point> m_tQueued;
+ std::optional<std::chrono::system_clock::time_point> m_tStart;
+ std::optional<std::chrono::system_clock::time_point> m_tEnd;
+
+ // 时间戳(可用于报表/追溯)
+ std::optional<std::chrono::system_clock::time_point> tQueued() const { return m_tQueued; }
+ std::optional<std::chrono::system_clock::time_point> tStart() const { return m_tStart; }
+ std::optional<std::chrono::system_clock::time_point> tEnd() const { return m_tEnd; }
+ void markQueued();
+ void markStart();
+ void markEnd();
+
private:
MaterialsType m_type;
std::string m_strID;
@@ -54,6 +99,7 @@
int m_nOriginPort;
int m_nOriginSlot;
BOOL m_bScheduledForProcessing; /* 是否将加工处理 */
+ CProcessJob* m_pProcessJob;
};
}
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index 28ce403..7cc6006 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -385,7 +385,7 @@
CStep* pStep = getStepWithName(STEP_EQ_PORT2_INUSE);
CPortStatusReport portStatusReport;
portStatusReport.setPortStatus(PORT_INUSE);
- portStatusReport.setJobExistenceSlot(0xf);
+ portStatusReport.setJobExistenceSlot(0xff );
portStatusReport.setCassetteId("CID1004");
int nRet = portStatusReport.serialize(szBuffer, 64);
decodePortStatusReport(pStep, szBuffer, 64);
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 1f38e9f..e01b180 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -1143,6 +1143,25 @@
};
listener.onPortStatusChanged = [&](void* pEquipment, short status, __int64 data) {
LOGE("<Master-%s>onPortStatusChanged。status=%d, data=%lld", ((CEquipment*)pEquipment)->getName().c_str(), status);
+ if (status == PORT_INUSE && m_pControlJob != nullptr) {
+ CLoadPort* pPort = (CLoadPort*)pEquipment;
+ auto pjs = m_pControlJob->getPjs();
+ for (auto pj : pjs) {
+ auto carrier = pj->getCarrier(pPort->getCassetteId());
+ if (carrier != nullptr) {
+ for (auto slot : carrier->slots) {
+ CGlass* pGlass = pPort->getGlassFromSlot(slot);
+ carrier->contexts.push_back((void*)pGlass);
+ if (pGlass != nullptr) {
+ pGlass->setProcessJob(pj);
+ }
+ }
+ }
+ }
+
+
+ }
+
if (m_listener.onLoadPortStatusChanged != nullptr) {
m_listener.onLoadPortStatusChanged(this, (CEquipment*)pEquipment, status, data);
}
@@ -1868,7 +1887,7 @@
m_processJobs = temp;
this->saveState();
- return m_processJobs.size();
+ return (int)m_processJobs.size();
}
std::vector<CProcessJob*>& CMaster::getProcessJobs()
diff --git a/SourceCode/Bond/Servo/ProcessJob.cpp b/SourceCode/Bond/Servo/ProcessJob.cpp
index 801d9d2..b672e27 100644
--- a/SourceCode/Bond/Servo/ProcessJob.cpp
+++ b/SourceCode/Bond/Servo/ProcessJob.cpp
@@ -419,4 +419,15 @@
return "";
}
+
+ CarrierSlotInfo* CProcessJob::getCarrier(std::string& strId)
+ {
+ for (auto& item : m_carriers) {
+ if (item.carrierId.compare(strId) == 0) {
+ return &item;
+ }
+ }
+
+ return nullptr;
+ }
}
diff --git a/SourceCode/Bond/Servo/ProcessJob.h b/SourceCode/Bond/Servo/ProcessJob.h
index 7c78b26..1300b46 100644
--- a/SourceCode/Bond/Servo/ProcessJob.h
+++ b/SourceCode/Bond/Servo/ProcessJob.h
@@ -49,8 +49,9 @@
}
*/
struct CarrierSlotInfo {
- std::string carrierId; // CARRIERID
- std::vector<uint8_t> slots; // SLOTID[]
+ std::string carrierId; // CARRIERID
+ std::vector<uint8_t> slots; // SLOTID[]
+ std::vector<void*> contexts; // Glass
};
/// 简单资源视图接口:供 Validate() 查询(由设备端实现者在外部提供)
@@ -154,6 +155,7 @@
// 访问器
const std::vector<CarrierSlotInfo>& carriers() const noexcept { return m_carriers; }
+ CarrierSlotInfo* getCarrier(std::string& strId);
// 判定是否“按载具/卡位”方式
bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); }
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 228d83e..ac1bebb 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
--
Gitblit v1.9.3