mirror of
https://github.com/home-assistant/core.git
synced 2025-11-14 13:30:43 +00:00
Volume trait for google assistant (#23237)
* Add action.devices.traits.Volume * Drop media player from brightness trait * Factor out commands into separate functions * Drop support for explicit mute
This commit is contained in:
committed by
Paulus Schoutsen
parent
2863ac1068
commit
e11e6e1b04
@@ -60,6 +60,7 @@ TRAIT_LOCKUNLOCK = PREFIX_TRAITS + 'LockUnlock'
|
||||
TRAIT_FANSPEED = PREFIX_TRAITS + 'FanSpeed'
|
||||
TRAIT_MODES = PREFIX_TRAITS + 'Modes'
|
||||
TRAIT_OPENCLOSE = PREFIX_TRAITS + 'OpenClose'
|
||||
TRAIT_VOLUME = PREFIX_TRAITS + 'Volume'
|
||||
|
||||
PREFIX_COMMANDS = 'action.devices.commands.'
|
||||
COMMAND_ONOFF = PREFIX_COMMANDS + 'OnOff'
|
||||
@@ -79,6 +80,8 @@ COMMAND_LOCKUNLOCK = PREFIX_COMMANDS + 'LockUnlock'
|
||||
COMMAND_FANSPEED = PREFIX_COMMANDS + 'SetFanSpeed'
|
||||
COMMAND_MODES = PREFIX_COMMANDS + 'SetModes'
|
||||
COMMAND_OPENCLOSE = PREFIX_COMMANDS + 'OpenClose'
|
||||
COMMAND_SET_VOLUME = PREFIX_COMMANDS + 'setVolume'
|
||||
COMMAND_VOLUME_RELATIVE = PREFIX_COMMANDS + 'volumeRelative'
|
||||
|
||||
TRAITS = []
|
||||
|
||||
@@ -141,8 +144,6 @@ class BrightnessTrait(_Trait):
|
||||
"""Test if state is supported."""
|
||||
if domain == light.DOMAIN:
|
||||
return features & light.SUPPORT_BRIGHTNESS
|
||||
if domain == media_player.DOMAIN:
|
||||
return features & media_player.SUPPORT_VOLUME_SET
|
||||
|
||||
return False
|
||||
|
||||
@@ -160,13 +161,6 @@ class BrightnessTrait(_Trait):
|
||||
if brightness is not None:
|
||||
response['brightness'] = int(100 * (brightness / 255))
|
||||
|
||||
elif domain == media_player.DOMAIN:
|
||||
level = self.state.attributes.get(
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL)
|
||||
if level is not None:
|
||||
# Convert 0.0-1.0 to 0-255
|
||||
response['brightness'] = int(level * 100)
|
||||
|
||||
return response
|
||||
|
||||
async def execute(self, command, data, params, challenge):
|
||||
@@ -179,13 +173,6 @@ class BrightnessTrait(_Trait):
|
||||
ATTR_ENTITY_ID: self.state.entity_id,
|
||||
light.ATTR_BRIGHTNESS_PCT: params['brightness']
|
||||
}, blocking=True, context=data.context)
|
||||
elif domain == media_player.DOMAIN:
|
||||
await self.hass.services.async_call(
|
||||
media_player.DOMAIN, media_player.SERVICE_VOLUME_SET, {
|
||||
ATTR_ENTITY_ID: self.state.entity_id,
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL:
|
||||
params['brightness'] / 100
|
||||
}, blocking=True, context=data.context)
|
||||
|
||||
|
||||
@register_trait
|
||||
@@ -1132,6 +1119,81 @@ class OpenCloseTrait(_Trait):
|
||||
'Setting a position is not supported')
|
||||
|
||||
|
||||
@register_trait
|
||||
class VolumeTrait(_Trait):
|
||||
"""Trait to control brightness of a device.
|
||||
|
||||
https://developers.google.com/actions/smarthome/traits/volume
|
||||
"""
|
||||
|
||||
name = TRAIT_VOLUME
|
||||
commands = [
|
||||
COMMAND_SET_VOLUME,
|
||||
COMMAND_VOLUME_RELATIVE,
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def supported(domain, features, device_class):
|
||||
"""Test if state is supported."""
|
||||
if domain == media_player.DOMAIN:
|
||||
return features & media_player.SUPPORT_VOLUME_SET
|
||||
|
||||
return False
|
||||
|
||||
def sync_attributes(self):
|
||||
"""Return brightness attributes for a sync request."""
|
||||
return {}
|
||||
|
||||
def query_attributes(self):
|
||||
"""Return brightness query attributes."""
|
||||
response = {}
|
||||
|
||||
level = self.state.attributes.get(
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL)
|
||||
muted = self.state.attributes.get(
|
||||
media_player.ATTR_MEDIA_VOLUME_MUTED)
|
||||
if level is not None:
|
||||
# Convert 0.0-1.0 to 0-100
|
||||
response['currentVolume'] = int(level * 100)
|
||||
response['isMuted'] = bool(muted)
|
||||
|
||||
return response
|
||||
|
||||
async def _execute_set_volume(self, data, params):
|
||||
level = params['volumeLevel']
|
||||
|
||||
await self.hass.services.async_call(
|
||||
media_player.DOMAIN,
|
||||
media_player.SERVICE_VOLUME_SET, {
|
||||
ATTR_ENTITY_ID: self.state.entity_id,
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL:
|
||||
level / 100
|
||||
}, blocking=True, context=data.context)
|
||||
|
||||
async def _execute_volume_relative(self, data, params):
|
||||
# This could also support up/down commands using relativeSteps
|
||||
relative = params['volumeRelativeLevel']
|
||||
current = self.state.attributes.get(
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL)
|
||||
|
||||
await self.hass.services.async_call(
|
||||
media_player.DOMAIN, media_player.SERVICE_VOLUME_SET, {
|
||||
ATTR_ENTITY_ID: self.state.entity_id,
|
||||
media_player.ATTR_MEDIA_VOLUME_LEVEL:
|
||||
current + relative / 100
|
||||
}, blocking=True, context=data.context)
|
||||
|
||||
async def execute(self, command, data, params, challenge):
|
||||
"""Execute a brightness command."""
|
||||
if command == COMMAND_SET_VOLUME:
|
||||
await self._execute_set_volume(data, params)
|
||||
elif command == COMMAND_VOLUME_RELATIVE:
|
||||
await self._execute_volume_relative(data, params)
|
||||
else:
|
||||
raise SmartHomeError(
|
||||
ERR_NOT_SUPPORTED, 'Command not supported')
|
||||
|
||||
|
||||
def _verify_pin_challenge(data, challenge):
|
||||
"""Verify a pin challenge."""
|
||||
if not data.config.secure_devices_pin:
|
||||
|
||||
Reference in New Issue
Block a user