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/Servo/CControlJob.h | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/Servo/CControlJob.h b/SourceCode/Bond/Servo/CControlJob.h
new file mode 100644
index 0000000..8533018
--- /dev/null
+++ b/SourceCode/Bond/Servo/CControlJob.h
@@ -0,0 +1,153 @@
+#pragma once
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <cstdint>
+#include <optional>
+#include <chrono>
+#include <functional>
+#include "ProcessJob.h"
+
+
+// —— 标准/项目内约定的属性名(A:40)——
+// 说明:不以空格开头/结尾,字符范围 0x20-0x7E,且不能包含 > : ? * ~
+inline constexpr const char* CJ_ATTR_CJID = "CJID"; // A:n
+inline constexpr const char* CJ_ATTR_PRIORITY = "Priority"; // U1
+inline constexpr const char* CJ_ATTR_PRJOBLIST = "PRJOBLIST"; // L:n of A:n (PJID[])
+
+namespace SERVO {
+ /// CJ 状态(贴近 E40 语义)
+ enum class CJState : uint8_t {
+ NoState = 0,
+ Queued,
+ Executing,
+ Paused,
+ Completed,
+ Aborted,
+ Failed
+ };
+
+ /// 创建/修改结果中的错误项
+ struct CJError {
+ uint16_t code; // 自定义错误码(例:2001=PJ_NOT_FOUND, 2002=NOT_JOINABLE)
+ std::string text; // 建议包含定位信息(ATTRID/PJID)
+ };
+
+ /// CControlJob:Control Job 管理类
+ class CControlJob {
+ public:
+ CControlJob();
+ explicit CControlJob(std::string cjId);
+ explicit CControlJob(CControlJob& src);
+
+ // —— 基本属性 —— //
+ const std::string& id() const noexcept { return m_cjId; }
+ CJState state() const noexcept { return m_state; }
+ uint8_t priority() const noexcept { return m_priority; }
+ void setPriority(uint8_t p) noexcept { m_priority = p; }
+ std::string getStateText();
+
+ // —— PJ 列表维护(去重)—— //
+ bool addPJ(const std::string& pjId); // 已存在则不重复添加
+ bool addPJs(const std::vector<std::string>& ids); // 返回是否有新增
+ bool removePJ(const std::string& pjId); // 存在则移除
+ bool containsPJ(const std::string& pjId) const;
+ const std::vector<std::string>& pjIds() const noexcept { return m_pjIds; }
+ bool setPJs(const std::vector<CProcessJob*>& pjs);
+ void clearPJs() { m_pjIds.clear(); }
+ const std::vector<CProcessJob*>& getPjs() { return m_pjs; };
+
+ // —— 校验 —— //
+ struct ValidationIssue { uint32_t code; std::string text; };
+
+ // 校验 CJ 是否可创建/更新(例如:PJ 是否存在、是否可加入)
+ // getPjExistsFn(pjId)->bool:PJ 是否存在
+ // canJoinFn(pjId)->bool :PJ 当前是否允许加入 CJ(如 PJ 状态为 Queued 等)
+ bool validateForCreate(
+ const std::function<bool(uint32_t& code, std::string& msg)>& canCreateCjFn,
+ const std::function<bool(const std::string&)>& getPjExistsFn,
+ const std::function<bool(const std::string&)>& canJoinFn
+ );
+ const std::vector<CControlJob::ValidationIssue>& CControlJob::issues();
+
+ // —— S14F9 → S14F10 的“应用结果”模型 —— //
+ struct CreateRequest {
+ std::optional<uint8_t> priority; // 若有则覆盖
+ std::vector<std::string> requestedPjIds;// 想要绑定的 PJ 列表
+ };
+ struct CreateResult {
+ std::vector<std::string> acceptedPjIds; // 成功绑定的 PJ(用于回显 PRJOBLIST)
+ std::vector<CJError> errors; // 失败项(含 PJID 说明)
+ uint8_t objack{ 0 }; // 0=全成功, 1=部分成功, 2=全失败
+ };
+
+ // 应用创建/更新请求:只绑定允许的 PJ,并生成 OBJACK/错误清单
+ // getPjExistsFn / canJoinFn 同上
+ CreateResult applyCreate(
+ const CreateRequest& req,
+ const std::function<bool(const std::string&)>& getPjExistsFn,
+ const std::function<bool(const std::string&)>& canJoinFn
+ );
+
+ // —— 状态机 —— //
+ bool queue(); // NoState -> Queued
+ bool start(); // Queued -> Executing
+ bool pause(); // Executing -> Paused
+ bool resume(); // Paused -> Executing
+ bool complete(); // Executing/Paused -> Completed
+ bool abort(); // 非终态 -> Aborted
+ bool fail(std::string reason); // 任意 -> Failed
+
+ 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; }
+
+ // —— 汇总状态辅助(可选)—— //
+ // 根据外部提供的“PJ 是否已完成”判断,尝试把 CJ 聚合置为 Completed。
+ // isPjCompletedFn(pjId)->bool
+ bool tryAggregateComplete(const std::function<bool(const std::string&)>& isPjCompletedFn);
+
+ // 工具:统一字符串限制
+ static void clampString(std::string& s, size_t maxLen);
+ static bool asciiPrintable(const std::string& s);
+
+ static constexpr uint32_t CJ_MAGIC = 0x434A5031; // "CJP1"
+ static constexpr uint16_t CJ_VERSION = 0x0001;
+
+ void serialize(std::ostream& os) const;
+ static bool deserialize(std::istream& is, CControlJob& out, std::string* err = nullptr);
+
+ private:
+ void markQueued();
+ void markStart();
+ void markEnd();
+
+ protected:
+ // —— 标识 & 配置 —— //
+ std::string m_cjId;
+ uint8_t m_priority{ 5 }; // 缺省优先级(自定)
+
+ // —— 组成 —— //
+ std::vector<std::string> m_pjIds;
+ std::vector<CProcessJob*> m_pjs;
+
+ // —— 状态 / 文本 —— //
+ CJState m_state{ CJState::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; // CJID / PJID 等
+
+ // 错误列表
+ std::vector<ValidationIssue> m_issues;
+ };
+}
+
--
Gitblit v1.9.3