def is_entity_exposed(self, entity): """Determine if an entity should be exposed on the emulated bridge. Async friendly. """ if entity.attributes.get('view') is not None: # Ignore entities that are views return False domain = entity.domain.lower() explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None) explicit_hidden = entity.attributes.get(ATTR_EMULATED_HUE_HIDDEN, None) if explicit_expose is True or explicit_hidden is False: expose = True elif explicit_expose is False or explicit_hidden is True: expose = False else: expose = None get_deprecated(entity.attributes, ATTR_EMULATED_HUE_HIDDEN, ATTR_EMULATED_HUE, None) domain_exposed_by_default = \ self.expose_by_default and domain in self.exposed_domains # Expose an entity if the entity's domain is exposed by default and # the configuration doesn't explicitly exclude it from being # exposed, or if the entity is explicitly exposed is_default_exposed = \ domain_exposed_by_default and expose is not False return is_default_exposed or expose
def devices_from_config(domain_config, hass=None): """Parse configuration and add Rflink switch devices.""" devices = [] for device_id, config in domain_config[CONF_DEVICES].items(): device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config) remove_deprecated(device_config) device = RflinkSwitch(device_id, hass, **device_config) devices.append(device) # Register entity (and aliases) to listen to incoming rflink events # Device id and normal aliases respond to normal and group command hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][device_id].append(device) if config[CONF_GROUP]: hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][device_id].append(device) for _id in get_deprecated(config, CONF_ALIASES, CONF_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) # group_aliases only respond to group commands for _id in get_deprecated( config, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES): hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) # nogroup_aliases only respond to normal commands for _id in get_deprecated( config, CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) return devices
def remove_deprecated(config): """Remove deprecated config options from device config.""" for index, deprecated_option in enumerate(DEPRECATED_CONFIG_OPTIONS): if deprecated_option in config: replacement_option = REPLACEMENT_CONFIG_OPTIONS[index] # generate deprecation warning get_deprecated(config, replacement_option, deprecated_option) # remove old config value replacing new one config[replacement_option] = config.pop(deprecated_option)
def devices_from_config(domain_config, hass=None): """Parse configuration and add Rflink light devices.""" devices = [] for device_id, config in domain_config[CONF_DEVICES].items(): # Determine which kind of entity to create if CONF_TYPE in config: # Remove type from config to not pass it as and argument to entity # instantiation entity_type = config.pop(CONF_TYPE) else: entity_type = entity_type_for_device_id(device_id) entity_class = entity_class_for_type(entity_type) device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config) remove_deprecated(device_config) is_hybrid = entity_class is HybridRflinkLight # Make user aware this can cause problems repetitions_enabled = device_config[CONF_SIGNAL_REPETITIONS] != 1 if is_hybrid and repetitions_enabled: _LOGGER.warning( "Hybrid type for %s not compatible with signal " "repetitions. Please set 'dimmable' or 'switchable' " "type explicitly in configuration", device_id) device = entity_class(device_id, hass, **device_config) devices.append(device) # Register entity (and aliases) to listen to incoming rflink events # Device id and normal aliases respond to normal and group command hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][device_id].append(device) if config[CONF_GROUP]: hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][device_id].append(device) for _id in get_deprecated(config, CONF_ALIASES, CONF_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) # group_aliases only respond to group commands for _id in get_deprecated( config, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES): hass.data[DATA_ENTITY_GROUP_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) # nogroup_aliases only respond to normal commands for _id in get_deprecated( config, CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][ EVENT_KEY_COMMAND][_id].append(device) return devices
def devices_from_config(domain_config, hass=None): """Parse configuration and add Rflink light devices.""" devices = [] for device_id, config in domain_config[CONF_DEVICES].items(): # Determine which kind of entity to create if CONF_TYPE in config: # Remove type from config to not pass it as and argument to entity # instantiation entity_type = config.pop(CONF_TYPE) else: entity_type = entity_type_for_device_id(device_id) entity_class = entity_class_for_type(entity_type) device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config) remove_deprecated(device_config) is_hybrid = entity_class is HybridRflinkLight # Make user aware this can cause problems repetitions_enabled = device_config[CONF_SIGNAL_REPETITIONS] != 1 if is_hybrid and repetitions_enabled: _LOGGER.warning( "Hybrid type for %s not compatible with signal " "repetitions. Please set 'dimmable' or 'switchable' " "type explicitly in configuration", device_id) device = entity_class(device_id, hass, **device_config) devices.append(device) # Register entity (and aliases) to listen to incoming rflink events # Device id and normal aliases respond to normal and group command hass.data[DATA_ENTITY_LOOKUP][EVENT_KEY_COMMAND][device_id].append( device) if config[CONF_GROUP]: hass.data[DATA_ENTITY_GROUP_LOOKUP][EVENT_KEY_COMMAND][ device_id].append(device) for _id in get_deprecated(config, CONF_ALIASES, CONF_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][EVENT_KEY_COMMAND][_id].append( device) hass.data[DATA_ENTITY_GROUP_LOOKUP][EVENT_KEY_COMMAND][_id].append( device) # group_aliases only respond to group commands for _id in get_deprecated(config, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES): hass.data[DATA_ENTITY_GROUP_LOOKUP][EVENT_KEY_COMMAND][_id].append( device) # nogroup_aliases only respond to normal commands for _id in get_deprecated(config, CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES): hass.data[DATA_ENTITY_LOOKUP][EVENT_KEY_COMMAND][_id].append( device) return devices
def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the REST binary sensor.""" name = config.get(CONF_NAME) resource = config.get(CONF_RESOURCE) method = config.get(CONF_METHOD) payload = config.get(CONF_PAYLOAD) verify_ssl = config.get(CONF_VERIFY_SSL) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) headers = config.get(CONF_HEADERS) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass if username and password: if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION: auth = HTTPDigestAuth(username, password) else: auth = HTTPBasicAuth(username, password) else: auth = None rest = RestData(method, resource, auth, headers, payload, verify_ssl) rest.update() if rest.data is None: _LOGGER.error("Unable to fetch REST data from %s", resource) return False add_devices( [RestBinarySensor(hass, rest, name, device_class, value_template)])
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Setup template binary sensors.""" sensors = [] for device, device_config in config[CONF_SENSORS].items(): value_template = device_config[CONF_VALUE_TEMPLATE] entity_ids = (device_config.get(ATTR_ENTITY_ID) or value_template.extract_entities()) friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) device_class = get_deprecated( device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) if value_template is not None: value_template.hass = hass sensors.append( BinarySensorTemplate( hass, device, friendly_name, device_class, value_template, entity_ids) ) if not sensors: _LOGGER.error('No sensors added') return False yield from async_add_devices(sensors, True) return True
def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Binary Sensor platform for EnOcean.""" dev_id = config.get(CONF_ID) devname = config.get(CONF_NAME) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) add_devices([EnOceanBinarySensor(dev_id, devname, device_class)])
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the REST binary sensor.""" name = config.get(CONF_NAME) resource = config.get(CONF_RESOURCE) method = config.get(CONF_METHOD) payload = config.get(CONF_PAYLOAD) verify_ssl = config.get(CONF_VERIFY_SSL) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) headers = config.get(CONF_HEADERS) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass if username and password: if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION: auth = HTTPDigestAuth(username, password) else: auth = HTTPBasicAuth(username, password) else: auth = None rest = RestData(method, resource, auth, headers, payload, verify_ssl) rest.update() if rest.data is None: _LOGGER.error("Unable to fetch REST data from %s", resource) return False add_devices([RestBinarySensor( hass, rest, name, device_class, value_template)])
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the trend sensors.""" sensors = [] for device, device_config in config[CONF_SENSORS].items(): entity_id = device_config[ATTR_ENTITY_ID] attribute = device_config.get(CONF_ATTRIBUTE) friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) device_class = get_deprecated( device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) invert = device_config[CONF_INVERT] sensors.append( SensorTrend( hass, device, friendly_name, entity_id, attribute, device_class, invert) ) if not sensors: _LOGGER.error("No sensors added") return False add_devices(sensors) return True
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up template binary sensors.""" sensors = [] for device, device_config in config[CONF_SENSORS].items(): value_template = device_config[CONF_VALUE_TEMPLATE] entity_ids = (device_config.get(ATTR_ENTITY_ID) or value_template.extract_entities()) friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) device_class = get_deprecated( device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) if value_template is not None: value_template.hass = hass sensors.append( BinarySensorTemplate( hass, device, friendly_name, device_class, value_template, entity_ids) ) if not sensors: _LOGGER.error("No sensors added") return False async_add_devices(sensors, True) return True
def test_config_get_deprecated_new(mock_get_logger): """Test deprecated class object.""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger config = {"new_name": True} assert get_deprecated(config, "new_name", "old_name") is True assert not mock_logger.warning.called
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the Kodi platform.""" host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) encryption = get_deprecated(config, CONF_PROXY_SSL, CONF_SSL) websocket = config.get(CONF_ENABLE_WEBSOCKET) if host.startswith('http://') or host.startswith('https://'): host = host.lstrip('http://').lstrip('https://') _LOGGER.warning( "Kodi host name should no longer conatin http:// See updated " "definitions here: " "https://home-assistant.io/components/media_player.kodi/") entity = KodiDevice(hass, name=config.get(CONF_NAME), host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), turn_off_action=config.get(CONF_TURN_OFF_ACTION), websocket=websocket) async_add_devices([entity], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on MediaPlayerDevice.""" method = SERVICE_TO_METHOD.get(service.service) if not method: return params = { key: value for key, value in service.data.items() if key != 'entity_id' } yield from getattr(entity, method['method'])(**params) update_tasks = [] if entity.should_poll: update_coro = entity.async_update_ha_state(True) update_tasks.append(update_coro) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) for service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[service].get('schema', MEDIA_PLAYER_SCHEMA) hass.services.async_register(DOMAIN, service, async_service_handler, description=None, schema=schema)
def test_config_get_deprecated_new(mock_get_logger): """Test deprecated class object.""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger config = { 'new_name': True, } assert get_deprecated(config, 'new_name', 'old_name') is True assert not mock_logger.warning.called
def test_config_get_deprecated_old(mock_get_logger): """Test deprecated class object.""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger config = { 'old_name': True, } assert get_deprecated(config, 'new_name', 'old_name') is True assert mock_logger.warning.called assert len(mock_logger.warning.mock_calls) == 1
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the Threshold sensor.""" entity_id = config.get(CONF_ENTITY_ID) name = config.get(CONF_NAME) threshold = config.get(CONF_THRESHOLD) limit_type = config.get(CONF_TYPE) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) yield from async_add_devices( [ThresholdSensor(hass, entity_id, name, threshold, limit_type, device_class)], True) return True
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Setup the Kodi platform.""" host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) encryption = get_deprecated(config, CONF_PROXY_SSL, CONF_SSL) websocket = config.get(CONF_ENABLE_WEBSOCKET) if host.startswith('http://') or host.startswith('https://'): host = host.lstrip('http://').lstrip('https://') _LOGGER.warning( "Kodi host name should no longer conatin http:// See updated " "definitions here: " "https://home-assistant.io/components/media_player.kodi/") entity = KodiDevice( hass, name=config.get(CONF_NAME), host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), turn_off_action=config.get(CONF_TURN_OFF_ACTION), websocket=websocket) async_add_devices([entity], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on MediaPlayerDevice.""" method = SERVICE_TO_METHOD.get(service.service) if not method: return params = {key: value for key, value in service.data.items() if key != 'entity_id'} yield from getattr(entity, method['method'])(**params) update_tasks = [] if entity.should_poll: update_coro = entity.async_update_ha_state(True) update_tasks.append(update_coro) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) for service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[service].get( 'schema', MEDIA_PLAYER_SCHEMA) hass.services.async_register( DOMAIN, service, async_service_handler, description=None, schema=schema)
def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Command line Binary Sensor.""" name = config.get(CONF_NAME) command = config.get(CONF_COMMAND) payload_off = config.get(CONF_PAYLOAD_OFF) payload_on = config.get(CONF_PAYLOAD_ON) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass data = CommandSensorData(command) add_devices([CommandBinarySensor( hass, data, name, device_class, payload_on, payload_off, value_template)])
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the MQTT binary sensor.""" if discovery_info is not None: config = PLATFORM_SCHEMA(discovery_info) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass async_add_devices([ MqttBinarySensor( config.get(CONF_NAME), config.get(CONF_STATE_TOPIC), get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS), config.get(CONF_QOS), config.get(CONF_PAYLOAD_ON), config.get(CONF_PAYLOAD_OFF), value_template) ])
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Command line Binary Sensor.""" name = config.get(CONF_NAME) command = config.get(CONF_COMMAND) payload_off = config.get(CONF_PAYLOAD_OFF) payload_on = config.get(CONF_PAYLOAD_ON) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass data = CommandSensorData(command) add_devices([ CommandBinarySensor(hass, data, name, device_class, payload_on, payload_off, value_template) ])
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the MQTT binary sensor.""" if discovery_info is not None: config = PLATFORM_SCHEMA(discovery_info) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass async_add_devices([MqttBinarySensor( config.get(CONF_NAME), config.get(CONF_STATE_TOPIC), get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS), config.get(CONF_QOS), config.get(CONF_PAYLOAD_ON), config.get(CONF_PAYLOAD_OFF), value_template )])
def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the aREST binary sensor.""" resource = config.get(CONF_RESOURCE) pin = config.get(CONF_PIN) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) try: response = requests.get(resource, timeout=10).json() except requests.exceptions.MissingSchema: _LOGGER.error("Missing resource or schema in configuration. " "Add http:// to your URL") return False except requests.exceptions.ConnectionError: _LOGGER.error("No route to device at %s", resource) return False arest = ArestData(resource, pin) add_devices([ArestBinarySensor( arest, resource, config.get(CONF_NAME, response[CONF_NAME]), device_class, pin)], True)
def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the aREST binary sensor.""" resource = config.get(CONF_RESOURCE) pin = config.get(CONF_PIN) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) try: response = requests.get(resource, timeout=10).json() except requests.exceptions.MissingSchema: _LOGGER.error("Missing resource or schema in configuration. " "Add http:// to your URL") return False except requests.exceptions.ConnectionError: _LOGGER.error("No route to device at %s", resource) return False arest = ArestData(resource, pin) add_devices([ArestBinarySensor( arest, resource, config.get(CONF_NAME, response[CONF_NAME]), device_class, pin)])
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Setup the Kodi platform.""" host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) encryption = get_deprecated(config, CONF_PROXY_SSL, CONF_SSL) websocket = config.get(CONF_ENABLE_WEBSOCKET) if host.startswith('http://') or host.startswith('https://'): host = host.lstrip('http://').lstrip('https://') _LOGGER.warning( "Kodi host name should no longer conatin http:// See updated " "definitions here: " "https://home-assistant.io/components/media_player.kodi/") entity = KodiDevice( hass, name=config.get(CONF_NAME), host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), turn_off_action=config.get(CONF_TURN_OFF_ACTION), websocket=websocket) async_add_devices([entity], update_before_add=True)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the Kodi platform.""" if DATA_KODI not in hass.data: hass.data[DATA_KODI] = [] host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) encryption = get_deprecated(config, CONF_PROXY_SSL, CONF_SSL) websocket = config.get(CONF_ENABLE_WEBSOCKET) if host.startswith('http://') or host.startswith('https://'): host = host.lstrip('http://').lstrip('https://') _LOGGER.warning( "Kodi host name should no longer conatin http:// See updated " "definitions here: " "https://home-assistant.io/components/media_player.kodi/") entity = KodiDevice( hass, name=config.get(CONF_NAME), host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), turn_off_action=config.get(CONF_TURN_OFF_ACTION), timeout=config.get(CONF_TIMEOUT), websocket=websocket) hass.data[DATA_KODI].append(entity) async_add_devices([entity], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on MediaPlayerDevice.""" method = SERVICE_TO_METHOD.get(service.service) if not method: return params = {key: value for key, value in service.data.items() if key != 'entity_id'} entity_ids = service.data.get('entity_id') if entity_ids: target_players = [player for player in hass.data[DATA_KODI] if player.entity_id in entity_ids] else: target_players = hass.data[DATA_KODI] update_tasks = [] for player in target_players: yield from getattr(player, method['method'])(**params) for player in target_players: if player.should_poll: update_coro = player.async_update_ha_state(True) update_tasks.append(update_coro) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) if hass.services.has_service(DOMAIN, SERVICE_ADD_MEDIA): return descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join( os.path.dirname(__file__), 'services.yaml')) for service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[service]['schema'] hass.services.async_register( DOMAIN, service, async_service_handler, description=descriptions.get(service), schema=schema)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the Kodi platform.""" if DATA_KODI not in hass.data: hass.data[DATA_KODI] = [] host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) encryption = get_deprecated(config, CONF_PROXY_SSL, CONF_SSL) websocket = config.get(CONF_ENABLE_WEBSOCKET) if host.startswith('http://') or host.startswith('https://'): host = host.lstrip('http://').lstrip('https://') _LOGGER.warning( "Kodi host name should no longer conatin http:// See updated " "definitions here: " "https://home-assistant.io/components/media_player.kodi/") entity = KodiDevice(hass, name=config.get(CONF_NAME), host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), turn_off_action=config.get(CONF_TURN_OFF_ACTION), timeout=config.get(CONF_TIMEOUT), websocket=websocket) hass.data[DATA_KODI].append(entity) async_add_devices([entity], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on MediaPlayerDevice.""" method = SERVICE_TO_METHOD.get(service.service) if not method: return params = { key: value for key, value in service.data.items() if key != 'entity_id' } entity_ids = service.data.get('entity_id') if entity_ids: target_players = [ player for player in hass.data[DATA_KODI] if player.entity_id in entity_ids ] else: target_players = hass.data[DATA_KODI] update_tasks = [] for player in target_players: yield from getattr(player, method['method'])(**params) for player in target_players: if player.should_poll: update_coro = player.async_update_ha_state(True) update_tasks.append(update_coro) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) if hass.services.has_service(DOMAIN, SERVICE_ADD_MEDIA): return descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml')) for service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[service]['schema'] hass.services.async_register(DOMAIN, service, async_service_handler, description=descriptions.get(service), schema=schema)
def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) from_state = config.get(CONF_FROM, MATCH_ALL) to_state = get_deprecated(config, CONF_TO, CONF_STATE, MATCH_ALL) time_delta = config.get(CONF_FOR) async_remove_state_for_cancel = None async_remove_state_for_listener = None match_all = (from_state == MATCH_ALL and to_state == MATCH_ALL) @callback def clear_listener(): """Clear all unsub listener.""" nonlocal async_remove_state_for_cancel, async_remove_state_for_listener # pylint: disable=not-callable if async_remove_state_for_listener is not None: async_remove_state_for_listener() async_remove_state_for_listener = None if async_remove_state_for_cancel is not None: async_remove_state_for_cancel() async_remove_state_for_cancel = None @callback def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" nonlocal async_remove_state_for_cancel, async_remove_state_for_listener def call_action(): """Call action with right context.""" hass.async_run_job( action, { 'trigger': { 'platform': 'state', 'entity_id': entity, 'from_state': from_s, 'to_state': to_s, 'for': time_delta, } }) # Ignore changes to state attributes if from/to is in use if (not match_all and from_s is not None and to_s is not None and from_s.last_changed == to_s.last_changed): return if time_delta is None: call_action() return @callback def state_for_listener(now): """Fire on state changes after a delay and calls action.""" nonlocal async_remove_state_for_listener async_remove_state_for_listener = None clear_listener() call_action() @callback def state_for_cancel_listener(entity, inner_from_s, inner_to_s): """Fire on changes and cancel for listener if changed.""" if inner_to_s.state == to_s.state: return clear_listener() # cleanup previous listener clear_listener() async_remove_state_for_listener = async_track_point_in_utc_time( hass, state_for_listener, dt_util.utcnow() + time_delta) async_remove_state_for_cancel = async_track_state_change( hass, entity, state_for_cancel_listener) unsub = async_track_state_change(hass, entity_id, state_automation_listener, from_state, to_state) @callback def async_remove(): """Remove state listeners async.""" unsub() clear_listener() return async_remove
def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) from_state = config.get(CONF_FROM, MATCH_ALL) to_state = get_deprecated(config, CONF_TO, CONF_STATE, MATCH_ALL) time_delta = config.get(CONF_FOR) async_remove_state_for_cancel = None async_remove_state_for_listener = None match_all = (from_state == MATCH_ALL and to_state == MATCH_ALL) @callback def clear_listener(): """Clear all unsub listener.""" nonlocal async_remove_state_for_cancel, async_remove_state_for_listener # pylint: disable=not-callable if async_remove_state_for_listener is not None: async_remove_state_for_listener() async_remove_state_for_listener = None if async_remove_state_for_cancel is not None: async_remove_state_for_cancel() async_remove_state_for_cancel = None @callback def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" nonlocal async_remove_state_for_cancel, async_remove_state_for_listener def call_action(): """Call action with right context.""" hass.async_run_job(action, { 'trigger': { 'platform': 'state', 'entity_id': entity, 'from_state': from_s, 'to_state': to_s, 'for': time_delta, } }) # Ignore changes to state attributes if from/to is in use if (not match_all and from_s is not None and to_s is not None and from_s.last_changed == to_s.last_changed): return if time_delta is None: call_action() return @callback def state_for_listener(now): """Fire on state changes after a delay and calls action.""" nonlocal async_remove_state_for_listener async_remove_state_for_listener = None clear_listener() call_action() @callback def state_for_cancel_listener(entity, inner_from_s, inner_to_s): """Fire on changes and cancel for listener if changed.""" if inner_to_s.state == to_s.state: return clear_listener() # cleanup previous listener clear_listener() async_remove_state_for_listener = async_track_point_in_utc_time( hass, state_for_listener, dt_util.utcnow() + time_delta) async_remove_state_for_cancel = async_track_state_change( hass, entity, state_for_cancel_listener) unsub = async_track_state_change( hass, entity_id, state_automation_listener, from_state, to_state) @callback def async_remove(): """Remove state listeners async.""" unsub() clear_listener() return async_remove