From ef8d394c16eb7c63422e7ec78fc3373e42b135a1 Mon Sep 17 00:00:00 2001 From: Simone Chemelli Date: Sat, 13 Jan 2024 22:33:02 +0100 Subject: [PATCH] Update sleep period for Shelly devices with buggy fw (#107961) * update sleep period for Shelly devices with buggy fw * code quality * update model list * add test * Apply review comments * fix test * use costant --- homeassistant/components/shelly/__init__.py | 19 +++++++++++++++++++ homeassistant/components/shelly/const.py | 13 +++++++++++++ tests/components/shelly/test_init.py | 18 ++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 6b7a00db8e2..6b8d100ea8f 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -30,12 +30,15 @@ from homeassistant.helpers.device_registry import ( from homeassistant.helpers.typing import ConfigType from .const import ( + BLOCK_EXPECTED_SLEEP_PERIOD, + BLOCK_WRONG_SLEEP_PERIOD, CONF_COAP_PORT, CONF_SLEEP_PERIOD, DATA_CONFIG_ENTRY, DEFAULT_COAP_PORT, DOMAIN, LOGGER, + MODELS_WITH_WRONG_SLEEP_PERIOD, PUSH_UPDATE_ISSUE_ID, ) from .coordinator import ( @@ -162,6 +165,22 @@ async def _async_setup_block_entry(hass: HomeAssistant, entry: ConfigEntry) -> b sleep_period = entry.data.get(CONF_SLEEP_PERIOD) shelly_entry_data = get_entry_data(hass)[entry.entry_id] + # Some old firmware have a wrong sleep period hardcoded value. + # Following code block will force the right value for affected devices + if ( + sleep_period == BLOCK_WRONG_SLEEP_PERIOD + and entry.data["model"] in MODELS_WITH_WRONG_SLEEP_PERIOD + ): + LOGGER.warning( + "Updating stored sleep period for %s: from %s to %s", + entry.title, + sleep_period, + BLOCK_EXPECTED_SLEEP_PERIOD, + ) + data = {**entry.data} + data[CONF_SLEEP_PERIOD] = sleep_period = BLOCK_EXPECTED_SLEEP_PERIOD + hass.config_entries.async_update_entry(entry, data=data) + async def _async_block_device_setup() -> None: """Set up a block based device that is online.""" shelly_entry_data.block = ShellyBlockCoordinator(hass, entry, device) diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py index 1e2c22691fb..6cc513015d3 100644 --- a/homeassistant/components/shelly/const.py +++ b/homeassistant/components/shelly/const.py @@ -14,7 +14,10 @@ from aioshelly.const import ( MODEL_DIMMER, MODEL_DIMMER_2, MODEL_DUO, + MODEL_DW, + MODEL_DW_2, MODEL_GAS, + MODEL_HT, MODEL_MOTION, MODEL_MOTION_2, MODEL_RGBW2, @@ -55,6 +58,12 @@ MODELS_SUPPORTING_LIGHT_EFFECTS: Final = ( MODEL_RGBW2, ) +MODELS_WITH_WRONG_SLEEP_PERIOD: Final = ( + MODEL_DW, + MODEL_DW_2, + MODEL_HT, +) + # Bulbs that support white & color modes DUAL_MODE_LIGHT_MODELS: Final = ( MODEL_BULB, @@ -176,6 +185,10 @@ KELVIN_MAX_VALUE: Final = 6500 KELVIN_MIN_VALUE_WHITE: Final = 2700 KELVIN_MIN_VALUE_COLOR: Final = 3000 +# Sleep period +BLOCK_WRONG_SLEEP_PERIOD = 21600 +BLOCK_EXPECTED_SLEEP_PERIOD = 43200 + UPTIME_DEVIATION: Final = 5 # Time to wait before reloading entry upon device config change diff --git a/tests/components/shelly/test_init.py b/tests/components/shelly/test_init.py index 643fc775cc4..bc0ba045a55 100644 --- a/tests/components/shelly/test_init.py +++ b/tests/components/shelly/test_init.py @@ -11,8 +11,12 @@ from aioshelly.exceptions import ( import pytest from homeassistant.components.shelly.const import ( + BLOCK_EXPECTED_SLEEP_PERIOD, + BLOCK_WRONG_SLEEP_PERIOD, CONF_BLE_SCANNER_MODE, + CONF_SLEEP_PERIOD, DOMAIN, + MODELS_WITH_WRONG_SLEEP_PERIOD, BLEScannerMode, ) from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState @@ -309,3 +313,17 @@ async def test_entry_missing_gen(hass: HomeAssistant, mock_block_device) -> None assert entry.state is ConfigEntryState.LOADED assert hass.states.get("switch.test_name_channel_1").state is STATE_ON + + +@pytest.mark.parametrize(("model"), MODELS_WITH_WRONG_SLEEP_PERIOD) +async def test_sleeping_block_device_wrong_sleep_period( + hass: HomeAssistant, mock_block_device, model +) -> None: + """Test sleeping block device with wrong sleep period.""" + entry = await init_integration( + hass, 1, model=model, sleep_period=BLOCK_WRONG_SLEEP_PERIOD, skip_setup=True + ) + assert entry.data[CONF_SLEEP_PERIOD] == BLOCK_WRONG_SLEEP_PERIOD + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + assert entry.data[CONF_SLEEP_PERIOD] == BLOCK_EXPECTED_SLEEP_PERIOD