diff --git a/homeassistant/components/adguard/manifest.json b/homeassistant/components/adguard/manifest.json index 4729cf1e60064b..023b1d2e24f888 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/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 0ed45315c93c78..50a8d674f771e3 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/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 21a88bb50b1c90..1335f58cbd4dfa 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 b0c4b3296969a1..db6b55429368c4 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/saunum/diagnostics.py b/homeassistant/components/saunum/diagnostics.py new file mode 100644 index 00000000000000..2f348dfa50cf65 --- /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 c7a52ef2f850c5..b18fb9e58a6f51 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/homeassistant/components/scrape/strings.json b/homeassistant/components/scrape/strings.json index 8a849ac62886c1..4aeae3ce685209 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 00f8c1fc81517c..92f68d17d0e737 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 a94703ed54f175..9d9ec1237642d4 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%]", diff --git a/homeassistant/components/tuya/const.py b/homeassistant/components/tuya/const.py index edd807c980fcc9..1e7648ab01c430 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 b631caffc7eab8..3c84885f5e28a6 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 c95dea753ea644..7fa7d6e136f14e 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/homeassistant/components/xbox/browse_media.py b/homeassistant/components/xbox/browse_media.py index 1a66a0d4956a9b..ab311e244b5ab1 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 410dcabba39159..94c4636afa3d9b 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: diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index b108e08b805dd4..d2fba4c40fd67a 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 c3383df0890727..9732f92d645364 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 @@ -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 042a052a238316..7f0e5e8f0ce3db 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 @@ -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 diff --git a/tests/components/miele/__init__.py b/tests/components/miele/__init__.py index 2e75470c4a4a1a..f58a9e7182d71e 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") diff --git a/tests/components/saunum/snapshots/test_diagnostics.ambr b/tests/components/saunum/snapshots/test_diagnostics.ambr new file mode 100644 index 00000000000000..1e1fce24d29d75 --- /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 00000000000000..a67a9379471090 --- /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 + ) diff --git a/tests/components/senz/conftest.py b/tests/components/senz/conftest.py index df1ab5d9c4db98..1259981277fed6 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 1dad116d8347d2..9908fa3b5c18c9 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, diff --git a/tests/components/smartthings/conftest.py b/tests/components/smartthings/conftest.py index 7840cf40777677..fb6dcedef4030e 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 00000000000000..0b8d0389194520 --- /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 00000000000000..91f4031b516abb --- /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 c68d1359c411a9..392defbb2b32b6 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 f4ad7c4bce482d..69af874582dcf1 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 e8c92b3bfcd18f..16956195e2449b 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 e2e32bdeac3e8d..2894f1b3193ecb 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({ diff --git a/tests/components/tuya/snapshots/test_select.ambr b/tests/components/tuya/snapshots/test_select.ambr index cb343fce8c984c..da473187b88524 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({