mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Cleaned up the core.
This commit is contained in:
parent
f1042cd136
commit
71bd03ed8c
@ -13,6 +13,8 @@ from collections import defaultdict, namedtuple
|
|||||||
from itertools import chain
|
from itertools import chain
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
ALL_EVENTS = '*'
|
ALL_EVENTS = '*'
|
||||||
EVENT_START = "start"
|
EVENT_START = "start"
|
||||||
EVENT_SHUTDOWN = "shutdown"
|
EVENT_SHUTDOWN = "shutdown"
|
||||||
@ -32,7 +34,7 @@ def start_home_assistant(eventbus):
|
|||||||
""" Start home assistant. """
|
""" Start home assistant. """
|
||||||
Timer(eventbus)
|
Timer(eventbus)
|
||||||
|
|
||||||
eventbus.fire(Event(EVENT_START))
|
eventbus.fire(EVENT_START)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@ -40,7 +42,7 @@ def start_home_assistant(eventbus):
|
|||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print ""
|
print ""
|
||||||
eventbus.fire(Event(EVENT_SHUTDOWN))
|
eventbus.fire(EVENT_SHUTDOWN)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -62,8 +64,6 @@ def track_state_change(eventbus, category, from_state, to_state, action):
|
|||||||
|
|
||||||
def listener(event):
|
def listener(event):
|
||||||
""" State change listener that listens for specific state changes. """
|
""" State change listener that listens for specific state changes. """
|
||||||
assert isinstance(event, Event), "event needs to be of Event type"
|
|
||||||
|
|
||||||
if category == event.data['category'] and \
|
if category == event.data['category'] and \
|
||||||
matcher(event.data['old_state'].state, from_state) and \
|
matcher(event.data['old_state'].state, from_state) and \
|
||||||
matcher(event.data['new_state'].state, to_state):
|
matcher(event.data['new_state'].state, to_state):
|
||||||
@ -86,8 +86,6 @@ def track_time_change(eventbus, action,
|
|||||||
|
|
||||||
def listener(event):
|
def listener(event):
|
||||||
""" Listens for matching time_changed events. """
|
""" Listens for matching time_changed events. """
|
||||||
assert isinstance(event, Event), "event needs to be of Event type"
|
|
||||||
|
|
||||||
if (point_in_time and event.data['now'] > point_in_time) or \
|
if (point_in_time and event.data['now'] > point_in_time) or \
|
||||||
(not point_in_time and \
|
(not point_in_time and \
|
||||||
matcher(event.data['now'].year, year) and \
|
matcher(event.data['now'].year, year) and \
|
||||||
@ -99,80 +97,60 @@ def track_time_change(eventbus, action,
|
|||||||
|
|
||||||
# point_in_time are exact points in time
|
# point_in_time are exact points in time
|
||||||
# so we always remove it after fire
|
# so we always remove it after fire
|
||||||
event.remove_listener = listen_once or point_in_time is not None
|
if listen_once or point_in_time:
|
||||||
|
event.eventbus.remove_listener(EVENT_TIME_CHANGED, listener)
|
||||||
|
|
||||||
action(event.data['now'])
|
action(event.data['now'])
|
||||||
|
|
||||||
eventbus.listen(EVENT_TIME_CHANGED, listener)
|
eventbus.listen(EVENT_TIME_CHANGED, listener)
|
||||||
|
|
||||||
|
Event = namedtuple("Event", ["eventbus", "event_type", "data"])
|
||||||
|
|
||||||
class EventBus(object):
|
class EventBus(object):
|
||||||
""" Class that allows code to listen for- and fire events. """
|
""" Class that allows code to listen for- and fire events. """
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.listeners = defaultdict(list)
|
self.listeners = defaultdict(list)
|
||||||
self.lock = threading.RLock()
|
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def fire(self, event):
|
def fire(self, event_type, event_data=None):
|
||||||
""" Fire an event. """
|
""" Fire an event. """
|
||||||
assert isinstance(event, Event), \
|
|
||||||
"event needs to be an instance of Event"
|
if not event_data:
|
||||||
|
event_data = {}
|
||||||
|
|
||||||
|
self.logger.info("EventBus:Event {}: {}".format(
|
||||||
|
event_type, event_data))
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
""" We dont want the eventbus to be blocking - run in a thread. """
|
""" Fire listeners for event. """
|
||||||
self.lock.acquire()
|
event = Event(self, event_type, event_data)
|
||||||
|
|
||||||
self.logger.info("EventBus:Event {}: {}".format(
|
for listener in chain(self.listeners[ALL_EVENTS],
|
||||||
event.event_type, event.data))
|
|
||||||
|
|
||||||
for callback in chain(self.listeners[ALL_EVENTS],
|
|
||||||
self.listeners[event.event_type]):
|
self.listeners[event.event_type]):
|
||||||
try:
|
try:
|
||||||
callback(event)
|
listener(event)
|
||||||
|
|
||||||
except Exception: #pylint: disable=broad-except
|
except Exception: #pylint: disable=broad-except
|
||||||
self.logger.exception("EventBus:Exception in listener")
|
self.logger.exception("EventBus:Exception in listener")
|
||||||
|
|
||||||
if event.remove_listener:
|
# We dont want the eventbus to be blocking - run in a thread.
|
||||||
if callback in self.listeners[ALL_EVENTS]:
|
|
||||||
self.listeners[ALL_EVENTS].remove(callback)
|
|
||||||
|
|
||||||
if callback in self.listeners[event.event_type]:
|
|
||||||
self.listeners[event.event_type].remove(callback)
|
|
||||||
|
|
||||||
event.remove_listener = False
|
|
||||||
|
|
||||||
if event.stop_propegating:
|
|
||||||
break
|
|
||||||
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
threading.Thread(target=run).start()
|
threading.Thread(target=run).start()
|
||||||
|
|
||||||
def listen(self, event_type, callback):
|
def listen(self, event_type, listener):
|
||||||
""" Listen for all events or events of a specific type.
|
""" Listen for all events or events of a specific type.
|
||||||
|
|
||||||
To listen to all events specify the constant ``ALL_EVENTS``
|
To listen to all events specify the constant ``ALL_EVENTS``
|
||||||
as event_type.
|
as event_type.
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
self.listeners[event_type].append(listener)
|
||||||
|
|
||||||
self.listeners[event_type].append(callback)
|
def remove_listener(self, event_type, listener):
|
||||||
|
""" Removes a listener of a specific event_type. """
|
||||||
self.lock.release()
|
try:
|
||||||
|
self.listeners[event_type].remove(listener)
|
||||||
# pylint: disable=too-few-public-methods
|
except ValueError:
|
||||||
class Event(object):
|
pass
|
||||||
""" An event to be sent over the eventbus. """
|
|
||||||
|
|
||||||
def __init__(self, event_type, data=None):
|
|
||||||
self.event_type = event_type
|
|
||||||
self.data = {} if data is None else data
|
|
||||||
self.stop_propegating = False
|
|
||||||
self.remove_listener = False
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str([self.event_type, self.data])
|
|
||||||
|
|
||||||
class StateMachine(object):
|
class StateMachine(object):
|
||||||
""" Helper class that tracks the state of different objects. """
|
""" Helper class that tracks the state of different objects. """
|
||||||
@ -180,7 +158,7 @@ class StateMachine(object):
|
|||||||
def __init__(self, eventbus):
|
def __init__(self, eventbus):
|
||||||
self.states = dict()
|
self.states = dict()
|
||||||
self.eventbus = eventbus
|
self.eventbus = eventbus
|
||||||
self.lock = threading.RLock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
def set_state(self, category, new_state):
|
def set_state(self, category, new_state):
|
||||||
""" Set the state of a category, add category is it does not exist. """
|
""" Set the state of a category, add category is it does not exist. """
|
||||||
@ -198,10 +176,10 @@ class StateMachine(object):
|
|||||||
if old_state.state != new_state:
|
if old_state.state != new_state:
|
||||||
self.states[category] = State(new_state, datetime.now())
|
self.states[category] = State(new_state, datetime.now())
|
||||||
|
|
||||||
self.eventbus.fire(Event(EVENT_STATE_CHANGED,
|
self.eventbus.fire(EVENT_STATE_CHANGED,
|
||||||
{'category':category,
|
{'category':category,
|
||||||
'old_state':old_state,
|
'old_state':old_state,
|
||||||
'new_state':self.states[category]}))
|
'new_state':self.states[category]})
|
||||||
|
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
@ -265,7 +243,7 @@ class Timer(threading.Thread):
|
|||||||
if self._stop.isSet():
|
if self._stop.isSet():
|
||||||
break
|
break
|
||||||
|
|
||||||
self.eventbus.fire(Event(EVENT_TIME_CHANGED, {'now':now}))
|
self.eventbus.fire(EVENT_TIME_CHANGED, {'now':now})
|
||||||
|
|
||||||
class HomeAssistantException(Exception):
|
class HomeAssistantException(Exception):
|
||||||
""" General Home Assistant exception occured. """
|
""" General Home Assistant exception occured. """
|
||||||
|
@ -33,7 +33,7 @@ from urlparse import urlparse, parse_qs
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from . import EVENT_START, EVENT_SHUTDOWN, Event
|
from . import EVENT_START, EVENT_SHUTDOWN
|
||||||
|
|
||||||
SERVER_PORT = 8123
|
SERVER_PORT = 8123
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
else:
|
else:
|
||||||
event_data = json.loads(post_data['event_data'][0])
|
event_data = json.loads(post_data['event_data'][0])
|
||||||
|
|
||||||
self.server.eventbus.fire(Event(event_name, event_data))
|
self.server.eventbus.fire(event_name, event_data)
|
||||||
|
|
||||||
self._message(use_json, "Event {} fired.".
|
self._message(use_json, "Event {} fired.".
|
||||||
format(event_name))
|
format(event_name))
|
||||||
|
@ -11,7 +11,7 @@ import time
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from . import EventBus, StateMachine, Event, EVENT_START, EVENT_SHUTDOWN
|
from . import EventBus, StateMachine, EVENT_START, EVENT_SHUTDOWN
|
||||||
from .httpinterface import HTTPInterface, SERVER_PORT
|
from .httpinterface import HTTPInterface, SERVER_PORT
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class TestHTTPInterface(unittest.TestCase):
|
|||||||
|
|
||||||
self.statemachine.set_state("test", "INIT_STATE")
|
self.statemachine.set_state("test", "INIT_STATE")
|
||||||
|
|
||||||
self.eventbus.fire(Event(EVENT_START))
|
self.eventbus.fire(EVENT_START)
|
||||||
|
|
||||||
# Give objects time to startup
|
# Give objects time to startup
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@ -48,7 +48,7 @@ class TestHTTPInterface(unittest.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls): # pylint: disable=invalid-name
|
def tearDownClass(cls): # pylint: disable=invalid-name
|
||||||
""" things to be run when tests are done. """
|
""" things to be run when tests are done. """
|
||||||
cls.eventbus.fire(Event(EVENT_SHUTDOWN))
|
cls.eventbus.fire(EVENT_SHUTDOWN)
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user