From cdf404901698256a2aadfb66ec8748b62240baec Mon Sep 17 00:00:00 2001 From: Raphael Maenle Date: Mon, 8 Jun 2026 03:16:56 +0200 Subject: [PATCH] F2: EPT joined to EquipmentDataModel + server-side CEID emission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EquipmentDataModel now carries an EptStateMachine as a value member alongside the other top-level state machines. Server installs a state-change handler that maps every EPT transition to a CEID emission through the existing emit_event path: 1100 NonScheduledTime 1103 Engineering 1101 ScheduledDowntime 1104 Standby 1102 UnscheduledDowntime 1105 Productive CEIDs land in the 1100+ block to keep clear of the demo equipment.yaml (100s/200s/400s) and E90 (900s). Log lines include the dwell time of the previous state so trace-level diagnostics show utilization without extra tooling. Application code drives transitions by calling model->ept.on_event(...); the existing event-report machinery (subscription state, S6F11 batching, spool) gates wire emission so EPT events spool on offline hosts like every other CEID. Closes Tranche F — E116 Equipment Performance Tracking end-to-end. Co-Authored-By: Claude Opus 4.7 --- apps/secs_server.cpp | 25 +++++++++++++++++++++++++ include/secsgem/gem/data_model.hpp | 2 ++ include/secsgem/gem/e116_constants.hpp | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 include/secsgem/gem/e116_constants.hpp diff --git a/apps/secs_server.cpp b/apps/secs_server.cpp index c5cb37c..b884397 100644 --- a/apps/secs_server.cpp +++ b/apps/secs_server.cpp @@ -16,6 +16,7 @@ #include "secsgem/endpoint.hpp" #include "secsgem/gem/control_state.hpp" #include "secsgem/gem/data_model.hpp" +#include "secsgem/gem/e116_constants.hpp" #include "secsgem/gem/e90_constants.hpp" #include "secsgem/gem/messages.hpp" #include "secsgem/gem/router.hpp" @@ -340,6 +341,30 @@ int main(int argc, char** argv) { } }); + // ---- E116 EPT state-change emitter ----------------------------------- + model->ept.set_state_change_handler( + [logfn, emit_event](gem::EptState from, gem::EptState to, + gem::EptEvent ev, std::chrono::milliseconds dwell) { + logfn(std::string("EPT: ") + gem::ept_state_name(from) + " -> " + + gem::ept_state_name(to) + " (" + gem::ept_event_name(ev) + + ", dwelt " + std::to_string(dwell.count()) + "ms)"); + switch (to) { + case gem::EptState::NonScheduledTime: + emit_event(gem::e116::kCeidNonScheduledTime); break; + case gem::EptState::ScheduledDowntime: + emit_event(gem::e116::kCeidScheduledDowntime); break; + case gem::EptState::UnscheduledDowntime: + emit_event(gem::e116::kCeidUnscheduledDowntime); break; + case gem::EptState::Engineering: + emit_event(gem::e116::kCeidEngineering); break; + case gem::EptState::Standby: + emit_event(gem::e116::kCeidStandby); break; + case gem::EptState::Productive: + emit_event(gem::e116::kCeidProductive); break; + case gem::EptState::NoState: break; + } + }); + // ---- Build the SECS dispatch table once ------------------------------- gem::Router router; diff --git a/include/secsgem/gem/data_model.hpp b/include/secsgem/gem/data_model.hpp index 9dac587..e5f3c1b 100644 --- a/include/secsgem/gem/data_model.hpp +++ b/include/secsgem/gem/data_model.hpp @@ -3,6 +3,7 @@ #include "secsgem/gem/store/alarms.hpp" #include "secsgem/gem/store/carriers.hpp" #include "secsgem/gem/store/clock.hpp" +#include "secsgem/gem/ept_state.hpp" #include "secsgem/gem/store/control_jobs.hpp" #include "secsgem/gem/store/equipment_constants.hpp" #include "secsgem/gem/store/event_reports.hpp" @@ -41,6 +42,7 @@ struct EquipmentDataModel { CarrierStore carriers; LoadPortStore load_ports; SubstrateStore substrates; + EptStateMachine ept; // Convenience: VID -> value lookup spanning SVIDs and DVIDs. std::optional vid_value(uint32_t vid) const { diff --git a/include/secsgem/gem/e116_constants.hpp b/include/secsgem/gem/e116_constants.hpp new file mode 100644 index 0000000..61af06c --- /dev/null +++ b/include/secsgem/gem/e116_constants.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +// E116 §6 standard collection-event identifiers, one per top-level +// state. Equipment fires the matching CEID on transition into that +// state; hosts subscribe via the existing S2F33 / S2F35 / S2F37 flow. +namespace secsgem::gem::e116 { + +inline constexpr uint32_t kCeidNonScheduledTime = 1100; +inline constexpr uint32_t kCeidScheduledDowntime = 1101; +inline constexpr uint32_t kCeidUnscheduledDowntime = 1102; +inline constexpr uint32_t kCeidEngineering = 1103; +inline constexpr uint32_t kCeidStandby = 1104; +inline constexpr uint32_t kCeidProductive = 1105; + +} // namespace secsgem::gem::e116