Compare commits
	
		
			6 Commits
		
	
	
		
			main
			...
			feature/ne
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						7c7648e51a | |
| 
							
							
								 | 
						09c1640839 | |
| 
							
							
								 | 
						88034c5531 | |
| 
							
							
								 | 
						a28def5313 | |
| 
							
							
								 | 
						735fd53644 | |
| 
							
							
								 | 
						d42e1b2832 | 
| 
						 | 
					@ -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
 | 
					*$py.class
 | 
				
			||||||
.DS_store
 | 
					.DS_store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config
 | 
					 | 
				
			||||||
.vscode
 | 
					 | 
				
			||||||
.ruff_cache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# C extensions
 | 
					# C extensions
 | 
				
			||||||
*.so
 | 
					*.so
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										55
									
								
								CHANGELOG.md
								
								
								
								
							
							
						
						
									
										55
									
								
								CHANGELOG.md
								
								
								
								
							| 
						 | 
					@ -1,60 +1,5 @@
 | 
				
			||||||
# Changelog
 | 
					# 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Updated the `README` as well as the documentation website
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## [0.3.0] Icons and Chore
 | 
					## [0.3.0] Icons and Chore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Added
 | 
					### Added
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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 = "*"
 | 
					homeassistant = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dev-packages]
 | 
					[dev-packages]
 | 
				
			||||||
ruff = "*"
 | 
					black = "*"
 | 
				
			||||||
 | 
					isort = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[requires]
 | 
					[requires]
 | 
				
			||||||
python_version = "3.12"
 | 
					python_version = "3.11"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										94
									
								
								README.md
								
								
								
								
							
							
						
						
									
										94
									
								
								README.md
								
								
								
								
							| 
						 | 
					@ -1,22 +1,6 @@
 | 
				
			||||||
# YASSI: Yet Another Samsung Soundbar Integration (for Home Assistant)
 | 
					# HomeAssistant: Samsung Soundbar Integration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Welcome to YASSI, the Home Assistant integration designed to bring comprehensive control over your Samsung Soundbar into your smart home ecosystem.
 | 
					> Yet another Samsung Soundbar Integration (YASSI)
 | 
				
			||||||
 | 
					 | 
				
			||||||
> [!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)
 | 
					 | 
				
			||||||
* [Features](#features)
 | 
					 | 
				
			||||||
* [Installation / Setup](#installation--setup)
 | 
					 | 
				
			||||||
  * [Prerequisites](#prerequisites)
 | 
					 | 
				
			||||||
  * [Installation:](#installation)
 | 
					 | 
				
			||||||
  * [Configuration](#configuration)
 | 
					 | 
				
			||||||
* [Support](#support)
 | 
					 | 
				
			||||||
* [Contributing](#contributing)
 | 
					 | 
				
			||||||
* [General Thanks](#general-thanks)
 | 
					 | 
				
			||||||
<!-- TOC -->
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Why YASSI
 | 
					## Why YASSI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,54 +18,48 @@ are not documented... ;)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Features
 | 
					## Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Set-Up through HomeAssistant-UI
 | 
				
			||||||
 | 
					- Theoretically it should be possible to have multiple Devices (not tested)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **UI Setup**: You can easily set up your Soundbar through the UI.
 | 
					- `media_player` Entity
 | 
				
			||||||
- **Media Player Controls**: Power, volume, mute, source selection, and media controls are all at your fingertips.
 | 
					  - On / Off
 | 
				
			||||||
- **Selectable Sound Modes**: Choose from various sound modes and inputs for optimal audio.
 | 
					  - Volume
 | 
				
			||||||
- **Subwoofer & Equalizer Adjustment**: Fine-tune your audio experience.
 | 
					  - Mute
 | 
				
			||||||
- **Switchable Enhancements**: Toggle features like night mode and voice amplification.
 | 
					  - Input Source
 | 
				
			||||||
- **Customizable Bass Level**: Set the bass to your preference.
 | 
					  - Sound Mode
 | 
				
			||||||
- **Multiple Devices**: should be theoretically possible but **not** tested
 | 
					  - Media
 | 
				
			||||||
 | 
					    - Play / Pause / Stop
 | 
				
			||||||
 | 
					    - Artist
 | 
				
			||||||
 | 
					    - Title
 | 
				
			||||||
 | 
					    - Music Cover Art url (iTunes Api)
 | 
				
			||||||
 | 
					- `switch` entity
 | 
				
			||||||
 | 
					  - Night mode
 | 
				
			||||||
 | 
					  - Bass mode
 | 
				
			||||||
 | 
					  - Voice amplifier
 | 
				
			||||||
 | 
					- `number` entity
 | 
				
			||||||
 | 
					  - bass level
 | 
				
			||||||
 | 
					  - *[to come] equalizer bands*
 | 
				
			||||||
 | 
					- `select` entity
 | 
				
			||||||
 | 
					  - sound mode (additional control in the "Device" tab)
 | 
				
			||||||
 | 
					  - input (additional control in the "Device" tab)
 | 
				
			||||||
 | 
					  - equalizer preset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For the full feature list per entity type, please take a look at the [documentation](ha-samsung-soundbar.vercel.app) website.
 | 
					## How to install it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation / Setup
 | 
					### HACS: 
 | 
				
			||||||
 | 
					>  ⚠️ not done yet but planned (hopefully)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Prerequisites
 | 
					### Adding this repository as custom repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Before you begin, ensure you have the following:
 | 
					Add this repository as custom repository in HACS and install it ;)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- A Samsung Soundbar compatible with SmartThings.
 | 
					### Manual
 | 
				
			||||||
- Home Assistant installed and running.
 | 
					 | 
				
			||||||
- HACS (Home Assistant Community Store) for easy installation.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Installation
 | 
					You can also copy the `samsung_soundbar` folder in the `custom_components` folder to
 | 
				
			||||||
 | 
					your `config/custom_components` folder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Add this repository as a custom repository in HACS or manually copy the `samsung_soundbar` folder to the `custom_components` directory in your Home Assistant configuration.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [](https://my.home-assistant.io/redirect/hacs_repository/?owner=samuelspagl&repository=ha_samsung_soundbar&category=integration)
 | 
					 | 
				
			||||||
2. Restart Home Assistant.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
> [!NOTE]
 | 
					 | 
				
			||||||
> It is planned to add it to the default `HACS` repository list, but not done yet.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Configuration
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
To integrate your Samsung Soundbar with Home Assistant using YASSI, you will be asked for the following variables:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- **SmartThings API Key**: [Retrieve your API key from SmartThings Tokens.](https://account.smartthings.com/tokens)
 | 
					 | 
				
			||||||
- **Device ID**: [Find your device ID at SmartThings Devices.](https://my.smartthings.com/advanced/devices)
 | 
					 | 
				
			||||||
- **Device Name**: Choose a name for your soundbar to be recognized in Home Assistant.
 | 
					 | 
				
			||||||
- **Max Volume**: Define the maximum volume level for the `media_player` slider (between `1` and `100`).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Support
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For support, feature requests, or bug reporting, please visit the Issues section of this GitHub repository.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Contributing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## General Thanks
 | 
					## General Thanks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Like already mentioned, thanks to @PiotrMachowski / @thierryBourbon for the general idea on how to do things.
 | 
					Like already mentioned, thanks to @PiotrMachowski / @thierryBourbon for the general
 | 
				
			||||||
 | 
					idea on how to do things.
 | 
				
			||||||
| 
						 | 
					@ -6,18 +6,9 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
 | 
				
			||||||
from pysmartthings import SmartThings
 | 
					from pysmartthings import SmartThings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .api_extension.SoundbarDevice import SoundbarDevice
 | 
					from .api_extension.SoundbarDevice import SoundbarDevice
 | 
				
			||||||
from .const import (
 | 
					from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID,
 | 
				
			||||||
    CONF_ENTRY_API_KEY,
 | 
					                    CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN,
 | 
				
			||||||
    CONF_ENTRY_DEVICE_ID,
 | 
					                    SUPPORTED_DOMAINS)
 | 
				
			||||||
    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 .models import DeviceConfig, SoundbarConfig
 | 
					from .models import DeviceConfig, SoundbarConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_LOGGER = logging.getLogger(__name__)
 | 
				
			||||||
| 
						 | 
					@ -30,9 +21,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
 | 
				
			||||||
    # store shell object
 | 
					    # store shell object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _LOGGER.info(f"[{DOMAIN}] Starting to setup a ConfigEntry")
 | 
					    _LOGGER.info(f"[{DOMAIN}] Starting to setup a ConfigEntry")
 | 
				
			||||||
    _LOGGER.debug(
 | 
					    _LOGGER.debug(f"[{DOMAIN}] Setting up ConfigEntry with the following data: {entry.data}")
 | 
				
			||||||
        f"[{DOMAIN}] Setting up ConfigEntry with the following data: {entry.data}"
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    if not DOMAIN in hass.data:
 | 
					    if not DOMAIN in hass.data:
 | 
				
			||||||
        _LOGGER.debug(f"[{DOMAIN}] Domain not found in hass.data setting default")
 | 
					        _LOGGER.debug(f"[{DOMAIN}] Domain not found in hass.data setting default")
 | 
				
			||||||
        hass.data[DOMAIN] = SoundbarConfig(
 | 
					        hass.data[DOMAIN] = SoundbarConfig(
 | 
				
			||||||
| 
						 | 
					@ -59,12 +48,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
 | 
				
			||||||
            session,
 | 
					            session,
 | 
				
			||||||
            entry.data.get(CONF_ENTRY_MAX_VOLUME),
 | 
					            entry.data.get(CONF_ENTRY_MAX_VOLUME),
 | 
				
			||||||
            entry.data.get(CONF_ENTRY_DEVICE_NAME),
 | 
					            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()
 | 
					        await soundbar_device.update()
 | 
				
			||||||
        domain_config.devices[entry.data.get(CONF_ENTRY_DEVICE_ID)] = DeviceConfig(
 | 
					        domain_config.devices[entry.data.get(CONF_ENTRY_DEVICE_ID)] = DeviceConfig(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,11 @@ import asyncio
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
from urllib.parse import quote
 | 
					from urllib.parse import quote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from pysmartthings import DeviceEntity
 | 
					from pysmartthings import DeviceEntity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .const import SpeakerIdentifier, RearSpeakerMode
 | 
					 | 
				
			||||||
from ..const import DOMAIN
 | 
					from ..const import DOMAIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
log = logging.getLogger(__name__)
 | 
					log = logging.getLogger(__name__)
 | 
				
			||||||
| 
						 | 
					@ -14,15 +14,7 @@ log = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SoundbarDevice:
 | 
					class SoundbarDevice:
 | 
				
			||||||
    def __init__(
 | 
					    def __init__(
 | 
				
			||||||
            self,
 | 
					        self, device: DeviceEntity, session, max_volume: int, device_name: str
 | 
				
			||||||
            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 = device
 | 
					        self.device = device
 | 
				
			||||||
        self._device_id = self.device.device_id
 | 
					        self._device_id = self.device.device_id
 | 
				
			||||||
| 
						 | 
					@ -30,21 +22,17 @@ class SoundbarDevice:
 | 
				
			||||||
        self.__session = session
 | 
					        self.__session = session
 | 
				
			||||||
        self.__device_name = device_name
 | 
					        self.__device_name = device_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__enable_soundmode = enable_soundmode
 | 
					 | 
				
			||||||
        self.__supported_soundmodes = []
 | 
					        self.__supported_soundmodes = []
 | 
				
			||||||
        self.__active_soundmode = ""
 | 
					        self.__active_soundmode = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__enable_woofer = enable_woofer
 | 
					 | 
				
			||||||
        self.__woofer_level = 0
 | 
					        self.__woofer_level = 0
 | 
				
			||||||
        self.__woofer_connection = ""
 | 
					        self.__woofer_connection = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__enable_eq = enable_eq
 | 
					 | 
				
			||||||
        self.__active_eq_preset = ""
 | 
					        self.__active_eq_preset = ""
 | 
				
			||||||
        self.__supported_eq_presets = []
 | 
					        self.__supported_eq_presets = []
 | 
				
			||||||
        self.__eq_action = ""
 | 
					        self.__eq_action = ""
 | 
				
			||||||
        self.__eq_bands = []
 | 
					        self.__eq_bands = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__enable_advanced_audio = enable_advanced_audio
 | 
					 | 
				
			||||||
        self.__voice_amplifier = 0
 | 
					        self.__voice_amplifier = 0
 | 
				
			||||||
        self.__night_mode = 0
 | 
					        self.__night_mode = 0
 | 
				
			||||||
        self.__bass_mode = 0
 | 
					        self.__bass_mode = 0
 | 
				
			||||||
| 
						 | 
					@ -61,41 +49,35 @@ class SoundbarDevice:
 | 
				
			||||||
        await self.device.status.refresh()
 | 
					        await self.device.status.refresh()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await self._update_media()
 | 
					        await self._update_media()
 | 
				
			||||||
 | 
					        await self._update_soundmode()
 | 
				
			||||||
        if self.__enable_soundmode:
 | 
					        await self._update_advanced_audio()
 | 
				
			||||||
            await self._update_soundmode()
 | 
					        await self._update_woofer()
 | 
				
			||||||
        if self.__enable_advanced_audio:
 | 
					        await self._update_equalizer()
 | 
				
			||||||
            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):
 | 
					    async def _update_media(self):
 | 
				
			||||||
        if "audioTrackData" in self.device.status._attributes:
 | 
					        self.__media_artist = self.device.status._attributes["audioTrackData"].value[
 | 
				
			||||||
            self.__media_artist = self.device.status._attributes["audioTrackData"].value[
 | 
					            "artist"
 | 
				
			||||||
                "artist"
 | 
					        ]
 | 
				
			||||||
            ]
 | 
					        self.__media_title = self.device.status._attributes["audioTrackData"].value[
 | 
				
			||||||
            self.__media_title = self.device.status._attributes["audioTrackData"].value[
 | 
					            "title"
 | 
				
			||||||
                "title"
 | 
					        ]
 | 
				
			||||||
            ]
 | 
					        if self.__media_title != self.__old_media_title:
 | 
				
			||||||
            if self.__media_title != self.__old_media_title:
 | 
					            self.__old_media_title = self.__media_title
 | 
				
			||||||
                self.__old_media_title = self.__media_title
 | 
					            self.__media_cover_url_update_time = datetime.datetime.now()
 | 
				
			||||||
                self.__media_cover_url_update_time = datetime.datetime.now()
 | 
					            self.__media_cover_url = await self.get_song_title_artwork(
 | 
				
			||||||
                self.__media_cover_url = await self.get_song_title_artwork(
 | 
					                self.__media_artist, self.__media_title
 | 
				
			||||||
                    self.__media_artist, self.__media_title
 | 
					            )
 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def _update_soundmode(self):
 | 
					    async def _update_soundmode(self):
 | 
				
			||||||
        await self.update_execution_data(["/sec/networkaudio/soundmode"])
 | 
					        await self.update_execution_data(["/sec/networkaudio/soundmode"])
 | 
				
			||||||
        await asyncio.sleep(1)
 | 
					        await asyncio.sleep(0.1)
 | 
				
			||||||
        payload = await self.get_execute_status()
 | 
					        payload = await self.get_execute_status()
 | 
				
			||||||
        retry = 0
 | 
					        retry = 0
 | 
				
			||||||
        while (
 | 
					        while (
 | 
				
			||||||
                "x.com.samsung.networkaudio.supportedSoundmode" not in payload
 | 
					            "x.com.samsung.networkaudio.supportedSoundmode" not in payload
 | 
				
			||||||
                and retry < 10
 | 
					            and retry < 10
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
            await asyncio.sleep(1)
 | 
					            await asyncio.sleep(0.2)
 | 
				
			||||||
            payload = await self.get_execute_status()
 | 
					            payload = await self.get_execute_status()
 | 
				
			||||||
            retry += 1
 | 
					            retry += 1
 | 
				
			||||||
        if retry == 10:
 | 
					        if retry == 10:
 | 
				
			||||||
| 
						 | 
					@ -197,15 +179,7 @@ class SoundbarDevice:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def state(self) -> str:
 | 
					    def state(self) -> str:
 | 
				
			||||||
        if self.device.status.switch:
 | 
					        return "on" if self.device.status.switch else "off"
 | 
				
			||||||
            if self.device.status.playback_status == "playing":
 | 
					 | 
				
			||||||
                return "playing"
 | 
					 | 
				
			||||||
            if self.device.status.playback_status == "paused":
 | 
					 | 
				
			||||||
                return "paused"
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                return "on"
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return "off"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def switch_off(self):
 | 
					    async def switch_off(self):
 | 
				
			||||||
        await self.device.switch_off(True)
 | 
					        await self.device.switch_off(True)
 | 
				
			||||||
| 
						 | 
					@ -373,15 +347,11 @@ class SoundbarDevice:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def media_duration(self) -> int | None:
 | 
					    def media_duration(self) -> int | None:
 | 
				
			||||||
        attr = self.device.status.attributes.get("totalTime", None)
 | 
					        return self.device.status.attributes.get("totalTime").value
 | 
				
			||||||
        if attr:
 | 
					 | 
				
			||||||
            return attr.value
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def media_position(self) -> int | None:
 | 
					    def media_position(self) -> int | None:
 | 
				
			||||||
        attr = self.device.status.attributes.get("elapsedTime", None)
 | 
					        return self.device.status.attributes.get("elapsedTime").value
 | 
				
			||||||
        if attr:
 | 
					 | 
				
			||||||
            return attr.value
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def media_play(self):
 | 
					    async def media_play(self):
 | 
				
			||||||
        await self.device.play(True)
 | 
					        await self.device.play(True)
 | 
				
			||||||
| 
						 | 
					@ -392,12 +362,6 @@ class SoundbarDevice:
 | 
				
			||||||
    async def media_stop(self):
 | 
					    async def media_stop(self):
 | 
				
			||||||
        await self.device.stop(True)
 | 
					        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
 | 
					    @property
 | 
				
			||||||
    def media_app_name(self):
 | 
					    def media_app_name(self):
 | 
				
			||||||
        detail_status = self.device.status.attributes.get("detailName", None)
 | 
					        detail_status = self.device.status.attributes.get("detailName", None)
 | 
				
			||||||
| 
						 | 
					@ -409,54 +373,21 @@ class SoundbarDevice:
 | 
				
			||||||
    def media_coverart_updated(self) -> datetime.datetime:
 | 
					    def media_coverart_updated(self) -> datetime.datetime:
 | 
				
			||||||
        return self.__media_cover_url_update_time
 | 
					        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 ------------
 | 
					    # ------------ SUPPORT FUNCTIONS ------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def update_execution_data(self, argument: str):
 | 
					    async def update_execution_data(self, argument: str):
 | 
				
			||||||
        stuff = await self.device.command("main", "execute", "execute", argument)
 | 
					        return await self.device.command("main", "execute", "execute", argument)
 | 
				
			||||||
        return stuff
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def set_custom_execution_data(self, href: str, property: str, value):
 | 
					    async def set_custom_execution_data(self, href: str, property: str, value):
 | 
				
			||||||
        argument = [href, {property: 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):
 | 
					    async def get_execute_status(self):
 | 
				
			||||||
        url = f"https://api.smartthings.com/v1/devices/{self._device_id}/components/main/capabilities/execute/status"
 | 
					        url = f"https://api.smartthings.com/v1/devices/{self._device_id}/components/main/capabilities/execute/status"
 | 
				
			||||||
        request_headers = {"Authorization": "Bearer " + self._api_key}
 | 
					        request_headers = {"Authorization": "Bearer " + self._api_key}
 | 
				
			||||||
        resp = await self.__session.get(url, headers=request_headers)
 | 
					        resp = await self.__session.get(url, headers=request_headers)
 | 
				
			||||||
        dict_stuff = await resp.json()
 | 
					        dict = await resp.json()
 | 
				
			||||||
        return dict_stuff["data"]["value"]["payload"]
 | 
					        return dict["data"]["value"]["payload"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def get_song_title_artwork(self, artist: str, title: str) -> str:
 | 
					    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
 | 
					import logging
 | 
				
			||||||
from typing import Any
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pysmartthings
 | 
					import pysmartthings
 | 
				
			||||||
import voluptuous as vol
 | 
					import voluptuous as vol
 | 
				
			||||||
from homeassistant import config_entries
 | 
					from homeassistant import config_entries
 | 
				
			||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
 | 
					from homeassistant.helpers.aiohttp_client import async_get_clientsession
 | 
				
			||||||
from pysmartthings import APIResponseError
 | 
					from pysmartthings import APIResponseError
 | 
				
			||||||
from voluptuous import All, Range
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .const import (
 | 
					from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID,
 | 
				
			||||||
    CONF_ENTRY_API_KEY,
 | 
					                    CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN)
 | 
				
			||||||
    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,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_LOGGER = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,8 +23,20 @@ async def validate_input(api, device_id: str):
 | 
				
			||||||
class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
 | 
					class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
 | 
				
			||||||
    async def async_step_user(self, user_input=None):
 | 
					    async def async_step_user(self, user_input=None):
 | 
				
			||||||
        if user_input is not None:
 | 
					        if user_input is not None:
 | 
				
			||||||
            self.user_input = user_input
 | 
					            try:
 | 
				
			||||||
            return await self.async_step_device()
 | 
					                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(
 | 
					        return self.async_show_form(
 | 
				
			||||||
            step_id="user",
 | 
					            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_API_KEY): str,
 | 
				
			||||||
                    vol.Required(CONF_ENTRY_DEVICE_ID): str,
 | 
					                    vol.Required(CONF_ENTRY_DEVICE_ID): str,
 | 
				
			||||||
                    vol.Required(CONF_ENTRY_DEVICE_NAME): str,
 | 
					                    vol.Required(CONF_ENTRY_DEVICE_NAME): str,
 | 
				
			||||||
                    vol.Required(CONF_ENTRY_MAX_VOLUME, default=100): All(
 | 
					                    vol.Required(CONF_ENTRY_MAX_VOLUME): int,
 | 
				
			||||||
                        int, Range(min=1, max=100)
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					 | 
				
			||||||
    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_ID = "device_id"
 | 
				
			||||||
CONF_ENTRY_DEVICE_NAME = "device_name"
 | 
					CONF_ENTRY_DEVICE_NAME = "device_name"
 | 
				
			||||||
CONF_ENTRY_MAX_VOLUME = "device_volume"
 | 
					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
 | 
					DEFAULT_NAME = DOMAIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BUTTON = BUTTON_DOMAIN
 | 
					BUTTON = BUTTON_DOMAIN
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,16 +1,12 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "domain": "samsung_soundbar",
 | 
					  "domain": "samsung_soundbar",
 | 
				
			||||||
  "name": "Samsung Soundbar",
 | 
					  "name": "Samsung Soundbar",
 | 
				
			||||||
  "codeowners": [
 | 
					  "codeowners": ["@samuelspagl"],
 | 
				
			||||||
    "@samuelspagl"
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  "config_flow": true,
 | 
					  "config_flow": true,
 | 
				
			||||||
  "documentation": "https://www.example.com",
 | 
					  "documentation": "https://www.example.com",
 | 
				
			||||||
  "integration_type": "hub",
 | 
					  "integration_type": "hub",
 | 
				
			||||||
  "iot_class": "cloud_polling",
 | 
					  "iot_class": "cloud_polling",
 | 
				
			||||||
  "issue_tracker": "https://github.com/samuelspagl/ha_samsung_soundbar/issues",
 | 
					  "issue_tracker": "https://github.com/samuelspagl/ha_samsung_soundbar/issues",
 | 
				
			||||||
  "requirements": [
 | 
					  "requirements": ["pysmartthings"],
 | 
				
			||||||
    "pysmartthings==0.7.8"
 | 
					  "version": "0.3.0"
 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  "version": "0.4.1"
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,25 +1,16 @@
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
from typing import Any, Mapping
 | 
					from typing import Any, Mapping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from homeassistant.components.media_player import (
 | 
					from homeassistant.components.media_player import (DEVICE_CLASS_SPEAKER,
 | 
				
			||||||
    DEVICE_CLASS_SPEAKER,
 | 
					                                                   MediaPlayerEntity)
 | 
				
			||||||
    MediaPlayerEntity,
 | 
					from homeassistant.components.media_player.const import \
 | 
				
			||||||
)
 | 
					    MediaPlayerEntityFeature
 | 
				
			||||||
from homeassistant.components.media_player.const import MediaPlayerEntityFeature
 | 
					 | 
				
			||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
 | 
					from homeassistant.helpers.aiohttp_client import async_get_clientsession
 | 
				
			||||||
from homeassistant.helpers.entity import DeviceInfo, generate_entity_id
 | 
					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.SoundbarDevice import SoundbarDevice
 | 
				
			||||||
from .api_extension.const import SpeakerIdentifier, RearSpeakerMode
 | 
					from .const import (CONF_ENTRY_API_KEY, CONF_ENTRY_DEVICE_ID,
 | 
				
			||||||
from .const import (
 | 
					                    CONF_ENTRY_DEVICE_NAME, CONF_ENTRY_MAX_VOLUME, DOMAIN)
 | 
				
			||||||
    CONF_ENTRY_API_KEY,
 | 
					 | 
				
			||||||
    CONF_ENTRY_DEVICE_ID,
 | 
					 | 
				
			||||||
    CONF_ENTRY_DEVICE_NAME,
 | 
					 | 
				
			||||||
    CONF_ENTRY_MAX_VOLUME,
 | 
					 | 
				
			||||||
    DOMAIN,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from .models import DeviceConfig
 | 
					from .models import DeviceConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_LOGGER = logging.getLogger(__name__)
 | 
				
			||||||
| 
						 | 
					@ -36,82 +27,14 @@ SUPPORT_SMARTTHINGS_SOUNDBAR = (
 | 
				
			||||||
    | MediaPlayerEntityFeature.TURN_OFF
 | 
					    | MediaPlayerEntityFeature.TURN_OFF
 | 
				
			||||||
    | MediaPlayerEntityFeature.TURN_ON
 | 
					    | MediaPlayerEntityFeature.TURN_ON
 | 
				
			||||||
    | MediaPlayerEntityFeature.PLAY
 | 
					    | MediaPlayerEntityFeature.PLAY
 | 
				
			||||||
    | MediaPlayerEntityFeature.NEXT_TRACK
 | 
					 | 
				
			||||||
    | MediaPlayerEntityFeature.PREVIOUS_TRACK
 | 
					 | 
				
			||||||
    | MediaPlayerEntityFeature.STOP
 | 
					    | MediaPlayerEntityFeature.STOP
 | 
				
			||||||
    | MediaPlayerEntityFeature.SELECT_SOUND_MODE
 | 
					    | 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):
 | 
					async def async_setup_entry(hass, config_entry, async_add_entities):
 | 
				
			||||||
    domain_data = hass.data[DOMAIN]
 | 
					    domain_data = hass.data[DOMAIN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    addServices()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    entities = []
 | 
					    entities = []
 | 
				
			||||||
    for key in domain_data.devices:
 | 
					    for key in domain_data.devices:
 | 
				
			||||||
        device_config: DeviceConfig = domain_data.devices[key]
 | 
					        device_config: DeviceConfig = domain_data.devices[key]
 | 
				
			||||||
| 
						 | 
					@ -248,45 +171,9 @@ class SmartThingsSoundbarMediaPlayer(MediaPlayerEntity):
 | 
				
			||||||
    async def async_media_pause(self):
 | 
					    async def async_media_pause(self):
 | 
				
			||||||
        await self.device.media_pause()
 | 
					        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):
 | 
					    async def async_media_stop(self):
 | 
				
			||||||
        await self.device.media_stop()
 | 
					        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
 | 
					    # This property can be uncommented for some extra_attributes
 | 
				
			||||||
    # Still enabling this can cause side-effects.
 | 
					    # Still enabling this can cause side-effects.
 | 
				
			||||||
    # @property
 | 
					    # @property
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,12 @@
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from homeassistant.components.number import (
 | 
					from homeassistant.components.number import (NumberEntity,
 | 
				
			||||||
    NumberEntity,
 | 
					                                             NumberEntityDescription,
 | 
				
			||||||
    NumberEntityDescription,
 | 
					                                             NumberMode)
 | 
				
			||||||
    NumberMode,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from homeassistant.helpers.entity import DeviceInfo
 | 
					from homeassistant.helpers.entity import DeviceInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .api_extension.SoundbarDevice import SoundbarDevice
 | 
					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
 | 
					from .models import DeviceConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_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:
 | 
					    for key in domain_data.devices:
 | 
				
			||||||
        device_config: DeviceConfig = domain_data.devices[key]
 | 
					        device_config: DeviceConfig = domain_data.devices[key]
 | 
				
			||||||
        device = device_config.device
 | 
					        device = device_config.device
 | 
				
			||||||
        if device.device_id == config_entry.data.get(
 | 
					        if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID):
 | 
				
			||||||
            CONF_ENTRY_DEVICE_ID
 | 
					 | 
				
			||||||
        ) and config_entry.data.get(CONF_ENTRY_SETTINGS_WOOFER_NUMBER):
 | 
					 | 
				
			||||||
            entities.append(
 | 
					            entities.append(
 | 
				
			||||||
                SoundbarWooferNumberEntity(
 | 
					                SoundbarWooferNumberEntity(
 | 
				
			||||||
                    device,
 | 
					                    device,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,14 @@
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from homeassistant.components.number import (
 | 
					from homeassistant.components.number import (NumberEntity,
 | 
				
			||||||
    NumberEntity,
 | 
					                                             NumberEntityDescription,
 | 
				
			||||||
    NumberEntityDescription,
 | 
					                                             NumberMode)
 | 
				
			||||||
    NumberMode,
 | 
					from homeassistant.components.select import (SelectEntity,
 | 
				
			||||||
)
 | 
					                                             SelectEntityDescription)
 | 
				
			||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
 | 
					 | 
				
			||||||
from homeassistant.helpers.entity import DeviceInfo
 | 
					from homeassistant.helpers.entity import DeviceInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .api_extension.SoundbarDevice import SoundbarDevice
 | 
					from .api_extension.SoundbarDevice import SoundbarDevice
 | 
				
			||||||
from .const import (
 | 
					from .const import CONF_ENTRY_DEVICE_ID, DOMAIN
 | 
				
			||||||
    CONF_ENTRY_DEVICE_ID,
 | 
					 | 
				
			||||||
    CONF_ENTRY_SETTINGS_EQ_SELECTOR,
 | 
					 | 
				
			||||||
    CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR,
 | 
					 | 
				
			||||||
    DOMAIN,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from .models import DeviceConfig
 | 
					from .models import DeviceConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_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_config: DeviceConfig = domain_data.devices[key]
 | 
				
			||||||
        device = device_config.device
 | 
					        device = device_config.device
 | 
				
			||||||
        if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID):
 | 
					        if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID):
 | 
				
			||||||
            if config_entry.data.get(CONF_ENTRY_SETTINGS_EQ_SELECTOR):
 | 
					            entities.append(
 | 
				
			||||||
                entities.append(
 | 
					                EqPresetSelectEntity(device, "eq_preset", "mdi:tune-vertical")
 | 
				
			||||||
                    EqPresetSelectEntity(device, "eq_preset", "mdi:tune-vertical")
 | 
					            )
 | 
				
			||||||
                )
 | 
					            entities.append(
 | 
				
			||||||
            if config_entry.data.get(CONF_ENTRY_SETTINGS_SOUNDMODE_SELECTOR):
 | 
					                SoundModeSelectEntity(device, "sound_mode_preset", "mdi:surround-sound")
 | 
				
			||||||
                entities.append(
 | 
					            )
 | 
				
			||||||
                    SoundModeSelectEntity(
 | 
					 | 
				
			||||||
                        device, "sound_mode_preset", "mdi:surround-sound"
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            entities.append(
 | 
					            entities.append(
 | 
				
			||||||
                InputSelectEntity(device, "input_preset", "mdi:video-input-hdmi")
 | 
					                InputSelectEntity(device, "input_preset", "mdi:video-input-hdmi")
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,7 @@
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from homeassistant.components.sensor import (
 | 
					from homeassistant.components.sensor import (SensorDeviceClass, SensorEntity,
 | 
				
			||||||
    SensorDeviceClass,
 | 
					                                             SensorStateClass)
 | 
				
			||||||
    SensorEntity,
 | 
					 | 
				
			||||||
    SensorStateClass,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from homeassistant.helpers.entity import DeviceInfo
 | 
					from homeassistant.helpers.entity import DeviceInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .api_extension.SoundbarDevice import SoundbarDevice
 | 
					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 homeassistant.helpers.entity import DeviceInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .api_extension.SoundbarDevice import SoundbarDevice
 | 
					from .api_extension.SoundbarDevice import SoundbarDevice
 | 
				
			||||||
from .const import (
 | 
					from .const import CONF_ENTRY_DEVICE_ID, DOMAIN
 | 
				
			||||||
    CONF_ENTRY_DEVICE_ID,
 | 
					 | 
				
			||||||
    CONF_ENTRY_SETTINGS_ADVANCED_AUDIO_SWITCHES,
 | 
					 | 
				
			||||||
    DOMAIN,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from .models import DeviceConfig
 | 
					from .models import DeviceConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LOGGER = logging.getLogger(__name__)
 | 
					_LOGGER = logging.getLogger(__name__)
 | 
				
			||||||
| 
						 | 
					@ -22,37 +18,36 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
 | 
				
			||||||
        device_config: DeviceConfig = domain_data.devices[key]
 | 
					        device_config: DeviceConfig = domain_data.devices[key]
 | 
				
			||||||
        device = device_config.device
 | 
					        device = device_config.device
 | 
				
			||||||
        if device.device_id == config_entry.data.get(CONF_ENTRY_DEVICE_ID):
 | 
					        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(
 | 
				
			||||||
                entities.append(
 | 
					                SoundbarSwitchAdvancedAudio(
 | 
				
			||||||
                    SoundbarSwitchAdvancedAudio(
 | 
					                    device,
 | 
				
			||||||
                        device,
 | 
					                    "nightmode",
 | 
				
			||||||
                        "nightmode",
 | 
					                    lambda: device.night_mode,
 | 
				
			||||||
                        lambda: device.night_mode,
 | 
					                    device.set_night_mode,
 | 
				
			||||||
                        device.set_night_mode,
 | 
					                    device.set_night_mode,
 | 
				
			||||||
                        device.set_night_mode,
 | 
					                    "mdi:weather-night",
 | 
				
			||||||
                        "mdi:weather-night",
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                entities.append(
 | 
					            )
 | 
				
			||||||
                    SoundbarSwitchAdvancedAudio(
 | 
					            entities.append(
 | 
				
			||||||
                        device,
 | 
					                SoundbarSwitchAdvancedAudio(
 | 
				
			||||||
                        "bassmode",
 | 
					                    device,
 | 
				
			||||||
                        lambda: device.bass_mode,
 | 
					                    "bassmode",
 | 
				
			||||||
                        device.set_bass_mode,
 | 
					                    lambda: device.bass_mode,
 | 
				
			||||||
                        device.set_bass_mode,
 | 
					                    device.set_bass_mode,
 | 
				
			||||||
                        "mdi:speaker-wireless",
 | 
					                    device.set_bass_mode,
 | 
				
			||||||
                    )
 | 
					                    "mdi:speaker-wireless",
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                entities.append(
 | 
					            )
 | 
				
			||||||
                    SoundbarSwitchAdvancedAudio(
 | 
					            entities.append(
 | 
				
			||||||
                        device,
 | 
					                SoundbarSwitchAdvancedAudio(
 | 
				
			||||||
                        "voice_amplifier",
 | 
					                    device,
 | 
				
			||||||
                        lambda: device.voice_amplifier,
 | 
					                    "voice_amplifier",
 | 
				
			||||||
                        device.set_voice_amplifier,
 | 
					                    lambda: device.voice_amplifier,
 | 
				
			||||||
                        device.set_voice_amplifier,
 | 
					                    device.set_voice_amplifier,
 | 
				
			||||||
                        "mdi:account-voice",
 | 
					                    device.set_voice_amplifier,
 | 
				
			||||||
                    )
 | 
					                    "mdi:account-voice",
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
    async_add_entities(entities)
 | 
					    async_add_entities(entities)
 | 
				
			||||||
    return True
 | 
					    return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,144 +10,7 @@
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  "description": "Bitte gib deine Daten ein.",
 | 
					                  "description": "Bitte gib deine Daten ein.",
 | 
				
			||||||
                  "title": "Authentifizierung"
 | 
					                  "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."
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,152 +1,15 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    "config": {
 | 
					    "config":{
 | 
				
			||||||
        "step": {
 | 
					        "step":{
 | 
				
			||||||
            "user": {
 | 
					            "user":{
 | 
				
			||||||
                "data": {
 | 
					                "data": {
 | 
				
			||||||
                    "api_key": "SmartThings API Token",
 | 
					                    "api_key": "SmartThings API Token",
 | 
				
			||||||
                    "device_id": "Device ID",
 | 
					                    "device_id": "Device ID",
 | 
				
			||||||
                    "device_name": "Device Name",
 | 
					                    "device_name":"Device Name",
 | 
				
			||||||
                    "device_volume": "Max Volume (int)"
 | 
					                    "device_volume": "Max Volume (int)"
 | 
				
			||||||
                },
 | 
					                  },
 | 
				
			||||||
                "description": "Please enter your credentials.",
 | 
					                  "description": "Please enter your credentials.",
 | 
				
			||||||
                "title": "Authentication"
 | 
					                  "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."
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
export default defineAppConfig({
 | 
					export default defineAppConfig({
 | 
				
			||||||
  docus: {
 | 
					  docus: {
 | 
				
			||||||
    title: '🔊 Yassi',
 | 
					    title: 'YASSI',
 | 
				
			||||||
    description: 'Yet another Samsung Soundbar integration for Home Assistant',
 | 
					    description: 'HomeAssistant: Yet another Samsung soundbar integration',
 | 
				
			||||||
    image: 'https://user-images.githubusercontent.com/904724/185365452-87b7ca7b-6030-4813-a2db-5e65c785bf88.png',
 | 
					    image: 'https://user-images.githubusercontent.com/904724/185365452-87b7ca7b-6030-4813-a2db-5e65c785bf88.png',
 | 
				
			||||||
    socials: {
 | 
					    socials: {
 | 
				
			||||||
      github: 'samuelspagl/ha_samsung_soundbar',
 | 
					      github: 'samuelspagl/ha_samsung_soundbar',
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ export default defineAppConfig({
 | 
				
			||||||
      fluid: true
 | 
					      fluid: true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    header: {
 | 
					    header: {
 | 
				
			||||||
      logo: false,
 | 
					      logo: true,
 | 
				
			||||||
      showLinkIcon: true,
 | 
					      showLinkIcon: true,
 | 
				
			||||||
      exclude: [],
 | 
					      exclude: [],
 | 
				
			||||||
      fluid: true
 | 
					      fluid: true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,19 +5,24 @@ title: "YASSI"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
cta:
 | 
					cta:
 | 
				
			||||||
  - Why another HomeAssistant integration?
 | 
					  - Why another HomeAssistant integration?
 | 
				
			||||||
  - /first-things-first/why-another-integration
 | 
					  - #why-another-integration
 | 
				
			||||||
secondary:
 | 
					secondary:
 | 
				
			||||||
  - Open on GitHub →
 | 
					  - Open on GitHub →
 | 
				
			||||||
  - https://github.com/samuelspagl/ha_samsung_soundbar
 | 
					  - https://github.com/nuxtlabs/docus
 | 
				
			||||||
 | 
					snippet:
 | 
				
			||||||
 | 
					  - Custom Components
 | 
				
			||||||
 | 
					  - "- input selection"
 | 
				
			||||||
 | 
					  - "- soundmode selection"
 | 
				
			||||||
 | 
					  - "- eq-preset selection"
 | 
				
			||||||
 | 
					  - "- woofer settings"
 | 
				
			||||||
 | 
					  - "- other cool things"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#title
 | 
					#title
 | 
				
			||||||
Yassi - Yet another Samsung Soundbar integration
 | 
					Yassi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#description
 | 
					#description
 | 
				
			||||||
**YASSI** is a **HomeAssistant** integration for **Samsung Soundbars**. It enhances control, and adds features like equalizer settings. Install it via HACS or manually. Kudos to the original idea by @PiotrMachowski and @thierryBourbon! 🎶🔊
 | 
					Yet another Samsung soundbar integration for HomeAssistant
 | 
				
			||||||
 | 
					 | 
				
			||||||
[](https://my.home-assistant.io/redirect/hacs_repository/?owner=samuelspagl&repository=ha_samsung_soundbar&category=integration)
 | 
					 | 
				
			||||||
::
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
::card-grid
 | 
					::card-grid
 | 
				
			||||||
| 
						 | 
					@ -29,42 +34,36 @@ Quick-Start
 | 
				
			||||||
#default
 | 
					#default
 | 
				
			||||||
  ::card
 | 
					  ::card
 | 
				
			||||||
  #title
 | 
					  #title
 | 
				
			||||||
  ❓ Why another integration?
 | 
					  Getting Started.
 | 
				
			||||||
  #description
 | 
					 | 
				
			||||||
  Whether you thought about it or not, here is the answer ;).
 | 
					 | 
				
			||||||
  <br>
 | 
					 | 
				
			||||||
  <br>
 | 
					 | 
				
			||||||
  :button-link[click here]{href="/first-things-first/why-another-integration"}
 | 
					 | 
				
			||||||
  ::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ::card
 | 
					 | 
				
			||||||
  #title
 | 
					 | 
				
			||||||
  🚀 Getting Started
 | 
					 | 
				
			||||||
  #description
 | 
					  #description
 | 
				
			||||||
  Go, Go, Go... Here you will find information on "How to install / configure".
 | 
					  Go, Go, Go... Here you will find information on "How to install / configure".
 | 
				
			||||||
  <br>
 | 
					  <br>
 | 
				
			||||||
  <br>
 | 
					  <br>
 | 
				
			||||||
  :button-link[click here]{href="/first-things-first/getting-started"}
 | 
					  :button-link[click here]{href="/getting-started"}
 | 
				
			||||||
  ::
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ::card
 | 
					  ::card
 | 
				
			||||||
  #title
 | 
					  #title
 | 
				
			||||||
  ✨ Features
 | 
					  Features
 | 
				
			||||||
  #description
 | 
					  #description
 | 
				
			||||||
  Many cool features are awaiting your eyes to see ✨.
 | 
					  Many cool features are awaiting your eyes to see ✨.
 | 
				
			||||||
  <br>
 | 
					  <br>
 | 
				
			||||||
  <br>
 | 
					  <br>
 | 
				
			||||||
  :button-link[click here]{href="/features"}
 | 
					  :button-link[click here]{href="/features"}
 | 
				
			||||||
  ::
 | 
					  ::
 | 
				
			||||||
 | 
					 | 
				
			||||||
  ::card
 | 
					 | 
				
			||||||
  #title
 | 
					 | 
				
			||||||
  ⚙️ SmartThings API related information
 | 
					 | 
				
			||||||
  #description
 | 
					 | 
				
			||||||
  If you want to know some background information on how equalizer support and
 | 
					 | 
				
			||||||
  other things were implemented, this is your section.
 | 
					 | 
				
			||||||
  <br>
 | 
					 | 
				
			||||||
  <br>
 | 
					 | 
				
			||||||
  :button-link[click here]{href="/features"}
 | 
					 | 
				
			||||||
  ::
 | 
					 | 
				
			||||||
::
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Why another integration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The current Samsung Soundbar Integration by @PiotrMachowski / @thierryBourbon are already pretty cool.
 | 
				
			||||||
 | 
					But I wanted it to appear as a device, and base the Foundation on the `pysmartthings` python package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Additionally, I wanted full control over the *Soundmode* and more. So I tried out a few things with the API,
 | 
				
			||||||
 | 
					and found that also the **Subwoofer** as well as the **Equalizer** are controllable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I created a new wrapper around the `pysmartthings.DeviceEntity` specifically set up for a Soundbar, and this
 | 
				
			||||||
 | 
					is the Result.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I hope to integrate also controls for **surround speaker** as well as **Space-Fit Sound**, but as these features
 | 
				
			||||||
 | 
					are not documented... ;) 
 | 
				
			||||||
| 
						 | 
					@ -1,13 +0,0 @@
 | 
				
			||||||
# ❓ Why another integration
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The current Samsung Soundbar Integration by @PiotrMachowski / @thierryBourbon are already pretty cool.
 | 
					 | 
				
			||||||
But I wanted it to appear as a device, and base the Foundation on the `pysmartthings` python package.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Additionally, I wanted full control over the *Soundmode* and more. So I tried out a few things with the API,
 | 
					 | 
				
			||||||
and found that also the **Subwoofer** as well as the **Equalizer** are controllable.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
I created a new wrapper around the `pysmartthings.DeviceEntity` specifically set up for a Soundbar, and this
 | 
					 | 
				
			||||||
is the Result.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
I hope to integrate also controls for **surround speaker** as well as **Space-Fit Sound**, but as these features
 | 
					 | 
				
			||||||
are not documented... ;) 
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,43 +0,0 @@
 | 
				
			||||||
# 🚀 Getting Started with Yassi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Welcome to Yassi, the HomeAssistant integration for your Samsung Soundbar. This guide will help you get up and running in no time.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 📦 Installation Options
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### HACS (Home Assistant Community Store)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#### 🌟 Official Repository (Coming Soon)
 | 
					 | 
				
			||||||
The Yassi integration will be available through the official HACS repository shortly. Stay tuned for updates.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#### ➕ Custom Repository
 | 
					 | 
				
			||||||
In the meantime, you can manually add this repository to HACS:
 | 
					 | 
				
			||||||
1. Click the following button and 'open link':
 | 
					 | 
				
			||||||
[](https://my.home-assistant.io/redirect/hacs_repository/?owner=samuelspagl&repository=ha_samsung_soundbar&category=integration)
 | 
					 | 
				
			||||||
2. Click 'add' to add the custom repository.
 | 
					 | 
				
			||||||
3. Download 'Yassi' and restart Home Assistant.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### 📂 Manual Installation
 | 
					 | 
				
			||||||
If you prefer to install Yassi manually:
 | 
					 | 
				
			||||||
1. Download the latest release from the repository.
 | 
					 | 
				
			||||||
2. Extract and copy the `custom_components/samsung_soundbar` folder.
 | 
					 | 
				
			||||||
3. Paste it into the `config/custom_components/samsung_soundbar` directory of your HomeAssistant setup.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## ⚙️ Configuration Steps
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Once Yassi is installed, you can configure it via the HomeAssistant UI:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Go to 'Configuration' and then 'Integrations'.
 | 
					 | 
				
			||||||
2. Click on 'Add Integration' and search for 'Yassi'.
 | 
					 | 
				
			||||||
3. Enter the following details to complete the setup:
 | 
					 | 
				
			||||||
   - 🔑 SmartThings API Key: [Obtain it here](https://account.smartthings.com/tokens).
 | 
					 | 
				
			||||||
   - 🆔 Device ID: [Find your Soundbar's device ID here](https://my.smartthings.com/advanced/devices).
 | 
					 | 
				
			||||||
   - ㍻ Soundbar Name: Choose a name for easy identification.
 | 
					 | 
				
			||||||
   - 🔊 Max Volume: Set the maximum volume limit for your Soundbar.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Follow these steps, and you'll be enjoying seamless control over your Samsung Soundbar with Yassi in no time!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
::alert{type="info"}
 | 
					 | 
				
			||||||
The `🔊 Max Volume` setting will readjust the internal values of the `media_player` entity from 0-100 to 0-MaxVolume.
 | 
					 | 
				
			||||||
Therefore will the slider not display the same value as the one provided by the `sensor` entity, which will always display
 | 
					 | 
				
			||||||
the raw value retrieved from the SmartThings API.
 | 
					 | 
				
			||||||
::
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,17 +0,0 @@
 | 
				
			||||||
# ‼️ Issues and other things
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
As the creator of this personal and fun project, I am thrilled to see people using it. While I won’t always have immediate availability to address every request, I’ll do my best to fix issues and implement features. Thanks a lot in advance! 🙌
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Here are some best practices to help me help you:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. 🐞 GitHub Issues: For any issues or bugs, please submit them via GitHub Issues. ([🔗 click here](https://github.com/samuelspagl/ha_samsung_soundbar/issues/new))
 | 
					 | 
				
			||||||
2. 📋 Provide Details: Include essential information:
 | 
					 | 
				
			||||||
    - Home Assistant OS Version
 | 
					 | 
				
			||||||
    - Samsung Soundbar Model
 | 
					 | 
				
			||||||
    - Other Relevant Details (like debug logs)
 | 
					 | 
				
			||||||
3. 🎇 Icons for Fun:
 | 
					 | 
				
			||||||
    - 📦 = Feature Request
 | 
					 | 
				
			||||||
    - 🐛 = Bug Report
 | 
					 | 
				
			||||||
    - ❓ = General Questions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Let’s collaborate to enhance your soundbar experience! 🎶🔊
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					# Getting Started
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HACS (official)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> ⚠️ Not done yet, hopefully soon.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HACS (custom repository)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can add this repository as a custom repository to your hacs.
 | 
				
			||||||
 | 
					After you've done that, you can search for it like with the "official"
 | 
				
			||||||
 | 
					integrations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Manual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copy the contents of `custom_components/samsung_soundbar` to `config/custom_components/samsung_soundbar`
 | 
				
			||||||
 | 
					on your HomeAssistant instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After you installed the custom component, it should be possible to configure the integration
 | 
				
			||||||
 | 
					in the `device` settings of your HomeAssistant.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You will need:
 | 
				
			||||||
 | 
					- a SmartThings `api_key` [click here](https://account.smartthings.com/tokens)
 | 
				
			||||||
 | 
					- the `device_id` of your device [click here](https://my.smartthings.com/advanced/devices)
 | 
				
			||||||
 | 
					- a name for your Soundbar
 | 
				
			||||||
 | 
					- and a `max_volume`
 | 
				
			||||||
| 
						 | 
					@ -1,52 +1,35 @@
 | 
				
			||||||
# ✨ Features Overview
 | 
					# Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Yassi allows you to retrieve and set the status of various features on your Samsung Soundbar. Below is a breakdown of capabilities organized by entity type.
 | 
					**YASSI** and retrieve / set the status of the following features grouped as a device:
 | 
				
			||||||
 | 
					- `media_player`:
 | 
				
			||||||
 | 
					  - `on / off` [*read, write*]
 | 
				
			||||||
 | 
					  - `volume` (set, step) [*read, write*]
 | 
				
			||||||
 | 
					  - `input` (select) [*read*, write*]
 | 
				
			||||||
 | 
					  - `sound_mode` (select) [*read, write*]
 | 
				
			||||||
 | 
					  - `play` (button) [*write*]
 | 
				
			||||||
 | 
					  - `pause` (button) [*write*]
 | 
				
			||||||
 | 
					  - `media_artwork` (image) [*read*]
 | 
				
			||||||
 | 
					  - `media_title` (text) [*read*]
 | 
				
			||||||
 | 
					  - `media_artist` (text) [*read*]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## `media_player` Entity
 | 
					- `number`
 | 
				
			||||||
 | 
					  - **Woofer**
 | 
				
			||||||
 | 
					    - level (set) [*read, write*]
 | 
				
			||||||
 | 
					- `select`
 | 
				
			||||||
 | 
					  - **Input**
 | 
				
			||||||
 | 
					    - `input` [*read, write*]
 | 
				
			||||||
 | 
					    - `supported_inputs` [*read*]
 | 
				
			||||||
 | 
					  - **Soundmode**
 | 
				
			||||||
 | 
					    - `active_soundmode` [*read, write*]
 | 
				
			||||||
 | 
					    - `supported_soundmodes` [*read*]
 | 
				
			||||||
 | 
					  - **EQ-Preset**
 | 
				
			||||||
 | 
					    - `active_eq_preset` [*read, write*]
 | 
				
			||||||
 | 
					    - `supported_eq_preset` [*read*]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| **Feature**       | **Capability** | **Access Type** |
 | 
					- `button`
 | 
				
			||||||
|-------------------|----------------|-----------------|
 | 
					  - `night_mode` [*read, write*]
 | 
				
			||||||
| Power             | on / off       | Read, Write     |
 | 
					  - `voice_amplifier` [*read, write*]
 | 
				
			||||||
| Volume            | set, step      | Read, Write     |
 | 
					  - `bass_mode` [*read, write*]
 | 
				
			||||||
| Input Selection   | select         | Read, Write     |
 | 
					 | 
				
			||||||
| Sound Mode        | select         | Read, Write     |
 | 
					 | 
				
			||||||
| Playback Control  | play, pause    | Write           |
 | 
					 | 
				
			||||||
| Media Information | artwork, title, artist | Read    |
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## `number` Entity
 | 
					- `image`
 | 
				
			||||||
 | 
					  - `media_coverart` [*read*]
 | 
				
			||||||
| **Feature** | **Capability** | **Access Type** |
 | 
					 | 
				
			||||||
|-------------|----------------|-----------------|
 | 
					 | 
				
			||||||
| Woofer Level | set           | Read, Write     |
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## `select` Entity
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| **Feature**       | **Capability**        | **Access Type** |
 | 
					 | 
				
			||||||
|-------------------|-----------------------|-----------------|
 | 
					 | 
				
			||||||
| Input             | input, supported_inputs | Read, Write   |
 | 
					 | 
				
			||||||
| Sound Mode        | active_soundmode, supported_soundmodes | Read, Write |
 | 
					 | 
				
			||||||
| EQ-Preset         | active_eq_preset, supported_eq_preset | Read, Write |
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## `button` Entity
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| **Feature**       | **Capability** | **Access Type** |
 | 
					 | 
				
			||||||
|-------------------|----------------|-----------------|
 | 
					 | 
				
			||||||
| Night Mode        | toggle         | Read, Write     |
 | 
					 | 
				
			||||||
| Voice Amplifier   | toggle         | Read, Write     |
 | 
					 | 
				
			||||||
| Bass Mode         | toggle         | Read, Write     |
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## `image` Entity
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| **Feature**       | **Capability** | **Access Type** |
 | 
					 | 
				
			||||||
|-------------------|----------------|-----------------|
 | 
					 | 
				
			||||||
| Media Cover Art   | display        | Read            |
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## `sensor` Entity
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| **Feature** | **Capability**     | **Access Type** |
 | 
					 | 
				
			||||||
|-------------|--------------------|-----------------|
 | 
					 | 
				
			||||||
| Volume      | float sensor value | Read            |
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Hopefully this format provides a clear and concise view of what Yassi can do with your Samsung Soundbar, making it easier to understand and configure.
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,5 +3,5 @@
 | 
				
			||||||
  "filename": "samsung_soundbar.zip",
 | 
					  "filename": "samsung_soundbar.zip",
 | 
				
			||||||
  "render_readme": true,
 | 
					  "render_readme": true,
 | 
				
			||||||
  "zip_release": 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