From 30ef090d9ef06ec372d8b01d87297d88b186539f Mon Sep 17 00:00:00 2001 From: Samuel Spagl <46893256+samuelspagl@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:45:32 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=F0=9F=90=9B:=20add=20volume=20`sensor?= =?UTF-8?q?`=20entity,=20fix=20sound=5Fmode/source=20in=20`media=5Fplayer`?= =?UTF-8?q?=20entity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This merge-request adds new functionality as well as fixes a minor bug. For more information see #9. - New sensor entity added - Disabled extra_state_attributes to correctly display available sources/soundmodes in the media_player configuration. --------- Co-authored-by: samuelspagl --- .gitignore | 1 + CHANGELOG.md | 18 +++++++ .../samsung_soundbar/__init__.py | 26 ++++------ .../samsung_soundbar/manifest.json | 2 +- .../samsung_soundbar/media_player.py | 12 +++-- custom_components/samsung_soundbar/sensor.py | 49 +++++++++++++++++++ 6 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 custom_components/samsung_soundbar/sensor.py diff --git a/.gitignore b/.gitignore index cc66de8..d9c982e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__/ *.py[cod] *$py.class +.DS_store # C extensions *.so diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29..636180f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## [0.2.0] Add volume sensor - 2024-02-08 + +### Added + +- add new sensor entity for the volume + +### Fix + +- remove `extra_state_attributes` from `media_player` instance: + The property caused some unwanted side-effects on some systems. + +## [0.1.0] 🎉 First Version + +### Added + +- first version, gonna extend this Changelog sometime :D \ No newline at end of file diff --git a/custom_components/samsung_soundbar/__init__.py b/custom_components/samsung_soundbar/__init__.py index 31c5c48..09d9a4f 100644 --- a/custom_components/samsung_soundbar/__init__.py +++ b/custom_components/samsung_soundbar/__init__.py @@ -6,19 +6,14 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from pysmartthings import SmartThings from .api_extension.SoundbarDevice import SoundbarDevice -from .const import ( - CONF_ENTRY_API_KEY, - CONF_ENTRY_DEVICE_ID, - CONF_ENTRY_DEVICE_NAME, - CONF_ENTRY_MAX_VOLUME, - SUPPORTED_DOMAINS, - DOMAIN, -) +from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID, + CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN, + SUPPORTED_DOMAINS) from .models import DeviceConfig, SoundbarConfig _LOGGER = logging.getLogger(__name__) -PLATFORMS = ["media_player", "switch", "image", "number", "select"] +PLATFORMS = ["media_player", "switch", "image", "number", "select", "sensor"] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -47,15 +42,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ) session = async_get_clientsession(hass) soundbar_device = SoundbarDevice( - smart_things_device, - session, - entry.data.get(CONF_ENTRY_MAX_VOLUME), - entry.data.get(CONF_ENTRY_DEVICE_NAME), - ) + smart_things_device, + session, + entry.data.get(CONF_ENTRY_MAX_VOLUME), + entry.data.get(CONF_ENTRY_DEVICE_NAME), + ) await soundbar_device.update() domain_config.devices[entry.data.get(CONF_ENTRY_DEVICE_ID)] = DeviceConfig( - entry.data, - soundbar_device + entry.data, soundbar_device ) _LOGGER.info(f"[{DOMAIN}] after initializing Soundbar device") diff --git a/custom_components/samsung_soundbar/manifest.json b/custom_components/samsung_soundbar/manifest.json index aa8db7f..2772074 100644 --- a/custom_components/samsung_soundbar/manifest.json +++ b/custom_components/samsung_soundbar/manifest.json @@ -8,5 +8,5 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/samuelspagl/ha_samsung_soundbar/issues", "requirements": ["pysmartthings"], - "version": "0.1.0" + "version": "0.2.0" } diff --git a/custom_components/samsung_soundbar/media_player.py b/custom_components/samsung_soundbar/media_player.py index 40a7840..9efcbda 100644 --- a/custom_components/samsung_soundbar/media_player.py +++ b/custom_components/samsung_soundbar/media_player.py @@ -1,5 +1,5 @@ import logging -from typing import Mapping, Any +from typing import Any, Mapping from homeassistant.components.media_player import ( DEVICE_CLASS_SPEAKER, @@ -20,7 +20,6 @@ from homeassistant.components.media_player.const import ( from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity import DeviceInfo, generate_entity_id -from .models import DeviceConfig from .api_extension.SoundbarDevice import SoundbarDevice from .const import ( CONF_ENTRY_API_KEY, @@ -29,6 +28,7 @@ from .const import ( CONF_ENTRY_MAX_VOLUME, DOMAIN, ) +from .models import DeviceConfig _LOGGER = logging.getLogger(__name__) @@ -191,6 +191,8 @@ class SmartThingsSoundbarMediaPlayer(MediaPlayerEntity): async def async_media_stop(self): await self.device.media_stop() - @property - def extra_state_attributes(self) -> Mapping[str, Any] | None: - return self.device.retrieve_data + # This property can be uncommented for some extra_attributes + # Still enabling this can cause side-effects. + # @property + # def extra_state_attributes(self) -> Mapping[str, Any] | None: + # return {"device_information": self.device.retrieve_data} diff --git a/custom_components/samsung_soundbar/sensor.py b/custom_components/samsung_soundbar/sensor.py new file mode 100644 index 0000000..6712b85 --- /dev/null +++ b/custom_components/samsung_soundbar/sensor.py @@ -0,0 +1,49 @@ +import logging + +from homeassistant.components.sensor import SensorEntity, SensorDeviceClass, SensorStateClass + +from .models import DeviceConfig +from .api_extension.SoundbarDevice import SoundbarDevice +from .const import CONF_ENTRY_DEVICE_ID, DOMAIN +from homeassistant.helpers.entity import DeviceInfo + +_LOGGER = logging.getLogger(__name__) + +async def async_setup_entry(hass, config_entry, async_add_entities): + domain_data = hass.data[DOMAIN] + entities = [] + for key in domain_data.devices: + device_config: DeviceConfig = domain_data.devices[key] + device = device_config.device + + if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID): + entities.append( + VolumeSensor(device, "volume_level") + ) + async_add_entities(entities) + return True + + + +class VolumeSensor(SensorEntity): + def __init__(self, device: SoundbarDevice, append_unique_id: str): + self.entity_id = f"sensor.{device.device_name}_{append_unique_id}" + self.__device = device + self._attr_unique_id = f"{device.device_id}_sw_{append_unique_id}" + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, self.__device.device_id)}, + name=self.__device.device_name, + manufacturer=self.__device.manufacturer, + model=self.__device.model, + sw_version=self.__device.firmware_version, + ) + self.__append_unique_id = append_unique_id + + _attr_device_class = SensorDeviceClass.VOLUME + + def update(self) -> None: + """Fetch new state data for the sensor. + + This is the only method that should fetch new data for Home Assistant. + """ + self._attr_native_value = self.__device.device.status.volume