From 618fe81207a02aff97e18a1fdc1ac07f94998689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A5le=20Stor=C3=B8=20Hauknes?= Date: Sun, 5 Oct 2025 14:49:34 +0200 Subject: [PATCH] Check if firmware is outdated when adding an Airthings BLE device (#153559) --- .../components/airthings_ble/config_flow.py | 9 +++ .../components/airthings_ble/strings.json | 1 + .../airthings_ble/test_config_flow.py | 69 +++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/homeassistant/components/airthings_ble/config_flow.py b/homeassistant/components/airthings_ble/config_flow.py index fa6a52a5a798..c9b1ffbc81d5 100644 --- a/homeassistant/components/airthings_ble/config_flow.py +++ b/homeassistant/components/airthings_ble/config_flow.py @@ -117,6 +117,12 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN): ) -> ConfigFlowResult: """Confirm discovery.""" if user_input is not None: + if ( + self._discovered_device is not None + and self._discovered_device.device.firmware.need_firmware_upgrade + ): + return self.async_abort(reason="firmware_upgrade_required") + return self.async_create_entry( title=self.context["title_placeholders"]["name"], data={} ) @@ -137,6 +143,9 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN): self._abort_if_unique_id_configured() discovery = self._discovered_devices[address] + if discovery.device.firmware.need_firmware_upgrade: + return self.async_abort(reason="firmware_upgrade_required") + self.context["title_placeholders"] = { "name": discovery.name, } diff --git a/homeassistant/components/airthings_ble/strings.json b/homeassistant/components/airthings_ble/strings.json index f73546bbe422..f5639e8da8f1 100644 --- a/homeassistant/components/airthings_ble/strings.json +++ b/homeassistant/components/airthings_ble/strings.json @@ -20,6 +20,7 @@ "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "firmware_upgrade_required": "Your device requires a firmware upgrade. Please use the Airthings app (Android/iOS) to upgrade it.", "unknown": "[%key:common::config_flow::error::unknown%]" } }, diff --git a/tests/components/airthings_ble/test_config_flow.py b/tests/components/airthings_ble/test_config_flow.py index 42db22a99153..8203892adb92 100644 --- a/tests/components/airthings_ble/test_config_flow.py +++ b/tests/components/airthings_ble/test_config_flow.py @@ -281,3 +281,72 @@ async def test_unsupported_device(hass: HomeAssistant) -> None: ) assert result["type"] is FlowResultType.ABORT assert result["reason"] == "no_devices_found" + + +async def test_bluetooth_confirm_firmware_required(hass: HomeAssistant) -> None: + """Test discovery via bluetooth with a valid device.""" + device = AirthingsDevice( + manufacturer="Airthings AS", + model=AirthingsDeviceType.WAVE_ENHANCE_EU, + name="Airthings Wave Enhance", + identifier="123456", + ) + device.firmware.update_current_version("1.0.0") + device.firmware.update_required_version("2.6.1") + with ( + patch_async_ble_device_from_address(WAVE_SERVICE_INFO), + patch_airthings_ble(device), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_BLUETOOTH}, + data=WAVE_SERVICE_INFO, + ) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "bluetooth_confirm" + + with patch_async_setup_entry(): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={"not": "empty"} + ) + await hass.async_block_till_done() + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "firmware_upgrade_required" + + +async def test_step_user_firmware_required(hass: HomeAssistant) -> None: + """Test the user has selected a device with a firmware upgrade required.""" + device = AirthingsDevice( + manufacturer="Airthings AS", + model=AirthingsDeviceType.WAVE_ENHANCE_EU, + name="Airthings Wave Enhance", + identifier="123456", + ) + device.firmware.update_current_version("1.0.0") + device.firmware.update_required_version("2.6.1") + + with ( + patch( + "homeassistant.components.airthings_ble.config_flow.async_discovered_service_info", + return_value=[WAVE_SERVICE_INFO], + ), + patch_async_ble_device_from_address(WAVE_SERVICE_INFO), + patch_airthings_ble(device), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "user" + + with patch( + "homeassistant.components.airthings_ble.async_setup_entry", + return_value=True, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={CONF_ADDRESS: "cc:cc:cc:cc:cc:cc"} + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "firmware_upgrade_required"