d159bd39d7
Hierarchical object tree for equipment self-description. Each object carries a CemObjectType (Equipment / Subsystem / IODevice / Module / MaterialLocation / Other), an optional parent_objid, and a flat attribute map keyed by name (the wire shape S14F1 / F3 returns). Operations covered: add(CemObject) - dedup'd, validates parent exists get / has - lookup by objid get_attr / set_attr - E14 GetAttr / SetAttr semantics children(parent) - tree traversal; empty parent = roots The flat-map representation matches how E14 ObjectService traffic addresses nodes (by OBJSPEC string). Wiring S14F1/F2 GetAttr and S14F3/F4 SetAttr to this store is a downstream commit; the data model is what was missing. Joins EquipmentDataModel alongside the other top-level stores. Three test cases cover hierarchical add+dedup, children() traversal, and get/set/missing attribute semantics. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
63 lines
1.9 KiB
C++
63 lines
1.9 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "secsgem/gem/carrier_state.hpp" // shared CarrierTransition template
|
|
|
|
// E157 §6 Module Process Tracking — per-module state model for a process
|
|
// step within a recipe. The lifecycle is similar to E40 PJ but scoped
|
|
// to a single module step rather than a whole job; an E157 instance is
|
|
// typically created per (Module, Substrate, RecipeStep) triple by the
|
|
// process executive when a wafer arrives at a module.
|
|
//
|
|
// Wire-byte values per E157-0712 §10.3.
|
|
namespace secsgem::gem {
|
|
|
|
enum class ModuleState : uint8_t {
|
|
NotExecuting = 0,
|
|
GeneralExecuting = 1, // setup, pre-process, etc.
|
|
StepExecuting = 2, // actively running the recipe step
|
|
StepCompleted = 3,
|
|
NoState = 255,
|
|
};
|
|
|
|
const char* module_state_name(ModuleState s);
|
|
std::optional<ModuleState> parse_module_state(const std::string& s);
|
|
|
|
enum class ModuleEvent {
|
|
StartGeneral, // NotExecuting -> GeneralExecuting
|
|
StartStep, // GeneralExecuting -> StepExecuting
|
|
CompleteStep, // StepExecuting -> StepCompleted
|
|
Reset, // any -> NotExecuting (cancellation)
|
|
Abort, // any -> StepCompleted (early termination)
|
|
};
|
|
|
|
const char* module_event_name(ModuleEvent e);
|
|
|
|
using ModuleTable = CarrierTransitionTable<ModuleState, ModuleEvent>;
|
|
ModuleTable default_module_table();
|
|
|
|
class ModuleStateMachine {
|
|
public:
|
|
using StateChangeHandler =
|
|
std::function<void(ModuleState from, ModuleState to, ModuleEvent)>;
|
|
|
|
ModuleStateMachine();
|
|
|
|
ModuleState state() const { return state_; }
|
|
void set_state_change_handler(StateChangeHandler h) { on_change_ = std::move(h); }
|
|
|
|
bool on_event(ModuleEvent e);
|
|
|
|
private:
|
|
ModuleTable table_;
|
|
ModuleState state_ = ModuleState::NotExecuting;
|
|
StateChangeHandler on_change_;
|
|
};
|
|
|
|
} // namespace secsgem::gem
|