28static void check(
bool ok,
const std::string& what) {
29 std::cout << (
ok ?
" ok " :
" FAIL ") << what << std::endl;
65[boards.pt_board_slot10]
71[boards.actuator_board]
77[sensor_roles_pt_board_z]
80[sensor_roles_pt_board]
85[sensor_roles_pt_board_2]
89[sensor_roles_pt_board_off]
92[sensor_roles_pt_board_slot10]
95[sensor_roles_actuator_board]
101 check(cfg.boards.size() == 6,
"fixture parsed six boards");
106 check(
r.has_value(),
"GN2 Regulated resolves");
108 check(
r->board_key ==
"pt_board",
"GN2 Regulated is on pt_board");
109 check(
r->channel == 6,
"GN2 Regulated is channel 6");
110 check(
r->board_number == 1,
"board_id 21 -> slot 1");
111 check(
r->table() == std::make_pair<uint8_t, uint8_t>(0x20, 0x16),
112 "GN2 Regulated table is {0x20, 0x16}");
117 check(
r.has_value(),
"GN2 High resolves");
119 check(
r->board_number == 2,
"board_id 22 -> slot 2");
120 check(
r->channel == 4,
"GN2 High is channel 4");
124 r->table() == std::make_pair<uint8_t, uint8_t>(0x20, 0x34),
125 "GN2 High table is {0x20, 0x34} — board 2, NOT in ControllerService's 0x11..0x1A");
126 check(
r->board !=
nullptr &&
r->board->ip ==
"192.168.2.22",
127 "ref carries the owning board");
134 check(
r.has_value(),
"Slot Ten Sensor resolves");
136 check(
r->board_number == 10,
"board_id 30 -> slot 10 (not 0)");
140 check(
r->table_lo ==
static_cast<uint8_t
>((10 - 1) * 0x20 + 0x10 + 2),
141 "slot 10 table_lo follows the documented encoding");
147 "a disabled board's roles do not resolve");
149 "a non-PT board's roles do not resolve");
151 "an unknown role resolves to nullopt, not a default");
162 check(
r.has_value() &&
r->board_key ==
"pt_board_2",
163 "duplicate role resolves by cfg.boards order (key-sorted), not TOML text order");
171 check(all.size() == 7,
"pt_role_tables lists every enabled PT board's roles and no others");
172 bool saw_ghost =
false, saw_actuator_role =
false;
173 for (
const auto&
r : all) {
174 if (
r.role ==
"Ghost Sensor")
176 if (
r.role ==
"Not A Sensor")
177 saw_actuator_role =
true;
179 check(!saw_ghost,
"pt_role_tables omits a disabled board");
180 check(!saw_actuator_role,
"pt_role_tables omits a non-PT board");
189 const std::string
t7 = std::string(
kConfig) + R
"TOML(
195[[boards.labjack_1.channels]]
202[[boards.labjack_1.channels]]
214[[boards.labjack_2.channels]]
217role = "Disabled T7 PT"
224 check(
r.has_value(),
"a T7 PT input resolves by role");
226 check(
r->t7 !=
nullptr &&
r->board ==
nullptr &&
r->board_key ==
"labjack_1",
227 "it carries its T7, and no ESP32 board");
228 check(
r->channel == 6 &&
r->board_number == 1,
"AIN6 on slot 1");
230 check(
r->table() == std::make_pair(
id[0],
id[1]) &&
231 r->table() == std::make_pair<uint8_t, uint8_t>(0x26, 0x16),
232 "its table is the T7 calibrated table {0x26, 0x16}, not {0x20, 0x16}");
236 "nor does a PT on a disabled T7");
238 std::make_pair<uint8_t, uint8_t>(0x20, 0x16),
239 "the ESP32 PT with the same low byte keeps its own table");
244 "a state script may name it (slug T7_TANK)");
250 "\n[[boards.labjack_1.channels]]\nain = 99\n"
251 "kind = \"PT\"\nrole = \"Bad\"\n");
253 "with T7 config errors no T7 input resolves");
259 b.section =
"boards.pt_board_2";
261 b.section =
"pt_board_2";
263 "board_key_of passes a bare key through");
266 std::cout << (
g_failures == 0 ?
"\nAll sensor-table checks passed.\n"
267 :
"\nFAILURES: " + std::to_string(
g_failures) +
"\n");
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
std::optional< PtRoleRef > find_pt_role(const Config &cfg, const std::string &role)
Resolve one role by its canonical config name.
std::string board_key_of(const BoardConfig &b)
The board's section name minus a leading "boards.", e.g.
Config load_from_string(const std::string &text)
Parse config from an in-memory TOML string (SequencerService / ActuatorCommander hold it so).
std::vector< PtRoleRef > pt_role_tables(const Config &cfg)
Every PT sensor role declared by an enabled PT board, in board-declaration order, then every PT input...
std::string slugify(const std::string &name)
Canonical name -> slug: trim, uppercase, collapse internal whitespace runs to a single '_'.
TableBuild build_slug_tables(const fsw::config::Config &cfg)
Build the actuator / sensor / state slug tables from a loaded config.
std::array< uint8_t, 2 > calibrated_table_id(uint8_t slot, uint8_t ain)
Calibrated table for one AIN: table_id + 0x10, e.g.
The whole parsed config.toml, restricted to what C++ consumes.
std::vector< std::string > t7_errors
static void check(bool ok, const std::string &what)
static std::string t7(const std::string &channels, const std::string &extra="", const std::string &name="lj", int board_id=81)
static const uint8_t kConfig[]