mirror of
https://github.com/home-assistant/core.git
synced 2026-01-15 20:16:55 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa29eeba04 | ||
|
|
fe47253f68 | ||
|
|
234c759b45 | ||
|
|
ba4d4bcd29 | ||
|
|
d7bbdb033d | ||
|
|
63fd5f2d31 | ||
|
|
c78d3b6154 | ||
|
|
dcfe7b2280 | ||
|
|
6330bb1004 | ||
|
|
672a896124 |
@@ -18,6 +18,7 @@ from homeassistant.util.logging import AsyncHandler
|
||||
from homeassistant.util.package import async_get_user_site, is_virtual_env
|
||||
from homeassistant.util.yaml import clear_secret_cache
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -153,6 +154,34 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||
stop = time()
|
||||
_LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
|
||||
|
||||
# TEMP: warn users for invalid slugs
|
||||
# Remove after 0.94 or 1.0
|
||||
if cv.INVALID_SLUGS_FOUND or cv.INVALID_ENTITY_IDS_FOUND:
|
||||
msg = []
|
||||
|
||||
if cv.INVALID_ENTITY_IDS_FOUND:
|
||||
msg.append(
|
||||
"Your configuration contains invalid entity ID references. "
|
||||
"Please find and update the following. "
|
||||
"This will become a breaking change."
|
||||
)
|
||||
msg.append('\n'.join('- {} -> {}'.format(*item)
|
||||
for item
|
||||
in cv.INVALID_ENTITY_IDS_FOUND.items()))
|
||||
|
||||
if cv.INVALID_SLUGS_FOUND:
|
||||
msg.append(
|
||||
"Your configuration contains invalid slugs. "
|
||||
"Please find and update the following. "
|
||||
"This will become a breaking change."
|
||||
)
|
||||
msg.append('\n'.join('- {} -> {}'.format(*item)
|
||||
for item in cv.INVALID_SLUGS_FOUND.items()))
|
||||
|
||||
hass.components.persistent_notification.async_create(
|
||||
'\n\n'.join(msg), "Config Warning", "config_warning"
|
||||
)
|
||||
|
||||
return hass
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from homeassistant.const import (
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
|
||||
REQUIREMENTS = ['aioasuswrt==1.1.17']
|
||||
REQUIREMENTS = ['aioasuswrt==1.1.18']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ SUPPORT_HUE = {
|
||||
}
|
||||
|
||||
ATTR_IS_HUE_GROUP = 'is_hue_group'
|
||||
GAMUT_TYPE_UNAVAILABLE = 'None'
|
||||
# Minimum Hue Bridge API version to support groups
|
||||
# 1.4.0 introduced extended group info
|
||||
# 1.12 introduced the state object for groups
|
||||
@@ -221,13 +222,23 @@ class HueLight(Light):
|
||||
if is_group:
|
||||
self.is_osram = False
|
||||
self.is_philips = False
|
||||
self.gamut_typ = 'None'
|
||||
self.gamut_typ = GAMUT_TYPE_UNAVAILABLE
|
||||
self.gamut = None
|
||||
else:
|
||||
self.is_osram = light.manufacturername == 'OSRAM'
|
||||
self.is_philips = light.manufacturername == 'Philips'
|
||||
self.gamut_typ = self.light.colorgamuttype
|
||||
self.gamut = self.light.colorgamut
|
||||
_LOGGER.debug("Color gamut of %s: %s", self.name, str(self.gamut))
|
||||
if self.gamut:
|
||||
if not color.check_valid_gamut(self.gamut):
|
||||
err = "Please check for software updates of the bridge " \
|
||||
"and/or bulb in the Philips Hue App, " \
|
||||
"Color gamut of %s: %s, not valid, " \
|
||||
"setting gamut to None."
|
||||
_LOGGER.warning(err, self.name, str(self.gamut))
|
||||
self.gamut_typ = GAMUT_TYPE_UNAVAILABLE
|
||||
self.gamut = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
|
||||
@@ -116,10 +116,17 @@ class TelldusLiveEntity(Entity):
|
||||
def device_info(self):
|
||||
"""Return device info."""
|
||||
device = self._client.device_info(self.device.device_id)
|
||||
return {
|
||||
device_info = {
|
||||
'identifiers': {('tellduslive', self.device.device_id)},
|
||||
'name': self.device.name,
|
||||
'model': device['model'].title(),
|
||||
'manufacturer': device['protocol'].title(),
|
||||
'via_hub': ('tellduslive', device.get('client')),
|
||||
}
|
||||
model = device.get('model')
|
||||
if model is not None:
|
||||
device_info['model'] = model.title()
|
||||
protocol = device.get('protocol')
|
||||
if protocol is not None:
|
||||
device_info['manufacturer'] = protocol.title()
|
||||
client = device.get('client')
|
||||
if client is not None:
|
||||
device_info['via_hub'] = ('tellduslive', client)
|
||||
return device_info
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 86
|
||||
PATCH_VERSION = '2'
|
||||
PATCH_VERSION = '4'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
REQUIRED_PYTHON_VER = (3, 5, 3)
|
||||
|
||||
@@ -26,6 +26,13 @@ from homeassistant.helpers import template as template_helper
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
TIME_PERIOD_ERROR = "offset {} should be format 'HH:MM' or 'HH:MM:SS'"
|
||||
OLD_SLUG_VALIDATION = r'^[a-z0-9_]+$'
|
||||
OLD_ENTITY_ID_VALIDATION = r"^(\w+)\.(\w+)$"
|
||||
# Keep track of invalid slugs and entity ids found so we can create a
|
||||
# persistent notification. Rare temporary exception to use a global.
|
||||
INVALID_SLUGS_FOUND = {}
|
||||
INVALID_ENTITY_IDS_FOUND = {}
|
||||
|
||||
|
||||
# Home Assistant types
|
||||
byte = vol.All(vol.Coerce(int), vol.Range(min=0, max=255))
|
||||
@@ -149,6 +156,18 @@ def entity_id(value: Any) -> str:
|
||||
value = string(value).lower()
|
||||
if valid_entity_id(value):
|
||||
return value
|
||||
if re.match(OLD_ENTITY_ID_VALIDATION, value):
|
||||
# To ease the breaking change, we allow old slugs for now
|
||||
# Remove after 0.94 or 1.0
|
||||
fixed = '.'.join(util_slugify(part) for part in value.split('.', 1))
|
||||
INVALID_ENTITY_IDS_FOUND[value] = fixed
|
||||
logging.getLogger(__name__).warning(
|
||||
"Found invalid entity_id %s, please update with %s. This "
|
||||
"will become a breaking change.",
|
||||
value, fixed
|
||||
)
|
||||
return value
|
||||
|
||||
raise vol.Invalid('Entity ID {} is an invalid entity id'.format(value))
|
||||
|
||||
|
||||
@@ -333,7 +352,22 @@ def schema_with_slug_keys(value_schema: Union[T, Callable]) -> Callable:
|
||||
raise vol.Invalid('expected dictionary')
|
||||
|
||||
for key in value.keys():
|
||||
slug(key)
|
||||
try:
|
||||
slug(key)
|
||||
except vol.Invalid:
|
||||
# To ease the breaking change, we allow old slugs for now
|
||||
# Remove after 0.94 or 1.0
|
||||
if re.match(OLD_SLUG_VALIDATION, key):
|
||||
fixed = util_slugify(key)
|
||||
INVALID_SLUGS_FOUND[key] = fixed
|
||||
logging.getLogger(__name__).warning(
|
||||
"Found invalid slug %s, please update with %s. This "
|
||||
"will be come a breaking change.",
|
||||
key, fixed
|
||||
)
|
||||
else:
|
||||
raise
|
||||
|
||||
return schema(value)
|
||||
return verify
|
||||
|
||||
|
||||
@@ -600,3 +600,21 @@ def check_point_in_lamps_reach(p: Tuple[float, float],
|
||||
t = cross_product(v1, q) / cross_product(v1, v2)
|
||||
|
||||
return (s >= 0.0) and (t >= 0.0) and (s + t <= 1.0)
|
||||
|
||||
|
||||
def check_valid_gamut(Gamut: GamutType) -> bool:
|
||||
"""Check if the supplied gamut is valid."""
|
||||
# Check if the three points of the supplied gamut are not on the same line.
|
||||
v1 = XYPoint(Gamut.green.x - Gamut.red.x, Gamut.green.y - Gamut.red.y)
|
||||
v2 = XYPoint(Gamut.blue.x - Gamut.red.x, Gamut.blue.y - Gamut.red.y)
|
||||
not_on_line = cross_product(v1, v2) > 0.0001
|
||||
|
||||
# Check if all six coordinates of the gamut lie between 0 and 1.
|
||||
red_valid = Gamut.red.x >= 0 and Gamut.red.x <= 1 and \
|
||||
Gamut.red.y >= 0 and Gamut.red.y <= 1
|
||||
green_valid = Gamut.green.x >= 0 and Gamut.green.x <= 1 and \
|
||||
Gamut.green.y >= 0 and Gamut.green.y <= 1
|
||||
blue_valid = Gamut.blue.x >= 0 and Gamut.blue.x <= 1 and \
|
||||
Gamut.blue.y >= 0 and Gamut.blue.y <= 1
|
||||
|
||||
return not_on_line and red_valid and green_valid and blue_valid
|
||||
|
||||
@@ -87,7 +87,7 @@ abodepy==0.15.0
|
||||
afsapi==0.0.4
|
||||
|
||||
# homeassistant.components.asuswrt
|
||||
aioasuswrt==1.1.17
|
||||
aioasuswrt==1.1.18
|
||||
|
||||
# homeassistant.components.device_tracker.automatic
|
||||
aioautomatic==0.6.5
|
||||
|
||||
@@ -701,7 +701,9 @@ def test_available():
|
||||
"""Test available property."""
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=False,
|
||||
@@ -711,7 +713,9 @@ def test_available():
|
||||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=True),
|
||||
is_group=False,
|
||||
@@ -721,7 +725,9 @@ def test_available():
|
||||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=True,
|
||||
|
||||
@@ -602,3 +602,31 @@ def test_comp_entity_ids():
|
||||
for invalid in (['light.kitchen', 'not-entity-id'], '*', ''):
|
||||
with pytest.raises(vol.Invalid):
|
||||
schema(invalid)
|
||||
|
||||
|
||||
def test_schema_with_slug_keys_allows_old_slugs(caplog):
|
||||
"""Test schema with slug keys allowing old slugs."""
|
||||
schema = cv.schema_with_slug_keys(str)
|
||||
|
||||
with patch.dict(cv.INVALID_SLUGS_FOUND, clear=True):
|
||||
for value in ('_world', 'wow__yeah'):
|
||||
caplog.clear()
|
||||
# Will raise if not allowing old slugs
|
||||
schema({value: 'yo'})
|
||||
assert "Found invalid slug {}".format(value) in caplog.text
|
||||
|
||||
assert len(cv.INVALID_SLUGS_FOUND) == 2
|
||||
|
||||
|
||||
def test_entity_id_allow_old_validation(caplog):
|
||||
"""Test schema allowing old entity_ids."""
|
||||
schema = vol.Schema(cv.entity_id)
|
||||
|
||||
with patch.dict(cv.INVALID_ENTITY_IDS_FOUND, clear=True):
|
||||
for value in ('hello.__world', 'great.wow__yeah'):
|
||||
caplog.clear()
|
||||
# Will raise if not allowing old entity ID
|
||||
schema(value)
|
||||
assert "Found invalid entity_id {}".format(value) in caplog.text
|
||||
|
||||
assert len(cv.INVALID_ENTITY_IDS_FOUND) == 2
|
||||
|
||||
@@ -8,6 +8,18 @@ import voluptuous as vol
|
||||
GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
|
||||
color_util.XYPoint(0.2151, 0.7106),
|
||||
color_util.XYPoint(0.138, 0.08))
|
||||
GAMUT_INVALID_1 = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
|
||||
color_util.XYPoint(-0.201, 0.7106),
|
||||
color_util.XYPoint(0.138, 0.08))
|
||||
GAMUT_INVALID_2 = color_util.GamutType(color_util.XYPoint(0.704, 1.296),
|
||||
color_util.XYPoint(0.2151, 0.7106),
|
||||
color_util.XYPoint(0.138, 0.08))
|
||||
GAMUT_INVALID_3 = color_util.GamutType(color_util.XYPoint(0.0, 0.0),
|
||||
color_util.XYPoint(0.0, 0.0),
|
||||
color_util.XYPoint(0.0, 0.0))
|
||||
GAMUT_INVALID_4 = color_util.GamutType(color_util.XYPoint(0.1, 0.1),
|
||||
color_util.XYPoint(0.3, 0.3),
|
||||
color_util.XYPoint(0.7, 0.7))
|
||||
|
||||
|
||||
class TestColorUtil(unittest.TestCase):
|
||||
@@ -338,6 +350,14 @@ class TestColorUtil(unittest.TestCase):
|
||||
assert color_util.color_rgb_to_hex(51, 153, 255) == '3399ff'
|
||||
assert color_util.color_rgb_to_hex(255, 67.9204190, 0) == 'ff4400'
|
||||
|
||||
def test_gamut(self):
|
||||
"""Test gamut functions."""
|
||||
assert color_util.check_valid_gamut(GAMUT)
|
||||
assert not color_util.check_valid_gamut(GAMUT_INVALID_1)
|
||||
assert not color_util.check_valid_gamut(GAMUT_INVALID_2)
|
||||
assert not color_util.check_valid_gamut(GAMUT_INVALID_3)
|
||||
assert not color_util.check_valid_gamut(GAMUT_INVALID_4)
|
||||
|
||||
|
||||
class ColorTemperatureMiredToKelvinTests(unittest.TestCase):
|
||||
"""Test color_temperature_mired_to_kelvin."""
|
||||
|
||||
Reference in New Issue
Block a user