Files
secs-gem/data/messages.yaml
T
raphael 813e011409
tests / build-and-test (push) Failing after 32s
Close COMPLIANCE.md gap: Documentation (S1F19-F22)
Adds the GEM "Documentation" Fundamental capability: the equipment now
self-reports which GEM capabilities it supports, and the host can
discover the DVID namelist with the same shape used for SVIDs.

Catalog (data/messages.yaml -> generated messages.hpp)

  S1F19 W   header-only                Get GEM Compliance Request
  S1F20     <L,3 <A SOFTREV>
                 <A EQPTYP>
                 <L,a <L,2 <U1 CCODE> <A CDESC>>>>
                                       Get GEM Compliance Data
  S1F21 W   <L,n <U4 VID>>             DVID Namelist Request (n=0 = all)
  S1F22     <L,n <L,3 <U4 VID>
                       <A VNAME>
                       <A UNITS>>>     DVID Namelist Data

  Codegen emits CapabilityEntry and GemCompliance structs.  S1F22 reuses
  S1F12's StatusName struct (same wire shape; dedup avoids redefinition).

Equipment data dictionary (data/equipment.yaml)

  device:                              Adds `equipment_type: "EQUIPMENT"`
                                       for the S1F20 EQPTYP field.

  capabilities:                        New section.  List of
    - {code, name}                     (CCODE, CDESC) pairs honestly
                                       reflecting what the codebase
                                       implements: 1, 2, 3, 5, 6, 7, 8,
                                       9, 11, 12, 14 (partial), 15.

  dvids:                               New section, same schema as
                                       svids:.  Demo populates two:
    - WaferCounter      (U4, units wafer)
    - ChamberPressure   (F4, units Torr)

Loader (src/config/loader.cpp + include/secsgem/config/loader.hpp)

  EquipmentDescriptor gains equipment_type and capabilities (vector of
  (uint8_t, string) pairs).  load_equipment now reads `capabilities:`
  into the descriptor and `dvids:` into model.dvids.

Server (apps/secs_server.cpp)

  router.on(1, 19) returns S1F20 with desc.software_rev,
  desc.equipment_type, and desc.capabilities converted to
  vector<CapabilityEntry>.
  router.on(1, 21) returns S1F22 built from model.dvids.all().

Client (apps/secs_client.cpp)

  Two new demo steps after Request Online and before SVID discovery:
    S1F19 -> S1F20: logs SOFTREV, EQPTYP, and every (CCODE, CDESC)
                    the equipment claims.
    S1F21 -> S1F22: logs each DVID with units.

Tests

  tests/test_messages.cpp   Round-trip S1F19/F20 with a 3-entry
                            capability list; round-trip S1F22 with two
                            DVIDs.

  tests/test_loader.cpp     Asserts equipment_type, the capabilities
                            list contains CCODE 14 (Spooling), and the
                            two DVIDs land in model.dvids.

COMPLIANCE.md

  "Documentation" Fundamental moves from  to .
  S1F19/F20 + S1F21/F22 rows in the coverage matrix flip to .
  The "what would it take" list drops the documentation-messages bullet.

Verified

  - Tests: 77 cases / 444 assertions pass.
  - Demo: client logs the full capability list received from the
    equipment, including CCODE 14 "Spooling (partial; S2F43/F44 +
    S6F23/F24)" — the equipment honestly reports its partial
    implementation rather than overclaiming.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 00:30:43 +02:00

717 lines
19 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}
- 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}}
# 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).
# =====================================================================
# 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}
# =====================================================================
# 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}