def track_point_in_time(self, action, point_in_time): """Deprecated method as of 8/4/2015 to track point in time.""" _LOGGER.warning( 'hass.track_point_in_time is deprecated. ' 'Please use homeassistant.helpers.event.track_point_in_time') import homeassistant.helpers.event as helper helper.track_point_in_time(self, action, point_in_time)
def test_track_point_in_time(self): """Test track point in time.""" before_birthday = datetime(1985, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) birthday_paulus = datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) after_birthday = datetime(1987, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) runs = [] track_point_in_utc_time( self.hass, lambda x: runs.append(1), birthday_paulus) self._send_time_changed(before_birthday) self.hass.pool.block_till_done() self.assertEqual(0, len(runs)) self._send_time_changed(birthday_paulus) self.hass.pool.block_till_done() self.assertEqual(1, len(runs)) # A point in time tracker will only fire once, this should do nothing self._send_time_changed(birthday_paulus) self.hass.pool.block_till_done() self.assertEqual(1, len(runs)) track_point_in_time( self.hass, lambda x: runs.append(1), birthday_paulus) self._send_time_changed(after_birthday) self.hass.pool.block_till_done() self.assertEqual(2, len(runs))
def scheduleHardOffTimes(self): # get my hard/soft off times self._hardOff = self.timeStringToDateTime( self._config["hardOff"]["at"]) _LOGGER.info("Hard Off times is {}".format(self._hardOff)) track_point_in_time(self._hass, self.hardOff, self._hardOff)
def schedule_lights_at_sun_set(hass, entity, old_state, new_state): """The moment sun sets we want to have all the lights on. We will schedule to have each light start after one another and slowly transition in. """ start_point = calc_time_for_light_when_sunset() if not start_point: return def async_turn_on_factory(light_id): """Lambda can keep track of function parameters. No local parameters. If we put the lambda directly in the below statement only the last light will be turned on. """ @callback def async_turn_on_light(now): """Turn on specific light.""" async_turn_on_before_sunset(light_id) return async_turn_on_light for index, light_id in enumerate(light_ids): track_point_in_time(hass, async_turn_on_factory(light_id), start_point + index * LIGHT_TRANSITION_TIME)
def update_emoncms(time): """Send whitelisted entities states regularly to Emoncms.""" payload_dict = {} for entity_id in whitelist: state = hass.states.get(entity_id) if state is None or state.state in (STATE_UNKNOWN, "", STATE_UNAVAILABLE): continue try: payload_dict[entity_id] = state_helper.state_as_number(state) except ValueError: continue if payload_dict: payload = "{%s}" % ",".join(f"{key}:{val}" for key, val in payload_dict.items()) send_data( conf.get(CONF_URL), conf.get(CONF_API_KEY), str(conf.get(CONF_INPUTNODE)), payload, ) track_point_in_time( hass, update_emoncms, time + timedelta(seconds=conf.get(CONF_SCAN_INTERVAL)))
def _handle_code(self, call): """Handle received code by the pilight-daemon. If the code matches the defined payload of this sensor the sensor state is changed accordingly. """ # Check if received code matches defined payload # True if payload is contained in received code dict payload_ok = True for key in self._payload: if key not in call.data: payload_ok = False continue if self._payload[key] != call.data[key]: payload_ok = False # Read out variable if payload ok if payload_ok: if self._variable not in call.data: return value = call.data[self._variable] self._state = (value == self._on_value) if self._delay_after is None: self._delay_after = dt_util.utcnow() + datetime.timedelta( seconds=self._reset_delay_sec) track_point_in_time( self._hass, self._reset_state, self._delay_after) self.schedule_update_ha_state()
def update_emoncms(time): """Send whitelisted entities states reguarly to Emoncms.""" payload_dict = {} for entity_id in whitelist: state = hass.states.get(entity_id) if state is None or state.state in ( STATE_UNKNOWN, '', STATE_UNAVAILABLE): continue try: payload_dict[entity_id] = state_helper.state_as_number( state) except ValueError: continue if len(payload_dict) > 0: payload = "{%s}" % ",".join("{}:{}".format(key, val) for key, val in payload_dict.items()) send_data(conf.get(CONF_URL), conf.get(CONF_API_KEY), str(conf.get(CONF_INPUTNODE)), payload) track_point_in_time(hass, update_emoncms, time + timedelta(seconds=conf.get(CONF_SCAN_INTERVAL)))
def alarm_trigger(self, code=None): if self._trigger_till is None: _LOGGER.info( '%s: triggered',self._name ) self._trigger_till = time.monotonic() + self._trigger_time.total_seconds() self._base.siren_on( duration=self._trigger_time.total_seconds(),volume=self._alarm_volume ) self.async_schedule_update_ha_state() track_point_in_time( self._hass,self.async_update_ha_state, dt_util.utcnow() + self._trigger_time )
def schedule_light_on_sun_rise(entity, old_state, new_state): """The moment sun sets we want to have all the lights on. We will schedule to have each light start after one another and slowly transition in.""" def turn_light_on_before_sunset(light_id): """ Helper function to turn on lights slowly if there are devices home and the light is not on yet. """ if device_tracker.is_on(hass) and not light.is_on(hass, light_id): light.turn_on(hass, light_id, transition=LIGHT_TRANSITION_TIME.seconds, profile=light_profile) def turn_on(light_id): """ Lambda can keep track of function parameters but not local parameters. If we put the lambda directly in the below statement only the last light will be turned on.. """ return lambda now: turn_light_on_before_sunset(light_id) start_point = calc_time_for_light_when_sunset() if start_point: for index, light_id in enumerate(light_ids): track_point_in_time( hass, turn_on(light_id), (start_point + index * LIGHT_TRANSITION_TIME))
def timer(self, nowtime): self.schedule_update_ha_state(True) polling_delta = self.set_polling() nexttime = nowtime + polling_delta _LOGGER.debug("Next updated scheduled for: %s", nexttime) # Setup timer to run again at polling delta track_point_in_time(self.hass, self.timer, nexttime)
def turn_on(self, **kwargs): """Turn the switch on.""" self._on_until = time.monotonic() + self._on_for.total_seconds() self.async_schedule_update_ha_state() track_point_in_time(self.hass, self.async_update_ha_state, dt_util.utcnow() + self._on_for) _LOGGER.debug('turned on')
def update(now=None): # request r = requests.get(url, headers) response = r.content.decode("utf-8") jsonstring = json.loads(response) inner = jsonstring["data"] prayer = inner["timings"] fajr = prayer["Fajr"] sunrise = prayer["Sunrise"] dhuhr = prayer["Dhuhr"] asr = prayer["Asr"] maghrib = prayer["Maghrib"] isha = prayer["Isha"] hass.states.set('Gebedstijden.Fajr', fajr) hass.states.set('Gebedstijden.Sunrise', sunrise) hass.states.set('Gebedstijden.Dhuhr', dhuhr) hass.states.set('Gebedstijden.Asr', asr) hass.states.set('Gebedstijden.Maghrib', maghrib) hass.states.set('Gebedstijden.Isha', isha) # Run again at next (local) midnight. track_point_in_time( hass, update, dt_util.find_next_time_expression_time(dt_util.now(), [0], [0], [0]))
def _handle_code(self, call): """Handle received code by the pilight-daemon. If the code matches the defined payload of this sensor the sensor state is changed accordingly. """ # Check if received code matches defined payload # True if payload is contained in received code dict payload_ok = True for key in self._payload: if key not in call.data: payload_ok = False continue if self._payload[key] != call.data[key]: payload_ok = False # Read out variable if payload ok if payload_ok: if self._variable not in call.data: return value = call.data[self._variable] self._state = value == self._on_value if self._delay_after is None: self._delay_after = dt_util.utcnow() + datetime.timedelta( seconds=self._reset_delay_sec) track_point_in_time(self._hass, self._reset_state, self._delay_after) self.schedule_update_ha_state()
def update_properties(self): """Called when a value for this entity's node has changed.""" self._state = self._value.data # only allow this value to be true for re_arm secs self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time(self._hass, self.async_update_ha_state, self.invalidate_after)
def scheduleReset(self): # get my hard/soft off times self._reset = self.timeStringToDateTime(self._config["reset"]["at"]) _LOGGER.info("reset time is {}".format(self._reset)) track_point_in_time(self._hass, self.resetCheck, self._reset)
def update_properties(self): """Called when a value for this entity's node has changed.""" self._state = self._value.data # only allow this value to be true for re_arm secs self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time( self._hass, self.async_update_ha_state, self.invalidate_after)
def _set_timer_startup_is_done(minutes): """Start a timer for "startup is done".""" point_in_time = datetime.now() + timedelta(minutes=minutes) track_point_in_time( hass, partial(_handle_startup_is_done, ), point_in_time=point_in_time, )
def value_changed(self, value): """ Called when a value has changed on the network. """ if self._value.value_id == value.value_id: self.update_ha_state() if value.data: # only allow this value to be true for 60 secs self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time(self._hass, self.update_ha_state, self.invalidate_after)
def __init__(self, sensor_value, sensor_class, hass, re_arm_sec=60): super(ZWaveTriggerSensor, self).__init__(sensor_value, sensor_class) self._hass = hass self.re_arm_sec = re_arm_sec self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) # If it's active make sure that we set the timeout tracker if sensor_value.data: track_point_in_time(self._hass, self.update_ha_state, self.invalidate_after)
def __init__(self, value, device_class, hass, re_arm_sec=60): """Initialize the sensor.""" super(ZWaveTriggerSensor, self).__init__(value, device_class) self._hass = hass self.re_arm_sec = re_arm_sec self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) # If it's active make sure that we set the timeout tracker track_point_in_time(self._hass, self.async_update_ha_state, self.invalidate_after)
def __init__(self, value, device_class, hass, re_arm_sec=60): """Initialize the sensor.""" super(ZWaveTriggerSensor, self).__init__(value, device_class) self._hass = hass self.re_arm_sec = re_arm_sec self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) # If it's active make sure that we set the timeout tracker track_point_in_time( self._hass, self.async_update_ha_state, self.invalidate_after)
def alarm_arm_away(self, code=None): """Send arm away command.""" if not self._validate_code(code, STATE_ALARM_ARMED_AWAY): return self._state = STATE_ALARM_ARMED_AWAY self._state_ts = dt_util.utcnow() self.update_ha_state() if self._pending_time: track_point_in_time(self._hass, self.async_update_ha_state, self._state_ts + self._pending_time)
def update_properties(self): """Handle value changes for this entity's node.""" self._state = self.values.primary.data # only allow this value to be true for re_arm secs if not self.hass: return self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time(self.hass, self.async_update_ha_state, self.invalidate_after)
def value_changed(self, value): """Called when a value for this entity's node has changed.""" if self._value.value_id == value.value_id: self.schedule_update_ha_state() if value.data: # only allow this value to be true for re_arm secs self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time( self._hass, self.async_update_ha_state, self.invalidate_after)
def __init__(self, sensor_value, sensor_class, hass, re_arm_sec=60): super(ZWaveTriggerSensor, self).__init__(sensor_value, sensor_class) self._hass = hass self.re_arm_sec = re_arm_sec self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) # If it's active make sure that we set the timeout tracker if sensor_value.data: track_point_in_time( self._hass, self.update_ha_state, self.invalidate_after)
def value_changed(self, value): """Called when a value has changed on the network.""" if self._value.value_id == value.value_id: self.schedule_update_ha_state() if value.data: # only allow this value to be true for re_arm secs self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time( self._hass, self.async_update_ha_state, self.invalidate_after)
def request_position_till_stop(self): """Request the position of the blind every UPDATE_INTERVAL_MOVING seconds until it stops moving.""" self._previous_positions = [] if self._requesting_position or self.current_cover_position is None: return self._requesting_position = True track_point_in_time( self.hass, self.async_scheduled_update_request_callback, dt_util.utcnow() + timedelta(seconds=UPDATE_INTERVAL_MOVING), )
def schedule_next_event(self, hass, next_event): """ Schedule the event. """ next_time = self.__get_next_time(next_event) # pylint: disable=unused-argument def execute(now): """ Call the execute method. """ self.execute(hass) track_point_in_time(hass, execute, next_time) return next_time
def _activate(self, on_off): """Turn the switch on.""" if self._toggled == on_off: self._toggle_until = time.monotonic( ) + self._toggle_for.total_seconds() track_point_in_time(self.hass, self.async_update_ha_state, dt_util.utcnow() + self._toggle_for) _LOGGER.debug('turned on') elif self._cancellable: self._toggle_until = None _LOGGER.debug('forced off') self.async_schedule_update_ha_state()
def alarm_arm_away(self, code=None): """Send arm away command.""" if not self._validate_code(code, STATE_ALARM_ARMED_AWAY): return self._state = STATE_ALARM_ARMED_AWAY self._state_ts = dt_util.utcnow() self.update_ha_state() if self._pending_time: track_point_in_time(self._hass, self.update_ha_state, self._state_ts + self._pending_time)
def alarm_arm_night(self, code=None): """Send arm night command.""" if not self._validate_code(code, STATE_ALARM_ARMED_NIGHT): return self._state = STATE_ALARM_ARMED_NIGHT self._state_ts = dt_util.utcnow() self.schedule_update_ha_state() if self._pending_time: track_point_in_time(self._hass, self.async_update_ha_state, self._state_ts + self._pending_time)
def alarm_trigger(self, code=None): """ Send alarm trigger command. No code needed. """ self._state = STATE_ALARM_TRIGGERED self._state_ts = dt_util.utcnow() self.update_ha_state() if self._trigger_time: track_point_in_time(self._hass, self.update_ha_state, self._state_ts + self._pending_time) track_point_in_time( self._hass, self.update_ha_state, self._state_ts + self._pending_time + self._trigger_time)
def alarm_trigger(self, code=None): """Send alarm trigger command. No code needed.""" self._pre_trigger_state = self._state self._state = STATE_ALARM_TRIGGERED self._state_ts = dt_util.utcnow() self.update_ha_state() if self._trigger_time: track_point_in_time(self._hass, self.async_update_ha_state, self._state_ts + self._pending_time) track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + self._pending_time + self._trigger_time )
def half_hour_timer(nowtime): roundedtime = myrates.round_time(nowtime) nexttime = roundedtime + timedelta(minutes=30) hass.states.set("octopusagile.half_hour_timer_nextupdate", nexttime.strftime("%Y-%m-%dT%H:%M:%SZ")) try: if first_run is False: handle_half_hour_timer(None) hass.states.set("octopusagile.half_hour_timer_lastupdate", nowtime.strftime("%Y-%m-%dT%H:%M:%SZ")) except Exception as e: _LOGGER.error(e) # Setup timer to run again in 30 track_point_in_time(hass, half_hour_timer, nexttime)
def update_nothrottle(self, dummy=None): """Update sensor without throttle.""" self._data.update_no_throttle() # Schedule a forced update 15 mintunes in the future if the update above # returned no data for this sensors power number. if not self._data.expired: track_point_in_time( self.hass, self.update_nothrottle, dt_util.now() + MIN_TIME_BETWEEN_FORCED_UPDATES, ) return self.schedule_update_ha_state()
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 update_properties(self): """Handle value changes for this entity's node.""" self._state = self.values.primary.data _LOGGER.debug('off_delay=%s', self.values.off_delay) # Set re_arm_sec if off_delay is provided from the sensor if self.values.off_delay: _LOGGER.debug('off_delay.data=%s', self.values.off_delay.data) self.re_arm_sec = self.values.off_delay.data * 8 # only allow this value to be true for re_arm secs if not self.hass: return self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time(self.hass, self.async_update_ha_state, self.invalidate_after)
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 update(self, *args): """Update the sensor.""" # _LOGGER.warning('In update with: {}'.format(args)) data = scrap_pvpc_current_prices(rate=self.rate, timeout=self._timeout) if data: date, prices = data if args: now = args[0] else: now = dt_util.now() today = now.date() if today < date: _LOGGER.warning("Setting tomorrow (%s) prices: %s", date.strftime('%Y-%m-%d'), str(prices)) self._tomorrow_prices = prices elif today == date: _LOGGER.debug("Updating today prices: %s", str(prices)) self._today_prices = prices else: _LOGGER.error("Bad date scrapping data? '%s', prices: %s", date.strftime('%Y-%m-%d'), str(prices)) self._tomorrow_prices = None if self._today_prices is not None: self._state = self._today_prices[now.hour] # self._attributes[ATTR_TODAY_PRICES] = self._today_prices for i, p in enumerate(self._today_prices): key = ATTR_PRICE + ' {:02d}h'.format(i) self._attributes[key] = p _LOGGER.info("Price at %dh: %.5f €/kWh", now.hour, self._state) if self._tomorrow_prices is not None: self._attributes[ATTR_TOMORROW_PRICES] = self._tomorrow_prices elif ATTR_TOMORROW_PRICES in self._attributes: self._attributes.pop(ATTR_TOMORROW_PRICES) elif self._today_prices is not None: now = dt_util.now() self._state = self._today_prices[now.hour] else: self._state = None _LOGGER.warning("Trying to update later, after %d seconds", self._timeout) track_point_in_time( self.hass, self.update, dt_util.now() + timedelta(seconds=3 * self._timeout)) self.schedule_update_ha_state(False)
def check_thermostat_change(self, entity, old_state, new_state): # pylint: disable=too-many-branches,too-many-statements,too-many-locals """ Function to handle a manual thermostat change """ _LOGGER.error('start: thermostat change triggered') # skip thermostat changes triggered by thermostat_control if self.change_triggered_by_ha == 1: self.change_triggered_by_ha = 0 self.update_ha_state() _LOGGER.error('ignore: change triggered by HA') return # state not changed if new_state.attributes['away_mode'] == 'on': _LOGGER.error('ignore: away mode is on') return # state not changed if old_state.state == new_state.state: _LOGGER.error('ignore: no change in thermostat value') return # state is not set at startup if new_state.state == 'not set': _LOGGER.error('ignore: thermostat state not set') return # setup the thermostat trigger to reset back after duration reset_time = dt_util.utcnow() + dt.timedelta(hours=1) track_point_in_time(self.hass, self.reset_override, reset_time) _LOGGER.error('override trigger added: %s', reset_time) # manual thermostat change overrides all settings reset_time = (str(reset_time.hour).zfill(2) + ':' + str(reset_time.minute).zfill(2)) self.manual_override = 'on' self.manual_override_end = reset_time self.set_temp = new_state.state self.update_ha_state() # thermostat change not required as manually set _LOGGER.error('end: thermostat change complete reset: %s set_temp: %s', reset_time, new_state.state)
def update_properties(self): """Handle value changes for this entity's node.""" self._state = self.values.primary.data _LOGGER.debug('off_delay=%s', self.values.off_delay) # Set re_arm_sec if off_delay is provided from the sensor if self.values.off_delay: _LOGGER.debug('off_delay.data=%s', self.values.off_delay.data) self.re_arm_sec = self.values.off_delay.data * 8 # only allow this value to be true for re_arm secs if not self.hass: return self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) track_point_in_time( self.hass, self.async_update_ha_state, self.invalidate_after)
def update_nothrottle(self, dummy=None): """Update sensor without throttle.""" self._data.update_no_throttle() # Schedule a forced update 5 seconds in the future if the update above # returned no data for this sensors email. This is mainly to make sure # that we don't get HTTP Error "too many requests" and to have initial # data after hass startup once we have the data it will update as # normal using update if self._email not in self._data.data: track_point_in_time( self.hass, self.update_nothrottle, dt_util.now() + MIN_TIME_BETWEEN_FORCED_UPDATES) return self._state = len(self._data.data[self._email]) self.schedule_update_ha_state()
def test_track_point_in_time(self): """Test track point in time.""" before_birthday = datetime(1985, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) birthday_paulus = datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) after_birthday = datetime(1987, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) runs = [] track_point_in_utc_time( self.hass, callback(lambda x: runs.append(1)), birthday_paulus) self._send_time_changed(before_birthday) self.hass.block_till_done() assert 0 == len(runs) self._send_time_changed(birthday_paulus) self.hass.block_till_done() assert 1 == len(runs) # A point in time tracker will only fire once, this should do nothing self._send_time_changed(birthday_paulus) self.hass.block_till_done() assert 1 == len(runs) track_point_in_time( self.hass, callback(lambda x: runs.append(1)), birthday_paulus) self._send_time_changed(after_birthday) self.hass.block_till_done() assert 2 == len(runs) unsub = track_point_in_time( self.hass, callback(lambda x: runs.append(1)), birthday_paulus) unsub() self._send_time_changed(after_birthday) self.hass.block_till_done() assert 2 == len(runs)
def schedule(self, hass): """ Schedule this event so that it will be called. """ next_time = dt_util.now().replace( hour=self.hour, minute=self.minute, second=self.second) # Calculate the next time the event should be executed. # That is the next day that the schedule is configured to run while next_time < dt_util.now() or \ next_time.weekday() not in self.my_schedule.days: next_time = next_time + timedelta(days=1) # pylint: disable=unused-argument def execute(now): """ Call the execute method """ self.execute(hass) track_point_in_time(hass, execute, next_time) _LOGGER.info( 'TimeEventListener scheduled for %s, will call service %s.%s', next_time, self.domain, self.service)
def _execute_until_done(self): """ Executes a sequence of actions until finished or until a delay is encountered. If a delay action is encountered, the script registers itself to be called again in the future, when _execute_until_done will resume. Returns True if finished, False otherwise. """ for action in self.actions: if CONF_SERVICE in action: self._call_service(action) elif CONF_DELAY in action: delay = timedelta(**action[CONF_DELAY]) point_in_time = date_util.now() + delay self.listener = track_point_in_time( self.hass, self, point_in_time) return False return True
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)
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)
def _update_state(self, state): self._state = state self._state_ts = dt_util.utcnow() self.schedule_update_ha_state() pending_time = self._pending_time_by_state[state] if state == STATE_ALARM_TRIGGERED and self._trigger_time: track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time) track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + self._trigger_time + pending_time) elif state in SUPPORTED_PENDING_STATES and pending_time: track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time)
def _update_state(self, state): """Update the state.""" if self._state == state: return self._previous_state = self._state self._state = state self._state_ts = dt_util.utcnow() self.schedule_update_ha_state() pending_time = self._pending_time(state) if state == STATE_ALARM_TRIGGERED: track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time) trigger_time = self._trigger_time_by_state[self._previous_state] track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time + trigger_time) elif state in SUPPORTED_PENDING_STATES and pending_time: track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time)
def binary_sensor_update(event): """Call for control updates from the RFXtrx gateway.""" if not isinstance(event, rfxtrxmod.ControlEvent): return device_id = slugify(event.device.id_string.lower()) if device_id in rfxtrx.RFX_DEVICES: sensor = rfxtrx.RFX_DEVICES[device_id] else: sensor = rfxtrx.get_pt2262_device(device_id) if sensor is None: # Add the entity if not exists and automatic_add is True if not config[CONF_AUTOMATIC_ADD]: return if event.device.packettype == 0x13: poss_dev = rfxtrx.find_possible_pt2262_device(device_id) if poss_dev is not None: poss_id = slugify(poss_dev.event.device.id_string.lower()) _LOGGER.debug( "Found possible matching device ID: %s", poss_id) pkt_id = "".join("{0:02x}".format(x) for x in event.data) sensor = RfxtrxBinarySensor(event, pkt_id) sensor.hass = hass rfxtrx.RFX_DEVICES[device_id] = sensor add_devices([sensor]) _LOGGER.info( "Added binary sensor %s (Device ID: %s Class: %s Sub: %s)", pkt_id, slugify(event.device.id_string.lower()), event.device.__class__.__name__, event.device.subtype) elif not isinstance(sensor, RfxtrxBinarySensor): return else: _LOGGER.debug( "Binary sensor update (Device ID: %s Class: %s Sub: %s)", slugify(event.device.id_string.lower()), event.device.__class__.__name__, event.device.subtype) if sensor.is_lighting4: if sensor.data_bits is not None: cmd = rfxtrx.get_pt2262_cmd(device_id, sensor.data_bits) sensor.apply_cmd(int(cmd, 16)) else: sensor.update_state(True) else: rfxtrx.apply_received_command(event) if (sensor.is_on and sensor.off_delay is not None and sensor.delay_listener is None): def off_delay_listener(now): """Switch device off after a delay.""" sensor.delay_listener = None sensor.update_state(False) sensor.delay_listener = evt.track_point_in_time( hass, off_delay_listener, dt_util.utcnow() + sensor.off_delay)