Apply new customize format to Zwave (#5603)
This commit is contained in:
parent
405b2fdfa0
commit
1fb372ffdb
9 changed files with 171 additions and 84 deletions
|
@ -17,6 +17,7 @@ from homeassistant.const import STATE_OFF, STATE_ON
|
||||||
from homeassistant.util.color import HASS_COLOR_MAX, HASS_COLOR_MIN, \
|
from homeassistant.util.color import HASS_COLOR_MAX, HASS_COLOR_MIN, \
|
||||||
color_temperature_mired_to_kelvin, color_temperature_to_rgb, \
|
color_temperature_mired_to_kelvin, color_temperature_to_rgb, \
|
||||||
color_rgb_to_rgbw, color_rgbw_to_rgb
|
color_rgb_to_rgbw, color_rgbw_to_rgb
|
||||||
|
from homeassistant.helpers import customize
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -54,13 +55,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
return
|
return
|
||||||
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
|
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
|
||||||
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
|
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
|
||||||
customize = hass.data['zwave_customize']
|
|
||||||
name = '{}.{}'.format(DOMAIN, zwave.object_id(value))
|
name = '{}.{}'.format(DOMAIN, zwave.object_id(value))
|
||||||
node_config = customize.get(name, {})
|
node_config = customize.get_overrides(hass, zwave.DOMAIN, name)
|
||||||
refresh = node_config.get(zwave.CONF_REFRESH_VALUE)
|
refresh = node_config.get(zwave.CONF_REFRESH_VALUE)
|
||||||
delay = node_config.get(zwave.CONF_REFRESH_DELAY)
|
delay = node_config.get(zwave.CONF_REFRESH_DELAY)
|
||||||
_LOGGER.debug('customize=%s name=%s node_config=%s CONF_REFRESH_VALUE=%s'
|
_LOGGER.debug('name=%s node_config=%s CONF_REFRESH_VALUE=%s'
|
||||||
' CONF_REFRESH_DELAY=%s', customize, name, node_config,
|
' CONF_REFRESH_DELAY=%s', name, node_config,
|
||||||
refresh, delay)
|
refresh, delay)
|
||||||
if value.command_class != zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL:
|
if value.command_class != zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL:
|
||||||
return
|
return
|
||||||
|
|
|
@ -11,10 +11,10 @@ from pprint import pprint
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery, customize
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_BATTERY_LEVEL, ATTR_LOCATION, ATTR_ENTITY_ID, CONF_CUSTOMIZE,
|
ATTR_BATTERY_LEVEL, ATTR_LOCATION, ATTR_ENTITY_ID, CONF_CUSTOMIZE,
|
||||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_ENTITY_ID)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.event import track_time_change
|
from homeassistant.helpers.event import track_time_change
|
||||||
from homeassistant.util import convert, slugify
|
from homeassistant.util import convert, slugify
|
||||||
|
@ -150,9 +150,9 @@ CHANGE_ASSOCIATION_SCHEMA = vol.Schema({
|
||||||
vol.Optional(const.ATTR_INSTANCE, default=0x00): vol.Coerce(int)
|
vol.Optional(const.ATTR_INSTANCE, default=0x00): vol.Coerce(int)
|
||||||
})
|
})
|
||||||
|
|
||||||
CUSTOMIZE_SCHEMA = vol.Schema({
|
_ZWAVE_CUSTOMIZE_SCHEMA_ENTRY = vol.Schema({
|
||||||
vol.Optional(CONF_POLLING_INTENSITY):
|
vol.Required(CONF_ENTITY_ID): cv.match_all,
|
||||||
vol.All(cv.positive_int),
|
vol.Optional(CONF_POLLING_INTENSITY): cv.positive_int,
|
||||||
vol.Optional(CONF_IGNORED, default=DEFAULT_CONF_IGNORED): cv.boolean,
|
vol.Optional(CONF_IGNORED, default=DEFAULT_CONF_IGNORED): cv.boolean,
|
||||||
vol.Optional(CONF_REFRESH_VALUE, default=DEFAULT_CONF_REFRESH_VALUE):
|
vol.Optional(CONF_REFRESH_VALUE, default=DEFAULT_CONF_REFRESH_VALUE):
|
||||||
cv.boolean,
|
cv.boolean,
|
||||||
|
@ -164,8 +164,9 @@ CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
vol.Optional(CONF_AUTOHEAL, default=DEFAULT_CONF_AUTOHEAL): cv.boolean,
|
vol.Optional(CONF_AUTOHEAL, default=DEFAULT_CONF_AUTOHEAL): cv.boolean,
|
||||||
vol.Optional(CONF_CONFIG_PATH): cv.string,
|
vol.Optional(CONF_CONFIG_PATH): cv.string,
|
||||||
vol.Optional(CONF_CUSTOMIZE, default={}):
|
vol.Optional(CONF_CUSTOMIZE, default=[]):
|
||||||
vol.Schema({cv.string: CUSTOMIZE_SCHEMA}),
|
vol.All(customize.CUSTOMIZE_SCHEMA,
|
||||||
|
[_ZWAVE_CUSTOMIZE_SCHEMA_ENTRY]),
|
||||||
vol.Optional(CONF_DEBUG, default=DEFAULT_DEBUG): cv.boolean,
|
vol.Optional(CONF_DEBUG, default=DEFAULT_DEBUG): cv.boolean,
|
||||||
vol.Optional(CONF_POLLING_INTERVAL, default=DEFAULT_POLLING_INTERVAL):
|
vol.Optional(CONF_POLLING_INTERVAL, default=DEFAULT_POLLING_INTERVAL):
|
||||||
cv.positive_int,
|
cv.positive_int,
|
||||||
|
@ -268,8 +269,7 @@ def setup(hass, config):
|
||||||
|
|
||||||
# Load configuration
|
# Load configuration
|
||||||
use_debug = config[DOMAIN].get(CONF_DEBUG)
|
use_debug = config[DOMAIN].get(CONF_DEBUG)
|
||||||
hass.data['zwave_customize'] = config[DOMAIN].get(CONF_CUSTOMIZE)
|
customize.set_customize(hass, DOMAIN, config[DOMAIN].get(CONF_CUSTOMIZE))
|
||||||
customize = hass.data['zwave_customize']
|
|
||||||
autoheal = config[DOMAIN].get(CONF_AUTOHEAL)
|
autoheal = config[DOMAIN].get(CONF_AUTOHEAL)
|
||||||
|
|
||||||
# Setup options
|
# Setup options
|
||||||
|
@ -349,7 +349,7 @@ def setup(hass, config):
|
||||||
value.genre)
|
value.genre)
|
||||||
name = "{}.{}".format(component, object_id(value))
|
name = "{}.{}".format(component, object_id(value))
|
||||||
|
|
||||||
node_config = customize.get(name, {})
|
node_config = customize.get_overrides(hass, DOMAIN, name)
|
||||||
|
|
||||||
if node_config.get(CONF_IGNORED):
|
if node_config.get(CONF_IGNORED):
|
||||||
_LOGGER.info("Ignoring device %s", name)
|
_LOGGER.info("Ignoring device %s", name)
|
||||||
|
|
|
@ -13,7 +13,7 @@ from homeassistant.const import (
|
||||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM,
|
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM,
|
||||||
CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
|
CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
|
||||||
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
||||||
CONF_ENTITY_ID, __version__)
|
__version__)
|
||||||
from homeassistant.core import DOMAIN as CONF_CORE
|
from homeassistant.core import DOMAIN as CONF_CORE
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.loader import get_component
|
from homeassistant.loader import get_component
|
||||||
|
@ -21,7 +21,7 @@ from homeassistant.util.yaml import load_yaml
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util import dt as date_util, location as loc_util
|
from homeassistant.util import dt as date_util, location as loc_util
|
||||||
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
|
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
|
||||||
from homeassistant.helpers.customize import set_customize
|
from homeassistant.helpers import customize
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -86,27 +86,6 @@ tts:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
CUSTOMIZE_SCHEMA_ENTRY = vol.Schema({
|
|
||||||
vol.Required(CONF_ENTITY_ID): vol.All(
|
|
||||||
cv.ensure_list_csv, vol.Length(min=1), [cv.string], [vol.Lower])
|
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
|
||||||
|
|
||||||
|
|
||||||
def _convert_old_config(inp: Any) -> List:
|
|
||||||
if not isinstance(inp, dict):
|
|
||||||
return cv.ensure_list(inp)
|
|
||||||
if CONF_ENTITY_ID in inp:
|
|
||||||
return [inp] # sigle entry
|
|
||||||
res = []
|
|
||||||
|
|
||||||
inp = vol.Schema({cv.match_all: dict})(inp)
|
|
||||||
for key, val in inp.items():
|
|
||||||
val = dict(val)
|
|
||||||
val[CONF_ENTITY_ID] = key
|
|
||||||
res.append(val)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
PACKAGES_CONFIG_SCHEMA = vol.Schema({
|
PACKAGES_CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.slug: vol.Schema( # Package names are slugs
|
cv.slug: vol.Schema( # Package names are slugs
|
||||||
{cv.slug: vol.Any(dict, list)}) # Only slugs for component names
|
{cv.slug: vol.Any(dict, list)}) # Only slugs for component names
|
||||||
|
@ -120,8 +99,7 @@ CORE_CONFIG_SCHEMA = vol.Schema({
|
||||||
vol.Optional(CONF_TEMPERATURE_UNIT): cv.temperature_unit,
|
vol.Optional(CONF_TEMPERATURE_UNIT): cv.temperature_unit,
|
||||||
CONF_UNIT_SYSTEM: cv.unit_system,
|
CONF_UNIT_SYSTEM: cv.unit_system,
|
||||||
CONF_TIME_ZONE: cv.time_zone,
|
CONF_TIME_ZONE: cv.time_zone,
|
||||||
vol.Optional(CONF_CUSTOMIZE, default=[]): vol.All(
|
vol.Optional(CONF_CUSTOMIZE, default=[]): customize.CUSTOMIZE_SCHEMA,
|
||||||
_convert_old_config, [CUSTOMIZE_SCHEMA_ENTRY]),
|
|
||||||
vol.Optional(CONF_PACKAGES, default={}): PACKAGES_CONFIG_SCHEMA,
|
vol.Optional(CONF_PACKAGES, default={}): PACKAGES_CONFIG_SCHEMA,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -280,6 +258,7 @@ def async_process_ha_core_config(hass, config):
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
|
print(CORE_CONFIG_SCHEMA)
|
||||||
config = CORE_CONFIG_SCHEMA(config)
|
config = CORE_CONFIG_SCHEMA(config)
|
||||||
hac = hass.config
|
hac = hass.config
|
||||||
|
|
||||||
|
@ -306,9 +285,9 @@ def async_process_ha_core_config(hass, config):
|
||||||
if CONF_TIME_ZONE in config:
|
if CONF_TIME_ZONE in config:
|
||||||
set_time_zone(config.get(CONF_TIME_ZONE))
|
set_time_zone(config.get(CONF_TIME_ZONE))
|
||||||
|
|
||||||
customize = merge_packages_customize(
|
merged_customize = merge_packages_customize(
|
||||||
config[CONF_CUSTOMIZE], config[CONF_PACKAGES])
|
config[CONF_CUSTOMIZE], config[CONF_PACKAGES])
|
||||||
set_customize(hass, customize)
|
customize.set_customize(hass, CONF_CORE, merged_customize)
|
||||||
|
|
||||||
if CONF_UNIT_SYSTEM in config:
|
if CONF_UNIT_SYSTEM in config:
|
||||||
if config[CONF_UNIT_SYSTEM] == CONF_UNIT_SYSTEM_IMPERIAL:
|
if config[CONF_UNIT_SYSTEM] == CONF_UNIT_SYSTEM_IMPERIAL:
|
||||||
|
@ -463,15 +442,14 @@ def merge_packages_config(config, packages):
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def merge_packages_customize(customize, packages):
|
def merge_packages_customize(core_customize, packages):
|
||||||
"""Merge customize from packages."""
|
"""Merge customize from packages."""
|
||||||
schema = vol.Schema({
|
schema = vol.Schema({
|
||||||
vol.Optional(CONF_CORE): vol.Schema({
|
vol.Optional(CONF_CORE): vol.Schema({
|
||||||
CONF_CUSTOMIZE: vol.All(
|
CONF_CUSTOMIZE: customize.CUSTOMIZE_SCHEMA}),
|
||||||
_convert_old_config, [CUSTOMIZE_SCHEMA_ENTRY])})
|
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
cust = list(customize)
|
cust = list(core_customize)
|
||||||
for pkg in packages.values():
|
for pkg in packages.values():
|
||||||
conf = schema(pkg)
|
conf = schema(pkg)
|
||||||
cust.extend(conf.get(CONF_CORE, {}).get(CONF_CUSTOMIZE, []))
|
cust.extend(conf.get(CONF_CORE, {}).get(CONF_CUSTOMIZE, []))
|
||||||
|
|
|
@ -1,25 +1,51 @@
|
||||||
"""A helper module for customization."""
|
"""A helper module for customization."""
|
||||||
import collections
|
import collections
|
||||||
from typing import Dict, List
|
from typing import Any, Dict, List
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import CONF_ENTITY_ID
|
from homeassistant.const import CONF_ENTITY_ID
|
||||||
from homeassistant.core import HomeAssistant, split_entity_id
|
from homeassistant.core import HomeAssistant, split_entity_id
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_OVERWRITE_KEY = 'overwrite'
|
_OVERWRITE_KEY_FORMAT = '{}.overwrite'
|
||||||
_OVERWRITE_CACHE_KEY = 'overwrite_cache'
|
_OVERWRITE_CACHE_KEY_FORMAT = '{}.overwrite_cache'
|
||||||
|
|
||||||
|
_CUSTOMIZE_SCHEMA_ENTRY = vol.Schema({
|
||||||
|
vol.Required(CONF_ENTITY_ID): vol.All(
|
||||||
|
cv.ensure_list_csv, vol.Length(min=1), [vol.Schema(str)], [vol.Lower])
|
||||||
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
def set_customize(hass: HomeAssistant, customize: List[Dict]) -> None:
|
def _convert_old_config(inp: Any) -> List:
|
||||||
|
if not isinstance(inp, dict):
|
||||||
|
return cv.ensure_list(inp)
|
||||||
|
if CONF_ENTITY_ID in inp:
|
||||||
|
return [inp] # sigle entry
|
||||||
|
res = []
|
||||||
|
|
||||||
|
inp = vol.Schema({cv.match_all: dict})(inp)
|
||||||
|
for key, val in inp.items():
|
||||||
|
val = dict(val)
|
||||||
|
val[CONF_ENTITY_ID] = key
|
||||||
|
res.append(val)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOMIZE_SCHEMA = vol.All(_convert_old_config, [_CUSTOMIZE_SCHEMA_ENTRY])
|
||||||
|
|
||||||
|
|
||||||
|
def set_customize(
|
||||||
|
hass: HomeAssistant, domain: str, customize: List[Dict]) -> None:
|
||||||
"""Overwrite all current customize settings.
|
"""Overwrite all current customize settings.
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
hass.data[_OVERWRITE_KEY] = customize
|
hass.data[_OVERWRITE_KEY_FORMAT.format(domain)] = customize
|
||||||
hass.data[_OVERWRITE_CACHE_KEY] = {}
|
hass.data[_OVERWRITE_CACHE_KEY_FORMAT.format(domain)] = {}
|
||||||
|
|
||||||
|
|
||||||
def get_overrides(hass: HomeAssistant, entity_id: str) -> Dict:
|
def get_overrides(hass: HomeAssistant, domain: str, entity_id: str) -> Dict:
|
||||||
"""Return a dictionary of overrides related to entity_id.
|
"""Return a dictionary of overrides related to entity_id.
|
||||||
|
|
||||||
Whole-domain overrides are of lowest priorities,
|
Whole-domain overrides are of lowest priorities,
|
||||||
|
@ -28,10 +54,11 @@ def get_overrides(hass: HomeAssistant, entity_id: str) -> Dict:
|
||||||
|
|
||||||
The lookups are cached.
|
The lookups are cached.
|
||||||
"""
|
"""
|
||||||
if _OVERWRITE_CACHE_KEY in hass.data and \
|
cache_key = _OVERWRITE_CACHE_KEY_FORMAT.format(domain)
|
||||||
entity_id in hass.data[_OVERWRITE_CACHE_KEY]:
|
if cache_key in hass.data and entity_id in hass.data[cache_key]:
|
||||||
return hass.data[_OVERWRITE_CACHE_KEY][entity_id]
|
return hass.data[cache_key][entity_id]
|
||||||
if _OVERWRITE_KEY not in hass.data:
|
overwrite_key = _OVERWRITE_KEY_FORMAT.format(domain)
|
||||||
|
if overwrite_key not in hass.data:
|
||||||
return {}
|
return {}
|
||||||
domain_result = {} # type: Dict[str, Any]
|
domain_result = {} # type: Dict[str, Any]
|
||||||
glob_result = {} # type: Dict[str, Any]
|
glob_result = {} # type: Dict[str, Any]
|
||||||
|
@ -57,7 +84,7 @@ def get_overrides(hass: HomeAssistant, entity_id: str) -> Dict:
|
||||||
else:
|
else:
|
||||||
target[key] = source[key]
|
target[key] = source[key]
|
||||||
|
|
||||||
for rule in hass.data[_OVERWRITE_KEY]:
|
for rule in hass.data[overwrite_key]:
|
||||||
if CONF_ENTITY_ID in rule:
|
if CONF_ENTITY_ID in rule:
|
||||||
entities = rule[CONF_ENTITY_ID]
|
entities = rule[CONF_ENTITY_ID]
|
||||||
if domain in entities:
|
if domain in entities:
|
||||||
|
@ -74,7 +101,7 @@ def get_overrides(hass: HomeAssistant, entity_id: str) -> Dict:
|
||||||
deep_update(result, clean_entry(domain_result))
|
deep_update(result, clean_entry(domain_result))
|
||||||
deep_update(result, clean_entry(glob_result))
|
deep_update(result, clean_entry(glob_result))
|
||||||
deep_update(result, clean_entry(exact_result))
|
deep_update(result, clean_entry(exact_result))
|
||||||
if _OVERWRITE_CACHE_KEY not in hass.data:
|
if cache_key not in hass.data:
|
||||||
hass.data[_OVERWRITE_CACHE_KEY] = {}
|
hass.data[cache_key] = {}
|
||||||
hass.data[_OVERWRITE_CACHE_KEY][entity_id] = result
|
hass.data[cache_key][entity_id] = result
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -11,7 +11,7 @@ from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON,
|
ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON,
|
||||||
STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||||
ATTR_ENTITY_PICTURE)
|
ATTR_ENTITY_PICTURE)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, DOMAIN as CORE_DOMAIN
|
||||||
from homeassistant.exceptions import NoEntitySpecifiedError
|
from homeassistant.exceptions import NoEntitySpecifiedError
|
||||||
from homeassistant.util import ensure_unique_string, slugify
|
from homeassistant.util import ensure_unique_string, slugify
|
||||||
from homeassistant.util.async import (
|
from homeassistant.util.async import (
|
||||||
|
@ -242,7 +242,7 @@ class Entity(object):
|
||||||
end - start)
|
end - start)
|
||||||
|
|
||||||
# Overwrite properties that have been set in the config file.
|
# Overwrite properties that have been set in the config file.
|
||||||
attr.update(get_overrides(self.hass, self.entity_id))
|
attr.update(get_overrides(self.hass, CORE_DOMAIN, self.entity_id))
|
||||||
|
|
||||||
# Remove hidden property if false so it won't show up.
|
# Remove hidden property if false so it won't show up.
|
||||||
if not attr.get(ATTR_HIDDEN, True):
|
if not attr.get(ATTR_HIDDEN, True):
|
||||||
|
|
68
tests/components/test_zwave.py
Normal file
68
tests/components/test_zwave.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
"""The tests for the zwave component."""
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import setup_component
|
||||||
|
from homeassistant.components import zwave
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
|
class TestComponentZwave(unittest.TestCase):
|
||||||
|
"""Test the Zwave component."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Stop everything that was started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
|
def _validate_config(self, validator, config):
|
||||||
|
libopenzwave = MagicMock()
|
||||||
|
libopenzwave.__file__ = 'test'
|
||||||
|
with patch.dict('sys.modules', {
|
||||||
|
'libopenzwave': libopenzwave,
|
||||||
|
'openzwave.option': MagicMock(),
|
||||||
|
'openzwave.network': MagicMock(),
|
||||||
|
'openzwave.group': MagicMock(),
|
||||||
|
}):
|
||||||
|
validator(setup_component(self.hass, zwave.DOMAIN, {
|
||||||
|
zwave.DOMAIN: config,
|
||||||
|
}))
|
||||||
|
|
||||||
|
def test_empty_config(self):
|
||||||
|
"""Test empty config."""
|
||||||
|
self._validate_config(self.assertTrue, {})
|
||||||
|
|
||||||
|
def test_empty_customize(self):
|
||||||
|
"""Test empty customize."""
|
||||||
|
self._validate_config(self.assertTrue, {'customize': {}})
|
||||||
|
self._validate_config(self.assertTrue, {'customize': []})
|
||||||
|
|
||||||
|
def test_empty_customize_content(self):
|
||||||
|
"""Test empty customize."""
|
||||||
|
self._validate_config(
|
||||||
|
self.assertTrue, {'customize': {'test.test': {}}})
|
||||||
|
|
||||||
|
def test_full_customize_dict(self):
|
||||||
|
"""Test full customize as dict."""
|
||||||
|
self._validate_config(self.assertTrue, {'customize': {'test.test': {
|
||||||
|
zwave.CONF_POLLING_INTENSITY: 10,
|
||||||
|
zwave.CONF_IGNORED: 1,
|
||||||
|
zwave.CONF_REFRESH_VALUE: 1,
|
||||||
|
zwave.CONF_REFRESH_DELAY: 10}}})
|
||||||
|
|
||||||
|
def test_full_customize_list(self):
|
||||||
|
"""Test full customize as list."""
|
||||||
|
self._validate_config(self.assertTrue, {'customize': [{
|
||||||
|
'entity_id': 'test.test',
|
||||||
|
zwave.CONF_POLLING_INTENSITY: 10,
|
||||||
|
zwave.CONF_IGNORED: 1,
|
||||||
|
zwave.CONF_REFRESH_VALUE: 1,
|
||||||
|
zwave.CONF_REFRESH_DELAY: 10}]})
|
||||||
|
|
||||||
|
def test_bad_customize(self):
|
||||||
|
"""Test customize with extra keys."""
|
||||||
|
self._validate_config(
|
||||||
|
self.assertFalse, {'customize': {'test.test': {'extra_key': 10}}})
|
|
@ -1,5 +1,7 @@
|
||||||
"""Test the customize helper."""
|
"""Test the customize helper."""
|
||||||
import homeassistant.helpers.customize as customize
|
import homeassistant.helpers.customize as customize
|
||||||
|
from voluptuous import MultipleInvalid
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class MockHass(object):
|
class MockHass(object):
|
||||||
|
@ -17,8 +19,9 @@ class TestHelpersCustomize(object):
|
||||||
self.hass = MockHass()
|
self.hass = MockHass()
|
||||||
|
|
||||||
def _get_overrides(self, overrides):
|
def _get_overrides(self, overrides):
|
||||||
customize.set_customize(self.hass, overrides)
|
test_domain = 'test.domain'
|
||||||
return customize.get_overrides(self.hass, self.entity_id)
|
customize.set_customize(self.hass, test_domain, overrides)
|
||||||
|
return customize.get_overrides(self.hass, test_domain, self.entity_id)
|
||||||
|
|
||||||
def test_override_single_value(self):
|
def test_override_single_value(self):
|
||||||
"""Test entity customization through configuration."""
|
"""Test entity customization through configuration."""
|
||||||
|
@ -75,7 +78,7 @@ class TestHelpersCustomize(object):
|
||||||
'key3': 'valueDomain'}
|
'key3': 'valueDomain'}
|
||||||
|
|
||||||
def test_override_deep_dict(self):
|
def test_override_deep_dict(self):
|
||||||
"""Test we can overwrite hidden property to True."""
|
"""Test we can deep-overwrite a dict."""
|
||||||
result = self._get_overrides(
|
result = self._get_overrides(
|
||||||
[{'entity_id': [self.entity_id],
|
[{'entity_id': [self.entity_id],
|
||||||
'test': {'key1': 'value1', 'key2': 'value2'}},
|
'test': {'key1': 'value1', 'key2': 'value2'}},
|
||||||
|
@ -85,3 +88,32 @@ class TestHelpersCustomize(object):
|
||||||
'key1': 'value1',
|
'key1': 'value1',
|
||||||
'key2': 'value22',
|
'key2': 'value22',
|
||||||
'key3': 'value3'}
|
'key3': 'value3'}
|
||||||
|
|
||||||
|
def test_schema_bad_schema(self):
|
||||||
|
"""Test bad customize schemas."""
|
||||||
|
for value in (
|
||||||
|
{'test.test': 10},
|
||||||
|
{'test.test': ['hello']},
|
||||||
|
{'entity_id': {'a': 'b'}},
|
||||||
|
{'entity_id': 10},
|
||||||
|
[{'test.test': 'value'}],
|
||||||
|
):
|
||||||
|
with pytest.raises(
|
||||||
|
MultipleInvalid,
|
||||||
|
message="{} should have raised MultipleInvalid".format(
|
||||||
|
value)):
|
||||||
|
customize.CUSTOMIZE_SCHEMA(value)
|
||||||
|
|
||||||
|
def test_get_customize_schema_allow_extra(self):
|
||||||
|
"""Test schema with ALLOW_EXTRA."""
|
||||||
|
for value in (
|
||||||
|
{'test.test': {'hidden': True}},
|
||||||
|
{'test.test': {'key': ['value1', 'value2']}},
|
||||||
|
[{'entity_id': 'id1', 'key': 'value'}],
|
||||||
|
):
|
||||||
|
customize.CUSTOMIZE_SCHEMA(value)
|
||||||
|
|
||||||
|
def test_get_customize_schema_csv(self):
|
||||||
|
"""Test schema with comma separated entity IDs."""
|
||||||
|
assert [{'entity_id': ['id1', 'id2', 'id3']}] == \
|
||||||
|
customize.CUSTOMIZE_SCHEMA([{'entity_id': 'id1,ID2 , id3'}])
|
||||||
|
|
|
@ -90,6 +90,7 @@ class TestHelpersEntity(object):
|
||||||
"""Test we can overwrite hidden property to True."""
|
"""Test we can overwrite hidden property to True."""
|
||||||
set_customize(
|
set_customize(
|
||||||
self.hass,
|
self.hass,
|
||||||
|
entity.CORE_DOMAIN,
|
||||||
[{'entity_id': [self.entity.entity_id], ATTR_HIDDEN: True}])
|
[{'entity_id': [self.entity.entity_id], ATTR_HIDDEN: True}])
|
||||||
self.entity.update_ha_state()
|
self.entity.update_ha_state()
|
||||||
|
|
||||||
|
|
|
@ -234,25 +234,6 @@ class TestConfig(unittest.TestCase):
|
||||||
|
|
||||||
assert state.attributes['hidden']
|
assert state.attributes['hidden']
|
||||||
|
|
||||||
def test_entity_customization_comma_separated(self):
|
|
||||||
"""Test entity customization through configuration."""
|
|
||||||
config = {CONF_LATITUDE: 50,
|
|
||||||
CONF_LONGITUDE: 50,
|
|
||||||
CONF_NAME: 'Test',
|
|
||||||
CONF_CUSTOMIZE: [
|
|
||||||
{'entity_id': 'test.not_test,test,test.not_t*',
|
|
||||||
'key1': 'value1'},
|
|
||||||
{'entity_id': 'test.test,not_test,test.not_t*',
|
|
||||||
'key2': 'value2'},
|
|
||||||
{'entity_id': 'test.not_test,not_test,test.t*',
|
|
||||||
'key3': 'value3'}]}
|
|
||||||
|
|
||||||
state = self._compute_state(config)
|
|
||||||
|
|
||||||
assert state.attributes['key1'] == 'value1'
|
|
||||||
assert state.attributes['key2'] == 'value2'
|
|
||||||
assert state.attributes['key3'] == 'value3'
|
|
||||||
|
|
||||||
@mock.patch('homeassistant.config.shutil')
|
@mock.patch('homeassistant.config.shutil')
|
||||||
@mock.patch('homeassistant.config.os')
|
@mock.patch('homeassistant.config.os')
|
||||||
def test_remove_lib_on_upgrade(self, mock_os, mock_shutil):
|
def test_remove_lib_on_upgrade(self, mock_os, mock_shutil):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue