#pragma once #include #include #include #include #include #include #include "secsgem/gem/control_job_state.hpp" #include "secsgem/gem/control_state.hpp" #include "secsgem/gem/data_model.hpp" #include "secsgem/gem/process_job_state.hpp" // YAML-driven loaders for the E30 control-state transition table and the // equipment data dictionary. Behaviour rules live in the YAML; this is the // parser that wires them into the runtime structures. namespace secsgem::config { class ConfigError : public std::runtime_error { public: using std::runtime_error::runtime_error; }; struct ControlStateConfig { gem::ControlTransitionTable table; gem::ControlState initial = gem::ControlState::HostOffline; }; // Loads data/control_state.yaml. ControlStateConfig load_control_state(const std::string& yaml_path); struct EquipmentDescriptor { uint16_t device_id = 0; std::string model_name; std::string software_rev; std::string equipment_type; // S1F20 EQPTYP std::vector> capabilities; // (CCODE, CDESC) std::optional emit_on_control_change; }; // Loads data/equipment.yaml into the given data model and returns the // equipment header (device id, MDLN, SOFTREV, optional auto-emit CEID). EquipmentDescriptor load_equipment(const std::string& yaml_path, gem::EquipmentDataModel& model); struct ProcessJobStateConfig { gem::ProcessJobTransitionTable table; gem::ProcessJobState initial = gem::ProcessJobState::Queued; }; // Loads data/process_job_state.yaml. ProcessJobStateConfig load_process_job_state(const std::string& yaml_path); struct ControlJobStateConfig { gem::ControlJobTransitionTable table; gem::ControlJobState initial = gem::ControlJobState::Queued; }; // Loads data/control_job_state.yaml. ControlJobStateConfig load_control_job_state(const std::string& yaml_path); } // namespace secsgem::config