From 437bc04fe8e1101b8048fc2957018f635393a6a7 Mon Sep 17 00:00:00 2001 From: Manu <4445816+tr4nt0r@users.noreply.github.com> Date: Sun, 16 Nov 2025 11:30:04 +0100 Subject: [PATCH 1/9] Remove Live-TV support from Xbox integration (#156669) --- homeassistant/components/xbox/browse_media.py | 26 +------------------ homeassistant/components/xbox/media_player.py | 7 ++--- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/xbox/browse_media.py b/homeassistant/components/xbox/browse_media.py index 1a66a0d4956a9..ab311e244b5ab 100644 --- a/homeassistant/components/xbox/browse_media.py +++ b/homeassistant/components/xbox/browse_media.py @@ -5,7 +5,7 @@ from typing import NamedTuple from pythonxbox.api.client import XboxLiveClient -from pythonxbox.api.provider.catalog.const import HOME_APP_IDS, SYSTEM_PFN_ID_MAP +from pythonxbox.api.provider.catalog.const import HOME_APP_IDS from pythonxbox.api.provider.catalog.models import ( AlternateIdType, CatalogResponse, @@ -42,7 +42,6 @@ class MediaTypeDetails(NamedTuple): async def build_item_response( client: XboxLiveClient, device_id: str, - tv_configured: bool, media_content_type: str, media_content_id: str, ) -> BrowseMedia | None: @@ -83,29 +82,6 @@ async def build_item_response( ) ) - # Add TV if configured - if tv_configured: - tv_catalog: CatalogResponse = ( - await client.catalog.get_product_from_alternate_id( - SYSTEM_PFN_ID_MAP["Microsoft.Xbox.LiveTV_8wekyb3d8bbwe"][id_type], - id_type, - ) - ) - tv_thumb = _find_media_image( - tv_catalog.products[0].localized_properties[0].images - ) - children.append( - BrowseMedia( - media_class=MediaClass.APP, - media_content_id="TV", - media_content_type=MediaType.APP, - title="Live TV", - can_play=True, - can_expand=False, - thumbnail=None if tv_thumb is None else tv_thumb.uri, - ) - ) - content_types = sorted( {app.content_type for app in apps.result if app.content_type in TYPE_MAP} ) diff --git a/homeassistant/components/xbox/media_player.py b/homeassistant/components/xbox/media_player.py index 410dcabba3915..94c4636afa3d9 100644 --- a/homeassistant/components/xbox/media_player.py +++ b/homeassistant/components/xbox/media_player.py @@ -176,7 +176,6 @@ async def async_browse_media( return await build_item_response( self.client, self._console.id, - self.data.status.is_tv_configured, media_content_type or "", media_content_id or "", ) # type: ignore[return-value] @@ -187,10 +186,8 @@ async def async_play_media( """Launch an app on the Xbox.""" if media_id == "Home": await self.client.smartglass.go_home(self._console.id) - elif media_id == "TV": - await self.client.smartglass.show_tv_guide(self._console.id) - else: - await self.client.smartglass.launch_app(self._console.id, media_id) + + await self.client.smartglass.launch_app(self._console.id, media_id) def _find_media_image(images: list[Image]) -> Image | None: From 87d2597292a0b5f76dc42ca8f27563e9433f003b Mon Sep 17 00:00:00 2001 From: mettolen <1007649+mettolen@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:40:49 +0200 Subject: [PATCH 2/9] Add diagnostics to Saunum integration (#156623) --- .../components/saunum/diagnostics.py | 49 +++++++++++++++++++ .../components/saunum/quality_scale.yaml | 4 +- .../saunum/snapshots/test_diagnostics.ambr | 37 ++++++++++++++ tests/components/saunum/test_diagnostics.py | 22 +++++++++ 4 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/saunum/diagnostics.py create mode 100644 tests/components/saunum/snapshots/test_diagnostics.ambr create mode 100644 tests/components/saunum/test_diagnostics.py diff --git a/homeassistant/components/saunum/diagnostics.py b/homeassistant/components/saunum/diagnostics.py new file mode 100644 index 0000000000000..2f348dfa50cf6 --- /dev/null +++ b/homeassistant/components/saunum/diagnostics.py @@ -0,0 +1,49 @@ +"""Diagnostics support for Saunum Leil Sauna Control Unit integration.""" + +from __future__ import annotations + +from dataclasses import asdict +from typing import Any + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.const import CONF_HOST +from homeassistant.core import HomeAssistant + +from . import LeilSaunaConfigEntry + +REDACT_CONFIG = {CONF_HOST} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, entry: LeilSaunaConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + coordinator = entry.runtime_data + + # Build diagnostics data + diagnostics_data: dict[str, Any] = { + "config": async_redact_data(entry.data, REDACT_CONFIG), + "client_info": {"connected": coordinator.client.is_connected}, + "coordinator_info": { + "last_update_success": coordinator.last_update_success, + "update_interval": str(coordinator.update_interval), + "last_exception": str(coordinator.last_exception) + if coordinator.last_exception + else None, + }, + } + + # Add coordinator data if available + if coordinator.data: + data_dict = asdict(coordinator.data) + diagnostics_data["coordinator_data"] = data_dict + + # Add alarm summary + alarm_fields = [ + key + for key, value in data_dict.items() + if key.startswith("alarm_") and value is True + ] + diagnostics_data["active_alarms"] = alarm_fields + + return diagnostics_data diff --git a/homeassistant/components/saunum/quality_scale.yaml b/homeassistant/components/saunum/quality_scale.yaml index c7a52ef2f850c..b18fb9e58a6f5 100644 --- a/homeassistant/components/saunum/quality_scale.yaml +++ b/homeassistant/components/saunum/quality_scale.yaml @@ -41,7 +41,7 @@ rules: # Gold tier devices: done - diagnostics: todo + diagnostics: done discovery: status: exempt comment: Device uses generic Espressif hardware with no unique identifying information (MAC OUI or hostname) that would distinguish it from other Espressif-based devices on the network. @@ -49,7 +49,7 @@ rules: docs-data-update: done docs-examples: todo docs-known-limitations: done - docs-supported-devices: todo + docs-supported-devices: done docs-supported-functions: done docs-troubleshooting: done docs-use-cases: done diff --git a/tests/components/saunum/snapshots/test_diagnostics.ambr b/tests/components/saunum/snapshots/test_diagnostics.ambr new file mode 100644 index 0000000000000..1e1fce24d29d7 --- /dev/null +++ b/tests/components/saunum/snapshots/test_diagnostics.ambr @@ -0,0 +1,37 @@ +# serializer version: 1 +# name: test_entry_diagnostics + dict({ + 'active_alarms': list([ + ]), + 'client_info': dict({ + 'connected': True, + }), + 'config': dict({ + 'host': '**REDACTED**', + }), + 'coordinator_data': dict({ + 'alarm_door_open': False, + 'alarm_door_sensor': False, + 'alarm_internal_temp': False, + 'alarm_temp_sensor_open': False, + 'alarm_temp_sensor_short': False, + 'alarm_thermal_cutoff': False, + 'current_temperature': 75.0, + 'door_open': False, + 'fan_duration': 10, + 'fan_speed': 2, + 'heater_elements_active': 0, + 'light_on': False, + 'on_time': 3600, + 'sauna_duration': 120, + 'sauna_type': 0, + 'session_active': False, + 'target_temperature': 80, + }), + 'coordinator_info': dict({ + 'last_exception': None, + 'last_update_success': True, + 'update_interval': '0:01:00', + }), + }) +# --- diff --git a/tests/components/saunum/test_diagnostics.py b/tests/components/saunum/test_diagnostics.py new file mode 100644 index 0000000000000..a67a937947109 --- /dev/null +++ b/tests/components/saunum/test_diagnostics.py @@ -0,0 +1,22 @@ +"""Test Saunum Leil Sauna diagnostics.""" + +from syrupy.assertion import SnapshotAssertion + +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry +from tests.components.diagnostics import get_diagnostics_for_config_entry +from tests.typing import ClientSessionGenerator + + +async def test_entry_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + init_integration: MockConfigEntry, + snapshot: SnapshotAssertion, +) -> None: + """Test config entry diagnostics.""" + assert ( + await get_diagnostics_for_config_entry(hass, hass_client, init_integration) + == snapshot + ) From 6f0de3071abed4256fef93be7c9903f34ae311b4 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 16 Nov 2025 11:43:25 +0100 Subject: [PATCH 3/9] Add fixture for dual washing machine to SmartThings (#156646) --- tests/components/smartthings/conftest.py | 1 + .../device_status/da_wm_wm_100002.json | 261 ++++++++++++++++++ .../fixtures/devices/da_wm_wm_100002.json | 122 ++++++++ .../snapshots/test_binary_sensor.ambr | 97 +++++++ .../smartthings/snapshots/test_init.ambr | 31 +++ .../smartthings/snapshots/test_select.ambr | 59 ++++ .../smartthings/snapshots/test_sensor.ambr | 195 +++++++++++++ 7 files changed, 766 insertions(+) create mode 100644 tests/components/smartthings/fixtures/device_status/da_wm_wm_100002.json create mode 100644 tests/components/smartthings/fixtures/devices/da_wm_wm_100002.json diff --git a/tests/components/smartthings/conftest.py b/tests/components/smartthings/conftest.py index 7840cf4077767..fb6dcedef4030 100644 --- a/tests/components/smartthings/conftest.py +++ b/tests/components/smartthings/conftest.py @@ -131,6 +131,7 @@ def mock_smartthings() -> Generator[AsyncMock]: "da_wm_wd_000001_1", "da_wm_wm_01011", "da_wm_wm_100001", + "da_wm_wm_100002", "da_wm_wm_000001", "da_wm_wm_000001_1", "da_wm_sc_000001", diff --git a/tests/components/smartthings/fixtures/device_status/da_wm_wm_100002.json b/tests/components/smartthings/fixtures/device_status/da_wm_wm_100002.json new file mode 100644 index 0000000000000..0b8d038919452 --- /dev/null +++ b/tests/components/smartthings/fixtures/device_status/da_wm_wm_100002.json @@ -0,0 +1,261 @@ +{ + "components": { + "sub": { + "ocf": { + "st": { + "value": null + }, + "mndt": { + "value": null + }, + "mnfv": { + "value": null + }, + "mnhw": { + "value": null + }, + "di": { + "value": null + }, + "mnsl": { + "value": null + }, + "dmv": { + "value": null + }, + "n": { + "value": null + }, + "mnmo": { + "value": null + }, + "vid": { + "value": null + }, + "mnmn": { + "value": null + }, + "mnml": { + "value": null + }, + "mnpv": { + "value": null + }, + "mnos": { + "value": null + }, + "pi": { + "value": null + }, + "icv": { + "value": null + } + }, + "remoteControlStatus": { + "remoteControlEnabled": { + "value": "true", + "timestamp": "2025-11-14T02:38:34.039Z" + } + }, + "samsungce.driverVersion": { + "versionNumber": { + "value": null + } + }, + "refresh": {}, + "samsungce.washerOperatingState": { + "washerJobState": { + "value": "none", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "operatingState": { + "value": "ready", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "supportedOperatingStates": { + "value": ["ready", "running", "paused"], + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "scheduledJobs": { + "value": null + }, + "scheduledPhases": { + "value": null + }, + "progress": { + "value": null + }, + "remainingTimeStr": { + "value": "00:43", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "washerJobPhase": { + "value": null + }, + "operationTime": { + "value": null + }, + "remainingTime": { + "value": 43, + "unit": "min", + "timestamp": "2025-11-14T02:27:39.046Z" + } + }, + "washerOperatingState": { + "completionTime": { + "value": "2025-11-14T03:10:39Z", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "machineState": { + "value": "stop", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "washerJobState": { + "value": "none", + "timestamp": "2025-11-14T02:27:39.046Z" + }, + "supportedMachineStates": { + "value": null + } + }, + "switch": { + "switch": { + "value": null + } + } + }, + "main": { + "ocf": { + "st": { + "value": null + }, + "mndt": { + "value": null + }, + "mnfv": { + "value": null + }, + "mnhw": { + "value": null + }, + "di": { + "value": "C097276D-C8D4-0000-0000-000000000000", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "mnsl": { + "value": null + }, + "dmv": { + "value": "res.1.1.0,sh.1.1.0", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "n": { + "value": "Washer", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "mnmo": { + "value": "TP6X_WV60M9900AV|20198041|20020001001111060100000000000000", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "vid": { + "value": "DA-WM-WM-100002", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "mnmn": { + "value": "Samsung Electronics", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "mnml": { + "value": null + }, + "mnpv": { + "value": null + }, + "mnos": { + "value": null + }, + "pi": { + "value": "shp", + "timestamp": "2025-11-14T02:27:38.956Z" + }, + "icv": { + "value": "core.1.1.0", + "timestamp": "2025-11-14T02:27:38.956Z" + } + }, + "remoteControlStatus": { + "remoteControlEnabled": { + "value": "true", + "timestamp": "2025-11-14T02:38:36.210Z" + } + }, + "samsungce.driverVersion": { + "versionNumber": { + "value": 22100103, + "timestamp": "2025-11-14T02:27:38.980Z" + } + }, + "refresh": {}, + "samsungce.washerOperatingState": { + "washerJobState": { + "value": "spin", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "operatingState": { + "value": "running", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "supportedOperatingStates": { + "value": ["ready", "running", "paused"], + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "scheduledJobs": { + "value": null + }, + "scheduledPhases": { + "value": null + }, + "progress": { + "value": null + }, + "remainingTimeStr": { + "value": "00:05", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "washerJobPhase": { + "value": null + }, + "operationTime": { + "value": null + }, + "remainingTime": { + "value": 5, + "unit": "min", + "timestamp": "2025-11-14T02:27:39.112Z" + } + }, + "washerOperatingState": { + "completionTime": { + "value": "2025-11-14T02:32:39Z", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "machineState": { + "value": "run", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "washerJobState": { + "value": "spin", + "timestamp": "2025-11-14T02:27:39.112Z" + }, + "supportedMachineStates": { + "value": null + } + }, + "switch": { + "switch": { + "value": null + } + } + } + } +} diff --git a/tests/components/smartthings/fixtures/devices/da_wm_wm_100002.json b/tests/components/smartthings/fixtures/devices/da_wm_wm_100002.json new file mode 100644 index 0000000000000..91f4031b516ab --- /dev/null +++ b/tests/components/smartthings/fixtures/devices/da_wm_wm_100002.json @@ -0,0 +1,122 @@ +{ + "items": [ + { + "deviceId": "C097276D-C8D4-0000-0000-000000000000", + "name": "Washer", + "label": "Washer", + "manufacturerName": "Samsung Electronics", + "presentationId": "DA-WM-WM-100002", + "deviceManufacturerCode": "Samsung Electronics", + "locationId": "600f7b9a-81f4-469a-bd36-b516160bc114", + "ownerId": "506a8ee1-c1cb-d9f2-77fa-e50b13541832", + "roomId": "7af56bf7-532c-45c5-8c51-2ed1cd7ac267", + "deviceTypeName": "Samsung OCF Washer", + "components": [ + { + "id": "main", + "label": "main", + "capabilities": [ + { + "id": "ocf", + "version": 1 + }, + { + "id": "refresh", + "version": 1 + }, + { + "id": "switch", + "version": 1 + }, + { + "id": "remoteControlStatus", + "version": 1 + }, + { + "id": "washerOperatingState", + "version": 1 + }, + { + "id": "samsungce.driverVersion", + "version": 1 + }, + { + "id": "samsungce.washerOperatingState", + "version": 1 + } + ], + "categories": [ + { + "name": "Washer", + "categoryType": "manufacturer" + } + ], + "optional": false + }, + { + "id": "sub", + "label": "sub", + "capabilities": [ + { + "id": "ocf", + "version": 1 + }, + { + "id": "refresh", + "version": 1 + }, + { + "id": "switch", + "version": 1 + }, + { + "id": "remoteControlStatus", + "version": 1 + }, + { + "id": "washerOperatingState", + "version": 1 + }, + { + "id": "samsungce.driverVersion", + "version": 1 + }, + { + "id": "samsungce.washerOperatingState", + "version": 1 + } + ], + "categories": [ + { + "name": "Other", + "categoryType": "manufacturer" + } + ], + "optional": false + } + ], + "createTime": "2025-11-14T02:27:38.701Z", + "profile": { + "id": "b238b509-7dac-3117-b872-5e30b1efdd34" + }, + "ocf": { + "ocfDeviceType": "oic.d.washer", + "name": "Washer", + "specVersion": "core.1.1.0", + "verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0", + "manufacturerName": "Samsung Electronics", + "modelNumber": "TP6X_WV60M9900AV|20198041|20020001001111060100000000000000", + "vendorId": "DA-WM-WM-100002", + "lastSignupTime": "2025-11-14T02:27:38.459592109Z", + "transferCandidate": false, + "additionalAuthCodeRequired": false + }, + "type": "OCF", + "restrictionTier": 0, + "allowed": null, + "executionContext": "CLOUD", + "relationships": [] + } + ], + "_links": {} +} diff --git a/tests/components/smartthings/snapshots/test_binary_sensor.ambr b/tests/components/smartthings/snapshots/test_binary_sensor.ambr index c68d1359c411a..392defbb2b32b 100644 --- a/tests/components/smartthings/snapshots/test_binary_sensor.ambr +++ b/tests/components/smartthings/snapshots/test_binary_sensor.ambr @@ -2765,6 +2765,103 @@ 'state': 'off', }) # --- +# name: test_all_entities[da_wm_wm_100002][binary_sensor.washer_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.washer_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_switch_switch_switch', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][binary_sensor.washer_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Washer Power', + }), + 'context': , + 'entity_id': 'binary_sensor.washer_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_all_entities[da_wm_wm_100002][binary_sensor.washer_remote_control-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.washer_remote_control', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Remote control', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'remote_control', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_remoteControlStatus_remoteControlEnabled_remoteControlEnabled', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][binary_sensor.washer_remote_control-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Washer Remote control', + }), + 'context': , + 'entity_id': 'binary_sensor.washer_remote_control', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- # name: test_all_entities[ecobee_sensor][binary_sensor.child_bedroom_motion-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/smartthings/snapshots/test_init.ambr b/tests/components/smartthings/snapshots/test_init.ambr index f4ad7c4bce482..69af874582dcf 100644 --- a/tests/components/smartthings/snapshots/test_init.ambr +++ b/tests/components/smartthings/snapshots/test_init.ambr @@ -1242,6 +1242,37 @@ 'via_device_id': None, }) # --- +# name: test_devices[da_wm_wm_100002] + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'config_entries_subentries': , + 'configuration_url': 'https://account.smartthings.com', + 'connections': set({ + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': None, + 'id': , + 'identifiers': set({ + tuple( + 'smartthings', + 'C097276D-C8D4-0000-0000-000000000000', + ), + }), + 'labels': set({ + }), + 'manufacturer': 'Samsung Electronics', + 'model': 'TP6X_WV60M9900AV', + 'model_id': None, + 'name': 'Washer', + 'name_by_user': None, + 'primary_config_entry': , + 'serial_number': None, + 'sw_version': None, + 'via_device_id': None, + }) +# --- # name: test_devices[ecobee_sensor] DeviceRegistryEntrySnapshot({ 'area_id': None, diff --git a/tests/components/smartthings/snapshots/test_select.ambr b/tests/components/smartthings/snapshots/test_select.ambr index e8c92b3bfcd18..16956195e2449 100644 --- a/tests/components/smartthings/snapshots/test_select.ambr +++ b/tests/components/smartthings/snapshots/test_select.ambr @@ -1146,3 +1146,62 @@ 'state': 'stop', }) # --- +# name: test_all_entities[da_wm_wm_100002][select.washer-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'run', + 'pause', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'select', + 'entity_category': None, + 'entity_id': 'select.washer', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'operating_state', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][select.washer-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Washer', + 'options': list([ + 'run', + 'pause', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'select.washer', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'run', + }) +# --- diff --git a/tests/components/smartthings/snapshots/test_sensor.ambr b/tests/components/smartthings/snapshots/test_sensor.ambr index e2e32bdeac3e8..2894f1b3193ec 100644 --- a/tests/components/smartthings/snapshots/test_sensor.ambr +++ b/tests/components/smartthings/snapshots/test_sensor.ambr @@ -13119,6 +13119,201 @@ 'state': 'stop', }) # --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_completion_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_completion_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Completion time', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'completion_time', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_washerOperatingState_completionTime_completionTime', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_completion_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'timestamp', + 'friendly_name': 'Washer Completion time', + }), + 'context': , + 'entity_id': 'sensor.washer_completion_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2025-11-14T02:32:39+00:00', + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_job_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'air_wash', + 'ai_rinse', + 'ai_spin', + 'ai_wash', + 'cooling', + 'delay_wash', + 'drying', + 'finish', + 'none', + 'pre_wash', + 'rinse', + 'spin', + 'wash', + 'weight_sensing', + 'wrinkle_prevent', + 'freeze_protection', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_job_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Job state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_job_state', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_washerOperatingState_washerJobState_washerJobState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_job_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washer Job state', + 'options': list([ + 'air_wash', + 'ai_rinse', + 'ai_spin', + 'ai_wash', + 'cooling', + 'delay_wash', + 'drying', + 'finish', + 'none', + 'pre_wash', + 'rinse', + 'spin', + 'wash', + 'weight_sensing', + 'wrinkle_prevent', + 'freeze_protection', + ]), + }), + 'context': , + 'entity_id': 'sensor.washer_job_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'spin', + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_machine_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_machine_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Machine state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_machine_state', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_machine_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washer Machine state', + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'sensor.washer_machine_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'run', + }) +# --- # name: test_all_entities[ecobee_sensor][sensor.child_bedroom_temperature-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ From 11d5d314cc42de916a6ad982cf2dbd1ac26adce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85ke=20Strandberg?= Date: Sun, 16 Nov 2025 12:12:45 +0100 Subject: [PATCH 4/9] Fix type hints in miele tests (#156657) --- tests/components/miele/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/components/miele/__init__.py b/tests/components/miele/__init__.py index 2e75470c4a4a1..f58a9e7182d71 100644 --- a/tests/components/miele/__init__.py +++ b/tests/components/miele/__init__.py @@ -1,6 +1,7 @@ """Tests for the Miele integration.""" from collections.abc import Awaitable, Callable +from typing import Any from unittest.mock import AsyncMock from homeassistant.core import HomeAssistant @@ -16,11 +17,15 @@ async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) await hass.async_block_till_done() -def get_data_callback(mock: AsyncMock) -> Callable[[int], Awaitable[None]]: +def get_data_callback( + mock: AsyncMock, +) -> Callable[[dict[str, Any]], Awaitable[None]]: """Get registered callback for api data push.""" return mock.listen_events.call_args_list[0].kwargs.get("data_callback") -def get_actions_callback(mock: AsyncMock) -> Callable[[int], Awaitable[None]]: +def get_actions_callback( + mock: AsyncMock, +) -> Callable[[dict[str, Any]], Awaitable[None]]: """Get registered callback for api data push.""" return mock.listen_events.call_args_list[0].kwargs.get("actions_callback") From cf1c1294d364c15d70f2da0abbc30c6a9b6c43f3 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:16:17 +0100 Subject: [PATCH 5/9] Bump adguardhome to 0.8.1 (#156679) --- homeassistant/components/adguard/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/adguard/manifest.json b/homeassistant/components/adguard/manifest.json index 4729cf1e60064..023b1d2e24f88 100644 --- a/homeassistant/components/adguard/manifest.json +++ b/homeassistant/components/adguard/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "local_polling", "loggers": ["adguardhome"], - "requirements": ["adguardhome==0.8.0"] + "requirements": ["adguardhome==0.8.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index c3383df089072..4bde1814334bf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -145,7 +145,7 @@ adb-shell[async]==0.4.4 adext==0.4.4 # homeassistant.components.adguard -adguardhome==0.8.0 +adguardhome==0.8.1 # homeassistant.components.advantage_air advantage-air==0.4.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 042a052a23831..9b485f97b71ad 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -133,7 +133,7 @@ adb-shell[async]==0.4.4 adext==0.4.4 # homeassistant.components.adguard -adguardhome==0.8.0 +adguardhome==0.8.1 # homeassistant.components.advantage_air advantage-air==0.4.4 From 008bb85c59c3f02f42d5937b7711d866af5d436f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85ke=20Strandberg?= Date: Sun, 16 Nov 2025 12:25:28 +0100 Subject: [PATCH 6/9] Mock arguments in senz tests (#156677) --- tests/components/senz/conftest.py | 4 ++-- tests/components/senz/test_init.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/components/senz/conftest.py b/tests/components/senz/conftest.py index df1ab5d9c4db9..1259981277fed 100644 --- a/tests/components/senz/conftest.py +++ b/tests/components/senz/conftest.py @@ -3,7 +3,7 @@ from collections.abc import Generator import time from typing import Any -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from aiosenz import Account, Thermostat import pytest @@ -92,7 +92,7 @@ def mock_senz_client(account_fixture, device_fixture) -> Generator[MagicMock]: client.get_account.return_value = Account(account_fixture) client.get_thermostats.return_value = [ - Thermostat(device, None) for device in device_fixture + Thermostat(device, Mock()) for device in device_fixture ] yield client diff --git a/tests/components/senz/test_init.py b/tests/components/senz/test_init.py index 1dad116d8347d..9908fa3b5c18c 100644 --- a/tests/components/senz/test_init.py +++ b/tests/components/senz/test_init.py @@ -2,7 +2,7 @@ from http import HTTPStatus import time -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from aiosenz import TOKEN_ENDPOINT from httpx import HTTPStatusError, RequestError @@ -129,7 +129,7 @@ async def test_expired_token_refresh_failure( ( HTTPStatusError( message="Exception", - request=None, + request=Mock(), response=MagicMock(status_code=HTTPStatus.UNAUTHORIZED), ), ConfigEntryState.SETUP_ERROR, @@ -137,7 +137,7 @@ async def test_expired_token_refresh_failure( ( HTTPStatusError( message="Exception", - request=None, + request=Mock(), response=MagicMock(status_code=HTTPStatus.FORBIDDEN), ), ConfigEntryState.SETUP_RETRY, From ba034c6c8ce948df19bc7a8c65e999a5ca003aa7 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:26:33 +0100 Subject: [PATCH 7/9] Add alarm_state to Tuya siren alarm (#151221) --- homeassistant/components/tuya/const.py | 1 + homeassistant/components/tuya/select.py | 5 ++ homeassistant/components/tuya/strings.json | 9 +++ .../tuya/snapshots/test_select.ambr | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/homeassistant/components/tuya/const.py b/homeassistant/components/tuya/const.py index edd807c980fcc..1e7648ab01c43 100644 --- a/homeassistant/components/tuya/const.py +++ b/homeassistant/components/tuya/const.py @@ -607,6 +607,7 @@ class DPCode(StrEnum): ALARM_DELAY_TIME = "alarm_delay_time" ALARM_MESSAGE = "alarm_message" ALARM_MSG = "alarm_msg" + ALARM_STATE = "alarm_state" ALARM_SWITCH = "alarm_switch" # Alarm switch ALARM_TIME = "alarm_time" # Alarm time ALARM_VOLUME = "alarm_volume" # Alarm volume diff --git a/homeassistant/components/tuya/select.py b/homeassistant/components/tuya/select.py index b631caffc7eab..3c84885f5e28a 100644 --- a/homeassistant/components/tuya/select.py +++ b/homeassistant/components/tuya/select.py @@ -207,6 +207,11 @@ ), ), DeviceCategory.SGBJ: ( + SelectEntityDescription( + key=DPCode.ALARM_STATE, + translation_key="siren_mode", + entity_category=EntityCategory.CONFIG, + ), SelectEntityDescription( key=DPCode.ALARM_VOLUME, translation_key="volume", diff --git a/homeassistant/components/tuya/strings.json b/homeassistant/components/tuya/strings.json index c95dea753ea64..7fa7d6e136f14 100644 --- a/homeassistant/components/tuya/strings.json +++ b/homeassistant/components/tuya/strings.json @@ -494,6 +494,15 @@ "power_on": "[%key:common::state::on%]" } }, + "siren_mode": { + "name": "Siren mode", + "state": { + "alarm_light": "Light", + "alarm_sound": "Sound", + "alarm_sound_light": "Sound & light", + "normal": "[%key:common::state::normal%]" + } + }, "target_humidity": { "name": "Target humidity" }, diff --git a/tests/components/tuya/snapshots/test_select.ambr b/tests/components/tuya/snapshots/test_select.ambr index cb343fce8c984..da473187b8852 100644 --- a/tests/components/tuya/snapshots/test_select.ambr +++ b/tests/components/tuya/snapshots/test_select.ambr @@ -4389,6 +4389,67 @@ 'state': 'power_on', }) # --- +# name: test_platform_setup_and_discovery[select.siren_siren_mode-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'alarm_sound', + 'alarm_light', + 'alarm_sound_light', + 'normal', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'select', + 'entity_category': , + 'entity_id': 'select.siren_siren_mode', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Siren mode', + 'platform': 'tuya', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'siren_mode', + 'unique_id': 'tuya.okwwus27jhqqe2mijbgsalarm_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_platform_setup_and_discovery[select.siren_siren_mode-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Siren Siren mode', + 'options': list([ + 'alarm_sound', + 'alarm_light', + 'alarm_sound_light', + 'normal', + ]), + }), + 'context': , + 'entity_id': 'select.siren_siren_mode', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'normal', + }) +# --- # name: test_platform_setup_and_discovery[select.siren_veranda_volume-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ From a0e0549d90755090d6827bee21f220c8d763299b Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Sun, 16 Nov 2025 15:00:51 +0100 Subject: [PATCH 8/9] Fix missing `temperature_delta` device class translations (#156685) --- homeassistant/components/mqtt/strings.json | 1 + homeassistant/components/random/strings.json | 1 + homeassistant/components/scrape/strings.json | 1 + homeassistant/components/sql/strings.json | 1 + homeassistant/components/template/strings.json | 1 + 5 files changed, 5 insertions(+) diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 21a88bb50b1c9..1335f58cbd4df 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -1312,6 +1312,7 @@ "speed": "[%key:component::sensor::entity_component::speed::name%]", "sulphur_dioxide": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]", "temperature": "[%key:component::sensor::entity_component::temperature::name%]", + "temperature_delta": "[%key:component::sensor::entity_component::temperature_delta::name%]", "timestamp": "[%key:component::sensor::entity_component::timestamp::name%]", "volatile_organic_compounds": "[%key:component::sensor::entity_component::volatile_organic_compounds::name%]", "volatile_organic_compounds_parts": "[%key:component::sensor::entity_component::volatile_organic_compounds_parts::name%]", diff --git a/homeassistant/components/random/strings.json b/homeassistant/components/random/strings.json index b0c4b3296969a..db6b55429368c 100644 --- a/homeassistant/components/random/strings.json +++ b/homeassistant/components/random/strings.json @@ -128,6 +128,7 @@ "speed": "[%key:component::sensor::entity_component::speed::name%]", "sulphur_dioxide": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]", "temperature": "[%key:component::sensor::entity_component::temperature::name%]", + "temperature_delta": "[%key:component::sensor::entity_component::temperature_delta::name%]", "timestamp": "[%key:component::sensor::entity_component::timestamp::name%]", "volatile_organic_compounds": "[%key:component::sensor::entity_component::volatile_organic_compounds::name%]", "volatile_organic_compounds_parts": "[%key:component::sensor::entity_component::volatile_organic_compounds_parts::name%]", diff --git a/homeassistant/components/scrape/strings.json b/homeassistant/components/scrape/strings.json index 8a849ac62886c..4aeae3ce68520 100644 --- a/homeassistant/components/scrape/strings.json +++ b/homeassistant/components/scrape/strings.json @@ -186,6 +186,7 @@ "speed": "[%key:component::sensor::entity_component::speed::name%]", "sulphur_dioxide": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]", "temperature": "[%key:component::sensor::entity_component::temperature::name%]", + "temperature_delta": "[%key:component::sensor::entity_component::temperature_delta::name%]", "timestamp": "[%key:component::sensor::entity_component::timestamp::name%]", "volatile_organic_compounds": "[%key:component::sensor::entity_component::volatile_organic_compounds::name%]", "volatile_organic_compounds_parts": "[%key:component::sensor::entity_component::volatile_organic_compounds_parts::name%]", diff --git a/homeassistant/components/sql/strings.json b/homeassistant/components/sql/strings.json index 00f8c1fc81517..92f68d17d0e73 100644 --- a/homeassistant/components/sql/strings.json +++ b/homeassistant/components/sql/strings.json @@ -161,6 +161,7 @@ "speed": "[%key:component::sensor::entity_component::speed::name%]", "sulphur_dioxide": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]", "temperature": "[%key:component::sensor::entity_component::temperature::name%]", + "temperature_delta": "[%key:component::sensor::entity_component::temperature_delta::name%]", "timestamp": "[%key:component::sensor::entity_component::timestamp::name%]", "volatile_organic_compounds": "[%key:component::sensor::entity_component::volatile_organic_compounds::name%]", "volatile_organic_compounds_parts": "[%key:component::sensor::entity_component::volatile_organic_compounds_parts::name%]", diff --git a/homeassistant/components/template/strings.json b/homeassistant/components/template/strings.json index a94703ed54f17..9d9ec1237642d 100644 --- a/homeassistant/components/template/strings.json +++ b/homeassistant/components/template/strings.json @@ -1111,6 +1111,7 @@ "speed": "[%key:component::sensor::entity_component::speed::name%]", "sulphur_dioxide": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]", "temperature": "[%key:component::sensor::entity_component::temperature::name%]", + "temperature_delta": "[%key:component::sensor::entity_component::temperature_delta::name%]", "timestamp": "[%key:component::sensor::entity_component::timestamp::name%]", "volatile_organic_compounds": "[%key:component::sensor::entity_component::volatile_organic_compounds::name%]", "volatile_organic_compounds_parts": "[%key:component::sensor::entity_component::volatile_organic_compounds_parts::name%]", From f695fb4d51dc8118feb828e8b7b42131d22c3f8b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 16 Nov 2025 09:12:44 -0600 Subject: [PATCH 9/9] Bump dbus-fast to 2.45.1 (#156691) --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 0ed45315c93c7..50a8d674f771e 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -20,7 +20,7 @@ "bluetooth-adapters==2.1.0", "bluetooth-auto-recovery==1.5.3", "bluetooth-data-tools==1.28.4", - "dbus-fast==2.45.0", + "dbus-fast==2.45.1", "habluetooth==5.7.0" ] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index b108e08b805dd..d2fba4c40fd67 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -30,7 +30,7 @@ certifi>=2021.5.30 ciso8601==2.3.3 cronsim==2.7 cryptography==46.0.2 -dbus-fast==2.45.0 +dbus-fast==2.45.1 file-read-backwards==2.0.0 fnv-hash-fast==1.6.0 go2rtc-client==0.2.1 diff --git a/requirements_all.txt b/requirements_all.txt index 4bde1814334bf..9732f92d64536 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -772,7 +772,7 @@ datadog==0.52.0 datapoint==0.12.1 # homeassistant.components.bluetooth -dbus-fast==2.45.0 +dbus-fast==2.45.1 # homeassistant.components.debugpy debugpy==1.8.16 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9b485f97b71ad..7f0e5e8f0ce3d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -675,7 +675,7 @@ datadog==0.52.0 datapoint==0.12.1 # homeassistant.components.bluetooth -dbus-fast==2.45.0 +dbus-fast==2.45.1 # homeassistant.components.debugpy debugpy==1.8.16