a2ebbf7c65
Python client:
- eq.names.event.* / .alarm.* / .command.* / .var.* / .constant.* —
autocomplete-able, typo-safe name lookup backed by the Describe RPC
(lazy, cached; AttributeError on bad name with close-match hints)
- @eq.command decorator — binds a handler by function name, validated
against the equipment's real command set at decoration time
- eq.report_substrate() — E90 wafer milestone reporting
- eq.report_module() — E157 module state reporting (auto-create)
Daemon (C++ service):
- ReportSubstrate RPC — drives E90 location + processing FSMs
- ReportModule RPC — drives E157 module FSM (auto-create on first report)
- ack_from_outcome() helper — consistent Ack mapping for read_sync results
Proto: SubstrateReport, ModuleReport, EquipmentDescription,
SpoolFlushRequest, TerminalMessage; Describe, FlushSpool,
SendTerminalMessage RPCs
Tests: C++ FSM test (journey + ghost rejection + E157 illegal jump);
interop coverage for names API and E90/E157 round-trip
Docs: ch42 RPC table + Python example updated; ch16 daemon-path section added
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
secsgem-client
A complete GEM tool integration in plain Python. The
secs_gemd daemon owns everything SEMI —
the HSMS link to the host, the GEM state machines, formats, timers,
spooling; this client tells it about your tool and reacts to the host.
from secsgem_client import Equipment
eq = Equipment("localhost:50051")
eq.set(ChamberPressure=2.5) # host sees it on its next poll
eq.fire("ProcessStarted") # S6F11 to the host, report auto-assembled
eq.alarm("chiller_temp_high") # S5F1 (set), eq.clear(...) for clear
@eq.on("START") # host remote commands -> your function
def start(cmd):
run_recipe(cmd.params.get("PPID"))
eq.fire("ProcessStarted") # the host's real completion signal
eq.listen() # block and dispatch (background=True for a thread)
Names are the ones from your equipment.yaml; values are plain Python
(float, int, bool, str, bytes, lists). Errors raise
SecsGemError with the daemon's explanation ("no variable named ...").
No compiled extension, no SEMI knowledge, no C++ toolchain — pip install
and a running daemon is the whole setup.