E40 Process Jobs + E94 Control Jobs + E30 communication state
GEM300 layer: SEMI E40-0705 Process Job and E94-0705 Control Job state machines, plus the E30 §6.1 communication-state machine that sits between HSMS SELECT and full GEM communication. Data-driven via data/process_job_state.yaml and data/control_job_state.yaml, mirroring the existing control_state.yaml pattern. Wire coverage: S14F9/F10 CreateObject (CJ) host -> equipment S14F11/F12 DeleteObject (CJ) host -> equipment S16F5/F6 PRJobCommand host -> equipment S16F9 PRJobAlert equipment -> host S16F11/F12 PRJobCreate (simplified body) host -> equipment S16F13/F14 PRJobDequeue host -> equipment S16F27/F28 CJobCommand host -> equipment Process Job FSM exposes 8 states matching PRJOBSTATE bytes (E40 §10.3.2); HOQ is reorder-aware (move-to-head against an insertion-order vector); Stop/Abort on a Queued PJ routes through ABORTING so the host observes PRJOBSTATE=7 on the wire (§6.3); alert_enabled is settable per-PJ for PRALERT control; FSM dispatches through ProcessJobStore::on_change_ dynamically so a late set_state_change_handler() reaches existing PJs. Hardening: loader rejects NoState (sentinel) as initial/from/to and rejects `on: created` rows; static_asserts pin enum values to wire bytes; ProcessJobStore is non-movable to keep the per-PJ this-capture safe. Server simulator cascades the full CJ -> PJ lifecycle on CJSTART so the wire trace exercises every legal state. CEIDs 400/401 fire on CJ state changes via the existing event-report pipeline. Tests: 60+ new assertions across test_process_jobs, test_control_jobs, test_communication_state, test_hsms_connection, plus loader and messages round-trip coverage. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -251,6 +251,24 @@ messages:
|
||||
parser: parse_s2f18
|
||||
body: {kind: scalar, item_type: ASCII, param: time_str}
|
||||
|
||||
# S2F25 / S2F26 — Loopback Diagnostic. Host sends an arbitrary byte
|
||||
# blob; equipment echoes it back unchanged in S2F26. Useful for round-
|
||||
# trip diagnostics and as a "keep-alive at the application layer."
|
||||
- id: S2F25
|
||||
stream: 2
|
||||
function: 25
|
||||
w: true
|
||||
builder: s2f25_loopback_diagnostic_request
|
||||
parser: parse_s2f25
|
||||
body: {kind: scalar, item_type: BINARY, param: payload}
|
||||
|
||||
- id: S2F26
|
||||
stream: 2
|
||||
function: 26
|
||||
builder: s2f26_loopback_diagnostic_data
|
||||
parser: parse_s2f26
|
||||
body: {kind: scalar, item_type: BINARY, param: payload}
|
||||
|
||||
- id: S2F29
|
||||
stream: 2
|
||||
function: 29
|
||||
@@ -660,6 +678,53 @@ messages:
|
||||
- {name: alid, shape: {kind: scalar, item_type: U4}}
|
||||
- {name: altx, shape: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
# S5F9 / S5F10 — Exception Post Notify / Confirm (E5).
|
||||
# Equipment posts a recoverable exception; the body lists the allowed
|
||||
# recovery actions that S5F13 may then send. Host acks via S5F10.
|
||||
- id: S5F9
|
||||
stream: 5
|
||||
function: 9
|
||||
w: true
|
||||
builder: s5f9_exception_post_notify
|
||||
parser: parse_s5f9
|
||||
body:
|
||||
kind: list
|
||||
struct_name: ExceptionPost
|
||||
fields:
|
||||
- {name: exid, shape: {kind: scalar, item_type: U4}}
|
||||
- {name: extype, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: exmessage, shape: {kind: scalar, item_type: ASCII}}
|
||||
- name: exrecvra
|
||||
shape: {kind: list_of, element: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S5F10
|
||||
stream: 5
|
||||
function: 10
|
||||
builder: s5f10_exception_post_confirm
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: AlarmAck, param: ack}
|
||||
|
||||
# S5F11 / S5F12 — Exception Clear Notify / Confirm. Equipment signals
|
||||
# that a previously-posted exception has cleared.
|
||||
- id: S5F11
|
||||
stream: 5
|
||||
function: 11
|
||||
w: true
|
||||
builder: s5f11_exception_clear_notify
|
||||
parser: parse_s5f11
|
||||
body:
|
||||
kind: list
|
||||
struct_name: ExceptionClear
|
||||
fields:
|
||||
- {name: exid, shape: {kind: scalar, item_type: U4}}
|
||||
- {name: extype, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: exmessage, shape: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S5F12
|
||||
stream: 5
|
||||
function: 12
|
||||
builder: s5f12_exception_clear_confirm
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: AlarmAck, param: ack}
|
||||
|
||||
# =====================================================================
|
||||
# S6 — Data collection
|
||||
# =====================================================================
|
||||
@@ -909,3 +974,168 @@ messages:
|
||||
function: 6
|
||||
builder: s10f6_terminal_display_multi_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: TerminalAck, param: ack}
|
||||
|
||||
# =====================================================================
|
||||
# S14 — Object services (E94 ControlJob create/delete).
|
||||
#
|
||||
# Real E14 ObjectService is a fully generic generic-attribute carrier;
|
||||
# for the E94 demo we use a simplified shape that names the object
|
||||
# type ("ControlJob") and carries the CTLJOBID + contained PRJOBIDs
|
||||
# directly. The wire shape is a defensible subset of E14F9 with the
|
||||
# generic ATTRIBUTES list specialized.
|
||||
# =====================================================================
|
||||
|
||||
# S14F9 / F10 — CreateObject (CJ). Host asks the equipment to bring
|
||||
# a new ControlJob into existence and registers the list of PJs it
|
||||
# contains; the CJ starts in CJ-QUEUED.
|
||||
- id: S14F9
|
||||
stream: 14
|
||||
function: 9
|
||||
w: true
|
||||
builder: s14f9_create_control_job
|
||||
parser: parse_s14f9
|
||||
body:
|
||||
kind: list
|
||||
struct_name: CreateControlJobRequest
|
||||
fields:
|
||||
- {name: ctljobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- name: prjobids
|
||||
shape: {kind: list_of, element: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S14F10
|
||||
stream: 14
|
||||
function: 10
|
||||
builder: s14f10_create_control_job_ack
|
||||
parser: parse_s14f10
|
||||
body:
|
||||
kind: list
|
||||
struct_name: CreateControlJobAck
|
||||
fields:
|
||||
- {name: ctljobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: ack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: ObjectAck}}
|
||||
|
||||
# S14F11 / F12 — DeleteObject (CJ).
|
||||
- id: S14F11
|
||||
stream: 14
|
||||
function: 11
|
||||
w: true
|
||||
builder: s14f11_delete_control_job
|
||||
parser: parse_s14f11
|
||||
body: {kind: scalar, item_type: ASCII, param: ctljobid}
|
||||
|
||||
- id: S14F12
|
||||
stream: 14
|
||||
function: 12
|
||||
builder: s14f12_delete_control_job_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: ObjectAck, param: ack}
|
||||
|
||||
# =====================================================================
|
||||
# S16 — Process Management (E40 Process Jobs, E94 Control Jobs).
|
||||
#
|
||||
# Wire shapes are E40-0705 / E94-0705 with a couple of deliberate
|
||||
# simplifications documented inline. The PJ/CJ state set and the legal
|
||||
# transitions live in data/process_job_state.yaml and
|
||||
# data/control_job_state.yaml respectively (data-driven, same pattern
|
||||
# as data/control_state.yaml).
|
||||
# =====================================================================
|
||||
|
||||
# S16F5 / F6 — PRJobCommand. Host issues Start / Pause / Resume /
|
||||
# Stop / Abort / HOQ against an existing process job.
|
||||
- id: S16F5
|
||||
stream: 16
|
||||
function: 5
|
||||
w: true
|
||||
builder: s16f5_pr_job_command
|
||||
parser: parse_s16f5
|
||||
body:
|
||||
kind: list
|
||||
struct_name: PRJobCommandRequest
|
||||
fields:
|
||||
- {name: prjobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: prcmd, shape: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S16F6
|
||||
stream: 16
|
||||
function: 6
|
||||
builder: s16f6_pr_job_command_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck, param: ack}
|
||||
|
||||
# S16F9 — PRJobAlert. E->H one-way alert that a PJ entered a new
|
||||
# state. PRJOBSTATE is the E40 PJ state code (0..7). Equipment
|
||||
# emits one per PJ state transition when alerts are enabled.
|
||||
- id: S16F9
|
||||
stream: 16
|
||||
function: 9
|
||||
builder: s16f9_pr_job_alert
|
||||
parser: parse_s16f9
|
||||
body:
|
||||
kind: list
|
||||
struct_name: PRJobAlert
|
||||
fields:
|
||||
- {name: prjobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: prjobstate, shape: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessJobState}}
|
||||
|
||||
# S16F11 / F12 — PRJobCreate.
|
||||
#
|
||||
# Real E40-0705 S16F11 body is <L,5 PRJOBID MF PRRECIPEMETHOD
|
||||
# RCPSPEC L MTRLOUTSPEC L PRPROCESSPARAMS>. We simplify to the
|
||||
# three pieces that actually drive the demo state machine:
|
||||
# PRJOBID, recipe (PPID), and the list of material identifiers. MF
|
||||
# / PRRECIPEMETHOD / PRPROCESSPARAMS are tool-specific; layering
|
||||
# them in is a YAML edit + builder overload, not surgery.
|
||||
- id: S16F11
|
||||
stream: 16
|
||||
function: 11
|
||||
w: true
|
||||
builder: s16f11_pr_job_create
|
||||
parser: parse_s16f11
|
||||
body:
|
||||
kind: list
|
||||
struct_name: PRJobCreateRequest
|
||||
fields:
|
||||
- {name: prjobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- name: mtrloutspec
|
||||
shape: {kind: list_of, element: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S16F12
|
||||
stream: 16
|
||||
function: 12
|
||||
builder: s16f12_pr_job_create_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck, param: ack}
|
||||
|
||||
# S16F13 / F14 — PRJobDequeue. Host removes a queued PJ.
|
||||
- id: S16F13
|
||||
stream: 16
|
||||
function: 13
|
||||
w: true
|
||||
builder: s16f13_pr_job_dequeue
|
||||
parser: parse_s16f13
|
||||
body: {kind: scalar, item_type: ASCII, param: prjobid}
|
||||
|
||||
- id: S16F14
|
||||
stream: 16
|
||||
function: 14
|
||||
builder: s16f14_pr_job_dequeue_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck, param: ack}
|
||||
|
||||
# S16F27 / F28 — CJobCommand (E94). Host issues Start / Pause /
|
||||
# Resume / Stop / Abort against an existing CJ.
|
||||
- id: S16F27
|
||||
stream: 16
|
||||
function: 27
|
||||
w: true
|
||||
builder: s16f27_cj_command
|
||||
parser: parse_s16f27
|
||||
body:
|
||||
kind: list
|
||||
struct_name: CJobCommandRequest
|
||||
fields:
|
||||
- {name: ctljobid, shape: {kind: scalar, item_type: ASCII}}
|
||||
- {name: ctljobcmd, shape: {kind: scalar, item_type: ASCII}}
|
||||
|
||||
- id: S16F28
|
||||
stream: 16
|
||||
function: 28
|
||||
builder: s16f28_cj_command_ack
|
||||
body: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck, param: ack}
|
||||
|
||||
Reference in New Issue
Block a user