From 2515dbeee1235be5c32f1df434777495f8e1cd3a Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Fri, 24 Nov 2023 19:55:00 +0100 Subject: [PATCH] Bump aioshelly to version 6.1.0 (#104456) * Bump aioshelly * Use MODEL_* consts from aioshelly * Add missing models to BATTERY_DEVICES_WITH_PERMANENT_CONNECTION --- homeassistant/components/shelly/const.py | 60 ++++++++++++------- .../components/shelly/coordinator.py | 3 +- homeassistant/components/shelly/event.py | 3 +- homeassistant/components/shelly/light.py | 7 ++- homeassistant/components/shelly/manifest.json | 2 +- homeassistant/components/shelly/switch.py | 5 +- homeassistant/components/shelly/utils.py | 21 +++++-- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/shelly/__init__.py | 3 +- tests/components/shelly/conftest.py | 7 ++- tests/components/shelly/test_binary_sensor.py | 5 +- tests/components/shelly/test_climate.py | 7 ++- tests/components/shelly/test_config_flow.py | 59 +++++++++--------- tests/components/shelly/test_coordinator.py | 5 +- .../components/shelly/test_device_trigger.py | 3 +- tests/components/shelly/test_diagnostics.py | 5 +- tests/components/shelly/test_event.py | 3 +- tests/components/shelly/test_light.py | 27 ++++++--- tests/components/shelly/test_switch.py | 3 +- tests/components/shelly/test_utils.py | 40 ++++++++----- 21 files changed, 166 insertions(+), 106 deletions(-) diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py index db7623f684e..a90aba8db62 100644 --- a/homeassistant/components/shelly/const.py +++ b/homeassistant/components/shelly/const.py @@ -6,6 +6,22 @@ from logging import Logger, getLogger import re from typing import Final +from aioshelly.const import ( + MODEL_BULB, + MODEL_BULB_RGBW, + MODEL_BUTTON1, + MODEL_BUTTON1_V2, + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_DUO, + MODEL_GAS, + MODEL_MOTION, + MODEL_MOTION_2, + MODEL_RGBW2, + MODEL_VALVE, + MODEL_VINTAGE_V2, + MODEL_WALL_DISPLAY, +) from awesomeversion import AwesomeVersion DOMAIN: Final = "shelly" @@ -24,29 +40,29 @@ LIGHT_TRANSITION_MIN_FIRMWARE_DATE: Final = 20210226 MAX_TRANSITION_TIME: Final = 5000 RGBW_MODELS: Final = ( - "SHBLB-1", - "SHRGBW2", + MODEL_BULB, + MODEL_RGBW2, ) MODELS_SUPPORTING_LIGHT_TRANSITION: Final = ( - "SHBDUO-1", - "SHCB-1", - "SHDM-1", - "SHDM-2", - "SHRGBW2", - "SHVIN-1", + MODEL_DUO, + MODEL_BULB_RGBW, + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_RGBW2, + MODEL_VINTAGE_V2, ) MODELS_SUPPORTING_LIGHT_EFFECTS: Final = ( - "SHBLB-1", - "SHCB-1", - "SHRGBW2", + MODEL_BULB, + MODEL_BULB_RGBW, + MODEL_RGBW2, ) # Bulbs that support white & color modes DUAL_MODE_LIGHT_MODELS: Final = ( - "SHBLB-1", - "SHCB-1", + MODEL_BULB, + MODEL_BULB_RGBW, ) # Refresh interval for REST sensors @@ -79,7 +95,11 @@ INPUTS_EVENTS_DICT: Final = { } # List of battery devices that maintain a permanent WiFi connection -BATTERY_DEVICES_WITH_PERMANENT_CONNECTION: Final = ["SHMOS-01"] +BATTERY_DEVICES_WITH_PERMANENT_CONNECTION: Final = [ + MODEL_MOTION, + MODEL_MOTION_2, + MODEL_VALVE, +] # Button/Click events for Block & RPC devices EVENT_SHELLY_CLICK: Final = "shelly.click" @@ -124,7 +144,7 @@ INPUTS_EVENTS_SUBTYPES: Final = { "button4": 4, } -SHBTN_MODELS: Final = ["SHBTN-1", "SHBTN-2"] +SHBTN_MODELS: Final = [MODEL_BUTTON1, MODEL_BUTTON1_V2] STANDARD_RGB_EFFECTS: Final = { 0: "Off", @@ -165,7 +185,7 @@ UPTIME_DEVIATION: Final = 5 # Time to wait before reloading entry upon device config change ENTRY_RELOAD_COOLDOWN = 60 -SHELLY_GAS_MODELS = ["SHGS-1"] +SHELLY_GAS_MODELS = [MODEL_GAS] BLE_MIN_VERSION = AwesomeVersion("0.12.0-beta2") @@ -192,13 +212,11 @@ OTA_ERROR = "ota_error" OTA_PROGRESS = "ota_progress" OTA_SUCCESS = "ota_success" -MODEL_WALL_DISPLAY = "SAWD-0A1XX10EU1" - GEN1_RELEASE_URL = "https://shelly-api-docs.shelly.cloud/gen1/#changelog" GEN2_RELEASE_URL = "https://shelly-api-docs.shelly.cloud/gen2/changelog/" DEVICES_WITHOUT_FIRMWARE_CHANGELOG = ( MODEL_WALL_DISPLAY, - "SHMOS-01", - "SHMOS-02", - "SHTRV-01", + MODEL_MOTION, + MODEL_MOTION_2, + MODEL_VALVE, ) diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index e648a80420a..b618656313d 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -10,6 +10,7 @@ from typing import Any, Generic, TypeVar, cast import aioshelly from aioshelly.ble import async_ensure_ble_enabled, async_stop_scanner 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 @@ -219,7 +220,7 @@ class ShellyBlockCoordinator(ShellyCoordinatorBase[BlockDevice]): # Shelly TRV sends information about changing the configuration for no # reason, reloading the config entry is not needed for it. - if self.model == "SHTRV-01": + if self.model == MODEL_VALVE: self._last_cfg_changed = None # For dual mode bulbs ignore change if it is due to mode/effect change diff --git a/homeassistant/components/shelly/event.py b/homeassistant/components/shelly/event.py index 1b5cf911e85..af323c82a24 100644 --- a/homeassistant/components/shelly/event.py +++ b/homeassistant/components/shelly/event.py @@ -6,6 +6,7 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Final from aioshelly.block_device import Block +from aioshelly.const import MODEL_I3 from homeassistant.components.event import ( DOMAIN as EVENT_DOMAIN, @@ -135,7 +136,7 @@ class ShellyBlockEvent(ShellyBlockEntity, EventEntity): self.channel = channel = int(block.channel or 0) + 1 self._attr_unique_id = f"{super().unique_id}-{channel}" - if coordinator.model == "SHIX3-1": + if coordinator.model == MODEL_I3: self._attr_event_types = list(SHIX3_1_INPUTS_EVENTS_TYPES) else: self._attr_event_types = list(BASIC_INPUTS_EVENTS_TYPES) diff --git a/homeassistant/components/shelly/light.py b/homeassistant/components/shelly/light.py index 1c3a85f2f5e..829a60b3a9e 100644 --- a/homeassistant/components/shelly/light.py +++ b/homeassistant/components/shelly/light.py @@ -4,6 +4,7 @@ from __future__ import annotations from typing import Any, cast from aioshelly.block_device import Block +from aioshelly.const import MODEL_BULB from homeassistant.components.light import ( ATTR_BRIGHTNESS, @@ -254,7 +255,7 @@ class BlockShellyLight(ShellyBlockEntity, LightEntity): @property def effect_list(self) -> list[str] | None: """Return the list of supported effects.""" - if self.coordinator.model == "SHBLB-1": + if self.coordinator.model == MODEL_BULB: return list(SHBLB_1_RGB_EFFECTS.values()) return list(STANDARD_RGB_EFFECTS.values()) @@ -267,7 +268,7 @@ class BlockShellyLight(ShellyBlockEntity, LightEntity): else: effect_index = self.block.effect - if self.coordinator.model == "SHBLB-1": + if self.coordinator.model == MODEL_BULB: return SHBLB_1_RGB_EFFECTS[effect_index] return STANDARD_RGB_EFFECTS[effect_index] @@ -326,7 +327,7 @@ class BlockShellyLight(ShellyBlockEntity, LightEntity): if ATTR_EFFECT in kwargs and ATTR_COLOR_TEMP_KELVIN not in kwargs: # Color effect change - used only in color mode, switch device mode to color set_mode = "color" - if self.coordinator.model == "SHBLB-1": + if self.coordinator.model == MODEL_BULB: effect_dict = SHBLB_1_RGB_EFFECTS else: effect_dict = STANDARD_RGB_EFFECTS diff --git a/homeassistant/components/shelly/manifest.json b/homeassistant/components/shelly/manifest.json index c76e2102fa1..b8185712d31 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.0.0"], + "requirements": ["aioshelly==6.1.0"], "zeroconf": [ { "type": "_http._tcp.local.", diff --git a/homeassistant/components/shelly/switch.py b/homeassistant/components/shelly/switch.py index 5610956e790..35429c858f5 100644 --- a/homeassistant/components/shelly/switch.py +++ b/homeassistant/components/shelly/switch.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from typing import Any, cast from aioshelly.block_device import Block +from aioshelly.const import MODEL_2, MODEL_25, MODEL_GAS from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.config_entries import ConfigEntry @@ -65,7 +66,7 @@ def async_setup_block_entry( assert coordinator # Add Shelly Gas Valve as a switch - if coordinator.model == "SHGS-1": + if coordinator.model == MODEL_GAS: async_setup_block_attribute_entities( hass, async_add_entities, @@ -77,7 +78,7 @@ def async_setup_block_entry( # In roller mode the relay blocks exist but do not contain required info if ( - coordinator.model in ["SHSW-21", "SHSW-25"] + coordinator.model in [MODEL_2, MODEL_25] and coordinator.device.settings["mode"] != "relay" ): return diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index eff21e71413..6b5c59f28db 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -6,7 +6,14 @@ from typing import Any, cast from aiohttp.web import Request, WebSocketResponse from aioshelly.block_device import COAP, Block, BlockDevice -from aioshelly.const import MODEL_NAMES +from aioshelly.const import ( + MODEL_1L, + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_EM3, + MODEL_I3, + MODEL_NAMES, +) from aioshelly.rpc_device import RpcDevice, WsServer from homeassistant.components.http import HomeAssistantView @@ -57,7 +64,11 @@ def get_number_of_channels(device: BlockDevice, block: Block) -> int: if block.type == "input": # Shelly Dimmer/1L has two input channels and missing "num_inputs" - if device.settings["device"]["type"] in ["SHDM-1", "SHDM-2", "SHSW-L"]: + if device.settings["device"]["type"] in [ + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_1L, + ]: channels = 2 else: channels = device.shelly.get("num_inputs") @@ -106,7 +117,7 @@ def get_block_channel_name(device: BlockDevice, block: Block | None) -> str: if channel_name: return channel_name - if device.settings["device"]["type"] == "SHEM-3": + if device.settings["device"]["type"] == MODEL_EM3: base = ord("A") else: base = ord("1") @@ -136,7 +147,7 @@ def is_block_momentary_input( return False # Shelly 1L has two button settings in the first channel - if settings["device"]["type"] == "SHSW-L": + if settings["device"]["type"] == MODEL_1L: channel = int(block.channel or 0) + 1 button_type = button[0].get("btn" + str(channel) + "_type") else: @@ -180,7 +191,7 @@ def get_block_input_triggers( if device.settings["device"]["type"] in SHBTN_MODELS: trigger_types = SHBTN_INPUTS_EVENTS_TYPES - elif device.settings["device"]["type"] == "SHIX3-1": + elif device.settings["device"]["type"] == MODEL_I3: trigger_types = SHIX3_1_INPUTS_EVENTS_TYPES else: trigger_types = BASIC_INPUTS_EVENTS_TYPES diff --git a/requirements_all.txt b/requirements_all.txt index d35ee88e994..5787e1a8554 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -353,7 +353,7 @@ aioruuvigateway==0.1.0 aiosenz==1.0.0 # homeassistant.components.shelly -aioshelly==6.0.0 +aioshelly==6.1.0 # homeassistant.components.skybell aioskybell==22.7.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2ad933fa42c..3e9c1a19c2f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -326,7 +326,7 @@ aioruuvigateway==0.1.0 aiosenz==1.0.0 # homeassistant.components.shelly -aioshelly==6.0.0 +aioshelly==6.1.0 # homeassistant.components.skybell aioskybell==22.7.0 diff --git a/tests/components/shelly/__init__.py b/tests/components/shelly/__init__.py index 464118ac99b..0384e9255a3 100644 --- a/tests/components/shelly/__init__.py +++ b/tests/components/shelly/__init__.py @@ -7,6 +7,7 @@ from datetime import timedelta from typing import Any from unittest.mock import Mock +from aioshelly.const import MODEL_25 from freezegun.api import FrozenDateTimeFactory import pytest @@ -30,7 +31,7 @@ MOCK_MAC = "123456789ABC" async def init_integration( hass: HomeAssistant, gen: int, - model="SHSW-25", + model=MODEL_25, sleep_period=0, options: dict[str, Any] | None = None, skip_setup: bool = False, diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py index 12d84200720..aeeaf9242a1 100644 --- a/tests/components/shelly/conftest.py +++ b/tests/components/shelly/conftest.py @@ -4,6 +4,7 @@ from __future__ import annotations from unittest.mock import AsyncMock, Mock, PropertyMock, patch from aioshelly.block_device import BlockDevice, BlockUpdateType +from aioshelly.const import MODEL_1, MODEL_25, MODEL_PLUS_2PM from aioshelly.rpc_device import RpcDevice, RpcUpdateType import pytest @@ -22,7 +23,7 @@ MOCK_SETTINGS = { "device": { "mac": MOCK_MAC, "hostname": "test-host", - "type": "SHSW-25", + "type": MODEL_25, "num_outputs": 2, }, "coiot": {"update_period": 15}, @@ -167,7 +168,7 @@ MOCK_SHELLY_RPC = { "name": "Test Gen2", "id": "shellyplus2pm-123456789abc", "mac": MOCK_MAC, - "model": "SNSW-002P16EU", + "model": MODEL_PLUS_2PM, "gen": 2, "fw_id": "20220830-130540/0.11.0-gfa1bc37", "ver": "0.11.0", @@ -289,7 +290,7 @@ async def mock_block_device(): status=MOCK_STATUS_COAP, firmware_version="some fw string", initialized=True, - model="SHSW-1", + model=MODEL_1, gen=1, ) type(device).name = PropertyMock(return_value="Test name") diff --git a/tests/components/shelly/test_binary_sensor.py b/tests/components/shelly/test_binary_sensor.py index 8905ff5c3e8..8a5e0108ad7 100644 --- a/tests/components/shelly/test_binary_sensor.py +++ b/tests/components/shelly/test_binary_sensor.py @@ -1,4 +1,5 @@ """Tests for Shelly binary sensor platform.""" +from aioshelly.const import MODEL_MOTION from freezegun.api import FrozenDateTimeFactory from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN @@ -77,9 +78,9 @@ async def test_block_rest_binary_sensor_connected_battery_devices( """Test block REST binary sensor for connected battery devices.""" entity_id = register_entity(hass, BINARY_SENSOR_DOMAIN, "test_name_cloud", "cloud") monkeypatch.setitem(mock_block_device.status, "cloud", {"connected": False}) - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHMOS-01") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_MOTION) monkeypatch.setitem(mock_block_device.settings["coiot"], "update_period", 3600) - await init_integration(hass, 1, model="SHMOS-01") + await init_integration(hass, 1, model=MODEL_MOTION) assert hass.states.get(entity_id).state == STATE_OFF diff --git a/tests/components/shelly/test_climate.py b/tests/components/shelly/test_climate.py index d1e37f77574..fe518b8509c 100644 --- a/tests/components/shelly/test_climate.py +++ b/tests/components/shelly/test_climate.py @@ -2,6 +2,7 @@ from copy import deepcopy from unittest.mock import AsyncMock, PropertyMock +from aioshelly.const import MODEL_VALVE from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError import pytest @@ -54,7 +55,7 @@ async def test_climate_hvac_mode( monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "valveError", 0) monkeypatch.delattr(mock_block_device.blocks[EMETER_BLOCK_ID], "targetTemp") monkeypatch.delattr(mock_block_device.blocks[GAS_VALVE_BLOCK_ID], "targetTemp") - await init_integration(hass, 1, sleep_period=1000, model="SHTRV-01") + await init_integration(hass, 1, sleep_period=1000, model=MODEL_VALVE) # Make device online mock_block_device.mock_update() @@ -155,7 +156,7 @@ async def test_climate_set_preset_mode( monkeypatch.delattr(mock_block_device.blocks[GAS_VALVE_BLOCK_ID], "targetTemp") monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "valveError", 0) monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "mode", None) - await init_integration(hass, 1, sleep_period=1000, model="SHTRV-01") + await init_integration(hass, 1, sleep_period=1000, model=MODEL_VALVE) # Make device online mock_block_device.mock_update() @@ -507,7 +508,7 @@ async def test_device_not_calibrated( """Test to create an issue when the device is not calibrated.""" issue_registry: ir.IssueRegistry = ir.async_get(hass) - await init_integration(hass, 1, sleep_period=1000, model="SHTRV-01") + await init_integration(hass, 1, sleep_period=1000, model=MODEL_VALVE) # Make device online mock_block_device.mock_update() diff --git a/tests/components/shelly/test_config_flow.py b/tests/components/shelly/test_config_flow.py index 073847e0308..9482080a1a3 100644 --- a/tests/components/shelly/test_config_flow.py +++ b/tests/components/shelly/test_config_flow.py @@ -5,6 +5,7 @@ from dataclasses import replace from ipaddress import ip_address from unittest.mock import AsyncMock, patch +from aioshelly.const import MODEL_1, MODEL_PLUS_2PM from aioshelly.exceptions import ( DeviceConnectionError, FirmwareUnsupported, @@ -52,8 +53,8 @@ DISCOVERY_INFO_WITH_MAC = zeroconf.ZeroconfServiceInfo( @pytest.mark.parametrize( ("gen", "model"), [ - (1, "SHSW-1"), - (2, "SNSW-002P16EU"), + (1, MODEL_1), + (2, MODEL_PLUS_2PM), ], ) async def test_form( @@ -68,7 +69,7 @@ async def test_form( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False, "gen": gen}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False, "gen": gen}, ), patch( "homeassistant.components.shelly.async_setup", return_value=True ) as mock_setup, patch( @@ -98,13 +99,13 @@ async def test_form( [ ( 1, - "SHSW-1", + MODEL_1, {"username": "test user", "password": "test1 password"}, "test user", ), ( 2, - "SNSW-002P16EU", + MODEL_PLUS_2PM, {"password": "test2 password"}, "admin", ), @@ -128,7 +129,7 @@ async def test_form_auth( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True, "gen": gen}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": True, "gen": gen}, ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -306,7 +307,7 @@ async def test_form_already_configured(hass: HomeAssistant) -> None: with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False}, ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -339,7 +340,7 @@ async def test_user_setup_ignored_device( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False}, ), patch( "homeassistant.components.shelly.async_setup", return_value=True ) as mock_setup, patch( @@ -456,13 +457,13 @@ async def test_form_auth_errors_test_connection_gen2( [ ( 1, - "SHSW-1", - {"mac": "test-mac", "type": "SHSW-1", "auth": False, "gen": 1}, + MODEL_1, + {"mac": "test-mac", "type": MODEL_1, "auth": False, "gen": 1}, ), ( 2, - "SNSW-002P16EU", - {"mac": "test-mac", "model": "SHSW-1", "auth": False, "gen": 2}, + MODEL_PLUS_2PM, + {"mac": "test-mac", "model": MODEL_PLUS_2PM, "auth": False, "gen": 2}, ), ], ) @@ -525,7 +526,7 @@ async def test_zeroconf_sleeping_device( "homeassistant.components.shelly.config_flow.get_info", return_value={ "mac": "test-mac", - "type": "SHSW-1", + "type": MODEL_1, "auth": False, "sleep_mode": True, }, @@ -559,7 +560,7 @@ async def test_zeroconf_sleeping_device( assert result2["title"] == "Test name" assert result2["data"] == { "host": "1.1.1.1", - "model": "SHSW-1", + "model": MODEL_1, "sleep_period": 600, "gen": 1, } @@ -573,7 +574,7 @@ async def test_zeroconf_sleeping_device_error(hass: HomeAssistant) -> None: "homeassistant.components.shelly.config_flow.get_info", return_value={ "mac": "test-mac", - "type": "SHSW-1", + "type": MODEL_1, "auth": False, "sleep_mode": True, }, @@ -600,7 +601,7 @@ async def test_zeroconf_already_configured(hass: HomeAssistant) -> None: with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -627,7 +628,7 @@ async def test_zeroconf_ignored(hass: HomeAssistant) -> None: with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -648,7 +649,7 @@ async def test_zeroconf_with_wifi_ap_ip(hass: HomeAssistant) -> None: with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -700,7 +701,7 @@ async def test_zeroconf_require_auth(hass: HomeAssistant, mock_block_device) -> with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": True}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -726,7 +727,7 @@ async def test_zeroconf_require_auth(hass: HomeAssistant, mock_block_device) -> assert result2["title"] == "Test name" assert result2["data"] == { "host": "1.1.1.1", - "model": "SHSW-1", + "model": MODEL_1, "sleep_period": 0, "gen": 1, "username": "test username", @@ -754,7 +755,7 @@ async def test_reauth_successful( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True, "gen": gen}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": True, "gen": gen}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -790,7 +791,7 @@ async def test_reauth_unsuccessful(hass: HomeAssistant, gen, user_input) -> None with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True, "gen": gen}, + return_value={"mac": "test-mac", "type": MODEL_1, "auth": True, "gen": gen}, ), patch( "aioshelly.block_device.BlockDevice.create", new=AsyncMock(side_effect=InvalidAuthError), @@ -1029,7 +1030,7 @@ async def test_zeroconf_already_configured_triggers_refresh_mac_in_name( entry = MockConfigEntry( domain="shelly", unique_id="AABBCCDDEEFF", - data={"host": "1.1.1.1", "gen": 2, "sleep_period": 0, "model": "SHSW-1"}, + data={"host": "1.1.1.1", "gen": 2, "sleep_period": 0, "model": MODEL_1}, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) @@ -1038,7 +1039,7 @@ async def test_zeroconf_already_configured_triggers_refresh_mac_in_name( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "", "type": "SHSW-1", "auth": False}, + return_value={"mac": "", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -1061,7 +1062,7 @@ async def test_zeroconf_already_configured_triggers_refresh( entry = MockConfigEntry( domain="shelly", unique_id="AABBCCDDEEFF", - data={"host": "1.1.1.1", "gen": 2, "sleep_period": 0, "model": "SHSW-1"}, + data={"host": "1.1.1.1", "gen": 2, "sleep_period": 0, "model": MODEL_1}, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) @@ -1070,7 +1071,7 @@ async def test_zeroconf_already_configured_triggers_refresh( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "AABBCCDDEEFF", "type": "SHSW-1", "auth": False}, + return_value={"mac": "AABBCCDDEEFF", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -1093,7 +1094,7 @@ async def test_zeroconf_sleeping_device_not_triggers_refresh( entry = MockConfigEntry( domain="shelly", unique_id="AABBCCDDEEFF", - data={"host": "1.1.1.1", "gen": 2, "sleep_period": 1000, "model": "SHSW-1"}, + data={"host": "1.1.1.1", "gen": 2, "sleep_period": 1000, "model": MODEL_1}, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) @@ -1105,7 +1106,7 @@ async def test_zeroconf_sleeping_device_not_triggers_refresh( with patch( "homeassistant.components.shelly.config_flow.get_info", - return_value={"mac": "AABBCCDDEEFF", "type": "SHSW-1", "auth": False}, + return_value={"mac": "AABBCCDDEEFF", "type": MODEL_1, "auth": False}, ): result = await hass.config_entries.flow.async_init( DOMAIN, @@ -1148,7 +1149,7 @@ async def test_sleeping_device_gen2_with_new_firmware( assert result["data"] == { "host": "1.1.1.1", - "model": "SNSW-002P16EU", + "model": MODEL_PLUS_2PM, "sleep_period": 666, "gen": 2, } diff --git a/tests/components/shelly/test_coordinator.py b/tests/components/shelly/test_coordinator.py index 8ce80b70032..e73168c6b20 100644 --- a/tests/components/shelly/test_coordinator.py +++ b/tests/components/shelly/test_coordinator.py @@ -2,6 +2,7 @@ from datetime import timedelta from unittest.mock import AsyncMock, patch +from aioshelly.const import MODEL_BULB, MODEL_BUTTON1 from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError from freezegun.api import FrozenDateTimeFactory @@ -79,7 +80,7 @@ async def test_block_no_reload_on_bulb_changes( hass: HomeAssistant, freezer: FrozenDateTimeFactory, mock_block_device, monkeypatch ) -> None: """Test block no reload on bulb mode/effect change.""" - await init_integration(hass, 1, model="SHBLB-1") + await init_integration(hass, 1, model=MODEL_BULB) monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "cfgChanged", 1) mock_block_device.mock_update() @@ -284,7 +285,7 @@ async def test_block_button_click_event( "sensor_ids", {"inputEvent": "S", "inputEventCnt": 0}, ) - entry = await init_integration(hass, 1, model="SHBTN-1", sleep_period=1000) + entry = await init_integration(hass, 1, model=MODEL_BUTTON1, sleep_period=1000) # Make device online mock_block_device.mock_update() diff --git a/tests/components/shelly/test_device_trigger.py b/tests/components/shelly/test_device_trigger.py index 143501ef620..9a63e66980a 100644 --- a/tests/components/shelly/test_device_trigger.py +++ b/tests/components/shelly/test_device_trigger.py @@ -1,4 +1,5 @@ """The tests for Shelly device triggers.""" +from aioshelly.const import MODEL_BUTTON1 import pytest from pytest_unordered import unordered @@ -108,7 +109,7 @@ async def test_get_triggers_rpc_device(hass: HomeAssistant, mock_rpc_device) -> async def test_get_triggers_button(hass: HomeAssistant, mock_block_device) -> None: """Test we get the expected triggers from a shelly button.""" - entry = await init_integration(hass, 1, model="SHBTN-1") + entry = await init_integration(hass, 1, model=MODEL_BUTTON1) dev_reg = async_get_dev_reg(hass) device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0] diff --git a/tests/components/shelly/test_diagnostics.py b/tests/components/shelly/test_diagnostics.py index 39f1ef8d723..13126db0a0e 100644 --- a/tests/components/shelly/test_diagnostics.py +++ b/tests/components/shelly/test_diagnostics.py @@ -2,6 +2,7 @@ from unittest.mock import ANY from aioshelly.ble.const import BLE_SCAN_RESULT_EVENT +from aioshelly.const import MODEL_25 from homeassistant.components.diagnostics import REDACTED from homeassistant.components.shelly.const import ( @@ -40,7 +41,7 @@ async def test_block_config_entry_diagnostics( "bluetooth": "not initialized", "device_info": { "name": "Test name", - "model": "SHSW-25", + "model": MODEL_25, "sw_version": "some fw string", }, "device_settings": {"coiot": {"update_period": 15}}, @@ -136,7 +137,7 @@ async def test_rpc_config_entry_diagnostics( }, "device_info": { "name": "Test name", - "model": "SHSW-25", + "model": MODEL_25, "sw_version": "some fw string", }, "device_settings": {}, diff --git a/tests/components/shelly/test_event.py b/tests/components/shelly/test_event.py index b7824d8d7ac..09439adc6f7 100644 --- a/tests/components/shelly/test_event.py +++ b/tests/components/shelly/test_event.py @@ -1,6 +1,7 @@ """Tests for Shelly button platform.""" from __future__ import annotations +from aioshelly.const import MODEL_I3 from pytest_unordered import unordered from homeassistant.components.event import ( @@ -104,7 +105,7 @@ async def test_block_event(hass: HomeAssistant, monkeypatch, mock_block_device) async def test_block_event_shix3_1(hass: HomeAssistant, mock_block_device) -> None: """Test block device event for SHIX3-1.""" - await init_integration(hass, 1, model="SHIX3-1") + await init_integration(hass, 1, model=MODEL_I3) entity_id = "event.test_name_channel_1" state = hass.states.get(entity_id) diff --git a/tests/components/shelly/test_light.py b/tests/components/shelly/test_light.py index 69d0fccf421..e3aea966230 100644 --- a/tests/components/shelly/test_light.py +++ b/tests/components/shelly/test_light.py @@ -1,4 +1,13 @@ """Tests for Shelly light platform.""" +from aioshelly.const import ( + MODEL_BULB, + MODEL_BULB_RGBW, + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_DUO, + MODEL_RGBW2, + MODEL_VINTAGE_V2, +) import pytest from homeassistant.components.light import ( @@ -33,7 +42,7 @@ LIGHT_BLOCK_ID = 2 async def test_block_device_rgbw_bulb(hass: HomeAssistant, mock_block_device) -> None: """Test block device RGBW bulb.""" - await init_integration(hass, 1, model="SHBLB-1") + await init_integration(hass, 1, model=MODEL_BULB) # Test initial state = hass.states.get("light.test_name_channel_1") @@ -113,7 +122,7 @@ async def test_block_device_rgb_bulb( ) -> None: """Test block device RGB bulb.""" monkeypatch.delattr(mock_block_device.blocks[LIGHT_BLOCK_ID], "mode") - await init_integration(hass, 1, model="SHCB-1") + await init_integration(hass, 1, model=MODEL_BULB_RGBW) # Test initial state = hass.states.get("light.test_name_channel_1") @@ -215,7 +224,7 @@ async def test_block_device_white_bulb( monkeypatch.delattr(mock_block_device.blocks[LIGHT_BLOCK_ID], "mode") monkeypatch.delattr(mock_block_device.blocks[LIGHT_BLOCK_ID], "colorTemp") monkeypatch.delattr(mock_block_device.blocks[LIGHT_BLOCK_ID], "effect") - await init_integration(hass, 1, model="SHVIN-1") + await init_integration(hass, 1, model=MODEL_VINTAGE_V2) # Test initial state = hass.states.get("light.test_name_channel_1") @@ -259,12 +268,12 @@ async def test_block_device_white_bulb( @pytest.mark.parametrize( "model", [ - "SHBDUO-1", - "SHCB-1", - "SHDM-1", - "SHDM-2", - "SHRGBW2", - "SHVIN-1", + MODEL_DUO, + MODEL_BULB_RGBW, + MODEL_DIMMER, + MODEL_DIMMER_2, + MODEL_RGBW2, + MODEL_VINTAGE_V2, ], ) async def test_block_device_support_transition( diff --git a/tests/components/shelly/test_switch.py b/tests/components/shelly/test_switch.py index 9bc065ed166..69e1423f75a 100644 --- a/tests/components/shelly/test_switch.py +++ b/tests/components/shelly/test_switch.py @@ -2,6 +2,7 @@ from copy import deepcopy from unittest.mock import AsyncMock +from aioshelly.const import MODEL_GAS from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError import pytest @@ -238,7 +239,7 @@ async def test_block_device_gas_valve( ) -> None: """Test block device Shelly Gas with Valve addon.""" registry = er.async_get(hass) - await init_integration(hass, 1, "SHGS-1") + await init_integration(hass, 1, MODEL_GAS) entity_id = "switch.test_name_valve" entry = registry.async_get(entity_id) diff --git a/tests/components/shelly/test_utils.py b/tests/components/shelly/test_utils.py index 07ba0d724c2..e47f9e451b4 100644 --- a/tests/components/shelly/test_utils.py +++ b/tests/components/shelly/test_utils.py @@ -1,11 +1,19 @@ """Tests for Shelly utils.""" -import pytest - -from homeassistant.components.shelly.const import ( - GEN1_RELEASE_URL, - GEN2_RELEASE_URL, +from aioshelly.const import ( + MODEL_1, + MODEL_1L, + MODEL_BUTTON1, + MODEL_BUTTON1_V2, + MODEL_DIMMER_2, + MODEL_EM3, + MODEL_I3, + MODEL_MOTION, + MODEL_PLUS_2PM_V2, MODEL_WALL_DISPLAY, ) +import pytest + +from homeassistant.components.shelly.const import GEN1_RELEASE_URL, GEN2_RELEASE_URL from homeassistant.components.shelly.utils import ( get_block_channel_name, get_block_device_sleep_period, @@ -45,7 +53,7 @@ async def test_block_get_number_of_channels(mock_block_device, monkeypatch) -> N == 4 ) - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHDM-2") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_DIMMER_2) assert ( get_number_of_channels( mock_block_device, @@ -67,7 +75,7 @@ async def test_block_get_block_channel_name(mock_block_device, monkeypatch) -> N == "Test name channel 1" ) - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHEM-3") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_EM3) assert ( get_block_channel_name( @@ -113,7 +121,7 @@ async def test_is_block_momentary_input(mock_block_device, monkeypatch) -> None: ) monkeypatch.setitem(mock_block_device.settings, "mode", "relay") - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHSW-L") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_1L) assert ( is_block_momentary_input( mock_block_device.settings, mock_block_device.blocks[DEVICE_BLOCK_ID], True @@ -131,7 +139,7 @@ async def test_is_block_momentary_input(mock_block_device, monkeypatch) -> None: is False ) - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHBTN-2") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_BUTTON1_V2) assert ( is_block_momentary_input( @@ -183,7 +191,7 @@ async def test_get_block_input_triggers(mock_block_device, monkeypatch) -> None: ) ) == {("long", "button"), ("single", "button")} - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHBTN-1") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_BUTTON1) assert set( get_block_input_triggers( mock_block_device, mock_block_device.blocks[DEVICE_BLOCK_ID] @@ -195,7 +203,7 @@ async def test_get_block_input_triggers(mock_block_device, monkeypatch) -> None: ("triple", "button"), } - monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHIX3-1") + monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_I3) assert set( get_block_input_triggers( mock_block_device, mock_block_device.blocks[DEVICE_BLOCK_ID] @@ -235,12 +243,12 @@ async def test_get_rpc_input_triggers(mock_rpc_device, monkeypatch) -> None: @pytest.mark.parametrize( ("gen", "model", "beta", "expected"), [ - (1, "SHMOS-01", False, None), - (1, "SHSW-1", False, GEN1_RELEASE_URL), - (1, "SHSW-1", True, None), + (1, MODEL_MOTION, False, None), + (1, MODEL_1, False, GEN1_RELEASE_URL), + (1, MODEL_1, True, None), (2, MODEL_WALL_DISPLAY, False, None), - (2, "SNSW-102P16EU", False, GEN2_RELEASE_URL), - (2, "SNSW-102P16EU", True, None), + (2, MODEL_PLUS_2PM_V2, False, GEN2_RELEASE_URL), + (2, MODEL_PLUS_2PM_V2, True, None), ], ) def test_get_release_url(