Clean up Google Assistant (#11375)

* Clean up Google Assistant

* Fix tests
This commit is contained in:
Paulus Schoutsen 2017-12-31 15:04:49 -08:00 committed by GitHub
parent fcbf7abdaa
commit fc8b25a71f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 165 additions and 183 deletions

View file

@ -1,4 +1,6 @@
"""Support for Google Assistant Smart Home API."""
import asyncio
from collections import namedtuple
import logging
# Typing imports
@ -10,6 +12,7 @@ from homeassistant.helpers.entity import Entity # NOQA
from homeassistant.core import HomeAssistant # NOQA
from homeassistant.util import color
from homeassistant.util.unit_system import UnitSystem # NOQA
from homeassistant.util.decorator import Registry
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES, ATTR_ENTITY_ID,
@ -34,6 +37,7 @@ from .const import (
CONF_ALIASES, CLIMATE_SUPPORTED_MODES
)
HANDLERS = Registry()
_LOGGER = logging.getLogger(__name__)
# Mapping is [actions schema, primary trait, optional features]
@ -65,9 +69,7 @@ MAPPING_COMPONENT = {
} # type: Dict[str, list]
def make_actions_response(request_id: str, payload: dict) -> dict:
"""Make response message."""
return {'requestId': request_id, 'payload': payload}
Config = namedtuple('GoogleAssistantConfig', 'should_expose,agent_user_id')
def entity_to_device(entity: Entity, units: UnitSystem):
@ -286,3 +288,98 @@ def determine_service(
return (SERVICE_TURN_OFF, service_data)
return (None, service_data)
@asyncio.coroutine
def async_handle_message(hass, config, message):
"""Handle incoming API messages."""
request_id = message.get('requestId') # type: str
inputs = message.get('inputs') # type: list
if len(inputs) > 1:
_LOGGER.warning('Got unexpected more than 1 input. %s', message)
# Only use first input
intent = inputs[0].get('intent')
payload = inputs[0].get('payload')
handler = HANDLERS.get(intent)
if handler:
result = yield from handler(hass, config, payload)
else:
result = {'errorCode': 'protocolError'}
return {'requestId': request_id, 'payload': result}
@HANDLERS.register('action.devices.SYNC')
@asyncio.coroutine
def async_devices_sync(hass, config, payload):
"""Handle action.devices.SYNC request."""
devices = []
for entity in hass.states.async_all():
if not config.should_expose(entity):
continue
device = entity_to_device(entity, hass.config.units)
if device is None:
_LOGGER.warning("No mapping for %s domain", entity.domain)
continue
devices.append(device)
return {
'agentUserId': config.agent_user_id,
'devices': devices,
}
@HANDLERS.register('action.devices.QUERY')
@asyncio.coroutine
def async_devices_query(hass, config, payload):
"""Handle action.devices.QUERY request."""
devices = {}
for device in payload.get('devices', []):
devid = device.get('id')
# In theory this should never happpen
if not devid:
_LOGGER.error('Device missing ID: %s', device)
continue
state = hass.states.get(devid)
if not state:
# If we can't find a state, the device is offline
devices[devid] = {'online': False}
devices[devid] = query_device(state, hass.config.units)
return {'devices': devices}
@HANDLERS.register('action.devices.EXECUTE')
@asyncio.coroutine
def handle_devices_execute(hass, config, payload):
"""Handle action.devices.EXECUTE request."""
commands = []
for command in payload.get('commands', []):
ent_ids = [ent.get('id') for ent in command.get('devices', [])]
for execution in command.get('execution'):
for eid in ent_ids:
success = False
domain = eid.split('.')[0]
(service, service_data) = determine_service(
eid, execution.get('command'), execution.get('params'),
hass.config.units)
if domain == "group":
domain = "homeassistant"
success = yield from hass.services.async_call(
domain, service, service_data, blocking=True)
result = {"ids": [eid], "states": {}}
if success:
result['status'] = 'SUCCESS'
else:
result['status'] = 'ERROR'
commands.append(result)
return {'commands': commands}