Files
secs-gem/docs/13_e30_gem.md
raphael 4b4b2ac690 docs: correct drifted and fabricated APIs in chapters 13/17/35/51
An audit of doc code blocks against the real headers found APIs that do
not exist in the codebase, presented as authoritative walkthroughs:

- ch35 (dispatch): an entirely fabricated callback architecture —
  HostCommandRegistry::set_emit_ceid_handler, CommandOutcome, emit_ceids.
  Rewritten to the real Spec/Result/dispatch + the new set_handler hook.
- ch13 (E30): wrong store names — EventStore/ReportStore -> EventReportSubscriptions,
  SvidStore -> StatusVariableStore, AlarmStore/AlarmDispatcher -> AlarmRegistry,
  ClockStore -> Clock, TerminalServiceStore -> (no store), in both the
  capability tables and the worked S2F33 example.
- ch17 (E116): EptStore/seconds/bucket_ -> EptStateMachine/milliseconds/buckets_.
- ch51 (extending): stale host-command handler -> the real set_handler signature.

Verified clean by grep: no fabricated symbols remain in docs/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 18:00:58 +02:00

13 KiB
Raw Permalink Blame History

13 — E30: GEM — the behavioural model

12 E4 — SECS-I | Back to index | Next: 14 E40 + E94 — Process and control jobs

E5 (chapter 10) is the data encoding. E37 / E4 (chapters 1112) move the encoded bytes. This chapter is the first one where behaviour enters the picture.

SEMI E30 — Generic Equipment Model (GEM), published 1992, specifies what an equipment must do when its host sends specific messages. E5 says how to encode S1F13; E30 says what state must change when an S1F13 arrives, what reply must come back, and under what conditions either side may refuse.

E30 has two top-level concepts:

  1. Two state machines — communication state (above HSMS) and control state (governs who's allowed to issue commands).
  2. GEM Capabilities — Fundamentals (mandatory) and Additionals (optional but de-facto required). Each capability defines its own scenarios + messages.

By the end of this chapter you'll know both state machines, the 14 Fundamentals + Additionals, and where each one lives in code.


The two GEM state machines

GEM has two state machines that live on top of HSMS's transport state machine. Read carefully — beginners conflate these all the time:

State machine Lives where Concerns
HSMS transport secsgem::hsms::Connection NOT-CONNECTED → NOT-SELECTED → SELECTED
GEM communication secsgem::gem::CommunicationStateMachine DISABLED / WAIT-CRA / WAIT-DELAY / COMMUNICATING
GEM control secsgem::gem::ControlStateMachine EquipmentOffline / OnlineLocal / OnlineRemote / …

All three can be in independent states. SELECTED (HSMS) doesn't imply COMMUNICATING (GEM-comm); COMMUNICATING doesn't imply OnlineRemote (control).

Communication state (E30 §6.5)

What it answers: have host and equipment agreed they can talk to each other at the GEM level? This is above HSMS — even after HSMS is SELECTED, GEM-comm starts at WAIT-CRA and only reaches COMMUNICATING after a successful S1F13 / S1F14 (COMMACK=Accept) exchange.

                              wire: S1F13 →
DISABLED  ─enable──►  WAIT-CRA  ─────────────►  COMMUNICATING
                          │     ◄─ S1F14(Accept)
                          │
                          │     S1F14(Deny) or T_CRA expires
                          ▼
                      WAIT-DELAY
                          │     T_DELAY expires
                          ▼
                       WAIT-CRA  (retry)

Two timers, both in gem::CommunicationStateMachine:

  • T_CRA (default 45 s): how long to wait for the S1F14 reply after sending S1F13.
  • T_DELAY (default 10 s): how long to back off after a rejected S1F14 before retrying.

Code: include/secsgem/gem/communication_state.hpp; tests in tests/test_communication_state.cpp (12 cases — every transition, every timer expiry).

The state machine is IO-free — it raises actions (send S1F13, arm T_CRA, …) that the caller translates into asio work. This makes it unit-testable without spinning up a TCP socket. Same design pattern as secsi::Protocol from chapter 12.

Control state (E30 §6.2)

What it answers: who's allowed to issue commands right now?

Five states:

State Meaning
EquipmentOffline Off-network. Both panel and host commands disabled.
AttemptOnline Transient: equipment is dialing host. Rare.
HostOffline Host disconnected (or never connected). Operator can act, host cannot.
OnlineLocal Operator at the local panel has control. Host can read, not act.
OnlineRemote Host has full control.

Defined in include/secsgem/gem/control_state.hpp.

Transitions are driven by events (operator pressed Online, host sent S1F17, AttemptOnline succeeded or failed, …) and encoded as a transition table loaded from data/control_state.yaml:

# data/control_state.yaml
transitions:
  - {from: EquipmentOffline, on: operator_switch_online, to: AttemptOnline, then: OnlineRemote}
  - {from: OnlineRemote,     on: host_request_offline,   to: HostOffline, ack: Accept}
  - {from: OnlineLocal,      on: host_request_remote,    ack: NotAccept}
  ...

The table is pure data. ControlTransitionTable looks up rows; ControlStateMachine applies them. No if/else ladders embedded in C++.

// include/secsgem/gem/control_state.hpp:53
struct ControlTransition {
  ControlState from;
  ControlEvent on;
  std::optional<ControlState> to;
  std::optional<ControlState> then;   // chain through AttemptOnline
  std::optional<uint8_t> ack_code;
};

This is spec-as-data in its purest form: the SEMI standard section 6.2 is one YAML file. Add a state, add a transition, edit the YAML — no recompile, no C++ change. See chapter 31 for the wider story.

Tests: tests/test_control_state.cpp (15 cases — every YAML-defined transition, both ACK codes).


GEM Fundamentals (E30 §5.2)

The mandatory capabilities. An equipment that doesn't ship these isn't GEM-compliant, end of story.

Fundamental Messages Code
State models ControlStateMachine, CommunicationStateMachine
Equipment Processing States ControlTransitionTable (vendor supplies concrete states)
Host-Initiated S1F13/F14 S1F13 / S1F14 gem::CommunicationStateMachine
Event Notification S6F11 / S6F12 EventReportSubscriptions + EquipmentDataModel::compose_reports_for
On-Line Identification S1F1 / S1F2 Router handler in apps/secs_server.cpp
Error Messages S9F1/F3/F5/F7/F9/F11 Connection::emit_s9 + Router::dispatch_with_s9
Documentation S1F19/F20, S1F21/F22, S1F23/F24 gem::compliance / namelist handlers
Control (Operator-Initiated) ControlStateMachine::operator_online/offline/local/remote

Full per-capability accounting with status + spec section + code ref: docs/COMPLIANCE.md §3.


GEM Additionals (E30 §5.3)

The optional capabilities — but every commercial MES will require all of them. In practice "Additional" means "optional per the SEMI spec, but mandatory for procurement."

Additional Messages Code
Establish Communications S1F13/F14 CommunicationStateMachine (also in Fundamentals)
Dynamic Event Report Configuration S2F33/F34, S2F35/F36, S2F37/F38 EventReportSubscriptions
Variable Data Collection S1F21/F22 + DVID values via vid_value DataVariableStore
Trace Data Collection S2F23/F24, S6F1/F2 TraceStore
Status Data Collection S1F3/F4, S1F11/F12 StatusVariableStore
Alarm Management S5F1/F2, S5F3/F4, S5F5/F6, S5F7/F8 AlarmRegistry
Remote Control S2F41/F42, S2F49/F50, S2F21/F22 HostCommandRegistry
Equipment Constants S2F13/F14, S2F15/F16, S2F29/F30 EquipmentConstantStore
Process Program Management S7F1F6, S7F17F20, S7F23F26 RecipeStore
Material Movement (handled by E40 + E94 + E87 + E90 + E157) see chapters 1416
Equipment Terminal Services S10F1/F2, S10F3/F4, S10F5/F6 S10F1F6 Router handlers (no dedicated store)
Clock S2F17/F18, S2F31/F32 Clock (+ E148 in chapter 19)
Limits Monitoring S2F45/F46, S2F47/F48 LimitMonitorStore
Spooling S2F43/F44, S6F23/F24, S6F25/F26 SpoolStore (persistent file-backed journal)

Every capability has its own store (a namespace bundle of state + behaviour) and its own Router handlers for the messages that drive it. Stores compose into EquipmentDataModel. Chapter 32 is the deep dive.


How a typical scenario lands in code

Pick Event Notification — the canonical GEM scenario:

1. Host sends S2F33 (DefineReport): "RPTID 100 = [SVID 1, SVID 5]"
2. Equipment stores the definition in EventReportSubscriptions; replies S2F34(DRACK=0).
3. Host sends S2F35 (LinkEvent): "CEID 300 → RPTID 100"
4. Equipment stores the link in EventReportSubscriptions; replies S2F36(LRACK=0).
5. Host sends S2F37 (EnableEvent CEED=true, CEID=[300])
6. Equipment marks CEID 300 enabled in EventReportSubscriptions; replies S2F38(ERACK=0).
7. Later: some FSM transition decides to fire CEID 300.
   compose_reports_for(300) walks EventReportSubscriptions → StatusVariableStore
   and assembles {RPTID=100, V=[svid1_val, svid5_val]}.
8. Equipment emits S6F11 with the assembled body.
9. Host replies S6F12(ACKC6=0).

Steps 1, 3, 5 are inbound — gem::Router dispatches by (stream, function) to a registered handler. Steps 2, 4, 6, 8 are outbound — the handler or the FSM hands a built secs2::Message to the Connection. Step 7 is internal — the EquipmentDataModel walks its own stores; nothing on the wire happens until step 8.

Router and dispatch is in chapter 35; store internals in chapter 32.


The host-side analogue

Everything above describes the equipment side. The host side has its own E30 state — every Additional capability has a host-side view too (the host can disable an alarm, change a host command, etc.). This codebase implements the host-side as a thin module:

// include/secsgem/gem/host_handler.hpp
class HostHandler {
  // Decode equipment-initiated S5F1 / S6F11 / S9Fx.
  // Maintain the host's view of CEID enables, alarm enables, …
};

apps/secs_client.cpp is the canonical host binary. In the two-container demo it walks ~24 transactions against apps/secs_server.cpp — the host side mostly reads what the equipment reports and acknowledges. Driving an MES is a much bigger story (see chapter 41).


Where to go next

You now have:

  • E5 codec.
  • E37/E4 transport.
  • E30 state machines and capabilities.

That's the complete base GEM stack. Modern fab automation needs more — process job lifecycles, carrier management, substrate tracking — and that's what GEM 300 adds.

The next six chapters tackle the GEM 300 standards one family at a time. Each one fits on top of E30 in the same way: a state machine + a store + Router handlers + per-CEID emissions.

Next: → 14 E40 + E94 — Process and control jobs