Use debouncer in mysensors (#84638)

* Use debouncer in mysensors

* Clean cover tests

* Fix debouncer mocking

* Follow typing
pull/84654/head
Martin Hjelmare 2022-12-27 21:37:10 +01:00 committed by GitHub
parent 624c93bb38
commit d441fb2ec5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 31 additions and 159 deletions

View File

@ -10,6 +10,7 @@ from mysensors.sensor import ChildSensor
from homeassistant.const import ATTR_BATTERY_LEVEL, STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DeviceInfo, Entity
@ -55,7 +56,7 @@ class MySensorsDevice(ABC):
self.value_type: int = value_type # value_type as int. string variant can be looked up in gateway consts
self.child_type = self._child.type
self._values: dict[int, Any] = {}
self._update_scheduled = False
self._debouncer: Debouncer | None = None
@property
def dev_id(self) -> DevId:
@ -184,24 +185,18 @@ class MySensorsDevice(ABC):
def _async_update_callback(self) -> None:
"""Update the device."""
@callback
def async_update_callback(self) -> None:
async def async_update_callback(self) -> None:
"""Update the device after delay."""
if self._update_scheduled:
return
if not self._debouncer:
self._debouncer = Debouncer(
self.hass,
_LOGGER,
cooldown=UPDATE_DELAY,
immediate=False,
function=self._async_update_callback,
)
@callback
def async_update() -> None:
"""Perform update."""
try:
self._async_update_callback()
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error updating %s", self.name)
finally:
self._update_scheduled = False
self._update_scheduled = True
self.hass.loop.call_later(UPDATE_DELAY, async_update)
await self._debouncer.async_call()
def get_mysensors_devices(

View File

@ -144,8 +144,26 @@ async def integration_fixture(
"""Set up the mysensors integration with a config entry."""
config: dict[str, Any] = {}
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.mysensors.device.Debouncer", autospec=True
) as debouncer_class:
def debouncer(
*args: Any, function: Callable | None = None, **kwargs: Any
) -> MagicMock:
"""Mock the debouncer."""
async def call_debouncer():
"""Mock call to debouncer."""
if function is not None:
function()
debounce_instance = MagicMock()
debounce_instance.async_call.side_effect = call_debouncer
return debounce_instance
debouncer_class.side_effect = debouncer
with patch("homeassistant.components.mysensors.device.UPDATE_DELAY", new=0):
await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield config_entry

View File

@ -27,9 +27,6 @@ async def test_door_sensor(
assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.DOOR
receive_message("1;1;1;0;16;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -38,9 +35,6 @@ async def test_door_sensor(
assert state.state == "on"
receive_message("1;1;1;0;16;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -49,9 +49,6 @@ async def test_hvac_node_auto(
assert transport_write.call_args == call("1;1;1;1;21;AutoChangeOver\n")
receive_message("1;1;1;0;21;AutoChangeOver\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -83,9 +80,6 @@ async def test_hvac_node_auto(
receive_message("1;1;1;0;45;20.0\n")
receive_message("1;1;1;0;44;22.0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -113,9 +107,6 @@ async def test_hvac_node_auto(
assert transport_write.call_args == call("1;1;1;1;22;Max\n")
receive_message("1;1;1;0;22;Max\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -138,9 +129,6 @@ async def test_hvac_node_auto(
assert transport_write.call_args == call("1;1;1;1;21;Off\n")
receive_message("1;1;1;0;21;Off\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -175,9 +163,6 @@ async def test_hvac_node_heat(
assert transport_write.call_args == call("1;1;1;1;21;HeatOn\n")
receive_message("1;1;1;0;21;HeatOn\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -205,9 +190,6 @@ async def test_hvac_node_heat(
assert transport_write.call_args == call("1;1;1;1;45;20.0\n")
receive_message("1;1;1;0;45;20.0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -234,9 +216,6 @@ async def test_hvac_node_heat(
assert transport_write.call_args == call("1;1;1;1;22;Min\n")
receive_message("1;1;1;0;22;Min\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -259,9 +238,6 @@ async def test_hvac_node_heat(
assert transport_write.call_args == call("1;1;1;1;21;Off\n")
receive_message("1;1;1;0;21;Off\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -296,9 +272,6 @@ async def test_hvac_node_cool(
assert transport_write.call_args == call("1;1;1;1;21;CoolOn\n")
receive_message("1;1;1;0;21;CoolOn\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -326,9 +299,6 @@ async def test_hvac_node_cool(
assert transport_write.call_args == call("1;1;1;1;44;20.0\n")
receive_message("1;1;1;0;44;20.0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -355,9 +325,6 @@ async def test_hvac_node_cool(
assert transport_write.call_args == call("1;1;1;1;22;Auto\n")
receive_message("1;1;1;0;22;Auto\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -380,9 +347,6 @@ async def test_hvac_node_cool(
assert transport_write.call_args == call("1;1;1;1;21;Off\n")
receive_message("1;1;1;0;21;Off\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -50,9 +50,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;29;1\n")
receive_message("1;1;1;0;3;50\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -75,9 +72,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;31;1\n")
receive_message("1;1;1;0;3;50\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -101,9 +95,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;31;0\n")
receive_message("1;1;1;0;29;1\n")
receive_message("1;1;1;0;3;75\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -114,9 +105,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;29;0\n")
receive_message("1;1;1;0;3;100\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -139,9 +127,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;30;1\n")
receive_message("1;1;1;0;3;50\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -152,9 +137,6 @@ async def test_cover_node_percentage(
receive_message("1;1;1;0;30;0\n")
receive_message("1;1;1;0;3;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -176,9 +158,6 @@ async def test_cover_node_percentage(
assert transport_write.call_args == call("1;1;1;1;3;25\n")
receive_message("1;1;1;0;3;25\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -214,9 +193,6 @@ async def test_cover_node_binary(
receive_message("1;1;1;0;29;1\n")
receive_message("1;1;1;0;2;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -237,9 +213,6 @@ async def test_cover_node_binary(
assert transport_write.call_args == call("1;1;1;1;31;1\n")
receive_message("1;1;1;0;31;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -261,9 +234,6 @@ async def test_cover_node_binary(
receive_message("1;1;1;0;31;0\n")
receive_message("1;1;1;0;29;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -273,9 +243,6 @@ async def test_cover_node_binary(
receive_message("1;1;1;0;29;0\n")
receive_message("1;1;1;0;2;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -296,9 +263,6 @@ async def test_cover_node_binary(
assert transport_write.call_args == call("1;1;1;1;30;1\n")
receive_message("1;1;1;0;30;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -308,9 +272,6 @@ async def test_cover_node_binary(
receive_message("1;1;1;0;30;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -23,9 +23,6 @@ async def test_gps_sensor(
message_string = f"1;1;1;0;49;{latitude},{longitude},{altitude}\n"
receive_message(message_string)
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -41,9 +38,6 @@ async def test_gps_sensor(
message_string = f"1;1;1;0;49;{latitude},{longitude},{altitude}\n"
receive_message(message_string)
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -42,9 +42,6 @@ async def test_dimmer_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;100\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -68,9 +65,6 @@ async def test_dimmer_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;50\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -93,9 +87,6 @@ async def test_dimmer_node(
assert transport_write.call_args == call("1;1;1;1;2;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -132,9 +123,6 @@ async def test_rgb_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;100\n")
receive_message("1;1;1;0;40;ffffff\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -160,9 +148,6 @@ async def test_rgb_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;50\n")
receive_message("1;1;1;0;40;ffffff\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -186,9 +171,6 @@ async def test_rgb_node(
assert transport_write.call_args == call("1;1;1;1;2;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -213,9 +195,6 @@ async def test_rgb_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;50\n")
receive_message("1;1;1;0;40;ff0000\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -254,9 +233,6 @@ async def test_rgbw_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;100\n")
receive_message("1;1;1;0;41;ffffffff\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -282,9 +258,6 @@ async def test_rgbw_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;50\n")
receive_message("1;1;1;0;41;ffffffff\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -308,9 +281,6 @@ async def test_rgbw_node(
assert transport_write.call_args == call("1;1;1;1;2;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -335,9 +305,6 @@ async def test_rgbw_node(
receive_message("1;1;1;0;2;1\n")
receive_message("1;1;1;0;3;50\n")
receive_message("1;1;1;0;41;ff000000\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -48,9 +48,6 @@ async def test_gps_sensor(
message_string = f"1;1;1;0;49;{new_coords},{altitude}\n"
receive_message(message_string)
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -144,9 +141,6 @@ async def test_temperature_sensor(
message_string = f"1;1;1;0;0;{temperature}\n"
receive_message(message_string)
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)

View File

@ -36,9 +36,6 @@ async def test_relay_node(
assert transport_write.call_args == call("1;1;1;1;2;1\n")
receive_message("1;1;1;0;2;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -59,9 +56,6 @@ async def test_relay_node(
assert transport_write.call_args == call("1;1;1;1;2;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -96,9 +90,6 @@ async def test_ir_transceiver(
assert transport_write.call_args_list[1] == call("1;1;1;1;2;1\n")
receive_message("1;1;1;0;2;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -120,9 +111,6 @@ async def test_ir_transceiver(
assert transport_write.call_args == call("1;1;1;1;2;0\n")
receive_message("1;1;1;0;2;0\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)
@ -145,9 +133,6 @@ async def test_ir_transceiver(
receive_message("1;1;1;0;32;new_code\n")
receive_message("1;1;1;0;2;1\n")
# the integration adds multiple jobs to do the update currently
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
state = hass.states.get(entity_id)