H2: E157 module CEIDs + server-side emission

Adds the canonical E157 collection-event identifiers in the 1570+ block:

  1570 ModuleProcessStateChange  (generic; fired on any transition)
  1571 ModuleNotExecuting
  1572 ModuleGeneralExecuting
  1573 ModuleStepExecuting
  1574 ModuleStepCompleted

Server installs a state-change handler that fires both the generic
CEID and the state-specific one for each transition.  Hosts that
prefer "wake me on any module change and I'll fan it out myself" can
subscribe to only the generic CEID; hosts that want narrower
notifications subscribe to specific states.

Closes Tranche H — E157 Module Process Tracking end-to-end (FSM +
Store + CEIDs + server emission).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 03:38:11 +02:00
parent 82fac6fd17
commit 90fdf45df5
2 changed files with 43 additions and 0 deletions
+27
View File
@@ -17,6 +17,7 @@
#include "secsgem/gem/control_state.hpp"
#include "secsgem/gem/data_model.hpp"
#include "secsgem/gem/e116_constants.hpp"
#include "secsgem/gem/e157_constants.hpp"
#include "secsgem/gem/e90_constants.hpp"
#include "secsgem/gem/messages.hpp"
#include "secsgem/gem/router.hpp"
@@ -365,6 +366,32 @@ int main(int argc, char** argv) {
}
});
// ---- E157 module state-change emitter --------------------------------
// Every module transition fires the generic ModuleProcessStateChange
// CEID plus the state-specific one, mirroring secsgem-py's per-module
// CEID granularity. Hosts that don't subscribe to the specific CEID
// can still listen on the generic one to drive an internal FSM.
model->modules.set_state_change_handler(
[logfn, emit_event](const std::string& mod, gem::ModuleState from,
gem::ModuleState to, gem::ModuleEvent ev) {
logfn(std::string("MOD ") + mod + ": " +
gem::module_state_name(from) + " -> " +
gem::module_state_name(to) + " (" +
gem::module_event_name(ev) + ")");
emit_event(gem::e157::kCeidModuleProcessStateChange);
switch (to) {
case gem::ModuleState::NotExecuting:
emit_event(gem::e157::kCeidModuleNotExecuting); break;
case gem::ModuleState::GeneralExecuting:
emit_event(gem::e157::kCeidModuleGeneralExecuting); break;
case gem::ModuleState::StepExecuting:
emit_event(gem::e157::kCeidModuleStepExecuting); break;
case gem::ModuleState::StepCompleted:
emit_event(gem::e157::kCeidModuleStepCompleted); break;
case gem::ModuleState::NoState: break;
}
});
// ---- Build the SECS dispatch table once -------------------------------
gem::Router router;