SecsFrame.Gem 是只依赖 SecsFrame 的独立程序集。
当前切片提供 Host/Equipment 两侧的通讯建立及应用接受策略、在线/离线及
应用转换策略、状态变量读取、设备常量读取、应用托管时钟、报告定义、事件
链接和带应用发送策略的 Collection Event,以及报警目录查询、单报警发送
启停、最小报警通知、远程命令链路与应用状态接受策略,不把 GEM 状态或消息
目录放入 HSMS 状态机。
GemHostServices 依赖 SecsHost;
GemEquipmentServices 依赖 SecsEquipment。服务不拥有
角色端点,释放服务只移除它注册的 Primary 路由,端点仍由应用释放。
GemMessageProfile 显式配置每个 Primary/Secondary 对、成功和
失败应答值、时钟文本 codec 以及报警发送启停控制码 codec。
CreateEngineeringBaseline() 当前返回以下常见工程配置:
| 操作 | Primary | Secondary |
|---|---|---|
| 通讯建立 | S1F13 | S1F14 |
| 在线查询 | S1F1 | S1F2 |
| 请求在线 | S1F17 | S1F18 |
| 请求离线 | S1F15 | S1F16 |
| 状态变量读取 | S1F3 | S1F4 |
| 设备常量读取 | S2F13 | S2F14 |
| 时钟读取 | S2F17 | S2F18 |
| 时钟设置 | S2F31 | S2F32 |
| 报告定义 | S2F33 | S2F34 |
| 事件链接 | S2F35 | S2F36 |
| Collection Event | S6F11 | S6F12 |
| 报警通知 | S5F1 | S5F2 |
| 报警发送启停 | S5F3 | S5F4 |
| 报警目录查询 | S5F5 | S5F6 |
| 远程命令 | S2F41 | S2F42 |
这张表描述仓库自己的默认配置,不是复制的 SEMI 规范表,也不表示已经
核对 E30 的必选能力、状态条件、数据项定义、报告生命周期或应答枚举。
默认成功应答为 Binary 0,失败应答为 Binary 1;报警发送允许/禁止码分别
为 Binary 0x80/0x00;时钟使用 UTC 的
yyyyMMddHHmmssff ASCII 工程格式。这些值是非规范性工程
基线,仍需使用授权 E30-0526 与目标设备核对。现场差异应使用独立 profile
和 codec,不应修改严格基线或根据 Function 奇偶推断消息含义。
GEM 服务不会创建第二个事件消费者。应用必须把角色端点单消费者事件流的 每个事件交给服务;未匹配事件仍返回给应用处理:
await foreach (var connectionEvent in equipment.GetEventsAsync(cancellationToken))
{
if (!await gem.TryDispatchAsync(connectionEvent, cancellationToken))
{
await HandleApplicationEventAsync(connectionEvent, cancellationToken);
}
}完成或接受通讯建立后,CommunicationState 变为
Communicating 并记录 PeerIdentity。在线/离线请求
成功后,两侧分别更新本地或已观察的远端 OnlineState。收到
非 Selected 的状态事件后,这些状态会重置;因此只分派数据事件会遗漏
断线重置。
Host 与 Equipment 都可使用
RegisterCommunicationEstablishmentHandler 注册单一可释放
策略。每个结构有效的对端通讯建立请求都会把请求方
GemIdentity 交给处理器。返回 false 时服务发送
profile 的失败应答和空身份 List,发起方抛出包含操作和原始应答字节的
GemRequestRejectedException。双方均不更新
CommunicationState 或 PeerIdentity;如果请求是
已通讯状态下的重新建立,既有状态和身份也会保留。
返回 true 时服务先完整写出成功 Secondary,再记录请求方身份
并进入 Communicating。没有注册策略时继续自动接受,保持此前
行为。应用可以改变策略结果并在同一 Selected 会话再次调用
EstablishCommunicationAsync;库不自动重试、不创建计时器或
后台恢复循环。
Host 与 Equipment 还可显式调用 RestoreCommunicationAsync。
该方法先等待当前或下一次 HSMS Selected,再通过当前 profile 发起恰好一次
既有通讯建立事务;它不消费第二份事件流、不循环,也不合并并发调用。等待
或事务期间的取消只终止本次调用,不会在后续重选时迟到发送。对端拒绝、
会话在等待后再次失效或其他传输失败会直接传播,应用决定是否再次调用。
收到非 Selected 状态事件时,通讯状态、对端身份和在线状态仍先全部重置。
恢复成功只重新记录 Communicating 与
PeerIdentity,不会把 OnlineState 隐式恢复为
断线前状态;应用必须另行请求或执行在线转换。与所有 GEM 状态一样,正确
重置仍依赖应用把完整单消费者事件流交给 TryDispatchAsync。
Equipment 可使用 RegisterOnlineStateTransitionHandler 注册
单一可释放策略。每个结构有效的 Host 在线/离线请求都会把当前状态和目标
状态交给处理器;返回 false 时 Equipment 发送 profile 的失败
应答且保持当前状态,Host 抛出包含操作和原始应答字节的
GemRequestRejectedException,不会更新观察状态。返回
true 时仍先完整写出成功 Secondary,再更新 Equipment 状态。
这两类策略没有注册处理器时都继续自动接受。处理器在服务锁外执行;释放 注册只影响后续请求,已经取得的处理器快照会完成。处理器异常和取消继续 传播给事件循环,不会被折叠为失败应答。同状态在线请求也会交给处理器。 应用应遵守角色端点的单消费者事件循环约束,使决策和状态转换按请求顺序 执行。
除前述通讯建立/在线转换策略外,后文还为远程命令、Collection Event 和 报警通知提供显式应用策略。当前仍不把变量读取、常量、时钟等其他操作硬性 门控在某个 GEM 状态上,也不自动重新建立通讯。这样可在尚未获得授权 E30 状态表前避免把未经核对的状态条件固化为公共行为。
Equipment 可按任意不可变 SecsItem 标识符运行期注册状态变量
和设备常量提供器。请求可以混用 U2、U4、ASCII 或厂商自定义标识类型,
响应按请求顺序返回提供器生成的动态 Item,值同样可以是嵌套 List。注册
对象可释放并替换,不需要预先生成完整设备消息、报告或事件目录。
IGemClock 把读时钟和设时钟交给应用。库不会修改操作系统时钟;
应用可以拒绝设置请求,Host 会收到包含操作和原始应答字节的
GemRequestRejectedException。
Host 使用 DefineReportsAsync 和
LinkEventReportsAsync 下发完整配置集。报告由动态 RPTID 和
有序状态变量标识组成;事件链接由动态 CEID 和有序 RPTID 组成。标识继续
使用不可变 SecsItem,不要求预生成消息或事件目录。
当前工程语义是完整集替换:
- 空报告集清除全部报告;替换报告集同时移除引用已删除报告的旧事件链接;
- 空链接集清除全部链接;空 RPTID 列表保留一个不携带报告的事件;
- 报告只引用当前已注册的状态变量,链接只引用当前已定义的报告;
- 未知变量或报告返回失败应答且不提交;畸形或重复标识作为协议异常上报;
- 校验成功的配置在发送成功应答前于 Equipment 锁内原子提交,因此 Host 收到成功应答时配置已经可见。
SendCollectionEventAsync 先在锁内快照事件链接、报告定义和
状态变量提供器,再在锁外按链接/定义顺序异步采值。并发替换配置或释放
注册不会改变正在生成的这一条事件;提供器仍可能按应用取消或失败。值保持
任意动态 Item,包括嵌套 List 和空报告。
Equipment 可另用 RegisterCollectionEventSendPolicyHandler
注册单一可释放发送策略。配置有效的每次发送会把当前
CommunicationState、OnlineState、DATAID 和
CEID 交给策略。返回 false 时
SendCollectionEventAsync 抛出本地
InvalidOperationException;状态变量提供器不会执行,也不会
创建 S6F11 事务,因此 Host 不会收到消息。
没有注册策略时继续采值并发送,保持此前行为。策略、状态和报告执行计划在 Equipment 锁内一起快照,策略在锁外执行;释放注册只影响后续发送,已取得 的快照会完成。策略异常和取消直接传播给调用方。应用可以改变策略结果并在 同一 Selected 会话再次显式调用发送;库不自动重试,也不内置未经授权 E30-0526 核对的通讯/在线状态矩阵。
Host 使用 RegisterCollectionEventHandler 注册单一可释放处理器。
处理器返回 true 发送成功应答,返回 false 发送失败
应答;没有处理器时明确失败。释放注册只影响后续事件,已经取得处理器快照
的分派会完成。应用处理器异常和取消继续传播给事件循环,不被库隐藏。
Equipment 使用 GemAlarmNotification 提供一个精确 Binary 代码
字节、动态 SecsItem 报警标识和七位 ASCII 文本,再通过
SendAlarmNotificationAsync 发送。库原样保留代码字节,不解释
其中的 set/clear、类别或厂商位;这些语义在取得授权 E30 副本并完成设备
互操作核对前由应用负责。
Host 使用 RegisterAlarmNotificationHandler 注册单一可释放
处理器。处理器返回 true 发送成功应答,返回
false 或没有处理器时发送失败应答。注册快照、释放、异常和
取消语义与 Collection Event 处理器一致。本切片不解释报警条件状态,也
不包含历史或持久化。Equipment 发送策略只向应用暴露当前状态,不内置
基于 GEM 在线状态的矩阵。
Equipment 使用 RegisterAlarm 注册不可变
GemAlarmDefinition。报警定义保留原始单字节代码、动态报警
标识和七位 ASCII 文本;标识必须唯一。注册对象默认允许发送,并通过
IsSendEnabled 暴露当前发送许可。注册对象可精确释放并重新
注册,全量目录按当前注册顺序返回。
Host 使用 ListAlarmsAsync 查询目录。省略标识或传入空列表会
取得全量快照;传入唯一标识列表时按请求顺序返回已注册的匹配项,未知标识
被忽略。查询回复不携带额外失败应答,因此未知标识不会被转换为 T3 超时。
请求和回复都是一次事务快照;并发注册或释放只影响后续查询。
Host 使用 SetAlarmSendEnabledAsync 控制一个已注册报警。
请求是控制码和动态报警标识组成的二元素 List;控制码由
GemAlarmControlCodec 严格映射。Equipment 在构造成功应答前
原子更新注册状态,未知标识使用 profile 的失败应答拒绝。
禁用只阻断当前注册 ID 后续进入
SendAlarmNotificationAsync 的调用,不修改报警定义、目录或
通知代码位,也不改变报警条件。发送许可在调用入口取得一次快照;已经通过
检查的并发发送会继续完成。未注册 ID 的原始通知保持既有发送行为。释放并
重新注册会恢复默认允许状态,HSMS 会话变化不会重置注册状态。
Equipment 可另用
RegisterAlarmNotificationSendPolicyHandler 注册单一可释放
发送策略。每个通过上述单报警发送许可检查的通知会把当前
CommunicationState、OnlineState 和完整
GemAlarmNotification 交给策略。返回 false
时 SendAlarmNotificationAsync 抛出本地
InvalidOperationException,不创建 S5F1 事务,因此 Host
不会收到消息。已禁用的已注册报警在策略之前拒绝,策略不会执行。
没有注册策略时继续发送,保持此前行为。发送许可、策略与状态在 Equipment 锁内按调用时一起快照,策略在锁外执行;释放注册只影响后续发送,已取得的 策略快照会完成。策略异常和取消直接传播给调用方。应用可以改变策略结果并 在同一 Selected 会话显式重试;库不自动重试,也不内置未经授权 E30-0526 核对的通讯/在线状态矩阵。
当前 API 故意不提供“全部报警”启停、批量控制、报警条件屏蔽或历史。 这些语义以及控制码含义仍需依据授权 E30-0526 和目标设备互操作结果核对。
Host 使用 GemRemoteCommand 携带动态命令标识和有序参数,再
通过 ExecuteRemoteCommandAsync 发起请求。命令、参数名称和
参数值均保持为任意非 null SecsItem;参数名称必须唯一,值可
包含嵌套 List。库不把现场命令限制为预生成枚举或 ASCII 字符串。
Equipment 使用 RegisterRemoteCommand 按不可变
SecsItem 命令标识注册多个精确运行期处理器;返回的
GemRemoteCommandEntryRegistration 暴露精确标识和
IsExecutionEnabled,可用
SetExecutionEnabled(bool) 在运行期启停,也可释放。同一结构
相等标识不能重复注册,新注册项默认允许执行。应用还可使用
RegisterRemoteCommandHandler 注册单一全局回退处理器。
分派优先选择精确处理器,未匹配时才选择全局回退;两者都不存在时 Equipment
使用 profile 的失败应答值和空参数结果立即回复。
已匹配但禁用的精确项表示“已知但当前不可执行”,同样立即返回失败结果; 它不会调用精确处理器、接受策略或全局回退,避免停用命令经回退路径绕过。 应用重新启用后可在同一 Selected 会话显式重试。释放精确项后,该标识才 重新成为未匹配命令并可进入全局回退;重新注册的新项恢复默认启用状态。
选中的处理器返回 GemRemoteCommandResult,其中包含一个原始
整体完成码和有序参数结果;每个参数结果保留动态名称与原始单字节代码。
Host 返回完整结果,不把非零代码折叠成异常,也不解释代码枚举。
Equipment 可另用 RegisterRemoteCommandAcceptanceHandler
注册单一可释放接受策略。存在执行处理器时,每个结构有效的请求先把当前
CommunicationState、OnlineState 和已解码命令
交给策略。返回 false 时 Equipment 使用 profile 的失败应答值
和空参数结果回复,执行处理器不会被调用,双方 GEM 状态不变;Host 仍返回
原始 GemRemoteCommandResult,不会把非零结果转换为异常。
没有注册接受策略时命令直接进入选中的执行处理器,保持此前行为。没有执行 处理器或精确项已禁用时请求立即失败,接受策略不会执行。接受策略、精确项 可用性、精确/回退选择和当前状态在 Equipment 锁内按请求一起快照,并在 锁外按策略、执行顺序调用;启停或释放注册只影响后续请求,已取得的快照会 完成。策略或执行处理器的异常和取消继续传播给事件循环,不会被折叠为失败 应答。
当前切片只要求请求参数名和结果参数名各自唯一,不推断结果必须覆盖哪些 请求参数,也不内置任何通讯/在线状态矩阵。运行期目录只负责应用侧精确 分派和本地可用性,不新增 E30 消息、不提供 Host 目录查询,也不包含参数 Schema、角色/用户权限、排队、自动重试、幂等策略或执行历史。
当前实现严格要求:
- 基础 Primary 设置 W-Bit,请求体符合 profile 对应的空 Body、List、 ASCII 或 Identity 结构;
- Secondary 的 Stream、Function 和 W-Bit 与配置完全匹配;
- 通讯建立回复是确认字节与身份组成的二元素 List;接受时必须包含两项 ASCII Identity,策略拒绝时使用 profile 失败确认和空身份 List;
- 在线/离线请求必须设置 W-Bit 且 Body 为空;应用拒绝使用 profile 失败 应答,接受应答写出完成前不得改变 Equipment 在线状态;
- 状态变量和设备常量请求只引用已注册标识,提供器不得返回 null;
- 时钟字符串由显式 codec 完整解析;
- 报告/链接请求是二元素 List,Collection Event 是三元素 List,各嵌套项 的标识和值列表形状必须完整且标识不能产生歧义;
- 报警通知是三元素 List,代码必须是恰好一个 Binary 字节,文本必须为 ASCII,报警标识保持为任意非 null 动态 Item;
- 报警目录请求是唯一动态标识组成的 List,空 List 表示全量查询;回复是 报警定义 List,每项必须包含单字节 Binary 代码、唯一标识和 ASCII 文本;
- 报警发送启停请求是二元素 List,控制码必须是恰好一个 Binary 字节且为 profile 配置的允许或禁止码;未知报警标识使用失败应答拒绝;
- 远程命令请求是命令标识和参数列表组成的二元素 List,每个参数是名称与 值组成的二元素 List;回复是整体单字节代码和参数结果列表组成的二元素 List,每个参数结果必须包含唯一名称和单字节 Binary 代码;
- 报告配置请求和 Collection Event 必须设置 W-Bit,Secondary 的消息对和 应答字节必须与 profile 匹配;报警通知遵循相同要求;
- 远程命令必须设置 W-Bit 且 Secondary 消息对完全匹配;整体和参数结果码 保持原始字节,不限制为 profile 的成功/失败两个值;接受策略拒绝时使用 profile 失败值和空参数结果,且不得调用执行处理器;已禁用精确项也使用 相同失败结果,并且不得调用接受策略、精确处理器或全局回退。
畸形输入和提供器失败会作为异常返回应用事件循环;语义有效但引用未知变量 或报告的配置使用失败应答拒绝。本切片尚未实现自动 S9Fx、错误 Secondary、 后台通讯重建、报警历史/批量控制、完整命令权限/参数 Schema/调度或完整 GEM 错误恢复,这些行为不能从当前 API 推断为标准合规。
公开 SEMI 目录当前标识 GEM 基线为 E30-0526。仍需使用团队合法获得的 副本核对消息条件、COMMACK/ONLACK/OFLACK/TIACK 语义、MDLN 条件结构、 空 SVID/ECID 列表行为、报告定义与链接生命周期、Collection Event 数据 结构和应答、报警通知/目录/发送启停结构、代码位与控制码语义、时间格式 选择、状态转换和错误响应,以及远程命令结构、整体/参数结果代码语义。 不得把标准正文、 消息表、状态图或 Schema 提交仓库。完整版本和版权边界见 STANDARDS.md。
当前证据包括三目标框架的严格输入测试,以及 Host Active / Equipment Passive 真实 TCP 下的双向通讯建立、首次建立拒绝后同会话恢复、已通讯 重新建立拒绝时的状态/身份保持与恢复、Separate 后状态/身份清空、重选后的 显式单次恢复、等待取消后零迟到事务、恢复拒绝与显式重试、在线状态不隐式 恢复、在线转换接受/拒绝与状态保持、异构动态标识、报告定义、 事件链接、Collection Event 嵌套值与空报告、应用发送策略拒绝零采值/零 事务和同会话重试、报警通知接受/拒绝、应用发送策略拒绝零事务与同会话 重试、已禁用报警优先拒绝、配置/事件拒绝、报警目录全量/选择查询与释放 快照、单报警发送启停与未知标识拒绝、远程命令动态参数与结果、精确目录 优先/全局回退/释放恢复、精确项禁用无回退绕过和重新启用后的同会话重试、 无处理器拒绝、应用状态拒绝短路与同会话重试、时钟读写和 Linktest。它们 是独立工程验证,不是 SEMI 一致性认证。