Allow switches to be represented as outlets on google assistant (#23149)

* Add device class support for switch to support outlet type

* Add a test for cover device class sync

* Drop remnant unused import
This commit is contained in:
Joakim Plate 2019-04-17 02:07:14 +02:00 committed by Paulus Schoutsen
parent e02a5f0b31
commit 1bfccd803f
5 changed files with 70 additions and 1 deletions

View file

@ -14,12 +14,13 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None):
class DemoSwitch(SwitchDevice):
"""Representation of a demo switch."""
def __init__(self, name, state, icon, assumed):
def __init__(self, name, state, icon, assumed, device_class=None):
"""Initialize the Demo switch."""
self._name = name or DEVICE_DEFAULT_NAME
self._state = state
self._icon = icon
self._assumed = assumed
self._device_class = device_class
@property
def should_poll(self):
@ -57,6 +58,11 @@ class DemoSwitch(SwitchDevice):
"""Return true if switch is on."""
return self._state
@property
def device_class(self):
"""Return device of entity."""
return self._device_class
def turn_on(self, **kwargs):
"""Turn the switch on."""
self._state = True

View file

@ -31,6 +31,7 @@ TYPE_THERMOSTAT = PREFIX_TYPES + 'THERMOSTAT'
TYPE_LOCK = PREFIX_TYPES + 'LOCK'
TYPE_BLINDS = PREFIX_TYPES + 'BLINDS'
TYPE_GARAGE = PREFIX_TYPES + 'GARAGE'
TYPE_OUTLET = PREFIX_TYPES + 'OUTLET'
SERVICE_REQUEST_SYNC = 'request_sync'
HOMEGRAPH_URL = 'https://homegraph.googleapis.com/'

View file

@ -32,6 +32,7 @@ from . import trait
from .const import (
TYPE_LIGHT, TYPE_LOCK, TYPE_SCENE, TYPE_SWITCH, TYPE_VACUUM,
TYPE_THERMOSTAT, TYPE_FAN, TYPE_CAMERA, TYPE_BLINDS, TYPE_GARAGE,
TYPE_OUTLET,
CONF_ALIASES, CONF_ROOM_HINT,
ERR_FUNCTION_NOT_SUPPORTED, ERR_PROTOCOL_ERROR, ERR_DEVICE_OFFLINE,
ERR_UNKNOWN_ERROR,
@ -60,6 +61,8 @@ DOMAIN_TO_GOOGLE_TYPES = {
DEVICE_CLASS_TO_GOOGLE_TYPES = {
(cover.DOMAIN, cover.DEVICE_CLASS_GARAGE): TYPE_GARAGE,
(switch.DOMAIN, switch.DEVICE_CLASS_SWITCH): TYPE_SWITCH,
(switch.DOMAIN, switch.DEVICE_CLASS_OUTLET): TYPE_OUTLET,
}

View file

@ -33,6 +33,16 @@ PROP_TO_ATTR = {
'today_energy_kwh': ATTR_TODAY_ENERGY_KWH,
}
DEVICE_CLASS_OUTLET = 'outlet'
DEVICE_CLASS_SWITCH = 'switch'
DEVICE_CLASSES = [
DEVICE_CLASS_OUTLET,
DEVICE_CLASS_SWITCH,
]
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES))
SWITCH_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
})
@ -113,3 +123,8 @@ class SwitchDevice(ToggleEntity):
data[attr] = value
return data
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return None

View file

@ -14,6 +14,7 @@ from homeassistant.components.google_assistant import (
const, trait, helpers, smart_home as sh,
EVENT_COMMAND_RECEIVED, EVENT_QUERY_RECEIVED, EVENT_SYNC_RECEIVED)
from homeassistant.components.demo.light import DemoLight
from homeassistant.components.demo.switch import DemoSwitch
from homeassistant.helpers import device_registry
from tests.common import (mock_device_registry, mock_registry,
@ -557,6 +558,49 @@ async def test_empty_name_doesnt_sync(hass):
}
@pytest.mark.parametrize("device_class,google_type", [
('non_existing_class', 'action.devices.types.SWITCH'),
('switch', 'action.devices.types.SWITCH'),
('outlet', 'action.devices.types.OUTLET')
])
async def test_device_class_switch(hass, device_class, google_type):
"""Test that a cover entity syncs to the correct device type."""
sensor = DemoSwitch(
'Demo Sensor',
state=False,
icon='mdi:switch',
assumed=False,
device_class=device_class
)
sensor.hass = hass
sensor.entity_id = 'switch.demo_sensor'
await sensor.async_update_ha_state()
result = await sh.async_handle_message(
hass, BASIC_CONFIG, 'test-agent',
{
"requestId": REQ_ID,
"inputs": [{
"intent": "action.devices.SYNC"
}]
})
assert result == {
'requestId': REQ_ID,
'payload': {
'agentUserId': 'test-agent',
'devices': [{
'attributes': {},
'id': 'switch.demo_sensor',
'name': {'name': 'Demo Sensor'},
'traits': ['action.devices.traits.OnOff'],
'type': google_type,
'willReportState': False
}]
}
}
async def test_query_disconnect(hass):
"""Test a disconnect message."""
result = await sh.async_handle_message(