From 2970196f61d47497f0f95ca3bf254fb19a749a6c Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 3 Jan 2017 16:19:28 -0600 Subject: [PATCH] Add support for limiting which entities are recorded (#4733) --- homeassistant/components/history.py | 8 +--- homeassistant/components/recorder/__init__.py | 44 ++++++++++++++++--- homeassistant/const.py | 4 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/history.py b/homeassistant/components/history.py index eee0570c9bc..a077ad09ec7 100644 --- a/homeassistant/components/history.py +++ b/homeassistant/components/history.py @@ -10,7 +10,8 @@ from datetime import timedelta from itertools import groupby 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.util.dt as dt_util from homeassistant.components import recorder, script @@ -21,11 +22,6 @@ from homeassistant.const import ATTR_HIDDEN DOMAIN = 'history' DEPENDENCIES = ['recorder', 'http'] -CONF_EXCLUDE = 'exclude' -CONF_INCLUDE = 'include' -CONF_ENTITIES = 'entities' -CONF_DOMAINS = 'domains' - CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ CONF_EXCLUDE: vol.Schema({ diff --git a/homeassistant/components/recorder/__init__.py b/homeassistant/components/recorder/__init__.py index 8de8925e093..41a7991c32f 100644 --- a/homeassistant/components/recorder/__init__.py +++ b/homeassistant/components/recorder/__init__.py @@ -12,14 +12,15 @@ import queue import threading import time from datetime import timedelta, datetime -from typing import Any, Union, Optional, List +from typing import Any, Union, Optional, List, Dict import voluptuous as vol from homeassistant.core import HomeAssistant, callback -from homeassistant.const import (EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED, - EVENT_TIME_CHANGED, MATCH_ALL) +from homeassistant.const import ( + ATTR_ENTITY_ID, ATTR_DOMAIN, CONF_ENTITIES, CONF_EXCLUDE, CONF_DOMAINS, + CONF_INCLUDE, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, + EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, MATCH_ALL) import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import track_point_in_utc_time from homeassistant.helpers.typing import ConfigType, QueryType @@ -44,6 +45,16 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_PURGE_DAYS): vol.All(vol.Coerce(int), vol.Range(min=1)), 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) @@ -110,7 +121,10 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool: db_url = DEFAULT_URL.format( 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 @@ -153,7 +167,8 @@ def log_error(e: Exception, retry_wait: Optional[float]=0, class Recorder(threading.Thread): """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.""" threading.Thread.__init__(self) @@ -166,6 +181,11 @@ class Recorder(threading.Thread): self.engine = 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): """Start recording.""" self.start() @@ -210,6 +230,18 @@ class Recorder(threading.Thread): self.queue.task_done() 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) self._commit(dbevent) diff --git a/homeassistant/const.py b/homeassistant/const.py index 0789531e9a3..d266a3aae55 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -81,11 +81,14 @@ CONF_DEVICES = 'devices' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_DISCOVERY = 'discovery' CONF_DISPLAY_OPTIONS = 'display_options' +CONF_DOMAINS = 'domains' CONF_ELEVATION = 'elevation' CONF_EMAIL = 'email' +CONF_ENTITIES = 'entities' CONF_ENTITY_ID = 'entity_id' CONF_ENTITY_NAMESPACE = 'entity_namespace' CONF_EVENT = 'event' +CONF_EXCLUDE = 'exclude' CONF_FILE_PATH = 'file_path' CONF_FILENAME = 'filename' CONF_FRIENDLY_NAME = 'friendly_name' @@ -93,6 +96,7 @@ CONF_HEADERS = 'headers' CONF_HOST = 'host' CONF_HOSTS = 'hosts' CONF_ICON = 'icon' +CONF_INCLUDE = 'include' CONF_ID = 'id' CONF_LATITUDE = 'latitude' CONF_LONGITUDE = 'longitude'