Make Shelly deprecated firmware issue more general (#154539)

This commit is contained in:
Maciej Bieniek
2025-10-16 12:50:43 +02:00
committed by GitHub
parent 8dc33ece7b
commit 70fc6df599
5 changed files with 57 additions and 25 deletions
+2 -2
View File
@@ -59,8 +59,8 @@ from .coordinator import (
)
from .repairs import (
async_manage_ble_scanner_firmware_unsupported_issue,
async_manage_deprecated_firmware_issue,
async_manage_outbound_websocket_incorrectly_enabled_issue,
async_manage_wall_display_firmware_unsupported_issue,
)
from .utils import (
async_create_issue_unsupported_firmware,
@@ -337,7 +337,7 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry)
await hass.config_entries.async_forward_entry_setups(
entry, runtime_data.platforms
)
async_manage_wall_display_firmware_unsupported_issue(hass, entry)
async_manage_deprecated_firmware_issue(hass, entry)
async_manage_ble_scanner_firmware_unsupported_issue(
hass,
entry,
+23 -5
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
from enum import StrEnum
from logging import Logger, getLogger
import re
from typing import Final
from typing import Final, TypedDict
from aioshelly.const import (
MODEL_BULB,
@@ -232,7 +232,6 @@ class BLEScannerMode(StrEnum):
BLE_SCANNER_MIN_FIRMWARE = "1.5.1"
WALL_DISPLAY_MIN_FIRMWARE = "2.3.0"
MAX_PUSH_UPDATE_FAILURES = 5
PUSH_UPDATE_ISSUE_ID = "push_update_{unique}"
@@ -245,9 +244,28 @@ BLE_SCANNER_FIRMWARE_UNSUPPORTED_ISSUE_ID = "ble_scanner_firmware_unsupported_{u
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID = (
"outbound_websocket_incorrectly_enabled_{unique}"
)
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID = (
"wall_display_firmware_unsupported_{unique}"
)
DEPRECATED_FIRMWARE_ISSUE_ID = "deprecated_firmware_{unique}"
class DeprecatedFirmwareInfo(TypedDict):
"""TypedDict for Deprecated Firmware Info."""
min_firmware: str
ha_version: str
# Provide firmware deprecation data:
# key: device model
# value: dict with:
# min_firmware: minimum supported firmware version
# ha_version: Home Assistant version when older firmware will be deprecated
# Example:
# DEPRECATED_FIRMWARES: dict[str, DeprecatedFirmwareInfo] = {
# MODEL_WALL_DISPLAY: DeprecatedFirmwareInfo(
# {"min_firmware": "2.3.0", "ha_version": "2025.10.0"}
# ),
# }
DEPRECATED_FIRMWARES: dict[str, DeprecatedFirmwareInfo] = {}
GAS_VALVE_OPEN_STATES = ("opening", "opened")
+15 -10
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from aioshelly.const import MODEL_OUT_PLUG_S_G3, MODEL_PLUG_S_G3, MODEL_WALL_DISPLAY
from aioshelly.const import MODEL_OUT_PLUG_S_G3, MODEL_PLUG_S_G3
from aioshelly.exceptions import DeviceConnectionError, RpcCallError
from aioshelly.rpc_device import RpcDevice
from awesomeversion import AwesomeVersion
@@ -19,10 +19,10 @@ from .const import (
BLE_SCANNER_FIRMWARE_UNSUPPORTED_ISSUE_ID,
BLE_SCANNER_MIN_FIRMWARE,
CONF_BLE_SCANNER_MODE,
DEPRECATED_FIRMWARE_ISSUE_ID,
DEPRECATED_FIRMWARES,
DOMAIN,
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID,
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID,
WALL_DISPLAY_MIN_FIRMWARE,
BLEScannerMode,
)
from .coordinator import ShellyConfigEntry
@@ -70,21 +70,25 @@ def async_manage_ble_scanner_firmware_unsupported_issue(
@callback
def async_manage_wall_display_firmware_unsupported_issue(
def async_manage_deprecated_firmware_issue(
hass: HomeAssistant,
entry: ShellyConfigEntry,
) -> None:
"""Manage the Wall Display firmware unsupported issue."""
issue_id = WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID.format(unique=entry.unique_id)
"""Manage deprecated firmware issue."""
issue_id = DEPRECATED_FIRMWARE_ISSUE_ID.format(unique=entry.unique_id)
if TYPE_CHECKING:
assert entry.runtime_data.rpc is not None
device = entry.runtime_data.rpc.device
model = entry.data["model"]
if model in DEPRECATED_FIRMWARES:
min_firmware = DEPRECATED_FIRMWARES[model]["min_firmware"]
ha_version = DEPRECATED_FIRMWARES[model]["ha_version"]
if entry.data["model"] == MODEL_WALL_DISPLAY:
firmware = AwesomeVersion(device.shelly["ver"])
if firmware < WALL_DISPLAY_MIN_FIRMWARE:
if firmware < min_firmware:
ir.async_create_issue(
hass,
DOMAIN,
@@ -92,11 +96,12 @@ def async_manage_wall_display_firmware_unsupported_issue(
is_fixable=True,
is_persistent=True,
severity=ir.IssueSeverity.WARNING,
translation_key="wall_display_firmware_unsupported",
translation_key="deprecated_firmware",
translation_placeholders={
"device_name": device.name,
"ip_address": device.ip_address,
"firmware": firmware,
"ha_version": ha_version,
},
data={"entry_id": entry.entry_id},
)
@@ -241,7 +246,7 @@ async def async_create_fix_flow(
if (
"ble_scanner_firmware_unsupported" in issue_id
or "wall_display_firmware_unsupported" in issue_id
or "deprecated_firmware" in issue_id
):
return FirmwareUpdateFlow(device)
+2 -2
View File
@@ -312,13 +312,13 @@
}
}
},
"wall_display_firmware_unsupported": {
"deprecated_firmware": {
"title": "{device_name} is running outdated firmware",
"fix_flow": {
"step": {
"confirm": {
"title": "{device_name} is running outdated firmware",
"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."
"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."
}
},
"abort": {
+15 -6
View File
@@ -1,6 +1,6 @@
"""Test repairs handling for Shelly."""
from unittest.mock import Mock
from unittest.mock import Mock, patch
from aioshelly.const import MODEL_WALL_DISPLAY
from aioshelly.exceptions import DeviceConnectionError, RpcCallError
@@ -9,10 +9,11 @@ import pytest
from homeassistant.components.shelly.const import (
BLE_SCANNER_FIRMWARE_UNSUPPORTED_ISSUE_ID,
CONF_BLE_SCANNER_MODE,
DEPRECATED_FIRMWARE_ISSUE_ID,
DOMAIN,
OUTBOUND_WEBSOCKET_INCORRECTLY_ENABLED_ISSUE_ID,
WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID,
BLEScannerMode,
DeprecatedFirmwareInfo,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
@@ -215,17 +216,25 @@ async def test_outbound_websocket_incorrectly_enabled_issue_exc(
assert len(issue_registry.issues) == 1
async def test_wall_display_unsupported_firmware_issue(
async def test_deprecated_firmware_issue(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_rpc_device: Mock,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test repair issues handling for Wall Display with unsupported firmware."""
issue_id = WALL_DISPLAY_FIRMWARE_UNSUPPORTED_ISSUE_ID.format(unique=MOCK_MAC)
"""Test repair issues handling deprecated firmware."""
issue_id = DEPRECATED_FIRMWARE_ISSUE_ID.format(unique=MOCK_MAC)
assert await async_setup_component(hass, "repairs", {})
await hass.async_block_till_done()
await init_integration(hass, 2, model=MODEL_WALL_DISPLAY)
with patch(
"homeassistant.components.shelly.repairs.DEPRECATED_FIRMWARES",
{
MODEL_WALL_DISPLAY: DeprecatedFirmwareInfo(
{"min_firmware": "2.3.0", "ha_version": "2025.10.0"}
)
},
):
await init_integration(hass, 2, model=MODEL_WALL_DISPLAY)
# The default fw version in tests is 1.0.0, the repair issue should be created.
assert issue_registry.async_get_issue(DOMAIN, issue_id)