async def test_warning_deprecated_connection_class(hass, caplog): """Test that we log a warning when the connection_class is used.""" discovery_function = Mock() with patch.dict(config_entries.HANDLERS): config_entry_flow.register_discovery_flow( "test", "Test", discovery_function, connection_class="local_polling") assert "integration is setting a connection_class" in caplog.text
def discovery_flow_conf(hass): """Register a handler.""" handler_conf = {"discovered": False} async def has_discovered_devices(hass): """Mock if we have discovered devices.""" return handler_conf["discovered"] with patch.dict(config_entries.HANDLERS): config_entry_flow.register_discovery_flow("test", "Test", has_discovered_devices) yield handler_conf
def flow_conf(hass): """Register a handler.""" handler_conf = { 'discovered': False, } async def has_discovered_devices(hass): """Mock if we have discovered devices.""" return handler_conf['discovered'] with patch.dict(config_entries.HANDLERS): config_entry_flow.register_discovery_flow( 'test', 'Test', has_discovered_devices) yield handler_conf
def flow_conf(hass): """Register a handler.""" handler_conf = { 'discovered': False, } async def has_discovered_devices(hass): """Mock if we have discovered devices.""" return handler_conf['discovered'] with patch.dict(config_entries.HANDLERS): config_entry_flow.register_discovery_flow( 'test', 'Test', has_discovered_devices) yield handler_conf
_LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, delete_port_mapping) return True async def async_unload_entry(hass: HomeAssistantType, config_entry: ConfigEntry): """Unload a UPnP/IGD device from a config entry.""" udn = config_entry.data['udn'] device = hass.data[DOMAIN]['devices'][udn] # remove port mapping _LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() # remove sensors _LOGGER.debug('Deleting sensors') dispatcher.async_dispatcher_send(hass, SIGNAL_REMOVE_SENSOR, device) return True config_entry_flow.register_discovery_flow( DOMAIN, 'UPnP/IGD', Device.async_discover, config_entries.CONN_CLASS_LOCAL_POLL)
async def async_setup(hass, config): """Set up the Sonos component.""" conf = config.get(DOMAIN) hass.data[DOMAIN] = conf or {} if conf is not None: hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True async def async_setup_entry(hass, entry): """Set up Sonos from a config entry.""" hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, 'media_player')) 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)
"""Config flow for HDHomeRun.""" from homeassistant.helpers import config_entry_flow from homeassistant import config_entries from hdhr.adapter import HdhrUtility from .const import DOMAIN async def _async_has_devices(hass): """Return if there are devices that can be discovered.""" hdhr_devices = HdhrUtility.discover_find_devices_custom() return len(hdhr_devices) > 0 config_entry_flow.register_discovery_flow(DOMAIN, 'HDHomeRun', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)
"""Config flow for iOS.""" from homeassistant.helpers import config_entry_flow from .const import DOMAIN config_entry_flow.register_discovery_flow(DOMAIN, "Home Assistant iOS", lambda *_: True)
"""Config flow for TP-Link.""" from homeassistant.helpers import config_entry_flow from .common import async_get_discoverable_devices from .const import DOMAIN config_entry_flow.register_discovery_flow( DOMAIN, "TP-Link Smart Home", async_get_discoverable_devices, )
"""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)
async def async_setup(hass, config): """Set up the LIFX component.""" conf = config.get(DOMAIN) hass.data[DOMAIN] = conf or {} if conf is not None: hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True async def async_setup_entry(hass, entry): """Set up LIFX from a config entry.""" hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, LIGHT_DOMAIN)) 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)
"""Config flow for SpaceX Launches and Starman.""" from spacexpypi import SpaceX from homeassistant import config_entries from homeassistant.helpers import config_entry_flow from .const import DOMAIN async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" api_client = SpaceX() devices = await api_client.get_next_launch() return len(devices) > 0 config_entry_flow.register_discovery_flow( DOMAIN, "SpaceX Launches and Starman", _async_has_devices, config_entries.CONN_CLASS_UNKNOWN, )
"""Config flow for UPnP Availability.""" import logging from homeassistant.helpers import config_entry_flow from .const import DOMAIN _LOGGER = logging.getLogger(__name__) async def _async_has_devices(hass) -> bool: """There are always devices to be discovered.""" return True config_entry_flow.register_discovery_flow(DOMAIN, "UPnP Availability", _async_has_devices)
hass.async_add_job( hass.config_entries.async_forward_entry_setup( entry, 'climate')) return True async def async_unload_entry(hass, entry): """Unload the config entry and stop discovery process.""" await async_stop_discovery_service(hass) return True async def _async_has_devices(hass): disco = await async_start_discovery_service(hass) try: async with timeout(5): await disco.controller_ready.wait() except TimeoutError: pass _LOGGER.debug("Controllers %s", disco.controllers) return len(disco.controllers) > 0 config_entry_flow.register_discovery_flow( DOMAIN, 'iZone Aircon', _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH)
async def test_get_entries(hass, client, clear_handlers): """Test get entries.""" mock_integration(hass, MockModule("comp1")) mock_integration( hass, MockModule("comp2", partial_manifest={"integration_type": "helper"})) mock_integration(hass, MockModule("comp3")) @HANDLERS.register("comp1") class Comp1ConfigFlow: """Config flow with options flow.""" @staticmethod @callback def async_get_options_flow(config_entry): """Get options flow.""" pass @classmethod @callback def async_supports_options_flow(cls, config_entry): """Return options flow support for this handler.""" return True config_entry_flow.register_discovery_flow("comp2", "Comp 2", lambda: None) entry = MockConfigEntry( domain="comp1", title="Test 1", source="bla", ) entry.supports_unload = True entry.add_to_hass(hass) MockConfigEntry( domain="comp2", title="Test 2", source="bla2", state=core_ce.ConfigEntryState.SETUP_ERROR, reason="Unsupported API", ).add_to_hass(hass) MockConfigEntry( domain="comp3", title="Test 3", source="bla3", disabled_by=core_ce.ConfigEntryDisabler.USER, ).add_to_hass(hass) resp = await client.get("/api/config/config_entries/entry") assert resp.status == HTTPStatus.OK data = await resp.json() for entry in data: entry.pop("entry_id") assert data == [ { "domain": "comp1", "title": "Test 1", "source": "bla", "state": core_ce.ConfigEntryState.NOT_LOADED.value, "supports_options": True, "supports_remove_device": False, "supports_unload": True, "pref_disable_new_entities": False, "pref_disable_polling": False, "disabled_by": None, "reason": None, }, { "domain": "comp2", "title": "Test 2", "source": "bla2", "state": core_ce.ConfigEntryState.SETUP_ERROR.value, "supports_options": False, "supports_remove_device": False, "supports_unload": False, "pref_disable_new_entities": False, "pref_disable_polling": False, "disabled_by": None, "reason": "Unsupported API", }, { "domain": "comp3", "title": "Test 3", "source": "bla3", "state": core_ce.ConfigEntryState.NOT_LOADED.value, "supports_options": False, "supports_remove_device": False, "supports_unload": False, "pref_disable_new_entities": False, "pref_disable_polling": False, "disabled_by": core_ce.ConfigEntryDisabler.USER, "reason": None, }, ] resp = await client.get("/api/config/config_entries/entry?domain=comp3") assert resp.status == HTTPStatus.OK data = await resp.json() assert len(data) == 1 assert data[0]["domain"] == "comp3" resp = await client.get( "/api/config/config_entries/entry?domain=comp3&type=helper") assert resp.status == HTTPStatus.OK data = await resp.json() assert len(data) == 0 resp = await client.get( "/api/config/config_entries/entry?domain=comp3&type=integration") assert resp.status == HTTPStatus.OK data = await resp.json() assert len(data) == 1 resp = await client.get("/api/config/config_entries/entry?type=integration" ) assert resp.status == HTTPStatus.OK data = await resp.json() assert len(data) == 2 assert data[0]["domain"] == "comp1" assert data[1]["domain"] == "comp3"
"""Config flow for Kuler Sky.""" import logging import pykulersky from homeassistant.helpers import config_entry_flow from .const import DOMAIN _LOGGER = logging.getLogger(__name__) async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" # Check if there are any devices that can be discovered in the network. try: devices = await pykulersky.discover() except pykulersky.PykulerskyException as exc: _LOGGER.error("Unable to discover nearby Kuler Sky devices: %s", exc) return False return len(devices) > 0 config_entry_flow.register_discovery_flow(DOMAIN, "Kuler Sky", _async_has_devices)
"""Config flow for iOS.""" from homeassistant.helpers import config_entry_flow from .const import DOMAIN config_entry_flow.register_discovery_flow(DOMAIN, "Safegate Pro iOS", lambda *_: True)
_LOGGER.debug("Got %s climates: %s", len(climates), climates) hass.async_create_task(forward_setup(config_entry, 'climate')) async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Unload a config entry.""" forward_unload = hass.config_entries.async_forward_entry_unload remove_lights = remove_switches = False if hass.data[DOMAIN][CONF_LIGHTS]: remove_lights = await forward_unload(entry, 'light') if hass.data[DOMAIN][CONF_SENSORS]: remove_sensors = await forward_unload(entry, 'sensor') if hass.data[DOMAIN][CONF_SWITCHES]: remove_switches = await forward_unload(entry, 'switch') if hass.data[DOMAIN][CONF_CLIMATES]: remove_climates = await forward_unload(entry, 'climate') if remove_lights or remove_sensors or remove_switches or remove_climates: hass.data[DOMAIN].clear() return True # We were not able to unload the platforms, either because there # were none or one of the forward_unloads failed. return False config_entry_flow.register_discovery_flow( DOMAIN, 'Aqualink', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL) # Not really.
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) hass = request.app['hass'] # Commented for now while iOS app is getting frequent updates # try: # data = IDENTIFY_SCHEMA(req_data) # except vol.Invalid as ex: # return self.json_message( # vol.humanize.humanize_error(request.json, ex), # HTTP_BAD_REQUEST) data[ATTR_LAST_SEEN_AT] = datetime.datetime.now().isoformat() name = data.get(ATTR_DEVICE_ID) hass.data[DOMAIN][ATTR_DEVICES][name] = data try: save_json(self._config_path, hass.data[DOMAIN]) except HomeAssistantError: return self.json_message("Error saving device.", HTTP_INTERNAL_SERVER_ERROR) return self.json({"status": "registered"}) config_entry_flow.register_discovery_flow( DOMAIN, 'Home Assistant iOS', lambda *_: True, config_entries.CONN_CLASS_CLOUD_PUSH)
"""Component to embed Google Cast.""" from homeassistant.helpers import config_entry_flow DOMAIN = 'cast' REQUIREMENTS = ['pychromecast==2.1.0'] async def async_setup(hass, config): """Set up the Cast component.""" hass.data[DOMAIN] = config.get(DOMAIN, {}) return True async def async_setup_entry(hass, entry): """Set up Cast from a config entry.""" hass.async_add_job(hass.config_entries.async_forward_entry_setup( entry, 'media_player')) 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_job(discover_chromecasts) config_entry_flow.register_discovery_flow( DOMAIN, 'Google Cast', _async_has_devices)
"""Config flow for Gree.""" from greeclimate.discovery import Discovery from homeassistant.components.network import async_get_ipv4_broadcast_addresses from homeassistant.core import HomeAssistant from homeassistant.helpers import config_entry_flow from .const import DISCOVERY_TIMEOUT, DOMAIN async def _async_has_devices(hass: HomeAssistant) -> bool: """Return if there are devices that can be discovered.""" gree_discovery = Discovery(DISCOVERY_TIMEOUT) bcast_addr = list(await async_get_ipv4_broadcast_addresses(hass)) devices = await gree_discovery.scan(wait_for=DISCOVERY_TIMEOUT, bcast_ifaces=bcast_addr) return len(devices) > 0 config_entry_flow.register_discovery_flow(DOMAIN, "Gree Climate", _async_has_devices)
async def delete_port_mapping(event): """Delete port mapping on quit.""" _LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, delete_port_mapping) return True async def async_unload_entry(hass: HomeAssistantType, config_entry: ConfigEntry): """Unload a UPnP/IGD device from a config entry.""" udn = config_entry.data['udn'] device = hass.data[DOMAIN]['devices'][udn] # remove port mapping _LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() # remove sensors _LOGGER.debug('Deleting sensors') dispatcher.async_dispatcher_send(hass, SIGNAL_REMOVE_SENSOR, device) return True config_entry_flow.register_discovery_flow(DOMAIN, 'UPnP/IGD', Device.async_discover, config_entries.CONN_CLASS_LOCAL_POLL)
async def _async_has_devices(hass): controller_ready = asyncio.Event() @callback def dispatch_discovered(_): controller_ready.set() async_dispatcher_connect(hass, DISPATCH_CONTROLLER_DISCOVERED, dispatch_discovered) disco = await async_start_discovery_service(hass) with suppress(asyncio.TimeoutError): async with timeout(TIMEOUT_DISCOVERY): await controller_ready.wait() if not disco.pi_disco.controllers: await async_stop_discovery_service(hass) _LOGGER.debug("No controllers found") return False _LOGGER.debug("Controllers %s", disco.pi_disco.controllers) return True config_entry_flow.register_discovery_flow(IZONE, "iZone Aircon", _async_has_devices)
async def async_setup(hass, config): """Set up the Cast component.""" conf = config.get(DOMAIN) hass.data[DOMAIN] = conf or {} if conf is not None: hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True async def async_setup_entry(hass, entry): """Set up Cast from a config entry.""" hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, 'media_player')) 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)
"""Config flow for Zerproc.""" import logging import pyzerproc from homeassistant.core import HomeAssistant from homeassistant.helpers import config_entry_flow from .const import DOMAIN _LOGGER = logging.getLogger(__name__) async def _async_has_devices(hass: HomeAssistant) -> bool: """Return if there are devices that can be discovered.""" try: devices = await pyzerproc.discover() return len(devices) > 0 except pyzerproc.ZerprocException: _LOGGER.error("Unable to discover nearby Zerproc devices", exc_info=True) return False config_entry_flow.register_discovery_flow(DOMAIN, "Zerproc", _async_has_devices)
"""Config flow for Kuler Sky.""" import logging import pykulersky from homeassistant import config_entries from homeassistant.helpers import config_entry_flow from .const import DOMAIN _LOGGER = logging.getLogger(__name__) async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" # Check if there are any devices that can be discovered in the network. try: devices = await pykulersky.discover() except pykulersky.PykulerskyException as exc: _LOGGER.error("Unable to discover nearby Kuler Sky devices: %s", exc) return False return len(devices) > 0 config_entry_flow.register_discovery_flow(DOMAIN, "Kuler Sky", _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)
async def async_setup(hass, config): """Set up the Sonos component.""" conf = config.get(DOMAIN) hass.data[DOMAIN] = conf or {} if conf is not None: hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, source=data_entry_flow.SOURCE_IMPORT)) return True async def async_setup_entry(hass, entry): """Set up Sonos from a config entry.""" hass.async_add_job(hass.config_entries.async_forward_entry_setup( entry, 'media_player')) return True async def _async_has_devices(hass): """Return if there are devices that can be discovered.""" import soco return await hass.async_add_job(soco.discover) config_entry_flow.register_discovery_flow(DOMAIN, 'Sonos', _async_has_devices)
def zeroconf_Info2Values(info: ServiceInfo): res = {} res['port'] = info.port res['server'] = info.server for key, value in info.properties.items(): res[key.decode("utf-8")] = value.decode("utf-8") return res async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" # check if the api is reachable zeroconf = await async_get_instance(hass) tmp = zeroconf.get_service_info(ZCNF_TYPE, ZCNF_NAME + '.' + ZCNF_TYPE) val_dict = zeroconf_Info2Values(tmp) act_assist = ActAssist(aiohttp_client.async_get_clientsession(hass), val_dict[KEY_HOSTNAME], val_dict['port'], val_dict[KEY_WEBHOOK]) try: status = await act_assist.call_webhook() _LOGGER.warning('Webhook returned: ' + str(status)) return status == 200 except aiohttp.ClientError: _LOGGER.warning('No ') return False config_entry_flow.register_discovery_flow(DOMAIN, "Activity Assistant", _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH)
"""Config flow for Hisense AEH-W4A1 integration.""" from pyaehw4a1.aehw4a1 import AehW4a1 from homeassistant.helpers import config_entry_flow from .const import DOMAIN async def _async_has_devices(hass): """Return if there are devices that can be discovered.""" aehw4a1_ip_addresses = await AehW4a1().discovery() return len(aehw4a1_ip_addresses) > 0 config_entry_flow.register_discovery_flow(DOMAIN, "Hisense AEH-W4A1", _async_has_devices)
"""Config flow for NEW_NAME.""" import my_pypi_dependency from homeassistant.helpers import config_entry_flow from homeassistant import config_entries from .const import DOMAIN async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" # TODO Check if there are any devices that can be discovered in the network. devices = await hass.async_add_executor_job(my_pypi_dependency.discover) return len(devices) > 0 config_entry_flow.register_discovery_flow(DOMAIN, "NEW_NAME", _async_has_devices, config_entries.CONN_CLASS_UNKNOWN)
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) hass = request.app['hass'] # Commented for now while iOS app is getting frequent updates # try: # data = IDENTIFY_SCHEMA(req_data) # except vol.Invalid as ex: # return self.json_message( # vol.humanize.humanize_error(request.json, ex), # HTTP_BAD_REQUEST) data[ATTR_LAST_SEEN_AT] = datetime.datetime.now().isoformat() name = data.get(ATTR_DEVICE_ID) hass.data[DOMAIN][ATTR_DEVICES][name] = data try: save_json(self._config_path, hass.data[DOMAIN]) except HomeAssistantError: return self.json_message("Error saving device.", HTTP_INTERNAL_SERVER_ERROR) return self.json({"status": "registered"}) config_entry_flow.register_discovery_flow(DOMAIN, 'Home Assistant iOS', lambda *_: True, config_entries.CONN_CLASS_CLOUD_PUSH)
from bleak.backends.scanner import AdvertisementData from fjaraskupan import device_filter from homeassistant.helpers.config_entry_flow import register_discovery_flow from .const import DOMAIN CONST_WAIT_TIME = 5.0 async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" event = asyncio.Event() def detection(device: BLEDevice, advertisement_data: AdvertisementData): if device_filter(device, advertisement_data): event.set() async with BleakScanner(detection_callback=detection): try: async with async_timeout.timeout(CONST_WAIT_TIME): await event.wait() except asyncio.TimeoutError: return False return True register_discovery_flow(DOMAIN, "Fjäråskupan", _async_has_devices)
async def async_setup(hass, config): """Set up the Cast component.""" conf = config.get(DOMAIN) hass.data[DOMAIN] = conf or {} if conf is not None: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True async def async_setup_entry(hass, entry): """Set up Cast from a config entry.""" hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, 'media_player')) 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)
async def _async_has_devices(hass): controller_ready = asyncio.Event() @callback def dispatch_discovered(_): controller_ready.set() async_dispatcher_connect(hass, DISPATCH_CONTROLLER_DISCOVERED, dispatch_discovered) disco = await async_start_discovery_service(hass) try: async with timeout(TIMEOUT_DISCOVERY): await controller_ready.wait() except asyncio.TimeoutError: pass if not disco.pi_disco.controllers: await async_stop_discovery_service(hass) _LOGGER.debug("No controllers found") return False _LOGGER.debug("Controllers %s", disco.pi_disco.controllers) return True config_entry_flow.register_discovery_flow( IZONE, "iZone Aircon", _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL )
"""Config flow for LinkPlay.""" import upnpclient import netdisco.ssdp from homeassistant import config_entries from homeassistant.helpers import config_entry_flow from . import DOMAIN async def _async_has_devices(hass): """Return if there are devices that can be discovered.""" return await hass.async_add_executor_job(upnp_discover) config_entry_flow.register_discovery_flow(DOMAIN, "LinkPlay", _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH) def upnp_discover(timeout=5): devices = {} for entry in netdisco.ssdp.scan(timeout): if entry.location in devices: continue try: devices[entry.location] = upnpclient.Device(entry.location) except Exception as exc: pass return list(devices.values())
from .const import (debug, DOMAIN) from homeassistant import config_entries from homeassistant.helpers import config_entry_flow async def _async_has_devices(hass): """Return if there are devices that can be discovered.""" return True config_entry_flow.register_discovery_flow(DOMAIN, "This is my integration title", _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)