Compare commits
	
		
			9 Commits
		
	
	
		
			main
			...
			docs/enhan
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 058e8a92ab | |
|  | c80db28fff | |
|  | be963d25ce | |
|  | b102447764 | |
|  | 15474a698d | |
|  | 1dbf47c7c5 | |
|  | 58de8dae5a | |
|  | af02062a57 | |
|  | bd86e799e1 | 
|  | @ -1,32 +0,0 @@ | |||
| // For format details, see https://aka.ms/devcontainer.json. For config options, see the | ||||
| // README at: https://github.com/devcontainers/templates/tree/main/src/python | ||||
| { | ||||
| 	"name": "Python 3", | ||||
| 	// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile | ||||
| 	"image": "homeassistant/home-assistant:dev", | ||||
| 	"postCreateCommand": "scripts/setup", | ||||
| 	"forwardPorts": [ | ||||
|         8123 | ||||
|     ], | ||||
|     "portsAttributes": { | ||||
|         "8123": { | ||||
|             "label": "Home Assistant", | ||||
|             "onAutoForward": "notify" | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	// Features to add to the dev container. More info: https://containers.dev/features. | ||||
| 	// "features": {}, | ||||
| 
 | ||||
| 	// Use 'forwardPorts' to make a list of ports inside the container available locally. | ||||
| 	// "forwardPorts": [], | ||||
| 
 | ||||
| 	// Use 'postCreateCommand' to run commands after the container is created. | ||||
| 	// "postCreateCommand": "pip3 install --user -r requirements.txt", | ||||
| 
 | ||||
| 	// Configure tool-specific properties. | ||||
| 	// "customizations": {}, | ||||
| 
 | ||||
| 	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. | ||||
| 	// "remoteUser": "root" | ||||
| } | ||||
|  | @ -4,11 +4,6 @@ __pycache__/ | |||
| *$py.class | ||||
| .DS_store | ||||
| 
 | ||||
| config | ||||
| .vscode | ||||
| .ruff_cache | ||||
| 
 | ||||
| 
 | ||||
| # C extensions | ||||
| *.so | ||||
| .idea | ||||
|  |  | |||
							
								
								
									
										49
									
								
								CHANGELOG.md
								
								
								
								
							
							
						
						
									
										49
									
								
								CHANGELOG.md
								
								
								
								
							|  | @ -1,54 +1,5 @@ | |||
| # Changelog | ||||
| 
 | ||||
| ## [0.4.1] Media Mystique: The Great Data Disappearing Act! | ||||
| 
 | ||||
| ### Fixed | ||||
| 
 | ||||
| - Made media data (*track title*, *artist*, *length*) optional to acoomodate soundbars that don't provide this information (🥲) | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - Add translations for the english translation file | ||||
| 
 | ||||
| ## [0.4.0] Started with an "ick", but is now packed with new features 💪 | ||||
| 
 | ||||
| > ⚠️ Please read the following carefully: | ||||
| > This release is a bit special. As "something" on Samsung's side changed, | ||||
| > it is currently not possible to retrieve the status of "custom capabilities", eg. | ||||
| > woofer, soundmode, eq, and others. Therefore I decided to give the option to | ||||
| > disable the entities of these features as the value of these entities is not trustworthy. | ||||
| > Instead I implemented all of these and more (thanks to @whitebearded) as service calls. | ||||
| > Have fun using them! | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - Configuration flow options for enable / disable | ||||
|   - "advanced audio" features (NightMode, Bassmode, VoiceEnhancer) | ||||
|   - "woofer" feature | ||||
|   - "soundmode" feature | ||||
|   - "eq" feature | ||||
| - added `media_player` support for next and previous track | ||||
| - Service calls for: | ||||
|   - "advanced audio" features (NightMode, Bassmode, VoiceEnhancer) | ||||
|   - "woofer" feature | ||||
|   - "soundmode" feature | ||||
|   - "speaker_level" | ||||
|   - "rear_speaker_mode" | ||||
|   - "space_fit_sound" | ||||
|   - "active_voice_amplifier" | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| - Fixed state, also displaying "playing" and "paused" values | ||||
| 
 | ||||
| ## [0.3.2] Fix division by zero | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - The config flow now also checks whether the `int` provided for `CONF_ENTRY_MAX_VOLUME` is | ||||
|   greater than `1` and lower than `100`. This will make sure that a division by zero cannot happen. | ||||
| - Add default value `100` to `CONF_ENTRY_MAX_VOLUME` | ||||
| 
 | ||||
| ## [0.3.1] Documentation enhancements | ||||
| 
 | ||||
| ### Changed | ||||
|  |  | |||
							
								
								
									
										21
									
								
								LICENSE
								
								
								
								
							
							
						
						
									
										21
									
								
								LICENSE
								
								
								
								
							|  | @ -1,21 +0,0 @@ | |||
| MIT License | ||||
| 
 | ||||
| Copyright (c) 2024 Samuel Spagl | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										5
									
								
								Pipfile
								
								
								
								
							
							
						
						
									
										5
									
								
								Pipfile
								
								
								
								
							|  | @ -9,7 +9,8 @@ rich = "*" | |||
| homeassistant = "*" | ||||
| 
 | ||||
| [dev-packages] | ||||
| ruff = "*" | ||||
| black = "*" | ||||
| isort = "*" | ||||
| 
 | ||||
| [requires] | ||||
| python_version = "3.12" | ||||
| python_version = "3.11" | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -2,9 +2,6 @@ | |||
| 
 | ||||
| Welcome to YASSI, the Home Assistant integration designed to bring comprehensive control over your Samsung Soundbar into your smart home ecosystem. | ||||
| 
 | ||||
| > [!NOTE] | ||||
| > Please use service calls for setting the attribute of a custom capability instead of the entity. (See #43 for more information) | ||||
| 
 | ||||
| **Table of Contents:** | ||||
| <!-- TOC --> | ||||
| * [Why YASSI](#why-yassi) | ||||
|  |  | |||
|  | @ -6,18 +6,9 @@ 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, | ||||
|     CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES, | ||||
|     CONF_ENTRY_SETTINGS_EQ_SELECTOR, | ||||
|     CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR, | ||||
|     CONF_ENTRY_SETTINGS_WOOFER_NUMBER, | ||||
|     DOMAIN, | ||||
|     SUPPORTED_DOMAINS, | ||||
| ) | ||||
| 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__) | ||||
|  | @ -30,9 +21,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | |||
|     # store shell object | ||||
| 
 | ||||
|     _LOGGER.info(f"[{DOMAIN}] Starting to setup a ConfigEntry") | ||||
|     _LOGGER.debug( | ||||
|         f"[{DOMAIN}] Setting up ConfigEntry with the following data: {entry.data}" | ||||
|     ) | ||||
|     _LOGGER.debug(f"[{DOMAIN}] Setting up ConfigEntry with the following data: {entry.data}") | ||||
|     if not DOMAIN in hass.data: | ||||
|         _LOGGER.debug(f"[{DOMAIN}] Domain not found in hass.data setting default") | ||||
|         hass.data[DOMAIN] = SoundbarConfig( | ||||
|  | @ -59,12 +48,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | |||
|             session, | ||||
|             entry.data.get(CONF_ENTRY_MAX_VOLUME), | ||||
|             entry.data.get(CONF_ENTRY_DEVICE_NAME), | ||||
|             enable_eq=entry.data.get(CONF_ENTRY_SETTINGS_EQ_SELECTOR), | ||||
|             enable_advanced_audio=entry.data.get( | ||||
|                 CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES | ||||
|             ), | ||||
|             enable_soundmode=entry.data.get(CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR), | ||||
|             enable_woofer=entry.data.get(CONF_ENTRY_SETTINGS_WOOFER_NUMBER), | ||||
|         ) | ||||
|         await soundbar_device.update() | ||||
|         domain_config.devices[entry.data.get(CONF_ENTRY_DEVICE_ID)] = DeviceConfig( | ||||
|  |  | |||
|  | @ -2,11 +2,11 @@ import asyncio | |||
| import datetime | ||||
| import json | ||||
| import logging | ||||
| import time | ||||
| from urllib.parse import quote | ||||
| 
 | ||||
| from pysmartthings import DeviceEntity | ||||
| 
 | ||||
| from .const import SpeakerIdentifier, RearSpeakerMode | ||||
| from ..const import DOMAIN | ||||
| 
 | ||||
| log = logging.getLogger(__name__) | ||||
|  | @ -14,15 +14,7 @@ log = logging.getLogger(__name__) | |||
| 
 | ||||
| class SoundbarDevice: | ||||
|     def __init__( | ||||
|             self, | ||||
|             device: DeviceEntity, | ||||
|             session, | ||||
|             max_volume: int, | ||||
|             device_name: str, | ||||
|             enable_eq: bool = False, | ||||
|             enable_soundmode: bool = False, | ||||
|             enable_advanced_audio: bool = False, | ||||
|             enable_woofer: bool = False, | ||||
|         self, device: DeviceEntity, session, max_volume: int, device_name: str | ||||
|     ): | ||||
|         self.device = device | ||||
|         self._device_id = self.device.device_id | ||||
|  | @ -30,21 +22,17 @@ class SoundbarDevice: | |||
|         self.__session = session | ||||
|         self.__device_name = device_name | ||||
| 
 | ||||
|         self.__enable_soundmode = enable_soundmode | ||||
|         self.__supported_soundmodes = [] | ||||
|         self.__active_soundmode = "" | ||||
| 
 | ||||
|         self.__enable_woofer = enable_woofer | ||||
|         self.__woofer_level = 0 | ||||
|         self.__woofer_connection = "" | ||||
| 
 | ||||
|         self.__enable_eq = enable_eq | ||||
|         self.__active_eq_preset = "" | ||||
|         self.__supported_eq_presets = [] | ||||
|         self.__eq_action = "" | ||||
|         self.__eq_bands = [] | ||||
| 
 | ||||
|         self.__enable_advanced_audio = enable_advanced_audio | ||||
|         self.__voice_amplifier = 0 | ||||
|         self.__night_mode = 0 | ||||
|         self.__bass_mode = 0 | ||||
|  | @ -61,18 +49,12 @@ class SoundbarDevice: | |||
|         await self.device.status.refresh() | ||||
| 
 | ||||
|         await self._update_media() | ||||
| 
 | ||||
|         if self.__enable_soundmode: | ||||
|         await self._update_soundmode() | ||||
|         if self.__enable_advanced_audio: | ||||
|         await self._update_advanced_audio() | ||||
|         if self.__enable_soundmode: | ||||
|         await self._update_woofer() | ||||
|         if self.__enable_eq: | ||||
|         await self._update_equalizer() | ||||
| 
 | ||||
|     async def _update_media(self): | ||||
|         if "audioTrackData" in self.device.status._attributes: | ||||
|         self.__media_artist = self.device.status._attributes["audioTrackData"].value[ | ||||
|             "artist" | ||||
|         ] | ||||
|  | @ -88,14 +70,14 @@ class SoundbarDevice: | |||
| 
 | ||||
|     async def _update_soundmode(self): | ||||
|         await self.update_execution_data(["/sec/networkaudio/soundmode"]) | ||||
|         await asyncio.sleep(1) | ||||
|         await asyncio.sleep(0.1) | ||||
|         payload = await self.get_execute_status() | ||||
|         retry = 0 | ||||
|         while ( | ||||
|             "x.com.samsung.networkaudio.supportedSoundmode" not in payload | ||||
|             and retry < 10 | ||||
|         ): | ||||
|             await asyncio.sleep(1) | ||||
|             await asyncio.sleep(0.2) | ||||
|             payload = await self.get_execute_status() | ||||
|             retry += 1 | ||||
|         if retry == 10: | ||||
|  | @ -197,15 +179,7 @@ class SoundbarDevice: | |||
| 
 | ||||
|     @property | ||||
|     def state(self) -> str: | ||||
|         if self.device.status.switch: | ||||
|             if self.device.status.playback_status == "playing": | ||||
|                 return "playing" | ||||
|             if self.device.status.playback_status == "paused": | ||||
|                 return "paused" | ||||
|             else: | ||||
|                 return "on" | ||||
|         else: | ||||
|             return "off" | ||||
|         return "on" if self.device.status.switch else "off" | ||||
| 
 | ||||
|     async def switch_off(self): | ||||
|         await self.device.switch_off(True) | ||||
|  | @ -373,15 +347,11 @@ class SoundbarDevice: | |||
| 
 | ||||
|     @property | ||||
|     def media_duration(self) -> int | None: | ||||
|         attr = self.device.status.attributes.get("totalTime", None) | ||||
|         if attr: | ||||
|             return attr.value | ||||
|         return self.device.status.attributes.get("totalTime").value | ||||
| 
 | ||||
|     @property | ||||
|     def media_position(self) -> int | None: | ||||
|         attr = self.device.status.attributes.get("elapsedTime", None) | ||||
|         if attr: | ||||
|             return attr.value | ||||
|         return self.device.status.attributes.get("elapsedTime").value | ||||
| 
 | ||||
|     async def media_play(self): | ||||
|         await self.device.play(True) | ||||
|  | @ -392,12 +362,6 @@ class SoundbarDevice: | |||
|     async def media_stop(self): | ||||
|         await self.device.stop(True) | ||||
| 
 | ||||
|     async def media_next_track(self): | ||||
|         await self.device.command("main", "mediaPlayback", "fastForward") | ||||
| 
 | ||||
|     async def media_previous_track(self): | ||||
|         await self.device.command("main", "mediaPlayback", "rewind") | ||||
| 
 | ||||
|     @property | ||||
|     def media_app_name(self): | ||||
|         detail_status = self.device.status.attributes.get("detailName", None) | ||||
|  | @ -409,54 +373,21 @@ class SoundbarDevice: | |||
|     def media_coverart_updated(self) -> datetime.datetime: | ||||
|         return self.__media_cover_url_update_time | ||||
| 
 | ||||
|     # ------------ Speaker Level ---------------- | ||||
| 
 | ||||
|     async def set_speaker_level(self, speaker: SpeakerIdentifier, level: int): | ||||
|         await self.set_custom_execution_data( | ||||
|             href="/sec/networkaudio/channelVolume", | ||||
|             property="x.com.samsung.networkaudio.channelVolume", | ||||
|             value=[{"name": speaker.value, "value": level}], | ||||
|         ) | ||||
| 
 | ||||
|     async def set_rear_speaker_mode(self, mode: RearSpeakerMode): | ||||
|         await self.set_custom_execution_data( | ||||
|             href="/sec/networkaudio/surroundspeaker", | ||||
|             property="x.com.samsung.networkaudio.currentRearPosition", | ||||
|             value=mode.value, | ||||
|         ) | ||||
| 
 | ||||
|     # ------------ OTHER FUNCTIONS ------------ | ||||
| 
 | ||||
|     async def set_active_voice_amplifier(self, enabled: bool): | ||||
|         await self.set_custom_execution_data( | ||||
|             href="/sec/networkaudio/activeVoiceAmplifier", | ||||
|             property="x.com.samsung.networkaudio.activeVoiceAmplifier", | ||||
|             value=1 if enabled else 0 | ||||
|         ) | ||||
| 
 | ||||
|     async def set_space_fit_sound(self, enabled: bool): | ||||
|         await self.set_custom_execution_data( | ||||
|             href="/sec/networkaudio/spacefitSound", | ||||
|             property="x.com.samsung.networkaudio.spacefitSound", | ||||
|             value=1 if enabled else 0 | ||||
|         ) | ||||
| 
 | ||||
|     # ------------ SUPPORT FUNCTIONS ------------ | ||||
| 
 | ||||
|     async def update_execution_data(self, argument: str): | ||||
|         stuff = await self.device.command("main", "execute", "execute", argument) | ||||
|         return stuff | ||||
|         return await self.device.command("main", "execute", "execute", argument) | ||||
| 
 | ||||
|     async def set_custom_execution_data(self, href: str, property: str, value): | ||||
|         argument = [href, {property: value}] | ||||
|         assert await self.device.command("main", "execute", "execute", argument) | ||||
|         await self.device.command("main", "execute", "execute", argument) | ||||
| 
 | ||||
|     async def get_execute_status(self): | ||||
|         url = f"https://api.smartthings.com/v1/devices/{self._device_id}/components/main/capabilities/execute/status" | ||||
|         request_headers = {"Authorization": "Bearer " + self._api_key} | ||||
|         resp = await self.__session.get(url, headers=request_headers) | ||||
|         dict_stuff = await resp.json() | ||||
|         return dict_stuff["data"]["value"]["payload"] | ||||
|         dict = await resp.json() | ||||
|         return dict["data"]["value"]["payload"] | ||||
| 
 | ||||
|     async def get_song_title_artwork(self, artist: str, title: str) -> str: | ||||
|         """ | ||||
|  |  | |||
|  | @ -1,15 +0,0 @@ | |||
| from enum import Enum | ||||
| 
 | ||||
| 
 | ||||
| class SpeakerIdentifier(Enum): | ||||
|     CENTER = "Spk_Center" | ||||
|     SIDE = "Spk_Side" | ||||
|     WIDE = "Spk_Wide" | ||||
|     FRONT_TOP = "Spk_Front_Top" | ||||
|     REAR = "Spk_Rear" | ||||
|     REAR_TOP = "Spk_Rear_Top" | ||||
| 
 | ||||
| 
 | ||||
| class RearSpeakerMode(Enum): | ||||
|     FRONT = "Front" | ||||
|     REAR = "Rear" | ||||
|  | @ -1,24 +1,13 @@ | |||
| import logging | ||||
| from typing import Any | ||||
| 
 | ||||
| import pysmartthings | ||||
| import voluptuous as vol | ||||
| from homeassistant import config_entries | ||||
| from homeassistant.helpers.aiohttp_client import async_get_clientsession | ||||
| from pysmartthings import APIResponseError | ||||
| from voluptuous import All, Range | ||||
| 
 | ||||
| from .const import ( | ||||
|     CONF_ENTRY_API_KEY, | ||||
|     CONF_ENTRY_DEVICE_ID, | ||||
|     CONF_ENTRY_DEVICE_NAME, | ||||
|     CONF_ENTRY_MAX_VOLUME, | ||||
|     CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES, | ||||
|     CONF_ENTRY_SETTINGS_EQ_SELECTOR, | ||||
|     CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR, | ||||
|     CONF_ENTRY_SETTINGS_WOOFER_NUMBER, | ||||
|     DOMAIN, | ||||
| ) | ||||
| from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID, | ||||
|                     CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN) | ||||
| 
 | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
| 
 | ||||
|  | @ -34,8 +23,20 @@ async def validate_input(api, device_id: str): | |||
| class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||||
|     async def async_step_user(self, user_input=None): | ||||
|         if user_input is not None: | ||||
|             self.user_input = user_input | ||||
|             return await self.async_step_device() | ||||
|             try: | ||||
|                 session = async_get_clientsession(self.hass) | ||||
|                 api = pysmartthings.SmartThings( | ||||
|                     session, user_input.get(CONF_ENTRY_API_KEY) | ||||
|                 ) | ||||
|                 device = await validate_input(api, user_input.get(CONF_ENTRY_DEVICE_ID)) | ||||
| 
 | ||||
|                 _LOGGER.debug( | ||||
|                     f"Successfully validated Input, Creating entry with title {DOMAIN} and data {user_input}" | ||||
|                 ) | ||||
|                 return self.async_create_entry(title=DOMAIN, data=user_input) | ||||
|             except Exception as excp: | ||||
|                 _LOGGER.error(f"The ConfigFlow triggered an exception {excp}") | ||||
|                 return self.async_abort(reason="fetch_failed") | ||||
| 
 | ||||
|         return self.async_show_form( | ||||
|             step_id="user", | ||||
|  | @ -44,98 +45,7 @@ class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | |||
|                     vol.Required(CONF_ENTRY_API_KEY): str, | ||||
|                     vol.Required(CONF_ENTRY_DEVICE_ID): str, | ||||
|                     vol.Required(CONF_ENTRY_DEVICE_NAME): str, | ||||
|                     vol.Required(CONF_ENTRY_MAX_VOLUME, default=100): All( | ||||
|                         int, Range(min=1, max=100) | ||||
|                     ), | ||||
|                     vol.Required(CONF_ENTRY_MAX_VOLUME): int, | ||||
|                 } | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     async def async_step_device(self, user_input: dict[str, any] | None = None): | ||||
|         if user_input is not None: | ||||
|             self.user_input.update(user_input) | ||||
| 
 | ||||
|             try: | ||||
|                 session = async_get_clientsession(self.hass) | ||||
|                 api = pysmartthings.SmartThings( | ||||
|                     session, self.user_input.get(CONF_ENTRY_API_KEY) | ||||
|                 ) | ||||
|                 device = await validate_input( | ||||
|                     api, self.user_input.get(CONF_ENTRY_DEVICE_ID) | ||||
|                 ) | ||||
|                 _LOGGER.debug( | ||||
|                     f"Successfully validated Input, Creating entry with title {DOMAIN} and data {user_input}" | ||||
|                 ) | ||||
|             except Exception as excp: | ||||
|                 _LOGGER.error(f"The ConfigFlow triggered an exception {excp}") | ||||
|                 return self.async_abort(reason="fetch_failed") | ||||
|             return self.async_create_entry(title=DOMAIN, data=self.user_input) | ||||
| 
 | ||||
|         return self.async_show_form( | ||||
|             step_id="device", | ||||
|             data_schema=vol.Schema( | ||||
|                 { | ||||
|                     vol.Required(CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES): bool, | ||||
|                     vol.Required(CONF_ENTRY_SETTINGS_EQ_SELECTOR): bool, | ||||
|                     vol.Required(CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR): bool, | ||||
|                     vol.Required(CONF_ENTRY_SETTINGS_WOOFER_NUMBER): bool, | ||||
|                 } | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None): | ||||
|         """Handle a reconfiguration flow initialized by the user.""" | ||||
|         self.config_entry = self.hass.config_entries.async_get_entry( | ||||
|             self.context["entry_id"] | ||||
|         ) | ||||
|         return await self.async_step_reconfigure_confirm() | ||||
| 
 | ||||
|     async def async_step_reconfigure_confirm( | ||||
|         self, user_input: dict[str, Any] | None = None | ||||
|     ): | ||||
|         """Handle a reconfiguration flow initialized by the user.""" | ||||
|         errors: dict[str, str] = {} | ||||
|         assert self.config_entry | ||||
| 
 | ||||
|         if user_input is not None: | ||||
|             return self.async_update_reload_and_abort( | ||||
|                 self.config_entry, | ||||
|                 data={**self.config_entry.data, **user_input}, | ||||
|                 reason="reconfigure_successful", | ||||
|             ) | ||||
| 
 | ||||
|         return self.async_show_form( | ||||
|             step_id="reconfigure_confirm", | ||||
|             data_schema=vol.Schema( | ||||
|                 { | ||||
|                     vol.Required( | ||||
|                         CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES, | ||||
|                         default=self.config_entry.data.get( | ||||
|                             CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES | ||||
|                         ), | ||||
|                     ): bool, | ||||
|                     vol.Required( | ||||
|                         CONF_ENTRY_SETTINGS_EQ_SELECTOR, | ||||
|                         default=self.config_entry.data.get( | ||||
|                             CONF_ENTRY_SETTINGS_EQ_SELECTOR | ||||
|                         ), | ||||
|                     ): bool, | ||||
|                     vol.Required( | ||||
|                         CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR, | ||||
|                         default=self.config_entry.data.get( | ||||
|                             CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR | ||||
|                         ), | ||||
|                     ): bool, | ||||
|                     vol.Required( | ||||
|                         CONF_ENTRY_SETTINGS_WOOFER_NUMBER, | ||||
|                         default=self.config_entry.data.get( | ||||
|                             CONF_ENTRY_SETTINGS_WOOFER_NUMBER | ||||
|                         ), | ||||
|                     ): bool, | ||||
|                     vol.Required(CONF_ENTRY_MAX_VOLUME, default=100): All( | ||||
|                         int, Range(min=1, max=100) | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             errors=errors, | ||||
|         ) | ||||
|  |  | |||
|  | @ -9,12 +9,6 @@ CONF_ENTRY_API_KEY = "api_key" | |||
| CONF_ENTRY_DEVICE_ID = "device_id" | ||||
| CONF_ENTRY_DEVICE_NAME = "device_name" | ||||
| CONF_ENTRY_MAX_VOLUME = "device_volume" | ||||
| 
 | ||||
| CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES = "settings_advanced_audio" | ||||
| CONF_ENTRY_SETTINGS_EQ_SELECTOR = "settings_eq" | ||||
| CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR = "settings_soundmode" | ||||
| CONF_ENTRY_SETTINGS_WOOFER_NUMBER = "settings_woofer" | ||||
| 
 | ||||
| DEFAULT_NAME = DOMAIN | ||||
| 
 | ||||
| BUTTON = BUTTON_DOMAIN | ||||
|  |  | |||
|  | @ -1,16 +1,12 @@ | |||
| { | ||||
|   "domain": "samsung_soundbar", | ||||
|   "name": "Samsung Soundbar", | ||||
|   "codeowners": [ | ||||
|     "@samuelspagl" | ||||
|   ], | ||||
|   "codeowners": ["@samuelspagl"], | ||||
|   "config_flow": true, | ||||
|   "documentation": "https://www.example.com", | ||||
|   "integration_type": "hub", | ||||
|   "iot_class": "cloud_polling", | ||||
|   "issue_tracker": "https://github.com/samuelspagl/ha_samsung_soundbar/issues", | ||||
|   "requirements": [ | ||||
|     "pysmartthings==0.7.8" | ||||
|   ], | ||||
|   "version": "0.4.1" | ||||
|   "requirements": ["pysmartthings"], | ||||
|   "version": "0.3.1" | ||||
| } | ||||
|  | @ -1,25 +1,16 @@ | |||
| import logging | ||||
| from typing import Any, Mapping | ||||
| 
 | ||||
| from homeassistant.components.media_player import ( | ||||
|     DEVICE_CLASS_SPEAKER, | ||||
|     MediaPlayerEntity, | ||||
| ) | ||||
| from homeassistant.components.media_player.const import MediaPlayerEntityFeature | ||||
| from homeassistant.components.media_player import (DEVICE_CLASS_SPEAKER, | ||||
|                                                    MediaPlayerEntity) | ||||
| from homeassistant.components.media_player.const import \ | ||||
|     MediaPlayerEntityFeature | ||||
| from homeassistant.helpers.aiohttp_client import async_get_clientsession | ||||
| from homeassistant.helpers.entity import DeviceInfo, generate_entity_id | ||||
| from homeassistant.helpers import config_validation as cv, entity_platform, selector | ||||
| import voluptuous as vol | ||||
| 
 | ||||
| from .api_extension.SoundbarDevice import SoundbarDevice | ||||
| from .api_extension.const import SpeakerIdentifier, RearSpeakerMode | ||||
| from .const import ( | ||||
|     CONF_ENTRY_API_KEY, | ||||
|     CONF_ENTRY_DEVICE_ID, | ||||
|     CONF_ENTRY_DEVICE_NAME, | ||||
|     CONF_ENTRY_MAX_VOLUME, | ||||
|     DOMAIN, | ||||
| ) | ||||
| from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID, | ||||
|                     CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN) | ||||
| from .models import DeviceConfig | ||||
| 
 | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | @ -36,82 +27,14 @@ SUPPORT_SMARTTHINGS_SOUNDBAR = ( | |||
|     | MediaPlayerEntityFeature.TURN_OFF | ||||
|     | MediaPlayerEntityFeature.TURN_ON | ||||
|     | MediaPlayerEntityFeature.PLAY | ||||
|     | MediaPlayerEntityFeature.NEXT_TRACK | ||||
|     | MediaPlayerEntityFeature.PREVIOUS_TRACK | ||||
|     | MediaPlayerEntityFeature.STOP | ||||
|     | MediaPlayerEntityFeature.SELECT_SOUND_MODE | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| def addServices(): | ||||
|     platform = entity_platform.async_get_current_platform() | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "select_soundmode", | ||||
|         cv.make_entity_service_schema({vol.Required("sound_mode"): str}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_select_sound_mode.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_woofer_level", | ||||
|         cv.make_entity_service_schema( | ||||
|             {vol.Required("level"): vol.All(int, vol.Range(min=-12, max=6))} | ||||
|         ), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_woofer_level.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_night_mode", | ||||
|         cv.make_entity_service_schema({vol.Required("enabled"): bool}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_night_mode.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_bass_enhancer", | ||||
|         cv.make_entity_service_schema({vol.Required("enabled"): bool}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_bass_mode.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_voice_enhancer", | ||||
|         cv.make_entity_service_schema({vol.Required("enabled"): bool}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_voice_mode.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_speaker_level", | ||||
|         cv.make_entity_service_schema( | ||||
|             {vol.Required("speaker_identifier"): str, vol.Required("level"): int} | ||||
|         ), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_speaker_level.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_rear_speaker_mode", | ||||
|         cv.make_entity_service_schema({vol.Required("speaker_mode"): str}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_rear_speaker_mode.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_active_voice_amplifier", | ||||
|         cv.make_entity_service_schema({vol.Required("enabled"): bool}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_active_voice_amplifier.__name__, | ||||
|     ) | ||||
| 
 | ||||
|     platform.async_register_entity_service( | ||||
|         "set_space_fit_sound", | ||||
|         cv.make_entity_service_schema({vol.Required("enabled"): bool}), | ||||
|         SmartThingsSoundbarMediaPlayer.async_set_space_fit_sound.__name__, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| async def async_setup_entry(hass, config_entry, async_add_entities): | ||||
|     domain_data = hass.data[DOMAIN] | ||||
| 
 | ||||
|     addServices() | ||||
| 
 | ||||
|     entities = [] | ||||
|     for key in domain_data.devices: | ||||
|         device_config: DeviceConfig = domain_data.devices[key] | ||||
|  | @ -248,45 +171,9 @@ class SmartThingsSoundbarMediaPlayer(MediaPlayerEntity): | |||
|     async def async_media_pause(self): | ||||
|         await self.device.media_pause() | ||||
| 
 | ||||
|     async def async_media_next_track(self): | ||||
|         await self.device.media_next_track() | ||||
| 
 | ||||
|     async def async_media_previous_track(self): | ||||
|         await self.device.media_previous_track() | ||||
| 
 | ||||
|     async def async_media_stop(self): | ||||
|         await self.device.media_stop() | ||||
| 
 | ||||
|     # ---------- SERVICE_UTILITY ------------ | ||||
| 
 | ||||
|     async def async_set_woofer_level(self, level: int): | ||||
|         await self.device.set_woofer(level) | ||||
| 
 | ||||
|     async def async_set_bass_mode(self, enabled: bool): | ||||
|         await self.device.set_bass_mode(enabled) | ||||
| 
 | ||||
|     async def async_set_voice_mode(self, enabled: bool): | ||||
|         await self.device.set_voice_amplifier(enabled) | ||||
| 
 | ||||
|     async def async_set_night_mode(self, enabled: bool): | ||||
|         await self.device.set_night_mode(enabled) | ||||
| 
 | ||||
|     # ---------- SERVICE_UTILITY ------------ | ||||
| 
 | ||||
|     async def async_set_speaker_level(self, speaker_identifier: str, level: int): | ||||
|         await self.device.set_speaker_level( | ||||
|             SpeakerIdentifier(speaker_identifier), level | ||||
|         ) | ||||
| 
 | ||||
|     async def async_set_rear_speaker_mode(self, speaker_mode: str): | ||||
|         await self.device.set_rear_speaker_mode(RearSpeakerMode(speaker_mode)) | ||||
| 
 | ||||
|     async def async_set_active_voice_amplifier(self, enabled: bool): | ||||
|         await self.device.set_active_voice_amplifier(enabled) | ||||
| 
 | ||||
|     async def async_set_space_fit_sound(self, enabled: bool): | ||||
|         await self.device.set_space_fit_sound(enabled) | ||||
| 
 | ||||
|     # This property can be uncommented for some extra_attributes | ||||
|     # Still enabling this can cause side-effects. | ||||
|     # @property | ||||
|  |  | |||
|  | @ -1,14 +1,12 @@ | |||
| import logging | ||||
| 
 | ||||
| from homeassistant.components.number import ( | ||||
|     NumberEntity, | ||||
| from homeassistant.components.number import (NumberEntity, | ||||
|                                              NumberEntityDescription, | ||||
|     NumberMode, | ||||
| ) | ||||
|                                              NumberMode) | ||||
| from homeassistant.helpers.entity import DeviceInfo | ||||
| 
 | ||||
| from .api_extension.SoundbarDevice import SoundbarDevice | ||||
| from .const import CONF_ENTRY_DEVICE_ID, CONF_ENTRY_SETTINGS_WOOFER_NUMBER, DOMAIN | ||||
| from .const import CONF_ENTRY_DEVICE_ID, DOMAIN | ||||
| from .models import DeviceConfig | ||||
| 
 | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | @ -21,9 +19,7 @@ async def async_setup_entry(hass, config_entry, async_add_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 | ||||
|         ) and config_entry.data.get(CONF_ENTRY_SETTINGS_WOOFER_NUMBER): | ||||
|         if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID): | ||||
|             entities.append( | ||||
|                 SoundbarWooferNumberEntity( | ||||
|                     device, | ||||
|  |  | |||
|  | @ -1,20 +1,14 @@ | |||
| import logging | ||||
| 
 | ||||
| from homeassistant.components.number import ( | ||||
|     NumberEntity, | ||||
| from homeassistant.components.number import (NumberEntity, | ||||
|                                              NumberEntityDescription, | ||||
|     NumberMode, | ||||
| ) | ||||
| from homeassistant.components.select import SelectEntity, SelectEntityDescription | ||||
|                                              NumberMode) | ||||
| from homeassistant.components.select import (SelectEntity, | ||||
|                                              SelectEntityDescription) | ||||
| from homeassistant.helpers.entity import DeviceInfo | ||||
| 
 | ||||
| from .api_extension.SoundbarDevice import SoundbarDevice | ||||
| from .const import ( | ||||
|     CONF_ENTRY_DEVICE_ID, | ||||
|     CONF_ENTRY_SETTINGS_EQ_SELECTOR, | ||||
|     CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR, | ||||
|     DOMAIN, | ||||
| ) | ||||
| from .const import CONF_ENTRY_DEVICE_ID, DOMAIN | ||||
| from .models import DeviceConfig | ||||
| 
 | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | @ -27,17 +21,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities): | |||
|         device_config: DeviceConfig = domain_data.devices[key] | ||||
|         device = device_config.device | ||||
|         if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID): | ||||
|             if config_entry.data.get(CONF_ENTRY_SETTINGS_EQ_SELECTOR): | ||||
|             entities.append( | ||||
|                 EqPresetSelectEntity(device, "eq_preset", "mdi:tune-vertical") | ||||
|             ) | ||||
|             if config_entry.data.get(CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR): | ||||
|             entities.append( | ||||
|                     SoundModeSelectEntity( | ||||
|                         device, "sound_mode_preset", "mdi:surround-sound" | ||||
|                 SoundModeSelectEntity(device, "sound_mode_preset", "mdi:surround-sound") | ||||
|             ) | ||||
|                 ) | ||||
| 
 | ||||
|             entities.append( | ||||
|                 InputSelectEntity(device, "input_preset", "mdi:video-input-hdmi") | ||||
|             ) | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| import logging | ||||
| 
 | ||||
| from homeassistant.components.sensor import ( | ||||
|     SensorDeviceClass, | ||||
|     SensorEntity, | ||||
|     SensorStateClass, | ||||
| ) | ||||
| from homeassistant.components.sensor import (SensorDeviceClass, SensorEntity, | ||||
|                                              SensorStateClass) | ||||
| from homeassistant.helpers.entity import DeviceInfo | ||||
| 
 | ||||
| from .api_extension.SoundbarDevice import SoundbarDevice | ||||
|  |  | |||
|  | @ -1,167 +0,0 @@ | |||
| 
 | ||||
| select_soundmode: | ||||
|   name: Select Soundmode | ||||
|   description: Some Soundbars support different "sound modes". If supported you can select them here. | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     sound_mode: | ||||
|       name: Sound Mode | ||||
|       description: Select the Soundmode you are interested in. | ||||
|       required: true | ||||
|       example: "adaptive sound" | ||||
|       # The default field value | ||||
|       default: "standard" | ||||
|       # Selector (https://www.home-assistant.io/docs/blueprint/selectors/) to control | ||||
|       # the input UI for this field | ||||
|       selector: | ||||
|         select: | ||||
|           translation_key: "soundmode" | ||||
|           options: | ||||
|             - "standard" | ||||
|             - "surround" | ||||
|             - "game" | ||||
|             - "adaptive sound" | ||||
| 
 | ||||
| set_woofer_level: | ||||
|   name: Set Woofer level | ||||
|   description: Set the subwoofer level of your soundbar | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     level: | ||||
|       name: Volume level | ||||
|       required: true | ||||
|       example: 3 | ||||
|       default: 0 | ||||
|       selector: | ||||
|         number: | ||||
|           min: -12 | ||||
|           max: 6 | ||||
|           step: 1 | ||||
| 
 | ||||
| set_night_mode: | ||||
|   name: Set NightMode | ||||
|   description: Activates / deactivates the Nightmode | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     enabled: | ||||
|       name: Enabled / Disabled | ||||
|       required: true | ||||
|       example: true | ||||
|       default: false | ||||
|       selector: | ||||
|         boolean: | ||||
| 
 | ||||
| set_bass_enhancer: | ||||
|   name: Set bass enhancement | ||||
|   description: Activates / deactivates the bass enhancement | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     enabled: | ||||
|       name: Enabled / Disabled | ||||
|       required: true | ||||
|       example: true | ||||
|       default: false | ||||
|       selector: | ||||
|         boolean: | ||||
| 
 | ||||
| set_voice_enhancer: | ||||
|   name: Set voice enhancement | ||||
|   description: Activates / deactivates the voice enhancement | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     enabled: | ||||
|       name: Enabled / Disabled | ||||
|       required: true | ||||
|       example: true | ||||
|       default: false | ||||
|       selector: | ||||
|         boolean: | ||||
| 
 | ||||
| set_speaker_level: | ||||
|   name: Set Speaker level | ||||
|   description: Set the speaker levels of your soundbar | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     speaker_identifier: | ||||
|       name: Speaker Identifier | ||||
|       required: true | ||||
|       example: Spk_Center | ||||
|       selector: | ||||
|         select: | ||||
|           translation_key: "speaker_identifier" | ||||
|           options: | ||||
|             - "Spk_Center" | ||||
|             - "Spk_Side" | ||||
|             - "Spk_Wide" | ||||
|             - "Spk_Front_Top" | ||||
|             - "Spk_Rear" | ||||
|             - "Spk_Rear_Top" | ||||
|     level: | ||||
|       name: Speaker Level | ||||
|       required: true | ||||
|       example: 0 | ||||
|       selector: | ||||
|         number: | ||||
|           min: -6 | ||||
|           max: 6 | ||||
|           step: 1 | ||||
| 
 | ||||
| set_rear_speaker_mode: | ||||
|   name: Set rear speaker mode | ||||
|   description: Set the rear speaker mode of your soundbar | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     speaker_mode: | ||||
|       name: Speaker mode | ||||
|       required: true | ||||
|       example: Rear | ||||
|       selector: | ||||
|         select: | ||||
|           translation_key: "rear_speaker_mode" | ||||
|           options: | ||||
|             - "Rear" | ||||
|             - "Front" | ||||
| 
 | ||||
| set_active_voice_amplifier: | ||||
|   name: Set active voice amplifier | ||||
|   description: Activates / deactivates the active voice amplifier | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     enabled: | ||||
|       name: Enabled / Disabled | ||||
|       required: true | ||||
|       example: true | ||||
|       default: false | ||||
|       selector: | ||||
|         boolean: | ||||
| 
 | ||||
| set_space_fit_sound: | ||||
|   name: Set SpaceFitSound | ||||
|   description: Activates / deactivates the SpaceFitSound | ||||
|   target: | ||||
|     device: | ||||
|       integration: samsung_soundbar | ||||
|   fields: | ||||
|     enabled: | ||||
|       name: Enabled / Disabled | ||||
|       required: true | ||||
|       example: true | ||||
|       default: false | ||||
|       selector: | ||||
|         boolean: | ||||
|  | @ -4,11 +4,7 @@ from homeassistant.components.switch import SwitchEntity | |||
| from homeassistant.helpers.entity import DeviceInfo | ||||
| 
 | ||||
| from .api_extension.SoundbarDevice import SoundbarDevice | ||||
| from .const import ( | ||||
|     CONF_ENTRY_DEVICE_ID, | ||||
|     CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES, | ||||
|     DOMAIN, | ||||
| ) | ||||
| from .const import CONF_ENTRY_DEVICE_ID, DOMAIN | ||||
| from .models import DeviceConfig | ||||
| 
 | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | @ -22,7 +18,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities): | |||
|         device_config: DeviceConfig = domain_data.devices[key] | ||||
|         device = device_config.device | ||||
|         if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID): | ||||
|             if config_entry.data.get(CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES): | ||||
|             entities.append( | ||||
|                 SoundbarSwitchAdvancedAudio( | ||||
|                     device, | ||||
|  |  | |||
|  | @ -10,143 +10,6 @@ | |||
|                   }, | ||||
|                   "description": "Bitte gib deine Daten ein.", | ||||
|                   "title": "Authentifizierung" | ||||
|             }, | ||||
|             "device":{ | ||||
|                 "data" : { | ||||
|                     "settings_advanced_audio": "'Advanced Audio switches' aktivieren (NightMode, BassMode, VoiceEnhancer)", | ||||
|                     "settings_eq": "'EQ selector' aktivieren", | ||||
|                     "settings_soundmode": "'Soundmode selector' aktivieren", | ||||
|                     "settings_woofer": "'Subwoofer Entität' aktivieren" | ||||
|                 }, | ||||
|                 "description": "Einige Soundbars haben verschiedene Featuresets. Wähle bitte aus welche Features von deiner Soundbar supported werden (einsehbar in der SmartThings App).", | ||||
|                 "title": "Geräte Einstellungen" | ||||
|             }, | ||||
|             "reconfigure_confirm":{ | ||||
|                 "data" : { | ||||
|                     "settings_advanced_audio": "'Advanced Audio switches' aktivieren (NightMode, BassMode, VoiceEnhancer)", | ||||
|                     "settings_eq": "'EQ selector' aktivieren", | ||||
|                     "settings_soundmode": "'Soundmode selector' aktivieren", | ||||
|                     "settings_woofer": "'Subwoofer Entität' aktivieren", | ||||
|                     "device_volume": "Max Volume (int)" | ||||
|                 }, | ||||
|                 "description": "Einige Soundbars haben verschiedene Featuresets. Wähle bitte aus welche Features von deiner Soundbar supported werden (einsehbar in der SmartThings App).", | ||||
|                 "title": "Geräte Einstellungen" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "selector": { | ||||
|         "soundmode": { | ||||
|             "options": { | ||||
|                 "standard": "Standard", | ||||
|                 "surround": "Surround", | ||||
|                 "game": "Gaming", | ||||
|                 "adaptive sound": "Adaptive Sound" | ||||
|             } | ||||
|         }, | ||||
|         "speaker_identifier": { | ||||
|             "options": { | ||||
|                 "Spk_Center": "Center", | ||||
|                 "Spk_Side": "Side", | ||||
|                 "Spk_Wide": "Wide", | ||||
|                 "Spk_Front_Top": "Front Top", | ||||
|                 "Spk_Rear": "Rear", | ||||
|                 "Spk_Rear_Top": "Rear Top" | ||||
|             } | ||||
|         }, | ||||
|         "rear_speaker_mode": { | ||||
|             "options": { | ||||
|                 "Rear": "Rear", | ||||
|                 "Front": "Front" | ||||
|             } | ||||
|         } | ||||
|   }, | ||||
|   "services":{ | ||||
|     "select_soundmode":{ | ||||
|         "name": "SoundMode auswählen", | ||||
|         "description": "Wähle hier zwischen, 'Standard', 'Surround', 'Game' und 'Adaptive Sound'." | ||||
|     }, | ||||
|     "set_woofer_level":{ | ||||
|         "name": "Subwoofer Level setzen", | ||||
|         "description": "Verändere die Lautstärke deines Subwoofers.", | ||||
|         "fields":{ | ||||
|             "level":{ | ||||
|                 "name": "Volume Level", | ||||
|                 "description": "Subwoofer Level, von -12 bis +6" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "set_night_mode":{ | ||||
|         "name": "Nachtmodus setzen", | ||||
|         "description": "Schalte den 'Nachtmodus' an / aus.", | ||||
|         "fields":{ | ||||
|             "enabled":{ | ||||
|                 "name": "An / ausschalten", | ||||
|                 "description": "Siehe Name." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "set_bass_enhancer":{ | ||||
|         "name": "Bassmodus setzen", | ||||
|         "description": "Schalte den 'Bassmodus' an / aus.", | ||||
|         "fields":{ | ||||
|             "enabled":{ | ||||
|                 "name": "An / ausschalten", | ||||
|                 "description": "Siehe Name." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "set_voice_enhancer":{ | ||||
|         "name": "Stimmenverbesserer setzen", | ||||
|         "description": "Schalte den 'Stimmenverbesserer' an / aus.", | ||||
|         "fields":{ | ||||
|             "enabled":{ | ||||
|                 "name": "An / ausschalten", | ||||
|                 "description": "Siehe Name." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "set_speaker_level":{ | ||||
|         "name": "Lautsprecher level verändern", | ||||
|         "description": "Verändere die Lautstärke der einzelnen Lautsprecher", | ||||
|         "fields":{ | ||||
|                 "speaker_identifier": { | ||||
|                     "name": "Lautsprecher", | ||||
|                     "description": "Auszuwählender Lautsprecher" | ||||
|                 }, | ||||
|                 "level": { | ||||
|                     "name": "Lautstärke Level", | ||||
|                     "description": "Lautstärke Level zwischen -6 und 6." | ||||
|                 } | ||||
|             } | ||||
|     }, | ||||
|     "set_rear_speaker_mode":{ | ||||
|         "name": "Modus der hinteren Lautsprecher setzen", | ||||
|         "description": "Nutze deine Rücklautsprecher, als 'Vorder-' oder 'Rücklautsprecher'.", | ||||
|         "fields":{ | ||||
|                 "speaker_mode": { | ||||
|                     "name": "Lautsprecher Modus", | ||||
|                     "description": "Nutze den Lautsprecher als Front oder Rear Speaker." | ||||
|                 } | ||||
|             } | ||||
|     }, | ||||
|     "set_active_voice_amplifier":{ | ||||
|         "name": "Stimmenverstärker setzen", | ||||
|         "description": "Schalte den 'Stimmenverstärker' an / aus.", | ||||
|         "fields":{ | ||||
|             "enabled":{ | ||||
|                 "name": "An / ausschalten", | ||||
|                 "description": "Siehe Name." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "set_space_fit_sound":{ | ||||
|         "name": "SpaceFitSound setzen", | ||||
|         "description": "Schalte den 'SpaceFitSound' an / aus.", | ||||
|         "fields":{ | ||||
|             "enabled":{ | ||||
|                 "name": "An / ausschalten", | ||||
|                 "description": "Siehe Name." | ||||
|             } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -10,143 +10,6 @@ | |||
|                   }, | ||||
|                   "description": "Please enter your credentials.", | ||||
|                   "title": "Authentication" | ||||
|             }, | ||||
|             "device": { | ||||
|                 "data": { | ||||
|                     "settings_advanced_audio": "Enable 'Advanced Audio switches' capabilities (NightMode, BassMode, VoiceEnhancer)", | ||||
|                     "settings_eq": "Enable 'EQ selector' capabilities", | ||||
|                     "settings_soundmode": "Enable 'Soundmode selector' capabilities", | ||||
|                     "settings_woofer": "Enable 'Woofer number' capability" | ||||
|                 }, | ||||
|                 "description": "Some soundbars have a different featureset than others. Please the features supported by your soundbar (visible in the SmartThings App).", | ||||
|                 "title": "Device Settings" | ||||
|             }, | ||||
|             "reconfigure_confirm": { | ||||
|                 "data": { | ||||
|                     "settings_advanced_audio": "Enable 'Advanced Audio switches' capabilities (NightMode, BassMode, VoiceEnhancer)", | ||||
|                     "settings_eq": "Enable 'EQ selector' capabilities", | ||||
|                     "settings_soundmode": "Enable 'Soundmode selector' capabilities", | ||||
|                     "settings_woofer": "Enable 'Woofer number' capability", | ||||
|                     "device_volume": "Max Volume (int)" | ||||
|                 }, | ||||
|                 "description": "Some soundbars have a different featureset than others. Please the features supported by your soundbar (visible in the SmartThings App).", | ||||
|                 "title": "Device Settings" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "selector": { | ||||
|         "soundmode": { | ||||
|             "options": { | ||||
|                 "standard": "Standard", | ||||
|                 "surround": "Surround", | ||||
|                 "game": "Gaming", | ||||
|                 "adaptive sound": "Adaptive Sound" | ||||
|             } | ||||
|         }, | ||||
|         "speaker_identifier": { | ||||
|             "options": { | ||||
|                 "Spk_Center": "Center", | ||||
|                 "Spk_Side": "Side", | ||||
|                 "Spk_Wide": "Wide", | ||||
|                 "Spk_Front_Top": "Front Top", | ||||
|                 "Spk_Rear": "Rear", | ||||
|                 "Spk_Rear_Top": "Rear Top" | ||||
|             } | ||||
|         }, | ||||
|         "rear_speaker_mode": { | ||||
|             "options": { | ||||
|                 "Rear": "Rear", | ||||
|                 "Front": "Front" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "services": { | ||||
|         "select_soundmode": { | ||||
|             "name": "Select Sound Mode", | ||||
|             "description": "Choose between 'Standard', 'Surround', 'Game', and 'Adaptive Sound'." | ||||
|         }, | ||||
|         "set_woofer_level": { | ||||
|             "name": "Set Subwoofer Level", | ||||
|             "description": "Change the volume of your subwoofer.", | ||||
|             "fields": { | ||||
|                 "level": { | ||||
|                     "name": "Volume Level", | ||||
|                     "description": "Subwoofer level, from -12 to +6" | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_night_mode": { | ||||
|             "name": "Set Night Mode", | ||||
|             "description": "Turn 'Night Mode' on/off.", | ||||
|             "fields": { | ||||
|                 "enabled": { | ||||
|                     "name": "On/Off", | ||||
|                     "description": "See name." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_bass_enhancer": { | ||||
|             "name": "Set Bass Mode", | ||||
|             "description": "Turn 'Bass Mode' on/off.", | ||||
|             "fields": { | ||||
|                 "enabled": { | ||||
|                     "name": "On/Off", | ||||
|                     "description": "See name." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_voice_enhancer": { | ||||
|             "name": "Set Voice Enhancer", | ||||
|             "description": "Turn 'Voice Enhancer' on/off.", | ||||
|             "fields": { | ||||
|                 "enabled": { | ||||
|                     "name": "On/Off", | ||||
|                     "description": "See name." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_speaker_level": { | ||||
|             "name": "Change Speaker Level", | ||||
|             "description": "Change the volume of individual speakers.", | ||||
|             "fields":{ | ||||
|                 "speaker_identifier": { | ||||
|                     "name": "Speaker Identifier", | ||||
|                     "description": "Identifier of the speaker." | ||||
|                 }, | ||||
|                 "level": { | ||||
|                     "name": "Level", | ||||
|                     "description": "Level of the Speaker from -6 to 6." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_rear_speaker_mode": { | ||||
|             "name": "Set Rear Speaker Mode", | ||||
|             "description": "Use your rear speakers as 'Front' or 'Rear' speakers.", | ||||
|             "fields":{ | ||||
|                 "speaker_mode": { | ||||
|                     "name": "Speaker mode", | ||||
|                     "description": "Weather the speaker are used as rear / front speakers." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_active_voice_amplifier": { | ||||
|             "name": "Set Voice Amplifier", | ||||
|             "description": "Turn 'Voice Amplifier' on/off.", | ||||
|             "fields": { | ||||
|                 "enabled": { | ||||
|                     "name": "On/Off", | ||||
|                     "description": "See name." | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "set_space_fit_sound": { | ||||
|             "name": "Set SpaceFitSound", | ||||
|             "description": "Turn 'SpaceFitSound' on/off.", | ||||
|             "fields": { | ||||
|                 "enabled": { | ||||
|                     "name": "On/Off", | ||||
|                     "description": "See name." | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -3,5 +3,5 @@ | |||
|   "filename": "samsung_soundbar.zip", | ||||
|   "render_readme": true, | ||||
|   "zip_release": true, | ||||
|   "homeassistant": "2024.3.0" | ||||
|   "homeassistant": "2024.1.0" | ||||
| } | ||||
|  | @ -1,20 +0,0 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| cd "$(dirname "$0")/.." | ||||
| 
 | ||||
| # Create config dir if not present | ||||
| if [[ ! -d "${PWD}/config" ]]; then | ||||
|     mkdir -p "${PWD}/config" | ||||
|     hass --config "${PWD}/config" --script ensure_config | ||||
| fi | ||||
| 
 | ||||
| # Set the path to custom_components | ||||
| ## This let's us have the structure we want <root>/custom_components/integration_blueprint | ||||
| ## while at the same time have Home Assistant configuration inside <root>/config | ||||
| ## without resulting to symlinks. | ||||
| export PYTHONPATH="${PYTHONPATH}:${PWD}/custom_components" | ||||
| 
 | ||||
| # Start Home Assistant | ||||
| hass --config "${PWD}/config" --debug | ||||
|  | @ -1,7 +0,0 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| cd "$(dirname "$0")/.." | ||||
| 
 | ||||
| pip install rich pysmartthings | ||||
		Loading…
	
		Reference in New Issue