Add logbook component

This commit is contained in:
Paulus Schoutsen 2015-03-29 14:43:16 -07:00
parent a2f8fa7b05
commit 234bfe1199
3 changed files with 130 additions and 2 deletions

View File

@ -0,0 +1,127 @@
"""
homeassistant.components.logbook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Parses events and generates a human log
"""
from datetime import datetime
from homeassistant import State, DOMAIN as HA_DOMAIN
from homeassistant.const import (
EVENT_STATE_CHANGED, STATE_HOME, STATE_ON, STATE_OFF,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
import homeassistant.util as util
import homeassistant.components.recorder as recorder
import homeassistant.components.sun as sun
DOMAIN = "logbook"
DEPENDENCIES = ['recorder', 'http']
URL_LOGBOOK = '/api/logbook'
QUERY_EVENTS_AFTER = "SELECT * FROM events WHERE time_fired > ?"
QUERY_EVENTS_BETWEEN = """
SELECT * FROM events WHERE time_fired > ? AND time_fired < ?
ORDER BY time_fired
"""
def setup(hass, config):
""" Listens for download events to download files. """
hass.http.register_path('GET', URL_LOGBOOK, _handle_get_logbook)
return True
def _handle_get_logbook(handler, path_match, data):
""" Return logbook entries. """
start_today = datetime.now().date()
import time
print(time.mktime(start_today.timetuple()))
handler.write_json(humanify(
recorder.query_events(QUERY_EVENTS_AFTER, (start_today,))))
class Entry(object):
""" A human readable version of the log. """
# pylint: disable=too-many-arguments
def __init__(self, when=None, name=None, message=None, domain=None,
entity_id=None):
self.when = when
self.name = name
self.message = message
self.domain = domain
self.entity_id = entity_id
@property
def is_valid(self):
""" Returns if this entry contains all the needed fields. """
return self.when and self.name and self.message
def as_dict(self):
""" Convert Entry to a dict to be used within JSON. """
return {
'when': util.datetime_to_str(self.when),
'name': self.name,
'message': self.message,
'domain': self.domain,
'entity_id': self.entity_id,
}
def humanify(events):
""" Generator that converts a list of events into Entry objects. """
# pylint: disable=too-many-branches
for event in events:
if event.event_type == EVENT_STATE_CHANGED:
# Do not report on new entities
if 'old_state' not in event.data:
continue
to_state = State.from_dict(event.data.get('new_state'))
if not to_state:
continue
domain = to_state.domain
entry = Entry(
event.time_fired, domain=domain,
name=to_state.name, entity_id=to_state.entity_id)
if domain == 'device_tracker':
entry.message = '{} home'.format(
'arrived' if to_state.state == STATE_HOME else 'left')
elif domain == 'sun':
if to_state.state == sun.STATE_ABOVE_HORIZON:
entry.message = 'has risen'
else:
entry.message = 'has set'
elif to_state.state == STATE_ON:
# Future: combine groups and its entity entries ?
entry.message = "turned on"
elif to_state.state == STATE_OFF:
entry.message = "turned off"
else:
entry.message = "changed to {}".format(to_state.state)
if entry.is_valid:
yield entry
elif event.event_type == EVENT_HOMEASSISTANT_START:
# Future: look for sequence stop/start and rewrite as restarted
yield Entry(
event.time_fired, "Home Assistant", "started",
domain=HA_DOMAIN)
elif event.event_type == EVENT_HOMEASSISTANT_STOP:
yield Entry(
event.time_fired, "Home Assistant", "stopped",
domain=HA_DOMAIN)

View File

@ -9,7 +9,7 @@ import logging
import threading import threading
import queue import queue
import sqlite3 import sqlite3
from datetime import datetime from datetime import datetime, date
import time import time
import json import json
import atexit import atexit
@ -272,6 +272,7 @@ class Recorder(threading.Thread):
atexit.register(self._close_connection) atexit.register(self._close_connection)
# Have datetime objects be saved as integers # Have datetime objects be saved as integers
sqlite3.register_adapter(date, _adapt_datetime)
sqlite3.register_adapter(datetime, _adapt_datetime) sqlite3.register_adapter(datetime, _adapt_datetime)
# Validate we are on the correct schema or that we have to migrate # Validate we are on the correct schema or that we have to migrate

View File

@ -262,7 +262,7 @@ class JSONEncoder(json.JSONEncoder):
def default(self, obj): def default(self, obj):
""" Converts Home Assistant objects and hands """ Converts Home Assistant objects and hands
other objects to the original method. """ other objects to the original method. """
if isinstance(obj, (ha.State, ha.Event)): if hasattr(obj, 'as_dict'):
return obj.as_dict() return obj.as_dict()
try: try: