Skip to content

Commit

Permalink
Add list as possible values for State On/Off ModBus Switch (home-assi…
Browse files Browse the repository at this point in the history
…stant#127444)

* add possibility to set multiple val on state

* Add support for list also in state_off
  • Loading branch information
crug80 authored Oct 18, 2024
1 parent 5a0ef14 commit 49d534e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
6 changes: 4 additions & 2 deletions homeassistant/components/modbus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,10 @@
CALL_TYPE_X_REGISTER_HOLDINGS,
]
),
vol.Optional(CONF_STATE_OFF): cv.positive_int,
vol.Optional(CONF_STATE_ON): cv.positive_int,
vol.Optional(CONF_STATE_OFF): vol.All(
cv.ensure_list, [cv.positive_int]
),
vol.Optional(CONF_STATE_ON): vol.All(cv.ensure_list, [cv.positive_int]),
vol.Optional(CONF_DELAY, default=0): cv.positive_int,
}
),
Expand Down
10 changes: 6 additions & 4 deletions homeassistant/components/modbus/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,10 @@ def __init__(self, hass: HomeAssistant, hub: ModbusHub, config: dict) -> None:
self._verify_type = convert[
config[CONF_VERIFY].get(CONF_INPUT_TYPE, config[CONF_WRITE_TYPE])
][0]
self._state_on = config[CONF_VERIFY].get(CONF_STATE_ON, self.command_on)
self._state_off = config[CONF_VERIFY].get(CONF_STATE_OFF, self._command_off)
self._state_on = config[CONF_VERIFY].get(CONF_STATE_ON, [self.command_on])
self._state_off = config[CONF_VERIFY].get(
CONF_STATE_OFF, [self._command_off]
)
else:
self._verify_active = False

Expand Down Expand Up @@ -363,9 +365,9 @@ async def async_update(self, now: datetime | None = None) -> None:
self._attr_is_on = bool(result.bits[0] & 1)
else:
value = int(result.registers[0])
if value == self._state_on:
if value in self._state_on:
self._attr_is_on = True
elif value == self._state_off:
elif value in self._state_off:
self._attr_is_on = False
elif value is not None:
_LOGGER.error(
Expand Down
95 changes: 95 additions & 0 deletions tests/components/modbus/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

ENTITY_ID = f"{SWITCH_DOMAIN}.{TEST_ENTITY_NAME}".replace(" ", "_")
ENTITY_ID2 = f"{ENTITY_ID}_2"
ENTITY_ID3 = f"{ENTITY_ID}_3"


@pytest.mark.parametrize(
Expand Down Expand Up @@ -153,6 +154,42 @@
}
]
},
{
CONF_SWITCHES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1234,
CONF_DEVICE_ADDRESS: 10,
CONF_COMMAND_OFF: 0x00,
CONF_COMMAND_ON: 0x01,
CONF_DEVICE_CLASS: "switch",
CONF_VERIFY: {
CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING,
CONF_ADDRESS: 1235,
CONF_STATE_OFF: 0,
CONF_STATE_ON: [1, 2, 3],
},
}
]
},
{
CONF_SWITCHES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1236,
CONF_DEVICE_ADDRESS: 10,
CONF_COMMAND_OFF: 0x00,
CONF_COMMAND_ON: 0x01,
CONF_DEVICE_CLASS: "switch",
CONF_VERIFY: {
CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING,
CONF_ADDRESS: 1235,
CONF_STATE_OFF: [0, 5, 6],
CONF_STATE_ON: 1,
},
}
]
},
],
)
async def test_config_switch(hass: HomeAssistant, mock_modbus) -> None:
Expand Down Expand Up @@ -218,6 +255,18 @@ async def test_config_switch(hass: HomeAssistant, mock_modbus) -> None:
None,
STATE_OFF,
),
(
[0x03],
False,
{CONF_VERIFY: {CONF_STATE_ON: [1, 3]}},
STATE_ON,
),
(
[0x04],
False,
{CONF_VERIFY: {CONF_STATE_OFF: [0, 4]}},
STATE_OFF,
),
],
)
async def test_all_switch(hass: HomeAssistant, mock_do_cycle, expected) -> None:
Expand Down Expand Up @@ -269,6 +318,13 @@ async def test_restore_state_switch(
CONF_SCAN_INTERVAL: 0,
CONF_VERIFY: {},
},
{
CONF_NAME: f"{TEST_ENTITY_NAME} 3",
CONF_ADDRESS: 18,
CONF_WRITE_TYPE: CALL_TYPE_REGISTER_HOLDING,
CONF_SCAN_INTERVAL: 0,
CONF_VERIFY: {CONF_STATE_ON: [1, 3]},
},
],
},
],
Expand Down Expand Up @@ -306,6 +362,19 @@ async def test_switch_service_turn(
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID2).state == STATE_OFF
mock_modbus.read_holding_registers.return_value = ReadResult([0x03])
assert hass.states.get(ENTITY_ID3).state == STATE_OFF
await hass.services.async_call(
"switch", "turn_on", service_data={"entity_id": ENTITY_ID3}
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID3).state == STATE_ON
mock_modbus.read_holding_registers.return_value = ReadResult([0x00])
await hass.services.async_call(
"switch", "turn_off", service_data={"entity_id": ENTITY_ID3}
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID3).state == STATE_OFF

mock_modbus.write_register.side_effect = ModbusException("fail write_")
await hass.services.async_call(
Expand All @@ -319,6 +388,12 @@ async def test_switch_service_turn(
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE
mock_modbus.write_register.side_effect = ModbusException("fail write_")
await hass.services.async_call(
"switch", "turn_on", service_data={"entity_id": ENTITY_ID3}
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID3).state == STATE_UNAVAILABLE


@pytest.mark.parametrize(
Expand All @@ -334,6 +409,26 @@ async def test_switch_service_turn(
}
]
},
{
CONF_SWITCHES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1236,
CONF_WRITE_TYPE: CALL_TYPE_COIL,
CONF_VERIFY: {CONF_STATE_ON: [1, 3]},
}
]
},
{
CONF_SWITCHES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1235,
CONF_WRITE_TYPE: CALL_TYPE_COIL,
CONF_VERIFY: {CONF_STATE_OFF: [0, 5]},
}
]
},
],
)
async def test_service_switch_update(hass: HomeAssistant, mock_modbus_ha) -> None:
Expand Down

0 comments on commit 49d534e

Please sign in to comment.