diff --git a/homeassistant/components/zha/core/cluster_handlers/__init__.py b/homeassistant/components/zha/core/cluster_handlers/__init__.py index 7863b043455..ec29e4e53eb 100644 --- a/homeassistant/components/zha/core/cluster_handlers/__init__.py +++ b/homeassistant/components/zha/core/cluster_handlers/__init__.py @@ -45,6 +45,8 @@ if TYPE_CHECKING: _LOGGER = logging.getLogger(__name__) +DEFAULT_REQUEST_RETRIES = 3 + class AttrReportConfig(TypedDict, total=True): """Configuration to report for the attributes.""" @@ -78,6 +80,8 @@ def decorate_command(cluster_handler, command): @wraps(command) async def wrapper(*args, **kwds): + kwds.setdefault("tries", DEFAULT_REQUEST_RETRIES) + try: result = await command(*args, **kwds) cluster_handler.debug( diff --git a/tests/components/zha/test_alarm_control_panel.py b/tests/components/zha/test_alarm_control_panel.py index 319301cf7dc..34ce746e128 100644 --- a/tests/components/zha/test_alarm_control_panel.py +++ b/tests/components/zha/test_alarm_control_panel.py @@ -96,6 +96,7 @@ async def test_alarm_control_panel( 0, security.IasAce.AudibleNotification.Default_Sound, security.IasAce.AlarmStatus.No_Alarm, + tries=3, ) # disarm from HA @@ -134,6 +135,7 @@ async def test_alarm_control_panel( 0, security.IasAce.AudibleNotification.Default_Sound, security.IasAce.AlarmStatus.Emergency, + tries=3, ) # reset the panel @@ -157,6 +159,7 @@ async def test_alarm_control_panel( 0, security.IasAce.AudibleNotification.Default_Sound, security.IasAce.AlarmStatus.No_Alarm, + tries=3, ) # arm_night from HA @@ -177,6 +180,7 @@ async def test_alarm_control_panel( 0, security.IasAce.AudibleNotification.Default_Sound, security.IasAce.AlarmStatus.No_Alarm, + tries=3, ) # reset the panel @@ -274,5 +278,6 @@ async def reset_alarm_panel(hass, cluster, entity_id): 0, security.IasAce.AudibleNotification.Default_Sound, security.IasAce.AlarmStatus.No_Alarm, + tries=3, ) cluster.client_command.reset_mock() diff --git a/tests/components/zha/test_device_action.py b/tests/components/zha/test_device_action.py index f1ab44f69eb..9d9a4bc2a54 100644 --- a/tests/components/zha/test_device_action.py +++ b/tests/components/zha/test_device_action.py @@ -328,7 +328,7 @@ async def test_action(hass: HomeAssistant, device_ias, device_inovelli) -> None: 5, expect_reply=False, manufacturer=4151, - tries=1, + tries=3, tsn=None, ) in cluster.request.call_args_list @@ -345,7 +345,7 @@ async def test_action(hass: HomeAssistant, device_ias, device_inovelli) -> None: 5, expect_reply=False, manufacturer=4151, - tries=1, + tries=3, tsn=None, ) in cluster.request.call_args_list diff --git a/tests/components/zha/test_discover.py b/tests/components/zha/test_discover.py index 236a3c4ad86..a87d624ec00 100644 --- a/tests/components/zha/test_discover.py +++ b/tests/components/zha/test_discover.py @@ -131,7 +131,7 @@ async def test_devices( ), expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) ] diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py index c4751f7e7f6..5ea71573a27 100644 --- a/tests/components/zha/test_light.py +++ b/tests/components/zha/test_light.py @@ -553,7 +553,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -589,7 +589,7 @@ async def test_transitions( transition_time=35, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -600,7 +600,7 @@ async def test_transitions( transition_time=35, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -637,7 +637,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -674,7 +674,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -685,7 +685,7 @@ async def test_transitions( transition_time=0, # no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_level.request.call_args_list[1] == call( @@ -696,7 +696,7 @@ async def test_transitions( transition_time=10, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -758,7 +758,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -769,7 +769,7 @@ async def test_transitions( transition_time=0, # no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_level.request.call_args_list[1] == call( @@ -780,7 +780,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -838,7 +838,7 @@ async def test_transitions( dev1_cluster_on_off.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -850,7 +850,7 @@ async def test_transitions( transition_time=0, # no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -910,7 +910,7 @@ async def test_transitions( transition_time=1, # transition time - sengled light uses default minimum expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -968,7 +968,7 @@ async def test_transitions( transition_time=1, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev2_cluster_color.request.call_args == call( @@ -979,7 +979,7 @@ async def test_transitions( transition_time=1, # sengled transition == 1 when new_color_provided_while_off expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev2_cluster_level.request.call_args_list[1] == call( @@ -990,7 +990,7 @@ async def test_transitions( transition_time=10, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1121,7 +1121,7 @@ async def test_transitions( transition_time=20, # transition time expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1151,7 +1151,7 @@ async def test_transitions( transition_time=1, # transition time - sengled light uses default minimum expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1184,7 +1184,7 @@ async def test_transitions( eWeLink_cluster_on_off.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -1195,7 +1195,7 @@ async def test_transitions( transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1261,7 +1261,7 @@ async def test_on_with_off_color(hass: HomeAssistant, device_light_1) -> None: dev1_cluster_on_off.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -1272,7 +1272,7 @@ async def test_on_with_off_color(hass: HomeAssistant, device_light_1) -> None: transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1319,7 +1319,7 @@ async def test_on_with_off_color(hass: HomeAssistant, device_light_1) -> None: transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_color.request.call_args == call( @@ -1330,7 +1330,7 @@ async def test_on_with_off_color(hass: HomeAssistant, device_light_1) -> None: transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) assert dev1_cluster_level.request.call_args_list[1] == call( @@ -1341,7 +1341,7 @@ async def test_on_with_off_color(hass: HomeAssistant, device_light_1) -> None: transition_time=0, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -1373,7 +1373,9 @@ async def async_test_on_from_light(hass, cluster, entity_id): assert hass.states.get(entity_id).state == STATE_ON -async def async_test_on_off_from_hass(hass, cluster, entity_id): +async def async_test_on_off_from_hass( + hass, cluster, entity_id, expected_tries: int = 3 +): """Test on off functionality from hass.""" # turn on via UI cluster.request.reset_mock() @@ -1388,14 +1390,16 @@ async def async_test_on_off_from_hass(hass, cluster, entity_id): cluster.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) - await async_test_off_from_hass(hass, cluster, entity_id) + await async_test_off_from_hass( + hass, cluster, entity_id, expected_tries=expected_tries + ) -async def async_test_off_from_hass(hass, cluster, entity_id): +async def async_test_off_from_hass(hass, cluster, entity_id, expected_tries: int = 3): """Test turning off the light from Home Assistant.""" # turn off via UI @@ -1411,13 +1415,18 @@ async def async_test_off_from_hass(hass, cluster, entity_id): cluster.commands_by_name["off"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) async def async_test_level_on_off_from_hass( - hass, on_off_cluster, level_cluster, entity_id, expected_default_transition: int = 0 + hass, + on_off_cluster, + level_cluster, + entity_id, + expected_default_transition: int = 0, + expected_tries: int = 3, ): """Test on off functionality from hass.""" @@ -1439,7 +1448,7 @@ async def async_test_level_on_off_from_hass( on_off_cluster.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) on_off_cluster.request.reset_mock() @@ -1463,7 +1472,7 @@ async def async_test_level_on_off_from_hass( on_off_cluster.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) assert level_cluster.request.call_args == call( @@ -1474,7 +1483,7 @@ async def async_test_level_on_off_from_hass( transition_time=100, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) on_off_cluster.request.reset_mock() @@ -1499,13 +1508,15 @@ async def async_test_level_on_off_from_hass( transition_time=int(expected_default_transition), expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) on_off_cluster.request.reset_mock() level_cluster.request.reset_mock() - await async_test_off_from_hass(hass, on_off_cluster, entity_id) + await async_test_off_from_hass( + hass, on_off_cluster, entity_id, expected_tries=expected_tries + ) async def async_test_dimmer_from_light(hass, cluster, entity_id, level, expected_state): @@ -1522,7 +1533,9 @@ async def async_test_dimmer_from_light(hass, cluster, entity_id, level, expected assert hass.states.get(entity_id).attributes.get("brightness") == level -async def async_test_flash_from_hass(hass, cluster, entity_id, flash): +async def async_test_flash_from_hass( + hass, cluster, entity_id, flash, expected_tries: int = 3 +): """Test flash functionality from hass.""" # turn on via UI cluster.request.reset_mock() @@ -1542,7 +1555,7 @@ async def async_test_flash_from_hass(hass, cluster, entity_id, flash): effect_variant=general.Identify.EffectVariant.Default, expect_reply=True, manufacturer=None, - tries=1, + tries=expected_tries, tsn=None, ) @@ -1642,13 +1655,15 @@ async def test_zha_group_light_entity( assert "color_mode" not in group_state.attributes # test turning the lights on and off from the HA - await async_test_on_off_from_hass(hass, group_cluster_on_off, group_entity_id) + await async_test_on_off_from_hass( + hass, group_cluster_on_off, group_entity_id, expected_tries=1 + ) await async_shift_time(hass) # test short flashing the lights from the HA await async_test_flash_from_hass( - hass, group_cluster_identify, group_entity_id, FLASH_SHORT + hass, group_cluster_identify, group_entity_id, FLASH_SHORT, expected_tries=1 ) await async_shift_time(hass) @@ -1663,6 +1678,7 @@ async def test_zha_group_light_entity( group_cluster_level, group_entity_id, expected_default_transition=1, # a Sengled light is in that group and needs a minimum 0.1s transition + expected_tries=1, ) await async_shift_time(hass) @@ -1683,7 +1699,7 @@ async def test_zha_group_light_entity( # test long flashing the lights from the HA await async_test_flash_from_hass( - hass, group_cluster_identify, group_entity_id, FLASH_LONG + hass, group_cluster_identify, group_entity_id, FLASH_LONG, expected_tries=1 ) await async_shift_time(hass) diff --git a/tests/components/zha/test_switch.py b/tests/components/zha/test_switch.py index 9f98acb9359..8fb7825a953 100644 --- a/tests/components/zha/test_switch.py +++ b/tests/components/zha/test_switch.py @@ -176,7 +176,7 @@ async def test_switch( cluster.commands_by_name["on"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, ) @@ -196,7 +196,7 @@ async def test_switch( cluster.commands_by_name["off"].schema, expect_reply=True, manufacturer=None, - tries=1, + tries=3, tsn=None, )