From 9acca1bf5833cfa000e663f156f13411702c8114 Mon Sep 17 00:00:00 2001
From: jan iversen <jancasacondor@gmail.com>
Date: Tue, 12 Sep 2023 16:01:15 +0200
Subject: [PATCH] Make modbus retry fast on read errors (#99576)

* Fast retry on read errors.

* Review comments.
---
 homeassistant/components/modbus/base_platform.py |  4 +++-
 homeassistant/components/modbus/sensor.py        |  7 ++++++-
 tests/components/modbus/test_sensor.py           | 12 ++++--------
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/homeassistant/components/modbus/base_platform.py b/homeassistant/components/modbus/base_platform.py
index 672250790da..0db716c3403 100644
--- a/homeassistant/components/modbus/base_platform.py
+++ b/homeassistant/components/modbus/base_platform.py
@@ -115,7 +115,9 @@ class BasePlatform(Entity):
     def async_run(self) -> None:
         """Remote start entity."""
         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:
             self._cancel_timer = async_track_time_interval(
                 self.hass, self.async_update, timedelta(seconds=self._scan_interval)
diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py
index fe2d4bc415d..f2ed504b41b 100644
--- a/homeassistant/components/modbus/sensor.py
+++ b/homeassistant/components/modbus/sensor.py
@@ -1,7 +1,7 @@
 """Support for Modbus Register sensors."""
 from __future__ import annotations
 
-from datetime import datetime
+from datetime import datetime, timedelta
 import logging
 from typing import Any
 
@@ -19,6 +19,7 @@ from homeassistant.const import (
 )
 from homeassistant.core import HomeAssistant, callback
 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.update_coordinator import (
     CoordinatorEntity,
@@ -106,12 +107,16 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity):
         """Update the state of the sensor."""
         # remark "now" is a dummy parameter to avoid problems with
         # async_track_time_interval
+        self._cancel_call = None
         raw_result = await self._hub.async_pb_call(
             self._slave, self._address, self._count, self._input_type
         )
         if raw_result is None:
             if self._lazy_errors:
                 self._lazy_errors -= 1
+                self._cancel_call = async_call_later(
+                    self.hass, timedelta(seconds=1), self.async_update
+                )
                 return
             self._lazy_errors = self._lazy_error_count
             self._attr_available = False
diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py
index 551398c898b..98fd537f1bf 100644
--- a/tests/components/modbus/test_sensor.py
+++ b/tests/components/modbus/test_sensor.py
@@ -946,27 +946,23 @@ async def test_wrong_unpack(hass: HomeAssistant, mock_do_cycle) -> None:
     ],
 )
 @pytest.mark.parametrize(
-    ("register_words", "do_exception", "start_expect", "end_expect"),
+    ("register_words", "do_exception"),
     [
         (
             [0x8000],
             True,
-            "17",
-            STATE_UNAVAILABLE,
         ),
     ],
 )
 async def test_lazy_error_sensor(
-    hass: HomeAssistant, mock_do_cycle: FrozenDateTimeFactory, start_expect, end_expect
+    hass: HomeAssistant, mock_do_cycle: FrozenDateTimeFactory
 ) -> None:
     """Run test for sensor."""
     hass.states.async_set(ENTITY_ID, 17)
     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)
-    assert hass.states.get(ENTITY_ID).state == start_expect
-    await do_next_cycle(hass, mock_do_cycle, 11)
-    assert hass.states.get(ENTITY_ID).state == end_expect
+    assert hass.states.get(ENTITY_ID).state == STATE_UNAVAILABLE
 
 
 @pytest.mark.parametrize(