mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Code cleanup and new sun set transition
This commit is contained in:
parent
9732bf99ac
commit
5f4ddfe92c
@ -9,8 +9,7 @@ STATE_DEVICE_DEFAULT = STATE_DEVICE_NOT_HOME
|
||||
|
||||
# After how much time do we consider a device not home if
|
||||
# it does not show up on scans
|
||||
# 70 seconds is to ensure 2 scans
|
||||
TIME_SPAN_FOR_ERROR_IN_SCANNING = timedelta(seconds=70)
|
||||
TIME_SPAN_FOR_ERROR_IN_SCANNING = timedelta(seconds=60)
|
||||
|
||||
STATE_CATEGORY_ALL_DEVICES = 'device.alldevices'
|
||||
STATE_CATEGORY_DEVICE_FORMAT = 'device.{}'
|
||||
@ -27,9 +26,9 @@ class DeviceTracker(object):
|
||||
temp_devices_to_track = device_scanner.get_devices_to_track()
|
||||
|
||||
self.devices_to_track = { device: { 'name': temp_devices_to_track[device],
|
||||
'last_seen': default_last_seen,
|
||||
'category': STATE_CATEGORY_DEVICE_FORMAT.format(temp_devices_to_track[device]) }
|
||||
for device in temp_devices_to_track }
|
||||
'last_seen': default_last_seen,
|
||||
'category': STATE_CATEGORY_DEVICE_FORMAT.format(temp_devices_to_track[device]) }
|
||||
for device in temp_devices_to_track }
|
||||
|
||||
# Add categories to state machine
|
||||
statemachine.add_category(STATE_CATEGORY_ALL_DEVICES, STATE_DEVICE_DEFAULT)
|
||||
@ -41,8 +40,7 @@ class DeviceTracker(object):
|
||||
|
||||
|
||||
def device_state_categories(self):
|
||||
for device in self.devices_to_track:
|
||||
yield self.devices_to_track[device]['category']
|
||||
return [self.devices_to_track[device]['category'] for device in self.devices_to_track]
|
||||
|
||||
|
||||
def set_state(self, device, state):
|
||||
@ -53,7 +51,8 @@ class DeviceTracker(object):
|
||||
|
||||
|
||||
def update_devices(self, found_devices):
|
||||
# Keep track of devices that are home, all that are not will be marked not home
|
||||
"""Keep track of devices that are home, all that are not will be marked not home"""
|
||||
|
||||
temp_tracking_devices = self.devices_to_track.keys()
|
||||
|
||||
for device in found_devices:
|
||||
@ -71,7 +70,7 @@ class DeviceTracker(object):
|
||||
if datetime.now() - self.devices_to_track[device]['last_seen'] > TIME_SPAN_FOR_ERROR_IN_SCANNING:
|
||||
self.set_state(device, STATE_DEVICE_NOT_HOME)
|
||||
|
||||
# Get the set of currently used statuses
|
||||
# Get the currently used statuses
|
||||
states_of_devices = [self.statemachine.get_state(self.devices_to_track[device]['category']).state for device in self.devices_to_track]
|
||||
|
||||
all_devices_state = STATE_DEVICE_HOME if STATE_DEVICE_HOME in states_of_devices else STATE_DEVICE_NOT_HOME
|
||||
|
@ -33,14 +33,18 @@ class StateMachine(object):
|
||||
|
||||
self.lock.release()
|
||||
|
||||
def is_state(self, category, state):
|
||||
assert category in self.states, "Category does not exist: {}".format(category)
|
||||
|
||||
return self.get_state(category).state == state
|
||||
|
||||
def get_state(self, category):
|
||||
assert category in self.states, "Category does not exist: {}".format(category)
|
||||
|
||||
return self.states[category]
|
||||
|
||||
def get_states(self):
|
||||
for category in sorted(self.states.keys()):
|
||||
yield category, self.states[category].state, self.states[category].last_changed
|
||||
return [(category, self.states[category].state, self.states[category].last_changed) for category in sorted(self.states.keys())]
|
||||
|
||||
|
||||
def track_state_change(eventbus, category, from_state, to_state, action):
|
||||
|
@ -1,5 +1,5 @@
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
|
||||
from phue import Bridge
|
||||
|
||||
@ -10,6 +10,9 @@ from app.observer.Timer import track_time_change
|
||||
|
||||
LIGHTS_TURNING_ON_BEFORE_SUN_SET_PERIOD = timedelta(minutes=15)
|
||||
|
||||
LIGHT_TRANSITION_TIME_HUE = 9000 # 1/10th seconds
|
||||
LIGHT_TRANSITION_TIME = timedelta(seconds=LIGHT_TRANSITION_TIME_HUE/10)
|
||||
|
||||
class HueTrigger(object):
|
||||
def __init__(self, config, eventbus, statemachine, device_tracker, weather):
|
||||
self.eventbus = eventbus
|
||||
@ -31,57 +34,63 @@ class HueTrigger(object):
|
||||
track_state_change(eventbus, STATE_CATEGORY_SUN, SUN_STATE_BELOW_HORIZON, SUN_STATE_ABOVE_HORIZON, self.handle_sun_rising)
|
||||
|
||||
# If the sun is already above horizon schedule the time-based pre-sun set event
|
||||
if statemachine.get_state(STATE_CATEGORY_SUN).state == SUN_STATE_ABOVE_HORIZON:
|
||||
if statemachine.is_state(STATE_CATEGORY_SUN, SUN_STATE_ABOVE_HORIZON):
|
||||
self.handle_sun_rising(None, None, None)
|
||||
|
||||
|
||||
def get_lights_status(self):
|
||||
lights_are_on = sum([1 for light in self.lights if light.on]) > 0
|
||||
|
||||
light_needed = not lights_are_on and self.statemachine.get_state(STATE_CATEGORY_SUN).state == SUN_STATE_BELOW_HORIZON
|
||||
light_needed = not lights_are_on and self.statemachine.is_state(STATE_CATEGORY_SUN, SUN_STATE_BELOW_HORIZON)
|
||||
|
||||
return lights_are_on, light_needed
|
||||
|
||||
def turn_light_on(self, light_id=None, transitiontime=None):
|
||||
if light_id is None:
|
||||
light_id = [light.light_id for light in self.lights]
|
||||
|
||||
def turn_lights_on(self, transitiontime=None):
|
||||
command = {'on': True, 'xy': [0.5119, 0.4147], 'bri':164}
|
||||
|
||||
if transitiontime is not None:
|
||||
command['transitiontime'] = transitiontime
|
||||
|
||||
self.bridge.set_light([1, 2, 3], command)
|
||||
self.bridge.set_light(light_id, command)
|
||||
|
||||
|
||||
def turn_lights_off(self, transitiontime=None):
|
||||
def turn_light_off(self, light_id=None, transitiontime=None):
|
||||
if light_id is None:
|
||||
light_id = [light.light_id for light in self.lights]
|
||||
|
||||
command = {'on': False}
|
||||
|
||||
if transitiontime is not None:
|
||||
command['transitiontime'] = transitiontime
|
||||
|
||||
self.bridge.set_light([1, 2, 3], command)
|
||||
self.bridge.set_light(light_id, command)
|
||||
|
||||
|
||||
def handle_sun_rising(self, category, old_state, new_state):
|
||||
# Schedule an event X minutes prior to sun setting
|
||||
point_in_time = self.weather.next_sun_setting()-LIGHTS_TURNING_ON_BEFORE_SUN_SET_PERIOD
|
||||
"""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."""
|
||||
|
||||
self.logger.info("Will put lights on at {} to compensate less light from setting sun.".format(point_in_time))
|
||||
start_point = self.weather.next_sun_setting() - LIGHT_TRANSITION_TIME * len(self.lights)
|
||||
|
||||
track_time_change(self.eventbus, self.handle_sun_setting, point_in_time=point_in_time)
|
||||
# Lambda can keep track of function parameters, not from local parameters
|
||||
# If we put the lambda directly in the below statement only the last light
|
||||
# would be turned on..
|
||||
def turn_on(light_id):
|
||||
return lambda now: self.turn_light_on_before_sunset(light_id)
|
||||
|
||||
for index, light in enumerate(self.lights):
|
||||
track_time_change(self.eventbus, turn_on(light.light_id),
|
||||
point_in_time=start_point + index * LIGHT_TRANSITION_TIME)
|
||||
|
||||
|
||||
# Gets called when darkness starts falling in, slowly turn on the lights
|
||||
def handle_sun_setting(self, now):
|
||||
lights_are_on, light_needed = self.get_lights_status()
|
||||
|
||||
if not lights_are_on and self.statemachine.get_state(STATE_CATEGORY_ALL_DEVICES).state == STATE_DEVICE_HOME:
|
||||
self.logger.info("Sun setting and devices home. Turning on lights.")
|
||||
|
||||
# We will start the lights now and by the time the sun sets
|
||||
# the lights will be at full brightness
|
||||
transitiontime = (self.weather.next_sun_setting() - datetime.now()).seconds * 10
|
||||
|
||||
self.turn_lights_on(transitiontime)
|
||||
def turn_light_on_before_sunset(self, light_id=None):
|
||||
"""Helper function to turn on lights slowly if there are devices home and the light is not on yet."""
|
||||
if self.statemachine.is_state(STATE_CATEGORY_ALL_DEVICES, STATE_DEVICE_HOME) and not self.bridge.get_light(light_id, 'on'):
|
||||
self.turn_light_on(light_id, LIGHT_TRANSITION_TIME_HUE)
|
||||
|
||||
|
||||
def handle_device_state_change(self, category, old_state, new_state):
|
||||
@ -90,9 +99,9 @@ class HueTrigger(object):
|
||||
# Specific device came home ?
|
||||
if category != STATE_CATEGORY_ALL_DEVICES and new_state.state == STATE_DEVICE_HOME and light_needed:
|
||||
self.logger.info("Home coming event for {}. Turning lights on".format(category))
|
||||
self.turn_lights_on()
|
||||
self.turn_light_on()
|
||||
|
||||
# Did all devices leave the house?
|
||||
elif category == STATE_CATEGORY_ALL_DEVICES and new_state.state == STATE_DEVICE_NOT_HOME and lights_are_on:
|
||||
self.logger.info("Everyone has left. Turning lights off")
|
||||
self.turn_lights_off()
|
||||
self.turn_light_off()
|
||||
|
@ -39,7 +39,7 @@ class Timer(threading.Thread):
|
||||
break
|
||||
|
||||
|
||||
def track_time_change(eventBus, action, year='*', month='*', day='*', hour='*', minute='*', second='*', point_in_time=None, listen_once=False):
|
||||
def track_time_change(eventbus, action, year='*', month='*', day='*', hour='*', minute='*', second='*', point_in_time=None, listen_once=False):
|
||||
year, month, day = ensure_list(year), ensure_list(month), ensure_list(day)
|
||||
hour, minute, second = ensure_list(hour), ensure_list(minute), ensure_list(second)
|
||||
|
||||
@ -60,4 +60,4 @@ def track_time_change(eventBus, action, year='*', month='*', day='*', hour='*',
|
||||
|
||||
action(event.data['now'])
|
||||
|
||||
eventBus.listen(EVENT_TIME_CHANGED, listener)
|
||||
eventbus.listen(EVENT_TIME_CHANGED, listener)
|
||||
|
Loading…
x
Reference in New Issue
Block a user