From 3e0ceaf4e569ea1f57a14de2f6135d1f1a50d080 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期三, 27 八月 2025 13:47:31 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/EAPSimulator/ProcessJob.h | 198 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 198 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/EAPSimulator/ProcessJob.h b/SourceCode/Bond/EAPSimulator/ProcessJob.h
new file mode 100644
index 0000000..92d70b9
--- /dev/null
+++ b/SourceCode/Bond/EAPSimulator/ProcessJob.h
@@ -0,0 +1,198 @@
+#pragma once
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <unordered_set>
+#include <algorithm>
+#include <cstdint>
+#include <chrono>
+#include <optional>
+
+namespace SERVO {
+ /// PJ 生命周期(贴近 E40 常见状态)
+ enum class PJState : uint8_t {
+ NoState = 0,
+ Queued,
+ SettingUp,
+ InProcess,
+ Paused,
+ Aborting,
+ Completed,
+ Aborted,
+ Failed
+ };
+
+ /// 配方指定方式(对应 S16F15 里 PRRECIPEMETHOD)
+ enum class RecipeMethod : uint8_t {
+ NoTuning = 1, // 1 - recipe without variable tuning
+ WithTuning = 2 // 2 - recipe with variable tuning
+ };
+
+ /// 启动策略(对应 S16F15 里 PRPROCESSSTART)
+ enum class StartPolicy : uint8_t {
+ Queued = 0, // 建立后排队
+ AutoStart = 1 // 条件满足则自动启动
+ };
+
+ /** 配方参数对(S16F15 中 RCPPARNM / RCPPARVAL) */
+ struct PJParam {
+ std::string name; // RCPPARNM
+ std::string value; // RCPPARVAL
+ };
+
+ /**
+ {L:2
+ CARRIERID
+ {L:j
+ SLOTID
+ }
+ }
+ */
+ struct CarrierSlotInfo {
+ std::string carrierId; // CARRIERID
+ std::vector<uint8_t> slots; // SLOTID[]
+ };
+
+ /// 简单资源视图接口:供 Validate() 查询(由设备端实现者在外部提供)
+ struct IResourceView {
+ virtual ~IResourceView() = default;
+ virtual bool recipeExists(const std::string& ppid) const = 0;
+ virtual bool carrierPresent(const std::string& carrierId) const = 0;
+ virtual bool slotUsable(const std::string& carrierId, uint16_t slot) const = 0;
+ virtual bool ceidDefined(uint32_t ceid) const = 0;
+ // 你也可以扩展:port状态、占用情况、CJ/PJ空间等
+ };
+
+ /// PJ 主类
+ /**
+ * ProcessJob —— 与 S16F15(PRJobMultiCreate)字段一一对应的承载类
+ *
+ * S16F15 结构(核心节选):
+ * {L:6
+ * PRJOBID -> m_pjId
+ * MF -> m_mf
+ * {L:n { CARRIERID {L:j SLOTID} } }
+ * {L:3
+ * PRRECIPEMETHOD -> m_recipeType
+ * RCPSPEC(PPID) -> m_recipeSpec
+ * {L:m { RCPPARNM RCPPARVAL }} -> m_params
+ * }
+ * PRPROCESSSTART -> m_startPolicy
+ * {L:k PRPAUSEEVENTID} -> m_pauseEvents
+ * }
+ */
+ class CProcessJob {
+ public:
+ // —— 构造 / 基本设置 ——
+ explicit CProcessJob(std::string pjId);
+
+ const std::string& id() const noexcept { return m_pjId; }
+ const std::string& parentCjId() const noexcept { return m_parentCjId; }
+ PJState state() const noexcept { return m_state; }
+ StartPolicy startPolicy() const noexcept { return m_startPolicy; }
+ RecipeMethod recipeMethod() const noexcept { return m_recipeMethod; }
+ const std::string& recipeSpec() const noexcept { return m_recipeSpec; } // PPID 或 Spec
+
+ // 绑定父 CJ
+ void setParentCjId(std::string cjId);
+
+ // 配方
+ void setRecipe(RecipeMethod method, std::string spec);
+
+ // 启动策略
+ void setStartPolicy(StartPolicy sp) { m_startPolicy = sp; }
+
+ // 参数
+ void addParam(std::string name, std::string value);
+ void setParams(std::vector<PJParam> params);
+
+ // 暂停事件
+ void addPauseEvent(uint32_t ceid);
+ void setPauseEvents(std::vector<uint32_t> ceids);
+
+ // —— 校验 ——
+ struct ValidationIssue {
+ uint32_t code; // 自定义错误码
+ std::string text; // 文本描述
+ };
+ // 返回问题清单(空=通过)
+ std::vector<ValidationIssue> validate(const IResourceView& rv) const;
+
+ // —— 状态机(带守卫)——
+ bool queue(); // NoState -> Queued
+ bool start(); // Queued/SettingUp -> InProcess
+ bool enterSettingUp(); // Queued -> SettingUp
+ bool pause(); // InProcess -> Paused
+ bool resume(); // Paused -> InProcess
+ bool complete(); // InProcess -> Completed
+ bool abort(); // Any (未终态) -> Aborted
+ bool fail(std::string reason); // 任意态 -> Failed(记录失败原因)
+
+ // —— 访问器(用于上报/查询)——
+ const std::vector<PJParam>& params() const noexcept { return m_params; }
+ const std::vector<uint32_t>& pauseEvents() const noexcept { return m_pauseEvents; }
+ const std::string& failReason() const noexcept { return m_failReason; }
+
+ // 时间戳(可用于报表/追溯)
+ 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; }
+
+ // 长度限制工具(可在集成时统一策略)
+ static void clampString(std::string& s, size_t maxLen);
+ static bool asciiPrintable(const std::string& s);
+
+ // 清空并整体设置
+ void setCarriers(std::vector<CarrierSlotInfo> carriers);
+
+ // 追加一个载具
+ void addCarrier(std::string carrierId, std::vector<uint8_t> slots);
+
+ // 访问器
+ const std::vector<CarrierSlotInfo>& carriers() const noexcept { return m_carriers; }
+
+ // 判定是否“按载具/卡位”方式
+ bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); }
+
+
+ private:
+ // 内部状态转移帮助
+ void markQueued();
+ void markStart();
+ void markEnd();
+
+ private:
+ // 标识
+ std::string m_pjId;
+ std::string m_parentCjId;
+
+ // 配方
+ RecipeMethod m_recipeMethod{ RecipeMethod::NoTuning };
+ std::string m_recipeSpec; // PPID / Spec
+
+ // 物料
+ static constexpr uint8_t MATERIAL_FORMAT = 14; // substrate
+ std::vector<CarrierSlotInfo> m_carriers; // {L:n { CARRIERID {L:j SLOTID} }}
+
+ // 参数 / 暂停事件
+ std::vector<PJParam> m_params;
+ std::vector<uint32_t> m_pauseEvents;
+
+ // 状态 & 记录
+ StartPolicy m_startPolicy{ StartPolicy::Queued }; // 0=Queued, 1=AutoStart
+ PJState m_state{ PJState::NoState };
+ std::string m_failReason;
+
+ // 时间戳
+ 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;
+
+ // 约束(可按你们协议调整)
+ static constexpr size_t MAX_ID_LEN = 64; // PJID/ CJID/ CarrierID/ MID/ PPID
+ static constexpr size_t MAX_PARAM_K = 32; // 参数名
+ static constexpr size_t MAX_PARAM_V = 64; // 参数值
+ };
+}
+
+
--
Gitblit v1.9.3