Skip to content

Commit 70fc6df

Browse files
authored
Make Shelly deprecated firmware issue more general (home-assistant#154539)
1 parent 8dc33ec commit 70fc6df

File tree

5 files changed

+57
-25
lines changed

5 files changed

+57
-25
lines changed

homeassistant/components/shelly/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@
5959
)
6060
from .repairs import (
6161
async_manage_ble_scanner_firmware_unsupported_issue,
62+
async_manage_deprecated_firmware_issue,
6263
async_manage_outbound_websocket_incorrectly_enabled_issue,
63-
async_manage_wall_display_firmware_unsupported_issue,
6464
)
6565
from .utils import (
6666
async_create_issue_unsupported_firmware,
@@ -337,7 +337,7 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry)
337337
await hass.config_entries.async_forward_entry_setups(
338338
entry, runtime_data.platforms
339339
)
340-
async_manage_wall_display_firmware_unsupported_issue(hass, entry)
340+
async_manage_deprecated_firmware_issue(hass, entry)
341341
async_manage_ble_scanner_firmware_unsupported_issue(
342342
hass,
343343
entry,

homeassistant/components/shelly/const.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from enum import StrEnum
66
from logging import Logger, getLogger
77
import re
8-
from typing import Final
8+
from typing import Final, TypedDict
99

1010
from aioshelly.const import (
1111
MODEL_BULB,
@@ -232,7 +232,6 @@ class BLEScannerMode(StrEnum):
232232

233233

234234
BLE_SCANNER_MIN_FIRMWARE = "1.5.1"
235-
WALL_DISPLAY_MIN_FIRMWARE = "2.3.0"
236235

237236
MAX_PUSH_UPDATE_FAILURES = 5
238237
PUSH_UPDATE_ISSUE_ID = "push_update_{unique}"
@@ -245,9 +244,28 @@ class BLEScannerMode(StrEnum):
245244
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID = (
246245
"outbound_websocket_incorrectly_enabled_{unique}"
247246
)
248-
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID = (
249-
"wall_display_firmware_unsupported_{unique}"
250-
)
247+
DEPRECATED_FIRMWARE_ISSUE_ID = "deprecated_firmware_{unique}"
248+
249+
250+
class DeprecatedFirmwareInfo(TypedDict):
251+
"""TypedDict for Deprecated Firmware Info."""
252+
253+
min_firmware: str
254+
ha_version: str
255+
256+
257+
# Provide firmware deprecation data:
258+
# key: device model
259+
# value: dict with:
260+
# min_firmware: minimum supported firmware version
261+
# ha_version: Home Assistant version when older firmware will be deprecated
262+
# Example:
263+
# DEPRECATED_FIRMWARES: dict[str, DeprecatedFirmwareInfo] = {
264+
# MODEL_WALL_DISPLAY: DeprecatedFirmwareInfo(
265+
# {"min_firmware": "2.3.0", "ha_version": "2025.10.0"}
266+
# ),
267+
# }
268+
DEPRECATED_FIRMWARES: dict[str, DeprecatedFirmwareInfo] = {}
251269

252270
GAS_VALVE_OPEN_STATES = ("opening", "opened")
253271

homeassistant/components/shelly/repairs.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from typing import TYPE_CHECKING
66

7-
from aioshelly.const import MODEL_OUT_PLUG_S_G3, MODEL_PLUG_S_G3, MODEL_WALL_DISPLAY
7+
from aioshelly.const import MODEL_OUT_PLUG_S_G3, MODEL_PLUG_S_G3
88
from aioshelly.exceptions import DeviceConnectionError, RpcCallError
99
from aioshelly.rpc_device import RpcDevice
1010
from awesomeversion import AwesomeVersion
@@ -19,10 +19,10 @@
1919
BLE_SCANNER_FIRMWARE_UNSUPPORTED_ISSUE_ID,
2020
BLE_SCANNER_MIN_FIRMWARE,
2121
CONF_BLE_SCANNER_MODE,
22+
DEPRECATED_FIRMWARE_ISSUE_ID,
23+
DEPRECATED_FIRMWARES,
2224
DOMAIN,
2325
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID,
24-
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID,
25-
WALL_DISPLAY_MIN_FIRMWARE,
2626
BLEScannerMode,
2727
)
2828
from .coordinator import ShellyConfigEntry
@@ -70,33 +70,38 @@ def async_manage_ble_scanner_firmware_unsupported_issue(
7070

7171

7272
@callback
73-
def async_manage_wall_display_firmware_unsupported_issue(
73+
def async_manage_deprecated_firmware_issue(
7474
hass: HomeAssistant,
7575
entry: ShellyConfigEntry,
7676
) -> None:
77-
"""Manage the Wall Display firmware unsupported issue."""
78-
issue_id = WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID.format(unique=entry.unique_id)
77+
"""Manage deprecated firmware issue."""
78+
issue_id = DEPRECATED_FIRMWARE_ISSUE_ID.format(unique=entry.unique_id)
7979

8080
if TYPE_CHECKING:
8181
assert entry.runtime_data.rpc is not None
8282

8383
device = entry.runtime_data.rpc.device
84+
model = entry.data["model"]
85+
86+
if model in DEPRECATED_FIRMWARES:
87+
min_firmware = DEPRECATED_FIRMWARES[model]["min_firmware"]
88+
ha_version = DEPRECATED_FIRMWARES[model]["ha_version"]
8489

85-
if entry.data["model"] == MODEL_WALL_DISPLAY:
8690
firmware = AwesomeVersion(device.shelly["ver"])
87-
if firmware < WALL_DISPLAY_MIN_FIRMWARE:
91+
if firmware < min_firmware:
8892
ir.async_create_issue(
8993
hass,
9094
DOMAIN,
9195
issue_id,
9296
is_fixable=True,
9397
is_persistent=True,
9498
severity=ir.IssueSeverity.WARNING,
95-
translation_key="wall_display_firmware_unsupported",
99+
translation_key="deprecated_firmware",
96100
translation_placeholders={
97101
"device_name": device.name,
98102
"ip_address": device.ip_address,
99103
"firmware": firmware,
104+
"ha_version": ha_version,
100105
},
101106
data={"entry_id": entry.entry_id},
102107
)
@@ -241,7 +246,7 @@ async def async_create_fix_flow(
241246

242247
if (
243248
"ble_scanner_firmware_unsupported" in issue_id
244-
or "wall_display_firmware_unsupported" in issue_id
249+
or "deprecated_firmware" in issue_id
245250
):
246251
return FirmwareUpdateFlow(device)
247252

homeassistant/components/shelly/strings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,13 @@
312312
}
313313
}
314314
},
315-
"wall_display_firmware_unsupported": {
315+
"deprecated_firmware": {
316316
"title": "{device_name} is running outdated firmware",
317317
"fix_flow": {
318318
"step": {
319319
"confirm": {
320320
"title": "{device_name} is running outdated firmware",
321-
"description": "Your Shelly device {device_name} with IP address {ip_address} is running firmware {firmware}. This firmware version will not be supported by Shelly integration starting from Home Assistant 2025.11.0.\n\nSelect **Submit** button to start the OTA update to the latest stable firmware version."
321+
"description": "Your Shelly device {device_name} with IP address {ip_address} is running firmware {firmware}. This firmware version will not be supported by Shelly integration starting from Home Assistant {ha_version}.\n\nSelect **Submit** button to start the OTA update to the latest stable firmware version."
322322
}
323323
},
324324
"abort": {

tests/components/shelly/test_repairs.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Test repairs handling for Shelly."""
22

3-
from unittest.mock import Mock
3+
from unittest.mock import Mock, patch
44

55
from aioshelly.const import MODEL_WALL_DISPLAY
66
from aioshelly.exceptions import DeviceConnectionError, RpcCallError
@@ -9,10 +9,11 @@
99
from homeassistant.components.shelly.const import (
1010
BLE_SCANNER_FIRMWARE_UNSUPPORTED_ISSUE_ID,
1111
CONF_BLE_SCANNER_MODE,
12+
DEPRECATED_FIRMWARE_ISSUE_ID,
1213
DOMAIN,
1314
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID,
14-
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID,
1515
BLEScannerMode,
16+
DeprecatedFirmwareInfo,
1617
)
1718
from homeassistant.core import HomeAssistant
1819
from homeassistant.helpers import issue_registry as ir
@@ -215,17 +216,25 @@ async def test_outbound_websocket_incorrectly_enabled_issue_exc(
215216
assert len(issue_registry.issues) == 1
216217

217218

218-
async def test_wall_display_unsupported_firmware_issue(
219+
async def test_deprecated_firmware_issue(
219220
hass: HomeAssistant,
220221
hass_client: ClientSessionGenerator,
221222
mock_rpc_device: Mock,
222223
issue_registry: ir.IssueRegistry,
223224
) -> None:
224-
"""Test repair issues handling for Wall Display with unsupported firmware."""
225-
issue_id = WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID.format(unique=MOCK_MAC)
225+
"""Test repair issues handling deprecated firmware."""
226+
issue_id = DEPRECATED_FIRMWARE_ISSUE_ID.format(unique=MOCK_MAC)
226227
assert await async_setup_component(hass, "repairs", {})
227228
await hass.async_block_till_done()
228-
await init_integration(hass, 2, model=MODEL_WALL_DISPLAY)
229+
with patch(
230+
"homeassistant.components.shelly.repairs.DEPRECATED_FIRMWARES",
231+
{
232+
MODEL_WALL_DISPLAY: DeprecatedFirmwareInfo(
233+
{"min_firmware": "2.3.0", "ha_version": "2025.10.0"}
234+
)
235+
},
236+
):
237+
await init_integration(hass, 2, model=MODEL_WALL_DISPLAY)
229238

230239
# The default fw version in tests is 1.0.0, the repair issue should be created.
231240
assert issue_registry.async_get_issue(DOMAIN, issue_id)

0 commit comments

Comments
 (0)