Implement soundtouch select source (#31669)
This commit is contained in:
parent
3fcd7866cc
commit
8f76f59b8b
5 changed files with 159 additions and 4 deletions
|
@ -2,6 +2,6 @@
|
|||
"domain": "soundtouch",
|
||||
"name": "Bose Soundtouch",
|
||||
"documentation": "https://www.home-assistant.io/integrations/soundtouch",
|
||||
"requirements": ["libsoundtouch==0.7.2"],
|
||||
"requirements": ["libsoundtouch==0.8"],
|
||||
"codeowners": []
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import logging
|
|||
import re
|
||||
|
||||
from libsoundtouch import soundtouch_device
|
||||
from libsoundtouch.utils import Source
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerEntity
|
||||
|
@ -12,6 +13,7 @@ from homeassistant.components.media_player.const import (
|
|||
SUPPORT_PLAY,
|
||||
SUPPORT_PLAY_MEDIA,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
SUPPORT_TURN_OFF,
|
||||
SUPPORT_TURN_ON,
|
||||
SUPPORT_VOLUME_MUTE,
|
||||
|
@ -80,6 +82,7 @@ SUPPORT_SOUNDTOUCH = (
|
|||
| SUPPORT_TURN_ON
|
||||
| SUPPORT_PLAY
|
||||
| SUPPORT_PLAY_MEDIA
|
||||
| SUPPORT_SELECT_SOURCE
|
||||
)
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
|
@ -234,6 +237,19 @@ class SoundTouchDevice(MediaPlayerEntity):
|
|||
|
||||
return MAP_STATUS.get(self._status.play_status, STATE_UNAVAILABLE)
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
"""Name of the current input source."""
|
||||
return self._status.source
|
||||
|
||||
@property
|
||||
def source_list(self):
|
||||
"""List of available input sources."""
|
||||
return [
|
||||
Source.AUX.value,
|
||||
Source.BLUETOOTH.value,
|
||||
]
|
||||
|
||||
@property
|
||||
def is_volume_muted(self):
|
||||
"""Boolean if volume is currently muted."""
|
||||
|
@ -357,6 +373,17 @@ class SoundTouchDevice(MediaPlayerEntity):
|
|||
else:
|
||||
_LOGGER.warning("Unable to find preset with id %s", media_id)
|
||||
|
||||
def select_source(self, source):
|
||||
"""Select input source."""
|
||||
if source == Source.AUX.value:
|
||||
_LOGGER.debug("Selecting source AUX")
|
||||
self._device.select_source_aux()
|
||||
elif source == Source.BLUETOOTH.value:
|
||||
_LOGGER.debug("Selecting source Bluetooth")
|
||||
self._device.select_source_bluetooth()
|
||||
else:
|
||||
_LOGGER.warning("Source %s is not supported", source)
|
||||
|
||||
def create_zone(self, slaves):
|
||||
"""
|
||||
Create a zone (multi-room) and play on selected devices.
|
||||
|
|
|
@ -837,7 +837,7 @@ libpyvivotek==0.4.0
|
|||
librouteros==3.0.0
|
||||
|
||||
# homeassistant.components.soundtouch
|
||||
libsoundtouch==0.7.2
|
||||
libsoundtouch==0.8
|
||||
|
||||
# homeassistant.components.life360
|
||||
life360==4.1.1
|
||||
|
|
|
@ -356,7 +356,7 @@ libpurecool==0.6.1
|
|||
librouteros==3.0.0
|
||||
|
||||
# homeassistant.components.soundtouch
|
||||
libsoundtouch==0.7.2
|
||||
libsoundtouch==0.8
|
||||
|
||||
# homeassistant.components.logi_circle
|
||||
logi_circle==0.2.2
|
||||
|
|
|
@ -11,6 +11,7 @@ from libsoundtouch.device import (
|
|||
import pytest
|
||||
|
||||
from homeassistant.components.media_player.const import (
|
||||
ATTR_INPUT_SOURCE,
|
||||
ATTR_MEDIA_CONTENT_ID,
|
||||
ATTR_MEDIA_CONTENT_TYPE,
|
||||
)
|
||||
|
@ -254,6 +255,36 @@ class MockStatusPause(Status):
|
|||
self._station_name = None
|
||||
|
||||
|
||||
class MockStatusPlayingAux(Status):
|
||||
"""Mock status AUX."""
|
||||
|
||||
def __init__(self):
|
||||
"""Init the class."""
|
||||
self._source = "AUX"
|
||||
self._play_status = "PLAY_STATE"
|
||||
self._image = "image.url"
|
||||
self._artist = None
|
||||
self._track = None
|
||||
self._album = None
|
||||
self._duration = None
|
||||
self._station_name = None
|
||||
|
||||
|
||||
class MockStatusPlayingBluetooth(Status):
|
||||
"""Mock status Bluetooth."""
|
||||
|
||||
def __init__(self):
|
||||
"""Init the class."""
|
||||
self._source = "BLUETOOTH"
|
||||
self._play_status = "PLAY_STATE"
|
||||
self._image = "image.url"
|
||||
self._artist = "artist"
|
||||
self._track = "track"
|
||||
self._album = "album"
|
||||
self._duration = None
|
||||
self._station_name = None
|
||||
|
||||
|
||||
async def test_ensure_setup_config(mocked_status, mocked_volume, hass, one_device):
|
||||
"""Test setup OK with custom config."""
|
||||
await setup_soundtouch(
|
||||
|
@ -365,6 +396,37 @@ async def test_playing_radio(mocked_status, mocked_volume, hass, one_device):
|
|||
assert entity_1_state.attributes["media_title"] == "station"
|
||||
|
||||
|
||||
async def test_playing_aux(mocked_status, mocked_volume, hass, one_device):
|
||||
"""Test playing AUX info."""
|
||||
mocked_status.side_effect = MockStatusPlayingAux
|
||||
await setup_soundtouch(hass, DEVICE_1_CONFIG)
|
||||
|
||||
assert one_device.call_count == 1
|
||||
assert mocked_status.call_count == 2
|
||||
assert mocked_volume.call_count == 2
|
||||
|
||||
entity_1_state = hass.states.get("media_player.soundtouch_1")
|
||||
assert entity_1_state.state == STATE_PLAYING
|
||||
assert entity_1_state.attributes["source"] == "AUX"
|
||||
|
||||
|
||||
async def test_playing_bluetooth(mocked_status, mocked_volume, hass, one_device):
|
||||
"""Test playing Bluetooth info."""
|
||||
mocked_status.side_effect = MockStatusPlayingBluetooth
|
||||
await setup_soundtouch(hass, DEVICE_1_CONFIG)
|
||||
|
||||
assert one_device.call_count == 1
|
||||
assert mocked_status.call_count == 2
|
||||
assert mocked_volume.call_count == 2
|
||||
|
||||
entity_1_state = hass.states.get("media_player.soundtouch_1")
|
||||
assert entity_1_state.state == STATE_PLAYING
|
||||
assert entity_1_state.attributes["source"] == "BLUETOOTH"
|
||||
assert entity_1_state.attributes["media_track"] == "track"
|
||||
assert entity_1_state.attributes["media_artist"] == "artist"
|
||||
assert entity_1_state.attributes["media_album_name"] == "album"
|
||||
|
||||
|
||||
async def test_get_volume_level(mocked_status, mocked_volume, hass, one_device):
|
||||
"""Test volume level."""
|
||||
mocked_volume.side_effect = MockVolume
|
||||
|
@ -426,7 +488,7 @@ async def test_media_commands(mocked_status, mocked_volume, hass, one_device):
|
|||
assert mocked_volume.call_count == 2
|
||||
|
||||
entity_1_state = hass.states.get("media_player.soundtouch_1")
|
||||
assert entity_1_state.attributes["supported_features"] == 18365
|
||||
assert entity_1_state.attributes["supported_features"] == 20413
|
||||
|
||||
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.power_off")
|
||||
|
@ -694,6 +756,72 @@ async def test_play_media_url(
|
|||
mocked_play_url.assert_called_with("http://fqdn/file.mp3")
|
||||
|
||||
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.select_source_aux")
|
||||
async def test_select_source_aux(
|
||||
mocked_select_source_aux, mocked_status, mocked_volume, hass, one_device
|
||||
):
|
||||
"""Test select AUX."""
|
||||
await setup_soundtouch(hass, DEVICE_1_CONFIG)
|
||||
|
||||
assert mocked_select_source_aux.call_count == 0
|
||||
await hass.services.async_call(
|
||||
"media_player",
|
||||
"select_source",
|
||||
{"entity_id": "media_player.soundtouch_1", ATTR_INPUT_SOURCE: "AUX"},
|
||||
True,
|
||||
)
|
||||
|
||||
assert mocked_select_source_aux.call_count == 1
|
||||
|
||||
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.select_source_bluetooth")
|
||||
async def test_select_source_bluetooth(
|
||||
mocked_select_source_bluetooth, mocked_status, mocked_volume, hass, one_device
|
||||
):
|
||||
"""Test select Bluetooth."""
|
||||
await setup_soundtouch(hass, DEVICE_1_CONFIG)
|
||||
|
||||
assert mocked_select_source_bluetooth.call_count == 0
|
||||
await hass.services.async_call(
|
||||
"media_player",
|
||||
"select_source",
|
||||
{"entity_id": "media_player.soundtouch_1", ATTR_INPUT_SOURCE: "BLUETOOTH"},
|
||||
True,
|
||||
)
|
||||
|
||||
assert mocked_select_source_bluetooth.call_count == 1
|
||||
|
||||
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.select_source_bluetooth")
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.select_source_aux")
|
||||
async def test_select_source_invalid_source(
|
||||
mocked_select_source_aux,
|
||||
mocked_select_source_bluetooth,
|
||||
mocked_status,
|
||||
mocked_volume,
|
||||
hass,
|
||||
one_device,
|
||||
):
|
||||
"""Test select unsupported source."""
|
||||
await setup_soundtouch(hass, DEVICE_1_CONFIG)
|
||||
|
||||
assert mocked_select_source_aux.call_count == 0
|
||||
assert mocked_select_source_bluetooth.call_count == 0
|
||||
|
||||
await hass.services.async_call(
|
||||
"media_player",
|
||||
"select_source",
|
||||
{
|
||||
"entity_id": "media_player.soundtouch_1",
|
||||
ATTR_INPUT_SOURCE: "SOMETHING_UNSUPPORTED",
|
||||
},
|
||||
True,
|
||||
)
|
||||
|
||||
assert mocked_select_source_aux.call_count == 0
|
||||
assert mocked_select_source_bluetooth.call_count == 0
|
||||
|
||||
|
||||
@patch("libsoundtouch.device.SoundTouchDevice.create_zone")
|
||||
async def test_play_everywhere(
|
||||
mocked_create_zone, mocked_status, mocked_volume, hass, two_zones
|
||||
|
|
Loading…
Add table
Reference in a new issue