def __init__(self, hass, device_id, friendly_name, target_entity, attribute, sensor_class, invert): """Initialize the sensor.""" self._hass = hass self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._target_entity = target_entity self._attribute = attribute self._sensor_class = sensor_class self._invert = invert self._state = None self.from_state = None self.to_state = None self.update() def trend_sensor_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" self.from_state = old_state self.to_state = new_state self.update_ha_state(True) track_state_change(hass, target_entity, trend_sensor_state_listener)
def trigger(hass, config, action): """Listen for state changes based on configuration.""" value_template = config.get(CONF_VALUE_TEMPLATE) # Local variable to keep track of if the action has already been triggered already_triggered = False def state_changed_listener(entity_id, from_s, to_s): """Listen for state changes and calls action.""" nonlocal already_triggered template_result = condition.template(hass, value_template) # Check to see if template returns true if template_result and not already_triggered: already_triggered = True action({ 'trigger': { 'platform': 'template', 'entity_id': entity_id, 'from_state': from_s, 'to_state': to_s, }, }) elif not template_result: already_triggered = False track_state_change(hass, MATCH_ALL, state_changed_listener) return True
def trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: _LOGGER.error("Missing configuration key %s", CONF_ENTITY_ID) return False below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) value_template = config.get(CONF_VALUE_TEMPLATE) if below is None and above is None: _LOGGER.error("Missing configuration key." " One of %s or %s is required", CONF_BELOW, CONF_ABOVE) return False renderer = partial(_renderer, hass, value_template) # pylint: disable=unused-argument def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" # Fire action if we go from outside range into range if _in_range(above, below, renderer(to_s)) and \ (from_s is None or not _in_range(above, below, renderer(from_s))): action() track_state_change( hass, entity_id, state_automation_listener) return True
def __init__( self, hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp, target_temp, ac_mode, min_cycle_duration, ): """Initialize the thermostat.""" self.hass = hass self._name = name self.heater_entity_id = heater_entity_id self.ac_mode = ac_mode self.min_cycle_duration = min_cycle_duration self._active = False self._cur_temp = None self._min_temp = min_temp self._max_temp = max_temp self._target_temp = target_temp self._unit = hass.config.units.temperature_unit track_state_change(hass, sensor_entity_id, self._sensor_changed) sensor_state = hass.states.get(sensor_entity_id) if sensor_state: self._update_temp(sensor_state)
def turn_on(self, *args, **kwargs): """ Turn on the selected media_player from input_select """ if (self._api == None): _LOGGER.error("Can't start the player, no header file") return _LOGGER.debug("TURNON") self._playing = False if not self._update_entity_ids(): return _player = self.hass.states.get(self._entity_ids) data = {ATTR_ENTITY_ID: _player.entity_id} self._allow_next = False track_state_change(self.hass, _player.entity_id, self._sync_player) track_state_change(self.hass, self._playMode, self._update_playmode) self._turn_on_media_player(data) #_LOGGER.error("subscribe to changes of ") self._get_cipher('BB2mjBuAtiQ') # display imidiatly a loading state to provide feedback to the user self._track_name = "loading..." self._track_album_name = "" self._track_artist = "" self._track_artist_cover = None self._track_album_cover = None self._state = STATE_PLAYING # a bit early otherwise no info will be shown self.schedule_update_ha_state() # grabbing data from API, might take a 1-3 sec self._load_playlist()
def __init__(self, hass, app_name, topic, sandbox, cert_file): """Initialize APNS application.""" self.hass = hass self.app_name = app_name self.sandbox = sandbox self.certificate = cert_file self.yaml_path = hass.config.path(app_name + '_' + APNS_DEVICES) self.devices = {} self.device_states = {} self.topic = topic if os.path.isfile(self.yaml_path): self.devices = { str(key): ApnsDevice( str(key), value.get('name'), value.get('tracking_device_id'), value.get('disabled', False) ) for (key, value) in load_yaml_config_file(self.yaml_path).items() } tracking_ids = [ device.full_tracking_device_id for (key, device) in self.devices.items() if device.tracking_device_id is not None ] track_state_change( hass, tracking_ids, self.device_state_changed_listener)
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) zone_entity_id = config.get(CONF_ZONE) if entity_id is None or zone_entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s or %s", CONF_ENTITY_ID, CONF_ZONE) return False event = config.get(CONF_EVENT, DEFAULT_EVENT) def zone_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ if from_s and None in (from_s.attributes.get(ATTR_LATITUDE), from_s.attributes.get(ATTR_LONGITUDE)) or \ None in (to_s.attributes.get(ATTR_LATITUDE), to_s.attributes.get(ATTR_LONGITUDE)): return from_match = _in_zone(hass, zone_entity_id, from_s) if from_s else None to_match = _in_zone(hass, zone_entity_id, to_s) # pylint: disable=too-many-boolean-expressions if event == EVENT_ENTER and not from_match and to_match or \ event == EVENT_LEAVE and from_match and not to_match: action() track_state_change(hass, entity_id, zone_automation_listener, MATCH_ALL, MATCH_ALL) return True
def setup_proximity_component( hass: HomeAssistant, name: str, config: ConfigType ) -> bool: """Set up the individual proximity component.""" ignored_zones: list[str] = config[CONF_IGNORED_ZONES] proximity_devices: list[str] = config[CONF_DEVICES] tolerance: int = config[CONF_TOLERANCE] proximity_zone = name unit_of_measurement: str = config.get( CONF_UNIT_OF_MEASUREMENT, hass.config.units.length_unit ) zone_id = f"zone.{config[CONF_ZONE]}" proximity = Proximity( # type:ignore[no-untyped-call] hass, proximity_zone, DEFAULT_DIST_TO_ZONE, DEFAULT_DIR_OF_TRAVEL, DEFAULT_NEAREST, ignored_zones, proximity_devices, tolerance, zone_id, unit_of_measurement, ) proximity.entity_id = f"{DOMAIN}.{proximity_zone}" proximity.schedule_update_ha_state() track_state_change(hass, proximity_devices, proximity.check_proximity_state_change) return True
def __init__(self, hass, entity_id, entity_state, start, end, duration, sensor_type, name): """Initialize the HistoryStats sensor.""" self._hass = hass self._entity_id = entity_id self._entity_state = entity_state self._duration = duration self._start = start self._end = end self._type = sensor_type self._name = name self._unit_of_measurement = UNITS[sensor_type] self._period = (datetime.datetime.now(), datetime.datetime.now()) self.value = None self.count = None def force_refresh(*args): """Force the component to refresh.""" self.schedule_update_ha_state(True) # Update value when home assistant starts hass.bus.listen_once(EVENT_HOMEASSISTANT_START, force_refresh) # Update value when tracked entity changes its state track_state_change(hass, entity_id, force_refresh)
def register_presence_handlers(hass, config): """ Registers the event handlers that handle presence. """ rfid_sensor = config[DOMAIN].get(CONF_RFID, None) if rfid_sensor is None: _LOGGER.warning('RFID sensor not configured.') return def rfid_seen(now=None): """ Calls see service periodically with state of RFID sensor. """ rfid_state = hass.states.get(rfid_sensor) location = STATE_NOT_HOME if rfid_state is not None and str(rfid_state.state) == '1': location = STATE_HOME _LOGGER.debug('rfid %s state is %s', rfid_sensor, location) hass.services.call(DEVICE_TRACKER_DOMAIN, SERVICE_SEE, { ATTR_DEV_ID: split_entity_id(rfid_sensor)[1], ATTR_LOCATION_NAME: location, }) helper.track_utc_time_change(hass, rfid_seen, second=0) def rfid_state_change(entity_id, old_state, new_state): """ Calls see service immediately with state of RFID sensor. """ rfid_seen() helper.track_state_change(hass, rfid_sensor, rfid_state_change)
def __init__(self, hass, device_id, friendly_name, target_entity, attribute, sensor_class, invert): """Initialize the sensor.""" self._hass = hass self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._target_entity = target_entity self._attribute = attribute self._sensor_class = sensor_class self._invert = invert self._state = None self.from_state = None self.to_state = None self.update() def trend_sensor_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" self.from_state = old_state self.to_state = new_state self.update_ha_state(True) track_state_change(hass, target_entity, trend_sensor_state_listener)
def setup(hass, config): """Set up a component.""" _LOGGER.debug("Couples setting up...") component = EntityComponent(_LOGGER, DOMAIN, hass) entities = [] object_ids = [] for couple_name, cfg in config[DOMAIN].items(): if not cfg: cfg = {} ids = cfg[CONF_ENTITIES] object_ids = object_ids + ids entities.append(CoupledAlarms(hass, couple_name, ids)) if not entities: return False component.add_entities(entities) def notify_state_change(entity_id, old_state, new_state): for entity in entities: entity.state_changed(entity_id, old_state, new_state) track_state_change(hass, object_ids, notify_state_change) return True
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s", CONF_ENTITY_ID) return False from_state = config.get(CONF_FROM, MATCH_ALL) to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL if isinstance(from_state, bool) or isinstance(to_state, bool): logging.getLogger(__name__).error( 'Config error. Surround to/from values with quotes.') return False def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ action() track_state_change(hass, entity_id, state_automation_listener, from_state, to_state) return True
def __init__(self, hass, name, temp_sensor, humidity_sensor): """Initialize the sensor.""" self._state = None self._name = name self._temp_sensor = temp_sensor self._humidity_sensor = humidity_sensor self._is_metric = hass.config.units.is_metric self._temp = None self._hum = None track_state_change(hass, temp_sensor, self._sensor_changed) track_state_change(hass, humidity_sensor, self._sensor_changed) # Read initial state temp = hass.states.get(temp_sensor) hum = hass.states.get(humidity_sensor) if temp: self._temp = DewPoint._update_temp_sensor(temp) if hum: self._hum = DewPoint._update_hum_sensor(hum) self.update()
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: _LOGGER.error("Missing configuration key %s", CONF_ENTITY_ID) return False below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) attribute = config.get(CONF_ATTRIBUTE) if below is None and above is None: _LOGGER.error("Missing configuration key." " One of %s or %s is required", CONF_BELOW, CONF_ABOVE) return False # pylint: disable=unused-argument def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ # Fire action if we go from outside range into range if _in_range(to_s, above, below, attribute) and \ (from_s is None or not _in_range(from_s, above, below, attribute)): action() track_state_change( hass, entity_id, state_automation_listener) return True
def __init__( self, hass, entity_id, entity_state, start, end, duration, sensor_type, name): """Initialize the HistoryStats sensor.""" self._hass = hass self._entity_id = entity_id self._entity_state = entity_state self._duration = duration self._start = start self._end = end self._type = sensor_type self._name = name self._unit_of_measurement = UNITS[sensor_type] self._period = (datetime.datetime.now(), datetime.datetime.now()) self.value = 0 self.count = 0 def force_refresh(*args): """Force the component to refresh.""" self.schedule_update_ha_state(True) # Update value when home assistant starts hass.bus.listen_once(EVENT_HOMEASSISTANT_START, force_refresh) # Update value when tracked entity changes its state track_state_change(hass, entity_id, force_refresh)
def __init__(self, hass, app_name, topic, sandbox, cert_file): """Initialize APNS application.""" self.hass = hass self.app_name = app_name self.sandbox = sandbox self.certificate = cert_file self.yaml_path = hass.config.path(app_name + '_' + APNS_DEVICES) self.devices = {} self.device_states = {} self.topic = topic if os.path.isfile(self.yaml_path): self.devices = { str(key): ApnsDevice(str(key), value.get('name'), value.get('tracking_device_id'), value.get('disabled', False)) for (key, value) in load_yaml_config_file(self.yaml_path).items() } tracking_ids = [ device.full_tracking_device_id for (key, device) in self.devices.items() if device.tracking_device_id is not None ] track_state_change(hass, tracking_ids, self.device_state_changed_listener)
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: _LOGGER.error("Missing configuration key %s", CONF_ENTITY_ID) return False below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) if below is None and above is None: _LOGGER.error( "Missing configuration key." " One of %s or %s is required", CONF_BELOW, CONF_ABOVE) return False # pylint: disable=unused-argument def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ # Fire action if we go from outside range into range if _in_range(to_s.state, above, below) and \ (from_s is None or not _in_range(from_s.state, above, below)): action() track_state_change(hass, entity_id, state_automation_listener) return True
def setup_proximity_component(hass, name, config): """Set up the individual proximity component.""" ignored_zones = config.get(CONF_IGNORED_ZONES) proximity_devices = config.get(CONF_DEVICES) tolerance = config.get(CONF_TOLERANCE) proximity_zone = name unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT, hass.config.units.length_unit) zone_id = f"zone.{config.get(CONF_ZONE)}" proximity = Proximity( hass, proximity_zone, DEFAULT_DIST_TO_ZONE, DEFAULT_DIR_OF_TRAVEL, DEFAULT_NEAREST, ignored_zones, proximity_devices, tolerance, zone_id, unit_of_measurement, ) proximity.entity_id = f"{DOMAIN}.{proximity_zone}" proximity.schedule_update_ha_state() track_state_change(hass, proximity_devices, proximity.check_proximity_state_change) return True
def __init__(self, hass, config, logger): self.logger = logger self.hass = hass self.heater_entity_id = config.get("heater") self.name_device = config.get("name") self.target_sensor_entity_id = config.get("target_sensor") self.time_temp = [] if config.get("time_temp"): for time_temp in list(config.get("time_temp").split(",")): time, temp = time_temp.split(':') time_start, time_end = time.split('-') start_time = datetime.datetime.time( datetime.datetime.strptime(time_start, '%H%M')) end_time = datetime.datetime.time( datetime.datetime.strptime(time_end, '%H%M')) self.time_temp.append((start_time, end_time, float(temp))) self._min_temp = util.convert(config.get("min_temp"), float, 0) self._max_temp = util.convert(config.get("max_temp"), float, 100) self._manual_sat_temp = None self._away = False self._heater_manual_changed = True track_state_change(hass, self.heater_entity_id, self._heater_turned_on, STATE_OFF, STATE_ON) track_state_change(hass, self.heater_entity_id, self._heater_turned_off, STATE_ON, STATE_OFF)
def __init__(self, hass, app_name, topic, sandbox, cert_file): """Initialize APNS application.""" self.hass = hass self.app_name = app_name self.sandbox = sandbox self.certificate = cert_file self.yaml_path = hass.config.path(f"{app_name}_{APNS_DEVICES}") self.devices = {} self.device_states = {} self.topic = topic try: self.devices = { str(key): ApnsDevice( str(key), value.get("name"), value.get("tracking_device_id"), value.get("disabled", False), ) for (key, value) in load_yaml_config_file(self.yaml_path).items() } except FileNotFoundError: pass tracking_ids = [ device.full_tracking_device_id for (key, device) in self.devices.items() if device.tracking_device_id is not None ] track_state_change(hass, tracking_ids, self.device_state_changed_listener)
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) zone_entity_id = config.get(CONF_ZONE) if entity_id is None or zone_entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s or %s", CONF_ENTITY_ID, CONF_ZONE) return False event = config.get(CONF_EVENT, DEFAULT_EVENT) def zone_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ if from_s and None in (from_s.attributes.get(ATTR_LATITUDE), from_s.attributes.get(ATTR_LONGITUDE)) or \ None in (to_s.attributes.get(ATTR_LATITUDE), to_s.attributes.get(ATTR_LONGITUDE)): return from_match = _in_zone(hass, zone_entity_id, from_s) if from_s else None to_match = _in_zone(hass, zone_entity_id, to_s) # pylint: disable=too-many-boolean-expressions if event == EVENT_ENTER and not from_match and to_match or \ event == EVENT_LEAVE and from_match and not to_match: action() track_state_change( hass, entity_id, zone_automation_listener, MATCH_ALL, MATCH_ALL) return True
def __init__(self, hass, entity_id, name, sampling_size): """Initialize the Statistics sensor.""" self._hass = hass self._entity_id = entity_id self.is_binary = True if self._entity_id.split('.')[0] == \ 'binary_sensor' else False if not self.is_binary: self._name = '{} {}'.format(name, ATTR_MEAN) else: self._name = '{} {}'.format(name, ATTR_COUNT) self._sampling_size = sampling_size self._unit_of_measurement = None if self._sampling_size == 0: self.states = deque() else: self.states = deque(maxlen=self._sampling_size) self.median = self.mean = self.variance = self.stdev = 0 self.min = self.max = self.total = self.count = 0 self.update() def stats_sensor_state_listener(entity, old_state, new_state): """Called when the sensor changes state.""" self._unit_of_measurement = new_state.attributes.get( ATTR_UNIT_OF_MEASUREMENT) try: self.states.append(float(new_state.state)) self.count = self.count + 1 except ValueError: self.count = self.count + 1 self.update_ha_state(True) track_state_change(hass, entity_id, stats_sensor_state_listener)
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s", CONF_ENTITY_ID) return False from_state = config.get(CONF_FROM, MATCH_ALL) to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL if isinstance(from_state, bool) or isinstance(to_state, bool): logging.getLogger(__name__).error( 'Config error. Surround to/from values with quotes.') return False def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ action() track_state_change( hass, entity_id, state_automation_listener, from_state, to_state) return True
def __init__(self, hass, entity_id, name, sampling_size): """Initialize the Statistics sensor.""" self._hass = hass self._entity_id = entity_id self.is_binary = True if self._entity_id.split(".")[0] == "binary_sensor" else False if not self.is_binary: self._name = "{} {}".format(name, ATTR_MEAN) else: self._name = "{} {}".format(name, ATTR_COUNT) self._sampling_size = sampling_size self._unit_of_measurement = None if self._sampling_size == 0: self.states = deque() else: self.states = deque(maxlen=self._sampling_size) self.median = self.mean = self.variance = self.stdev = 0 self.min = self.max = self.total = self.count = 0 self.update() def calculate_sensor_state_listener(entity, old_state, new_state): """Called when the sensor changes state.""" self._unit_of_measurement = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) try: self.states.append(float(new_state.state)) self.count = self.count + 1 except ValueError: self.count = self.count + 1 self.update_ha_state(True) track_state_change(hass, entity_id, calculate_sensor_state_listener)
def _resume_mp(config): media_player = "media_player." + config.get("media_player", "") resume_state = None resume = False def _state_change(entity_id=None, old_state=None, new_state=None): nonlocal resume_state, resume content_id = hass.states.get(media_player).attributes.get( "media_content_id", []) if resume_state and new_state.state != 'playing' and resume: print(resume_state) data = { ATTR_MEDIA_CONTENT_ID: resume_state.attributes.get("media_content_id", ""), ATTR_MEDIA_CONTENT_TYPE: "audio/mp3", ATTR_ENTITY_ID: media_player, } resume_state = None resume = True hass.services.call(DOMAIN_MP, SERVICE_PLAY_MEDIA, data) elif (new_state.state == 'playing' and ("nrk.no" in content_id or "nrk-mms-live.online.no" in content_id)): resume_state = new_state elif (resume_state and new_state.state == 'playing' and "tts_proxy" in content_id): resume = True else: resume_state = None resume = False track_state_change(hass, media_player, _state_change)
def track_change(self, entity_ids, action, from_state=None, to_state=None): """DEPRECATED AS OF 8/4/2015.""" _LOGGER.warning( 'hass.states.track_change is deprecated. ' 'Use homeassistant.helpers.event.track_state_change instead.') import homeassistant.helpers.event as helper helper.track_state_change(_MockHA(self._bus), entity_ids, action, from_state, to_state)
def setup(hass, config): def coffee_state_changed(entity_id, old_state, new_state): _LOGGER.info('{} changed to {}'.format(entity_id, new_state.state)) if new_state.state in [ 'unknown', 'INITIALISING', 'UNINITIALISED', 'ERROR' ]: # hide all but init hide_entity(hass, entity_id=INIT_COFFEE_SCRIPT, hidden=False) for e in [ SINGLE_COFFEE_SCRIPT, DOUBLE_COFFEE_SCRIPT, FUND_COFFEE_SCRIPT, ADDRESSES_COFFEE_SENSOR, CLOSE_COFFEE_SCRIPT, BALANCE_COFFEE_SENSOR, PROVIDER_TRANSACTION, COFFEE_TRANSACTION, COFFEE_FLASH_SERVER, PROVIDER_FLASH_SERVER ]: hide_entity(hass, entity_id=e, hidden=True) elif new_state.state == 'INITIALISED': hide_entity(hass, entity_id=INIT_COFFEE_SCRIPT, hidden=True) hide_entity(hass, entity_id=FUND_COFFEE_SCRIPT, hidden=False) hide_entity(hass, entity_id=BALANCE_COFFEE_SENSOR, hidden=True) hide_entity(hass, entity_id=ADDRESSES_COFFEE_SENSOR, hidden=False) elif new_state.state == 'FUNDED': hide_entity(hass, entity_id=FUND_COFFEE_SCRIPT, hidden=True) hide_entity(hass, entity_id=BALANCE_COFFEE_SENSOR, hidden=False) hide_entity(hass, entity_id=CLOSE_COFFEE_SCRIPT, hidden=False) hide_entity(hass, entity_id=SINGLE_COFFEE_SCRIPT, hidden=False) hide_entity(hass, entity_id=DOUBLE_COFFEE_SCRIPT, hidden=False) hide_entity(hass, entity_id=ADDRESSES_COFFEE_SENSOR, hidden=False) elif new_state.state == 'CLOSING': hide_entity(hass, entity_id=SINGLE_COFFEE_SCRIPT, hidden=True) hide_entity(hass, entity_id=DOUBLE_COFFEE_SCRIPT, hidden=True) elif new_state.state == 'CLOSED': hide_entity(hass, entity_id=INIT_COFFEE_SCRIPT, hidden=False) # hide all but init and transaction for e in [ SINGLE_COFFEE_SCRIPT, DOUBLE_COFFEE_SCRIPT, FUND_COFFEE_SCRIPT, ADDRESSES_COFFEE_SENSOR, CLOSE_COFFEE_SCRIPT, BALANCE_COFFEE_SENSOR, COFFEE_TRANSACTION, PROVIDER_TRANSACTION ]: hide_entity(hass, entity_id=e, hidden=True) elif new_state.state in ['NO_FUNDS', 'NO_ADDRESSES_LEFT']: for e in [ SINGLE_COFFEE_SCRIPT, DOUBLE_COFFEE_SCRIPT, FUND_COFFEE_SCRIPT, INIT_COFFEE_SCRIPT, PROVIDER_TRANSACTION, COFFEE_TRANSACTION ]: hide_entity(hass, entity_id=e, hidden=True) hide_entity(hass, entity_id=CLOSE_COFFEE_SCRIPT, hidden=False) hide_entity(hass, entity_id=BALANCE_COFFEE_SENSOR, hidden=False) track_state_change(hass, entity_ids=['sensor.coffee_machine_state'], action=coffee_state_changed) return True
def setup(hass, config): """ Sets up the simple alarms. """ logger = logging.getLogger(__name__) logger.info("Starting laundry automation.") sensors = ["sensor.washer_status", "sensor.dryer_status"] wait_time = config[DOMAIN].get(CONF_WAIT_TIME, 300) def track_complete_status(entity_id, old_state, new_state): """ Called when appliance goes from running to complete. """ actually_complete = True for i in range(1, wait_time): state = hass.states.get(entity_id).state if state == COMPLETE: time.sleep(1) else: actually_complete = False logger.info("LAUNDRY NOT ACTUALLY COMPLETE!!") break if actually_complete: global fluxing fluxing = False if 'dryer' in entity_id: hass.services.call('scene', 'turn_on', {"entity_id":"scene.red"}) message = "The dryer is complete, please empty it!" elif 'washer' in entity_id: hass.services.call('scene', 'turn_on', {"entity_id":"scene.blue"}) message = "The washing machine is complete, please empty it!" logger.info("LAUNDRY ACTUALLY COMPLETE!!") if hass.states.get(LAURENS_DEVICE).state == STATE_HOME: hass.services.call('notify', 'join_lauren', {"message":message}) if hass.states.get(NOLANS_DEVICE).state == STATE_HOME: hass.services.call('notify', 'join', {"message":message}) def appliance_emptied(entity_id, old_state, new_state): """ Called when appliance goes from complete to empty. """ hass.services.call('scene', 'turn_on', {"entity_id":"scene.normal"}) global fluxing fluxing = True def flux_update(service): """ Called every 30 seconds to flux the lights. """ global fluxing ib_flux_state = hass.states.get('input_boolean.flux_automation') if fluxing and ib_flux_state: if ib_flux_state.state == 'on': hass.services.call('switch', 'flux_update') track_state_change( hass, sensors, track_complete_status, RUNNING, COMPLETE) track_state_change( hass, sensors, appliance_emptied, COMPLETE, EMPTY) track_time_change(hass, flux_update, second=[0,30]) return True
def setup(hass, config): """ Sets up the simple alarms. """ logger = logging.getLogger(__name__) logger.info("Starting laundry automation.") sensors = ["sensor.washer_status", "sensor.dryer_status"] wait_time = config[DOMAIN].get(CONF_WAIT_TIME, 300) def track_complete_status(entity_id, old_state, new_state): """ Called when appliance goes from running to complete. """ actually_complete = True for i in range(1, wait_time): state = hass.states.get(entity_id).state if state == COMPLETE: time.sleep(1) else: actually_complete = False logger.info("LAUNDRY NOT ACTUALLY COMPLETE!!") break if actually_complete: global fluxing fluxing = False if 'dryer' in entity_id: hass.services.call('scene', 'turn_on', {"entity_id": "scene.red"}) message = "The dryer is complete, please empty it!" elif 'washer' in entity_id: hass.services.call('scene', 'turn_on', {"entity_id": "scene.blue"}) message = "The washing machine is complete, please empty it!" logger.info("LAUNDRY ACTUALLY COMPLETE!!") if hass.states.get(LAURENS_DEVICE).state == STATE_HOME: hass.services.call('notify', 'join_lauren', {"message": message}) if hass.states.get(NOLANS_DEVICE).state == STATE_HOME: hass.services.call('notify', 'join', {"message": message}) def appliance_emptied(entity_id, old_state, new_state): """ Called when appliance goes from complete to empty. """ hass.services.call('scene', 'turn_on', {"entity_id": "scene.normal"}) global fluxing fluxing = True def flux_update(service): """ Called every 30 seconds to flux the lights. """ global fluxing ib_flux_state = hass.states.get('input_boolean.flux_automation') if fluxing and ib_flux_state: if ib_flux_state.state == 'on': hass.services.call('switch', 'flux_update') track_state_change(hass, sensors, track_complete_status, RUNNING, COMPLETE) track_state_change(hass, sensors, appliance_emptied, COMPLETE, EMPTY) track_time_change(hass, flux_update, second=[0, 30]) return True
def setup(hass, config): """ Sets up the simple alarms. """ logger = logging.getLogger(__name__) max_sun_elevation = 100 light_entity_id = "light.gang" leave_lights_on_for_min = 1 # keep_lights_off_for_min = 5 trigger_sensors = ['binary_sensor.movement3', 'binary_sensor.door_soverom'] #auto_triggered = False turn_off_light_listener = None def activate(entity_id, old_state, new_state): """ Called when a known person comes home. """ state_sun = hass.states.get('sun.sun') if state_sun.attributes[STATE_ATTR_ELEVATION] > max_sun_elevation: return nonlocal turn_off_light_listener if turn_off_light_listener is not None: turn_off_light_listener() turn_off_light_listener = None turn_off_light_listener = track_point_in_time( hass, deactivate, dt_util.utcnow() + datetime.timedelta(minutes=leave_lights_on_for_min)) light_state = hass.states.get(light_entity_id) if light_state.state == STATE_ON: return now = dt_util.now() if now.hour >= 22 or now.hour < 7: light.turn_on(hass, light_entity_id, xy_color=[0.6461, 0.3426], brightness=64, transition=3) elif entity_id == 'binary_sensor.movement3': light.turn_on(hass, light_entity_id, xy_color=[0.4607, 0.43], brightness=81, transition=1) else: return def deactivate(now): light.turn_off(hass, light_entity_id) track_state_change(hass, trigger_sensors, activate, STATE_OFF, STATE_ON) return True
def setup_platform( hass: HomeAssistant, config: ConfigEntry, add_entities: Callable[[List[Entity], bool], None], discovery_info=None, ) -> None: """Set up the Spotify Metafy platform.""" if "spotify" not in hass.data: raise PlatformNotReady entities: List[MetafyMediaPlayer] = [] entity_component: EntityComponent = hass.data[MEDIA_PLAYER_DOMAIN] # Make sure all the players are ready for user in config["users"]: spotify_entity_id = user["spotify_entity_id"] spotify_media_player: SpotifyMediaPlayer = entity_component.get_entity( spotify_entity_id ) if spotify_media_player is None: raise PlatformNotReady for user in config["users"]: user_prefix = user["user_prefix"] if "user_prefix" in user else "" destination = user["destination"] playlists = user["playlists"] spotify_entity_id = user["spotify_entity_id"] spotify_media_player: SpotifyMediaPlayer = entity_component.get_entity( spotify_entity_id ) for playlist in playlists: uri = playlist["uri"] spotify_playlist_info = spotify_media_player._spotify.playlist(uri) playlist_name = user_prefix + spotify_playlist_info["name"] mmp = MetafyMediaPlayer( spotify_media_player, uri, destination, playlist_name, spotify_playlist_info, ) entities.append(mmp) add_entities(entities) for entity in entities: track_state_change( hass, [entity._spotify_media_player.entity_id], entity.update_on_state_change, ) return True
def __init__(self, hass, scene_config): self.hass = hass self.scene_config = scene_config self.is_active = False self.prev_states = None self.ignore_updates = False track_state_change(self.hass, self.entity_ids, self.entity_state_changed) self.update()
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s", CONF_ENTITY_ID) return None from_state = config.get(CONF_FROM, MATCH_ALL) to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = get_time_config(config) if isinstance(from_state, bool) or isinstance(to_state, bool): logging.getLogger(__name__).error( 'Config error. Surround to/from values with quotes.') return None if CONF_FOR in config and time_delta is None: return None def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ def state_for_listener(now): """ Fires on state changes after a delay and calls action. """ hass.bus.remove_listener( EVENT_STATE_CHANGED, for_state_listener) action() def state_for_cancel_listener(entity, inner_from_s, inner_to_s): """ Fires on state changes and cancels for listener if state changed. """ if inner_to_s == to_s: return hass.bus.remove_listener(EVENT_TIME_CHANGED, for_time_listener) hass.bus.remove_listener( EVENT_STATE_CHANGED, for_state_listener) if time_delta is not None: target_tm = dt_util.utcnow() + time_delta for_time_listener = track_point_in_time( hass, state_for_listener, target_tm) for_state_listener = track_state_change( hass, entity_id, state_for_cancel_listener, MATCH_ALL, MATCH_ALL) else: action() track_state_change( hass, entity_id, state_automation_listener, from_state, to_state) return True
def __init__(self, hass, scene_config): self.hass = hass self.scene_config = scene_config self.is_active = False self.prev_states = None self.ignore_updates = False track_state_change( self.hass, self.entity_ids, self.entity_state_changed) self.update()
def test_track_state_change(self): """Test track_state_change.""" # 2 lists to track how often our callbacks get called specific_runs = [] wildcard_runs = [] track_state_change( self.hass, 'light.Bowl', lambda a, b, c: specific_runs.append(1), 'on', 'off') track_state_change( self.hass, 'light.Bowl', lambda _, old_s, new_s: wildcard_runs.append((old_s, new_s)), ha.MATCH_ALL, ha.MATCH_ALL) # Adding state to state machine self.hass.states.set("light.Bowl", "on") self.hass.pool.block_till_done() self.assertEqual(0, len(specific_runs)) self.assertEqual(1, len(wildcard_runs)) self.assertIsNone(wildcard_runs[-1][0]) self.assertIsNotNone(wildcard_runs[-1][1]) # Set same state should not trigger a state change/listener self.hass.states.set('light.Bowl', 'on') self.hass.pool.block_till_done() self.assertEqual(0, len(specific_runs)) self.assertEqual(1, len(wildcard_runs)) # State change off -> on self.hass.states.set('light.Bowl', 'off') self.hass.pool.block_till_done() self.assertEqual(1, len(specific_runs)) self.assertEqual(2, len(wildcard_runs)) # State change off -> off self.hass.states.set('light.Bowl', 'off', {"some_attr": 1}) self.hass.pool.block_till_done() self.assertEqual(1, len(specific_runs)) self.assertEqual(3, len(wildcard_runs)) # State change off -> on self.hass.states.set('light.Bowl', 'on') self.hass.pool.block_till_done() self.assertEqual(1, len(specific_runs)) self.assertEqual(4, len(wildcard_runs)) self.hass.states.remove('light.bowl') self.hass.pool.block_till_done() self.assertEqual(1, len(specific_runs)) self.assertEqual(5, len(wildcard_runs)) self.assertIsNotNone(wildcard_runs[-1][0]) self.assertIsNone(wildcard_runs[-1][1])
def test_case_insensitivty(self): self.pool.add_worker() runs = [] track_state_change(ha._MockHA(self.bus), 'light.BoWl', lambda a, b, c: runs.append(1), ha.MATCH_ALL, ha.MATCH_ALL) self.states.set('light.BOWL', 'off') self.bus._pool.block_till_done() self.assertTrue(self.states.is_state('light.bowl', 'off')) self.assertEqual(1, len(runs))
def test_case_insensitivty(self): self.pool.add_worker() runs = [] track_state_change( ha._MockHA(self.bus), 'light.BoWl', lambda a, b, c: runs.append(1), ha.MATCH_ALL, ha.MATCH_ALL) self.states.set('light.BOWL', 'off') self.bus._pool.block_till_done() self.assertTrue(self.states.is_state('light.bowl', 'off')) self.assertEqual(1, len(runs))
def 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 = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = config.get(CONF_FOR) def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" def call_action(): """Call action with right context.""" action({ 'trigger': { 'platform': 'state', 'entity_id': entity, 'from_state': from_s, 'to_state': to_s, 'for': time_delta, } }) if time_delta is None: call_action() return def state_for_listener(now): """Fire on state changes after a delay and calls action.""" hass.bus.remove_listener(EVENT_STATE_CHANGED, attached_state_for_cancel) call_action() 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 hass.bus.remove_listener(EVENT_TIME_CHANGED, attached_state_for_listener) hass.bus.remove_listener(EVENT_STATE_CHANGED, attached_state_for_cancel) attached_state_for_listener = track_point_in_time( hass, state_for_listener, dt_util.utcnow() + time_delta) attached_state_for_cancel = track_state_change( hass, entity, state_for_cancel_listener) track_state_change(hass, entity_id, state_automation_listener, from_state, to_state) return True
def 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 = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = config.get(CONF_FOR) def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" def call_action(): """Call action with right context.""" action({ 'trigger': { 'platform': 'state', 'entity_id': entity, 'from_state': from_s, 'to_state': to_s, 'for': time_delta, } }) if time_delta is None: call_action() return def state_for_listener(now): """Fire on state changes after a delay and calls action.""" hass.bus.remove_listener( EVENT_STATE_CHANGED, attached_state_for_cancel) call_action() 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 hass.bus.remove_listener(EVENT_TIME_CHANGED, attached_state_for_listener) hass.bus.remove_listener(EVENT_STATE_CHANGED, attached_state_for_cancel) attached_state_for_listener = track_point_in_time( hass, state_for_listener, dt_util.utcnow() + time_delta) attached_state_for_cancel = track_state_change( hass, entity, state_for_cancel_listener) track_state_change( hass, entity_id, state_automation_listener, from_state, to_state) return True
def trigger(hass, config, action): """ Listen for state changes based on `config`. """ entity_id = config.get(CONF_ENTITY_ID) if entity_id is None: logging.getLogger(__name__).error( "Missing trigger configuration key %s", CONF_ENTITY_ID) return None from_state = config.get(CONF_FROM, MATCH_ALL) to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = get_time_config(config) if isinstance(from_state, bool) or isinstance(to_state, bool): logging.getLogger(__name__).error( 'Config error. Surround to/from values with quotes.') return None if CONF_FOR in config and time_delta is None: return None def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ def state_for_listener(now): """ Fires on state changes after a delay and calls action. """ hass.bus.remove_listener(EVENT_STATE_CHANGED, for_state_listener) action() def state_for_cancel_listener(entity, inner_from_s, inner_to_s): """ Fires on state changes and cancels for listener if state changed. """ if inner_to_s == to_s: return hass.bus.remove_listener(EVENT_TIME_CHANGED, for_time_listener) hass.bus.remove_listener(EVENT_STATE_CHANGED, for_state_listener) if time_delta is not None: target_tm = dt_util.utcnow() + time_delta for_time_listener = track_point_in_time(hass, state_for_listener, target_tm) for_state_listener = track_state_change(hass, entity_id, state_for_cancel_listener, MATCH_ALL, MATCH_ALL) else: action() track_state_change(hass, entity_id, state_automation_listener, from_state, to_state) return True
def _started(self, event): ''' Callback invoked when all components have been initialized. Setting up other listeners here ensures we won't get extra calls. This is when time events start firing anyway. ''' _LOGGER.info('Starting alarm for {}'.format(self.time)) track_state_change(self.hass, self.time, self._time_changed) if self.master_control: track_state_change(self.hass, self.master_control, self._master_control_changed) self._update_alarms()
def turn_on(self, *args, **kwargs): """ Turn on the selected media_player from input_select """ if self._unsub_speaker_tracker: self._unsub_speaker_tracker() self._playing = False select_speaker = self.hass.states.get(self._media_player) self._speaker = "media_player.{}".format(select_speaker.state) speaker_state = self.hass.states.get(self._speaker) if speaker_state == None: self._speaker = None return self.schedule_update_ha_state() _LOGGER.info("turn on speaker %s", self._speaker) if speaker_state.state == STATE_OFF: self.hass.services.call(DOMAIN_MP, 'turn_on', {ATTR_ENTITY_ID: self._speaker}) self._state = STATE_IDLE self._unsub_speaker_tracker = track_state_change( self.hass, self._speaker, self._sync_player) self.schedule_update_ha_state() elif speaker_state.state == STATE_IDLE: self._state = STATE_IDLE self._unsub_speaker_tracker = track_state_change( self.hass, self._speaker, self._sync_player) self.schedule_update_ha_state() elif speaker_state.state == STATE_PLAYING or speaker_state.state == STATE_PAUSED: self._state = STATE_IDLE self.hass.services.call(DOMAIN_MP, 'media_stop', {ATTR_ENTITY_ID: self._speaker}) self._unsub_speaker_tracker = track_state_change( self.hass, self._speaker, self._sync_player) self.schedule_update_ha_state() else: self._state = STATE_OFF return if self._current_track == None: url = "{}/current_track".format(self._gmproxyurl) try: self._current_track = json.loads(requests.get(url).content) self.update_media_info() except: self._state = STATE_OFF return if self._current_track == None: self._state = STATE_OFF else: self.media_play()
def __init__(self, hass, name, heater_entity_id, sensor_entity_id): self.hass = hass self._name = name self.heater_entity_id = heater_entity_id self._active = False self._cur_temp = None self._target_temp = None self._unit = None track_state_change(hass, sensor_entity_id, self._sensor_changed) sensor_state = hass.states.get(sensor_entity_id) if sensor_state: self._update_temp(sensor_state)
def setup(hass, config): # state listener: pass in entity that changed def state_changed(entity_id, old_state, new_state): _LOGGER.debug(f"{dbg()}:{entity_id} changed state: {new_state}") hass.data[ENERGY_ASSET_DOMAIN].add_dirty_list(entity_id) hass.data[ENERGY_ASSET_DOMAIN].update_asset(entity_id, new_state.attributes) _LOGGER.debug(f"{dbg()}:Entities: {group.get_entity_ids(hass, 'group.all_switches')}") # register the state change listener: pass in the entities to observer and the callback listener # will listen on the event bus and filter for the entities we care about track_state_change(hass, group.get_entity_ids(hass, 'group.all_switches'), state_changed) return True # show that the component loaded successfully
def __init__(self, hass, name, heater_entity_id, sensor_entity_id): self.hass = hass self._name = name self.heater_entity_id = heater_entity_id self._active = False self._cur_temp = None self._target_temp = None self._unit = None track_state_change(hass, sensor_entity_id, self._sensor_changed) sensor_state = hass.states.get(sensor_entity_id) if sensor_state: self._update_temp(sensor_state)
def trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) zone_entity_id = config.get(CONF_ZONE) event = config.get(CONF_EVENT) def zone_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" if from_s and not location.has_location(from_s) or not location.has_location(to_s): return zone_state = hass.states.get(zone_entity_id) if from_s: from_match = condition.zone(hass, zone_state, from_s) else: from_match = False to_match = condition.zone(hass, zone_state, to_s) # pylint: disable=too-many-boolean-expressions if event == EVENT_ENTER and not from_match and to_match or event == EVENT_LEAVE and from_match and not to_match: action( { "trigger": { "platform": "zone", "entity_id": entity, "from_state": from_s, "to_state": to_s, "zone": zone_state, "event": event, } } ) return track_state_change(hass, entity_id, zone_automation_listener, MATCH_ALL, MATCH_ALL)
def trigger(hass, config, action): """Listen for state changes based on configuration.""" value_template = config.get(CONF_VALUE_TEMPLATE) value_template.hass = hass # Local variable to keep track of if the action has already been triggered already_triggered = False @asyncio.coroutine def state_changed_listener(entity_id, from_s, to_s): """Listen for state changes and calls action.""" nonlocal already_triggered template_result = condition.async_template(hass, value_template) # Check to see if template returns true if template_result and not already_triggered: already_triggered = True hass.async_add_job(action, { 'trigger': { 'platform': 'template', 'entity_id': entity_id, 'from_state': from_s, 'to_state': to_s, }, }) elif not template_result: already_triggered = False return track_state_change(hass, value_template.extract_entities(), state_changed_listener)
def 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 = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = config.get(CONF_FOR) remove_state_for_cancel = None remove_state_for_listener = None def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" nonlocal remove_state_for_cancel, remove_state_for_listener def call_action(): """Call action with right context.""" action( { "trigger": { "platform": "state", "entity_id": entity, "from_state": from_s, "to_state": to_s, "for": time_delta, } } ) if time_delta is None: call_action() return def state_for_listener(now): """Fire on state changes after a delay and calls action.""" remove_state_for_cancel() call_action() 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 remove_state_for_listener() remove_state_for_cancel() remove_state_for_listener = track_point_in_time(hass, state_for_listener, dt_util.utcnow() + time_delta) remove_state_for_cancel = track_state_change(hass, entity, state_for_cancel_listener) unsub = track_state_change(hass, entity_id, state_automation_listener, from_state, to_state) def remove(): """Remove state listeners.""" unsub() # pylint: disable=not-callable if remove_state_for_cancel is not None: remove_state_for_cancel() if remove_state_for_listener is not None: remove_state_for_listener() return remove
def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" def state_for_listener(now): """Fire on state changes after a delay and calls action.""" hass.bus.remove_listener( EVENT_STATE_CHANGED, for_state_listener) action() 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 == to_s: return hass.bus.remove_listener(EVENT_TIME_CHANGED, for_time_listener) hass.bus.remove_listener( EVENT_STATE_CHANGED, for_state_listener) if time_delta is not None: target_tm = dt_util.utcnow() + time_delta for_time_listener = track_point_in_time( hass, state_for_listener, target_tm) for_state_listener = track_state_change( hass, entity_id, state_for_cancel_listener, MATCH_ALL, MATCH_ALL) else: action()
def __init__(self, hass, config, see): self._hass = hass self._see = see entities = config[CONF_ENTITY_ID] self._entities = {} for entity_id in entities: self._entities[entity_id] = { WARNED: False, SOURCE_TYPE: None, STATE: None } self._dev_id = config[CONF_NAME] self._entity_id = ENTITY_ID_FORMAT.format(self._dev_id) self._time_as = config[CONF_TIME_AS] if self._time_as in [TZ_DEVICE_UTC, TZ_DEVICE_LOCAL]: from timezonefinderL import TimezoneFinder self._tf = TimezoneFinder() self._lock = threading.Lock() self._prev_seen = None self._remove = track_state_change(hass, entities, self._update_info) for entity_id in entities: self._update_info(entity_id, None, hass.states.get(entity_id), init=True)
def __init__(self, hass, device_id, friendly_name, unit_of_measurement, state_template, entity_ids): """Initialize the sensor.""" self.hass = hass self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass) self._name = friendly_name self._unit_of_measurement = unit_of_measurement self._template = state_template self._state = None self.update() def template_sensor_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" self.update_ha_state(True) track_state_change(hass, entity_ids, template_sensor_state_listener)
def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements """ Get the zones and offsets from configuration.yaml. """ ignored_zones = [] if 'ignored_zones' in config[DOMAIN]: for variable in config[DOMAIN]['ignored_zones']: ignored_zones.append(variable) # Get the devices from configuration.yaml if 'devices' not in config[DOMAIN]: _LOGGER.error('devices not found in config') return False proximity_devices = [] for variable in config[DOMAIN]['devices']: proximity_devices.append(variable) # Get the direction of travel tolerance from configuration.yaml tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE) # Get the zone to monitor proximity to from configuration.yaml proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE) entity_id = DOMAIN + '.' + proximity_zone proximity_zone = 'zone.' + proximity_zone state = hass.states.get(proximity_zone) zone_friendly_name = (state.name).lower() # set the default values dist_to_zone = 'not set' dir_of_travel = 'not set' nearest = 'not set' proximity = Proximity(hass, zone_friendly_name, dist_to_zone, dir_of_travel, nearest, ignored_zones, proximity_devices, tolerance, proximity_zone) proximity.entity_id = entity_id proximity.update_ha_state() # Main command to monitor proximity of devices track_state_change(hass, proximity_devices, proximity.check_proximity_state_change) return True
def test_multiple_emails(self): """Test multiple emails.""" states = [] test_message1 = email.message.Message() test_message1['From'] = "*****@*****.**" test_message1['Subject'] = "Test" test_message1['Date'] = datetime.datetime(2016, 1, 1, 12, 44, 57) test_message1.set_payload("Test Message") test_message2 = email.message.Message() test_message2['From'] = "*****@*****.**" test_message2['Subject'] = "Test 2" test_message2['Date'] = datetime.datetime(2016, 1, 1, 12, 44, 57) test_message2.set_payload("Test Message 2") states_received = Event() def state_changed_listener(entity_id, from_s, to_s): states.append(to_s) if len(states) == 2: states_received.set() track_state_change( self.hass, ["sensor.emailtest"], state_changed_listener) sensor = imap_email_content.EmailContentSensor( self.hass, FakeEMailReader(deque([test_message1, test_message2])), "test_emails_sensor", ["*****@*****.**"], None) sensor.entity_id = "sensor.emailtest" sensor.update() self.hass.block_till_done() states_received.wait(5) self.assertEqual("Test Message", states[0].state) self.assertEqual("Test Message 2", states[1].state) self.assertEqual("Test Message 2", sensor.state)
def __init__(self, hass, name, children, commands, attributes): """Initialize the Universal media device.""" self.hass = hass self._name = name self._children = children self._cmds = commands self._attrs = attributes self._child_state = None def on_dependency_update(*_): """Update ha state when dependencies update.""" self.update_ha_state(True) depend = copy(children) for entity in attributes.values(): depend.append(entity[0]) track_state_change(hass, depend, on_dependency_update)
def __init__(self, hass, name, children, commands, attributes): # pylint: disable=too-many-arguments self.hass = hass self._name = name self._children = children self._cmds = commands self._attrs = attributes self._child_state = None def on_dependency_update(*_): """ update ha state when dependencies update """ self.update_ha_state(True) depend = copy(children) for entity in attributes.values(): depend.append(entity[0]) track_state_change(hass, depend, on_dependency_update)