[modbus_server] Add tests for U_WORD_S and S_WORD_S (#17832)

Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
This commit is contained in:
Marek Pilch
2026-08-05 14:47:48 -04:00
committed by GitHub
co-authored by Jonathan Swoboda
parent 202b31f711
commit b521b5e1ca
6 changed files with 110 additions and 1 deletions
@@ -82,3 +82,5 @@ def test_raw_value_type_rejected() -> None:
with pytest.raises(cv.Invalid):
validator("RAW")
assert validator("U_WORD") == "U_WORD"
assert validator("U_WORD_S") == "U_WORD_S"
assert validator("S_WORD_S") == "S_WORD_S"
@@ -40,3 +40,11 @@ modbus_server:
value_type: U_WORD
read_lambda: |-
return (random_uint32() % 100);
# Covers CPP_TYPE_REGISTER_MAP / signed byte-swapped codegen
- address: 0x6
value_type: S_WORD_S
read_lambda: |-
return -2;
write_lambda: |-
printf("address=%d, value=%d\n", (int) address, (int) x);
return true;
@@ -34,6 +34,21 @@ TEST(ModbusServerWrite, SingleWordSucceeds) {
EXPECT_EQ(written, 0x1234);
}
TEST(ModbusServerWrite, SwappedWordSucceeds) {
ModbusServer server;
int64_t written = -1;
ServerRegister reg(0x0000, SensorValueType::U_WORD_S, 1);
reg.write_lambda = [&written](int64_t value) {
written = value;
return true;
};
server.add_server_register(&reg);
auto status = server.on_write_registers(0x0000, make_registers({0x3412}));
EXPECT_FALSE(status.has_value());
EXPECT_EQ(written, 0x1234);
}
// A multi-register value is decoded high word first and applied as a single number.
TEST(ModbusServerWrite, DwordSucceeds) {
ModbusServer server;
@@ -136,6 +151,19 @@ TEST(ModbusServerRead, SingleWordSucceeds) {
EXPECT_EQ(out[0], 0x1234);
}
TEST(ModbusServerRead, SwappedWordReturnsByteSwappedRegister) {
ModbusServer server;
ServerRegister reg(0x0000, SensorValueType::U_WORD_S, 1);
reg.read_lambda = []() -> int64_t { return 0x1234; };
server.add_server_register(&reg);
RegisterValues out;
auto status = server.on_read_registers(0x0000, 1, out);
EXPECT_FALSE(status.has_value());
ASSERT_EQ(out.size(), 1u);
EXPECT_EQ(out[0], 0x3412);
}
TEST(ModbusServerRead, DwordReturnsTwoWordsHighFirst) {
ModbusServer server;
ServerRegister reg(0x0000, SensorValueType::U_DWORD, 2);
@@ -64,9 +64,15 @@ modbus_server:
- address: 0x01
value_type: U_WORD
read_lambda: return 99;
- address: 0x02
value_type: U_WORD_S
read_lambda: return 4660;
- address: 0x03
value_type: S_WORD
read_lambda: return -99;
- address: 0x04
value_type: S_WORD_S
read_lambda: return -2;
- address: 0x05
value_type: U_DWORD
read_lambda: return 16909060;
@@ -105,12 +111,30 @@ sensor:
address: 0x01
register_type: holding
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_u_word_s"
address: 0x02
register_type: holding
value_type: U_WORD_S
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_u_word_s_raw"
address: 0x02
register_type: holding
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_s_word"
address: 0x03
register_type: holding
value_type: S_WORD
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_s_word_s"
address: 0x04
register_type: holding
value_type: S_WORD_S
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_u_dword"
@@ -45,9 +45,15 @@ globals:
- id: stored_u_word
type: uint16_t
initial_value: "11"
- id: stored_u_word_s
type: uint16_t
initial_value: "4660"
- id: stored_s_word
type: int16_t
initial_value: "-11"
- id: stored_s_word_s
type: int16_t
initial_value: "-2"
- id: stored_u_dword
type: uint32_t
initial_value: "1001"
@@ -103,10 +109,18 @@ modbus_server:
value_type: U_WORD
read_lambda: return id(stored_u_word);
write_lambda: id(stored_u_word) = x; return true;
- address: 0x02
value_type: U_WORD_S
read_lambda: return id(stored_u_word_s);
write_lambda: id(stored_u_word_s) = x; return true;
- address: 0x03
value_type: S_WORD
read_lambda: return id(stored_s_word);
write_lambda: id(stored_s_word) = x; return true;
- address: 0x04
value_type: S_WORD_S
read_lambda: return id(stored_s_word_s);
write_lambda: id(stored_s_word_s) = x; return true;
- address: 0x05
value_type: U_DWORD
read_lambda: return id(stored_u_dword);
@@ -155,12 +169,24 @@ sensor:
address: 0x01
register_type: holding
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_u_word_s"
address: 0x02
register_type: holding
value_type: U_WORD_S
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_s_word"
address: 0x03
register_type: holding
value_type: S_WORD
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_s_word_s"
address: 0x04
register_type: holding
value_type: S_WORD_S
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "reg_u_dword"
@@ -231,6 +257,14 @@ number:
value_type: U_WORD
min_value: 0
max_value: 65535
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "write_u_word_s"
address: 0x02
register_type: holding
value_type: U_WORD_S
min_value: 0
max_value: 65535
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "write_s_word"
@@ -239,6 +273,14 @@ number:
value_type: S_WORD
min_value: -16777215
max_value: 16777215
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "write_s_word_s"
address: 0x04
register_type: holding
value_type: S_WORD_S
min_value: -16777215
max_value: 16777215
- platform: modbus_controller
modbus_controller_id: modbus_controller_1
name: "write_u_dword"
+6 -1
View File
@@ -215,7 +215,10 @@ async def test_uart_mock_modbus_server_controller(
expected_values = {
"reg_u_word": 99,
"reg_u_word_s": 4660,
"reg_u_word_s_raw": 13330,
"reg_s_word": -99,
"reg_s_word_s": -2,
"reg_u_dword": 16909060,
"reg_s_dword": -16909060,
"reg_u_dword_r": pytest.approx(67305985),
@@ -249,14 +252,16 @@ async def test_uart_mock_modbus_server_controller_write(
Verifies that writing to modbus server registers via the controller updates
the server's stored values, which are then read back correctly on the next poll.
All 12 value types are tested: U/S_WORD, U/S_DWORD(_R), U/S_QWORD(_R), FP32(_R).
All 14 value types are tested: U/S_WORD, U/S_WORD_S, U/S_DWORD(_R), U/S_QWORD(_R), FP32(_R).
"""
line_callback, error_log_lines, warning_log_lines = _make_modbus_line_callback()
register_test_cases: dict[str, RegisterTestCase] = {
"reg_u_word": RegisterTestCase(11, "write_u_word", 42, 42),
"reg_u_word_s": RegisterTestCase(4660, "write_u_word_s", 17185, 17185),
"reg_s_word": RegisterTestCase(-11, "write_s_word", -42, -42),
"reg_s_word_s": RegisterTestCase(-2, "write_s_word_s", -257, -257),
"reg_u_dword": RegisterTestCase(1001, "write_u_dword", 2002, 2002),
"reg_s_dword": RegisterTestCase(-1001, "write_s_dword", -2002, -2002),
"reg_u_dword_r": RegisterTestCase(3003, "write_u_dword_r", 4004, 4004),