Compare commits

...

28 Commits

Author SHA1 Message Date
Paulus Schoutsen
fbc53a886f Merge pull request #30525 from home-assistant/rc
0.103.6
2020-01-06 22:43:24 +01:00
Paulus Schoutsen
5675f16b61 Bumped version to 0.103.6 2020-01-06 22:02:31 +01:00
Paulus Schoutsen
4d0a093ec4 Fix google sync (#30524) 2020-01-06 22:02:25 +01:00
michaeldavie
60a9de40aa Bump env_canada to 0.0.31 (#30409) 2020-01-06 22:02:24 +01:00
Andrew Sayre
ed6b95f14a Bump pysmartthings 0.7.0 (#30302) 2020-01-06 22:01:06 +01:00
Robert Svensson
ce114b81c3 Handle wired bug on restart (#30276) 2020-01-06 22:01:05 +01:00
Pascal Vizeli
79b47157b8 Merge pull request #30260 from home-assistant/rc
0.103.5
2019-12-28 22:16:11 +01:00
Pascal Vizeli
ae42736235 Bump version 0.103.5 2019-12-28 20:26:06 +00:00
Marcelo Moreira de Mello
fdd090bae0 Bump ring to 0.2.8 to fix Oauth issues (#30245) 2019-12-28 20:24:29 +00:00
Paulus Schoutsen
48d35a4550 Merge pull request #30154 from home-assistant/rc
0.103.4
2019-12-22 23:41:22 +01:00
Robert Svensson
31b17e2b95 Allow battery value of 0 as well as make sure to not create a battery tracker if one already exist (#30155) 2019-12-22 22:58:36 +01:00
Paulus Schoutsen
720d63f496 Bumped version to 0.103.4 2019-12-22 22:34:57 +01:00
Franck Nijhof
e9b19e0465 Fix deconz SSDP updating Hassio discovery (#30153) 2019-12-22 22:34:14 +01:00
springstan
e74c4c5d99 Move imports into setup function in homekit __init__.py (#30137) 2019-12-22 22:25:27 +01:00
Paulus Schoutsen
697833bc91 Remove requirement from entity integration (#30113) 2019-12-22 22:25:03 +01:00
Paulus Schoutsen
3e7699b886 Merge pull request #30096 from home-assistant/rc
0.103.3
2019-12-20 21:28:49 +01:00
Paulus Schoutsen
d448ed9f6d Bump ring to 0.2.5 (#30103) 2019-12-20 20:44:46 +01:00
springstan
f229cf2796 Bump starlingbank to 3.2 (#30098) 2019-12-20 20:44:46 +01:00
Pascal Vizeli
5def51835e Fix v2 2019-12-20 17:10:04 +00:00
Pascal Vizeli
12f1a322a7 Fix test 2019-12-20 16:20:10 +00:00
Fazli Sapuan
488f26d55b Fix homekit handling of 0 light brightness and fan speed (#29962)
* Fix homekit handling of 0 light brightness and fan speed

* Update homekit tests for new initial brightness/speed value
2019-12-20 16:08:08 +00:00
Wim Haanstra
20a0557be7 Fix failure in transform method (#30023)
* Fix failure in transform method

* Fix formatting issue
2019-12-20 16:07:07 +00:00
omriasta
e58291015c Patch rachio (#30031)
* fix binary sensor offline/online

fixed self._handle_update on line 66 to produce args, kwargs.
Updated the binary sensor to check the correct index in the tuple.

* Fixed Standby switch

Set standby switch to poll in order to get status when homeassistant starts up.
Updated the index for the switch to get the status from the tuple.
2019-12-20 16:05:28 +00:00
Pascal Vizeli
e6a27983d3 Bump version 0.103.3 2019-12-20 14:16:39 +00:00
Franck Nijhof
939ca63cbc Fix update port and api key on deconz discovery config entry u… (#30088)
* Fix update port and api key on discovery config entry update

* Remove coroutine from _update_entry
2019-12-20 14:15:45 +00:00
Paulus Schoutsen
50714fbedf Merge pull request #30064 from home-assistant/rc
0.103.2
2019-12-19 08:03:47 +01:00
Paulus Schoutsen
c9de5b9fef Bumped version to 0.103.2 2019-12-19 07:53:38 +01:00
Paulus Schoutsen
aae80dca1c Fix recursion 2019-12-19 07:53:32 +01:00
37 changed files with 271 additions and 123 deletions

View File

@@ -77,6 +77,12 @@ class CloudGoogleConfig(AbstractConfig):
"""Return Cloud User account."""
return self._user
async def async_initialize(self):
"""Perform async initialization of config."""
await super().async_initialize()
# Remove bad data that was there until 0.103.6 - Jan 6, 2020
self._store.pop_agent_user_id(self._user)
def should_expose(self, state):
"""If a state object should be exposed."""
return self._should_expose_entity_id(state.entity_id)
@@ -93,6 +99,15 @@ class CloudGoogleConfig(AbstractConfig):
entity_config = entity_configs.get(entity_id, {})
return entity_config.get(PREF_SHOULD_EXPOSE, DEFAULT_SHOULD_EXPOSE)
@property
def agent_user_id(self):
"""Return Agent User Id to use for query responses."""
return self._cloud.username
def get_agent_user_id(self, context):
"""Get agent user ID making request."""
return self.agent_user_id
def should_2fa(self, state):
"""If an entity should be checked for 2FA."""
entity_configs = self._prefs.google_entity_configs

View File

@@ -175,7 +175,7 @@ class GoogleActionsSyncView(HomeAssistantView):
hass = request.app["hass"]
cloud: Cloud = hass.data[DOMAIN]
gconf = await cloud.client.get_google_config()
status = await gconf.async_sync_entities(gconf.cloud_user)
status = await gconf.async_sync_entities(gconf.agent_user_id)
return self.json({}, status_code=status)

View File

@@ -158,12 +158,21 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
title="deCONZ-" + self.deconz_config[CONF_BRIDGEID], data=self.deconz_config
)
async def _update_entry(self, entry, host):
def _update_entry(self, entry, host, port, api_key=None):
"""Update existing entry."""
if entry.data[CONF_HOST] == host:
if (
entry.data[CONF_HOST] == host
and entry.data[CONF_PORT] == port
and (api_key is None or entry.data[CONF_API_KEY] == api_key)
):
return self.async_abort(reason="already_configured")
entry.data[CONF_HOST] = host
entry.data[CONF_PORT] = port
if api_key is not None:
entry.data[CONF_API_KEY] = api_key
self.hass.config_entries.async_update_entry(entry)
return self.async_abort(reason="updated_instance")
@@ -182,7 +191,11 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
for entry in self.hass.config_entries.async_entries(DOMAIN):
if uuid == entry.data.get(CONF_UUID):
return await self._update_entry(entry, discovery_info[CONF_HOST])
if entry.source == "hassio":
return self.async_abort(reason="already_configured")
return self._update_entry(
entry, discovery_info[CONF_HOST], entry.data.get(CONF_PORT)
)
bridgeid = discovery_info[ATTR_SERIAL]
if any(
@@ -212,7 +225,12 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if bridgeid in gateway_entries:
entry = gateway_entries[bridgeid]
return await self._update_entry(entry, user_input[CONF_HOST])
return self._update_entry(
entry,
user_input[CONF_HOST],
user_input[CONF_PORT],
user_input[CONF_API_KEY],
)
self._hassio_discovery = user_input

View File

@@ -59,7 +59,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
entity_handler.add_entity(new_sensor)
entities.append(new_sensor)
if sensor.battery:
if sensor.battery is not None:
new_battery = DeconzBattery(sensor, gateway)
if new_battery.unique_id not in batteries:
batteries.add(new_battery.unique_id)
@@ -225,6 +225,9 @@ class DeconzBatteryHandler:
@callback
def create_tracker(self, sensor):
"""Create new tracker for battery state."""
for tracker in self._trackers:
if sensor == tracker.sensor:
return
self._trackers.add(DeconzSensorStateTracker(sensor, self.gateway))
@callback

View File

@@ -15,11 +15,11 @@ from homeassistant.components.image_processing import (
CONF_SOURCE,
PLATFORM_SCHEMA,
ImageProcessingEntity,
draw_box,
)
from homeassistant.core import split_entity_id
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
from homeassistant.util.pil import draw_box
_LOGGER = logging.getLogger(__name__)

View File

@@ -1,10 +1,8 @@
{
"domain": "doods",
"name": "DOODS - Distributed Outside Object Detection Service",
"documentation": "https://www.home-assistant.io/integrations/doods",
"requirements": [
"pydoods==1.0.2"
],
"dependencies": [],
"codeowners": []
"domain": "doods",
"name": "DOODS - Distributed Outside Object Detection Service",
"documentation": "https://www.home-assistant.io/integrations/doods",
"requirements": ["pydoods==1.0.2", "pillow==6.2.1"],
"dependencies": [],
"codeowners": []
}

View File

@@ -3,7 +3,9 @@
def dsmr_transform(value):
"""Transform DSMR version value to right format."""
return float(value) / 10
if value.isdigit():
return float(value) / 10
return value
def tariff_transform(value):

View File

@@ -3,7 +3,7 @@
"name": "Environment Canada",
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
"requirements": [
"env_canada==0.0.30"
"env_canada==0.0.31"
],
"dependencies": [],
"codeowners": [

View File

@@ -1,4 +1,5 @@
"""Helper classes for Google Assistant integration."""
from abc import ABC, abstractmethod
from asyncio import gather
from collections.abc import Mapping
import logging
@@ -35,7 +36,7 @@ SYNC_DELAY = 15
_LOGGER = logging.getLogger(__name__)
class AbstractConfig:
class AbstractConfig(ABC):
"""Hold the configuration for Google Assistant."""
_unsub_report_state = None
@@ -95,9 +96,13 @@ class AbstractConfig:
"""Return the user ID to be used for actions received via the local SDK."""
raise NotImplementedError
@abstractmethod
def get_agent_user_id(self, context):
"""Get agent user ID from context."""
@abstractmethod
def should_expose(self, state) -> bool:
"""Return if entity should be exposed."""
raise NotImplementedError
def should_2fa(self, state):
"""If an entity should have 2FA checked."""

View File

@@ -121,6 +121,10 @@ class GoogleConfig(AbstractConfig):
return is_default_exposed or explicit_expose
def get_agent_user_id(self, context):
"""Get agent user ID making request."""
return context.user_id
def should_2fa(self, state):
"""If an entity should have 2FA checked."""
return True

View File

@@ -79,7 +79,7 @@ async def async_devices_sync(hass, data, payload):
EVENT_SYNC_RECEIVED, {"request_id": data.request_id}, context=data.context
)
agent_user_id = data.context.user_id
agent_user_id = data.config.get_agent_user_id(data.context)
devices = await asyncio.gather(
*(

View File

@@ -303,6 +303,7 @@ class HomeKit:
def setup(self):
"""Set up bridge and accessory driver."""
# pylint: disable=import-outside-toplevel
from .accessories import HomeBridge, HomeDriver
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.stop)

View File

@@ -88,8 +88,11 @@ class Fan(HomeAccessory):
)
if CHAR_ROTATION_SPEED in chars:
# Initial value is set to 100 because 0 is a special value (off). 100 is
# an arbitrary non-zero value. It is updated immediately by update_state
# to set to the correct initial value.
self.char_speed = serv_fan.configure_char(
CHAR_ROTATION_SPEED, value=0, setter_callback=self.set_speed
CHAR_ROTATION_SPEED, value=100, setter_callback=self.set_speed
)
if CHAR_SWING_MODE in chars:
@@ -156,7 +159,22 @@ class Fan(HomeAccessory):
speed = new_state.attributes.get(ATTR_SPEED)
hk_speed_value = self.speed_mapping.speed_to_homekit(speed)
if hk_speed_value is not None and self.char_speed.value != hk_speed_value:
self.char_speed.set_value(hk_speed_value)
# If the homeassistant component reports its speed as the first entry
# in its speed list but is not off, the hk_speed_value is 0. But 0
# is a special value in homekit. When you turn on a homekit accessory
# it will try to restore the last rotation speed state which will be
# the last value saved by char_speed.set_value. But if it is set to
# 0, HomeKit will update the rotation speed to 100 as it thinks 0 is
# off.
#
# Therefore, if the hk_speed_value is 0 and the device is still on,
# the rotation speed is mapped to 1 otherwise the update is ignored
# in order to avoid this incorrect behavior.
if hk_speed_value == 0:
if state == STATE_ON:
self.char_speed.set_value(1)
else:
self.char_speed.set_value(hk_speed_value)
# Handle Oscillating
if self.char_swing is not None:

View File

@@ -82,8 +82,11 @@ class Light(HomeAccessory):
)
if CHAR_BRIGHTNESS in self.chars:
# Initial value is set to 100 because 0 is a special value (off). 100 is
# an arbitrary non-zero value. It is updated immediately by update_state
# to set to the correct initial value.
self.char_brightness = serv_light.configure_char(
CHAR_BRIGHTNESS, value=0, setter_callback=self.set_brightness
CHAR_BRIGHTNESS, value=100, setter_callback=self.set_brightness
)
if CHAR_COLOR_TEMPERATURE in self.chars:
min_mireds = self.hass.states.get(self.entity_id).attributes.get(
@@ -183,7 +186,21 @@ class Light(HomeAccessory):
if not self._flag[CHAR_BRIGHTNESS] and isinstance(brightness, int):
brightness = round(brightness / 255 * 100, 0)
if self.char_brightness.value != brightness:
self.char_brightness.set_value(brightness)
# The homeassistant component might report its brightness as 0 but is
# not off. But 0 is a special value in homekit. When you turn on a
# homekit accessory it will try to restore the last brightness state
# which will be the last value saved by char_brightness.set_value.
# But if it is set to 0, HomeKit will update the brightness to 100 as
# it thinks 0 is off.
#
# Therefore, if the the brighness is 0 and the device is still on,
# the brightness is mapped to 1 otherwise the update is ignored in
# order to avoid this incorrect behavior.
if brightness == 0:
if state == STATE_ON:
self.char_brightness.set_value(1)
else:
self.char_brightness.set_value(brightness)
self._flag[CHAR_BRIGHTNESS] = False
# Handle color temperature

View File

@@ -2,9 +2,7 @@
import asyncio
from datetime import timedelta
import logging
from typing import Tuple
from PIL import ImageDraw
import voluptuous as vol
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME, CONF_ENTITY_ID, CONF_NAME
@@ -65,46 +63,6 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE.extend(PLATFORM_SCHEMA.schema)
def draw_box(
draw: ImageDraw,
box: Tuple[float, float, float, float],
img_width: int,
img_height: int,
text: str = "",
color: Tuple[int, int, int] = (255, 255, 0),
) -> None:
"""
Draw a bounding box on and image.
The bounding box is defined by the tuple (y_min, x_min, y_max, x_max)
where the coordinates are floats in the range [0.0, 1.0] and
relative to the width and height of the image.
For example, if an image is 100 x 200 pixels (height x width) and the bounding
box is `(0.1, 0.2, 0.5, 0.9)`, the upper-left and bottom-right coordinates of
the bounding box will be `(40, 10)` to `(180, 50)` (in (x,y) coordinates).
"""
line_width = 3
font_height = 8
y_min, x_min, y_max, x_max = box
(left, right, top, bottom) = (
x_min * img_width,
x_max * img_width,
y_min * img_height,
y_max * img_height,
)
draw.line(
[(left, top), (left, bottom), (right, bottom), (right, top), (left, top)],
width=line_width,
fill=color,
)
if text:
draw.text(
(left + line_width, abs(top - line_width - font_height)), text, fill=color
)
async def async_setup(hass, config):
"""Set up the image processing."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)

View File

@@ -2,11 +2,7 @@
"domain": "image_processing",
"name": "Image processing",
"documentation": "https://www.home-assistant.io/integrations/image_processing",
"requirements": [
"pillow==6.2.1"
],
"dependencies": [
"camera"
],
"requirements": [],
"dependencies": ["camera"],
"codeowners": []
}

View File

@@ -63,7 +63,7 @@ class RachioControllerBinarySensor(BinarySensorDevice):
return
# For this device
self._handle_update()
self._handle_update(args, kwargs)
@abstractmethod
def _poll_update(self, data=None) -> bool:
@@ -119,9 +119,9 @@ class RachioControllerOnlineBinarySensor(RachioControllerBinarySensor):
def _handle_update(self, *args, **kwargs) -> None:
"""Handle an update to the state of this sensor."""
if args[0][KEY_SUBTYPE] == SUBTYPE_ONLINE:
if args[0][0][KEY_SUBTYPE] == SUBTYPE_ONLINE:
self._state = True
elif args[0][KEY_SUBTYPE] == SUBTYPE_OFFLINE:
elif args[0][0][KEY_SUBTYPE] == SUBTYPE_OFFLINE:
self._state = False
self.schedule_update_ha_state()

View File

@@ -107,7 +107,7 @@ class RachioStandbySwitch(RachioSwitch):
dispatcher_connect(
hass, SIGNAL_RACHIO_CONTROLLER_UPDATE, self._handle_any_update
)
super().__init__(controller, poll=False)
super().__init__(controller, poll=True)
self._poll_update(controller.init_data)
@property
@@ -134,9 +134,9 @@ class RachioStandbySwitch(RachioSwitch):
def _handle_update(self, *args, **kwargs) -> None:
"""Update the state using webhook data."""
if args[0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_ON:
if args[0][0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_ON:
self._state = True
elif args[0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_OFF:
elif args[0][0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_OFF:
self._state = False
self.schedule_update_ha_state()

View File

@@ -2,11 +2,7 @@
"domain": "ring",
"name": "Ring",
"documentation": "https://www.home-assistant.io/integrations/ring",
"requirements": [
"ring_doorbell==0.2.3"
],
"dependencies": [
"ffmpeg"
],
"requirements": ["ring_doorbell==0.2.8"],
"dependencies": ["ffmpeg"],
"codeowners": []
}

View File

@@ -2,7 +2,7 @@
"domain": "seven_segments",
"name": "Seven segments",
"documentation": "https://www.home-assistant.io/integrations/seven_segments",
"requirements": [],
"requirements": ["pillow==6.2.1"],
"dependencies": [],
"codeowners": []
}

View File

@@ -3,7 +3,7 @@
"name": "Smartthings",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/smartthings",
"requirements": ["pysmartapp==0.3.2", "pysmartthings==0.6.9"],
"requirements": ["pysmartapp==0.3.2", "pysmartthings==0.7.0"],
"dependencies": ["webhook"],
"after_dependencies": ["cloud"],
"codeowners": ["@andrewsayre"]

View File

@@ -2,9 +2,7 @@
"domain": "starlingbank",
"name": "Starlingbank",
"documentation": "https://www.home-assistant.io/integrations/starlingbank",
"requirements": [
"starlingbank==3.1"
],
"requirements": ["starlingbank==3.2"],
"dependencies": [],
"codeowners": []
}

View File

@@ -15,11 +15,11 @@ from homeassistant.components.image_processing import (
CONF_SOURCE,
PLATFORM_SCHEMA,
ImageProcessingEntity,
draw_box,
)
from homeassistant.core import split_entity_id
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
from homeassistant.util.pil import draw_box
_LOGGER = logging.getLogger(__name__)

View File

@@ -2,7 +2,12 @@
"domain": "tensorflow",
"name": "Tensorflow",
"documentation": "https://www.home-assistant.io/integrations/tensorflow",
"requirements": ["tensorflow==1.13.2", "numpy==1.17.4", "protobuf==3.6.1"],
"requirements": [
"tensorflow==1.13.2",
"numpy==1.17.4",
"protobuf==3.6.1",
"pillow==6.2.1"
],
"dependencies": [],
"codeowners": []
}

View File

@@ -131,6 +131,9 @@ class UniFiClientTracker(ScannerEntity):
self.is_wired = self.client.mac not in controller.wireless_clients
self.wired_bug = None
if self.is_wired != self.client.is_wired:
self.wired_bug = dt_util.utcnow() - self.controller.option_detection_time
@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""

View File

@@ -1,7 +1,7 @@
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 0
MINOR_VERSION = 103
PATCH_VERSION = "1"
PATCH_VERSION = "6"
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 6, 1)

View File

@@ -3,7 +3,7 @@ import asyncio
from pathlib import Path
import logging
import os
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Set
from homeassistant.exceptions import HomeAssistantError
import homeassistant.util.package as pkg_util
@@ -28,16 +28,19 @@ class RequirementsNotFound(HomeAssistantError):
async def async_get_integration_with_requirements(
hass: HomeAssistant, domain: str
hass: HomeAssistant, domain: str, done: Set[str] = None
) -> Integration:
"""Get an integration with installed requirements.
This can raise IntegrationNotFound if manifest or integration
is invalid, RequirementNotFound if there was some type of
failure to install requirements.
Does not handle circular dependencies.
"""
if done is None:
done = {domain}
else:
done.add(domain)
integration = await async_get_integration(hass, domain)
if hass.config.skip_pip:
@@ -48,11 +51,18 @@ async def async_get_integration_with_requirements(
hass, integration.domain, integration.requirements
)
deps = integration.dependencies + (integration.after_dependencies or [])
deps_to_check = [
dep
for dep in integration.dependencies + (integration.after_dependencies or [])
if dep not in done
]
if deps:
if deps_to_check:
await asyncio.gather(
*[async_get_integration_with_requirements(hass, dep) for dep in deps]
*[
async_get_integration_with_requirements(hass, dep, done)
for dep in deps_to_check
]
)
return integration

47
homeassistant/util/pil.py Normal file
View File

@@ -0,0 +1,47 @@
"""PIL utilities.
Can only be used by integrations that have pillow in their requirements.
"""
from typing import Tuple
from PIL import ImageDraw
def draw_box(
draw: ImageDraw,
box: Tuple[float, float, float, float],
img_width: int,
img_height: int,
text: str = "",
color: Tuple[int, int, int] = (255, 255, 0),
) -> None:
"""
Draw a bounding box on and image.
The bounding box is defined by the tuple (y_min, x_min, y_max, x_max)
where the coordinates are floats in the range [0.0, 1.0] and
relative to the width and height of the image.
For example, if an image is 100 x 200 pixels (height x width) and the bounding
box is `(0.1, 0.2, 0.5, 0.9)`, the upper-left and bottom-right coordinates of
the bounding box will be `(40, 10)` to `(180, 50)` (in (x,y) coordinates).
"""
line_width = 3
font_height = 8
y_min, x_min, y_max, x_max = box
(left, right, top, bottom) = (
x_min * img_width,
x_max * img_width,
y_min * img_height,
y_max * img_height,
)
draw.line(
[(left, top), (left, bottom), (right, bottom), (right, top), (left, top)],
width=line_width,
fill=color,
)
if text:
draw.text(
(left + line_width, abs(top - line_width - font_height)), text, fill=color
)

View File

@@ -475,7 +475,7 @@ enocean==0.50
enturclient==0.2.1
# homeassistant.components.environment_canada
env_canada==0.0.30
env_canada==0.0.31
# homeassistant.components.envirophat
# envirophat==0.0.6
@@ -980,9 +980,11 @@ piglow==1.2.4
# homeassistant.components.pilight
pilight==0.1.1
# homeassistant.components.image_processing
# homeassistant.components.doods
# homeassistant.components.proxy
# homeassistant.components.qrcode
# homeassistant.components.seven_segments
# homeassistant.components.tensorflow
pillow==6.2.1
# homeassistant.components.dominos
@@ -1483,7 +1485,7 @@ pysma==0.3.4
pysmartapp==0.3.2
# homeassistant.components.smartthings
pysmartthings==0.6.9
pysmartthings==0.7.0
# homeassistant.components.smarty
pysmarty==0.8
@@ -1730,7 +1732,7 @@ rfk101py==0.0.1
rflink==0.0.46
# homeassistant.components.ring
ring_doorbell==0.2.3
ring_doorbell==0.2.8
# homeassistant.components.fleetgo
ritassist==0.9.2
@@ -1868,7 +1870,7 @@ sqlalchemy==1.3.11
starline==0.1.3
# homeassistant.components.starlingbank
starlingbank==3.1
starlingbank==3.2
# homeassistant.components.statsd
statsd==3.2.1

View File

@@ -320,11 +320,6 @@ pexpect==4.6.0
# homeassistant.components.pilight
pilight==0.1.1
# homeassistant.components.image_processing
# homeassistant.components.proxy
# homeassistant.components.qrcode
pillow==6.2.1
# homeassistant.components.plex
plexapi==3.3.0
@@ -495,7 +490,7 @@ pysma==0.3.4
pysmartapp==0.3.2
# homeassistant.components.smartthings
pysmartthings==0.6.9
pysmartthings==0.7.0
# homeassistant.components.soma
pysoma==0.0.10
@@ -549,7 +544,7 @@ restrictedpython==5.0
rflink==0.0.46
# homeassistant.components.ring
ring_doorbell==0.2.3
ring_doorbell==0.2.8
# homeassistant.components.yamaha
rxv==0.6.0

View File

@@ -102,13 +102,17 @@ async def test_handler_google_actions(hass):
reqid = "5711642932632160983"
data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]}
config = await cloud.client.get_google_config()
resp = await cloud.client.async_google_message(data)
with patch(
"hass_nabucasa.Cloud._decode_claims",
return_value={"cognito:username": "myUserName"},
):
await cloud.client.get_google_config()
resp = await cloud.client.async_google_message(data)
assert resp["requestId"] == reqid
payload = resp["payload"]
assert payload["agentUserId"] == config.cloud_user
assert payload["agentUserId"] == "myUserName"
devices = payload["devices"]
assert len(devices) == 1

View File

@@ -323,32 +323,53 @@ async def test_hassio_update_instance(hass):
"""Test we can update an existing config entry."""
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_BRIDGEID: "id", config_flow.CONF_HOST: "1.2.3.4"},
data={
config_flow.CONF_BRIDGEID: "id",
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 40850,
config_flow.CONF_API_KEY: "secret",
},
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
data={config_flow.CONF_HOST: "mock-deconz", config_flow.CONF_SERIAL: "id"},
data={
config_flow.CONF_HOST: "mock-deconz",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "updated",
config_flow.CONF_SERIAL: "id",
},
context={"source": "hassio"},
)
assert result["type"] == "abort"
assert result["reason"] == "updated_instance"
assert entry.data[config_flow.CONF_HOST] == "mock-deconz"
assert entry.data[config_flow.CONF_PORT] == 8080
assert entry.data[config_flow.CONF_API_KEY] == "updated"
async def test_hassio_dont_update_instance(hass):
"""Test we can update an existing config entry."""
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_BRIDGEID: "id", config_flow.CONF_HOST: "1.2.3.4"},
data={
config_flow.CONF_BRIDGEID: "id",
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "secret",
},
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
data={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_SERIAL: "id"},
data={
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "secret",
config_flow.CONF_SERIAL: "id",
},
context={"source": "hassio"},
)

View File

@@ -63,6 +63,10 @@ class MockConfig(helpers.AbstractConfig):
"""Return local SDK webhook id."""
return self._local_sdk_user_id
def get_agent_user_id(self, context):
"""Get agent user ID making request."""
return context.user_id
def should_expose(self, state):
"""Expose it all."""
return self._should_expose is None or self._should_expose(state)

View File

@@ -197,7 +197,10 @@ async def test_fan_speed(hass, hk_driver, cls, events):
)
await hass.async_block_till_done()
acc = cls.fan(hass, hk_driver, "Fan", entity_id, 2, None)
assert acc.char_speed.value == 0
# Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the
# speed to 100 when turning on a fan on a freshly booted up server.
assert acc.char_speed.value != 0
await hass.async_add_job(acc.run)
assert (

View File

@@ -101,7 +101,9 @@ async def test_light_brightness(hass, hk_driver, cls, events):
await hass.async_block_till_done()
acc = cls.light(hass, hk_driver, "Light", entity_id, 2, None)
assert acc.char_brightness.value == 0
# Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the
# brightness to 100 when turning on a light on a freshly booted up server.
assert acc.char_brightness.value != 0
await hass.async_add_job(acc.run)
await hass.async_block_till_done()

View File

@@ -60,6 +60,7 @@ async def setup_unifi_integration(
clients_response,
devices_response,
clients_all_response,
known_wireless_clients=None,
):
"""Create the UniFi controller."""
if UNIFI_CONFIG not in hass.data:
@@ -77,6 +78,11 @@ async def setup_unifi_integration(
entry_id=1,
)
if known_wireless_clients:
hass.data[UNIFI_WIRELESS_CLIENTS].update_data(
known_wireless_clients, config_entry
)
mock_client_responses = deque()
mock_client_responses.append(clients_response)

View File

@@ -44,6 +44,14 @@ CLIENT_3 = {
"last_seen": 1562600145,
"mac": "00:00:00:00:00:03",
}
CLIENT_4 = {
"essid": "ssid",
"hostname": "client_4",
"ip": "10.0.0.4",
"is_wired": True,
"last_seen": 1562600145,
"mac": "00:00:00:00:00:04",
}
DEVICE_1 = {
"board_rev": 3,
@@ -103,16 +111,20 @@ async def test_no_clients(hass):
async def test_tracked_devices(hass):
"""Test the update_items function with some clients."""
client_4_copy = copy(CLIENT_4)
client_4_copy["last_seen"] = dt_util.as_timestamp(dt_util.utcnow())
controller = await setup_unifi_integration(
hass,
ENTRY_CONFIG,
options={CONF_SSID_FILTER: ["ssid"]},
sites=SITES,
clients_response=[CLIENT_1, CLIENT_2, CLIENT_3],
clients_response=[CLIENT_1, CLIENT_2, CLIENT_3, client_4_copy],
devices_response=[DEVICE_1, DEVICE_2],
clients_all_response={},
known_wireless_clients=(CLIENT_4["mac"],),
)
assert len(hass.states.async_all()) == 5
assert len(hass.states.async_all()) == 6
client_1 = hass.states.get("device_tracker.client_1")
assert client_1 is not None
@@ -125,6 +137,11 @@ async def test_tracked_devices(hass):
client_3 = hass.states.get("device_tracker.client_3")
assert client_3 is None
# Wireless client with wired bug, if bug active on restart mark device away
client_4 = hass.states.get("device_tracker.client_4")
assert client_4 is not None
assert client_4.state == "not_home"
device_1 = hass.states.get("device_tracker.device_1")
assert device_1 is not None
assert device_1.state == "not_home"