Files
secs-gem/docs/50_api_messages_yaml_reference.md
T
raphael af1a159c59 docs: bring the documentation up to the daemon/client era
A large gap had opened between the docs and the code: the README and
INTEGRATION guide did not mention the gRPC daemon or the Python client at
all (the entire vendor surface), ARCHITECTURE still described secs_server
as the ~1200-line canonical wiring example (it is a ~110-line thin main
over EquipmentRuntime), and test counts across six files were stale
(445/2753 -> 473/3087 core + the separate 125-assertion daemon suite).

- README: new "Integrating your tool (pick a tier)" section — Python
  client / any-language gRPC / embedded C++ — plus daemon tests and
  tools/run_interop.sh in the Testing section.
- ARCHITECTURE: layer diagram gains the vendor-surface and
  EquipmentRuntime/default_handlers tiers; stale wiring row fixed.
- INTEGRATION: three-tier chooser up front (this guide = the C++ tier).
- ch30 tour: secs_gemd + secs_gemd_tests in the binaries table.
- ch31: example alarm used a nonexistent `alcd:` field with bit 7 set
  (which the validator forbids) -> real `category:`/`name:` fields, and
  the roles: block documented.
- ch35: handler-location note now points at default_handlers.cpp's 15
  per-capability register_* functions.
- ch40: built-artifacts list + sample output counts.
- ch50: secsgem::gem runtime/default_handlers/handler_slot/name_index
  includes + new secsgem::daemon namespace section.
- PROOFS: test-count table gains the runtime/handlers/daemon row so the
  tally adds up; daemon suite noted. VERIFICATION/COMPLIANCE counts.
- interop/README: the one-command runner + the two daemon-track harnesses
  (daemon_interop, pyclient_interop).

Audited via a docs-vs-code sweep (the audit itself under-reported: it
validated counts textually; reality was 473/3087).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:18:31 +02:00

372 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 50 — API + message catalog + YAML schemas
← [41 Integration: hardware, MES, production](41_integration_hardware_mes_production.md) | [Back to index](00_index.md) | Next: [51 Extending the codebase](51_extending_the_codebase.md) →
This chapter is **reference**, not tutorial. Look up the namespace
or YAML key you need; cross-reference the code.
The whole codebase is small enough that "go read the header" is
often the right answer — this chapter helps you find which header.
---
## Namespace reference
### `secsgem::secs2` — codec (chapter 34)
```cpp
#include "secsgem/secs2/item.hpp"
#include "secsgem/secs2/codec.hpp"
#include "secsgem/secs2/message.hpp"
#include "secsgem/secs2/sml.hpp"
```
| Symbol | What it is |
|-------------------------------------------------|----------------------------------------------------|
| `enum class Format` | 16 SECS-II format codes. |
| `class Item` | Variant-based value type. |
| `class Message` | Stream + function + W-bit + system_bytes + body. |
| `class CodecError` | Thrown on malformed input. |
| `std::vector<uint8_t> encode(const Item&)` | Serialize an Item to bytes. |
| `void encode_into(const Item&, std::vector<uint8_t>&)` | Append-encode into existing buffer. |
| `Item decode(const std::vector<uint8_t>&)` | Decode one Item from a complete buffer. |
| `Item decode_at(const uint8_t*, size_t, size_t&)`| Decode one Item from a position; advances cursor. |
| `std::string to_sml(const Item&)` | Render as SML. |
| `std::optional<Item> try_parse_sml(const std::string&)` | Parse SML; returns nullopt on error. |
### `secsgem::hsms` — TCP transport (chapter 11, 33)
```cpp
#include "secsgem/hsms/header.hpp"
#include "secsgem/hsms/connection.hpp"
```
| Symbol | What it is |
|-------------------------------------------------|----------------------------------------------------|
| `enum class SType` | 9 session types. |
| `enum class SelectStatus / DeselectStatus / RejectReason` | Reply codes. |
| `struct Header` | 10-byte HSMS header. |
| `struct Frame` | Header + body, length-prefixed on wire. |
| `class FrameError` | Thrown on framing errors. |
| `struct Timers` | T3/T5/T6/T7/T8 + linktest cadence. |
| `class Connection` | One-socket session manager. |
| `Connection::Mode { Active, Passive }` | TCP role. |
| `Connection::State { NotSelected, Selected }` | Transport state. |
### `secsgem::secsi` — SECS-I transport (chapter 12, 33)
```cpp
#include "secsgem/secsi/header.hpp"
#include "secsgem/secsi/block.hpp"
#include "secsgem/secsi/protocol.hpp"
#include "secsgem/secsi/tcp_transport.hpp"
```
| Symbol | What it is |
|-------------------------------------------------|----------------------------------------------------|
| `struct Header` | 10-byte SECS-I block header (R/W/E + system bytes).|
| `class Block` | One block (header + body + checksum). |
| `split_message(msg)` / `assemble_message(blocks)`| Multi-block split / assemble. |
| `class Protocol` | IO-free FSM. |
| `enum class Timer { T1, T2, T3, T4 }` | Timer IDs (raised via `EventTimeout`). |
| `Action / Event` variants | FSM IO. |
| `class TcpTransport` | asio adapter for testing tunnels. |
### `secsgem::gem` — behavioural layer (chapters 1319, 32, 35)
```cpp
#include "secsgem/gem/data_model.hpp" // composite
#include "secsgem/gem/router.hpp" // dispatch table
#include "secsgem/gem/control_state.hpp" // E30 control FSM
#include "secsgem/gem/communication_state.hpp" // E30 comm FSM
#include "secsgem/gem/process_job_state.hpp" // E40
#include "secsgem/gem/control_job_state.hpp" // E94
#include "secsgem/gem/carrier_state.hpp" // E87
#include "secsgem/gem/load_port_state.hpp" // E87
#include "secsgem/gem/substrate_state.hpp" // E90
#include "secsgem/gem/module_state.hpp" // E157
#include "secsgem/gem/ept_state.hpp" // E116
#include "secsgem/gem/exception_state.hpp" // E5 §13
#include "secsgem/gem/e84_state.hpp" // E84 FSM
#include "secsgem/gem/e84_timers.hpp" // E84 TA1/TA2/TA3
#include "secsgem/gem/e84_asio_timers.hpp" // asio wrapper
#include "secsgem/gem/host_handler.hpp" // host-side analogue
#include "secsgem/gem/messages_helpers.hpp" // identifier wildcards
// Plus build/generated/secsgem/gem/messages.hpp (codegen).
```
`include/secsgem/gem/store/` — 18 per-domain stores. See
chapter [32](32_stores_and_the_data_model.md) for the full table.
Engine-owner and default-behaviour entry points (added with the daemon
track; see [DAEMON_ROADMAP.md](DAEMON_ROADMAP.md)):
```cpp
#include "secsgem/gem/runtime.hpp" // EquipmentRuntime: owns
// io_context + Server + model + control FSM + Router; thread-safe
// set_variable/emit_event/set_alarm/clear_alarm, on_command hook,
// read_sync (the standard cross-thread read), control-state mirror,
// add_control_state_observer / add_link_observer.
#include "secsgem/gem/default_handlers.hpp" // the 56 GEM handlers as 15
// per-capability register_* functions + register_default_handlers.
#include "secsgem/gem/handler_slot.hpp" // primary + observer handler slots
#include "secsgem/gem/name_index.hpp" // name -> VID/CEID resolution
```
### `secsgem::daemon` — the gRPC vendor surface
```cpp
#include "secsgem/daemon/equipment_service.hpp" // EquipmentService: the
// proto/secsgem/v1 Equipment service over an EquipmentRuntime
// (SetVariables/GetVariables/FireEvent/SetAlarm/ClearAlarm/
// GetControlState/RequestControlState/WatchHealth/Subscribe/
// CompleteCommand). Built into apps/secs_gemd.cpp; the Python
// client in clients/python wraps the same proto.
```
### `secsgem::config` — YAML loader + validator (chapter 31, 36)
```cpp
#include "secsgem/config/loader.hpp"
#include "secsgem/config/validate.hpp"
```
| Symbol | What it loads |
|-------------------------------------------------|----------------------------------------------------|
| `load_equipment(path)` | `data/equipment.yaml``EquipmentDescriptor`. |
| `load_control_state_table(path)` | `data/control_state.yaml``ControlStateConfig`. |
| `load_process_job_state(path)` | `data/process_job_state.yaml`. |
| `load_control_job_state(path)` | `data/control_job_state.yaml`. |
| `class ConfigValidator` | Multi-error YAML validator. |
### `secsgem::metrics` — Prometheus exporter (chapter 36)
```cpp
#include "secsgem/metrics/prometheus.hpp"
```
| Symbol | What it is |
|-------------------------------------------------|----------------------------------------------------|
| `class Registry` | Holds Counter + Gauge series with labels. |
| `enum class MetricType { Counter, Gauge }` | |
| `class PrometheusServer` | HTTP server on a configurable port. |
---
## Message catalog reference
164 entries in [`data/messages.yaml`](../data/messages.yaml).
Grouped by stream:
### S1 — Identification + status
| S/F | W | Name | Body |
|-------|---|-------------------------------|--------------------------------------------|
| S1F1 | W | Are You There | none |
| S1F2 | | On-Line Data | `<L,2> [MDLN, SOFTREV]` |
| S1F3 | W | Selected Equipment Status Req | `<L,n> [SVID, SVID, ...]` |
| S1F4 | | Selected Equipment Status Data| `<L,n> [SV, SV, ...]` |
| S1F11 | W | Status Variable Namelist Req | `<L,n> [SVID, ...]` |
| S1F12 | | Status Variable Namelist | `<L,n> [<L,3> [SVID, SVNAME, UNITS]]` |
| S1F13 | W | Establish Communications Req | `<L,2> [MDLN, SOFTREV]` |
| S1F14 | | Establish Communications Ack | `<L,2> [COMMACK, <L,2> [MDLN, SOFTREV]]` |
| S1F15 | W | Request Offline | none |
| S1F16 | | OFLACK | `OFLACK` |
| S1F17 | W | Request Online | none |
| S1F18 | | ONLACK | `ONLACK` |
| S1F19 | W | Compliance Request | none |
| S1F20 | | Compliance Data | `<L,n> [CCODE, ...]` |
| S1F21 | W | DVID Namelist Request | `<L,n> [DVID, ...]` |
| S1F22 | | DVID Namelist | `<L,n> [<L,3> [DVID, DVNAME, UNITS]]` |
| S1F23 | W | CEID Namelist Request | `<L,n> [CEID, ...]` |
| S1F24 | | CEID Namelist | `<L,n> [<L,2> [CEID, [VID, VID, ...]]]` |
### S2 — Equipment constants, clock, events, commands, spool
S2F13/F14 (EC values), S2F15/F16 (set EC), S2F17/F18 (clock read),
S2F21/F22 (legacy RCMD), S2F23/F24 (trace init), S2F29/F30 (EC
namelist), S2F31/F32 (set clock), S2F33F38 (report wiring),
S2F41/F42 (modern RCMD), S2F43/F44 (set spool streams),
S2F45F48 (limits), S2F49/F50 (enhanced RCMD).
### S3 — Carrier management (E87)
S3F17/F18 (CarrierAction), S3F19/F20 (slot map verify),
S3F25/F26 (carrier transfer), S3F27/F28 (cancel carrier).
### S5 — Alarms + exception recovery
S5F1/F2 (alarm set/clear), S5F3/F4 (enable/disable alarm),
S5F5/F6 (list all alarms), S5F7/F8 (list enabled alarms),
S5F9F18 (exception recovery, chapter 19).
### S6 — Data collection
S6F1/F2 (trace data), S6F11/F12 (event report), S6F15/F16 (event
report request), S6F19/F20 (individual report request),
S6F21/F22 (annotated individual report), S6F23/F24 (spool data
transmit/purge), S6F25/F26 (spool notification).
### S7 — Process program management
S7F1/F2 (PP load inquire), S7F3/F4 (PP send unformatted),
S7F5/F6 (PP request), S7F17/F18 (PP delete), S7F19/F20 (PP
namelist), S7F23/F24 (formatted PP send, E42), S7F25/F26
(formatted PP request).
### S9 — Protocol-error reports
S9F1 (unrecognized device ID), S9F3 (unrecognized stream),
S9F5 (unrecognized function), S9F7 (illegal data), S9F9 (T3
timeout), S9F11 (data too long), S9F13 (conversation timer
timeout). Auto-emitted; see chapter 11.
### S10 — Terminal services
S10F1/F2 (terminal display single, equipment→host),
S10F3/F4 (terminal display single, host→equipment),
S10F5/F6 (terminal display multi, host→equipment).
### S12 — Wafer maps
S12F* — Per E5 §13. Round-tripped through `raw_gem300_harness.py`.
### S14 — Object services (E39) + control jobs (E94)
S14F1/F2 (GetAttr), S14F3/F4 (SetAttr), S14F9/F10 (CreateCJ),
S14F11/F12 (DeleteCJ).
### S16 — Process jobs (E40)
S16F5/F6 (PRJobCommand), S16F7/F8 (PRJobMonitor), S16F9 (PRJobAlert
— unsolicited), S16F11/F12 (PRJobCreate), S16F13/F14 (PRJobDequeue),
S16F27/F28 (CJCommand).
For per-message body shapes, look up the YAML entry in
`data/messages.yaml`.
---
## YAML schema reference
### `data/messages.yaml`
```yaml
messages:
- id: S<X>F<Y> # required, must match (stream, function)
stream: <int 1-127>
function: <int 0-255>
w: <bool> # reply expected?
builder: <ident> # C++ builder function name
parser: <ident> # C++ parser function name
body: <body-shape> # see chapter 31 for the grammar
```
Body shapes:
```yaml
body: none
body:
kind: scalar
item_type: ASCII | BINARY_BYTE | BOOLEAN | U1..U8 | I1..I8 | F4 | F8 | ITEM
enum: <C++ enum type> # optional
param: <name> # optional, default 'value'
body:
kind: list
struct_name: <C++ type> # optional; if set, parser returns struct
fields:
- {name: <field>, shape: <body-shape>}
- ...
body:
kind: list_of
element: <body-shape>
name: <name> # parameter name, default 'values'
```
### `data/control_state.yaml`
```yaml
transitions:
- {from: <state>, on: <event>, to: <state>, then: <state>, ack: <code>}
```
`from`: one of `EquipmentOffline | AttemptOnline | HostOffline | OnlineLocal | OnlineRemote`.
`on`: one of `operator_switch_online | operator_switch_offline | operator_switch_local | operator_switch_remote | attempt_complete | attempt_failed | host_request_online | host_request_offline`.
`to`: optional new state.
`then`: optional chained state (for AttemptOnline pass-through).
`ack`: optional ACK code (`Accept`, `NotAccept`, `AlreadyOnline`).
### `data/process_job_state.yaml`
```yaml
transitions:
- {from: <state>, on: <event>, to: <state>}
```
`from` / `to`: `Queued | SettingUp | WaitingForStart | Processing | ProcessComplete | Paused | Stopping | Aborting`.
`on`: `select | setup_complete | start | pause | resume | stop | abort | process_complete | abort_complete`.
### `data/control_job_state.yaml`
Same shape, different state/event names — see
[`include/secsgem/gem/control_job_state.hpp`](../include/secsgem/gem/control_job_state.hpp).
### `data/equipment.yaml`
```yaml
device:
mdln: <ASCII>
softrev: <ASCII>
capabilities: [<list of GEM capability strings>]
svids:
- {id: <U4>, name: <ASCII>, units: <ASCII>, type: <type>, value: <default>}
dvids:
- {id: <U4>, name: <ASCII>, units: <ASCII>, type: <type>}
ecids:
- {id: <U4>, name: <ASCII>, units: <ASCII>, type: <type>, value: <default>, min: <num>, max: <num>}
ceids:
- {id: <U4>, name: <ASCII>}
alarms:
- {id: <U4>, alcd: <byte>, text: <ASCII>}
recipes:
- {id: <ASCII>, body: <bytes-or-string>}
host_commands:
- {name: <ASCII>, ack: <ACK enum>, emit_ceid: <U4>, set_alarm: <U4>}
events:
default_reports:
- {ceid: <U4>, vids: [<U4>, ...]}
spool:
whitelist: [<stream>, ...]
persistent_dir: <path> # optional
```
Type strings: `ASCII`, `BINARY`, `BOOLEAN`, `U1``U8`, `I1``I8`,
`F4`, `F8`. Same vocabulary as `data/messages.yaml` body shapes.
For required vs optional fields per record, see the validator
checks in
[`tests/test_config_validate.cpp`](../tests/test_config_validate.cpp).
---
## Where to go next
The last chapter is the practical companion to this one: the
**recipes** for extending the codebase — adding a new SVID, host
command, state, message, store, or persistence backend. Code
patches you can copy.
Next: [→ 51 Extending the codebase](51_extending_the_codebase.md)