feat(clients)+test(interop): C++ client + Java validation of the daemon (B7)
tests / build-and-test (push) Successful in 2m54s
tests / thread-sanitizer (push) Successful in 3m48s
tests / tshark-dissector (push) Successful in 2m24s
tests / secs4j-interop (push) Successful in 1m44s
tests / python-interop (push) Successful in 3m10s
tests / libfuzzer (push) Successful in 3m38s
tests / build-and-test (push) Successful in 2m54s
tests / thread-sanitizer (push) Successful in 3m48s
tests / tshark-dissector (push) Successful in 2m24s
tests / secs4j-interop (push) Successful in 1m44s
tests / python-interop (push) Successful in 3m10s
tests / libfuzzer (push) Successful in 3m38s
B7 — the daemon's HSMS face under the Java reference: Dockerfile.server now
bakes secs_gemd alongside secs_server (grpc deps in both stages), and
secs4j_validate.sh gains TARGET=gemd to point the 55-check secs4java8 suite
at the daemon instead. Result: 55/55 green. With secsgem-py already
validating both faces, byte-identical GEM between secs_server and secs_gemd
is now proven by both reference implementations, not inferred from shared
code. CI runs the daemon target as an extra step (image layers shared).
Second client — clients/cpp: a header-only C++ twin of the Python client
over the same proto. eq.set("ChamberPressure", 2.5) with bare literals
(integral/floating dispatch avoids variant ambiguity), get/fire/alarm/
clear, control_state/request_control_state/health, on("START", fn) +
listen()/listen_async()/stop() with auto-CompleteCommand, SecsGemError
carrying the daemon's message. cpp_mini_tool (~30 lines) mirrors the
Python mini_tool. Tested end-to-end over real loopback TCP against the
service inside secs_gemd_tests — now 4 cases / 141 assertions — including
set/get round-trips, error text, alarm-by-name into the model, health,
and the full HCACK-4 command loop with parameters.
(Build note: two grpc-heavy TUs at -O3 OOM even at -j2 on Docker Desktop;
built -j1. Known environment limitation, roadmap-documented.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+17
-5
@@ -27,7 +27,7 @@ host and stays conformant while the tool software restarts/upgrades/crashes.
|
||||
| gRPC/protobuf toolchain (Dockerfile + CMake codegen) | ✅ | grpc++ 1.51 / protoc 3.21; opt-in `SECSGEM_DAEMON`, graceful skip without grpc |
|
||||
| `secs_gemd`: `SetVariables` / `FireEvent` / `GetControlState` / `GetVariables` | ✅ | **format-aware** both directions (declared SECS-II formats on write, `from_item` on read) and thread-safe (snapshot maps + posted writes + `read_sync` reads). In-process gRPC tests incl. run_async production mode (`test_daemon_service.cpp`, 61 assertions) |
|
||||
| Daemon interop vs **secsgem-py** reference host | ✅ | `interop/daemon_interop.py` (via `gemd` compose service): gRPC `SetVariables(ChamberPressure=2.5)` + `FireEvent` → host receives `S6F11 CEID 300` carrying `<F4 2.5>` — value *and declared format* flow gRPC→engine→HSMS→host |
|
||||
| Daemon interop vs **secs4j** (Java) | ⬜ | mirror the secsgem-py harness against `interop/secs4j` |
|
||||
| Daemon interop vs **secs4j** (Java) | ✅ | `TARGET=gemd interop/secs4j_validate.sh` — 55/55 against the daemon's HSMS face; in CI |
|
||||
| `Subscribe` host→tool command stream + `CompleteCommand` | ✅ | HCACK-4 contract implemented + tested in-process AND live vs secsgem-py (full loop: S2F41 → stream → complete → S6F11) |
|
||||
| Universal RPC surface complete (vars/events/alarms/control-state/health) | ✅ | Phase A done; daemon tests 101 assertions, interop 15 checks |
|
||||
| Python client package (the "beautiful API") | ✅ | `clients/python` (`secsgem-client`); 13-check interop green via the published API |
|
||||
@@ -170,7 +170,12 @@ debts tax every later phase, and the most valuable tests aren't automated.
|
||||
START` → `S2F42 HCACK=4` → tool receives Command(name=START, id) on the
|
||||
stream → `CompleteCommand` → tool fires the event → host receives `S6F11`.
|
||||
(interop now 20 checks.)
|
||||
7. ⬜ Java interop: `secs4j` host variant of the same scenario.
|
||||
7. ✅ Java interop: `TARGET=gemd interop/secs4j_validate.sh` runs the full
|
||||
55-check secs4java8 suite against the DAEMON's HSMS face — 55/55 green
|
||||
(secs_gemd and secs_server sit on the same register_default_handlers, so
|
||||
byte-identical GEM is now proven, not assumed). CI step added. The
|
||||
command loop with a live subscriber is covered by the python harnesses
|
||||
(a Java *tool-side* gRPC client remains possible future work).
|
||||
|
||||
### Phase C — the beautiful Python client
|
||||
8. ✅ `clients/python/` — pip-installable `secsgem-client`, pure Python,
|
||||
@@ -185,9 +190,16 @@ debts tax every later phase, and the most valuable tests aren't automated.
|
||||
S5F1 set+clear on the wire, HCACK-4 command loop through the decorator,
|
||||
operator offline). Conversion layer unit-tested (bool-before-int etc).
|
||||
Wired into tools/run_interop.sh as the `pyclient` step.
|
||||
9. 🚧 `clients/python/examples/mini_tool.py` — a complete GEM tool in ~25
|
||||
lines ✅. Migrating the C++ `pvd_tool` to EquipmentRuntime + capability
|
||||
registration + `set_handler` ⬜.
|
||||
9. ✅ `clients/python/examples/mini_tool.py` (~25 lines) and the C++
|
||||
`pvd_tool` migrated to EquipmentRuntime + register_default_handlers +
|
||||
`set_handler` (1093 -> 570 lines; now serves all 56 handlers; boots
|
||||
verified). Chapter 42 teaches the daemon path.
|
||||
10. ✅ **C++ client** (`clients/cpp`): header-only twin of the Python
|
||||
client — `eq.set("ChamberPressure", 2.5)`, `eq.on("START", fn)` +
|
||||
`listen_async()`, alarms/health/control-state, SecsGemError. Tested
|
||||
end-to-end over loopback TCP against the real service inside
|
||||
`secs_gemd_tests` (141 assertions total), incl. the HCACK-4 loop.
|
||||
`cpp_mini_tool` is the worked example.
|
||||
|
||||
### Phase D — GEM300 in-the-loop (process/carrier tools)
|
||||
10. ⬜ Settle job/carrier semantics (who acks S16F5/S3F17, gate vs observe —
|
||||
|
||||
Reference in New Issue
Block a user