Skip to content

Commit

Permalink
migrate config flow to use options
Browse files Browse the repository at this point in the history
  • Loading branch information
kit-klein committed Jan 25, 2020
1 parent 7a6cf1e commit 2683d28
Show file tree
Hide file tree
Showing 9 changed files with 1,504 additions and 867 deletions.
77 changes: 47 additions & 30 deletions homeassistant/components/konnected/.translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,51 @@
"already_in_progress": "Config flow for device is already in progress.",
"cannot_connect": "Unable to connect to the Konnected Panel",
"not_konn_panel": "Not a recognized Konnected.io device",
"unknown": "Unknown error occurred"
"unknown": "Unknown error occurred",
"wrong_device": "MAC address of device at host does not match config entry"
},
"error": {
"linking": "Unknown linking error occurred.",
"register_failed": "Failed to register, please try again"
"cannot_connect": "Unable to connect to a Konnected Panel at {host}:{port}"
},
"step": {
"io": {
"confirm": {
"description": "Model: {model}\nHost: {host}\nPort: {port}\n\nUse config options to configure the IO and panel behavior.",
"title": "Konnected Device Ready"
},
"user": {
"data": {
"host": "Konnected device IP address",
"port": "Konnected device port"
},
"description": "Please enter the host information for your Konnected Panel.",
"title": "Discover Konnected Device"
}
},
"title": "Konnected.io"
},
"options": {
"abort": {},
"error": {},
"step": {
"options_binary": {
"data": {
"inverse": "Invert the open/close state",
"name": "Name (optional)",
"type": "Binary Sensor Type"
},
"description": "Please select the options for the binary sensor attached to {zone}",
"title": "Configure Binary Sensor"
},
"options_digital": {
"data": {
"name": "Name (optional)",
"poll_interval": "Poll Interval (minutes) (optional)",
"type": "Sensor Type"
},
"description": "Please select the options for the digital sensor attached to {zone}",
"title": "Configure Digital Sensor"
},
"options_io": {
"data": {
"1": "Zone 1",
"2": "Zone 2",
Expand All @@ -26,7 +63,7 @@
"description": "Discovered a {model} at {host}. Select the base configuration of each I/O below - depending on the I/O it may allow for binary sensors (open/close contacts), digital sensors (dht and ds18b20), or switchable outputs. You'll be able to configure detailed options in the next steps.",
"title": "Configure I/O"
},
"io_ext": {
"options_io_ext": {
"data": {
"10": "Zone 10",
"11": "Zone 11",
Expand All @@ -40,23 +77,12 @@
"description": "Select the configuration of the remaining I/O below. You'll be able to configure detailed options in the next steps.",
"title": "Configure Extended I/O"
},
"options_binary": {
"options_misc": {
"data": {
"inverse": "Invert the open/close state",
"name": "Name (optional)",
"type": "Binary Sensor Type"
"blink": "Blink panel LED on when sending state change"
},
"description": "Please select the options for the binary sensor attached to {zone}",
"title": "Configure Binary Sensor"
},
"options_digital": {
"data": {
"name": "Name (optional)",
"poll_interval": "Poll Interval (minutes) (optional)",
"type": "Sensor Type"
},
"description": "Please select the options for the digital sensor attached to {zone}",
"title": "Configure Digital Sensor"
"description": "Please select the desired behavior for your panel",
"title": "Configure Misc"
},
"options_switch": {
"data": {
Expand All @@ -68,17 +94,8 @@
},
"description": "Please select the output options for {zone}",
"title": "Configure Switchable Output"
},
"user": {
"data": {
"host": "Konnected device IP address",
"inverse": "Invert the open/close state",
"port": "Konnected device port"
},
"description": "Please enter the host information for your Konnected Panel.",
"title": "Discover Konnected Device"
}
},
"title": "Konnected.io"
"title": "Konnected Alarm Panel Options"
}
}
60 changes: 26 additions & 34 deletions homeassistant/components/konnected/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import hmac
import json
import logging
import random
import string

from aiohttp.hdrs import AUTHORIZATION
from aiohttp.web import Request, Response
Expand All @@ -30,11 +28,10 @@
STATE_ON,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, storage
from homeassistant.helpers import config_validation as cv

from .config_flow import ( # Loading the config flow file will register the flow
DEVICE_SCHEMA_YAML,
configured_devices,
)
from .const import (
CONF_ACTIVATION,
Expand All @@ -51,9 +48,6 @@

_LOGGER = logging.getLogger(__name__)

STORAGE_VERSION = 1
STORAGE_KEY = DOMAIN

# pylint: disable=no-value-for-parameter
CONFIG_SCHEMA = vol.Schema(
{
Expand All @@ -78,44 +72,23 @@ async def async_setup(hass: HomeAssistant, config: dict):
if cfg is None:
cfg = {}

store = storage.Store(hass, STORAGE_VERSION, STORAGE_KEY)
data_store = await store.async_load()
if data_store is None:
data_store = {}

# create a token if none in yaml or storage
access_token = (
cfg.get(CONF_ACCESS_TOKEN)
or data_store.get(CONF_ACCESS_TOKEN)
or "".join(random.choices(f"{string.ascii_uppercase}{string.digits}", k=20))
)
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {
CONF_ACCESS_TOKEN: access_token,
CONF_ACCESS_TOKEN: cfg.get(CONF_ACCESS_TOKEN),
CONF_API_HOST: cfg.get(CONF_API_HOST),
CONF_DEVICES: {},
"config_data": {},
}

# save off the access token
await store.async_save({CONF_ACCESS_TOKEN: access_token})

hass.http.register_view(KonnectedView(access_token))
hass.http.register_view(KonnectedView)

# Check if they have yaml configured devices
if CONF_DEVICES not in cfg:
return True

configured = configured_devices(hass)
devices = cfg[CONF_DEVICES]

if devices:
for device in devices:
# If configured, the panel is already imported and needs to be managed via config entries
if device["id"] in configured:
continue

# No existing config entry found, try importing it. Use
# Attempt to importing the cfg. Use
# hass.async_add_job to avoid a deadlock.
hass.async_create_task(
hass.config_entries.flow.async_init(
Expand Down Expand Up @@ -147,6 +120,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
# this will trigger a retry in the future
raise config_entries.ConfigEntryNotReady

entry.add_update_listener(async_entry_updated)
return True


Expand All @@ -166,16 +140,20 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
return unload_ok


async def async_entry_updated(hass: HomeAssistant, entry: ConfigEntry):
"""Reload the config entry when options change."""
await hass.config_entries.async_reload(entry.entry_id)


class KonnectedView(HomeAssistantView):
"""View creates an endpoint to receive push updates from the device."""

url = UPDATE_ENDPOINT
name = "api:konnected"
requires_auth = False # Uses access token from configuration

def __init__(self, auth_token):
def __init__(self):
"""Initialize the view."""
self.auth_token = auth_token

@staticmethod
def binary_value(state, activation):
Expand All @@ -190,7 +168,21 @@ async def update_sensor(self, request: Request, device_id) -> Response:
data = hass.data[DOMAIN]

auth = request.headers.get(AUTHORIZATION, None)
if auth is None or not hmac.compare_digest(f"Bearer {self.auth_token}", auth):
tokens = (
[hass.data[DOMAIN][CONF_ACCESS_TOKEN]]
if hass.data[DOMAIN].get(CONF_ACCESS_TOKEN)
else []
)
tokens.extend(
[
entry.data[CONF_ACCESS_TOKEN]
for entry in hass.config_entries.async_entries(DOMAIN)
]
)
if auth is None or not next(
(True for token in tokens if hmac.compare_digest(f"Bearer {token}", auth)),
False,
):
return self.json_message("unauthorized", status_code=HTTP_UNAUTHORIZED)

try: # Konnected 2.2.0 and above supports JSON payloads
Expand Down
Loading

0 comments on commit 2683d28

Please sign in to comment.