mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Cleaning up code
This commit is contained in:
parent
90c343d16b
commit
7636092c7d
@ -16,12 +16,11 @@ STATE_CATEGORY_ALL_DEVICES = 'device.alldevices'
|
||||
STATE_CATEGORY_DEVICE_FORMAT = 'device.{}'
|
||||
|
||||
|
||||
class DeviceTracker:
|
||||
class DeviceTracker(object):
|
||||
|
||||
def __init__(self, eventbus, statemachine, device_scanner):
|
||||
self.statemachine = statemachine
|
||||
self.eventbus = eventbus
|
||||
self.device_scanner = device_scanner
|
||||
|
||||
default_last_seen = datetime(1990, 1, 1)
|
||||
|
||||
@ -32,8 +31,6 @@ class DeviceTracker:
|
||||
'category': STATE_CATEGORY_DEVICE_FORMAT.format(temp_devices_to_track[device]) }
|
||||
for device in temp_devices_to_track }
|
||||
|
||||
self.all_devices_state = STATE_DEVICE_DEFAULT
|
||||
|
||||
# Add categories to state machine
|
||||
statemachine.add_category(STATE_CATEGORY_ALL_DEVICES, STATE_DEVICE_DEFAULT)
|
||||
|
||||
@ -71,15 +68,12 @@ class DeviceTracker:
|
||||
# Because we do not want to have stuff happening when the device does
|
||||
# not show up for 1 scan beacuse of reboot etc
|
||||
for device in temp_tracking_devices:
|
||||
if self.statemachine.get_state(self.devices_to_track[device]['category']).state == STATE_DEVICE_HOME and \
|
||||
datetime.now() - self.devices_to_track[device]['last_seen'] > TIME_SPAN_FOR_ERROR_IN_SCANNING:
|
||||
|
||||
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
|
||||
states_of_devices = [self.statemachine.get_state(self.devices_to_track[device]['category']).state for device in self.devices_to_track]
|
||||
|
||||
self.all_devices_state = STATE_DEVICE_HOME if STATE_DEVICE_HOME in states_of_devices else STATE_DEVICE_NOT_HOME
|
||||
all_devices_state = STATE_DEVICE_HOME if STATE_DEVICE_HOME in states_of_devices else STATE_DEVICE_NOT_HOME
|
||||
|
||||
self.statemachine.set_state(STATE_CATEGORY_ALL_DEVICES, self.all_devices_state)
|
||||
self.statemachine.set_state(STATE_CATEGORY_ALL_DEVICES, all_devices_state)
|
||||
|
@ -6,11 +6,11 @@ from threading import Thread, RLock
|
||||
|
||||
ALL_EVENTS = '*'
|
||||
|
||||
class EventBus:
|
||||
class EventBus(object):
|
||||
def __init__(self):
|
||||
self.listeners = defaultdict(list)
|
||||
self.lock = RLock()
|
||||
self.logger =logging.getLogger(__name__)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def fire(self, event):
|
||||
assert isinstance(event, Event), "event needs to be an instance of Event"
|
||||
@ -21,21 +21,21 @@ class EventBus:
|
||||
def run():
|
||||
self.lock.acquire()
|
||||
|
||||
self.logger.info("{} event received: {}".format(event.eventType, event.data))
|
||||
self.logger.info("{} event received: {}".format(event.event_type, event.data))
|
||||
|
||||
for callback in chain(self.listeners[ALL_EVENTS], self.listeners[event.eventType]):
|
||||
for callback in chain(self.listeners[ALL_EVENTS], self.listeners[event.event_type]):
|
||||
callback(event)
|
||||
|
||||
if event.removeListener:
|
||||
if event.remove_listener:
|
||||
if callback in self.listeners[ALL_EVENTS]:
|
||||
self.listeners[ALL_EVENTS].remove(callback)
|
||||
|
||||
if callback in self.listeners[event.eventType]:
|
||||
self.listeners[event.eventType].remove(callback)
|
||||
if callback in self.listeners[event.event_type]:
|
||||
self.listeners[event.event_type].remove(callback)
|
||||
|
||||
event.removeListener = False
|
||||
event.remove_listener = False
|
||||
|
||||
if event.stopPropegating:
|
||||
if event.stop_propegating:
|
||||
break
|
||||
|
||||
self.lock.release()
|
||||
@ -52,13 +52,12 @@ class EventBus:
|
||||
self.lock.release()
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self, eventType, data):
|
||||
self.eventType = eventType
|
||||
class Event(object):
|
||||
def __init__(self, event_type, data):
|
||||
self.event_type = event_type
|
||||
self.data = data
|
||||
self.stopPropegating = False
|
||||
self.removeListener = False
|
||||
self.stop_propegating = False
|
||||
self.remove_listener = False
|
||||
|
||||
def __str__(self):
|
||||
return str([self.eventType, self.data])
|
||||
|
||||
return str([self.event_type, self.data])
|
||||
|
@ -4,15 +4,14 @@ import time
|
||||
from app.StateMachine import StateMachine
|
||||
from app.EventBus import EventBus
|
||||
from app.DeviceTracker import DeviceTracker
|
||||
from HttpInterface import HttpInterface
|
||||
from app.HttpInterface import HttpInterface
|
||||
|
||||
from app.observer.WeatherWatcher import WeatherWatcher
|
||||
from app.observer.TomatoDeviceScanner import TomatoDeviceScanner
|
||||
from app.observer.Timer import Timer
|
||||
|
||||
from app.actor.HueTrigger import HueTrigger
|
||||
|
||||
class HomeAssistant:
|
||||
class HomeAssistant(object):
|
||||
|
||||
def __init__(self):
|
||||
self.config = None
|
||||
@ -90,7 +89,7 @@ class HomeAssistant:
|
||||
try:
|
||||
time.sleep(1)
|
||||
|
||||
except:
|
||||
except KeyboardInterrupt:
|
||||
print ""
|
||||
print "Interrupt received. Wrapping up and quiting.."
|
||||
self.timer.stop()
|
||||
@ -99,8 +98,3 @@ class HomeAssistant:
|
||||
self.httpinterface.stop()
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ import requests
|
||||
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
SERVER_HOST= '127.0.0.1'
|
||||
SERVER_HOST = '127.0.0.1'
|
||||
SERVER_PORT = 8080
|
||||
|
||||
class RequestHandler(BaseHTTPRequestHandler):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from collections import defaultdict, namedtuple
|
||||
from collections import namedtuple
|
||||
from threading import RLock
|
||||
from datetime import datetime
|
||||
|
||||
@ -7,29 +7,29 @@ from app.util import ensure_list, matcher
|
||||
|
||||
EVENT_STATE_CHANGED = "state_changed"
|
||||
|
||||
state = namedtuple("State", ['state','last_changed'])
|
||||
State = namedtuple("State", ['state','last_changed'])
|
||||
|
||||
class StateMachine:
|
||||
class StateMachine(object):
|
||||
|
||||
def __init__(self, eventBus):
|
||||
def __init__(self, eventbus):
|
||||
self.states = dict()
|
||||
self.eventBus = eventBus
|
||||
self.eventbus = eventbus
|
||||
self.lock = RLock()
|
||||
|
||||
def add_category(self, category, initialState):
|
||||
self.states[category] = state(initialState, datetime.now())
|
||||
def add_category(self, category, initial_state):
|
||||
self.states[category] = State(initial_state, datetime.now())
|
||||
|
||||
def set_state(self, category, newState):
|
||||
def set_state(self, category, new_state):
|
||||
self.lock.acquire()
|
||||
|
||||
assert category in self.states, "Category does not exist: {}".format(category)
|
||||
|
||||
oldState = self.states[category]
|
||||
old_state = self.states[category]
|
||||
|
||||
if oldState.state != newState:
|
||||
self.states[category] = state(newState, datetime.now())
|
||||
if old_state.state != new_state:
|
||||
self.states[category] = State(new_state, datetime.now())
|
||||
|
||||
self.eventBus.fire(Event(EVENT_STATE_CHANGED, {'category':category, 'oldState':oldState, 'newState':self.states[category]}))
|
||||
self.eventbus.fire(Event(EVENT_STATE_CHANGED, {'category':category, 'old_state':old_state, 'new_state':self.states[category]}))
|
||||
|
||||
self.lock.release()
|
||||
|
||||
@ -43,18 +43,17 @@ class StateMachine:
|
||||
yield category, self.states[category].state, self.states[category].last_changed
|
||||
|
||||
|
||||
def track_state_change(eventBus, category, fromState, toState, action):
|
||||
fromState = ensure_list(fromState)
|
||||
toState = ensure_list(toState)
|
||||
def track_state_change(eventbus, category, from_state, to_state, action):
|
||||
from_state = ensure_list(from_state)
|
||||
to_state = ensure_list(to_state)
|
||||
|
||||
def listener(event):
|
||||
assert isinstance(event, Event), "event needs to be of Event type"
|
||||
|
||||
if category == event.data['category'] and \
|
||||
matcher(event.data['oldState'].state, fromState) and \
|
||||
matcher(event.data['newState'].state, toState):
|
||||
matcher(event.data['old_state'].state, from_state) and \
|
||||
matcher(event.data['new_state'].state, to_state):
|
||||
|
||||
action(event.data['category'], event.data['oldState'], event.data['newState'])
|
||||
|
||||
eventBus.listen(EVENT_STATE_CHANGED, listener)
|
||||
action(event.data['category'], event.data['old_state'], event.data['new_state'])
|
||||
|
||||
eventbus.listen(EVENT_STATE_CHANGED, listener)
|
||||
|
@ -10,7 +10,7 @@ from app.observer.Timer import track_time_change
|
||||
|
||||
LIGHTS_TURNING_ON_BEFORE_SUN_SET_PERIOD = timedelta(minutes=30)
|
||||
|
||||
class HueTrigger:
|
||||
class HueTrigger(object):
|
||||
def __init__(self, config, eventbus, statemachine, device_tracker, weather):
|
||||
self.eventbus = eventbus
|
||||
self.statemachine = statemachine
|
||||
@ -49,7 +49,7 @@ class HueTrigger:
|
||||
if transitiontime is not None:
|
||||
command['transitiontime'] = transitiontime
|
||||
|
||||
self.bridge.set_light([1,2,3], command)
|
||||
self.bridge.set_light([1, 2, 3], command)
|
||||
|
||||
|
||||
def turn_lights_off(self, transitiontime=None):
|
||||
@ -58,12 +58,12 @@ class HueTrigger:
|
||||
if transitiontime is not None:
|
||||
command['transitiontime'] = transitiontime
|
||||
|
||||
self.bridge.set_light([1,2,3], command)
|
||||
self.bridge.set_light([1, 2, 3], command)
|
||||
|
||||
|
||||
def handle_sun_rising(self, category, oldState, newState):
|
||||
def handle_sun_rising(self, category, old_state, new_state):
|
||||
# Schedule an event X minutes prior to sun setting
|
||||
track_time_change(self.eventbus, self.handle_sun_setting, datetime=self.weather.next_sun_setting()-LIGHTS_TURNING_ON_BEFORE_SUN_SET_PERIOD)
|
||||
track_time_change(self.eventbus, self.handle_sun_setting, point_in_time=self.weather.next_sun_setting()-LIGHTS_TURNING_ON_BEFORE_SUN_SET_PERIOD)
|
||||
|
||||
|
||||
# Gets called when darkness starts falling in, slowly turn on the lights
|
||||
@ -80,17 +80,15 @@ class HueTrigger:
|
||||
self.turn_lights_on(transitiontime)
|
||||
|
||||
|
||||
def handle_device_state_change(self, category, oldState, newState):
|
||||
def handle_device_state_change(self, category, old_state, new_state):
|
||||
lights_are_on, light_needed = self.get_lights_status()
|
||||
|
||||
# Specific device came home ?
|
||||
if category != STATE_CATEGORY_ALL_DEVICES and newState.state == STATE_DEVICE_HOME and light_needed:
|
||||
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()
|
||||
|
||||
# Did all devices leave the house?
|
||||
elif category == STATE_CATEGORY_ALL_DEVICES and newState.state == STATE_DEVICE_NOT_HOME and lights_are_on:
|
||||
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()
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
import threading
|
||||
import time
|
||||
|
||||
@ -39,15 +39,15 @@ class Timer(threading.Thread):
|
||||
break
|
||||
|
||||
|
||||
def track_time_change(eventBus, action, year='*', month='*', day='*', hour='*', minute='*', second='*', datetime=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)
|
||||
|
||||
def listener(event):
|
||||
assert isinstance(event, Event), "event needs to be of Event type"
|
||||
|
||||
if (datetime is not None and event.data['now'] > datetime) or \
|
||||
datetime is None and \
|
||||
if (point_in_time is not None and event.data['now'] > point_in_time) or \
|
||||
point_in_time is None and \
|
||||
matcher(event.data['now'].year, year) and \
|
||||
matcher(event.data['now'].month, month) and \
|
||||
matcher(event.data['now'].day, day) and \
|
||||
@ -55,10 +55,9 @@ def track_time_change(eventBus, action, year='*', month='*', day='*', hour='*',
|
||||
matcher(event.data['now'].minute, minute) and \
|
||||
matcher(event.data['now'].second, second):
|
||||
|
||||
# datetime are exact points in time so we always remove it after fire
|
||||
event.removeListener = listen_once or datetime is not None
|
||||
# point_in_time are exact points in time so we always remove it after fire
|
||||
event.remove_listener = listen_once or point_in_time is not None
|
||||
|
||||
action(event.data['now'])
|
||||
|
||||
eventBus.listen(EVENT_TIME_CHANGED, listener)
|
||||
|
||||
|
@ -10,7 +10,7 @@ MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
|
||||
|
||||
KNOWN_DEVICES_FILE = "tomato_known_devices.csv"
|
||||
|
||||
class TomatoDeviceScanner:
|
||||
class TomatoDeviceScanner(object):
|
||||
# self.logger
|
||||
|
||||
def __init__(self, config):
|
||||
@ -39,7 +39,8 @@ class TomatoDeviceScanner:
|
||||
# Create a dict with ID: NAME of the devices to track
|
||||
self.devices_to_track = dict()
|
||||
|
||||
for mac in [mac for mac in known_devices if known_devices[mac]['track'] == '1']:
|
||||
for mac in known_devices:
|
||||
if known_devices[mac]['track'] == '1':
|
||||
self.devices_to_track[mac] = known_devices[mac]['name']
|
||||
|
||||
# Quicker way of the previous statement but it doesn't go together with exec:
|
||||
@ -63,7 +64,7 @@ class TomatoDeviceScanner:
|
||||
|
||||
self.last_results = [mac for iface, mac, rssi, tx, rx, quality, unknown_num in wldev]
|
||||
|
||||
except:
|
||||
except Exception:
|
||||
self.logger.exception("Scanning failed")
|
||||
|
||||
|
||||
@ -72,11 +73,11 @@ class TomatoDeviceScanner:
|
||||
|
||||
def tomato_request(self, action):
|
||||
# Get router info
|
||||
r = requests.post('http://{}/update.cgi'.format(self.config.get('tomato','host')),
|
||||
req = requests.post('http://{}/update.cgi'.format(self.config.get('tomato','host')),
|
||||
data={'_http_id':self.config.get('tomato','http_id'), 'exec':action},
|
||||
auth=requests.auth.HTTPBasicAuth(self.config.get('tomato','username'), self.config.get('tomato','password')))
|
||||
|
||||
return r.text
|
||||
return req.text
|
||||
|
||||
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
|
||||
import ephem
|
||||
|
||||
from app.EventBus import Event
|
||||
|
||||
from app.observer.Timer import track_time_change
|
||||
|
||||
STATE_CATEGORY_SUN = "weather.sun"
|
||||
@ -12,7 +10,7 @@ STATE_CATEGORY_SUN = "weather.sun"
|
||||
SUN_STATE_ABOVE_HORIZON = "above_horizon"
|
||||
SUN_STATE_BELOW_HORIZON = "below_horizon"
|
||||
|
||||
class WeatherWatcher:
|
||||
class WeatherWatcher(object):
|
||||
def __init__(self, config, eventbus, statemachine):
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.config = config
|
||||
@ -52,6 +50,4 @@ class WeatherWatcher:
|
||||
self.statemachine.set_state(STATE_CATEGORY_SUN, new_state)
|
||||
|
||||
# +10 seconds to be sure that the change has occured
|
||||
track_time_change(self.eventbus, self.update_sun_state, datetime=next_change + timedelta(seconds=10))
|
||||
|
||||
|
||||
track_time_change(self.eventbus, self.update_sun_state, point_in_time=next_change + timedelta(seconds=10))
|
||||
|
Loading…
x
Reference in New Issue
Block a user