Update StepSpeaker and Speaker interfaces in Alexa (#31444)
* Yield only one Speaker interface.
* Yield PowerController only is supported.
* Revert "Yield PowerController only is supported."
This reverts commit c0dbf7e4
* Add Alexa.Speaker interface properties.
* Refactor tests for Alexa.Speaker and Alexa.StepSpeaker.
* Code Smell Change.
* Fix R1705: Unnecessary "elif" after "return".
This commit is contained in:
parent
3f9dbe6845
commit
c8d9b83b24
3 changed files with 165 additions and 101 deletions
|
@ -1,5 +1,6 @@
|
||||||
"""Alexa capabilities."""
|
"""Alexa capabilities."""
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
|
|
||||||
from homeassistant.components import (
|
from homeassistant.components import (
|
||||||
cover,
|
cover,
|
||||||
|
@ -645,6 +646,43 @@ class AlexaSpeaker(AlexaCapability):
|
||||||
"""Return the Alexa API name of this interface."""
|
"""Return the Alexa API name of this interface."""
|
||||||
return "Alexa.Speaker"
|
return "Alexa.Speaker"
|
||||||
|
|
||||||
|
def properties_supported(self):
|
||||||
|
"""Return what properties this entity supports."""
|
||||||
|
properties = [{"name": "volume"}]
|
||||||
|
|
||||||
|
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
|
if supported & media_player.SUPPORT_VOLUME_MUTE:
|
||||||
|
properties.append({"name": "muted"})
|
||||||
|
|
||||||
|
return properties
|
||||||
|
|
||||||
|
def properties_proactively_reported(self):
|
||||||
|
"""Return True if properties asynchronously reported."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def properties_retrievable(self):
|
||||||
|
"""Return True if properties can be retrieved."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_property(self, name):
|
||||||
|
"""Read and return a property."""
|
||||||
|
if name == "volume":
|
||||||
|
current_level = self.entity.attributes.get(
|
||||||
|
media_player.ATTR_MEDIA_VOLUME_LEVEL
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
current = math.floor(int(current_level * 100))
|
||||||
|
except ZeroDivisionError:
|
||||||
|
current = 0
|
||||||
|
return current
|
||||||
|
|
||||||
|
if name == "muted":
|
||||||
|
return bool(
|
||||||
|
self.entity.attributes.get(media_player.ATTR_MEDIA_VOLUME_MUTED)
|
||||||
|
)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class AlexaStepSpeaker(AlexaCapability):
|
class AlexaStepSpeaker(AlexaCapability):
|
||||||
"""Implements Alexa.StepSpeaker.
|
"""Implements Alexa.StepSpeaker.
|
||||||
|
|
|
@ -508,12 +508,7 @@ class MediaPlayerCapabilities(AlexaEntity):
|
||||||
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
if supported & media_player.const.SUPPORT_VOLUME_SET:
|
if supported & media_player.const.SUPPORT_VOLUME_SET:
|
||||||
yield AlexaSpeaker(self.entity)
|
yield AlexaSpeaker(self.entity)
|
||||||
|
elif supported & media_player.const.SUPPORT_VOLUME_STEP:
|
||||||
step_volume_features = (
|
|
||||||
media_player.const.SUPPORT_VOLUME_MUTE
|
|
||||||
| media_player.const.SUPPORT_VOLUME_STEP
|
|
||||||
)
|
|
||||||
if supported & step_volume_features:
|
|
||||||
yield AlexaStepSpeaker(self.entity)
|
yield AlexaStepSpeaker(self.entity)
|
||||||
|
|
||||||
playback_features = (
|
playback_features = (
|
||||||
|
|
|
@ -16,6 +16,7 @@ from homeassistant.components.media_player.const import (
|
||||||
SUPPORT_TURN_ON,
|
SUPPORT_TURN_ON,
|
||||||
SUPPORT_VOLUME_MUTE,
|
SUPPORT_VOLUME_MUTE,
|
||||||
SUPPORT_VOLUME_SET,
|
SUPPORT_VOLUME_SET,
|
||||||
|
SUPPORT_VOLUME_STEP,
|
||||||
)
|
)
|
||||||
import homeassistant.components.vacuum as vacuum
|
import homeassistant.components.vacuum as vacuum
|
||||||
from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||||
|
@ -904,7 +905,6 @@ async def test_media_player(hass):
|
||||||
"Alexa.PlaybackStateReporter",
|
"Alexa.PlaybackStateReporter",
|
||||||
"Alexa.PowerController",
|
"Alexa.PowerController",
|
||||||
"Alexa.Speaker",
|
"Alexa.Speaker",
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
playback_capability = get_capability(capabilities, "Alexa.PlaybackController")
|
playback_capability = get_capability(capabilities, "Alexa.PlaybackController")
|
||||||
|
@ -958,93 +958,6 @@ async def test_media_player(hass):
|
||||||
hass,
|
hass,
|
||||||
)
|
)
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.Speaker",
|
|
||||||
"SetVolume",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_set",
|
|
||||||
hass,
|
|
||||||
payload={"volume": 50},
|
|
||||||
)
|
|
||||||
assert call.data["volume_level"] == 0.5
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.Speaker",
|
|
||||||
"SetMute",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_mute",
|
|
||||||
hass,
|
|
||||||
payload={"mute": True},
|
|
||||||
)
|
|
||||||
assert call.data["is_volume_muted"]
|
|
||||||
|
|
||||||
call, _, = await assert_request_calls_service(
|
|
||||||
"Alexa.Speaker",
|
|
||||||
"SetMute",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_mute",
|
|
||||||
hass,
|
|
||||||
payload={"mute": False},
|
|
||||||
)
|
|
||||||
assert not call.data["is_volume_muted"]
|
|
||||||
|
|
||||||
await assert_percentage_changes(
|
|
||||||
hass,
|
|
||||||
[(0.7, "-5"), (0.8, "5"), (0, "-80")],
|
|
||||||
"Alexa.Speaker",
|
|
||||||
"AdjustVolume",
|
|
||||||
"media_player#test",
|
|
||||||
"volume",
|
|
||||||
"media_player.volume_set",
|
|
||||||
"volume_level",
|
|
||||||
)
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
"SetMute",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_mute",
|
|
||||||
hass,
|
|
||||||
payload={"mute": True},
|
|
||||||
)
|
|
||||||
assert call.data["is_volume_muted"]
|
|
||||||
|
|
||||||
call, _, = await assert_request_calls_service(
|
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
"SetMute",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_mute",
|
|
||||||
hass,
|
|
||||||
payload={"mute": False},
|
|
||||||
)
|
|
||||||
assert not call.data["is_volume_muted"]
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
"AdjustVolume",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_up",
|
|
||||||
hass,
|
|
||||||
payload={"volumeSteps": 1, "volumeStepsDefault": False},
|
|
||||||
)
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
"AdjustVolume",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_down",
|
|
||||||
hass,
|
|
||||||
payload={"volumeSteps": -1, "volumeStepsDefault": False},
|
|
||||||
)
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
"AdjustVolume",
|
|
||||||
"media_player#test",
|
|
||||||
"media_player.volume_up",
|
|
||||||
hass,
|
|
||||||
payload={"volumeSteps": 10, "volumeStepsDefault": True},
|
|
||||||
)
|
|
||||||
call, _ = await assert_request_calls_service(
|
call, _ = await assert_request_calls_service(
|
||||||
"Alexa.ChannelController",
|
"Alexa.ChannelController",
|
||||||
"ChangeChannel",
|
"ChangeChannel",
|
||||||
|
@ -1140,7 +1053,6 @@ async def test_media_player_power(hass):
|
||||||
"Alexa.PowerController",
|
"Alexa.PowerController",
|
||||||
"Alexa.SeekController",
|
"Alexa.SeekController",
|
||||||
"Alexa.Speaker",
|
"Alexa.Speaker",
|
||||||
"Alexa.StepSpeaker",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
await assert_request_calls_service(
|
await assert_request_calls_service(
|
||||||
|
@ -1265,22 +1177,141 @@ async def test_media_player_inputs(hass):
|
||||||
|
|
||||||
|
|
||||||
async def test_media_player_speaker(hass):
|
async def test_media_player_speaker(hass):
|
||||||
"""Test media player discovery with device class speaker."""
|
"""Test media player with speaker interface."""
|
||||||
device = (
|
device = (
|
||||||
"media_player.test",
|
"media_player.test_speaker",
|
||||||
"off",
|
"off",
|
||||||
{
|
{
|
||||||
"friendly_name": "Test media player",
|
"friendly_name": "Test media player speaker",
|
||||||
"supported_features": 51765,
|
"supported_features": SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET,
|
||||||
"volume_level": 0.75,
|
"volume_level": 0.75,
|
||||||
"device_class": "speaker",
|
"device_class": "speaker",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
appliance = await discovery_test(device, hass)
|
appliance = await discovery_test(device, hass)
|
||||||
|
|
||||||
assert appliance["endpointId"] == "media_player#test"
|
assert appliance["endpointId"] == "media_player#test_speaker"
|
||||||
assert appliance["displayCategories"][0] == "SPEAKER"
|
assert appliance["displayCategories"][0] == "SPEAKER"
|
||||||
assert appliance["friendlyName"] == "Test media player"
|
assert appliance["friendlyName"] == "Test media player speaker"
|
||||||
|
|
||||||
|
capabilities = assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
"Alexa",
|
||||||
|
"Alexa.EndpointHealth",
|
||||||
|
"Alexa.PowerController",
|
||||||
|
"Alexa.Speaker",
|
||||||
|
)
|
||||||
|
|
||||||
|
speaker_capability = get_capability(capabilities, "Alexa.Speaker")
|
||||||
|
properties = speaker_capability["properties"]
|
||||||
|
assert {"name": "volume"} in properties["supported"]
|
||||||
|
assert {"name": "muted"} in properties["supported"]
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.Speaker",
|
||||||
|
"SetVolume",
|
||||||
|
"media_player#test_speaker",
|
||||||
|
"media_player.volume_set",
|
||||||
|
hass,
|
||||||
|
payload={"volume": 50},
|
||||||
|
)
|
||||||
|
assert call.data["volume_level"] == 0.5
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.Speaker",
|
||||||
|
"SetMute",
|
||||||
|
"media_player#test_speaker",
|
||||||
|
"media_player.volume_mute",
|
||||||
|
hass,
|
||||||
|
payload={"mute": True},
|
||||||
|
)
|
||||||
|
assert call.data["is_volume_muted"]
|
||||||
|
|
||||||
|
call, _, = await assert_request_calls_service(
|
||||||
|
"Alexa.Speaker",
|
||||||
|
"SetMute",
|
||||||
|
"media_player#test_speaker",
|
||||||
|
"media_player.volume_mute",
|
||||||
|
hass,
|
||||||
|
payload={"mute": False},
|
||||||
|
)
|
||||||
|
assert not call.data["is_volume_muted"]
|
||||||
|
|
||||||
|
await assert_percentage_changes(
|
||||||
|
hass,
|
||||||
|
[(0.7, "-5"), (0.8, "5"), (0, "-80")],
|
||||||
|
"Alexa.Speaker",
|
||||||
|
"AdjustVolume",
|
||||||
|
"media_player#test_speaker",
|
||||||
|
"volume",
|
||||||
|
"media_player.volume_set",
|
||||||
|
"volume_level",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_media_player_step_speaker(hass):
|
||||||
|
"""Test media player with step speaker interface."""
|
||||||
|
device = (
|
||||||
|
"media_player.test_step_speaker",
|
||||||
|
"off",
|
||||||
|
{
|
||||||
|
"friendly_name": "Test media player step speaker",
|
||||||
|
"supported_features": SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_STEP,
|
||||||
|
"device_class": "speaker",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
appliance = await discovery_test(device, hass)
|
||||||
|
|
||||||
|
assert appliance["endpointId"] == "media_player#test_step_speaker"
|
||||||
|
assert appliance["displayCategories"][0] == "SPEAKER"
|
||||||
|
assert appliance["friendlyName"] == "Test media player step speaker"
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.StepSpeaker",
|
||||||
|
"SetMute",
|
||||||
|
"media_player#test_step_speaker",
|
||||||
|
"media_player.volume_mute",
|
||||||
|
hass,
|
||||||
|
payload={"mute": True},
|
||||||
|
)
|
||||||
|
assert call.data["is_volume_muted"]
|
||||||
|
|
||||||
|
call, _, = await assert_request_calls_service(
|
||||||
|
"Alexa.StepSpeaker",
|
||||||
|
"SetMute",
|
||||||
|
"media_player#test_step_speaker",
|
||||||
|
"media_player.volume_mute",
|
||||||
|
hass,
|
||||||
|
payload={"mute": False},
|
||||||
|
)
|
||||||
|
assert not call.data["is_volume_muted"]
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.StepSpeaker",
|
||||||
|
"AdjustVolume",
|
||||||
|
"media_player#test_step_speaker",
|
||||||
|
"media_player.volume_up",
|
||||||
|
hass,
|
||||||
|
payload={"volumeSteps": 1, "volumeStepsDefault": False},
|
||||||
|
)
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.StepSpeaker",
|
||||||
|
"AdjustVolume",
|
||||||
|
"media_player#test_step_speaker",
|
||||||
|
"media_player.volume_down",
|
||||||
|
hass,
|
||||||
|
payload={"volumeSteps": -1, "volumeStepsDefault": False},
|
||||||
|
)
|
||||||
|
|
||||||
|
call, _ = await assert_request_calls_service(
|
||||||
|
"Alexa.StepSpeaker",
|
||||||
|
"AdjustVolume",
|
||||||
|
"media_player#test_step_speaker",
|
||||||
|
"media_player.volume_up",
|
||||||
|
hass,
|
||||||
|
payload={"volumeSteps": 10, "volumeStepsDefault": True},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_media_player_seek(hass):
|
async def test_media_player_seek(hass):
|
||||||
|
|
Loading…
Add table
Reference in a new issue