Hass.io discovery flow deconz (#22623)

* Add Hass.io deCONZ discovery flow

* add bridge ID

* fix attribute

* fix strings

* Address comments

* Add test

* Add only instance / changed maybe later
This commit is contained in:
Pascal Vizeli 2019-04-03 04:23:33 +02:00 committed by Paulus Schoutsen
parent 22d93a74a4
commit 5613e8bb60
5 changed files with 116 additions and 9 deletions

View File

@ -1,17 +1,18 @@
"""Config flow to configure deCONZ component."""
import asyncio
import async_timeout
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client
from .const import (
CONF_ALLOW_DECONZ_GROUPS, CONF_ALLOW_CLIP_SENSOR, DEFAULT_PORT, DOMAIN)
CONF_BRIDGEID = 'bridgeid'
CONF_ALLOW_CLIP_SENSOR, CONF_ALLOW_DECONZ_GROUPS, CONF_BRIDGEID,
DEFAULT_ALLOW_CLIP_SENSOR, DEFAULT_ALLOW_DECONZ_GROUPS, DEFAULT_PORT,
DOMAIN)
@callback
@ -28,6 +29,8 @@ class DeconzFlowHandler(config_entries.ConfigFlow):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
_hassio_discovery = None
def __init__(self):
"""Initialize the deCONZ config flow."""
self.bridges = []
@ -151,8 +154,10 @@ class DeconzFlowHandler(config_entries.ConfigFlow):
return self.async_show_form(
step_id='options',
data_schema=vol.Schema({
vol.Optional(CONF_ALLOW_CLIP_SENSOR): bool,
vol.Optional(CONF_ALLOW_DECONZ_GROUPS): bool,
vol.Optional(CONF_ALLOW_CLIP_SENSOR,
default=DEFAULT_ALLOW_CLIP_SENSOR): bool,
vol.Optional(CONF_ALLOW_DECONZ_GROUPS,
default=DEFAULT_ALLOW_DECONZ_GROUPS): bool,
}),
)
@ -191,3 +196,45 @@ class DeconzFlowHandler(config_entries.ConfigFlow):
user_input = {CONF_ALLOW_CLIP_SENSOR: True,
CONF_ALLOW_DECONZ_GROUPS: True}
return await self.async_step_options(user_input=user_input)
async def async_step_hassio(self, user_input=None):
"""Prepare configuration for a Hass.io deCONZ bridge.
This flow is triggered by the discovery component.
"""
if configured_hosts(self.hass):
return self.async_abort(reason='one_instance_only')
self._hassio_discovery = user_input
return await self.async_step_hassio_confirm()
async def async_step_hassio_confirm(self, user_input=None):
"""Confirm a Hass.io discovery."""
if user_input is not None:
data = self._hassio_discovery
return self.async_create_entry(
title=data['addon'], data={
CONF_HOST: data[CONF_HOST],
CONF_PORT: data[CONF_PORT],
CONF_BRIDGEID: data['serial'],
CONF_API_KEY: data[CONF_API_KEY],
CONF_ALLOW_CLIP_SENSOR:
user_input[CONF_ALLOW_CLIP_SENSOR],
CONF_ALLOW_DECONZ_GROUPS:
user_input[CONF_ALLOW_DECONZ_GROUPS],
})
return self.async_show_form(
step_id='hassio_confirm',
description_placeholders={
'addon': self._hassio_discovery['addon']
},
data_schema=vol.Schema({
vol.Optional(CONF_ALLOW_CLIP_SENSOR,
default=DEFAULT_ALLOW_CLIP_SENSOR): bool,
vol.Optional(CONF_ALLOW_DECONZ_GROUPS,
default=DEFAULT_ALLOW_DECONZ_GROUPS): bool,
})
)

View File

@ -6,9 +6,12 @@ _LOGGER = logging.getLogger('.')
DOMAIN = 'deconz'
DEFAULT_PORT = 80
DEFAULT_ALLOW_CLIP_SENSOR = False
DEFAULT_ALLOW_DECONZ_GROUPS = False
CONF_ALLOW_CLIP_SENSOR = 'allow_clip_sensor'
CONF_ALLOW_DECONZ_GROUPS = 'allow_deconz_groups'
CONF_BRIDGEID = 'bridgeid'
SUPPORTED_PLATFORMS = ['binary_sensor', 'climate', 'cover',
'light', 'scene', 'sensor', 'switch']

View File

@ -19,6 +19,14 @@
"allow_clip_sensor": "Allow importing virtual sensors",
"allow_deconz_groups": "Allow importing deCONZ groups"
}
},
"hassio_confirm": {
"title": "deCONZ Zigbee gateway via Hass.io add-on",
"description": "Do you want to configure Home Assistant to connect to the deCONZ gateway provided by the hass.io add-on {addon}?",
"data": {
"allow_clip_sensor": "Allow importing virtual sensors",
"allow_deconz_groups": "Allow importing deCONZ groups"
}
}
},
"error": {
@ -30,4 +38,4 @@
"one_instance_only": "Component only supports one deCONZ instance"
}
}
}
}

View File

@ -81,7 +81,7 @@ class HassIODiscovery(HomeAssistantView):
service = data[ATTR_SERVICE]
config_data = data[ATTR_CONFIG]
# Read addinional Add-on info
# Read additional Add-on info
try:
addon_info = await self.hassio.get_addon_info(data[ATTR_ADDON])
except HassioAPIError as err:
@ -98,7 +98,7 @@ class HassIODiscovery(HomeAssistantView):
service = data[ATTR_SERVICE]
uuid = data[ATTR_UUID]
# Check if realy deletet / prevent injections
# Check if really deletet / prevent injections
try:
data = await self.hassio.get_discovery_message(uuid)
except HassioAPIError:

View File

@ -265,3 +265,52 @@ async def test_options(hass, aioclient_mock):
'allow_clip_sensor': False,
'allow_deconz_groups': False
}
async def test_hassio_single_instance(hass):
"""Test we only allow a single config flow."""
MockConfigEntry(domain='deconz', data={
'host': '1.2.3.4'
}).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
'deconz', context={'source': 'hassio'})
assert result['type'] == 'abort'
assert result['reason'] == 'one_instance_only'
async def test_hassio_confirm(hass):
"""Test we can finish a config flow."""
result = await hass.config_entries.flow.async_init(
'deconz',
data={
'addon': 'Mock Addon',
'host': 'mock-deconz',
'port': 8080,
'serial': 'aa:bb',
'api_key': '1234567890ABCDEF',
},
context={'source': 'hassio'}
)
assert result['type'] == 'form'
assert result['step_id'] == 'hassio_confirm'
assert result['description_placeholders'] == {
'addon': 'Mock Addon',
}
result = await hass.config_entries.flow.async_configure(
result['flow_id'], {
'allow_clip_sensor': True,
'allow_deconz_groups': True,
}
)
assert result['type'] == 'create_entry'
assert result['result'].data == {
'host': 'mock-deconz',
'port': 8080,
'bridgeid': 'aa:bb',
'api_key': '1234567890ABCDEF',
'allow_clip_sensor': True,
'allow_deconz_groups': True,
}