From 35b733fa2c851983d701c0deebea206c03c70f3c Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 9 Dec 2023 16:12:05 +0100 Subject: [PATCH] Bump `aioshelly` to version 7.0.0 (#105384) * Remove get_rpc_device_sleep_period() function * Bump aioshelly version to 7.0.0 * Remove firmware compatibility check from BLE scanner * Remove firmware compatibility check from light transition * Update default fw ver * Use LightEntityFeature in tests --- homeassistant/components/shelly/__init__.py | 5 +- .../components/shelly/config_flow.py | 18 +----- homeassistant/components/shelly/const.py | 6 -- .../components/shelly/coordinator.py | 10 ---- homeassistant/components/shelly/light.py | 9 +-- homeassistant/components/shelly/manifest.json | 2 +- homeassistant/components/shelly/strings.json | 3 - homeassistant/components/shelly/utils.py | 9 --- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../shelly/bluetooth/test_scanner.py | 13 ----- tests/components/shelly/conftest.py | 30 ++-------- tests/components/shelly/test_config_flow.py | 56 ------------------- tests/components/shelly/test_light.py | 7 ++- 14 files changed, 18 insertions(+), 154 deletions(-) diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index b29fdcc6d19..553d32f8e48 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -49,7 +49,6 @@ from .utils import ( get_block_device_sleep_period, get_coap_context, get_device_entry_gen, - get_rpc_device_sleep_period, get_rpc_device_wakeup_period, get_ws_context, ) @@ -266,9 +265,7 @@ 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 - ) or get_rpc_device_wakeup_period(device.status) + data[CONF_SLEEP_PERIOD] = 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 6cde265bc25..98233d27b22 100644 --- a/homeassistant/components/shelly/config_flow.py +++ b/homeassistant/components/shelly/config_flow.py @@ -12,7 +12,6 @@ from aioshelly.exceptions import ( InvalidAuthError, ) from aioshelly.rpc_device import RpcDevice -from awesomeversion import AwesomeVersion import voluptuous as vol from homeassistant.components.zeroconf import ZeroconfServiceInfo @@ -24,7 +23,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.selector import SelectSelector, SelectSelectorConfig from .const import ( - BLE_MIN_VERSION, CONF_BLE_SCANNER_MODE, CONF_SLEEP_PERIOD, DOMAIN, @@ -32,14 +30,13 @@ from .const import ( MODEL_WALL_DISPLAY, BLEScannerMode, ) -from .coordinator import async_reconnect_soon, get_entry_data +from .coordinator import async_reconnect_soon from .utils import ( get_block_device_sleep_period, get_coap_context, get_info_auth, get_info_gen, get_model_name, - get_rpc_device_sleep_period, get_rpc_device_wakeup_period, get_ws_context, mac_address_from_name, @@ -78,9 +75,7 @@ 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) + sleep_period = get_rpc_device_wakeup_period(rpc_device.status) return { "title": rpc_device.name, @@ -383,15 +378,6 @@ class OptionsFlowHandler(OptionsFlow): ) -> FlowResult: """Handle options flow.""" if user_input is not None: - entry_data = get_entry_data(self.hass)[self.config_entry.entry_id] - if user_input[CONF_BLE_SCANNER_MODE] != BLEScannerMode.DISABLED and ( - not entry_data.rpc - or AwesomeVersion(entry_data.rpc.device.version) < BLE_MIN_VERSION - ): - return self.async_abort( - reason="ble_unsupported", - description_placeholders={"ble_min_version": BLE_MIN_VERSION}, - ) return self.async_create_entry(title="", data=user_input) return self.async_show_form( diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py index a90aba8db62..ca1c450c9fa 100644 --- a/homeassistant/components/shelly/const.py +++ b/homeassistant/components/shelly/const.py @@ -22,7 +22,6 @@ from aioshelly.const import ( MODEL_VINTAGE_V2, MODEL_WALL_DISPLAY, ) -from awesomeversion import AwesomeVersion DOMAIN: Final = "shelly" @@ -33,9 +32,6 @@ CONF_COAP_PORT: Final = "coap_port" DEFAULT_COAP_PORT: Final = 5683 FIRMWARE_PATTERN: Final = re.compile(r"^(\d{8})") -# Firmware 1.11.0 release date, this firmware supports light transition -LIGHT_TRANSITION_MIN_FIRMWARE_DATE: Final = 20210226 - # max light transition time in milliseconds MAX_TRANSITION_TIME: Final = 5000 @@ -187,8 +183,6 @@ ENTRY_RELOAD_COOLDOWN = 60 SHELLY_GAS_MODELS = [MODEL_GAS] -BLE_MIN_VERSION = AwesomeVersion("0.12.0-beta2") - CONF_BLE_SCANNER_MODE = "ble_scanner_mode" diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index d1f9d6943bf..a7659ecc392 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -13,7 +13,6 @@ from aioshelly.block_device import BlockDevice, BlockUpdateType from aioshelly.const import MODEL_VALVE from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError from aioshelly.rpc_device import RpcDevice, RpcUpdateType -from awesomeversion import AwesomeVersion from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import ATTR_DEVICE_ID, CONF_HOST, EVENT_HOMEASSISTANT_STOP @@ -33,7 +32,6 @@ from .const import ( ATTR_DEVICE, ATTR_GENERATION, BATTERY_DEVICES_WITH_PERMANENT_CONNECTION, - BLE_MIN_VERSION, CONF_BLE_SCANNER_MODE, CONF_SLEEP_PERIOD, DATA_CONFIG_ENTRY, @@ -587,14 +585,6 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): if ble_scanner_mode == BLEScannerMode.DISABLED and self.connected: await async_stop_scanner(self.device) return - if AwesomeVersion(self.device.version) < BLE_MIN_VERSION: - LOGGER.error( - "BLE not supported on device %s with firmware %s; upgrade to %s", - self.name, - self.device.version, - BLE_MIN_VERSION, - ) - return if await async_ensure_ble_enabled(self.device): # BLE enable required a reboot, don't bother connecting # the scanner since it will be disconnected anyway diff --git a/homeassistant/components/shelly/light.py b/homeassistant/components/shelly/light.py index 829a60b3a9e..2dfc5b497b1 100644 --- a/homeassistant/components/shelly/light.py +++ b/homeassistant/components/shelly/light.py @@ -24,11 +24,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import ( DUAL_MODE_LIGHT_MODELS, - FIRMWARE_PATTERN, KELVIN_MAX_VALUE, KELVIN_MIN_VALUE_COLOR, KELVIN_MIN_VALUE_WHITE, - LIGHT_TRANSITION_MIN_FIRMWARE_DATE, LOGGER, MAX_TRANSITION_TIME, MODELS_SUPPORTING_LIGHT_TRANSITION, @@ -155,12 +153,7 @@ class BlockShellyLight(ShellyBlockEntity, LightEntity): self._attr_supported_features |= LightEntityFeature.EFFECT if coordinator.model in MODELS_SUPPORTING_LIGHT_TRANSITION: - match = FIRMWARE_PATTERN.search(coordinator.device.settings.get("fw", "")) - if ( - match is not None - and int(match[0]) >= LIGHT_TRANSITION_MIN_FIRMWARE_DATE - ): - self._attr_supported_features |= LightEntityFeature.TRANSITION + self._attr_supported_features |= LightEntityFeature.TRANSITION @property def is_on(self) -> bool: diff --git a/homeassistant/components/shelly/manifest.json b/homeassistant/components/shelly/manifest.json index b8185712d31..b56ce07bc30 100644 --- a/homeassistant/components/shelly/manifest.json +++ b/homeassistant/components/shelly/manifest.json @@ -9,7 +9,7 @@ "iot_class": "local_push", "loggers": ["aioshelly"], "quality_scale": "platinum", - "requirements": ["aioshelly==6.1.0"], + "requirements": ["aioshelly==7.0.0"], "zeroconf": [ { "type": "_http._tcp.local.", diff --git a/homeassistant/components/shelly/strings.json b/homeassistant/components/shelly/strings.json index 9230ae605e0..330dd246c47 100644 --- a/homeassistant/components/shelly/strings.json +++ b/homeassistant/components/shelly/strings.json @@ -71,9 +71,6 @@ "ble_scanner_mode": "Bluetooth scanner mode" } } - }, - "abort": { - "ble_unsupported": "Bluetooth support requires firmware version {ble_min_version} or newer." } }, "selector": { diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index 6b5c59f28db..b53e3153a09 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -267,15 +267,6 @@ def get_block_device_sleep_period(settings: dict[str, Any]) -> int: return sleep_period * 60 # minutes to seconds -def get_rpc_device_sleep_period(config: dict[str, Any]) -> int: - """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)) - - def get_rpc_device_wakeup_period(status: dict[str, Any]) -> int: """Return the device wakeup period in seconds or 0 for non sleeping devices.""" return cast(int, status["sys"].get("wakeup_period", 0)) diff --git a/requirements_all.txt b/requirements_all.txt index 5e3e6a1224a..1dccc1a5551 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -356,7 +356,7 @@ aioruuvigateway==0.1.0 aiosenz==1.0.0 # homeassistant.components.shelly -aioshelly==6.1.0 +aioshelly==7.0.0 # homeassistant.components.skybell aioskybell==22.7.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 956d7079981..57ec5a22df9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -329,7 +329,7 @@ aioruuvigateway==0.1.0 aiosenz==1.0.0 # homeassistant.components.shelly -aioshelly==6.1.0 +aioshelly==7.0.0 # homeassistant.components.skybell aioskybell==22.7.0 diff --git a/tests/components/shelly/bluetooth/test_scanner.py b/tests/components/shelly/bluetooth/test_scanner.py index bd44782f928..9fe5f77f00c 100644 --- a/tests/components/shelly/bluetooth/test_scanner.py +++ b/tests/components/shelly/bluetooth/test_scanner.py @@ -108,19 +108,6 @@ async def test_scanner_ignores_wrong_version_and_logs( assert "Unsupported BLE scan result version: 0" in caplog.text -async def test_scanner_minimum_firmware_log_error( - hass: HomeAssistant, mock_rpc_device, monkeypatch, caplog: pytest.LogCaptureFixture -) -> None: - """Test scanner log error if device firmware incompatible.""" - monkeypatch.setattr(mock_rpc_device, "version", "0.11.0") - await init_integration( - hass, 2, options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE} - ) - assert mock_rpc_device.initialized is True - - assert "BLE not supported on device" in caplog.text - - async def test_scanner_warns_on_corrupt_event( hass: HomeAssistant, mock_rpc_device, monkeypatch, caplog: pytest.LogCaptureFixture ) -> None: diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py index 6eb74e26dcb..8a863a852f5 100644 --- a/tests/components/shelly/conftest.py +++ b/tests/components/shelly/conftest.py @@ -157,14 +157,13 @@ MOCK_CONFIG = { "sys": { "ui_data": {}, "device": {"name": "Test name"}, - "wakeup_period": 0, }, } MOCK_SHELLY_COAP = { "mac": MOCK_MAC, "auth": False, - "fw": "20201124-092854/v1.9.0@57ac4ad8", + "fw": "20210715-092854/v1.11.0@57ac4ad8", "num_outputs": 2, } @@ -174,8 +173,8 @@ MOCK_SHELLY_RPC = { "mac": MOCK_MAC, "model": MODEL_PLUS_2PM, "gen": 2, - "fw_id": "20220830-130540/0.11.0-gfa1bc37", - "ver": "0.11.0", + "fw_id": "20230803-130540/1.0.0-gfa1bc37", + "ver": "1.0.0", "app": "Plus2PM", "auth_en": False, "auth_domain": None, @@ -290,7 +289,7 @@ async def mock_block_device(): blocks=MOCK_BLOCKS, settings=MOCK_SETTINGS, shelly=MOCK_SHELLY_COAP, - version="0.10.0", + version="1.11.0", status=MOCK_STATUS_COAP, firmware_version="some fw string", initialized=True, @@ -314,7 +313,7 @@ def _mock_rpc_device(version: str | None = None): config=MOCK_CONFIG, event={}, shelly=MOCK_SHELLY_RPC, - version=version or "0.12.0", + version=version or "1.0.0", hostname="test-host", status=MOCK_STATUS_RPC, firmware_version="some fw string", @@ -324,23 +323,6 @@ def _mock_rpc_device(version: str | None = None): return device -@pytest.fixture -async def mock_pre_ble_rpc_device(): - """Mock rpc (Gen2, Websocket) device pre BLE.""" - with patch("aioshelly.rpc_device.RpcDevice.create") as rpc_device_mock: - - def update(): - rpc_device_mock.return_value.subscribe_updates.call_args[0][0]( - {}, RpcUpdateType.STATUS - ) - - device = _mock_rpc_device("0.11.0") - rpc_device_mock.return_value = device - rpc_device_mock.return_value.mock_update = Mock(side_effect=update) - - yield rpc_device_mock.return_value - - @pytest.fixture async def mock_rpc_device(): """Mock rpc (Gen2, Websocket) device with BLE support.""" @@ -363,7 +345,7 @@ async def mock_rpc_device(): {}, RpcUpdateType.DISCONNECTED ) - device = _mock_rpc_device("0.12.0") + device = _mock_rpc_device() rpc_device_mock.return_value = device rpc_device_mock.return_value.mock_disconnected = Mock(side_effect=disconnected) rpc_device_mock.return_value.mock_update = Mock(side_effect=update) diff --git a/tests/components/shelly/test_config_flow.py b/tests/components/shelly/test_config_flow.py index 9482080a1a3..c7ac472ada4 100644 --- a/tests/components/shelly/test_config_flow.py +++ b/tests/components/shelly/test_config_flow.py @@ -967,62 +967,6 @@ async def test_options_flow_ble(hass: HomeAssistant, mock_rpc_device) -> None: await hass.config_entries.async_unload(entry.entry_id) -async def test_options_flow_pre_ble_device( - hass: HomeAssistant, mock_pre_ble_rpc_device -) -> None: - """Test setting ble options for gen2 devices with pre ble firmware.""" - entry = await init_integration(hass, 2) - result = await hass.config_entries.options.async_init(entry.entry_id) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"] is None - - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={ - CONF_BLE_SCANNER_MODE: BLEScannerMode.DISABLED, - }, - ) - await hass.async_block_till_done() - - assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY - assert result["data"][CONF_BLE_SCANNER_MODE] == BLEScannerMode.DISABLED - - result = await hass.config_entries.options.async_init(entry.entry_id) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"] is None - - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={ - CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE, - }, - ) - await hass.async_block_till_done() - - assert result["type"] == data_entry_flow.FlowResultType.ABORT - assert result["reason"] == "ble_unsupported" - - result = await hass.config_entries.options.async_init(entry.entry_id) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"] is None - - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={ - CONF_BLE_SCANNER_MODE: BLEScannerMode.PASSIVE, - }, - ) - await hass.async_block_till_done() - - assert result["type"] == data_entry_flow.FlowResultType.ABORT - assert result["reason"] == "ble_unsupported" - - await hass.config_entries.async_unload(entry.entry_id) - - async def test_zeroconf_already_configured_triggers_refresh_mac_in_name( hass: HomeAssistant, mock_rpc_device, monkeypatch ) -> None: diff --git a/tests/components/shelly/test_light.py b/tests/components/shelly/test_light.py index e3aea966230..77b65ad3bb5 100644 --- a/tests/components/shelly/test_light.py +++ b/tests/components/shelly/test_light.py @@ -134,7 +134,10 @@ async def test_block_device_rgb_bulb( ColorMode.COLOR_TEMP, ColorMode.RGB, ] - assert attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.EFFECT + assert ( + attributes[ATTR_SUPPORTED_FEATURES] + == LightEntityFeature.EFFECT | LightEntityFeature.TRANSITION + ) assert len(attributes[ATTR_EFFECT_LIST]) == 4 assert attributes[ATTR_EFFECT] == "Off" @@ -232,7 +235,7 @@ async def test_block_device_white_bulb( assert state.state == STATE_ON assert attributes[ATTR_BRIGHTNESS] == 128 assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS] - assert attributes[ATTR_SUPPORTED_FEATURES] == 0 + assert attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION # Turn off mock_block_device.blocks[LIGHT_BLOCK_ID].set_state.reset_mock()