New LimitMonitorStore keyed by VID; each entry is a vector of LimitDefinition (LIMITID + upper/lower deadband as arbitrary Items). S2F45/F46 set, S2F47/F48 read. VLAACK validates each VID exists. Four new SxFy in the catalog; codegen handles the nested list-of-(VID, list-of-LimitDefinition) shape. LimitDefinition is defined in store/limits.hpp and referenced as external_struct so the data model and the message codecs share one type. The actual "value crossed limit" detection + CEID emission is left to the application's set_value path (E30 §6.21 leaves *how* the equipment detects crossings up to the implementer). COMPLIANCE.md: Limits Monitoring Additional capability flips ✅. Tests: 80 cases / 465 assertions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,36 @@ TEST_CASE("S10F3 terminal display round-trip") {
|
||||
CHECK(parsed->text == "ALARM: chiller temperature high");
|
||||
}
|
||||
|
||||
// ---- Limits Monitoring (S2F45-F48) -------------------------------------
|
||||
|
||||
TEST_CASE("S2F45 round-trips define-limits request") {
|
||||
std::vector<VidLimitsEntry> entries = {
|
||||
{100, {{0, s2::Item::u4(uint32_t{1000}), s2::Item::u4(uint32_t{0})}}},
|
||||
{101, {{0, s2::Item::f4(2.0f), s2::Item::f4(0.5f)},
|
||||
{1, s2::Item::f4(3.0f), s2::Item::f4(0.1f)}}},
|
||||
};
|
||||
auto m = s2f45_define_variable_limits(7, entries);
|
||||
auto parsed = parse_s2f45(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
CHECK(parsed->dataid == 7);
|
||||
REQUIRE(parsed->entries.size() == 2);
|
||||
CHECK(parsed->entries[0].vid == 100);
|
||||
REQUIRE(parsed->entries[0].limits.size() == 1);
|
||||
CHECK(parsed->entries[0].limits[0].upper == s2::Item::u4(uint32_t{1000}));
|
||||
CHECK(parsed->entries[1].vid == 101);
|
||||
REQUIRE(parsed->entries[1].limits.size() == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("S2F46 / S2F48 round-trips") {
|
||||
CHECK(*ack_byte(s2f46_define_variable_limits_ack(LimitMonitorAck::VidNotExist)) == 4);
|
||||
|
||||
std::vector<VidLimitsEntry> rows = {
|
||||
{100, {{0, s2::Item::u4(uint32_t{1000}), s2::Item::u4(uint32_t{0})}}}};
|
||||
auto m = s2f48_variable_limit_attribute_data(rows);
|
||||
REQUIRE(m.body.has_value());
|
||||
REQUIRE(m.body->is_list());
|
||||
}
|
||||
|
||||
// ---- S9 error-stream round-trips ----------------------------------------
|
||||
|
||||
TEST_CASE("S9 MHEAD-carrying messages round-trip") {
|
||||
|
||||
Reference in New Issue
Block a user