Make modbus retry fast on read errors (#99576)

* Fast retry on read errors.

* Review comments.
This commit is contained in:
jan iversen 2023-09-12 16:01:15 +02:00 committed by Paulus Schoutsen
parent d399ebb8e1
commit 7235de1a0c
3 changed files with 13 additions and 10 deletions

View File

@ -115,7 +115,9 @@ class BasePlatform(Entity):
def async_run(self) -> None: def async_run(self) -> None:
"""Remote start entity.""" """Remote start entity."""
self.async_hold(update=False) self.async_hold(update=False)
self._cancel_call = async_call_later(self.hass, 1, self.async_update) self._cancel_call = async_call_later(
self.hass, timedelta(milliseconds=100), self.async_update
)
if self._scan_interval > 0: if self._scan_interval > 0:
self._cancel_timer = async_track_time_interval( self._cancel_timer = async_track_time_interval(
self.hass, self.async_update, timedelta(seconds=self._scan_interval) self.hass, self.async_update, timedelta(seconds=self._scan_interval)

View File

@ -1,7 +1,7 @@
"""Support for Modbus Register sensors.""" """Support for Modbus Register sensors."""
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timedelta
import logging import logging
from typing import Any from typing import Any
@ -19,6 +19,7 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
@ -106,12 +107,16 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity):
"""Update the state of the sensor.""" """Update the state of the sensor."""
# remark "now" is a dummy parameter to avoid problems with # remark "now" is a dummy parameter to avoid problems with
# async_track_time_interval # async_track_time_interval
self._cancel_call = None
raw_result = await self._hub.async_pb_call( raw_result = await self._hub.async_pb_call(
self._slave, self._address, self._count, self._input_type self._slave, self._address, self._count, self._input_type
) )
if raw_result is None: if raw_result is None:
if self._lazy_errors: if self._lazy_errors:
self._lazy_errors -= 1 self._lazy_errors -= 1
self._cancel_call = async_call_later(
self.hass, timedelta(seconds=1), self.async_update
)
return return
self._lazy_errors = self._lazy_error_count self._lazy_errors = self._lazy_error_count
self._attr_available = False self._attr_available = False

View File

@ -992,27 +992,23 @@ async def test_unpack_ok(hass: HomeAssistant, mock_do_cycle, expected) -> None:
], ],
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("register_words", "do_exception", "start_expect", "end_expect"), ("register_words", "do_exception"),
[ [
( (
[0x8000], [0x8000],
True, True,
"17",
STATE_UNAVAILABLE,
), ),
], ],
) )
async def test_lazy_error_sensor( async def test_lazy_error_sensor(
hass: HomeAssistant, mock_do_cycle: FrozenDateTimeFactory, start_expect, end_expect hass: HomeAssistant, mock_do_cycle: FrozenDateTimeFactory
) -> None: ) -> None:
"""Run test for sensor.""" """Run test for sensor."""
hass.states.async_set(ENTITY_ID, 17) hass.states.async_set(ENTITY_ID, 17)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID).state == start_expect assert hass.states.get(ENTITY_ID).state == "17"
await do_next_cycle(hass, mock_do_cycle, 5) await do_next_cycle(hass, mock_do_cycle, 5)
assert hass.states.get(ENTITY_ID).state == start_expect assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE
await do_next_cycle(hass, mock_do_cycle, 11)
assert hass.states.get(ENTITY_ID).state == end_expect
@pytest.mark.parametrize( @pytest.mark.parametrize(