From d8d9449e2b948483d83329ec4d95cd2c75e4187d Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sat, 19 Apr 2025 09:53:31 +0200 Subject: [PATCH] Fix SmartThings soundbar without media playback (#143170) --- .../components/smartthings/media_player.py | 44 ++-- .../components/smartthings/sensor.py | 8 +- .../components/smartthings/switch.py | 1 - tests/components/smartthings/conftest.py | 1 + .../device_status/vd_network_audio_003s.json | 231 ++++++++++++++++++ .../devices/vd_network_audio_003s.json | 115 +++++++++ .../smartthings/snapshots/test_init.ambr | 33 +++ .../snapshots/test_media_player.ambr | 50 ++++ 8 files changed, 455 insertions(+), 28 deletions(-) create mode 100644 tests/components/smartthings/fixtures/device_status/vd_network_audio_003s.json create mode 100644 tests/components/smartthings/fixtures/devices/vd_network_audio_003s.json diff --git a/homeassistant/components/smartthings/media_player.py b/homeassistant/components/smartthings/media_player.py index 9a676d2efb6..335e8255ae4 100644 --- a/homeassistant/components/smartthings/media_player.py +++ b/homeassistant/components/smartthings/media_player.py @@ -23,7 +23,6 @@ from .entity import SmartThingsEntity MEDIA_PLAYER_CAPABILITIES = ( Capability.AUDIO_MUTE, Capability.AUDIO_VOLUME, - Capability.MEDIA_PLAYBACK, ) CONTROLLABLE_SOURCES = ["bluetooth", "wifi"] @@ -100,27 +99,25 @@ class SmartThingsMediaPlayer(SmartThingsEntity, MediaPlayerEntity): ) def _determine_features(self) -> MediaPlayerEntityFeature: - flags = MediaPlayerEntityFeature(0) - playback_commands = self.get_attribute_value( - Capability.MEDIA_PLAYBACK, Attribute.SUPPORTED_PLAYBACK_COMMANDS + flags = ( + MediaPlayerEntityFeature.VOLUME_SET + | MediaPlayerEntityFeature.VOLUME_STEP + | MediaPlayerEntityFeature.VOLUME_MUTE ) - if "play" in playback_commands: - flags |= MediaPlayerEntityFeature.PLAY - if "pause" in playback_commands: - flags |= MediaPlayerEntityFeature.PAUSE - if "stop" in playback_commands: - flags |= MediaPlayerEntityFeature.STOP - if "rewind" in playback_commands: - flags |= MediaPlayerEntityFeature.PREVIOUS_TRACK - if "fastForward" in playback_commands: - flags |= MediaPlayerEntityFeature.NEXT_TRACK - if self.supports_capability(Capability.AUDIO_VOLUME): - flags |= ( - MediaPlayerEntityFeature.VOLUME_SET - | MediaPlayerEntityFeature.VOLUME_STEP + if self.supports_capability(Capability.MEDIA_PLAYBACK): + playback_commands = self.get_attribute_value( + Capability.MEDIA_PLAYBACK, Attribute.SUPPORTED_PLAYBACK_COMMANDS ) - if self.supports_capability(Capability.AUDIO_MUTE): - flags |= MediaPlayerEntityFeature.VOLUME_MUTE + if "play" in playback_commands: + flags |= MediaPlayerEntityFeature.PLAY + if "pause" in playback_commands: + flags |= MediaPlayerEntityFeature.PAUSE + if "stop" in playback_commands: + flags |= MediaPlayerEntityFeature.STOP + if "rewind" in playback_commands: + flags |= MediaPlayerEntityFeature.PREVIOUS_TRACK + if "fastForward" in playback_commands: + flags |= MediaPlayerEntityFeature.NEXT_TRACK if self.supports_capability(Capability.SWITCH): flags |= ( MediaPlayerEntityFeature.TURN_ON | MediaPlayerEntityFeature.TURN_OFF @@ -270,6 +267,13 @@ class SmartThingsMediaPlayer(SmartThingsEntity, MediaPlayerEntity): def state(self) -> MediaPlayerState | None: """State of the media player.""" if self.supports_capability(Capability.SWITCH): + if not self.supports_capability(Capability.MEDIA_PLAYBACK): + if ( + self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) + == "on" + ): + return MediaPlayerState.ON + return MediaPlayerState.OFF if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on": if ( self.source is not None diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index e081f35d0e0..d5a465b8ccc 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -194,13 +194,7 @@ CAPABILITY_TO_SENSORS: dict[ native_unit_of_measurement=PERCENTAGE, deprecated=( lambda status: "media_player" - if all( - capability in status - for capability in ( - Capability.AUDIO_MUTE, - Capability.MEDIA_PLAYBACK, - ) - ) + if Capability.AUDIO_MUTE in status else None ), ) diff --git a/homeassistant/components/smartthings/switch.py b/homeassistant/components/smartthings/switch.py index 4e62957d3d4..ff53082ac7c 100644 --- a/homeassistant/components/smartthings/switch.py +++ b/homeassistant/components/smartthings/switch.py @@ -38,7 +38,6 @@ AC_CAPABILITIES = ( MEDIA_PLAYER_CAPABILITIES = ( Capability.AUDIO_MUTE, Capability.AUDIO_VOLUME, - Capability.MEDIA_PLAYBACK, ) diff --git a/tests/components/smartthings/conftest.py b/tests/components/smartthings/conftest.py index 56789f5b91a..aa29a610620 100644 --- a/tests/components/smartthings/conftest.py +++ b/tests/components/smartthings/conftest.py @@ -109,6 +109,7 @@ def mock_smartthings() -> Generator[AsyncMock]: "da_ref_normal_01011", "da_ref_normal_01001", "vd_network_audio_002s", + "vd_network_audio_003s", "vd_sensor_light_2023", "iphone", "da_sac_ehs_000001_sub", diff --git a/tests/components/smartthings/fixtures/device_status/vd_network_audio_003s.json b/tests/components/smartthings/fixtures/device_status/vd_network_audio_003s.json new file mode 100644 index 00000000000..e635f6c793a --- /dev/null +++ b/tests/components/smartthings/fixtures/device_status/vd_network_audio_003s.json @@ -0,0 +1,231 @@ +{ + "components": { + "main": { + "samsungvd.soundFrom": { + "mode": { + "value": 29, + "timestamp": "2025-04-05T13:51:47.865Z" + }, + "detailName": { + "value": "None", + "timestamp": "2025-04-05T13:51:50.230Z" + } + }, + "audioVolume": { + "volume": { + "value": 6, + "unit": "%", + "timestamp": "2025-04-17T11:17:25.272Z" + } + }, + "samsungvd.audioGroupInfo": { + "role": { + "value": null + }, + "channel": { + "value": null + }, + "status": { + "value": null + } + }, + "refresh": {}, + "audioNotification": {}, + "execute": { + "data": { + "value": null + } + }, + "samsungvd.audioInputSource": { + "supportedInputSources": { + "value": ["D.IN", "BT", "WIFI"], + "timestamp": "2025-03-18T19:11:54.071Z" + }, + "inputSource": { + "value": "D.IN", + "timestamp": "2025-04-17T11:18:02.048Z" + } + }, + "switch": { + "switch": { + "value": "off", + "timestamp": "2025-04-17T14:42:04.704Z" + } + }, + "sec.wifiConfiguration": { + "autoReconnection": { + "value": true, + "timestamp": "2025-03-18T19:11:54.484Z" + }, + "minVersion": { + "value": "1.0", + "timestamp": "2025-03-18T19:11:54.484Z" + }, + "supportedWiFiFreq": { + "value": ["2.4G", "5G"], + "timestamp": "2025-03-18T19:11:54.484Z" + }, + "supportedAuthType": { + "value": [ + "OPEN", + "WEP", + "WPA-PSK", + "WPA2-PSK", + "EAP", + "SAE", + "OWE", + "FT-PSK" + ], + "timestamp": "2025-03-18T19:11:54.484Z" + }, + "protocolType": { + "value": ["ble_ocf"], + "timestamp": "2025-03-18T19:11:54.484Z" + } + }, + "ocf": { + "st": { + "value": "1970-01-01T00:00:47Z", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mndt": { + "value": "2024-01-01", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnfv": { + "value": "SAT-MT8532D24WWC-1016.0", + "timestamp": "2025-02-21T16:47:38.134Z" + }, + "mnhw": { + "value": "", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "di": { + "value": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnsl": { + "value": "", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "dmv": { + "value": "res.1.1.0,sh.1.1.0", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "n": { + "value": "Soundbar", + "timestamp": "2025-02-21T16:47:38.134Z" + }, + "mnmo": { + "value": "HW-S60D", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "vid": { + "value": "VD-NetworkAudio-003S", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnmn": { + "value": "Samsung Electronics", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnml": { + "value": "", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnpv": { + "value": "8.0", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "mnos": { + "value": "Tizen", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "pi": { + "value": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6", + "timestamp": "2025-02-21T15:09:52.348Z" + }, + "icv": { + "value": "core.1.1.0", + "timestamp": "2025-02-21T15:09:52.348Z" + } + }, + "samsungvd.supportsFeatures": { + "mediaOutputSupported": { + "value": null + }, + "imeAdvSupported": { + "value": null + }, + "wifiUpdateSupport": { + "value": true, + "timestamp": "2025-03-18T19:11:53.853Z" + }, + "executableServiceList": { + "value": null + }, + "remotelessSupported": { + "value": null + }, + "artSupported": { + "value": null + }, + "mobileCamSupported": { + "value": null + } + }, + "sec.diagnosticsInformation": { + "logType": { + "value": ["errCode", "dump"], + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "endpoint": { + "value": "PIPER", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "minVersion": { + "value": "3.0", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "signinPermission": { + "value": null + }, + "setupId": { + "value": "301", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "protocolType": { + "value": "ble_ocf", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "tsId": { + "value": "VD02", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "mnId": { + "value": "0AJK", + "timestamp": "2025-03-18T19:11:54.336Z" + }, + "dumpType": { + "value": "file", + "timestamp": "2025-03-18T19:11:54.336Z" + } + }, + "audioMute": { + "mute": { + "value": "muted", + "timestamp": "2025-04-17T11:36:04.814Z" + } + }, + "samsungvd.thingStatus": { + "updatedTime": { + "value": 1744900925, + "timestamp": "2025-04-17T14:42:04.770Z" + }, + "status": { + "value": "Idle", + "timestamp": "2025-03-18T19:11:54.101Z" + } + } + } + } +} diff --git a/tests/components/smartthings/fixtures/devices/vd_network_audio_003s.json b/tests/components/smartthings/fixtures/devices/vd_network_audio_003s.json new file mode 100644 index 00000000000..428b0e635d5 --- /dev/null +++ b/tests/components/smartthings/fixtures/devices/vd_network_audio_003s.json @@ -0,0 +1,115 @@ +{ + "items": [ + { + "deviceId": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6", + "name": "Soundbar", + "label": "Soundbar", + "manufacturerName": "Samsung Electronics", + "presentationId": "VD-NetworkAudio-003S", + "deviceManufacturerCode": "Samsung Electronics", + "locationId": "6bdf6730-8167-488b-8645-d0c5046ff763", + "ownerId": "15f0ae72-da51-14e2-65cf-ef59ae867e7f", + "roomId": "3b0fe9a8-51d6-49cf-b64a-8a719013c0a7", + "deviceTypeName": "Samsung OCF Network Audio Player", + "components": [ + { + "id": "main", + "label": "main", + "capabilities": [ + { + "id": "ocf", + "version": 1 + }, + { + "id": "execute", + "version": 1 + }, + { + "id": "refresh", + "version": 1 + }, + { + "id": "switch", + "version": 1 + }, + { + "id": "audioVolume", + "version": 1 + }, + { + "id": "audioMute", + "version": 1 + }, + { + "id": "samsungvd.audioInputSource", + "version": 1 + }, + { + "id": "audioNotification", + "version": 1 + }, + { + "id": "samsungvd.soundFrom", + "version": 1 + }, + { + "id": "sec.diagnosticsInformation", + "version": 1 + }, + { + "id": "samsungvd.thingStatus", + "version": 1 + }, + { + "id": "samsungvd.supportsFeatures", + "version": 1 + }, + { + "id": "sec.wifiConfiguration", + "version": 1 + }, + { + "id": "samsungvd.audioGroupInfo", + "version": 1, + "ephemeral": true + } + ], + "categories": [ + { + "name": "NetworkAudio", + "categoryType": "manufacturer" + } + ], + "optional": false + } + ], + "createTime": "2025-02-21T14:25:21.843Z", + "profile": { + "id": "25504ad5-8563-3b07-8770-e52ad29a9c5a" + }, + "ocf": { + "ocfDeviceType": "oic.d.networkaudio", + "name": "Soundbar", + "specVersion": "core.1.1.0", + "verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0", + "manufacturerName": "Samsung Electronics", + "modelNumber": "HW-S60D", + "platformVersion": "8.0", + "platformOS": "Tizen", + "hwVersion": "", + "firmwareVersion": "SAT-MT8532D24WWC-1016.0", + "vendorId": "VD-NetworkAudio-003S", + "vendorResourceClientServerVersion": "4.0.26", + "lastSignupTime": "2025-03-18T19:11:51.176292902Z", + "transferCandidate": false, + "additionalAuthCodeRequired": false + }, + "type": "OCF", + "restrictionTier": 0, + "allowed": null, + "executionContext": "CLOUD", + "relationships": [] + } + ], + "_links": {} +} diff --git a/tests/components/smartthings/snapshots/test_init.ambr b/tests/components/smartthings/snapshots/test_init.ambr index 692207f4bb4..59ad2cff19b 100644 --- a/tests/components/smartthings/snapshots/test_init.ambr +++ b/tests/components/smartthings/snapshots/test_init.ambr @@ -1685,6 +1685,39 @@ 'via_device_id': None, }) # --- +# name: test_devices[vd_network_audio_003s] + 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': '', + 'id': , + 'identifiers': set({ + tuple( + 'smartthings', + 'a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6', + ), + }), + 'is_new': False, + 'labels': set({ + }), + 'manufacturer': 'Samsung Electronics', + 'model': 'HW-S60D', + 'model_id': None, + 'name': 'Soundbar', + 'name_by_user': None, + 'primary_config_entry': , + 'serial_number': None, + 'suggested_area': None, + 'sw_version': 'SAT-MT8532D24WWC-1016.0', + 'via_device_id': None, + }) +# --- # name: test_devices[vd_sensor_light_2023] DeviceRegistryEntrySnapshot({ 'area_id': None, diff --git a/tests/components/smartthings/snapshots/test_media_player.ambr b/tests/components/smartthings/snapshots/test_media_player.ambr index 83f9d19b9fa..8eca654abe3 100644 --- a/tests/components/smartthings/snapshots/test_media_player.ambr +++ b/tests/components/smartthings/snapshots/test_media_player.ambr @@ -231,6 +231,56 @@ 'state': 'on', }) # --- +# name: test_all_entities[vd_network_audio_003s][media_player.soundbar-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'media_player', + 'entity_category': None, + 'entity_id': 'media_player.soundbar', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': None, + 'platform': 'smartthings', + 'previous_unique_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6_main', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[vd_network_audio_003s][media_player.soundbar-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'speaker', + 'friendly_name': 'Soundbar', + 'supported_features': , + }), + 'context': , + 'entity_id': 'media_player.soundbar', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- # name: test_all_entities[vd_stv_2017_k][media_player.tv_samsung_8_series_49-entry] EntityRegistryEntrySnapshot({ 'aliases': set({