Add support for limiting which entities are recorded (#4733)

This commit is contained in:
Matthew Garrett 2017-01-03 16:19:28 -06:00 committed by Johann Kellerman
parent 4692ea85b7
commit 2970196f61
3 changed files with 44 additions and 12 deletions

View File

@ -10,7 +10,8 @@ from datetime import timedelta
from itertools import groupby from itertools import groupby
import voluptuous as vol import voluptuous as vol
from homeassistant.const import HTTP_BAD_REQUEST from homeassistant.const import (
HTTP_BAD_REQUEST, CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.components import recorder, script from homeassistant.components import recorder, script
@ -21,11 +22,6 @@ from homeassistant.const import ATTR_HIDDEN
DOMAIN = 'history' DOMAIN = 'history'
DEPENDENCIES = ['recorder', 'http'] DEPENDENCIES = ['recorder', 'http']
CONF_EXCLUDE = 'exclude'
CONF_INCLUDE = 'include'
CONF_ENTITIES = 'entities'
CONF_DOMAINS = 'domains'
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.Schema({
CONF_EXCLUDE: vol.Schema({ CONF_EXCLUDE: vol.Schema({

View File

@ -12,14 +12,15 @@ import queue
import threading import threading
import time import time
from datetime import timedelta, datetime from datetime import timedelta, datetime
from typing import Any, Union, Optional, List from typing import Any, Union, Optional, List, Dict
import voluptuous as vol import voluptuous as vol
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.const import (EVENT_HOMEASSISTANT_START, from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED, ATTR_ENTITY_ID, ATTR_DOMAIN, CONF_ENTITIES, CONF_EXCLUDE, CONF_DOMAINS,
EVENT_TIME_CHANGED, MATCH_ALL) CONF_INCLUDE, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, MATCH_ALL)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_utc_time from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant.helpers.typing import ConfigType, QueryType from homeassistant.helpers.typing import ConfigType, QueryType
@ -44,6 +45,16 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_PURGE_DAYS): vol.Optional(CONF_PURGE_DAYS):
vol.All(vol.Coerce(int), vol.Range(min=1)), vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Optional(CONF_DB_URL): cv.string, vol.Optional(CONF_DB_URL): cv.string,
vol.Optional(CONF_EXCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): cv.entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(cv.ensure_list, [cv.string])
}),
vol.Optional(CONF_INCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): cv.entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(cv.ensure_list, [cv.string])
})
}) })
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
@ -110,7 +121,10 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
db_url = DEFAULT_URL.format( db_url = DEFAULT_URL.format(
hass_config_path=hass.config.path(DEFAULT_DB_FILE)) hass_config_path=hass.config.path(DEFAULT_DB_FILE))
_INSTANCE = Recorder(hass, purge_days=purge_days, uri=db_url) include = config.get(DOMAIN, {}).get(CONF_INCLUDE, {})
exclude = config.get(DOMAIN, {}).get(CONF_EXCLUDE, {})
_INSTANCE = Recorder(hass, purge_days=purge_days, uri=db_url,
include=include, exclude=exclude)
return True return True
@ -153,7 +167,8 @@ def log_error(e: Exception, retry_wait: Optional[float]=0,
class Recorder(threading.Thread): class Recorder(threading.Thread):
"""A threaded recorder class.""" """A threaded recorder class."""
def __init__(self, hass: HomeAssistant, purge_days: int, uri: str) -> None: def __init__(self, hass: HomeAssistant, purge_days: int, uri: str,
include: Dict, exclude: Dict) -> None:
"""Initialize the recorder.""" """Initialize the recorder."""
threading.Thread.__init__(self) threading.Thread.__init__(self)
@ -166,6 +181,11 @@ class Recorder(threading.Thread):
self.engine = None # type: Any self.engine = None # type: Any
self._run = None # type: Any self._run = None # type: Any
self.include = include.get(CONF_ENTITIES, []) + \
include.get(CONF_DOMAINS, [])
self.exclude = exclude.get(CONF_ENTITIES, []) + \
exclude.get(CONF_DOMAINS, [])
def start_recording(event): def start_recording(event):
"""Start recording.""" """Start recording."""
self.start() self.start()
@ -210,6 +230,18 @@ class Recorder(threading.Thread):
self.queue.task_done() self.queue.task_done()
continue continue
entity_id = event.data.get(ATTR_ENTITY_ID)
domain = event.data.get(ATTR_DOMAIN)
if entity_id in self.exclude or domain in self.exclude:
self.queue.task_done()
continue
if (self.include and entity_id not in self.include and
domain not in self.include):
self.queue.task_done()
continue
dbevent = Events.from_event(event) dbevent = Events.from_event(event)
self._commit(dbevent) self._commit(dbevent)

View File

@ -81,11 +81,14 @@ CONF_DEVICES = 'devices'
CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger'
CONF_DISCOVERY = 'discovery' CONF_DISCOVERY = 'discovery'
CONF_DISPLAY_OPTIONS = 'display_options' CONF_DISPLAY_OPTIONS = 'display_options'
CONF_DOMAINS = 'domains'
CONF_ELEVATION = 'elevation' CONF_ELEVATION = 'elevation'
CONF_EMAIL = 'email' CONF_EMAIL = 'email'
CONF_ENTITIES = 'entities'
CONF_ENTITY_ID = 'entity_id' CONF_ENTITY_ID = 'entity_id'
CONF_ENTITY_NAMESPACE = 'entity_namespace' CONF_ENTITY_NAMESPACE = 'entity_namespace'
CONF_EVENT = 'event' CONF_EVENT = 'event'
CONF_EXCLUDE = 'exclude'
CONF_FILE_PATH = 'file_path' CONF_FILE_PATH = 'file_path'
CONF_FILENAME = 'filename' CONF_FILENAME = 'filename'
CONF_FRIENDLY_NAME = 'friendly_name' CONF_FRIENDLY_NAME = 'friendly_name'
@ -93,6 +96,7 @@ CONF_HEADERS = 'headers'
CONF_HOST = 'host' CONF_HOST = 'host'
CONF_HOSTS = 'hosts' CONF_HOSTS = 'hosts'
CONF_ICON = 'icon' CONF_ICON = 'icon'
CONF_INCLUDE = 'include'
CONF_ID = 'id' CONF_ID = 'id'
CONF_LATITUDE = 'latitude' CONF_LATITUDE = 'latitude'
CONF_LONGITUDE = 'longitude' CONF_LONGITUDE = 'longitude'