@@ -1188,6 +1188,132 @@ void test_capacity_limit_non_numeric(void) {
11881188 TEST_ASSERT_FALSE (mqtt_parse_command (PREFIX , PREFIX "/Set/CapacityLimit" , "abc" , & cmd ));
11891189}
11901190
1191+ // ---- MaxCircuitMains ----
1192+
1193+ /*
1194+ * @feature MQTT Command Parsing
1195+ * @req REQ-CIR-010
1196+ * @scenario Set MaxCircuitMains to valid value via MQTT
1197+ * @given A valid MQTT prefix
1198+ * @when Topic is prefix/Set/MaxCircuitMains with payload "25"
1199+ * @then Command type is MQTT_CMD_MAX_CIRCUIT_MAINS with value 25
1200+ */
1201+ void test_max_circuit_mains_valid (void ) {
1202+ TEST_ASSERT_TRUE (mqtt_parse_command (PREFIX , PREFIX "/Set/MaxCircuitMains" , "25" , & cmd ));
1203+ TEST_ASSERT_EQUAL_INT (MQTT_CMD_MAX_CIRCUIT_MAINS , cmd .cmd );
1204+ TEST_ASSERT_EQUAL_INT (25 , cmd .max_circuit_mains );
1205+ }
1206+
1207+ /*
1208+ * @feature MQTT Command Parsing
1209+ * @req REQ-CIR-010
1210+ * @scenario Set MaxCircuitMains to zero (disable) via MQTT
1211+ * @given A valid MQTT prefix
1212+ * @when Topic is prefix/Set/MaxCircuitMains with payload "0"
1213+ * @then Command type is MQTT_CMD_MAX_CIRCUIT_MAINS with value 0
1214+ */
1215+ void test_max_circuit_mains_zero (void ) {
1216+ TEST_ASSERT_TRUE (mqtt_parse_command (PREFIX , PREFIX "/Set/MaxCircuitMains" , "0" , & cmd ));
1217+ TEST_ASSERT_EQUAL_INT (MQTT_CMD_MAX_CIRCUIT_MAINS , cmd .cmd );
1218+ TEST_ASSERT_EQUAL_INT (0 , cmd .max_circuit_mains );
1219+ }
1220+
1221+ /*
1222+ * @feature MQTT Command Parsing
1223+ * @req REQ-CIR-010
1224+ * @scenario Set MaxCircuitMains to boundary max (600) via MQTT
1225+ * @given A valid MQTT prefix
1226+ * @when Topic is prefix/Set/MaxCircuitMains with payload "600"
1227+ * @then Command type is MQTT_CMD_MAX_CIRCUIT_MAINS with value 600
1228+ */
1229+ void test_max_circuit_mains_max (void ) {
1230+ TEST_ASSERT_TRUE (mqtt_parse_command (PREFIX , PREFIX "/Set/MaxCircuitMains" , "600" , & cmd ));
1231+ TEST_ASSERT_EQUAL_INT (MQTT_CMD_MAX_CIRCUIT_MAINS , cmd .cmd );
1232+ TEST_ASSERT_EQUAL_INT (600 , cmd .max_circuit_mains );
1233+ }
1234+
1235+ /*
1236+ * @feature MQTT Input Validation
1237+ * @req REQ-CIR-010
1238+ * @scenario Reject MaxCircuitMains below minimum (1-9 range)
1239+ * @given A valid MQTT prefix
1240+ * @when Topic is prefix/Set/MaxCircuitMains with payload "5"
1241+ * @then Parsing returns false (gap between 0 and 10)
1242+ */
1243+ void test_max_circuit_mains_below_min (void ) {
1244+ TEST_ASSERT_FALSE (mqtt_parse_command (PREFIX , PREFIX "/Set/MaxCircuitMains" , "5" , & cmd ));
1245+ }
1246+
1247+ /*
1248+ * @feature MQTT Input Validation
1249+ * @req REQ-CIR-010
1250+ * @scenario Reject MaxCircuitMains above maximum
1251+ * @given A valid MQTT prefix
1252+ * @when Topic is prefix/Set/MaxCircuitMains with payload "601"
1253+ * @then Parsing returns false
1254+ */
1255+ void test_max_circuit_mains_above_max (void ) {
1256+ TEST_ASSERT_FALSE (mqtt_parse_command (PREFIX , PREFIX "/Set/MaxCircuitMains" , "601" , & cmd ));
1257+ }
1258+
1259+ // ---- CircuitMeter ----
1260+
1261+ /*
1262+ * @feature MQTT Command Parsing
1263+ * @req REQ-CIR-011
1264+ * @scenario Set CircuitMeter API feed via MQTT with L1:L2:L3 format
1265+ * @given A valid MQTT prefix
1266+ * @when Topic is prefix/Set/CircuitMeter with payload "100:200:150"
1267+ * @then Command type is MQTT_CMD_CIRCUIT_METER with parsed phase currents
1268+ */
1269+ void test_circuit_meter_valid (void ) {
1270+ TEST_ASSERT_TRUE (mqtt_parse_command (PREFIX , PREFIX "/Set/CircuitMeter" , "100:200:150" , & cmd ));
1271+ TEST_ASSERT_EQUAL_INT (MQTT_CMD_CIRCUIT_METER , cmd .cmd );
1272+ TEST_ASSERT_EQUAL_INT (100 , cmd .circuit_meter .L1 );
1273+ TEST_ASSERT_EQUAL_INT (200 , cmd .circuit_meter .L2 );
1274+ TEST_ASSERT_EQUAL_INT (150 , cmd .circuit_meter .L3 );
1275+ }
1276+
1277+ /*
1278+ * @feature MQTT Command Parsing
1279+ * @req REQ-CIR-011
1280+ * @scenario CircuitMeter API feed with negative values (export)
1281+ * @given A valid MQTT prefix
1282+ * @when Topic is prefix/Set/CircuitMeter with payload "-50:100:-25"
1283+ * @then Command type is MQTT_CMD_CIRCUIT_METER with correct phase currents
1284+ */
1285+ void test_circuit_meter_negative (void ) {
1286+ TEST_ASSERT_TRUE (mqtt_parse_command (PREFIX , PREFIX "/Set/CircuitMeter" , "-50:100:-25" , & cmd ));
1287+ TEST_ASSERT_EQUAL_INT (MQTT_CMD_CIRCUIT_METER , cmd .cmd );
1288+ TEST_ASSERT_EQUAL_INT (-50 , cmd .circuit_meter .L1 );
1289+ TEST_ASSERT_EQUAL_INT (100 , cmd .circuit_meter .L2 );
1290+ TEST_ASSERT_EQUAL_INT (-25 , cmd .circuit_meter .L3 );
1291+ }
1292+
1293+ /*
1294+ * @feature MQTT Input Validation
1295+ * @req REQ-CIR-011
1296+ * @scenario Reject CircuitMeter with out of range values
1297+ * @given A valid MQTT prefix
1298+ * @when Topic is prefix/Set/CircuitMeter with payload "2001:0:0"
1299+ * @then Parsing returns false (exceeds +/-2000 dA range)
1300+ */
1301+ void test_circuit_meter_out_of_range (void ) {
1302+ TEST_ASSERT_FALSE (mqtt_parse_command (PREFIX , PREFIX "/Set/CircuitMeter" , "2001:0:0" , & cmd ));
1303+ }
1304+
1305+ /*
1306+ * @feature MQTT Input Validation
1307+ * @req REQ-CIR-011
1308+ * @scenario Reject CircuitMeter with missing fields
1309+ * @given A valid MQTT prefix
1310+ * @when Topic is prefix/Set/CircuitMeter with payload "100:200"
1311+ * @then Parsing returns false (needs 3 fields)
1312+ */
1313+ void test_circuit_meter_missing_fields (void ) {
1314+ TEST_ASSERT_FALSE (mqtt_parse_command (PREFIX , PREFIX "/Set/CircuitMeter" , "100:200" , & cmd ));
1315+ }
1316+
11911317// ---- Unrecognized topic ----
11921318
11931319/*
@@ -1351,6 +1477,19 @@ int main(void) {
13511477 RUN_TEST (test_capacity_limit_empty );
13521478 RUN_TEST (test_capacity_limit_non_numeric );
13531479
1480+ // MaxCircuitMains (Plan 14)
1481+ RUN_TEST (test_max_circuit_mains_valid );
1482+ RUN_TEST (test_max_circuit_mains_zero );
1483+ RUN_TEST (test_max_circuit_mains_max );
1484+ RUN_TEST (test_max_circuit_mains_below_min );
1485+ RUN_TEST (test_max_circuit_mains_above_max );
1486+
1487+ // CircuitMeter (Plan 14)
1488+ RUN_TEST (test_circuit_meter_valid );
1489+ RUN_TEST (test_circuit_meter_negative );
1490+ RUN_TEST (test_circuit_meter_out_of_range );
1491+ RUN_TEST (test_circuit_meter_missing_fields );
1492+
13541493 // Unrecognized
13551494 RUN_TEST (test_unrecognized_topic );
13561495 RUN_TEST (test_wrong_prefix );
0 commit comments