Add support for config_flow configuration
This commit is contained in:
parent
5b045f8c4f
commit
db21a76885
21
custom_components/blueprint/.translations/en.json
Normal file
21
custom_components/blueprint/.translations/en.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"title": "Blueprint",
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"title": "Blueprint",
|
||||||
|
"description": "If you need help with the configuration have a look here: https://github.com/custom-components/blueprint",
|
||||||
|
"data": {
|
||||||
|
"username": "Username",
|
||||||
|
"password": "Password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"auth": "Username/Password is wrong."
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"single_instance_allowed": "Only a single configuration of Blueprint is allowed."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
custom_components/blueprint/.translations/nb.json
Normal file
21
custom_components/blueprint/.translations/nb.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"title": "Blueprint",
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"title": "Blueprint",
|
||||||
|
"description": "Hvis du trenger hjep til konfigurasjon ta en titt her: https://github.com/custom-components/blueprint",
|
||||||
|
"data": {
|
||||||
|
"username": "Brukernavn",
|
||||||
|
"password": "Passord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"auth": "Brukernavn/Passord er feil."
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"single_instance_allowed": "Du kan konfigurere Blueprint kun en gang."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import os
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
from homeassistant import config_entries
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
@ -76,9 +77,15 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
"""Set up this component."""
|
"""Set up this component using YAML."""
|
||||||
|
if config.get(DOMAIN) is None:
|
||||||
|
# We get her if the integration is set up using config flow
|
||||||
|
return True
|
||||||
|
|
||||||
# Print startup message
|
# Print startup message
|
||||||
_LOGGER.info(CC_STARTUP_VERSION.format(name=DOMAIN, version=VERSION, issue_link=ISSUE_URL))
|
_LOGGER.info(
|
||||||
|
CC_STARTUP_VERSION.format(name=DOMAIN, version=VERSION, issue_link=ISSUE_URL)
|
||||||
|
)
|
||||||
|
|
||||||
# Check that all required files are present
|
# Check that all required files are present
|
||||||
file_check = await check_files(hass)
|
file_check = await check_files(hass)
|
||||||
@ -117,6 +124,60 @@ async def async_setup(hass, config):
|
|||||||
hass, platform, DOMAIN, entry_config, config
|
hass, platform, DOMAIN, entry_config, config
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
hass.async_create_task(
|
||||||
|
hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, config_entry):
|
||||||
|
"""Set up this integration using UI."""
|
||||||
|
conf = hass.data.get(DOMAIN_DATA)
|
||||||
|
if config_entry.source == config_entries.SOURCE_IMPORT:
|
||||||
|
if conf is None:
|
||||||
|
hass.async_create_task(
|
||||||
|
hass.config_entries.async_remove(config_entry.entry_id)
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Print startup message
|
||||||
|
_LOGGER.info(
|
||||||
|
CC_STARTUP_VERSION.format(name=DOMAIN, version=VERSION, issue_link=ISSUE_URL)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that all required files are present
|
||||||
|
file_check = await check_files(hass)
|
||||||
|
if not file_check:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Create DATA dict
|
||||||
|
hass.data[DOMAIN_DATA] = {}
|
||||||
|
|
||||||
|
# Get "global" configuration.
|
||||||
|
username = config_entry.data.get(CONF_USERNAME)
|
||||||
|
password = config_entry.data.get(CONF_PASSWORD)
|
||||||
|
|
||||||
|
# Configure the client.
|
||||||
|
client = Client(username, password)
|
||||||
|
hass.data[DOMAIN_DATA]["client"] = BlueprintData(hass, client)
|
||||||
|
|
||||||
|
# Add binary_sensor
|
||||||
|
hass.async_add_job(
|
||||||
|
hass.config_entries.async_forward_entry_setup(config_entry, "binary_sensor")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add sensor
|
||||||
|
hass.async_add_job(
|
||||||
|
hass.config_entries.async_forward_entry_setup(config_entry, "sensor")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add switch
|
||||||
|
hass.async_add_job(
|
||||||
|
hass.config_entries.async_forward_entry_setup(config_entry, "switch")
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -156,3 +217,28 @@ async def check_files(hass):
|
|||||||
returnvalue = True
|
returnvalue = True
|
||||||
|
|
||||||
return returnvalue
|
return returnvalue
|
||||||
|
|
||||||
|
|
||||||
|
async def async_remove_entry(hass, config_entry):
|
||||||
|
"""Handle removal of an entry."""
|
||||||
|
try:
|
||||||
|
await hass.config_entries.async_forward_entry_unload(
|
||||||
|
config_entry, "binary_sensor"
|
||||||
|
)
|
||||||
|
_LOGGER.info(
|
||||||
|
"Successfully removed binary_sensor from the blueprint integration"
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
await hass.config_entries.async_forward_entry_unload(config_entry, "sensor")
|
||||||
|
_LOGGER.info("Successfully removed sensor from the blueprint integration")
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
await hass.config_entries.async_forward_entry_unload(config_entry, "switch")
|
||||||
|
_LOGGER.info("Successfully removed switch from the blueprint integration")
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
"""Binary sensor platform for blueprint."""
|
"""Binary sensor platform for blueprint."""
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
from .const import ATTRIBUTION, BINARY_SENSOR_DEVICE_CLASS, DEFAULT_NAME, DOMAIN_DATA
|
from .const import (
|
||||||
|
ATTRIBUTION,
|
||||||
|
BINARY_SENSOR_DEVICE_CLASS,
|
||||||
|
DEFAULT_NAME,
|
||||||
|
DOMAIN_DATA,
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
@ -10,6 +16,11 @@ async def async_setup_platform(
|
|||||||
async_add_entities([BlueprintBinarySensor(hass, discovery_info)], True)
|
async_add_entities([BlueprintBinarySensor(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||||
|
"""Setup sensor platform."""
|
||||||
|
async_add_devices([BlueprintBinarySensor(hass, {})], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintBinarySensor(BinarySensorDevice):
|
class BlueprintBinarySensor(BinarySensorDevice):
|
||||||
"""blueprint binary_sensor class."""
|
"""blueprint binary_sensor class."""
|
||||||
|
|
||||||
@ -38,6 +49,21 @@ class BlueprintBinarySensor(BinarySensorDevice):
|
|||||||
self.attr["time"] = str(updated.get("time"))
|
self.attr["time"] = str(updated.get("time"))
|
||||||
self.attr["static"] = updated.get("static")
|
self.attr["static"] = updated.get("static")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique ID to use for this binary_sensor."""
|
||||||
|
return (
|
||||||
|
"0919a0cd-745c-48fd"
|
||||||
|
) # Don't had code this, use something from the device/service.
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
return {
|
||||||
|
"identifiers": {(DOMAIN, self.unique_id)},
|
||||||
|
"name": self.name,
|
||||||
|
"manufacturer": "Blueprint",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the binary_sensor."""
|
"""Return the name of the binary_sensor."""
|
||||||
|
83
custom_components/blueprint/config_flow.py
Normal file
83
custom_components/blueprint/config_flow.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
"""Adds config flow for Blueprint."""
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
from sampleclient.client import Client
|
||||||
|
from homeassistant import config_entries
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
@config_entries.HANDLERS.register(DOMAIN)
|
||||||
|
class BlueprintFlowHandler(config_entries.ConfigFlow):
|
||||||
|
"""Config flow for Blueprint."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize."""
|
||||||
|
self._errors = {}
|
||||||
|
|
||||||
|
async def async_step_user(
|
||||||
|
self, user_input={}
|
||||||
|
): # pylint: disable=dangerous-default-value
|
||||||
|
"""Handle a flow initialized by the user."""
|
||||||
|
self._errors = {}
|
||||||
|
if self._async_current_entries():
|
||||||
|
return self.async_abort(reason="single_instance_allowed")
|
||||||
|
if self.hass.data.get(DOMAIN):
|
||||||
|
return self.async_abort(reason="single_instance_allowed")
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
valid = await self._test_credentials(
|
||||||
|
user_input["username"], user_input["password"]
|
||||||
|
)
|
||||||
|
if valid:
|
||||||
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
else:
|
||||||
|
self._errors["base"] = "auth"
|
||||||
|
|
||||||
|
return await self._show_config_form(user_input)
|
||||||
|
|
||||||
|
return await self._show_config_form(user_input)
|
||||||
|
|
||||||
|
async def _show_config_form(self, user_input):
|
||||||
|
"""Show the configuration form to edit location data."""
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
if "username" in user_input:
|
||||||
|
username = user_input["username"]
|
||||||
|
if "password" in user_input:
|
||||||
|
password = user_input["password"]
|
||||||
|
|
||||||
|
data_schema = OrderedDict()
|
||||||
|
data_schema[vol.Required("username", default=username)] = str
|
||||||
|
data_schema[vol.Required("password", default=password)] = str
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user", data_schema=vol.Schema(data_schema), errors=self._errors
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_import(self, user_input): # pylint: disable=unused-argument
|
||||||
|
"""Import a config entry.
|
||||||
|
Special type of import, we're not actually going to store any data.
|
||||||
|
Instead, we're going to rely on the values that are in config file.
|
||||||
|
"""
|
||||||
|
if self._async_current_entries():
|
||||||
|
return self.async_abort(reason="single_instance_allowed")
|
||||||
|
|
||||||
|
return self.async_create_entry(title="configuration.yaml", data={})
|
||||||
|
|
||||||
|
async def _test_credentials(self, username, password):
|
||||||
|
"""Return true if credentials is valid."""
|
||||||
|
try:
|
||||||
|
client = Client(username, password)
|
||||||
|
client.get_data()
|
||||||
|
return True
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
pass
|
||||||
|
return False
|
@ -3,6 +3,13 @@
|
|||||||
"name": "Blueprint",
|
"name": "Blueprint",
|
||||||
"documentation": "https://github.com/custom-components/blueprint",
|
"documentation": "https://github.com/custom-components/blueprint",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": ["@ludeeus"],
|
"config_flow": true,
|
||||||
"requirements": ["sampleclient", "integrationhelper"]
|
"codeowners": [
|
||||||
|
"@ludeeus"
|
||||||
|
],
|
||||||
|
"requirements": [
|
||||||
|
"sampleclient",
|
||||||
|
"integrationhelper"
|
||||||
|
],
|
||||||
|
"homeassistant": "0.96.0"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
"""Sensor platform for blueprint."""
|
"""Sensor platform for blueprint."""
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
@ -10,6 +10,11 @@ async def async_setup_platform(
|
|||||||
async_add_entities([BlueprintSensor(hass, discovery_info)], True)
|
async_add_entities([BlueprintSensor(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||||
|
"""Setup sensor platform."""
|
||||||
|
async_add_devices([BlueprintSensor(hass, {})], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintSensor(Entity):
|
class BlueprintSensor(Entity):
|
||||||
"""blueprint Sensor class."""
|
"""blueprint Sensor class."""
|
||||||
|
|
||||||
@ -38,6 +43,21 @@ class BlueprintSensor(Entity):
|
|||||||
self.attr["time"] = str(updated.get("time"))
|
self.attr["time"] = str(updated.get("time"))
|
||||||
self.attr["none"] = updated.get("none")
|
self.attr["none"] = updated.get("none")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique ID to use for this sensor."""
|
||||||
|
return (
|
||||||
|
"0717a0cd-745c-48fd"
|
||||||
|
) # Don't had code this, use something from the device/service.
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
return {
|
||||||
|
"identifiers": {(DOMAIN, self.unique_id)},
|
||||||
|
"name": self.name,
|
||||||
|
"manufacturer": "Blueprint",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the sensor."""
|
"""Return the name of the sensor."""
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Switch platform for blueprint."""
|
"""Switch platform for blueprint."""
|
||||||
from homeassistant.components.switch import SwitchDevice
|
from homeassistant.components.switch import SwitchDevice
|
||||||
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON
|
from .const import ATTRIBUTION, DEFAULT_NAME, DOMAIN_DATA, ICON, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
@ -10,6 +10,11 @@ async def async_setup_platform(
|
|||||||
async_add_entities([BlueprintBinarySwitch(hass, discovery_info)], True)
|
async_add_entities([BlueprintBinarySwitch(hass, discovery_info)], True)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||||
|
"""Setup sensor platform."""
|
||||||
|
async_add_devices([BlueprintBinarySwitch(hass, {})], True)
|
||||||
|
|
||||||
|
|
||||||
class BlueprintBinarySwitch(SwitchDevice):
|
class BlueprintBinarySwitch(SwitchDevice):
|
||||||
"""blueprint switch class."""
|
"""blueprint switch class."""
|
||||||
|
|
||||||
@ -43,6 +48,21 @@ class BlueprintBinarySwitch(SwitchDevice):
|
|||||||
"""Turn off the switch."""
|
"""Turn off the switch."""
|
||||||
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False)
|
await self.hass.data[DOMAIN_DATA]["client"].client.change_something(False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique ID to use for this switch."""
|
||||||
|
return (
|
||||||
|
"0818a0cd-745c-48fd"
|
||||||
|
) # Don't had code this, use something from the device/service.
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
return {
|
||||||
|
"identifiers": {(DOMAIN, self.unique_id)},
|
||||||
|
"name": self.name,
|
||||||
|
"manufacturer": "Blueprint",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the switch."""
|
"""Return the name of the switch."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user