Skip to content

Commit a053142

Browse files
authored
modbus: Do not modify registers (return wrong data). (#151131)
1 parent dd0dce7 commit a053142

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

homeassistant/components/modbus/entity.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from abc import abstractmethod
66
from collections.abc import Callable
7+
import copy
78
from datetime import datetime, timedelta
89
import struct
910
from typing import Any, cast
@@ -280,7 +281,9 @@ def unpack_structure_result(self, registers: list[int]) -> str | None:
280281
"""Convert registers to proper result."""
281282

282283
if self._swap:
283-
registers = self._swap_registers(registers, self._slave_count)
284+
registers = self._swap_registers(
285+
copy.deepcopy(registers), self._slave_count
286+
)
284287
byte_string = b"".join([x.to_bytes(2, byteorder="big") for x in registers])
285288
if self._data_type == DataType.STRING:
286289
return byte_string.decode()

tests/components/modbus/test_sensor.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,46 @@ async def test_wrap_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None
13571357
assert hass.states.get(ENTITY_ID).state == expected
13581358

13591359

1360+
@pytest.mark.parametrize(
1361+
"do_config",
1362+
[
1363+
{
1364+
CONF_SENSORS: [
1365+
{
1366+
CONF_NAME: TEST_ENTITY_NAME,
1367+
CONF_ADDRESS: 201,
1368+
},
1369+
],
1370+
},
1371+
],
1372+
)
1373+
@pytest.mark.parametrize(
1374+
("config_addon", "register_words", "expected"),
1375+
[
1376+
(
1377+
{
1378+
CONF_SWAP: CONF_SWAP_WORD,
1379+
CONF_DATA_TYPE: DataType.UINT32,
1380+
},
1381+
[0x0102, 0x0304],
1382+
"50594050",
1383+
),
1384+
],
1385+
)
1386+
async def test_wrap_regs_ok_sensor(
1387+
hass: HomeAssistant, mock_modbus_ha, mock_do_cycle, expected
1388+
) -> None:
1389+
"""Run test for sensor struct."""
1390+
assert hass.states.get(ENTITY_ID).state == expected
1391+
await hass.services.async_call(
1392+
HOMEASSISTANT_DOMAIN,
1393+
SERVICE_UPDATE_ENTITY,
1394+
{ATTR_ENTITY_ID: ENTITY_ID},
1395+
blocking=True,
1396+
)
1397+
assert hass.states.get(ENTITY_ID).state == expected
1398+
1399+
13601400
@pytest.fixture(name="mock_restore")
13611401
async def mock_restore(hass: HomeAssistant) -> None:
13621402
"""Mock restore cache."""

0 commit comments

Comments
 (0)