Automatically generate config flow list (#23802)
* Add config flow to manifest.json * Still load config flows via config flow platform * Fix typo * Lint * Update config_flows.py" * Catch import error when setting up entry * Lint * Fix tests * Fix imports * Lint * Fix Unifi tests * Fix translation test * Add homekit_controller config flowpull/23845/head
parent
b8cbd39985
commit
1e22c8daca
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ambiclimate",
|
"domain": "ambiclimate",
|
||||||
"name": "Ambiclimate",
|
"name": "Ambiclimate",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ambiclimate",
|
"documentation": "https://www.home-assistant.io/components/ambiclimate",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"ambiclimate==0.1.1"
|
"ambiclimate==0.1.1"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ambient_station",
|
"domain": "ambient_station",
|
||||||
"name": "Ambient station",
|
"name": "Ambient station",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ambient_station",
|
"documentation": "https://www.home-assistant.io/components/ambient_station",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aioambient==0.3.0"
|
"aioambient==0.3.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "axis",
|
"domain": "axis",
|
||||||
"name": "Axis",
|
"name": "Axis",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/axis",
|
"documentation": "https://www.home-assistant.io/components/axis",
|
||||||
"requirements": ["axis==22"],
|
"requirements": ["axis==22"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
"""Component to embed Google Cast."""
|
"""Component to embed Google Cast."""
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.helpers import config_entry_flow
|
|
||||||
|
|
||||||
DOMAIN = 'cast'
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
|
@ -23,15 +22,3 @@ async def async_setup_entry(hass, entry):
|
||||||
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
|
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
|
||||||
entry, 'media_player'))
|
entry, 'media_player'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _async_has_devices(hass):
|
|
||||||
"""Return if there are devices that can be discovered."""
|
|
||||||
from pychromecast.discovery import discover_chromecasts
|
|
||||||
|
|
||||||
return await hass.async_add_executor_job(discover_chromecasts)
|
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(
|
|
||||||
DOMAIN, 'Google Cast', _async_has_devices,
|
|
||||||
config_entries.CONN_CLASS_LOCAL_PUSH)
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""Config flow for Cast."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_has_devices(hass):
|
||||||
|
"""Return if there are devices that can be discovered."""
|
||||||
|
from pychromecast.discovery import discover_chromecasts
|
||||||
|
|
||||||
|
return await hass.async_add_executor_job(discover_chromecasts)
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(
|
||||||
|
DOMAIN, 'Google Cast', _async_has_devices,
|
||||||
|
config_entries.CONN_CLASS_LOCAL_PUSH)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Consts for Cast integration."""
|
||||||
|
|
||||||
|
DOMAIN = 'cast'
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "cast",
|
"domain": "cast",
|
||||||
"name": "Cast",
|
"name": "Cast",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/cast",
|
"documentation": "https://www.home-assistant.io/components/cast",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pychromecast==3.2.1"
|
"pychromecast==3.2.1"
|
||||||
|
|
|
@ -6,6 +6,7 @@ from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.exceptions import Unauthorized
|
from homeassistant.exceptions import Unauthorized
|
||||||
from homeassistant.helpers.data_entry_flow import (
|
from homeassistant.helpers.data_entry_flow import (
|
||||||
FlowManagerIndexView, FlowManagerResourceView)
|
FlowManagerIndexView, FlowManagerResourceView)
|
||||||
|
from homeassistant.generated import config_flows
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
|
@ -172,7 +173,7 @@ class ConfigManagerAvailableFlowView(HomeAssistantView):
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
"""List available flow handlers."""
|
"""List available flow handlers."""
|
||||||
return self.json(config_entries.FLOWS)
|
return self.json(config_flows.FLOWS)
|
||||||
|
|
||||||
|
|
||||||
class OptionManagerFlowIndexView(FlowManagerIndexView):
|
class OptionManagerFlowIndexView(FlowManagerIndexView):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "daikin",
|
"domain": "daikin",
|
||||||
"name": "Daikin",
|
"name": "Daikin",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/daikin",
|
"documentation": "https://www.home-assistant.io/components/daikin",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pydaikin==1.4.0"
|
"pydaikin==1.4.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "deconz",
|
"domain": "deconz",
|
||||||
"name": "Deconz",
|
"name": "Deconz",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/deconz",
|
"documentation": "https://www.home-assistant.io/components/deconz",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pydeconz==58"
|
"pydeconz==58"
|
||||||
|
|
|
@ -8,9 +8,10 @@ from homeassistant.const import CONF_WEBHOOK_ID
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import intent, template, config_entry_flow
|
from homeassistant.helpers import intent, template, config_entry_flow
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
from .const import DOMAIN
|
||||||
|
|
||||||
DOMAIN = 'dialogflow'
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SOURCE = "Home Assistant Dialogflow"
|
SOURCE = "Home Assistant Dialogflow"
|
||||||
|
|
||||||
|
@ -83,16 +84,6 @@ async def async_unload_entry(hass, entry):
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'Dialogflow Webhook',
|
|
||||||
{
|
|
||||||
'dialogflow_url': 'https://dialogflow.com/docs/fulfillment#webhook',
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/dialogflow/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def dialogflow_error_response(message, error):
|
def dialogflow_error_response(message, error):
|
||||||
"""Return a response saying the error message."""
|
"""Return a response saying the error message."""
|
||||||
dialogflow_response = DialogflowResponse(message['result']['parameters'])
|
dialogflow_response = DialogflowResponse(message['result']['parameters'])
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""Config flow for DialogFlow."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'Dialogflow Webhook',
|
||||||
|
{
|
||||||
|
'dialogflow_url': 'https://dialogflow.com/docs/fulfillment#webhook',
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/dialogflow/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for DialogFlow."""
|
||||||
|
|
||||||
|
DOMAIN = "dialogflow"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "dialogflow",
|
"domain": "dialogflow",
|
||||||
"name": "Dialogflow",
|
"name": "Dialogflow",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/dialogflow",
|
"documentation": "https://www.home-assistant.io/components/dialogflow",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "emulated_roku",
|
"domain": "emulated_roku",
|
||||||
"name": "Emulated roku",
|
"name": "Emulated roku",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/emulated_roku",
|
"documentation": "https://www.home-assistant.io/components/emulated_roku",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"emulated_roku==0.1.8"
|
"emulated_roku==0.1.8"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "esphome",
|
"domain": "esphome",
|
||||||
"name": "ESPHome",
|
"name": "ESPHome",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/esphome",
|
"documentation": "https://www.home-assistant.io/components/esphome",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aioesphomeapi==2.0.1"
|
"aioesphomeapi==2.0.1"
|
||||||
|
|
|
@ -12,10 +12,11 @@ from homeassistant.helpers import config_entry_flow
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'geofency'
|
|
||||||
CONF_MOBILE_BEACONS = 'mobile_beacons'
|
CONF_MOBILE_BEACONS = 'mobile_beacons'
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
@ -134,12 +135,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'Geofency Webhook',
|
|
||||||
{
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/geofency/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
"""Config flow for Geofency."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'Geofency Webhook',
|
||||||
|
{
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/geofency/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for Geofency."""
|
||||||
|
|
||||||
|
DOMAIN = 'geofency'
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "geofency",
|
"domain": "geofency",
|
||||||
"name": "Geofency",
|
"name": "Geofency",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/geofency",
|
"documentation": "https://www.home-assistant.io/components/geofency",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -11,10 +11,10 @@ from homeassistant.const import HTTP_UNPROCESSABLE_ENTITY, \
|
||||||
from homeassistant.helpers import config_entry_flow
|
from homeassistant.helpers import config_entry_flow
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER
|
from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'gpslogger'
|
|
||||||
TRACKER_UPDATE = '{}_tracker_update'.format(DOMAIN)
|
TRACKER_UPDATE = '{}_tracker_update'.format(DOMAIN)
|
||||||
|
|
||||||
ATTR_ALTITUDE = 'altitude'
|
ATTR_ALTITUDE = 'altitude'
|
||||||
|
@ -105,12 +105,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'GPSLogger Webhook',
|
|
||||||
{
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/gpslogger/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
"""Config flow for GPSLogger."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'GPSLogger Webhook',
|
||||||
|
{
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/gpslogger/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for GPSLogger."""
|
||||||
|
|
||||||
|
DOMAIN = 'gpslogger'
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "gpslogger",
|
"domain": "gpslogger",
|
||||||
"name": "Gpslogger",
|
"name": "Gpslogger",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/gpslogger",
|
"documentation": "https://www.home-assistant.io/components/gpslogger",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "hangouts",
|
"domain": "hangouts",
|
||||||
"name": "Hangouts",
|
"name": "Hangouts",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/hangouts",
|
"documentation": "https://www.home-assistant.io/components/hangouts",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"hangups==0.4.9"
|
"hangups==0.4.9"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "heos",
|
"domain": "heos",
|
||||||
"name": "HEOS",
|
"name": "HEOS",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/heos",
|
"documentation": "https://www.home-assistant.io/components/heos",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyheos==0.5.2"
|
"pyheos==0.5.2"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "homekit_controller",
|
"domain": "homekit_controller",
|
||||||
"name": "Homekit controller",
|
"name": "Homekit controller",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/homekit_controller",
|
"documentation": "https://www.home-assistant.io/components/homekit_controller",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"homekit[IP]==0.14.0"
|
"homekit[IP]==0.14.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "homematicip_cloud",
|
"domain": "homematicip_cloud",
|
||||||
"name": "Homematicip cloud",
|
"name": "Homematicip cloud",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/homematicip_cloud",
|
"documentation": "https://www.home-assistant.io/components/homematicip_cloud",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"homematicip==0.10.7"
|
"homematicip==0.10.7"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "hue",
|
"domain": "hue",
|
||||||
"name": "Philips Hue",
|
"name": "Philips Hue",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/hue",
|
"documentation": "https://www.home-assistant.io/components/hue",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aiohue==1.9.1"
|
"aiohue==1.9.1"
|
||||||
|
|
|
@ -8,6 +8,7 @@ import voluptuous as vol
|
||||||
from homeassistant.const import CONF_WEBHOOK_ID
|
from homeassistant.const import CONF_WEBHOOK_ID
|
||||||
from homeassistant.helpers import config_entry_flow
|
from homeassistant.helpers import config_entry_flow
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -21,8 +22,6 @@ ATTR_VALUE3 = 'value3'
|
||||||
|
|
||||||
CONF_KEY = 'key'
|
CONF_KEY = 'key'
|
||||||
|
|
||||||
DOMAIN = 'ifttt'
|
|
||||||
|
|
||||||
SERVICE_TRIGGER = 'trigger'
|
SERVICE_TRIGGER = 'trigger'
|
||||||
|
|
||||||
SERVICE_TRIGGER_SCHEMA = vol.Schema({
|
SERVICE_TRIGGER_SCHEMA = vol.Schema({
|
||||||
|
@ -108,13 +107,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'IFTTT Webhook',
|
|
||||||
{
|
|
||||||
'applet_url': 'https://ifttt.com/maker_webhooks',
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/ifttt/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""Config flow for IFTTT."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'IFTTT Webhook',
|
||||||
|
{
|
||||||
|
'applet_url': 'https://ifttt.com/maker_webhooks',
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/ifttt/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for IFTTT."""
|
||||||
|
|
||||||
|
DOMAIN = "ifttt"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ifttt",
|
"domain": "ifttt",
|
||||||
"name": "Ifttt",
|
"name": "Ifttt",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ifttt",
|
"documentation": "https://www.home-assistant.io/components/ifttt",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyfttt==0.3"
|
"pyfttt==0.3"
|
||||||
|
|
|
@ -9,8 +9,7 @@ from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR
|
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import config_validation as cv, discovery
|
||||||
config_entry_flow, config_validation as cv, discovery)
|
|
||||||
from homeassistant.util.json import load_json, save_json
|
from homeassistant.util.json import load_json, save_json
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -279,8 +278,3 @@ class iOSIdentifyDeviceView(HomeAssistantView):
|
||||||
HTTP_INTERNAL_SERVER_ERROR)
|
HTTP_INTERNAL_SERVER_ERROR)
|
||||||
|
|
||||||
return self.json({"status": "registered"})
|
return self.json({"status": "registered"})
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(
|
|
||||||
DOMAIN, 'Home Assistant iOS', lambda *_: True,
|
|
||||||
config_entries.CONN_CLASS_CLOUD_PUSH)
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
"""Config flow for iOS."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(
|
||||||
|
DOMAIN, 'Home Assistant iOS', lambda *_: True,
|
||||||
|
config_entries.CONN_CLASS_CLOUD_PUSH)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for iOS."""
|
||||||
|
|
||||||
|
DOMAIN = "ios"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ios",
|
"domain": "ios",
|
||||||
"name": "Ios",
|
"name": "Ios",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ios",
|
"documentation": "https://www.home-assistant.io/components/ios",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ipma",
|
"domain": "ipma",
|
||||||
"name": "Ipma",
|
"name": "Ipma",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ipma",
|
"documentation": "https://www.home-assistant.io/components/ipma",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyipma==1.2.1"
|
"pyipma==1.2.1"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "iqvia",
|
"domain": "iqvia",
|
||||||
"name": "IQVIA",
|
"name": "IQVIA",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/iqvia",
|
"documentation": "https://www.home-assistant.io/components/iqvia",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"numpy==1.16.3",
|
"numpy==1.16.3",
|
||||||
|
|
|
@ -4,10 +4,10 @@ import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import CONF_PORT
|
from homeassistant.const import CONF_PORT
|
||||||
from homeassistant.helpers import config_entry_flow
|
|
||||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
DOMAIN = 'lifx'
|
|
||||||
CONF_SERVER = 'server'
|
CONF_SERVER = 'server'
|
||||||
CONF_BROADCAST = 'broadcast'
|
CONF_BROADCAST = 'broadcast'
|
||||||
|
|
||||||
|
@ -55,15 +55,3 @@ async def async_unload_entry(hass, entry):
|
||||||
await hass.config_entries.async_forward_entry_unload(entry, LIGHT_DOMAIN)
|
await hass.config_entries.async_forward_entry_unload(entry, LIGHT_DOMAIN)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _async_has_devices(hass):
|
|
||||||
"""Return if there are devices that can be discovered."""
|
|
||||||
import aiolifx
|
|
||||||
|
|
||||||
lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan()
|
|
||||||
return len(lifx_ip_addresses) > 0
|
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(
|
|
||||||
DOMAIN, 'LIFX', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""Config flow flow LIFX."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_has_devices(hass):
|
||||||
|
"""Return if there are devices that can be discovered."""
|
||||||
|
import aiolifx
|
||||||
|
|
||||||
|
lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan()
|
||||||
|
return len(lifx_ip_addresses) > 0
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(
|
||||||
|
DOMAIN, 'LIFX', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for LIFX."""
|
||||||
|
|
||||||
|
DOMAIN = 'lifx'
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "lifx",
|
"domain": "lifx",
|
||||||
"name": "Lifx",
|
"name": "Lifx",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/lifx",
|
"documentation": "https://www.home-assistant.io/components/lifx",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aiolifx==0.6.7",
|
"aiolifx==0.6.7",
|
||||||
|
|
|
@ -145,12 +145,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'Locative Webhook',
|
|
||||||
{
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/locative/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
"""Config flow for Locative."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'Locative Webhook',
|
||||||
|
{
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/locative/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for Locative."""
|
||||||
|
|
||||||
|
DOMAIN = "locative"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "locative",
|
"domain": "locative",
|
||||||
"name": "Locative",
|
"name": "Locative",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/locative",
|
"documentation": "https://www.home-assistant.io/components/locative",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "logi_circle",
|
"domain": "logi_circle",
|
||||||
"name": "Logi Circle",
|
"name": "Logi Circle",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/logi_circle",
|
"documentation": "https://www.home-assistant.io/components/logi_circle",
|
||||||
"requirements": ["logi_circle==0.2.2"],
|
"requirements": ["logi_circle==0.2.2"],
|
||||||
"dependencies": ["ffmpeg"],
|
"dependencies": ["ffmpeg"],
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "luftdaten",
|
"domain": "luftdaten",
|
||||||
"name": "Luftdaten",
|
"name": "Luftdaten",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/luftdaten",
|
"documentation": "https://www.home-assistant.io/components/luftdaten",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"luftdaten==0.3.4"
|
"luftdaten==0.3.4"
|
||||||
|
|
|
@ -10,12 +10,14 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_DOMAIN, CONF_WEBHOOK_ID
|
from homeassistant.const import CONF_API_KEY, CONF_DOMAIN, CONF_WEBHOOK_ID
|
||||||
from homeassistant.helpers import config_entry_flow
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_SANDBOX = 'sandbox'
|
CONF_SANDBOX = 'sandbox'
|
||||||
|
|
||||||
DEFAULT_SANDBOX = False
|
DEFAULT_SANDBOX = False
|
||||||
DOMAIN = 'mailgun'
|
|
||||||
|
|
||||||
MESSAGE_RECEIVED = '{}_message_received'.format(DOMAIN)
|
MESSAGE_RECEIVED = '{}_message_received'.format(DOMAIN)
|
||||||
|
|
||||||
|
@ -90,13 +92,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'Mailgun Webhook',
|
|
||||||
{
|
|
||||||
'mailgun_url': 'https://documentation.mailgun.com/en/latest/user_manual.html#webhooks', # noqa: E501 pylint: disable=line-too-long
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/mailgun/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""Config flow for Mailgun."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'Mailgun Webhook',
|
||||||
|
{
|
||||||
|
'mailgun_url': 'https://documentation.mailgun.com/en/latest/user_manual.html#webhooks', # noqa: E501 pylint: disable=line-too-long
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/mailgun/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for Mailgun."""
|
||||||
|
|
||||||
|
DOMAIN = "mailgun"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "mailgun",
|
"domain": "mailgun",
|
||||||
"name": "Mailgun",
|
"name": "Mailgun",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/mailgun",
|
"documentation": "https://www.home-assistant.io/components/mailgun",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pymailgunner==1.4"
|
"pymailgunner==1.4"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
"""Integrates Native Apps to Home Assistant."""
|
"""Integrates Native Apps to Home Assistant."""
|
||||||
from homeassistant import config_entries
|
|
||||||
from homeassistant.const import CONF_WEBHOOK_ID
|
from homeassistant.const import CONF_WEBHOOK_ID
|
||||||
from homeassistant.components.webhook import async_register as webhook_register
|
from homeassistant.components.webhook import async_register as webhook_register
|
||||||
from homeassistant.helpers import device_registry as dr, discovery
|
from homeassistant.helpers import device_registry as dr, discovery
|
||||||
|
@ -91,26 +90,3 @@ async def async_setup_entry(hass, entry):
|
||||||
hass.config_entries.async_forward_entry_setup(entry, DATA_SENSOR))
|
hass.config_entries.async_forward_entry_setup(entry, DATA_SENSOR))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@config_entries.HANDLERS.register(DOMAIN)
|
|
||||||
class MobileAppFlowHandler(config_entries.ConfigFlow):
|
|
||||||
"""Handle a Mobile App config flow."""
|
|
||||||
|
|
||||||
VERSION = 1
|
|
||||||
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
|
|
||||||
|
|
||||||
async def async_step_user(self, user_input=None):
|
|
||||||
"""Handle a flow initialized by the user."""
|
|
||||||
placeholders = {
|
|
||||||
'apps_url':
|
|
||||||
'https://www.home-assistant.io/components/mobile_app/#apps'
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.async_abort(reason='install_app',
|
|
||||||
description_placeholders=placeholders)
|
|
||||||
|
|
||||||
async def async_step_registration(self, user_input=None):
|
|
||||||
"""Handle a flow initialized during registration."""
|
|
||||||
return self.async_create_entry(title=user_input[ATTR_DEVICE_NAME],
|
|
||||||
data=user_input)
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
"""Config flow for Mobile App."""
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN, ATTR_DEVICE_NAME
|
||||||
|
|
||||||
|
|
||||||
|
@config_entries.HANDLERS.register(DOMAIN)
|
||||||
|
class MobileAppFlowHandler(config_entries.ConfigFlow):
|
||||||
|
"""Handle a Mobile App config flow."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input=None):
|
||||||
|
"""Handle a flow initialized by the user."""
|
||||||
|
placeholders = {
|
||||||
|
'apps_url':
|
||||||
|
'https://www.home-assistant.io/components/mobile_app/#apps'
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.async_abort(reason='install_app',
|
||||||
|
description_placeholders=placeholders)
|
||||||
|
|
||||||
|
async def async_step_registration(self, user_input=None):
|
||||||
|
"""Handle a flow initialized during registration."""
|
||||||
|
return self.async_create_entry(title=user_input[ATTR_DEVICE_NAME],
|
||||||
|
data=user_input)
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "mobile_app",
|
"domain": "mobile_app",
|
||||||
"name": "Home Assistant Mobile App Support",
|
"name": "Home Assistant Mobile App Support",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/mobile_app",
|
"documentation": "https://www.home-assistant.io/components/mobile_app",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"PyNaCl==1.3.0"
|
"PyNaCl==1.3.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "mqtt",
|
"domain": "mqtt",
|
||||||
"name": "MQTT",
|
"name": "MQTT",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/mqtt",
|
"documentation": "https://www.home-assistant.io/components/mqtt",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"hbmqtt==0.9.4",
|
"hbmqtt==0.9.4",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "nest",
|
"domain": "nest",
|
||||||
"name": "Nest",
|
"name": "Nest",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/nest",
|
"documentation": "https://www.home-assistant.io/components/nest",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"python-nest==4.1.0"
|
"python-nest==4.1.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "openuv",
|
"domain": "openuv",
|
||||||
"name": "Openuv",
|
"name": "Openuv",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/openuv",
|
"documentation": "https://www.home-assistant.io/components/openuv",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyopenuv==1.0.9"
|
"pyopenuv==1.0.9"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "owntracks",
|
"domain": "owntracks",
|
||||||
"name": "Owntracks",
|
"name": "Owntracks",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/owntracks",
|
"documentation": "https://www.home-assistant.io/components/owntracks",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"PyNaCl==1.3.0"
|
"PyNaCl==1.3.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "point",
|
"domain": "point",
|
||||||
"name": "Point",
|
"name": "Point",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/point",
|
"documentation": "https://www.home-assistant.io/components/point",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pypoint==1.1.1"
|
"pypoint==1.1.1"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "ps4",
|
"domain": "ps4",
|
||||||
"name": "Ps4",
|
"name": "Ps4",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/ps4",
|
"documentation": "https://www.home-assistant.io/components/ps4",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyps4-homeassistant==0.7.3"
|
"pyps4-homeassistant==0.7.3"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "rainmachine",
|
"domain": "rainmachine",
|
||||||
"name": "Rainmachine",
|
"name": "Rainmachine",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/rainmachine",
|
"documentation": "https://www.home-assistant.io/components/rainmachine",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"regenmaschine==1.4.0"
|
"regenmaschine==1.4.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "simplisafe",
|
"domain": "simplisafe",
|
||||||
"name": "Simplisafe",
|
"name": "Simplisafe",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/simplisafe",
|
"documentation": "https://www.home-assistant.io/components/simplisafe",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"simplisafe-python==3.4.1"
|
"simplisafe-python==3.4.1"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "smartthings",
|
"domain": "smartthings",
|
||||||
"name": "Smartthings",
|
"name": "Smartthings",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/smartthings",
|
"documentation": "https://www.home-assistant.io/components/smartthings",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pysmartapp==0.3.2",
|
"pysmartapp==0.3.2",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "smhi",
|
"domain": "smhi",
|
||||||
"name": "Smhi",
|
"name": "Smhi",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/smhi",
|
"documentation": "https://www.home-assistant.io/components/smhi",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"smhi-pkg==1.0.10"
|
"smhi-pkg==1.0.10"
|
||||||
|
|
|
@ -5,10 +5,11 @@ import voluptuous as vol
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||||
from homeassistant.const import CONF_HOSTS, ATTR_ENTITY_ID, ATTR_TIME
|
from homeassistant.const import CONF_HOSTS, ATTR_ENTITY_ID, ATTR_TIME
|
||||||
from homeassistant.helpers import config_entry_flow, config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
|
||||||
DOMAIN = 'sonos'
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
CONF_ADVERTISE_ADDR = 'advertise_addr'
|
CONF_ADVERTISE_ADDR = 'advertise_addr'
|
||||||
CONF_INTERFACE_ADDR = 'interface_addr'
|
CONF_INTERFACE_ADDR = 'interface_addr'
|
||||||
|
@ -141,14 +142,3 @@ async def async_setup_entry(hass, entry):
|
||||||
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
|
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
|
||||||
entry, MP_DOMAIN))
|
entry, MP_DOMAIN))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _async_has_devices(hass):
|
|
||||||
"""Return if there are devices that can be discovered."""
|
|
||||||
import pysonos
|
|
||||||
|
|
||||||
return await hass.async_add_executor_job(pysonos.discover)
|
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(
|
|
||||||
DOMAIN, 'Sonos', _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH)
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
"""Config flow for SONOS."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_has_devices(hass):
|
||||||
|
"""Return if there are devices that can be discovered."""
|
||||||
|
import pysonos
|
||||||
|
|
||||||
|
return await hass.async_add_executor_job(pysonos.discover)
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(
|
||||||
|
DOMAIN, 'Sonos', _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for Sonos."""
|
||||||
|
|
||||||
|
DOMAIN = "sonos"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "sonos",
|
"domain": "sonos",
|
||||||
"name": "Sonos",
|
"name": "Sonos",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/sonos",
|
"documentation": "https://www.home-assistant.io/components/sonos",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pysonos==0.0.12"
|
"pysonos==0.0.12"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "tellduslive",
|
"domain": "tellduslive",
|
||||||
"name": "Tellduslive",
|
"name": "Tellduslive",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/tellduslive",
|
"documentation": "https://www.home-assistant.io/components/tellduslive",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"tellduslive==0.10.10"
|
"tellduslive==0.10.10"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "toon",
|
"domain": "toon",
|
||||||
"name": "Toon",
|
"name": "Toon",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/toon",
|
"documentation": "https://www.home-assistant.io/components/toon",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"toonapilib==3.2.2"
|
"toonapilib==3.2.2"
|
||||||
|
|
|
@ -5,14 +5,12 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.helpers import config_entry_flow
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from .config_flow import async_get_devices
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'tplink'
|
|
||||||
|
|
||||||
TPLINK_HOST_SCHEMA = vol.Schema({
|
TPLINK_HOST_SCHEMA = vol.Schema({
|
||||||
vol.Required(CONF_HOST): cv.string
|
vol.Required(CONF_HOST): cv.string
|
||||||
})
|
})
|
||||||
|
@ -34,16 +32,6 @@ CONFIG_SCHEMA = vol.Schema({
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
async def _async_has_devices(hass):
|
|
||||||
"""Return if there are devices that can be discovered."""
|
|
||||||
from pyHS100 import Discover
|
|
||||||
|
|
||||||
def discover():
|
|
||||||
devs = Discover.discover()
|
|
||||||
return devs
|
|
||||||
return await hass.async_add_executor_job(discover)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
"""Set up the TP-Link component."""
|
"""Set up the TP-Link component."""
|
||||||
conf = config.get(DOMAIN)
|
conf = config.get(DOMAIN)
|
||||||
|
@ -74,7 +62,7 @@ async def async_setup_entry(hass, config_entry):
|
||||||
# If initialized from configure integrations, there's no config
|
# If initialized from configure integrations, there's no config
|
||||||
# so we default here to True
|
# so we default here to True
|
||||||
if config_data is None or config_data[CONF_DISCOVERY]:
|
if config_data is None or config_data[CONF_DISCOVERY]:
|
||||||
devs = await _async_has_devices(hass)
|
devs = await async_get_devices(hass)
|
||||||
_LOGGER.info("Discovered %s TP-Link smart home device(s)", len(devs))
|
_LOGGER.info("Discovered %s TP-Link smart home device(s)", len(devs))
|
||||||
devices.update(devs)
|
devices.update(devs)
|
||||||
|
|
||||||
|
@ -149,9 +137,3 @@ async def async_unload_entry(hass, entry):
|
||||||
# We were not able to unload the platforms, either because there
|
# We were not able to unload the platforms, either because there
|
||||||
# were none or one of the forward_unloads failed.
|
# were none or one of the forward_unloads failed.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(DOMAIN,
|
|
||||||
'TP-Link Smart Home',
|
|
||||||
_async_has_devices,
|
|
||||||
config_entries.CONN_CLASS_LOCAL_POLL)
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
"""Config flow for TP-Link."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_devices(hass):
|
||||||
|
"""Return if there are devices that can be discovered."""
|
||||||
|
from pyHS100 import Discover
|
||||||
|
|
||||||
|
def discover():
|
||||||
|
devs = Discover.discover()
|
||||||
|
return devs
|
||||||
|
return await hass.async_add_executor_job(discover)
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(DOMAIN,
|
||||||
|
'TP-Link Smart Home',
|
||||||
|
async_get_devices,
|
||||||
|
config_entries.CONN_CLASS_LOCAL_POLL)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for TP-Link."""
|
||||||
|
|
||||||
|
DOMAIN = "tplink"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "tplink",
|
"domain": "tplink",
|
||||||
"name": "Tplink",
|
"name": "Tplink",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/tplink",
|
"documentation": "https://www.home-assistant.io/components/tplink",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyHS100==0.3.5",
|
"pyHS100==0.3.5",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "tradfri",
|
"domain": "tradfri",
|
||||||
"name": "Tradfri",
|
"name": "Tradfri",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/tradfri",
|
"documentation": "https://www.home-assistant.io/components/tradfri",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pytradfri[async]==6.0.1"
|
"pytradfri[async]==6.0.1"
|
||||||
|
|
|
@ -4,8 +4,7 @@ import voluptuous as vol
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.const import CONF_WEBHOOK_ID
|
from homeassistant.const import CONF_WEBHOOK_ID
|
||||||
from homeassistant.helpers import config_entry_flow
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from .const import DOMAIN
|
||||||
DOMAIN = 'twilio'
|
|
||||||
|
|
||||||
CONF_ACCOUNT_SID = 'account_sid'
|
CONF_ACCOUNT_SID = 'account_sid'
|
||||||
CONF_AUTH_TOKEN = 'auth_token'
|
CONF_AUTH_TOKEN = 'auth_token'
|
||||||
|
@ -60,14 +59,3 @@ async def async_unload_entry(hass, entry):
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
async_remove_entry = config_entry_flow.webhook_async_remove_entry
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_webhook_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'Twilio Webhook',
|
|
||||||
{
|
|
||||||
'twilio_url':
|
|
||||||
'https://www.twilio.com/docs/glossary/what-is-a-webhook',
|
|
||||||
'docs_url': 'https://www.home-assistant.io/components/twilio/'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
"""Config flow for Twilio."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_webhook_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'Twilio Webhook',
|
||||||
|
{
|
||||||
|
'twilio_url':
|
||||||
|
'https://www.twilio.com/docs/glossary/what-is-a-webhook',
|
||||||
|
'docs_url': 'https://www.home-assistant.io/components/twilio/'
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Const for Twilio."""
|
||||||
|
|
||||||
|
DOMAIN = "twilio"
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "twilio",
|
"domain": "twilio",
|
||||||
"name": "Twilio",
|
"name": "Twilio",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/twilio",
|
"documentation": "https://www.home-assistant.io/components/twilio",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"twilio==6.19.1"
|
"twilio==6.19.1"
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
"""Support for devices connected to UniFi POE."""
|
"""Support for devices connected to UniFi POE."""
|
||||||
import voluptuous as vol
|
from homeassistant.const import CONF_HOST
|
||||||
|
|
||||||
from homeassistant import config_entries
|
|
||||||
from homeassistant.const import (
|
|
||||||
CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME, CONF_VERIFY_SSL)
|
|
||||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
||||||
|
|
||||||
from .const import (CONF_CONTROLLER, CONF_POE_CONTROL, CONF_SITE_ID,
|
from .const import CONF_CONTROLLER, CONF_SITE_ID, CONTROLLER_ID, DOMAIN
|
||||||
CONTROLLER_ID, DOMAIN, LOGGER)
|
from .controller import UniFiController
|
||||||
from .controller import UniFiController, get_controller
|
|
||||||
from .errors import (
|
|
||||||
AlreadyConfigured, AuthenticationRequired, CannotConnect, UserLevel)
|
|
||||||
|
|
||||||
DEFAULT_PORT = 8443
|
|
||||||
DEFAULT_SITE_ID = 'default'
|
|
||||||
DEFAULT_VERIFY_SSL = False
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
|
@ -64,116 +53,3 @@ async def async_unload_entry(hass, config_entry):
|
||||||
)
|
)
|
||||||
controller = hass.data[DOMAIN].pop(controller_id)
|
controller = hass.data[DOMAIN].pop(controller_id)
|
||||||
return await controller.async_reset()
|
return await controller.async_reset()
|
||||||
|
|
||||||
|
|
||||||
@config_entries.HANDLERS.register(DOMAIN)
|
|
||||||
class UnifiFlowHandler(config_entries.ConfigFlow):
|
|
||||||
"""Handle a UniFi config flow."""
|
|
||||||
|
|
||||||
VERSION = 1
|
|
||||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Initialize the UniFi flow."""
|
|
||||||
self.config = None
|
|
||||||
self.desc = None
|
|
||||||
self.sites = None
|
|
||||||
|
|
||||||
async def async_step_user(self, user_input=None):
|
|
||||||
"""Handle a flow initialized by the user."""
|
|
||||||
errors = {}
|
|
||||||
|
|
||||||
if user_input is not None:
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.config = {
|
|
||||||
CONF_HOST: user_input[CONF_HOST],
|
|
||||||
CONF_USERNAME: user_input[CONF_USERNAME],
|
|
||||||
CONF_PASSWORD: user_input[CONF_PASSWORD],
|
|
||||||
CONF_PORT: user_input.get(CONF_PORT),
|
|
||||||
CONF_VERIFY_SSL: user_input.get(CONF_VERIFY_SSL),
|
|
||||||
CONF_SITE_ID: DEFAULT_SITE_ID,
|
|
||||||
}
|
|
||||||
controller = await get_controller(self.hass, **self.config)
|
|
||||||
|
|
||||||
self.sites = await controller.sites()
|
|
||||||
|
|
||||||
return await self.async_step_site()
|
|
||||||
|
|
||||||
except AuthenticationRequired:
|
|
||||||
errors['base'] = 'faulty_credentials'
|
|
||||||
|
|
||||||
except CannotConnect:
|
|
||||||
errors['base'] = 'service_unavailable'
|
|
||||||
|
|
||||||
except Exception: # pylint: disable=broad-except
|
|
||||||
LOGGER.error(
|
|
||||||
'Unknown error connecting with UniFi Controller at %s',
|
|
||||||
user_input[CONF_HOST])
|
|
||||||
return self.async_abort(reason='unknown')
|
|
||||||
|
|
||||||
return self.async_show_form(
|
|
||||||
step_id='user',
|
|
||||||
data_schema=vol.Schema({
|
|
||||||
vol.Required(CONF_HOST): str,
|
|
||||||
vol.Required(CONF_USERNAME): str,
|
|
||||||
vol.Required(CONF_PASSWORD): str,
|
|
||||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): bool,
|
|
||||||
}),
|
|
||||||
errors=errors,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_step_site(self, user_input=None):
|
|
||||||
"""Select site to control."""
|
|
||||||
errors = {}
|
|
||||||
|
|
||||||
if user_input is not None:
|
|
||||||
|
|
||||||
try:
|
|
||||||
desc = user_input.get(CONF_SITE_ID, self.desc)
|
|
||||||
for site in self.sites.values():
|
|
||||||
if desc == site['desc']:
|
|
||||||
if site['role'] != 'admin':
|
|
||||||
raise UserLevel
|
|
||||||
self.config[CONF_SITE_ID] = site['name']
|
|
||||||
break
|
|
||||||
|
|
||||||
for entry in self._async_current_entries():
|
|
||||||
controller = entry.data[CONF_CONTROLLER]
|
|
||||||
if controller[CONF_HOST] == self.config[CONF_HOST] and \
|
|
||||||
controller[CONF_SITE_ID] == self.config[CONF_SITE_ID]:
|
|
||||||
raise AlreadyConfigured
|
|
||||||
|
|
||||||
data = {
|
|
||||||
CONF_CONTROLLER: self.config,
|
|
||||||
CONF_POE_CONTROL: True
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.async_create_entry(
|
|
||||||
title=desc,
|
|
||||||
data=data
|
|
||||||
)
|
|
||||||
|
|
||||||
except AlreadyConfigured:
|
|
||||||
return self.async_abort(reason='already_configured')
|
|
||||||
|
|
||||||
except UserLevel:
|
|
||||||
return self.async_abort(reason='user_privilege')
|
|
||||||
|
|
||||||
if len(self.sites) == 1:
|
|
||||||
self.desc = next(iter(self.sites.values()))['desc']
|
|
||||||
return await self.async_step_site(user_input={})
|
|
||||||
|
|
||||||
sites = []
|
|
||||||
for site in self.sites.values():
|
|
||||||
sites.append(site['desc'])
|
|
||||||
|
|
||||||
return self.async_show_form(
|
|
||||||
step_id='site',
|
|
||||||
data_schema=vol.Schema({
|
|
||||||
vol.Required(CONF_SITE_ID): vol.In(sites)
|
|
||||||
}),
|
|
||||||
errors=errors,
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
"""Config flow for Unifi."""
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME, CONF_VERIFY_SSL)
|
||||||
|
|
||||||
|
from .const import (CONF_CONTROLLER, CONF_POE_CONTROL, CONF_SITE_ID,
|
||||||
|
DOMAIN, LOGGER)
|
||||||
|
from .controller import get_controller
|
||||||
|
from .errors import (
|
||||||
|
AlreadyConfigured, AuthenticationRequired, CannotConnect, UserLevel)
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_PORT = 8443
|
||||||
|
DEFAULT_SITE_ID = 'default'
|
||||||
|
DEFAULT_VERIFY_SSL = False
|
||||||
|
|
||||||
|
|
||||||
|
@config_entries.HANDLERS.register(DOMAIN)
|
||||||
|
class UnifiFlowHandler(config_entries.ConfigFlow):
|
||||||
|
"""Handle a UniFi config flow."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize the UniFi flow."""
|
||||||
|
self.config = None
|
||||||
|
self.desc = None
|
||||||
|
self.sites = None
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input=None):
|
||||||
|
"""Handle a flow initialized by the user."""
|
||||||
|
errors = {}
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.config = {
|
||||||
|
CONF_HOST: user_input[CONF_HOST],
|
||||||
|
CONF_USERNAME: user_input[CONF_USERNAME],
|
||||||
|
CONF_PASSWORD: user_input[CONF_PASSWORD],
|
||||||
|
CONF_PORT: user_input.get(CONF_PORT),
|
||||||
|
CONF_VERIFY_SSL: user_input.get(CONF_VERIFY_SSL),
|
||||||
|
CONF_SITE_ID: DEFAULT_SITE_ID,
|
||||||
|
}
|
||||||
|
controller = await get_controller(self.hass, **self.config)
|
||||||
|
|
||||||
|
self.sites = await controller.sites()
|
||||||
|
|
||||||
|
return await self.async_step_site()
|
||||||
|
|
||||||
|
except AuthenticationRequired:
|
||||||
|
errors['base'] = 'faulty_credentials'
|
||||||
|
|
||||||
|
except CannotConnect:
|
||||||
|
errors['base'] = 'service_unavailable'
|
||||||
|
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
LOGGER.error(
|
||||||
|
'Unknown error connecting with UniFi Controller at %s',
|
||||||
|
user_input[CONF_HOST])
|
||||||
|
return self.async_abort(reason='unknown')
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id='user',
|
||||||
|
data_schema=vol.Schema({
|
||||||
|
vol.Required(CONF_HOST): str,
|
||||||
|
vol.Required(CONF_USERNAME): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
|
||||||
|
vol.Optional(
|
||||||
|
CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): bool,
|
||||||
|
}),
|
||||||
|
errors=errors,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_site(self, user_input=None):
|
||||||
|
"""Select site to control."""
|
||||||
|
errors = {}
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
|
||||||
|
try:
|
||||||
|
desc = user_input.get(CONF_SITE_ID, self.desc)
|
||||||
|
for site in self.sites.values():
|
||||||
|
if desc == site['desc']:
|
||||||
|
if site['role'] != 'admin':
|
||||||
|
raise UserLevel
|
||||||
|
self.config[CONF_SITE_ID] = site['name']
|
||||||
|
break
|
||||||
|
|
||||||
|
for entry in self._async_current_entries():
|
||||||
|
controller = entry.data[CONF_CONTROLLER]
|
||||||
|
if controller[CONF_HOST] == self.config[CONF_HOST] and \
|
||||||
|
controller[CONF_SITE_ID] == self.config[CONF_SITE_ID]:
|
||||||
|
raise AlreadyConfigured
|
||||||
|
|
||||||
|
data = {
|
||||||
|
CONF_CONTROLLER: self.config,
|
||||||
|
CONF_POE_CONTROL: True
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.async_create_entry(
|
||||||
|
title=desc,
|
||||||
|
data=data
|
||||||
|
)
|
||||||
|
|
||||||
|
except AlreadyConfigured:
|
||||||
|
return self.async_abort(reason='already_configured')
|
||||||
|
|
||||||
|
except UserLevel:
|
||||||
|
return self.async_abort(reason='user_privilege')
|
||||||
|
|
||||||
|
if len(self.sites) == 1:
|
||||||
|
self.desc = next(iter(self.sites.values()))['desc']
|
||||||
|
return await self.async_step_site(user_input={})
|
||||||
|
|
||||||
|
sites = []
|
||||||
|
for site in self.sites.values():
|
||||||
|
sites.append(site['desc'])
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id='site',
|
||||||
|
data_schema=vol.Schema({
|
||||||
|
vol.Required(CONF_SITE_ID): vol.In(sites)
|
||||||
|
}),
|
||||||
|
errors=errors,
|
||||||
|
)
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "unifi",
|
"domain": "unifi",
|
||||||
"name": "Unifi",
|
"name": "Unifi",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/unifi",
|
"documentation": "https://www.home-assistant.io/components/unifi",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aiounifi==4",
|
"aiounifi==4",
|
||||||
|
|
|
@ -7,7 +7,6 @@ import voluptuous as vol
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.helpers import config_entry_flow
|
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers import dispatcher
|
from homeassistant.helpers import dispatcher
|
||||||
|
@ -204,10 +203,3 @@ async def async_unload_entry(hass: HomeAssistantType,
|
||||||
dispatcher.async_dispatcher_send(hass, SIGNAL_REMOVE_SENSOR, device)
|
dispatcher.async_dispatcher_send(hass, SIGNAL_REMOVE_SENSOR, device)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
config_entry_flow.register_discovery_flow(
|
|
||||||
DOMAIN,
|
|
||||||
'UPnP/IGD',
|
|
||||||
Device.async_discover,
|
|
||||||
config_entries.CONN_CLASS_LOCAL_POLL)
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""Config flow for UPNP."""
|
||||||
|
from homeassistant.helpers import config_entry_flow
|
||||||
|
from homeassistant import config_entries
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .device import Device
|
||||||
|
|
||||||
|
|
||||||
|
config_entry_flow.register_discovery_flow(
|
||||||
|
DOMAIN,
|
||||||
|
'UPnP/IGD',
|
||||||
|
Device.async_discover,
|
||||||
|
config_entries.CONN_CLASS_LOCAL_POLL)
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "upnp",
|
"domain": "upnp",
|
||||||
"name": "Upnp",
|
"name": "Upnp",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/upnp",
|
"documentation": "https://www.home-assistant.io/components/upnp",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"async-upnp-client==0.14.7"
|
"async-upnp-client==0.14.7"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "zha",
|
"domain": "zha",
|
||||||
"name": "Zigbee Home Automation",
|
"name": "Zigbee Home Automation",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/zha",
|
"documentation": "https://www.home-assistant.io/components/zha",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"bellows-homeassistant==0.7.3",
|
"bellows-homeassistant==0.7.3",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "zone",
|
"domain": "zone",
|
||||||
"name": "Zone",
|
"name": "Zone",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/zone",
|
"documentation": "https://www.home-assistant.io/components/zone",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"domain": "zwave",
|
"domain": "zwave",
|
||||||
"name": "Z-Wave",
|
"name": "Z-Wave",
|
||||||
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/components/zwave",
|
"documentation": "https://www.home-assistant.io/components/zwave",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"homeassistant-pyozw==0.1.4",
|
"homeassistant-pyozw==0.1.4",
|
||||||
|
|
|
@ -140,57 +140,6 @@ SOURCE_DISCOVERY = 'discovery'
|
||||||
SOURCE_IMPORT = 'import'
|
SOURCE_IMPORT = 'import'
|
||||||
|
|
||||||
HANDLERS = Registry()
|
HANDLERS = Registry()
|
||||||
# Components that have config flows. In future we will auto-generate this list.
|
|
||||||
FLOWS = [
|
|
||||||
'ambiclimate',
|
|
||||||
'ambient_station',
|
|
||||||
'axis',
|
|
||||||
'cast',
|
|
||||||
'daikin',
|
|
||||||
'deconz',
|
|
||||||
'dialogflow',
|
|
||||||
'esphome',
|
|
||||||
'emulated_roku',
|
|
||||||
'geofency',
|
|
||||||
'gpslogger',
|
|
||||||
'hangouts',
|
|
||||||
'heos',
|
|
||||||
'homekit_controller',
|
|
||||||
'homematicip_cloud',
|
|
||||||
'hue',
|
|
||||||
'ifttt',
|
|
||||||
'ios',
|
|
||||||
'ipma',
|
|
||||||
'iqvia',
|
|
||||||
'lifx',
|
|
||||||
'locative',
|
|
||||||
'logi_circle',
|
|
||||||
'luftdaten',
|
|
||||||
'mailgun',
|
|
||||||
'mobile_app',
|
|
||||||
'mqtt',
|
|
||||||
'nest',
|
|
||||||
'openuv',
|
|
||||||
'owntracks',
|
|
||||||
'point',
|
|
||||||
'ps4',
|
|
||||||
'rainmachine',
|
|
||||||
'simplisafe',
|
|
||||||
'smartthings',
|
|
||||||
'smhi',
|
|
||||||
'sonos',
|
|
||||||
'tellduslive',
|
|
||||||
'toon',
|
|
||||||
'tplink',
|
|
||||||
'tradfri',
|
|
||||||
'twilio',
|
|
||||||
'unifi',
|
|
||||||
'upnp',
|
|
||||||
'zha',
|
|
||||||
'zone',
|
|
||||||
'zwave',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
STORAGE_KEY = 'core.config_entries'
|
STORAGE_KEY = 'core.config_entries'
|
||||||
STORAGE_VERSION = 1
|
STORAGE_VERSION = 1
|
||||||
|
@ -299,7 +248,17 @@ class ConfigEntry:
|
||||||
if integration is None:
|
if integration is None:
|
||||||
integration = await loader.async_get_integration(hass, self.domain)
|
integration = await loader.async_get_integration(hass, self.domain)
|
||||||
|
|
||||||
component = integration.get_component()
|
try:
|
||||||
|
component = integration.get_component()
|
||||||
|
if self.domain == integration.domain:
|
||||||
|
integration.get_platform('config_flow')
|
||||||
|
except ImportError as err:
|
||||||
|
_LOGGER.error(
|
||||||
|
'Error importing integration %s to set up %s config entry: %s',
|
||||||
|
integration.domain, self.domain, err)
|
||||||
|
if self.domain == integration.domain:
|
||||||
|
self.state = ENTRY_STATE_SETUP_ERROR
|
||||||
|
return
|
||||||
|
|
||||||
# Perform migration
|
# Perform migration
|
||||||
if integration.domain == self.domain:
|
if integration.domain == self.domain:
|
||||||
|
@ -422,7 +381,8 @@ class ConfigEntry:
|
||||||
if self.version == handler.VERSION:
|
if self.version == handler.VERSION:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
component = getattr(hass.components, self.domain)
|
integration = await loader.async_get_integration(hass, self.domain)
|
||||||
|
component = integration.get_component()
|
||||||
supports_migrate = hasattr(component, 'async_migrate_entry')
|
supports_migrate = hasattr(component, 'async_migrate_entry')
|
||||||
if not supports_migrate:
|
if not supports_migrate:
|
||||||
_LOGGER.error("Migration handler not found for entry %s for %s",
|
_LOGGER.error("Migration handler not found for entry %s for %s",
|
||||||
|
@ -430,7 +390,9 @@ class ConfigEntry:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = await component.async_migrate_entry(hass, self)
|
result = await component.async_migrate_entry( # type: ignore
|
||||||
|
hass, self
|
||||||
|
)
|
||||||
if not isinstance(result, bool):
|
if not isinstance(result, bool):
|
||||||
_LOGGER.error('%s.async_migrate_entry did not return boolean',
|
_LOGGER.error('%s.async_migrate_entry did not return boolean',
|
||||||
self.domain)
|
self.domain)
|
||||||
|
@ -441,7 +403,7 @@ class ConfigEntry:
|
||||||
return result
|
return result
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception('Error migrating entry %s for %s',
|
_LOGGER.exception('Error migrating entry %s for %s',
|
||||||
self.title, component.DOMAIN)
|
self.title, self.domain)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def add_update_listener(self, listener: Callable) -> Callable:
|
def add_update_listener(self, listener: Callable) -> Callable:
|
||||||
|
@ -714,10 +676,10 @@ class ConfigEntries:
|
||||||
self.hass, self._hass_config, integration)
|
self.hass, self._hass_config, integration)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
integration.get_component()
|
integration.get_platform('config_flow')
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
'Error occurred while loading integration %s: %s',
|
'Error occurred loading config flow for integration %s: %s',
|
||||||
handler_key, err)
|
handler_key, err)
|
||||||
raise data_entry_flow.UnknownHandler
|
raise data_entry_flow.UnknownHandler
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
"""Automatically generated by hassfest.
|
||||||
|
|
||||||
|
To update, run python3 -m hassfest
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
FLOWS = [
|
||||||
|
"ambiclimate",
|
||||||
|
"ambient_station",
|
||||||
|
"axis",
|
||||||
|
"cast",
|
||||||
|
"daikin",
|
||||||
|
"deconz",
|
||||||
|
"dialogflow",
|
||||||
|
"emulated_roku",
|
||||||
|
"esphome",
|
||||||
|
"geofency",
|
||||||
|
"gpslogger",
|
||||||
|
"hangouts",
|
||||||
|
"heos",
|
||||||
|
"homekit_controller",
|
||||||
|
"homematicip_cloud",
|
||||||
|
"hue",
|
||||||
|
"ifttt",
|
||||||
|
"ios",
|
||||||
|
"ipma",
|
||||||
|
"iqvia",
|
||||||
|
"lifx",
|
||||||
|
"locative",
|
||||||
|
"logi_circle",
|
||||||
|
"luftdaten",
|
||||||
|
"mailgun",
|
||||||
|
"mobile_app",
|
||||||
|
"mqtt",
|
||||||
|
"nest",
|
||||||
|
"openuv",
|
||||||
|
"owntracks",
|
||||||
|
"point",
|
||||||
|
"ps4",
|
||||||
|
"rainmachine",
|
||||||
|
"simplisafe",
|
||||||
|
"smartthings",
|
||||||
|
"smhi",
|
||||||
|
"sonos",
|
||||||
|
"tellduslive",
|
||||||
|
"toon",
|
||||||
|
"tplink",
|
||||||
|
"tradfri",
|
||||||
|
"twilio",
|
||||||
|
"unifi",
|
||||||
|
"upnp",
|
||||||
|
"zha",
|
||||||
|
"zone",
|
||||||
|
"zwave"
|
||||||
|
]
|
|
@ -2,9 +2,9 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Iterable, Optional
|
from typing import Any, Dict, Iterable, Optional
|
||||||
|
|
||||||
from homeassistant import config_entries
|
|
||||||
from homeassistant.loader import async_get_integration, bind_hass
|
from homeassistant.loader import async_get_integration, bind_hass
|
||||||
from homeassistant.util.json import load_json
|
from homeassistant.util.json import load_json
|
||||||
|
from homeassistant.generated import config_flows
|
||||||
from .typing import HomeAssistantType
|
from .typing import HomeAssistantType
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -106,7 +106,7 @@ async def async_get_component_resources(hass: HomeAssistantType,
|
||||||
translation_cache = hass.data[TRANSLATION_STRING_CACHE][language]
|
translation_cache = hass.data[TRANSLATION_STRING_CACHE][language]
|
||||||
|
|
||||||
# Get the set of components
|
# Get the set of components
|
||||||
components = hass.config.components | set(config_entries.FLOWS)
|
components = hass.config.components | set(config_flows.FLOWS)
|
||||||
|
|
||||||
# Calculate the missing components
|
# Calculate the missing components
|
||||||
missing_components = components - set(translation_cache)
|
missing_components = components - set(translation_cache)
|
||||||
|
|
6
pylintrc
6
pylintrc
|
@ -1,3 +1,9 @@
|
||||||
|
[MASTER]
|
||||||
|
ignore=tests
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
good-names=i,j,k,ex,Run,_,fp
|
||||||
|
|
||||||
[MESSAGES CONTROL]
|
[MESSAGES CONTROL]
|
||||||
# Reasons disabled:
|
# Reasons disabled:
|
||||||
# locally-disabled - it spams too much
|
# locally-disabled - it spams too much
|
||||||
|
|
|
@ -3,13 +3,14 @@ import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .model import Integration, Config
|
from .model import Integration, Config
|
||||||
from . import dependencies, manifest, codeowners, services
|
from . import dependencies, manifest, codeowners, services, config_flow
|
||||||
|
|
||||||
PLUGINS = [
|
PLUGINS = [
|
||||||
manifest,
|
manifest,
|
||||||
dependencies,
|
dependencies,
|
||||||
codeowners,
|
codeowners,
|
||||||
services,
|
services,
|
||||||
|
config_flow,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
"""Generate config flow file."""
|
||||||
|
import json
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from .model import Integration, Config
|
||||||
|
|
||||||
|
BASE = """
|
||||||
|
\"\"\"Automatically generated by hassfest.
|
||||||
|
|
||||||
|
To update, run python3 -m hassfest
|
||||||
|
\"\"\"
|
||||||
|
|
||||||
|
|
||||||
|
FLOWS = {}
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
|
||||||
|
def validate_integration(integration: Integration):
|
||||||
|
"""Validate we can load config flow without installing requirements."""
|
||||||
|
if not (integration.path / "config_flow.py").is_file():
|
||||||
|
integration.add_error(
|
||||||
|
'config_flow',
|
||||||
|
"Config flows need to be defined in the file config_flow.py")
|
||||||
|
|
||||||
|
# Currently not require being able to load config flow without
|
||||||
|
# installing requirements.
|
||||||
|
# try:
|
||||||
|
# integration.import_pkg('config_flow')
|
||||||
|
# except ImportError as err:
|
||||||
|
# integration.add_error(
|
||||||
|
# 'config_flow',
|
||||||
|
# "Unable to import config flow: {}. Config flows should be able "
|
||||||
|
# "to be imported without installing requirements.".format(err))
|
||||||
|
# return
|
||||||
|
|
||||||
|
# if integration.domain not in config_entries.HANDLERS:
|
||||||
|
# integration.add_error(
|
||||||
|
# 'config_flow',
|
||||||
|
# "Importing the config flow platform did not register a config "
|
||||||
|
# "flow handler.")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_and_validate(integrations: Dict[str, Integration]):
|
||||||
|
"""Validate and generate config flow data."""
|
||||||
|
domains = []
|
||||||
|
|
||||||
|
for domain in sorted(integrations):
|
||||||
|
integration = integrations[domain]
|
||||||
|
|
||||||
|
if not integration.manifest:
|
||||||
|
continue
|
||||||
|
|
||||||
|
config_flow = integration.manifest.get('config_flow')
|
||||||
|
|
||||||
|
if not config_flow:
|
||||||
|
continue
|
||||||
|
|
||||||
|
validate_integration(integration)
|
||||||
|
|
||||||
|
domains.append(domain)
|
||||||
|
|
||||||
|
return BASE.format(json.dumps(domains, indent=4))
|
||||||
|
|
||||||
|
|
||||||
|
def validate(integrations: Dict[str, Integration], config: Config):
|
||||||
|
"""Validate config flow file."""
|
||||||
|
config_flow_path = config.root / 'homeassistant/generated/config_flows.py'
|
||||||
|
config.cache['config_flow'] = content = generate_and_validate(integrations)
|
||||||
|
|
||||||
|
with open(str(config_flow_path), 'r') as fp:
|
||||||
|
if fp.read().strip() != content:
|
||||||
|
config.add_error(
|
||||||
|
"config_flow",
|
||||||
|
"File config_flows.py is not up to date. "
|
||||||
|
"Run python3 -m script.hassfest",
|
||||||
|
fixable=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def generate(integrations: Dict[str, Integration], config: Config):
|
||||||
|
"""Generate config flow file."""
|
||||||
|
config_flow_path = config.root / 'homeassistant/generated/config_flows.py'
|
||||||
|
with open(str(config_flow_path), 'w') as fp:
|
||||||
|
fp.write(config.cache['config_flow'] + '\n')
|
|
@ -10,6 +10,7 @@ from .model import Integration
|
||||||
MANIFEST_SCHEMA = vol.Schema({
|
MANIFEST_SCHEMA = vol.Schema({
|
||||||
vol.Required('domain'): str,
|
vol.Required('domain'): str,
|
||||||
vol.Required('name'): str,
|
vol.Required('name'): str,
|
||||||
|
vol.Optional('config_flow'): bool,
|
||||||
vol.Required('documentation'): str,
|
vol.Required('documentation'): str,
|
||||||
vol.Required('requirements'): [str],
|
vol.Required('requirements'): [str],
|
||||||
vol.Required('dependencies'): [str],
|
vol.Required('dependencies'): [str],
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import json
|
import json
|
||||||
from typing import List, Dict, Any
|
from typing import List, Dict, Any
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import importlib
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
|
@ -92,3 +93,10 @@ class Integration:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.manifest = manifest
|
self.manifest = manifest
|
||||||
|
|
||||||
|
def import_pkg(self, platform=None):
|
||||||
|
"""Import the Python file."""
|
||||||
|
pkg = "homeassistant.components.{}".format(self.domain)
|
||||||
|
if platform is not None:
|
||||||
|
pkg += ".{}".format(platform)
|
||||||
|
return importlib.import_module(pkg)
|
||||||
|
|
|
@ -926,7 +926,7 @@ async def get_system_health_info(hass, domain):
|
||||||
def mock_integration(hass, module):
|
def mock_integration(hass, module):
|
||||||
"""Mock an integration."""
|
"""Mock an integration."""
|
||||||
integration = loader.Integration(
|
integration = loader.Integration(
|
||||||
hass, 'homeassisant.components.{}'.format(module.DOMAIN), None,
|
hass, 'homeassistant.components.{}'.format(module.DOMAIN), None,
|
||||||
module.mock_manifest())
|
module.mock_manifest())
|
||||||
|
|
||||||
_LOGGER.info("Adding mock integration: %s", module.DOMAIN)
|
_LOGGER.info("Adding mock integration: %s", module.DOMAIN)
|
||||||
|
|
|
@ -12,9 +12,11 @@ from homeassistant.config_entries import HANDLERS
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.components.config import config_entries
|
from homeassistant.components.config import config_entries
|
||||||
|
from homeassistant.generated import config_flows
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
MockConfigEntry, MockModule, mock_coro_func, mock_integration)
|
MockConfigEntry, MockModule, mock_coro_func, mock_integration,
|
||||||
|
mock_entity_platform)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
@ -121,7 +123,7 @@ async def test_remove_entry_unauth(hass, client, hass_admin_user):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_available_flows(hass, client):
|
def test_available_flows(hass, client):
|
||||||
"""Test querying the available flows."""
|
"""Test querying the available flows."""
|
||||||
with patch.object(core_ce, 'FLOWS', ['hello', 'world']):
|
with patch.object(config_flows, 'FLOWS', ['hello', 'world']):
|
||||||
resp = yield from client.get(
|
resp = yield from client.get(
|
||||||
'/api/config/config_entries/flow_handlers')
|
'/api/config/config_entries/flow_handlers')
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
@ -137,6 +139,8 @@ def test_available_flows(hass, client):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_initialize_flow(hass, client):
|
def test_initialize_flow(hass, client):
|
||||||
"""Test we can initialize a flow."""
|
"""Test we can initialize a flow."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_step_user(self, user_input=None):
|
def async_step_user(self, user_input=None):
|
||||||
|
@ -221,6 +225,8 @@ async def test_initialize_flow_unauth(hass, client, hass_admin_user):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_abort(hass, client):
|
def test_abort(hass, client):
|
||||||
"""Test a flow that aborts."""
|
"""Test a flow that aborts."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_step_user(self, user_input=None):
|
def async_step_user(self, user_input=None):
|
||||||
|
@ -244,6 +250,8 @@ def test_abort(hass, client):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_create_account(hass, client):
|
def test_create_account(hass, client):
|
||||||
"""Test a flow that creates an account."""
|
"""Test a flow that creates an account."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
mock_integration(
|
mock_integration(
|
||||||
hass,
|
hass,
|
||||||
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
||||||
|
@ -286,6 +294,7 @@ def test_two_step_flow(hass, client):
|
||||||
mock_integration(
|
mock_integration(
|
||||||
hass,
|
hass,
|
||||||
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
@ -352,6 +361,7 @@ async def test_continue_flow_unauth(hass, client, hass_admin_user):
|
||||||
mock_integration(
|
mock_integration(
|
||||||
hass,
|
hass,
|
||||||
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
MockModule('test', async_setup_entry=mock_coro_func(True)))
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
@ -402,6 +412,8 @@ async def test_continue_flow_unauth(hass, client, hass_admin_user):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_get_progress_index(hass, client):
|
def test_get_progress_index(hass, client):
|
||||||
"""Test querying for the flows that are in progress."""
|
"""Test querying for the flows that are in progress."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
VERSION = 5
|
VERSION = 5
|
||||||
|
|
||||||
|
@ -441,6 +453,8 @@ async def test_get_progress_index_unauth(hass, client, hass_admin_user):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_get_progress_flow(hass, client):
|
def test_get_progress_flow(hass, client):
|
||||||
"""Test we can query the API for same result as we get from init a flow."""
|
"""Test we can query the API for same result as we get from init a flow."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_step_user(self, user_input=None):
|
def async_step_user(self, user_input=None):
|
||||||
|
@ -474,6 +488,8 @@ def test_get_progress_flow(hass, client):
|
||||||
|
|
||||||
async def test_get_progress_flow_unauth(hass, client, hass_admin_user):
|
async def test_get_progress_flow_unauth(hass, client, hass_admin_user):
|
||||||
"""Test we can can't query the API for result of flow."""
|
"""Test we can can't query the API for result of flow."""
|
||||||
|
mock_entity_platform(hass, 'config_flow.test', None)
|
||||||
|
|
||||||
class TestFlow(core_ce.ConfigFlow):
|
class TestFlow(core_ce.ConfigFlow):
|
||||||
async def async_step_user(self, user_input=None):
|
async def async_step_user(self, user_input=None):
|
||||||
schema = OrderedDict()
|
schema = OrderedDict()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue