Files
secs-gem/data/messages.yaml
T
raphael 90c177b7ce 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>
2026-06-07 21:00:32 +02:00

1142 lines
33 KiB
YAML

# SECS-II message catalog. Each entry describes one SxFy primary or reply;
# the codegen (tools/gen_messages.py) reads this and emits builders + parsers.
#
# Shape grammar (see tools/gen_messages.py for the full description):
#
# none - header-only (no body)
# scalar: - single Item; cpp_type derived from item_type/enum
# item_type: ASCII | BINARY_BYTE | BOOLEAN | U1..U8 | I1..I8 | F4 | F8 | ITEM
# enum: <C++ enum> - optional
# param: <name> - optional, default "value"
# list: - fixed-arity <L,k>
# fields: [{name, shape}, ...]
# struct_name: <Name> - optional; if set, parser returns the struct
# external_struct: bool - optional; struct is assumed to exist already
# list_of: - variable-arity <L,n>
# element: <shape>
# name: <param-name> - optional, default "values"
#
# Special-case messages whose shape can't be expressed (S1F4's optional-item
# semantics, S5F6's per-row ALCD callback) live in messages_helpers.hpp.
messages:
# =====================================================================
# S1 — Equipment status
# =====================================================================
- id: S1F1
stream: 1
function: 1
w: true
builder: s1f1_are_you_there
- id: S1F2
stream: 1
function: 2
builder: s1f2_on_line_data
body:
kind: list
fields:
- {name: mdln, shape: {kind: scalar, item_type: ASCII}}
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- id: S1F3
stream: 1
function: 3
w: true
builder: s1f3_selected_status_request
parser: parse_s1f3
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: svids
- id: S1F11
stream: 1
function: 11
w: true
builder: s1f11_status_namelist_request
parser: parse_s1f11
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: svids
- id: S1F12
stream: 1
function: 12
builder: s1f12_status_namelist_data
parser: parse_s1f12
body:
kind: list_of
name: items
element:
kind: list
struct_name: StatusName
fields:
- {name: id, shape: {kind: scalar, item_type: U4}}
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: units, shape: {kind: scalar, item_type: ASCII}}
- id: S1F13
stream: 1
function: 13
w: true
builder: s1f13_establish_comms
body:
kind: list
fields:
- {name: mdln, shape: {kind: scalar, item_type: ASCII}}
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- id: S1F14
stream: 1
function: 14
builder: s1f14_establish_comms_ack
body:
kind: list
fields:
- {name: ack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: CommAck}}
- name: identity
shape:
kind: list
struct_name: McAck
fields:
- {name: mdln, shape: {kind: scalar, item_type: ASCII}}
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- id: S1F15
stream: 1
function: 15
w: true
builder: s1f15_request_offline
- id: S1F16
stream: 1
function: 16
builder: s1f16_offline_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: OfflineAck, param: ack}
- id: S1F17
stream: 1
function: 17
w: true
builder: s1f17_request_online
- id: S1F18
stream: 1
function: 18
builder: s1f18_online_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: OnlineAck, param: ack}
# S1F19 / S1F20 — Get GEM Compliance. Host asks the equipment which GEM
# capabilities it supports; equipment replies with its SOFTREV, an
# implementer-defined equipment-type string, and a (CCODE, CDESC) list
# per E30 Appendix A. Closes the "Documentation" Fundamental capability
# by letting the equipment self-report its own COMPLIANCE.md status.
- id: S1F19
stream: 1
function: 19
w: true
builder: s1f19_get_gem_compliance_request
- id: S1F20
stream: 1
function: 20
builder: s1f20_get_gem_compliance_data
parser: parse_s1f20
body:
kind: list
struct_name: GemCompliance
fields:
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- {name: equipment_type, shape: {kind: scalar, item_type: ASCII}}
- name: capabilities
shape:
kind: list_of
element:
kind: list
struct_name: CapabilityEntry
fields:
- {name: ccode, shape: {kind: scalar, item_type: U1}}
- {name: cdesc, shape: {kind: scalar, item_type: ASCII}}
# S1F21 / S1F22 — Data Variable Namelist (same wire shape as S1F11/F12
# but for DVIDs). Reuses the StatusName struct emitted by S1F12.
- id: S1F21
stream: 1
function: 21
w: true
builder: s1f21_data_variable_namelist_request
parser: parse_s1f21
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: vids
- id: S1F22
stream: 1
function: 22
builder: s1f22_data_variable_namelist_data
parser: parse_s1f22
body:
kind: list_of
name: items
element:
kind: list
struct_name: StatusName
fields:
- {name: id, shape: {kind: scalar, item_type: U4}}
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: units, shape: {kind: scalar, item_type: ASCII}}
# =====================================================================
# S2 — Equipment control + reports
# =====================================================================
- id: S2F13
stream: 2
function: 13
w: true
builder: s2f13_ec_request
parser: parse_s2f13
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: ecids
- id: S2F14
stream: 2
function: 14
builder: s2f14_ec_data
parser: parse_s2f14
body:
kind: list_of
element: {kind: scalar, item_type: ITEM}
name: values
- id: S2F15
stream: 2
function: 15
w: true
builder: s2f15_ec_send
parser: parse_s2f15
body:
kind: list_of
name: sets
element:
kind: list
struct_name: EcSet
fields:
- {name: ecid, shape: {kind: scalar, item_type: U4}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- id: S2F16
stream: 2
function: 16
builder: s2f16_ec_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EquipmentAck, param: eac}
- id: S2F17
stream: 2
function: 17
w: true
builder: s2f17_date_time_request
- id: S2F18
stream: 2
function: 18
builder: s2f18_date_time_data
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
w: true
builder: s2f29_ec_namelist_request
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: ecids
- id: S2F30
stream: 2
function: 30
builder: s2f30_ec_namelist_data
body:
kind: list_of
name: items
element:
kind: list
struct_name: EcNameRow
fields:
- {name: ecid, shape: {kind: scalar, item_type: U4}}
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: min_str, shape: {kind: scalar, item_type: ASCII}}
- {name: max_str, shape: {kind: scalar, item_type: ASCII}}
- {name: default_str, shape: {kind: scalar, item_type: ASCII}}
- {name: units, shape: {kind: scalar, item_type: ASCII}}
- id: S2F31
stream: 2
function: 31
w: true
builder: s2f31_date_time_set
parser: parse_s2f31
body: {kind: scalar, item_type: ASCII, param: time_str}
- id: S2F32
stream: 2
function: 32
builder: s2f32_date_time_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: TimeAck, param: ack}
- id: S2F33
stream: 2
function: 33
w: true
builder: s2f33_define_report
parser: parse_s2f33
body:
kind: list
struct_name: DefineReportRequest
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- name: reports
shape:
kind: list_of
element:
kind: list
struct_name: DefineReportEntry
fields:
- {name: rptid, shape: {kind: scalar, item_type: U4}}
- name: vids
shape:
kind: list_of
element: {kind: scalar, item_type: U4}
- id: S2F34
stream: 2
function: 34
builder: s2f34_define_report_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: DefineReportAck, param: ack}
- id: S2F35
stream: 2
function: 35
w: true
builder: s2f35_link_event_report
parser: parse_s2f35
body:
kind: list
struct_name: LinkEventReportRequest
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- name: links
shape:
kind: list_of
element:
kind: list
struct_name: LinkEventEntry
fields:
- {name: ceid, shape: {kind: scalar, item_type: U4}}
- name: rptids
shape:
kind: list_of
element: {kind: scalar, item_type: U4}
- id: S2F36
stream: 2
function: 36
builder: s2f36_link_event_report_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: LinkEventAck, param: ack}
- id: S2F37
stream: 2
function: 37
w: true
builder: s2f37_enable_event
parser: parse_s2f37
body:
kind: list
struct_name: EnableEventRequest
fields:
- {name: enable, shape: {kind: scalar, item_type: BOOLEAN}}
- name: ceids
shape: {kind: list_of, element: {kind: scalar, item_type: U4}}
- id: S2F38
stream: 2
function: 38
builder: s2f38_enable_event_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EnableEventAck, param: ack}
- id: S2F41
stream: 2
function: 41
w: true
builder: s2f41_host_command
parser: parse_s2f41
body:
kind: list
struct_name: HostCommand
fields:
- {name: rcmd, shape: {kind: scalar, item_type: ASCII}}
- name: params
shape:
kind: list_of
element:
kind: list
struct_name: CommandParameter
external_struct: true
fields:
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- id: S2F42
stream: 2
function: 42
builder: s2f42_host_command_ack
parser: parse_s2f42
body:
kind: list
struct_name: HostCommandReply
fields:
- {name: hcack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck}}
- name: cpacks
shape:
kind: list_of
element:
kind: list
struct_name: CommandParameterAck
fields:
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: code, shape: {kind: scalar, item_type: BINARY_BYTE}}
# S2F23 / S2F24 — Trace Initialize Send (E30 §6.12). Host requests
# periodic SVID sampling: every DSPER, equipment captures the SVID
# values; every REPGSZ samples it emits an S6F1 batch; after TOTSMP
# total samples it stops. Periodic execution is the application's
# responsibility; this codebase only stores the request.
- id: S2F23
stream: 2
function: 23
w: true
builder: s2f23_trace_initialize_send
parser: parse_s2f23
body:
kind: list
struct_name: TraceInit
fields:
- {name: trid, shape: {kind: scalar, item_type: U4}}
- {name: dsper, shape: {kind: scalar, item_type: ASCII}}
- {name: totsmp, shape: {kind: scalar, item_type: U4}}
- {name: repgsz, shape: {kind: scalar, item_type: U4}}
- name: svids
shape:
kind: list_of
element: {kind: scalar, item_type: U4}
- id: S2F24
stream: 2
function: 24
builder: s2f24_trace_initialize_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: TraceAck, param: tiaack}
# S6F1 / S6F2 — Trace Data Send. Emitted by equipment when a batch
# completes. `values` holds REPGSZ * len(svids) Items (REPGSZ samples
# of len(svids) values each), but the shape lets the application choose
# any layout it wants.
- id: S6F1
stream: 6
function: 1
w: true
builder: s6f1_trace_data_send
parser: parse_s6f1
body:
kind: list
struct_name: TraceSample
fields:
- {name: trid, shape: {kind: scalar, item_type: U4}}
- {name: smpln, shape: {kind: scalar, item_type: U4}}
- {name: stime, shape: {kind: scalar, item_type: ASCII}}
- name: values
shape:
kind: list_of
element: {kind: scalar, item_type: ITEM}
- id: S6F2
stream: 6
function: 2
builder: s6f2_trace_data_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EventReportAck, param: ack}
# S2F45 / S2F46 / S2F47 / S2F48 — Limits Monitoring (E30 §6.21). Each
# VID may carry several LimitDefinitions (one per LIMITID), each with
# an upper / lower deadband expressed as an arbitrary Item.
- id: S2F45
stream: 2
function: 45
w: true
builder: s2f45_define_variable_limits
parser: parse_s2f45
body:
kind: list
struct_name: DefineLimitsRequest
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- name: entries
shape:
kind: list_of
element:
kind: list
struct_name: VidLimitsEntry
fields:
- {name: vid, shape: {kind: scalar, item_type: U4}}
- name: limits
shape:
kind: list_of
element:
kind: list
struct_name: LimitDefinition
external_struct: true
fields:
- {name: limitid, shape: {kind: scalar, item_type: U1}}
- {name: upper, shape: {kind: scalar, item_type: ITEM}}
- {name: lower, shape: {kind: scalar, item_type: ITEM}}
- id: S2F46
stream: 2
function: 46
builder: s2f46_define_variable_limits_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: LimitMonitorAck, param: vlaack}
- id: S2F47
stream: 2
function: 47
w: true
builder: s2f47_variable_limit_attribute_request
parser: parse_s2f47
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: vids
- id: S2F48
stream: 2
function: 48
builder: s2f48_variable_limit_attribute_data
body:
kind: list_of
name: entries
element:
kind: list
struct_name: VidLimitsEntry
fields:
- {name: vid, shape: {kind: scalar, item_type: U4}}
- name: limits
shape:
kind: list_of
element:
kind: list
struct_name: LimitDefinition
external_struct: true
fields:
- {name: limitid, shape: {kind: scalar, item_type: U1}}
- {name: upper, shape: {kind: scalar, item_type: ITEM}}
- {name: lower, shape: {kind: scalar, item_type: ITEM}}
# S2F43 / S2F44 — Reset Spooling (E30 §6.22, configure spoolable streams).
- id: S2F43
stream: 2
function: 43
w: true
builder: s2f43_reset_spooling
parser: parse_s2f43
body:
kind: list_of
element: {kind: scalar, item_type: BINARY_BYTE}
name: streams
- id: S2F44
stream: 2
function: 44
builder: s2f44_reset_spooling_ack
parser: parse_s2f44
body:
kind: list
struct_name: ResetSpoolingReply
fields:
- {name: rspack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: ResetSpoolAck}}
- name: per_stream
shape:
kind: list_of
element:
kind: list
struct_name: ResetSpoolStreamAck
fields:
- {name: stream, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: strack, shape: {kind: scalar, item_type: BINARY_BYTE}}
# =====================================================================
# S5 — Alarms
# =====================================================================
- id: S5F1
stream: 5
function: 1
w: true
builder: s5f1_alarm_report
parser: parse_s5f1
body:
kind: list
struct_name: AlarmReport
fields:
- {name: alcd, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: alid, shape: {kind: scalar, item_type: U4}}
- {name: altx, shape: {kind: scalar, item_type: ASCII}}
- id: S5F2
stream: 5
function: 2
builder: s5f2_alarm_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: AlarmAck, param: ack}
- id: S5F3
stream: 5
function: 3
w: true
builder: s5f3_enable_alarm
parser: parse_s5f3
body:
kind: list
struct_name: EnableAlarmRequest
fields:
- {name: aled, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: alid, shape: {kind: scalar, item_type: U4}}
- id: S5F4
stream: 5
function: 4
builder: s5f4_enable_alarm_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: AlarmAck, param: ack}
- id: S5F5
stream: 5
function: 5
w: true
builder: s5f5_list_alarms_request
parser: parse_s5f5
body:
kind: list_of
element: {kind: scalar, item_type: U4}
name: alids
# S5F6 is hand-written (per-row ALCD requires an active-callback API).
# S5F7 / S5F8 — List Enabled Alarms. Same wire shape as S5F6 but only
# alarms with bit-7 of their stored "enabled" flag are returned.
- id: S5F7
stream: 5
function: 7
w: true
builder: s5f7_list_enabled_alarms_request
- id: S5F8
stream: 5
function: 8
builder: s5f8_list_enabled_alarms_data
parser: parse_s5f8
body:
kind: list_of
name: items
element:
kind: list
struct_name: AlarmListing
fields:
- {name: alcd, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {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
# =====================================================================
- id: S6F11
stream: 6
function: 11
w: true
builder: s6f11_event_report
parser: parse_s6f11
body:
kind: list
struct_name: EventReportMessage
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- {name: ceid, shape: {kind: scalar, item_type: U4}}
- name: reports
shape:
kind: list_of
element:
kind: list
struct_name: ReportData
external_struct: true
fields:
- {name: rptid, shape: {kind: scalar, item_type: U4}}
- name: values
shape: {kind: list_of, element: {kind: scalar, item_type: ITEM}}
- id: S6F12
stream: 6
function: 12
builder: s6f12_event_report_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EventReportAck, param: ack}
# S6F23 / S6F24 — Request Spooled Data (E30 §6.22; host transmits or purges).
- id: S6F23
stream: 6
function: 23
w: true
builder: s6f23_request_spool_data
parser: parse_s6f23
body: {kind: scalar, item_type: BINARY_BYTE, enum: SpoolRequestCode, param: rsdc}
- id: S6F24
stream: 6
function: 24
builder: s6f24_request_spool_data_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: SpoolRequestAck, param: rsda}
# S6F25 / S6F26 — Spool data ready notification (equipment-initiated;
# fires on re-SELECT when there's queued data). Host acks with S6F26;
# then host decides whether to issue S6F23(Transmit) or S6F23(Purge).
- id: S6F25
stream: 6
function: 25
w: true
builder: s6f25_spool_data_ready
parser: parse_s6f25
body: {kind: scalar, item_type: U4, param: num_msg}
- id: S6F26
stream: 6
function: 26
builder: s6f26_spool_data_ready_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EventReportAck, param: ack}
# =====================================================================
# S7 — Process programs
# =====================================================================
- id: S7F3
stream: 7
function: 3
w: true
builder: s7f3_process_program_send
parser: parse_s7f3
body:
kind: list
struct_name: ProcessProgram
fields:
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
- {name: ppbody, shape: {kind: scalar, item_type: BINARY}}
- id: S7F4
stream: 7
function: 4
builder: s7f4_process_program_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessProgramAck, param: ack}
- id: S7F5
stream: 7
function: 5
w: true
builder: s7f5_process_program_request
parser: parse_s7f5
body: {kind: scalar, item_type: ASCII, param: ppid}
- id: S7F6
stream: 7
function: 6
builder: s7f6_process_program_data
parser: parse_s7f6
body:
kind: list
struct_name: ProcessProgram
fields:
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
- {name: ppbody, shape: {kind: scalar, item_type: BINARY}}
- id: S7F19
stream: 7
function: 19
w: true
builder: s7f19_current_eppd_request
- id: S7F20
stream: 7
function: 20
builder: s7f20_current_eppd_data
parser: parse_s7f20
body:
kind: list_of
element: {kind: scalar, item_type: ASCII}
name: ppids
# =====================================================================
# S9 — Protocol error notifications (E5). All carry the 10-byte
# offending message header (MHEAD) as a single BINARY item, except
# S9F13 which carries <L,2 <A MEXP> <A EDID>>. These are
# equipment-initiated (typically W=0) and host-side acks are not
# mandatory; we emit them on the wire but don't expect replies.
# =====================================================================
- id: S9F1
stream: 9
function: 1
builder: s9f1_unrecognized_device_id
parser: parse_s9f1
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F3
stream: 9
function: 3
builder: s9f3_unrecognized_stream_type
parser: parse_s9f3
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F5
stream: 9
function: 5
builder: s9f5_unrecognized_function_type
parser: parse_s9f5
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F7
stream: 9
function: 7
builder: s9f7_illegal_data
parser: parse_s9f7
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F9
stream: 9
function: 9
builder: s9f9_transaction_timer_timeout
parser: parse_s9f9
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F11
stream: 9
function: 11
builder: s9f11_data_too_long
parser: parse_s9f11
body: {kind: scalar, item_type: BINARY, param: mhead}
- id: S9F13
stream: 9
function: 13
builder: s9f13_conversation_timeout
parser: parse_s9f13
body:
kind: list
struct_name: ConversationTimeout
fields:
- {name: mexp, shape: {kind: scalar, item_type: ASCII}}
- {name: edid, shape: {kind: scalar, item_type: ASCII}}
# =====================================================================
# S10 — Terminal services
# =====================================================================
- id: S10F1
stream: 10
function: 1
w: true
builder: s10f1_terminal_display_single
parser: parse_s10f1
body:
kind: list
struct_name: TerminalDisplay
fields:
- {name: tid, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: text, shape: {kind: scalar, item_type: ASCII}}
- id: S10F2
stream: 10
function: 2
builder: s10f2_terminal_display_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: TerminalAck, param: ack}
- id: S10F3
stream: 10
function: 3
w: true
builder: s10f3_terminal_display_single
parser: parse_s10f3
body:
kind: list
struct_name: TerminalDisplay
fields:
- {name: tid, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: text, shape: {kind: scalar, item_type: ASCII}}
- id: S10F4
stream: 10
function: 4
builder: s10f4_terminal_display_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: TerminalAck, param: ack}
# S10F5 / S10F6 — Terminal Display, Multi-line (host -> equipment).
- id: S10F5
stream: 10
function: 5
w: true
builder: s10f5_terminal_display_multi
parser: parse_s10f5
body:
kind: list
struct_name: TerminalDisplayMulti
fields:
- {name: tid, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: lines
shape: {kind: list_of, element: {kind: scalar, item_type: ASCII}}
- id: S10F6
stream: 10
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}