From 05039036f1465106be8ae5db91716e58a40e01e7 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Wed, 21 Jun 2023 10:01:17 +0000 Subject: [PATCH] Add compatibility with sleeping Shelly gen2 devices with firmware 1.0.0 (#94864) --- homeassistant/components/shelly/__init__.py | 5 ++- .../components/shelly/config_flow.py | 7 +++- homeassistant/components/shelly/utils.py | 6 +++- tests/components/shelly/test_config_flow.py | 32 +++++++++++++++++++ tests/components/shelly/test_init.py | 18 ++++++++++- 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 7cb1f697765..69959453a78 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -44,6 +44,7 @@ from .utils import ( get_coap_context, get_device_entry_gen, get_rpc_device_sleep_period, + get_rpc_device_wakeup_period, get_ws_context, ) @@ -258,7 +259,9 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ConfigEntry) -> boo if sleep_period is None: data = {**entry.data} - data[CONF_SLEEP_PERIOD] = get_rpc_device_sleep_period(device.config) + data[CONF_SLEEP_PERIOD] = get_rpc_device_sleep_period( + device.config + ) or get_rpc_device_wakeup_period(device.status) hass.config_entries.async_update_entry(entry, data=data) hass.async_create_task(_async_rpc_device_setup()) diff --git a/homeassistant/components/shelly/config_flow.py b/homeassistant/components/shelly/config_flow.py index 43e9f9b8fe7..bad13fde006 100644 --- a/homeassistant/components/shelly/config_flow.py +++ b/homeassistant/components/shelly/config_flow.py @@ -39,6 +39,7 @@ from .utils import ( get_info_gen, get_model_name, get_rpc_device_sleep_period, + get_rpc_device_wakeup_period, get_ws_context, mac_address_from_name, ) @@ -76,9 +77,13 @@ async def validate_input( ) await rpc_device.shutdown() + sleep_period = get_rpc_device_sleep_period( + rpc_device.config + ) or get_rpc_device_wakeup_period(rpc_device.status) + return { "title": rpc_device.name, - CONF_SLEEP_PERIOD: get_rpc_device_sleep_period(rpc_device.config), + CONF_SLEEP_PERIOD: sleep_period, "model": rpc_device.shelly.get("model"), "gen": 2, } diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index c929e152b3f..03df3da346b 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -255,7 +255,11 @@ def get_block_device_sleep_period(settings: dict[str, Any]) -> int: def get_rpc_device_sleep_period(config: dict[str, Any]) -> int: - """Return the device sleep period in seconds or 0 for non sleeping devices.""" + """Return the device sleep period in seconds or 0 for non sleeping devices. + + sys.sleep.wakeup_period value is deprecated and not available in Shelly + firmware 1.0.0 or later. + """ return cast(int, config["sys"].get("sleep", {}).get("wakeup_period", 0)) diff --git a/tests/components/shelly/test_config_flow.py b/tests/components/shelly/test_config_flow.py index 621885bef08..7a29d7b1a42 100644 --- a/tests/components/shelly/test_config_flow.py +++ b/tests/components/shelly/test_config_flow.py @@ -1117,3 +1117,35 @@ async def test_zeroconf_sleeping_device_not_triggers_refresh( await hass.async_block_till_done() assert len(mock_rpc_device.initialize.mock_calls) == 0 assert "device did not update" not in caplog.text + + +async def test_sleeping_device_gen2_with_new_firmware( + hass: HomeAssistant, mock_rpc_device, monkeypatch +) -> None: + """Test sleeping device Gen2 with firmware 1.0.0 or later.""" + monkeypatch.setitem(mock_rpc_device.status["sys"], "wakeup_period", 666) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + assert result["type"] == "form" + assert result["errors"] == {} + + with patch( + "homeassistant.components.shelly.config_flow.get_info", + return_value={"mac": "test-mac", "gen": 2}, + ), patch("homeassistant.components.shelly.async_setup", return_value=True), patch( + "homeassistant.components.shelly.async_setup_entry", + return_value=True, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"host": "1.1.1.1"}, + ) + await hass.async_block_till_done() + + assert result["data"] == { + "host": "1.1.1.1", + "model": "SNSW-002P16EU", + "sleep_period": 666, + "gen": 2, + } diff --git a/tests/components/shelly/test_init.py b/tests/components/shelly/test_init.py index 42ec4578016..be6e319c8ac 100644 --- a/tests/components/shelly/test_init.py +++ b/tests/components/shelly/test_init.py @@ -17,7 +17,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, format_mac from homeassistant.setup import async_setup_component -from . import MOCK_MAC, init_integration +from . import MOCK_MAC, init_integration, mutate_rpc_device_status from tests.common import MockConfigEntry @@ -155,6 +155,22 @@ async def test_sleeping_rpc_device_online( assert entry.data["sleep_period"] == device_sleep +async def test_sleeping_rpc_device_online_new_firmware( + hass: HomeAssistant, + mock_rpc_device, + monkeypatch, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test sleeping device Gen2 with firmware 1.0.0 or later.""" + entry = await init_integration(hass, 2, sleep_period=None) + assert "will resume when device is online" in caplog.text + + mutate_rpc_device_status(monkeypatch, mock_rpc_device, "sys", "wakeup_period", 1500) + mock_rpc_device.mock_update() + assert "online, resuming setup" in caplog.text + assert entry.data["sleep_period"] == 1500 + + @pytest.mark.parametrize( ("gen", "entity_id"), [