Dedup and clarify imported konnected config flows (#32138)
* dedup config flows * use default (imported) options until user goes thru options flow * address pr feedback * correct key used to distinguish pro modelpull/32094/head^2
parent
438c4acf07
commit
5488389244
|
@ -11,9 +11,13 @@
|
|||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Model: {model}\nHost: {host}\nPort: {port}\n\nYou can configure the IO and panel behavior in the Konnected Alarm Panel settings.",
|
||||
"description": "Model: {model}\nID: {id}\nHost: {host}\nPort: {port}\n\nYou can configure the IO and panel behavior in the Konnected Alarm Panel settings.",
|
||||
"title": "Konnected Device Ready"
|
||||
},
|
||||
"import_confirm": {
|
||||
"description": "A Konnected Alarm Panel with ID {id} has been discovered in configuration.yaml. This flow will allow you to import it into a config entry.",
|
||||
"title": "Import Konnected Device"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Konnected device IP address",
|
||||
|
@ -29,6 +33,7 @@
|
|||
"abort": {
|
||||
"not_konn_panel": "Not a recognized Konnected.io device"
|
||||
},
|
||||
"error": {},
|
||||
"step": {
|
||||
"options_binary": {
|
||||
"data": {
|
||||
|
|
|
@ -32,6 +32,7 @@ from homeassistant.helpers import config_validation as cv
|
|||
from .const import (
|
||||
CONF_ACTIVATION,
|
||||
CONF_BLINK,
|
||||
CONF_DEFAULT_OPTIONS,
|
||||
CONF_DISCOVERY,
|
||||
CONF_INVERSE,
|
||||
CONF_MODEL,
|
||||
|
@ -138,7 +139,6 @@ OPTIONS_SCHEMA = vol.Schema(
|
|||
extra=vol.REMOVE_EXTRA,
|
||||
)
|
||||
|
||||
CONF_DEFAULT_OPTIONS = "default_options"
|
||||
CONFIG_ENTRY_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ID): cv.matches_regex("[0-9a-f]{12}"),
|
||||
|
@ -158,6 +158,9 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
|
||||
|
||||
# class variable to store/share discovered host information
|
||||
discovered_hosts = {}
|
||||
|
||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||
|
||||
def __init__(self):
|
||||
|
@ -178,7 +181,7 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
except (CannotConnect, KeyError):
|
||||
raise CannotConnect
|
||||
else:
|
||||
self.data[CONF_MODEL] = status.get("name", KONN_MODEL)
|
||||
self.data[CONF_MODEL] = status.get("model", KONN_MODEL)
|
||||
self.data[CONF_ACCESS_TOKEN] = "".join(
|
||||
random.choices(f"{string.ascii_uppercase}{string.digits}", k=20)
|
||||
)
|
||||
|
@ -196,6 +199,7 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
# config schema ensures we have port if we have host
|
||||
if device_config.get(CONF_HOST):
|
||||
# automatically connect if we have host info
|
||||
return await self.async_step_user(
|
||||
user_input={
|
||||
CONF_HOST: device_config[CONF_HOST],
|
||||
|
@ -205,6 +209,28 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
# if we have no host info wait for it or abort if previously configured
|
||||
self._abort_if_unique_id_configured()
|
||||
return await self.async_step_import_confirm()
|
||||
|
||||
async def async_step_import_confirm(self, user_input=None):
|
||||
"""Confirm the user wants to import the config entry."""
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="import_confirm",
|
||||
description_placeholders={"id": self.unique_id},
|
||||
)
|
||||
|
||||
# if we have ssdp discovered applicable host info use it
|
||||
if KonnectedFlowHandler.discovered_hosts.get(self.unique_id):
|
||||
return await self.async_step_user(
|
||||
user_input={
|
||||
CONF_HOST: KonnectedFlowHandler.discovered_hosts[self.unique_id][
|
||||
CONF_HOST
|
||||
],
|
||||
CONF_PORT: KonnectedFlowHandler.discovered_hosts[self.unique_id][
|
||||
CONF_PORT
|
||||
],
|
||||
}
|
||||
)
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_ssdp(self, discovery_info):
|
||||
|
@ -265,7 +291,13 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors["base"] = "cannot_connect"
|
||||
else:
|
||||
self.data[CONF_ID] = status["mac"].replace(":", "")
|
||||
self.data[CONF_MODEL] = status.get("name", KONN_MODEL)
|
||||
self.data[CONF_MODEL] = status.get("model", KONN_MODEL)
|
||||
|
||||
# save off our discovered host info
|
||||
KonnectedFlowHandler.discovered_hosts[self.data[CONF_ID]] = {
|
||||
CONF_HOST: self.data[CONF_HOST],
|
||||
CONF_PORT: self.data[CONF_PORT],
|
||||
}
|
||||
return await self.async_step_confirm()
|
||||
|
||||
return self.async_show_form(
|
||||
|
@ -290,23 +322,14 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
the connection.
|
||||
"""
|
||||
if user_input is None:
|
||||
# update an existing config entry if host info changes
|
||||
entry = await self.async_set_unique_id(
|
||||
self.data[CONF_ID], raise_on_progress=False
|
||||
)
|
||||
if entry and (
|
||||
entry.data[CONF_HOST] != self.data[CONF_HOST]
|
||||
or entry.data[CONF_PORT] != self.data[CONF_PORT]
|
||||
):
|
||||
entry_data = copy.deepcopy(entry.data)
|
||||
entry_data.update(self.data)
|
||||
self.hass.config_entries.async_update_entry(entry, data=entry_data)
|
||||
|
||||
self._abort_if_unique_id_configured()
|
||||
# abort and update an existing config entry if host info changes
|
||||
await self.async_set_unique_id(self.data[CONF_ID])
|
||||
self._abort_if_unique_id_configured(updates=self.data)
|
||||
return self.async_show_form(
|
||||
step_id="confirm",
|
||||
description_placeholders={
|
||||
"model": KONN_PANEL_MODEL_NAMES[self.data[CONF_MODEL]],
|
||||
"id": self.unique_id,
|
||||
"host": self.data[CONF_HOST],
|
||||
"port": self.data[CONF_PORT],
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@ DOMAIN = "konnected"
|
|||
|
||||
CONF_ACTIVATION = "activation"
|
||||
CONF_API_HOST = "api_host"
|
||||
CONF_DEFAULT_OPTIONS = "default_options"
|
||||
CONF_MOMENTARY = "momentary"
|
||||
CONF_PAUSE = "pause"
|
||||
CONF_POLL_INTERVAL = "poll_interval"
|
||||
|
|
|
@ -28,6 +28,7 @@ from .const import (
|
|||
CONF_ACTIVATION,
|
||||
CONF_API_HOST,
|
||||
CONF_BLINK,
|
||||
CONF_DEFAULT_OPTIONS,
|
||||
CONF_DHT_SENSORS,
|
||||
CONF_DISCOVERY,
|
||||
CONF_DS18B20_SENSORS,
|
||||
|
@ -64,7 +65,9 @@ class AlarmPanel:
|
|||
self.hass = hass
|
||||
self.config_entry = config_entry
|
||||
self.config = config_entry.data
|
||||
self.options = config_entry.options
|
||||
self.options = config_entry.options or config_entry.data.get(
|
||||
CONF_DEFAULT_OPTIONS, {}
|
||||
)
|
||||
self.host = self.config.get(CONF_HOST)
|
||||
self.port = self.config.get(CONF_PORT)
|
||||
self.client = None
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
"config": {
|
||||
"title": "Konnected.io",
|
||||
"step": {
|
||||
"import_confirm": {
|
||||
"title": "Import Konnected Device",
|
||||
"description": "A Konnected Alarm Panel with ID {id} has been discovered in configuration.yaml. This flow will allow you to import it into a config entry."
|
||||
},
|
||||
"user": {
|
||||
"title": "Discover Konnected Device",
|
||||
"description": "Please enter the host information for your Konnected Panel.",
|
||||
|
@ -12,7 +16,7 @@
|
|||
},
|
||||
"confirm": {
|
||||
"title": "Konnected Device Ready",
|
||||
"description": "Model: {model}\nHost: {host}\nPort: {port}\n\nYou can configure the IO and panel behavior in the Konnected Alarm Panel settings."
|
||||
"description": "Model: {model}\nID: {id}\nHost: {host}\nPort: {port}\n\nYou can configure the IO and panel behavior in the Konnected Alarm Panel settings."
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
|
|
|
@ -34,7 +34,7 @@ async def test_flow_works(hass, mock_panel):
|
|||
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected",
|
||||
"model": "Konnected",
|
||||
}
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={"port": 1234, "host": "1.2.3.4"}
|
||||
|
@ -43,6 +43,7 @@ async def test_flow_works(hass, mock_panel):
|
|||
assert result["step_id"] == "confirm"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Konnected Alarm Panel",
|
||||
"id": "112233445566",
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ async def test_pro_flow_works(hass, mock_panel):
|
|||
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={"port": 1234, "host": "1.2.3.4"}
|
||||
|
@ -79,6 +80,7 @@ async def test_pro_flow_works(hass, mock_panel):
|
|||
assert result["step_id"] == "confirm"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Konnected Alarm Panel Pro",
|
||||
"id": "112233445566",
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
}
|
||||
|
@ -100,7 +102,7 @@ async def test_ssdp(hass, mock_panel):
|
|||
"""Test a panel being discovered."""
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected",
|
||||
"model": "Konnected",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -117,6 +119,7 @@ async def test_ssdp(hass, mock_panel):
|
|||
assert result["step_id"] == "confirm"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Konnected Alarm Panel",
|
||||
"id": "112233445566",
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
}
|
||||
|
@ -125,8 +128,8 @@ async def test_ssdp(hass, mock_panel):
|
|||
async def test_import_no_host_user_finish(hass, mock_panel):
|
||||
"""Test importing a panel with no host info."""
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"mac": "aa:bb:cc:dd:ee:ff",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -159,6 +162,13 @@ async def test_import_no_host_user_finish(hass, mock_panel):
|
|||
},
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "import_confirm"
|
||||
assert result["description_placeholders"]["id"] == "aabbccddeeff"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
# confirm user is prompted to enter host
|
||||
|
@ -169,6 +179,7 @@ async def test_import_no_host_user_finish(hass, mock_panel):
|
|||
assert result["step_id"] == "confirm"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Konnected Alarm Panel Pro",
|
||||
"id": "aabbccddeeff",
|
||||
"host": "1.1.1.1",
|
||||
"port": 1234,
|
||||
}
|
||||
|
@ -180,6 +191,78 @@ async def test_import_no_host_user_finish(hass, mock_panel):
|
|||
assert result["type"] == "create_entry"
|
||||
|
||||
|
||||
async def test_import_ssdp_host_user_finish(hass, mock_panel):
|
||||
"""Test importing a panel with no host info which ssdp discovers."""
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": "import"},
|
||||
data={
|
||||
"default_options": {
|
||||
"blink": True,
|
||||
"discovery": True,
|
||||
"io": {
|
||||
"1": "Disabled",
|
||||
"10": "Disabled",
|
||||
"11": "Disabled",
|
||||
"12": "Disabled",
|
||||
"2": "Disabled",
|
||||
"3": "Disabled",
|
||||
"4": "Disabled",
|
||||
"5": "Disabled",
|
||||
"6": "Disabled",
|
||||
"7": "Disabled",
|
||||
"8": "Disabled",
|
||||
"9": "Disabled",
|
||||
"alarm1": "Disabled",
|
||||
"alarm2_out2": "Disabled",
|
||||
"out": "Disabled",
|
||||
"out1": "Disabled",
|
||||
},
|
||||
},
|
||||
"id": "112233445566",
|
||||
},
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "import_confirm"
|
||||
assert result["description_placeholders"]["id"] == "112233445566"
|
||||
|
||||
# discover the panel via ssdp
|
||||
ssdp_result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": "ssdp"},
|
||||
data={
|
||||
"ssdp_location": "http://0.0.0.0:1234/Device.xml",
|
||||
"manufacturer": config_flow.KONN_MANUFACTURER,
|
||||
"modelName": config_flow.KONN_MODEL_PRO,
|
||||
},
|
||||
)
|
||||
assert ssdp_result["type"] == "abort"
|
||||
assert ssdp_result["reason"] == "already_in_progress"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "confirm"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Konnected Alarm Panel Pro",
|
||||
"id": "112233445566",
|
||||
"host": "0.0.0.0",
|
||||
"port": 1234,
|
||||
}
|
||||
|
||||
# final confirmation
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result["type"] == "create_entry"
|
||||
|
||||
|
||||
async def test_ssdp_already_configured(hass, mock_panel):
|
||||
"""Test if a discovered panel has already been configured."""
|
||||
MockConfigEntry(
|
||||
|
@ -189,7 +272,7 @@ async def test_ssdp_already_configured(hass, mock_panel):
|
|||
).add_to_hass(hass)
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -265,7 +348,7 @@ async def test_ssdp_host_update(hass, mock_panel):
|
|||
).add_to_hass(hass)
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -289,7 +372,7 @@ async def test_import_existing_config(hass, mock_panel):
|
|||
"""Test importing a host with an existing config file."""
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -402,7 +485,7 @@ async def test_import_existing_config_entry(hass, mock_panel):
|
|||
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
# utilize a global access token this time
|
||||
|
@ -462,7 +545,7 @@ async def test_import_pin_config(hass, mock_panel):
|
|||
"""Test importing a host with an existing config file that specifies pin configs."""
|
||||
mock_panel.get_status.return_value = {
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"name": "Konnected Pro",
|
||||
"model": "Konnected Pro",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
|
|
@ -3,6 +3,7 @@ from asynctest import patch
|
|||
import pytest
|
||||
|
||||
from homeassistant.components.konnected import config_flow, panel
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
@ -92,9 +93,6 @@ async def test_create_and_setup(hass, mock_panel):
|
|||
options=device_options,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
hass.data[panel.DOMAIN] = {
|
||||
panel.CONF_API_HOST: "192.168.1.1",
|
||||
}
|
||||
|
||||
# override get_status to reflect non-pro board
|
||||
mock_panel.get_status.return_value = {
|
||||
|
@ -111,19 +109,35 @@ async def test_create_and_setup(hass, mock_panel):
|
|||
"mac": "11:22:33:44:55:66",
|
||||
"settings": {},
|
||||
}
|
||||
device = panel.AlarmPanel(hass, entry)
|
||||
await device.async_save_data()
|
||||
await device.async_connect()
|
||||
|
||||
# setup the integration and inspect panel behavior
|
||||
assert (
|
||||
await async_setup_component(
|
||||
hass,
|
||||
panel.DOMAIN,
|
||||
{
|
||||
panel.DOMAIN: {
|
||||
panel.CONF_ACCESS_TOKEN: "arandomstringvalue",
|
||||
panel.CONF_API_HOST: "http://192.168.1.1:8123",
|
||||
}
|
||||
},
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
# confirm panel instance was created and configured
|
||||
# hass.data is the only mechanism to get a reference to the created panel instance
|
||||
device = hass.data[panel.DOMAIN][panel.CONF_DEVICES]["112233445566"]["panel"]
|
||||
await device.update_switch("1", 0)
|
||||
|
||||
# confirm the correct api is used
|
||||
# pylint: disable=no-member
|
||||
assert device.client.put_device.call_count == 1
|
||||
assert device.client.put_zone.call_count == 0
|
||||
assert mock_panel.put_device.call_count == 1
|
||||
assert mock_panel.put_zone.call_count == 0
|
||||
|
||||
# confirm the settings are sent to the panel
|
||||
# pylint: disable=no-member
|
||||
assert device.client.put_settings.call_args_list[0][1] == {
|
||||
assert mock_panel.put_settings.call_args_list[0][1] == {
|
||||
"sensors": [{"pin": "1"}, {"pin": "2"}, {"pin": "5"}],
|
||||
"actuators": [{"trigger": 0, "pin": "8"}, {"trigger": 1, "pin": "9"}],
|
||||
"dht_sensors": [{"poll_interval": 3, "pin": "6"}],
|
||||
|
@ -131,67 +145,60 @@ async def test_create_and_setup(hass, mock_panel):
|
|||
"auth_token": "11223344556677889900",
|
||||
"blink": True,
|
||||
"discovery": True,
|
||||
"endpoint": "192.168.1.1/api/konnected",
|
||||
"endpoint": "http://192.168.1.1:8123/api/konnected",
|
||||
}
|
||||
|
||||
# confirm the device settings are saved in hass.data
|
||||
assert hass.data[panel.DOMAIN][panel.CONF_DEVICES] == {
|
||||
"112233445566": {
|
||||
"binary_sensors": {
|
||||
"1": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 1",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"2": {
|
||||
"inverse": True,
|
||||
"name": "winder",
|
||||
"state": None,
|
||||
"type": "window",
|
||||
},
|
||||
"3": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 3",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
assert device.stored_configuration == {
|
||||
"binary_sensors": {
|
||||
"1": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 1",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"blink": True,
|
||||
"panel": device,
|
||||
"discovery": True,
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"sensors": [
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 4",
|
||||
"poll_interval": 3,
|
||||
"type": "dht",
|
||||
"zone": "4",
|
||||
},
|
||||
{"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "5"},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"name": "switcher",
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
"state": None,
|
||||
"zone": "out",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator 6",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "6",
|
||||
},
|
||||
],
|
||||
}
|
||||
"2": {"inverse": True, "name": "winder", "state": None, "type": "window"},
|
||||
"3": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 3",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
},
|
||||
"blink": True,
|
||||
"panel": device,
|
||||
"discovery": True,
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"sensors": [
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 4",
|
||||
"poll_interval": 3,
|
||||
"type": "dht",
|
||||
"zone": "4",
|
||||
},
|
||||
{"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "5"},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"name": "switcher",
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
"state": None,
|
||||
"zone": "out",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator 6",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "6",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
@ -255,23 +262,35 @@ async def test_create_and_setup_pro(hass, mock_panel):
|
|||
options=device_options,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
hass.data[panel.DOMAIN] = {
|
||||
panel.CONF_API_HOST: "192.168.1.1",
|
||||
}
|
||||
|
||||
device = panel.AlarmPanel(hass, entry)
|
||||
await device.async_save_data()
|
||||
await device.async_connect()
|
||||
# setup the integration and inspect panel behavior
|
||||
assert (
|
||||
await async_setup_component(
|
||||
hass,
|
||||
panel.DOMAIN,
|
||||
{
|
||||
panel.DOMAIN: {
|
||||
panel.CONF_ACCESS_TOKEN: "arandomstringvalue",
|
||||
panel.CONF_API_HOST: "http://192.168.1.1:8123",
|
||||
}
|
||||
},
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
# confirm panel instance was created and configured
|
||||
# hass.data is the only mechanism to get a reference to the created panel instance
|
||||
device = hass.data[panel.DOMAIN][panel.CONF_DEVICES]["112233445566"]["panel"]
|
||||
await device.update_switch("2", 1)
|
||||
|
||||
# confirm the correct api is used
|
||||
# pylint: disable=no-member
|
||||
assert device.client.put_device.call_count == 0
|
||||
assert device.client.put_zone.call_count == 1
|
||||
assert mock_panel.put_device.call_count == 0
|
||||
assert mock_panel.put_zone.call_count == 1
|
||||
|
||||
# confirm the settings are sent to the panel
|
||||
# pylint: disable=no-member
|
||||
assert device.client.put_settings.call_args_list[0][1] == {
|
||||
assert mock_panel.put_settings.call_args_list[0][1] == {
|
||||
"sensors": [{"zone": "2"}, {"zone": "6"}, {"zone": "10"}],
|
||||
"actuators": [
|
||||
{"trigger": 1, "zone": "4"},
|
||||
|
@ -287,89 +306,248 @@ async def test_create_and_setup_pro(hass, mock_panel):
|
|||
"auth_token": "11223344556677889900",
|
||||
"blink": True,
|
||||
"discovery": True,
|
||||
"endpoint": "192.168.1.1/api/konnected",
|
||||
"endpoint": "http://192.168.1.1:8123/api/konnected",
|
||||
}
|
||||
|
||||
# confirm the device settings are saved in hass.data
|
||||
assert hass.data[panel.DOMAIN][panel.CONF_DEVICES] == {
|
||||
"112233445566": {
|
||||
"binary_sensors": {
|
||||
"10": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 10",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"2": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 2",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"6": {
|
||||
"inverse": True,
|
||||
"name": "winder",
|
||||
"state": None,
|
||||
"type": "window",
|
||||
},
|
||||
assert device.stored_configuration == {
|
||||
"binary_sensors": {
|
||||
"10": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 10",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"blink": True,
|
||||
"panel": device,
|
||||
"discovery": True,
|
||||
"2": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 2",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"6": {"inverse": True, "name": "winder", "state": None, "type": "window"},
|
||||
},
|
||||
"blink": True,
|
||||
"panel": device,
|
||||
"discovery": True,
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"sensors": [
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 3",
|
||||
"poll_interval": 3,
|
||||
"type": "dht",
|
||||
"zone": "3",
|
||||
},
|
||||
{"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "7"},
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 11",
|
||||
"poll_interval": 5,
|
||||
"type": "dht",
|
||||
"zone": "11",
|
||||
},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator 4",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "4",
|
||||
},
|
||||
{
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"name": "switcher",
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
"state": None,
|
||||
"zone": "8",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator out1",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "out1",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator alarm1",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "alarm1",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
async def test_default_options(hass, mock_panel):
|
||||
"""Test that we create a Konnected Panel and save the data."""
|
||||
device_config = config_flow.CONFIG_ENTRY_SCHEMA(
|
||||
{
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"sensors": [
|
||||
"id": "112233445566",
|
||||
"model": "Konnected Pro",
|
||||
"access_token": "11223344556677889900",
|
||||
"default_options": config_flow.OPTIONS_SCHEMA(
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 3",
|
||||
"poll_interval": 3,
|
||||
"type": "dht",
|
||||
"zone": "3",
|
||||
},
|
||||
{"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "7"},
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 11",
|
||||
"poll_interval": 5,
|
||||
"type": "dht",
|
||||
"zone": "11",
|
||||
},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator 4",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "4",
|
||||
},
|
||||
{
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"name": "switcher",
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
"state": None,
|
||||
"zone": "8",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator out1",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "out1",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator alarm1",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "alarm1",
|
||||
},
|
||||
],
|
||||
"io": {
|
||||
"1": "Binary Sensor",
|
||||
"2": "Binary Sensor",
|
||||
"3": "Binary Sensor",
|
||||
"4": "Digital Sensor",
|
||||
"5": "Digital Sensor",
|
||||
"6": "Switchable Output",
|
||||
"out": "Switchable Output",
|
||||
},
|
||||
"binary_sensors": [
|
||||
{"zone": "1", "type": "door"},
|
||||
{
|
||||
"zone": "2",
|
||||
"type": "window",
|
||||
"name": "winder",
|
||||
"inverse": True,
|
||||
},
|
||||
{"zone": "3", "type": "door"},
|
||||
],
|
||||
"sensors": [
|
||||
{"zone": "4", "type": "dht"},
|
||||
{"zone": "5", "type": "ds18b20", "name": "temper"},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"zone": "out",
|
||||
"name": "switcher",
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
},
|
||||
{"zone": "6"},
|
||||
],
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain="konnected",
|
||||
title="Konnected Alarm Panel",
|
||||
data=device_config,
|
||||
options={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
# override get_status to reflect non-pro board
|
||||
mock_panel.get_status.return_value = {
|
||||
"hwVersion": "2.3.0",
|
||||
"swVersion": "2.3.1",
|
||||
"heap": 10000,
|
||||
"uptime": 12222,
|
||||
"ip": "192.168.1.90",
|
||||
"port": 9123,
|
||||
"sensors": [],
|
||||
"actuators": [],
|
||||
"dht_sensors": [],
|
||||
"ds18b20_sensors": [],
|
||||
"mac": "11:22:33:44:55:66",
|
||||
"settings": {},
|
||||
}
|
||||
|
||||
# setup the integration and inspect panel behavior
|
||||
assert (
|
||||
await async_setup_component(
|
||||
hass,
|
||||
panel.DOMAIN,
|
||||
{
|
||||
panel.DOMAIN: {
|
||||
panel.CONF_ACCESS_TOKEN: "arandomstringvalue",
|
||||
panel.CONF_API_HOST: "http://192.168.1.1:8123",
|
||||
}
|
||||
},
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
# confirm panel instance was created and configured.
|
||||
# hass.data is the only mechanism to get a reference to the created panel instance
|
||||
device = hass.data[panel.DOMAIN][panel.CONF_DEVICES]["112233445566"]["panel"]
|
||||
await device.update_switch("1", 0)
|
||||
|
||||
# confirm the correct api is used
|
||||
# pylint: disable=no-member
|
||||
assert mock_panel.put_device.call_count == 1
|
||||
assert mock_panel.put_zone.call_count == 0
|
||||
|
||||
# confirm the settings are sent to the panel
|
||||
# pylint: disable=no-member
|
||||
assert mock_panel.put_settings.call_args_list[0][1] == {
|
||||
"sensors": [{"pin": "1"}, {"pin": "2"}, {"pin": "5"}],
|
||||
"actuators": [{"trigger": 0, "pin": "8"}, {"trigger": 1, "pin": "9"}],
|
||||
"dht_sensors": [{"poll_interval": 3, "pin": "6"}],
|
||||
"ds18b20_sensors": [{"pin": "7"}],
|
||||
"auth_token": "11223344556677889900",
|
||||
"blink": True,
|
||||
"discovery": True,
|
||||
"endpoint": "http://192.168.1.1:8123/api/konnected",
|
||||
}
|
||||
|
||||
# confirm the device settings are saved in hass.data
|
||||
assert device.stored_configuration == {
|
||||
"binary_sensors": {
|
||||
"1": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 1",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
"2": {"inverse": True, "name": "winder", "state": None, "type": "window"},
|
||||
"3": {
|
||||
"inverse": False,
|
||||
"name": "Konnected 445566 Zone 3",
|
||||
"state": None,
|
||||
"type": "door",
|
||||
},
|
||||
},
|
||||
"blink": True,
|
||||
"panel": device,
|
||||
"discovery": True,
|
||||
"host": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"sensors": [
|
||||
{
|
||||
"name": "Konnected 445566 Sensor 4",
|
||||
"poll_interval": 3,
|
||||
"type": "dht",
|
||||
"zone": "4",
|
||||
},
|
||||
{"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "5"},
|
||||
],
|
||||
"switches": [
|
||||
{
|
||||
"activation": "low",
|
||||
"momentary": 50,
|
||||
"name": "switcher",
|
||||
"pause": 100,
|
||||
"repeat": 4,
|
||||
"state": None,
|
||||
"zone": "out",
|
||||
},
|
||||
{
|
||||
"activation": "high",
|
||||
"momentary": None,
|
||||
"name": "Konnected 445566 Actuator 6",
|
||||
"pause": None,
|
||||
"repeat": None,
|
||||
"state": None,
|
||||
"zone": "6",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue