def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable): """Helper method to connect scanner-based platform to device tracker. This method is a coroutine. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any @asyncio.coroutine def async_device_tracker_scan(now: dt_util.dt.datetime): """Called when interval matches.""" found_devices = yield from scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = yield from scanner.async_get_device_name(mac) seen.add(mac) hass.async_add_job(async_see_device(mac=mac, host_name=host_name)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan, None)
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable, platform: str): """Set up the connect scanner-based platform to device tracker. This method must be run in the event loop. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) update_lock = asyncio.Lock(loop=hass.loop) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any async def async_device_tracker_scan(now: dt_util.dt.datetime): """Handle interval matches.""" if update_lock.locked(): _LOGGER.warning( "Updating device list from %s took longer than the scheduled " "scan interval %s", platform, interval) return async with update_lock: found_devices = await scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = await scanner.async_get_device_name(mac) seen.add(mac) try: extra_attributes = (await scanner.async_get_extra_attributes(mac)) except NotImplementedError: extra_attributes = dict() kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER, 'attributes': { 'scanner': scanner.__class__.__name__, **extra_attributes } } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [ zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE] ] kwargs['gps_accuracy'] = 0 hass.async_add_job(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan(None))
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable): """Helper method to connect scanner-based platform to device tracker. This method is a coroutine. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) # Initial scan of each mac we also tell about host name for config seen = set() # type: Any def device_tracker_scan(now: dt_util.dt.datetime): """Called when interval matches.""" found_devices = scanner.scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = scanner.get_device_name(mac) seen.add(mac) hass.add_job(async_see_device(mac=mac, host_name=host_name)) async_track_utc_time_change( hass, device_tracker_scan, second=range(0, 60, interval)) hass.async_add_job(device_tracker_scan, None)
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Setup a VEN from a config flow entry""" config = hass.data[const.DOMAIN][const.DATA_CONFIG] from pyoadr_ven import OpenADRVenAgent ven_config = config.get(const.DOMAIN) oadr_agent = OpenADRVenAgent( ven_id=balena.get_device_uuid(), vtn_id=ven_config.get(const.VTN_ID), vtn_address=ven_config.get(const.VTN_ADDRESS), poll_interval_secs=ven_config.get(const.POLL_INTERVAL_SECS), log_xml=ven_config.get(const.LOG_XML), opt_timeout_secs=ven_config.get(const.OPT_TIMEOUT_SECS), opt_default_decision=ven_config.get(const.OPT_DEFAULT_DECISION), report_parameters=ven_config.get(const.REPORT_PARAMETERS), client_pem_bundle=ven_config.get(const.CLIENT_PEM_BUNDLE_FILEPATH), vtn_ca_cert=ven_config.get(const.CA_CERT_FILEPATH), db_filepath=ven_config.get(const.DB_FILEPATH), ) hass.data[const.DOMAIN][const.OADR_AGENT] = oadr_agent # Register services defined in services.py await services.async_setup_services(hass) hass.async_add_job( hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) # Return boolean to indicate that initialization was successful. _LOGGER.info("PowerShaper entry setup complete") return True
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_devices, discovery_info=None): """Set up the cast platform.""" import pychromecast # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {}) hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {}) # None -> use discovery; (host, port) -> manually specify chromecast. want_host = None if discovery_info: want_host = (discovery_info.get('host'), discovery_info.get('port')) elif CONF_HOST in config: want_host = (config.get(CONF_HOST), DEFAULT_PORT) enable_discovery = False if want_host is None: # We were explicitly told to enable pychromecast discovery. enable_discovery = True elif want_host[1] != DEFAULT_PORT: # We're trying to add a group, so we have to use pychromecast's # discovery to get the correct friendly name. enable_discovery = True if enable_discovery: @callback def async_cast_discovered(chromecast): """Callback for when a new chromecast is discovered.""" if want_host is not None and \ (chromecast.host, chromecast.port) != want_host: return # for groups, only add requested device cast_device = _async_create_cast_device(hass, chromecast) if cast_device is not None: async_add_devices([cast_device]) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()): async_cast_discovered(chromecast) hass.async_add_job(_setup_internal_discovery, hass) else: # Manually add a "normal" Chromecast, we can do that without discovery. try: chromecast = await hass.async_add_job( pychromecast.Chromecast, *want_host) except pychromecast.ChromecastConnectionError as err: _LOGGER.warning("Can't set up chromecast on %s: %s", want_host[0], err) raise PlatformNotReady key = (chromecast.host, chromecast.port, chromecast.uuid) cast_device = _async_create_cast_device(hass, chromecast) if cast_device is not None: hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast async_add_devices([cast_device])
async def _handle_entity_call( hass: HomeAssistantType, entity: "Entity", func: Union[str, Callable[..., Any]], data: Union[Dict, ha.ServiceCall], context: ha.Context, ) -> None: """Handle calling service method.""" entity.async_set_context(context) if isinstance(func, str): result = hass.async_add_job(partial(getattr(entity, func), **data)) # type: ignore else: result = hass.async_add_job(func, entity, data) # Guard because callback functions do not return a task when passed to async_add_job. if result is not None: await result if asyncio.iscoroutine(result): _LOGGER.error( "Service %s for %s incorrectly returns a coroutine object. Await result instead in service handler. Report bug to integration author", func, entity.entity_id, ) await result # type: ignore
def async_see( hass: HomeAssistantType, mac: str = None, dev_id: str = None, host_name: str = None, location_name: str = None, gps: GPSType = None, gps_accuracy=None, battery: int = None, attributes: dict = None, ): """Call service to notify you see device.""" data = { key: value for key, value in ( (ATTR_MAC, mac), (ATTR_DEV_ID, dev_id), (ATTR_HOST_NAME, host_name), (ATTR_LOCATION_NAME, location_name), (ATTR_GPS, gps), (ATTR_GPS_ACCURACY, gps_accuracy), (ATTR_BATTERY, battery), ) if value is not None } if attributes: data[ATTR_ATTRIBUTES] = attributes hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SEE, data))
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable, platform: str): """Set up the connect scanner-based platform to device tracker. This method must be run in the event loop. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) update_lock = asyncio.Lock(loop=hass.loop) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any @asyncio.coroutine def async_device_tracker_scan(now: dt_util.dt.datetime): """Handle interval matches.""" if update_lock.locked(): _LOGGER.warning( "Updating device list from %s took longer than the scheduled " "scan interval %s", platform, interval) return with (yield from update_lock): found_devices = yield from scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = yield from scanner.async_get_device_name(mac) seen.add(mac) try: extra_attributes = (yield from scanner.async_get_extra_attributes(mac)) except NotImplementedError: extra_attributes = dict() kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER, 'attributes': { 'scanner': scanner.__class__.__name__, **extra_attributes } } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE]] kwargs['gps_accuracy'] = 0 hass.async_add_job(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan(None))
def async_publish(hass: HomeAssistantType, topic: Any, payload, qos=None, retain=None) -> None: """Publish message to an MQTT topic.""" data = _build_publish_data(topic, qos, retain) data[ATTR_PAYLOAD] = payload hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_PUBLISH, data))
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Setup UK carbon intensity integration from a config flow entry""" hass.async_add_job( hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) # Return boolean to indicate that initialization was successful. _LOGGER.debug("UK carbon intensity integration entry setup complete") return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Register the iZone component config.""" conf = config.get(DOMAIN) if not conf: return True hass.data[DATA_CONFIG] = conf # Explicitly added in the config file, create a config entry. hass.async_add_job(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable, platform: str): """Helper method to connect scanner-based platform to device tracker. This method must be run in the event loop. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) update_lock = asyncio.Lock(loop=hass.loop) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any @asyncio.coroutine def async_device_tracker_scan(now: dt_util.dt.datetime): """Called when interval matches.""" if update_lock.locked(): _LOGGER.warning( "Updating device list from %s took longer than the scheduled " "scan interval %s", platform, interval) return with (yield from update_lock): found_devices = yield from scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = yield from scanner.async_get_device_name(mac) seen.add(mac) kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [ zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE] ] kwargs['gps_accuracy'] = 0 hass.async_add_job(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan(None))
async def async_setup(hass: HomeAssistantType, config: Dict) -> bool: """Set up the switcher component.""" from aioswitcher.bridge import SwitcherV2Bridge phone_id = config[DOMAIN][CONF_PHONE_ID] device_id = config[DOMAIN][CONF_DEVICE_ID] device_password = config[DOMAIN][CONF_DEVICE_PASSWORD] v2bridge = SwitcherV2Bridge(hass.loop, phone_id, device_id, device_password) await v2bridge.start() async def async_stop_bridge(event: EventType) -> None: """On homeassistant stop, gracefully stop the bridge if running.""" await v2bridge.stop() hass.async_add_job( hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_bridge)) try: device_data = await wait_for(v2bridge.queue.get(), timeout=5.0, loop=hass.loop) except (Asyncio_TimeoutError, RuntimeError): _LOGGER.exception("failed to get response from device") await v2bridge.stop() return False hass.data[DOMAIN] = {DATA_DEVICE: device_data} hass.async_create_task( async_load_platform(hass, SWITCH_DOMAIN, DOMAIN, None, config)) @callback def device_updates(timestamp: Optional[datetime]) -> None: """Use for updating the device data from the queue.""" if v2bridge.running: try: device_new_data = v2bridge.queue.get_nowait() if device_new_data: async_dispatcher_send(hass, SIGNAL_SWITCHER_DEVICE_UPDATE, device_new_data) except QueueEmpty: pass async_track_time_interval(hass, device_updates, timedelta(seconds=4)) return True
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info): """Set up the cast platform.""" import pychromecast # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set()) info = None if discovery_info is not None: info = ChromecastInfo(host=discovery_info['host'], port=discovery_info['port']) elif CONF_HOST in config: info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT) @callback def async_cast_discovered(discover: ChromecastInfo) -> None: """Handle discovery of a new chromecast.""" if info is not None and info.host_port != discover.host_port: # Not our requested cast device. return cast_device = _async_create_cast_device(hass, discover) if cast_device is not None: async_add_entities([cast_device]) remove_handler = async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): async_cast_discovered(chromecast) if info is None or info.is_audio_group: # If we were a) explicitly told to enable discovery or # b) have an audio group cast device, we need internal discovery. hass.async_add_job(_setup_internal_discovery, hass) else: info = await hass.async_add_job(_fill_out_missing_chromecast_info, info) if info.friendly_name is None: _LOGGER.debug( "Cannot retrieve detail information for chromecast" " %s, the device may not be online", info) remove_handler() raise PlatformNotReady hass.async_add_job(_discover_chromecast, hass, info)
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info): """Set up the cast platform.""" import pychromecast # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set()) info = None if discovery_info is not None: info = ChromecastInfo(host=discovery_info['host'], port=discovery_info['port']) elif CONF_HOST in config: info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT) @callback def async_cast_discovered(discover: ChromecastInfo) -> None: """Handle discovery of a new chromecast.""" if info is not None and info.host_port != discover.host_port: # Not our requested cast device. return cast_device = _async_create_cast_device(hass, discover) if cast_device is not None: async_add_entities([cast_device]) remove_handler = async_dispatcher_connect( hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): async_cast_discovered(chromecast) if info is None or info.is_audio_group: # If we were a) explicitly told to enable discovery or # b) have an audio group cast device, we need internal discovery. hass.async_add_job(_setup_internal_discovery, hass) else: info = await hass.async_add_job(_fill_out_missing_chromecast_info, info) if info.friendly_name is None: _LOGGER.debug("Cannot retrieve detail information for chromecast" " %s, the device may not be online", info) remove_handler() raise PlatformNotReady hass.async_add_job(_discover_chromecast, hass, info)
def async_see(hass: HomeAssistantType, mac: str = None, dev_id: str = None, host_name: str = None, location_name: str = None, gps: GPSType = None, gps_accuracy=None, battery: int = None, attributes: dict = None): """Call service to notify you see device.""" data = {key: value for key, value in ((ATTR_MAC, mac), (ATTR_DEV_ID, dev_id), (ATTR_HOST_NAME, host_name), (ATTR_LOCATION_NAME, location_name), (ATTR_GPS, gps), (ATTR_GPS_ACCURACY, gps_accuracy), (ATTR_BATTERY, battery)) if value is not None} if attributes: data[ATTR_ATTRIBUTES] = attributes hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SEE, data))
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the Azure Event Grid platform.""" try: LOGGER.debug("async_setup") topics = config.get(DOMAIN) all_event_grids = {} LOGGER.debug("adding sensors") hass.async_add_job( discovery.async_load_platform(hass, 'sensor', DOMAIN, {}, config)) @asyncio.coroutine def async_handle_event_grid_service(service_call): """Handle calls to event grid services.""" topic_name = service_call.data[CONF_NAME] eventGrid = all_event_grids[topic_name] if service_call.service == SERVICE_AZURE_EVENT_GRID__PUBLISH_MESSAGE: eventGrid.event_grid_publish_message(service_call) for i in topics.items(): LOGGER.debug(i) name = i[0] host = i[1][CONF_HOST] key = i[1][CONF_TOPIC_KEY] LOGGER.debug(f"setting up topic: {name}") if host and key: LOGGER.debug(f'with host: {host}') eventGrid = AzureEventGrid(hass, host, name, key) all_event_grids[name] = eventGrid elif host or key: LOGGER.error( f'Incorrect config, please supply either both Host and Topic Key or Monitored Variables. Supplied {i[1]}' ) hass.services.async_register(DOMAIN, SERVICE_AZURE_EVENT_GRID__PUBLISH_MESSAGE, async_handle_event_grid_service, schema=MQTT_PUBLISH_SCHEMA) except Exception as err: LOGGER.error("Error async_setup: %s", err) return True
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable): """Helper method to connect scanner-based platform to device tracker. This method is a coroutine. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any @asyncio.coroutine def async_device_tracker_scan(now: dt_util.dt.datetime): """Called when interval matches.""" found_devices = yield from scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = yield from scanner.async_get_device_name(mac) seen.add(mac) kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [ zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE] ] kwargs['gps_accuracy'] = 0 hass.async_add_job(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan, None)
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: try: api = await AirthingsAPI.login( entry.data[CONF_API_KEY], LoginDetails(entry.data[CONF_EMAIL], entry.data[CONF_PASSWORD]), ) except Exception: logger.exception("login failed") return False hass.data[DOMAIN][KEY_API] = api for platform in PLATFORMS: hass.async_add_job( hass.config_entries.async_forward_entry_setup, entry, platform ) logger.info("starting auto update") api.start_auto_update(timedelta(minutes=10)) return True
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable): """Helper method to connect scanner-based platform to device tracker. This method is a coroutine. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any @asyncio.coroutine def async_device_tracker_scan(now: dt_util.dt.datetime): """Called when interval matches.""" found_devices = yield from scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = yield from scanner.async_get_device_name(mac) seen.add(mac) kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE]] kwargs['gps_accuracy'] = 0 hass.async_add_job(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_add_job(async_device_tracker_scan, None)
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the HomematicIP Cloud component.""" hass.data[DOMAIN] = {} accesspoints = config.get(DOMAIN, []) for conf in accesspoints: if conf[CONF_ACCESSPOINT] not in set( entry.data[HMIPC_HAPID] for entry in hass.config_entries.async_entries(DOMAIN)): hass.async_add_job( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={ HMIPC_HAPID: conf[CONF_ACCESSPOINT], HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN], HMIPC_NAME: conf[CONF_NAME], }, )) return True
def async_load_config(path: str, hass: HomeAssistantType, consider_home: timedelta): """Load devices from YAML configuration file. This method is a coroutine. """ dev_schema = vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon), vol.Optional('track', default=False): cv.boolean, vol.Optional(CONF_MAC, default=None): vol.Any(None, vol.All(cv.string, vol.Upper)), vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, vol.Optional('gravatar', default=None): vol.Any(None, cv.string), vol.Optional('picture', default=None): vol.Any(None, cv.string), vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(cv.time_period, cv.positive_timedelta), }) try: result = [] try: devices = yield from hass.async_add_job(load_yaml_config_file, path) except HomeAssistantError as err: _LOGGER.error("Unable to load %s: %s", path, str(err)) return [] for dev_id, device in devices.items(): # Deprecated option. We just ignore it to avoid breaking change device.pop('vendor', None) try: device = dev_schema(device) device['dev_id'] = cv.slugify(dev_id) except vol.Invalid as exp: async_log_exception(exp, dev_id, devices, hass) else: result.append(Device(hass, **device)) return result except (HomeAssistantError, FileNotFoundError): # When YAML file could not be loaded/did not contain a dict return []
def async_load_config(path: str, hass: HomeAssistantType, consider_home: timedelta): """Load devices from YAML configuration file. This method is a coroutine. """ dev_schema = vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon), vol.Optional('track', default=False): cv.boolean, vol.Optional(CONF_MAC, default=None): vol.Any(None, vol.All(cv.string, vol.Upper)), vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, vol.Optional('gravatar', default=None): vol.Any(None, cv.string), vol.Optional('picture', default=None): vol.Any(None, cv.string), vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All( cv.time_period, cv.positive_timedelta), }) try: result = [] try: devices = yield from hass.async_add_job( load_yaml_config_file, path) except HomeAssistantError as err: _LOGGER.error("Unable to load %s: %s", path, str(err)) return [] for dev_id, device in devices.items(): # Deprecated option. We just ignore it to avoid breaking change device.pop('vendor', None) try: device = dev_schema(device) device['dev_id'] = cv.slugify(dev_id) except vol.Invalid as exp: async_log_exception(exp, dev_id, devices, hass) else: result.append(Device(hass, **device)) return result except (HomeAssistantError, FileNotFoundError): # When YAML file could not be loaded/did not contain a dict return []
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the HomematicIP Cloud component.""" hass.data[DOMAIN] = {} accesspoints = config.get(DOMAIN, []) for conf in accesspoints: if conf[CONF_ACCESSPOINT] not in set( entry.data[HMIPC_HAPID] for entry in hass.config_entries.async_entries(DOMAIN)): hass.async_add_job( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={ HMIPC_HAPID: conf[CONF_ACCESSPOINT], HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN], HMIPC_NAME: conf[CONF_NAME], }, )) async def _async_activate_eco_mode_with_duration(service) -> None: """Service to activate eco mode with duration.""" duration = service.data[ATTR_DURATION] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_absence_with_duration(duration) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_absence_with_duration(duration) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION, _async_activate_eco_mode_with_duration, schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION, ) async def _async_activate_eco_mode_with_period(service) -> None: """Service to activate eco mode with period.""" endtime = service.data[ATTR_ENDTIME] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_absence_with_period(endtime) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_absence_with_period(endtime) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD, _async_activate_eco_mode_with_period, schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD, ) async def _async_activate_vacation(service) -> None: """Service to activate vacation.""" endtime = service.data[ATTR_ENDTIME] temperature = service.data[ATTR_TEMPERATURE] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_vacation(endtime, temperature) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_vacation(endtime, temperature) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_VACATION, _async_activate_vacation, schema=SCHEMA_ACTIVATE_VACATION, ) async def _async_deactivate_eco_mode(service) -> None: """Service to deactivate eco mode.""" hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.deactivate_absence() else: for hap in hass.data[DOMAIN].values(): await hap.home.deactivate_absence() hass.services.async_register( DOMAIN, SERVICE_DEACTIVATE_ECO_MODE, _async_deactivate_eco_mode, schema=SCHEMA_DEACTIVATE_ECO_MODE, ) async def _async_deactivate_vacation(service) -> None: """Service to deactivate vacation.""" hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.deactivate_vacation() else: for hap in hass.data[DOMAIN].values(): await hap.home.deactivate_vacation() hass.services.async_register( DOMAIN, SERVICE_DEACTIVATE_VACATION, _async_deactivate_vacation, schema=SCHEMA_DEACTIVATE_VACATION, ) async def _set_active_climate_profile(service) -> None: """Service to set the active climate profile.""" entity_id_list = service.data[ATTR_ENTITY_ID] climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1 for hap in hass.data[DOMAIN].values(): if entity_id_list != "all": for entity_id in entity_id_list: group = hap.hmip_device_by_entity_id.get(entity_id) if group and isinstance(group, AsyncHeatingGroup): await group.set_active_profile(climate_profile_index) else: for group in hap.home.groups: if isinstance(group, AsyncHeatingGroup): await group.set_active_profile(climate_profile_index) hass.services.async_register( DOMAIN, SERVICE_SET_ACTIVE_CLIMATE_PROFILE, _set_active_climate_profile, schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE, ) async def _async_dump_hap_config(service) -> None: """Service to dump the configuration of a Homematic IP Access Point.""" config_path = (service.data.get(ATTR_CONFIG_OUTPUT_PATH) or hass.config.config_dir) config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX] anonymize = service.data[ATTR_ANONYMIZE] for hap in hass.data[DOMAIN].values(): hap_sgtin = hap.config_entry.unique_id if anonymize: hap_sgtin = hap_sgtin[-4:] file_name = f"{config_file_prefix}_{hap_sgtin}.json" path = Path(config_path) config_file = path / file_name json_state = await hap.home.download_configuration() json_state = handle_config(json_state, anonymize) config_file.write_text(json_state, encoding="utf8") hass.services.async_register( DOMAIN, SERVICE_DUMP_HAP_CONFIG, _async_dump_hap_config, schema=SCHEMA_DUMP_HAP_CONFIG, ) async def _async_reset_energy_counter(service): """Service to reset the energy counter.""" entity_id_list = service.data[ATTR_ENTITY_ID] for hap in hass.data[DOMAIN].values(): if entity_id_list != "all": for entity_id in entity_id_list: device = hap.hmip_device_by_entity_id.get(entity_id) if device and isinstance(device, AsyncSwitchMeasuring): await device.reset_energy_counter() else: for device in hap.home.devices: if isinstance(device, AsyncSwitchMeasuring): await device.reset_energy_counter() hass.helpers.service.async_register_admin_service( DOMAIN, SERVICE_RESET_ENERGY_COUNTER, _async_reset_energy_counter, schema=SCHEMA_RESET_ENERGY_COUNTER, ) def _get_home(hapid: str) -> Optional[AsyncHome]: """Return a HmIP home.""" hap = hass.data[DOMAIN].get(hapid) if hap: return hap.home _LOGGER.info("No matching access point found for access point id %s", hapid) return None return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the HomematicIP Cloud component.""" hass.data[DOMAIN] = {} accesspoints = config.get(DOMAIN, []) for conf in accesspoints: if conf[CONF_ACCESSPOINT] not in configured_haps(hass): hass.async_add_job( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={ HMIPC_HAPID: conf[CONF_ACCESSPOINT], HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN], HMIPC_NAME: conf[CONF_NAME], }, ) ) async def _async_activate_eco_mode_with_duration(service): """Service to activate eco mode with duration.""" duration = service.data[ATTR_DURATION] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_absence_with_duration(duration) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_absence_with_duration(duration) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION, _async_activate_eco_mode_with_duration, schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION, ) async def _async_activate_eco_mode_with_period(service): """Service to activate eco mode with period.""" endtime = service.data[ATTR_ENDTIME] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_absence_with_period(endtime) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_absence_with_period(endtime) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD, _async_activate_eco_mode_with_period, schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD, ) async def _async_activate_vacation(service): """Service to activate vacation.""" endtime = service.data[ATTR_ENDTIME] temperature = service.data[ATTR_TEMPERATURE] hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.activate_vacation(endtime, temperature) else: for hap in hass.data[DOMAIN].values(): await hap.home.activate_vacation(endtime, temperature) hass.services.async_register( DOMAIN, SERVICE_ACTIVATE_VACATION, _async_activate_vacation, schema=SCHEMA_ACTIVATE_VACATION, ) async def _async_deactivate_eco_mode(service): """Service to deactivate eco mode.""" hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.deactivate_absence() else: for hap in hass.data[DOMAIN].values(): await hap.home.deactivate_absence() hass.services.async_register( DOMAIN, SERVICE_DEACTIVATE_ECO_MODE, _async_deactivate_eco_mode, schema=SCHEMA_DEACTIVATE_ECO_MODE, ) async def _async_deactivate_vacation(service): """Service to deactivate vacation.""" hapid = service.data.get(ATTR_ACCESSPOINT_ID) if hapid: home = _get_home(hapid) if home: await home.deactivate_vacation() else: for hap in hass.data[DOMAIN].values(): await hap.home.deactivate_vacation() hass.services.async_register( DOMAIN, SERVICE_DEACTIVATE_VACATION, _async_deactivate_vacation, schema=SCHEMA_DEACTIVATE_VACATION, ) async def _set_active_climate_profile(service): """Service to set the active climate profile.""" entity_id_list = service.data[ATTR_ENTITY_ID] climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1 for hap in hass.data[DOMAIN].values(): if entity_id_list != "all": for entity_id in entity_id_list: group = hap.hmip_device_by_entity_id.get(entity_id) if group: await group.set_active_profile(climate_profile_index) else: for group in hap.home.groups: if isinstance(group, AsyncHeatingGroup): await group.set_active_profile(climate_profile_index) hass.services.async_register( DOMAIN, SERVICE_SET_ACTIVE_CLIMATE_PROFILE, _set_active_climate_profile, schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE, ) def _get_home(hapid: str): """Return a HmIP home.""" hap = hass.data[DOMAIN].get(hapid) if hap: return hap.home _LOGGER.info("No matching access point found for access point id %s", hapid) return None return True
def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, []) conf = conf[0] if conf else {} consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = yield from async_load_config(yaml_path, hass, consider_home) tracker = DeviceTracker(hass, consider_home, track_new, devices) @asyncio.coroutine def async_setup_platform(p_type, p_config, disc_info=None): """Set up a device tracker platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) try: scanner = None setup = None if hasattr(platform, 'async_get_scanner'): scanner = yield from platform.async_get_scanner( hass, {DOMAIN: p_config}) elif hasattr(platform, 'get_scanner'): scanner = yield from hass.async_add_job( platform.get_scanner, hass, {DOMAIN: p_config}) elif hasattr(platform, 'async_setup_scanner'): setup = yield from platform.async_setup_scanner( hass, p_config, tracker.async_see, disc_info) elif hasattr(platform, 'setup_scanner'): setup = yield from hass.async_add_job( platform.setup_scanner, hass, p_config, tracker.see, disc_info) else: raise HomeAssistantError("Invalid device_tracker platform.") if scanner: async_setup_scanner_platform( hass, p_config, scanner, tracker.async_see, p_type) return if not setup: _LOGGER.error("Error setting up platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform %s", p_type) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) tracker.async_setup_group() @callback def async_device_tracker_discovered(service, info): """Handle the discovery of device tracker platforms.""" hass.async_add_job( async_setup_platform(DISCOVERY_PLATFORMS[service], {}, info)) discovery.async_listen( hass, DISCOVERY_PLATFORMS.keys(), async_device_tracker_discovered) @asyncio.coroutine def async_platform_discovered(platform, info): """Load a platform.""" yield from async_setup_platform(platform, {}, disc_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) # Clean up stale devices async_track_utc_time_change( hass, tracker.async_update_stale, second=range(0, 60, 5)) @asyncio.coroutine def async_see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES)} yield from tracker.async_see(**args) descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml') ) hass.services.async_register( DOMAIN, SERVICE_SEE, async_see_service, descriptions.get(SERVICE_SEE)) # restore yield from tracker.async_setup_tracked_device() return True
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_devices, discovery_info=None): """Set up the cast platform.""" import pychromecast # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {}) hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {}) # None -> use discovery; (host, port) -> manually specify chromecast. want_host = None if discovery_info: want_host = (discovery_info.get('host'), discovery_info.get('port')) elif CONF_HOST in config: want_host = (config.get(CONF_HOST), DEFAULT_PORT) enable_discovery = False if want_host is None: # We were explicitly told to enable pychromecast discovery. enable_discovery = True elif want_host[1] != DEFAULT_PORT: # We're trying to add a group, so we have to use pychromecast's # discovery to get the correct friendly name. enable_discovery = True if enable_discovery: @callback def async_cast_discovered(chromecast): """Callback for when a new chromecast is discovered.""" if want_host is not None and \ (chromecast.host, chromecast.port) != want_host: return # for groups, only add requested device cast_device = _async_create_cast_device(hass, chromecast) if cast_device is not None: async_add_devices([cast_device]) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()): async_cast_discovered(chromecast) hass.async_add_job(_setup_internal_discovery, hass) else: # Manually add a "normal" Chromecast, we can do that without discovery. try: chromecast = await hass.async_add_job(pychromecast.Chromecast, *want_host) except pychromecast.ChromecastConnectionError as err: _LOGGER.warning("Can't set up chromecast on %s: %s", want_host[0], err) raise PlatformNotReady key = (chromecast.host, chromecast.port, chromecast.uuid) cast_device = _async_create_cast_device(hass, chromecast) if cast_device is not None: hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast async_add_devices([cast_device])
def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, []) conf = conf[0] if conf else {} consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) defaults = conf.get(CONF_NEW_DEVICE_DEFAULTS, {}) devices = yield from async_load_config(yaml_path, hass, consider_home) tracker = DeviceTracker( hass, consider_home, track_new, defaults, devices) @asyncio.coroutine def async_setup_platform(p_type, p_config, disc_info=None): """Set up a device tracker platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) try: scanner = None setup = None if hasattr(platform, 'async_get_scanner'): scanner = yield from platform.async_get_scanner( hass, {DOMAIN: p_config}) elif hasattr(platform, 'get_scanner'): scanner = yield from hass.async_add_job( platform.get_scanner, hass, {DOMAIN: p_config}) elif hasattr(platform, 'async_setup_scanner'): setup = yield from platform.async_setup_scanner( hass, p_config, tracker.async_see, disc_info) elif hasattr(platform, 'setup_scanner'): setup = yield from hass.async_add_job( platform.setup_scanner, hass, p_config, tracker.see, disc_info) else: raise HomeAssistantError("Invalid device_tracker platform.") if scanner: async_setup_scanner_platform( hass, p_config, scanner, tracker.async_see, p_type) return if not setup: _LOGGER.error("Error setting up platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform %s", p_type) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) tracker.async_setup_group() @asyncio.coroutine def async_platform_discovered(platform, info): """Load a platform.""" yield from async_setup_platform(platform, {}, disc_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) # Clean up stale devices async_track_utc_time_change( hass, tracker.async_update_stale, second=range(0, 60, 5)) @asyncio.coroutine def async_see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES)} yield from tracker.async_see(**args) descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml') ) hass.services.async_register( DOMAIN, SERVICE_SEE, async_see_service, descriptions.get(SERVICE_SEE)) # restore yield from tracker.async_setup_tracked_device() return True