mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 09:58:07 -04:00
Add configurable delay between connect and first request in modbus (#50124)
* Activate startup delay. * Add removal of call_later if HA is stopped. This is unlikely to happen, but just security measure. * Removing timing interval. async_fire_time_changed() needs to be called twice, first time the delay is ended and second time update() is executed. * Variable naming.
This commit is contained in:
@@ -39,6 +39,7 @@ from homeassistant.const import (
|
||||
CONF_METHOD,
|
||||
CONF_NAME,
|
||||
CONF_PORT,
|
||||
CONF_SCAN_INTERVAL,
|
||||
CONF_SENSORS,
|
||||
CONF_TIMEOUT,
|
||||
CONF_TYPE,
|
||||
@@ -160,6 +161,12 @@ async def _config_helper(hass, do_config, caplog):
|
||||
CONF_TIMEOUT: 30,
|
||||
CONF_DELAY: 10,
|
||||
},
|
||||
{
|
||||
CONF_TYPE: "tcp",
|
||||
CONF_HOST: "modbusTestHost",
|
||||
CONF_PORT: 5501,
|
||||
CONF_DELAY: 5,
|
||||
},
|
||||
],
|
||||
)
|
||||
async def test_config_modbus(hass, caplog, do_config, mock_pymodbus):
|
||||
@@ -467,3 +474,116 @@ async def test_pymodbus_connect_fail(hass, caplog, mock_pymodbus):
|
||||
await hass.async_block_till_done()
|
||||
assert len(caplog.records) == 1
|
||||
assert caplog.records[0].levelname == "ERROR"
|
||||
|
||||
|
||||
async def test_delay(hass, mock_pymodbus):
|
||||
"""Run test for different read."""
|
||||
|
||||
# the purpose of this test is to test startup delay
|
||||
# We "hijiack" binary_sensor and sensor in order
|
||||
# to make a proper blackbox test.
|
||||
config = {
|
||||
DOMAIN: [
|
||||
{
|
||||
CONF_TYPE: "tcp",
|
||||
CONF_HOST: "modbusTestHost",
|
||||
CONF_PORT: 5501,
|
||||
CONF_NAME: TEST_MODBUS_NAME,
|
||||
CONF_DELAY: 15,
|
||||
CONF_BINARY_SENSORS: [
|
||||
{
|
||||
CONF_INPUT_TYPE: CALL_TYPE_COIL,
|
||||
CONF_NAME: f"{TEST_SENSOR_NAME}_2",
|
||||
CONF_ADDRESS: 52,
|
||||
CONF_SCAN_INTERVAL: 5,
|
||||
},
|
||||
{
|
||||
CONF_INPUT_TYPE: CALL_TYPE_DISCRETE,
|
||||
CONF_NAME: f"{TEST_SENSOR_NAME}_1",
|
||||
CONF_ADDRESS: 51,
|
||||
CONF_SCAN_INTERVAL: 5,
|
||||
},
|
||||
],
|
||||
CONF_SENSORS: [
|
||||
{
|
||||
CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING,
|
||||
CONF_NAME: f"{TEST_SENSOR_NAME}_3",
|
||||
CONF_ADDRESS: 53,
|
||||
CONF_SCAN_INTERVAL: 5,
|
||||
},
|
||||
{
|
||||
CONF_INPUT_TYPE: CALL_TYPE_REGISTER_INPUT,
|
||||
CONF_NAME: f"{TEST_SENSOR_NAME}_4",
|
||||
CONF_ADDRESS: 54,
|
||||
CONF_SCAN_INTERVAL: 5,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
mock_pymodbus.read_coils.return_value = ReadResult([0x01])
|
||||
mock_pymodbus.read_discrete_inputs.return_value = ReadResult([0x01])
|
||||
mock_pymodbus.read_holding_registers.return_value = ReadResult([7])
|
||||
mock_pymodbus.read_input_registers.return_value = ReadResult([7])
|
||||
now = dt_util.utcnow()
|
||||
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||
assert await async_setup_component(hass, DOMAIN, config) is True
|
||||
await hass.async_block_till_done()
|
||||
|
||||
now = now + timedelta(seconds=10)
|
||||
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||
async_fire_time_changed(hass, now)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check states
|
||||
entity_id = f"{BINARY_SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_1"
|
||||
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{BINARY_SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_2"
|
||||
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_3"
|
||||
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_4"
|
||||
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
|
||||
mock_pymodbus.reset_mock()
|
||||
data = {
|
||||
ATTR_HUB: TEST_MODBUS_NAME,
|
||||
ATTR_UNIT: 17,
|
||||
ATTR_ADDRESS: 16,
|
||||
ATTR_STATE: False,
|
||||
}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_WRITE_COIL, data, blocking=True)
|
||||
assert not mock_pymodbus.write_coil.called
|
||||
await hass.services.async_call(DOMAIN, SERVICE_WRITE_COIL, data, blocking=True)
|
||||
assert not mock_pymodbus.write_coil.called
|
||||
data[ATTR_STATE] = [True, False, True]
|
||||
await hass.services.async_call(DOMAIN, SERVICE_WRITE_COIL, data, blocking=True)
|
||||
assert not mock_pymodbus.write_coils.called
|
||||
|
||||
del data[ATTR_STATE]
|
||||
data[ATTR_VALUE] = 15
|
||||
await hass.services.async_call(DOMAIN, SERVICE_WRITE_REGISTER, data, blocking=True)
|
||||
assert not mock_pymodbus.write_register.called
|
||||
data[ATTR_VALUE] = [1, 2, 3]
|
||||
await hass.services.async_call(DOMAIN, SERVICE_WRITE_REGISTER, data, blocking=True)
|
||||
assert not mock_pymodbus.write_registers.called
|
||||
|
||||
# 2 times fire_changed is needed to secure "normal" update is called.
|
||||
now = now + timedelta(seconds=6)
|
||||
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||
async_fire_time_changed(hass, now)
|
||||
await hass.async_block_till_done()
|
||||
now = now + timedelta(seconds=10)
|
||||
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||
async_fire_time_changed(hass, now)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check states
|
||||
entity_id = f"{BINARY_SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_1"
|
||||
assert not hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{BINARY_SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_2"
|
||||
assert not hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_3"
|
||||
assert not hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
entity_id = f"{SENSOR_DOMAIN}.{TEST_SENSOR_NAME}_4"
|
||||
assert not hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
|
||||
Reference in New Issue
Block a user