STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
ScriptStates.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include <map>
5#include <string>
6#include <vector>
7
8#include "config/Config.hpp"
11
12namespace sequencer {
13
14/**
15 * Hard ceiling on script_timeout_ms, independent of per-state config.
16 *
17 * Same posture as HoldParse's kMaxHoldMs: this is not the real limit — each state carries its own,
18 * usually far smaller — it exists so a typo cannot arm a valve-open window measured in hours.
19 */
20inline constexpr uint32_t kMaxScriptTimeoutMs = 600000; // 10 minutes
21
22/** One dynamic state, resolved and proven usable. */
25 std::string name;
27 uint32_t timeout_ms = 0;
28 /** Where the state lands when the script runs off its end. */
30 /** Where it lands when timeout_ms expires. May differ from return_target. */
32 /** Canonical PT role names this script reads, deduplicated. The pressure subscriber's
33 * subscribe list is the union of these across every dynamic state — Elodin has no wildcard,
34 * and deriving the list from the AST is what makes it impossible to subscribe to the wrong
35 * table for a role. */
36 std::vector<std::string> pressure_roles;
37
38 /**
39 * Parallel to program.slugs — what each slug reference resolves to, decided at load.
40 *
41 * Resolution cannot fail at runtime this way. A lookup performed mid-script would have to have
42 * a failure path, and the only honest thing that path could do is abort a script that is
43 * holding valves; doing it here means an unresolvable name is a state that never becomes
44 * enterable instead.
45 *
46 * `names` holds the canonical config name for actuator and sensor slugs (empty for states);
47 * `states` holds the resolved State for transition targets (UNKNOWN otherwise).
48 */
49 std::vector<std::string> slug_names;
50 std::vector<State> slug_states;
51};
52
53/**
54 * What a config load made of its dynamic states.
55 *
56 * A state lands in exactly one of the two maps. `refused` is not an error to be recovered from —
57 * it is the answer, and it is the safe one: the sequencer treats a refused state as not enterable,
58 * so a script that does not hold up produces an unavailable button rather than an open valve.
59 *
60 * This mirrors the five refusal branches [flow] already uses (SequencerService.cpp:384-445) and
61 * for the same stated reason: a hold that cannot close its valve has no safe degraded mode, so it
62 * must not be enterable at all.
63 */
65 std::map<State, DynamicState> dynamic;
66 std::map<State, std::string> refused; // state -> operator-readable reason
67};
68
69/** Everything load_dynamic_states needs that it cannot get from Config alone. */
71 /** Directory holding config.toml; scripts resolve to <config_dir>/scripts/<script_file>. */
72 std::string config_dir;
73 /** Transition matrix, already loaded. */
74 const StateMachine* state_machine = nullptr;
75 /** The [fire] state, so a script cannot be attached to the burn. */
77 /** True when the named state has a column in state_machine_actuators.csv. A dynamic state
78 * must have one: the column is the defined baseline the script layers onto, and without it
79 * entry would leave every unmentioned valve wherever the previous state put it. */
80 std::function<bool(const std::string& state_name)> has_actuator_column;
81};
82
83/**
84 * Resolve, load and validate every `[[states]]` entry carrying a script_file.
85 *
86 * Never throws and never partially applies: a state either comes back fully usable or fully
87 * refused with a reason fit to show an operator.
88 */
89ScriptLoadResult load_dynamic_states(const fsw::config::Config& cfg, const std::string& config_text,
90 const ScriptLoadContext& ctx);
91
92/** True when `name` is a safe bare script filename: ^[A-Za-z0-9_-]+\.script$, no separators. */
93bool is_valid_script_filename(const std::string& name);
94
95} // namespace sequencer
Parses state_transitions.csv and validates state transitions.
bool is_valid_script_filename(const std::string &name)
True when name is a safe bare script filename: ^[A-Za-z0-9_-]+.script$, no separators.
constexpr uint32_t kMaxScriptTimeoutMs
Hard ceiling on script_timeout_ms, independent of per-state config.
ScriptLoadResult load_dynamic_states(const fsw::config::Config &cfg, const std::string &config_text, const ScriptLoadContext &ctx)
Resolve, load and validate every [[states]] entry carrying a script_file.
State
System state IDs — must match the TypeScript SystemState enum in web-gui/shared/types....
The whole parsed config.toml, restricted to what C++ consumes.
Definition Config.hpp:264
A parsed script, as a flat arena.
One dynamic state, resolved and proven usable.
State return_target
Where the state lands when the script runs off its end.
std::vector< std::string > pressure_roles
Canonical PT role names this script reads, deduplicated.
std::vector< std::string > slug_names
Parallel to program.slugs — what each slug reference resolves to, decided at load.
State timeout_target
Where it lands when timeout_ms expires.
fsw::script::ScriptProgram program
std::vector< State > slug_states
Everything load_dynamic_states needs that it cannot get from Config alone.
const StateMachine * state_machine
Transition matrix, already loaded.
State fire_state
The [fire] state, so a script cannot be attached to the burn.
std::function< bool(const std::string &state_name)> has_actuator_column
True when the named state has a column in state_machine_actuators.csv.
std::string config_dir
Directory holding config.toml; scripts resolve to <config_dir>/scripts/<script_file>.
What a config load made of its dynamic states.
std::map< State, std::string > refused
std::map< State, DynamicState > dynamic