feat(client)+feat(daemon): eq.names, @eq.command, E90/E157 RPCs
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>
This commit is contained in:
@@ -144,6 +144,28 @@ def run(grpc_addr: str, hsms_host: str, hsms_port: int) -> int:
|
||||
check("handler's eq.fire reached the host (completion signal)",
|
||||
ceid300.wait(timeout=10))
|
||||
|
||||
# ---- Describe-backed names + @eq.command binding ----
|
||||
check("eq.names.event has ProcessStarted",
|
||||
"ProcessStarted" in eq.names.event)
|
||||
check("eq.names.command has START", "START" in eq.names.command)
|
||||
try:
|
||||
_ = eq.names.event.NoSuchEvent
|
||||
check("typo on eq.names raises", False)
|
||||
except AttributeError:
|
||||
check("typo on eq.names raises", True)
|
||||
eq.fire(eq.names.event.ProcessStarted)
|
||||
check("eq.fire(eq.names.event.*) accepted", True)
|
||||
|
||||
# ---- E90/E157 material tracking ----
|
||||
eq.report_substrate("WFR-PY-1", "ARRIVED")
|
||||
eq.report_substrate("WFR-PY-1", "AT_WORK")
|
||||
eq.report_substrate("WFR-PY-1", "PROCESSING")
|
||||
eq.report_substrate("WFR-PY-1", "PROCESSED")
|
||||
check("report_substrate journey accepted", True)
|
||||
eq.report_module("MOD-PY-1", "GENERAL_EXECUTING")
|
||||
eq.report_module("MOD-PY-1", "STEP_EXECUTING")
|
||||
check("report_module accepted", True)
|
||||
|
||||
# ---- operator offline via the client ----
|
||||
eq.request_control_state("HOST_OFFLINE")
|
||||
check("request_control_state(HOST_OFFLINE)",
|
||||
|
||||
Reference in New Issue
Block a user