|
4 | 4 | For more details about this component, please refer to the documentation at |
5 | 5 | https://home-assistant.io/components/remote_homeassistant/ |
6 | 6 | """ |
7 | | - |
| 7 | +import fnmatch |
8 | 8 | import logging |
9 | 9 | import copy |
10 | 10 | import asyncio |
11 | 11 | import aiohttp |
| 12 | +import re |
12 | 13 |
|
13 | 14 | import voluptuous as vol |
14 | 15 |
|
|
18 | 19 | from homeassistant.helpers.typing import HomeAssistantType, ConfigType |
19 | 20 | from homeassistant.const import (CONF_HOST, CONF_PORT, EVENT_CALL_SERVICE, |
20 | 21 | EVENT_HOMEASSISTANT_STOP, |
21 | | - EVENT_STATE_CHANGED, EVENT_SERVICE_REGISTERED, CONF_EXCLUDE, CONF_ENTITIES, |
22 | | - CONF_DOMAINS, CONF_INCLUDE) |
| 22 | + EVENT_STATE_CHANGED, EVENT_SERVICE_REGISTERED, |
| 23 | + CONF_EXCLUDE, CONF_ENTITIES, CONF_ENTITY_ID, |
| 24 | + CONF_DOMAINS, CONF_INCLUDE, CONF_UNIT_OF_MEASUREMENT, CONF_ABOVE, CONF_BELOW) |
23 | 25 | from homeassistant.config import DATA_CUSTOMIZE |
24 | 26 | from homeassistant.helpers.aiohttp_client import async_get_clientsession |
25 | 27 | import homeassistant.helpers.config_validation as cv |
|
33 | 35 | CONF_API_PASSWORD = 'api_password' |
34 | 36 | CONF_SUBSCRIBE_EVENTS = 'subscribe_events' |
35 | 37 | CONF_ENTITY_PREFIX = 'entity_prefix' |
| 38 | +CONF_FILTER = 'filter' |
36 | 39 |
|
37 | 40 | DOMAIN = 'remote_homeassistant' |
38 | 41 |
|
|
63 | 66 | ), |
64 | 67 | } |
65 | 68 | ), |
| 69 | + vol.Optional(CONF_FILTER, default=[]): vol.All( |
| 70 | + cv.ensure_list, |
| 71 | + [ |
| 72 | + vol.Schema( |
| 73 | + { |
| 74 | + vol.Optional(CONF_ENTITY_ID): cv.string, |
| 75 | + vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, |
| 76 | + vol.Optional(CONF_ABOVE): vol.Coerce(float), |
| 77 | + vol.Optional(CONF_BELOW): vol.Coerce(float), |
| 78 | + } |
| 79 | + ) |
| 80 | + ] |
| 81 | + ), |
66 | 82 | vol.Optional(CONF_SUBSCRIBE_EVENTS, |
67 | 83 | default=DEFAULT_SUBSCRIBED_EVENTS): cv.ensure_list, |
68 | 84 | vol.Optional(CONF_ENTITY_PREFIX, default=DEFAULT_ENTITY_PREFIX): cv.string, |
@@ -109,6 +125,16 @@ def __init__(self, hass, conf): |
109 | 125 | self._blacklist_e = set(exclude.get(CONF_ENTITIES, [])) |
110 | 126 | self._blacklist_d = set(exclude.get(CONF_DOMAINS, [])) |
111 | 127 |
|
| 128 | + self._filter = [ |
| 129 | + { |
| 130 | + CONF_ENTITY_ID: re.compile(fnmatch.translate(f.get(CONF_ENTITY_ID))) if f.get(CONF_ENTITY_ID) else None, |
| 131 | + CONF_UNIT_OF_MEASUREMENT: f.get(CONF_UNIT_OF_MEASUREMENT), |
| 132 | + CONF_ABOVE: f.get(CONF_ABOVE), |
| 133 | + CONF_BELOW: f.get(CONF_BELOW) |
| 134 | + } |
| 135 | + for f in conf.get(CONF_FILTER, []) |
| 136 | + ] |
| 137 | + |
112 | 138 | self._subscribe_events = conf.get(CONF_SUBSCRIBE_EVENTS) |
113 | 139 | self._entity_prefix = conf.get(CONF_ENTITY_PREFIX) |
114 | 140 |
|
@@ -311,6 +337,26 @@ def state_changed(entity_id, state, attr): |
311 | 337 | ): |
312 | 338 | return |
313 | 339 |
|
| 340 | + for f in self._filter: |
| 341 | + if f[CONF_ENTITY_ID] and not f[CONF_ENTITY_ID].match(entity_id): |
| 342 | + continue |
| 343 | + if f[CONF_UNIT_OF_MEASUREMENT]: |
| 344 | + if CONF_UNIT_OF_MEASUREMENT not in attr: |
| 345 | + continue |
| 346 | + if f[CONF_UNIT_OF_MEASUREMENT] != attr[CONF_UNIT_OF_MEASUREMENT]: |
| 347 | + continue |
| 348 | + try: |
| 349 | + if f[CONF_BELOW] and float(state) < f[CONF_BELOW]: |
| 350 | + _LOGGER.info("%s: ignoring state '%s', because " |
| 351 | + "below '%s'", entity_id, state, f[CONF_BELOW]) |
| 352 | + return |
| 353 | + if f[CONF_ABOVE] and float(state) > f[CONF_ABOVE]: |
| 354 | + _LOGGER.info("%s: ignoring state '%s', because " |
| 355 | + "above '%s'", entity_id, state, f[CONF_ABOVE]) |
| 356 | + return |
| 357 | + except ValueError: |
| 358 | + pass |
| 359 | + |
314 | 360 | if self._entity_prefix: |
315 | 361 | object_id = self._entity_prefix + object_id |
316 | 362 | entity_id = domain + '.' + object_id |
|
0 commit comments