E2: E90 standard CEIDs + server-side substrate event emission

Adds the canonical E90-0716 §6.5 collection-event identifiers as a
single header of inline constants (gem/e90_constants.hpp) keyed off
SubstrateState / SubstrateProcessingState transitions:

  901 AtSource           910 NeedsProcessing
  902 AtWork             911 InProcess
  903 AtDestination      912 Processed
                         913 Aborted
                         914 Stopped
                         915 Rejected
                         916 Lost
                         917 Skipped

Values use the 901+ block to avoid collision with the demo CEIDs in
data/equipment.yaml (100s/200s/400s).

Server installs location + processing change handlers on
model->substrates that map every transition to emit_event() with the
matching CEID.  The existing event-report machinery (subscription
state, S6F11 batching, spool) gates the actual wire emission, so this
plays nicely with hosts that subscribe to only a subset of substrate
events.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 00:50:53 +02:00
parent 7c726ed9ba
commit 511950aa4a
2 changed files with 83 additions and 0 deletions
+56
View File
@@ -16,6 +16,7 @@
#include "secsgem/endpoint.hpp"
#include "secsgem/gem/control_state.hpp"
#include "secsgem/gem/data_model.hpp"
#include "secsgem/gem/e90_constants.hpp"
#include "secsgem/gem/messages.hpp"
#include "secsgem/gem/router.hpp"
#include "secsgem/secs2/message.hpp"
@@ -284,6 +285,61 @@ int main(int argc, char** argv) {
}
});
// ---- E90 substrate state-change emitters -----------------------------
// Map SubstrateState / SubstrateProcessingState transitions to the
// standard E90 CEIDs. Only the post-transition state matters; the
// event-report machinery already gates on enabled CEIDs so emitting
// for every transition is safe and gives the host a complete trace.
model->substrates.set_location_handler(
[logfn, emit_event](const std::string& substid,
gem::SubstrateState from,
gem::SubstrateState to,
gem::SubstrateEvent ev) {
logfn(std::string("SUB ") + substid + ": " +
gem::substrate_state_name(from) + " -> " +
gem::substrate_state_name(to) + " (" +
gem::substrate_event_name(ev) + ")");
switch (to) {
case gem::SubstrateState::AtSource:
emit_event(gem::e90::kCeidSubstrateAtSource); break;
case gem::SubstrateState::AtWork:
emit_event(gem::e90::kCeidSubstrateAtWork); break;
case gem::SubstrateState::AtDestination:
emit_event(gem::e90::kCeidSubstrateAtDestination); break;
case gem::SubstrateState::NoState: break;
}
});
model->substrates.set_processing_handler(
[logfn, emit_event](const std::string& substid,
gem::SubstrateProcessingState from,
gem::SubstrateProcessingState to,
gem::SubstrateProcessingEvent ev) {
logfn(std::string("SUB ") + substid + " proc: " +
gem::substrate_processing_state_name(from) + " -> " +
gem::substrate_processing_state_name(to) + " (" +
gem::substrate_processing_event_name(ev) + ")");
switch (to) {
case gem::SubstrateProcessingState::NeedsProcessing:
emit_event(gem::e90::kCeidSubstrateNeedsProcessing); break;
case gem::SubstrateProcessingState::InProcess:
emit_event(gem::e90::kCeidSubstrateInProcess); break;
case gem::SubstrateProcessingState::Processed:
emit_event(gem::e90::kCeidSubstrateProcessed); break;
case gem::SubstrateProcessingState::Aborted:
emit_event(gem::e90::kCeidSubstrateAborted); break;
case gem::SubstrateProcessingState::Stopped:
emit_event(gem::e90::kCeidSubstrateStopped); break;
case gem::SubstrateProcessingState::Rejected:
emit_event(gem::e90::kCeidSubstrateRejected); break;
case gem::SubstrateProcessingState::Lost:
emit_event(gem::e90::kCeidSubstrateLost); break;
case gem::SubstrateProcessingState::Skipped:
emit_event(gem::e90::kCeidSubstrateSkipped); break;
case gem::SubstrateProcessingState::NoState: break;
}
});
// ---- Build the SECS dispatch table once -------------------------------
gem::Router router;
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <cstdint>
// E90 §6 standard collection event identifiers. Equipment vendors
// frequently register additional CEIDs around the base set; the
// constants below are the canonical ones called out by E90-0716 §6.5,
// keyed off the SubstrateState transitions so application code can
// emit them directly from a SubstrateStore change handler.
//
// Values use a high block (901+) to avoid collisions with the demo
// CEIDs in data/equipment.yaml (which uses 100s/200s/400s).
namespace secsgem::gem::e90 {
inline constexpr uint32_t kCeidSubstrateAtSource = 901;
inline constexpr uint32_t kCeidSubstrateAtWork = 902;
inline constexpr uint32_t kCeidSubstrateAtDestination = 903;
inline constexpr uint32_t kCeidSubstrateNeedsProcessing = 910;
inline constexpr uint32_t kCeidSubstrateInProcess = 911;
inline constexpr uint32_t kCeidSubstrateProcessed = 912;
inline constexpr uint32_t kCeidSubstrateAborted = 913;
inline constexpr uint32_t kCeidSubstrateStopped = 914;
inline constexpr uint32_t kCeidSubstrateRejected = 915;
inline constexpr uint32_t kCeidSubstrateLost = 916;
inline constexpr uint32_t kCeidSubstrateSkipped = 917;
} // namespace secsgem::gem::e90