Skip to content

Commit

Permalink
Improve handling of old firmware versions (#125406)
Browse files Browse the repository at this point in the history
* Update Info fixture with new fields from pysmlight 0.0.14

* Create repair if device is running unsupported firmware

* Add test for legacy firmware info

* Add strings for repair issue
  • Loading branch information
tl-sl authored Sep 6, 2024
1 parent 8168b8f commit 6b1fc00
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
22 changes: 21 additions & 1 deletion homeassistant/components/smlight/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.issue_registry import IssueSeverity
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DOMAIN, LOGGER, SCAN_INTERVAL
Expand Down Expand Up @@ -40,6 +42,7 @@ def __init__(self, hass: HomeAssistant, host: str) -> None:

self.unique_id: str | None = None
self.client = Api2(host=host, session=async_get_clientsession(hass))
self.legacy_api: int = 0

async def _async_setup(self) -> None:
"""Authenticate if needed during initial setup."""
Expand All @@ -62,11 +65,28 @@ async def _async_setup(self) -> None:
info = await self.client.get_info()
self.unique_id = format_mac(info.MAC)

if info.legacy_api:
self.legacy_api = info.legacy_api
ir.async_create_issue(
self.hass,
DOMAIN,
"unsupported_firmware",
is_fixable=False,
is_persistent=False,
learn_more_url="https://smlight.tech/flasher/#SLZB-06",
severity=IssueSeverity.ERROR,
translation_key="unsupported_firmware",
)

async def _async_update_data(self) -> SmData:
"""Fetch data from the SMLIGHT device."""
try:
sensors = Sensors()
if not self.legacy_api:
sensors = await self.client.get_sensors()

return SmData(
sensors=await self.client.get_sensors(),
sensors=sensors,
info=await self.client.get_info(),
)
except SmlightAuthError as err:
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/smlight/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,11 @@
"name": "LED night mode"
}
}
},
"issues": {
"unsupported_firmware": {
"title": "SLZB core firmware update required",
"description": "Your SMLIGHT SLZB-06x device is running an unsupported core firmware version. Please update it to the latest version to enjoy all the features of this integration."
}
}
}
4 changes: 3 additions & 1 deletion tests/components/smlight/fixtures/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
"device_ip": "192.168.1.161",
"fs_total": 3456,
"fw_channel": "dev",
"legacy_api": 0,
"hostname": "SLZB-06p7",
"MAC": "AA:BB:CC:DD:EE:FF",
"model": "SLZB-06p7",
"ram_total": 296,
"sw_version": "v2.3.1.dev",
"sw_version": "v2.3.6",
"wifi_mode": 0,
"zb_flash_size": 704,
"zb_hw": "CC2652P7",
Expand Down
2 changes: 1 addition & 1 deletion tests/components/smlight/snapshots/test_init.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
'primary_config_entry': <ANY>,
'serial_number': None,
'suggested_area': None,
'sw_version': 'core: v2.3.1.dev / zigbee: -1',
'sw_version': 'core: v2.3.6 / zigbee: -1',
'via_device_id': None,
})
# ---
34 changes: 33 additions & 1 deletion tests/components/smlight/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
from unittest.mock import MagicMock

from freezegun.api import FrozenDateTimeFactory
from pysmlight import Info
from pysmlight.exceptions import SmlightAuthError, SmlightConnectionError, SmlightError
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.smlight.const import SCAN_INTERVAL
from homeassistant.components.smlight.const import DOMAIN, SCAN_INTERVAL
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.issue_registry import IssueRegistry

from .conftest import setup_integration

Expand Down Expand Up @@ -110,3 +112,33 @@ async def test_device_info(
)
assert device_entry is not None
assert device_entry == snapshot


async def test_device_legacy_firmware(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_smlight_client: MagicMock,
device_registry: dr.DeviceRegistry,
issue_registry: IssueRegistry,
) -> None:
"""Test device setup for old firmware version that dont support required API."""
LEGACY_VERSION = "v2.3.1"
mock_smlight_client.get_sensors.side_effect = SmlightError
mock_smlight_client.get_info.return_value = Info(
legacy_api=1, sw_version=LEGACY_VERSION, MAC="AA:BB:CC:DD:EE:FF"
)
entry = await setup_integration(hass, mock_config_entry)

assert entry.unique_id == "aa:bb:cc:dd:ee:ff"

device_entry = device_registry.async_get_device(
connections={(dr.CONNECTION_NETWORK_MAC, entry.unique_id)}
)
assert LEGACY_VERSION in device_entry.sw_version

issue = issue_registry.async_get_issue(
domain=DOMAIN, issue_id="unsupported_firmware"
)
assert issue is not None
assert issue.domain == DOMAIN
assert issue.issue_id == "unsupported_firmware"

0 comments on commit 6b1fc00

Please sign in to comment.