mirror of
https://github.com/home-assistant/core.git
synced 2026-01-09 00:58:32 +01:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d52eba484 | ||
|
|
8e05a5c12b | ||
|
|
25fe6ec536 | ||
|
|
30a1fedce8 | ||
|
|
4e569ac0c3 | ||
|
|
8a6370f7c9 | ||
|
|
874cccd530 | ||
|
|
1bea8747ac | ||
|
|
e54394e906 | ||
|
|
c384fd9653 | ||
|
|
3560fa754c | ||
|
|
101a6ab07c | ||
|
|
eb1ca20cfc | ||
|
|
49d51e5040 | ||
|
|
31130f902b | ||
|
|
8603f1a047 | ||
|
|
a34786fb2d | ||
|
|
8e51c12010 | ||
|
|
e3d176f479 | ||
|
|
e37619acc1 | ||
|
|
85fa88c8b3 | ||
|
|
7935c2504e | ||
|
|
7018806802 | ||
|
|
a7f34bbce9 | ||
|
|
e6683b4c84 |
@@ -33,6 +33,8 @@ STATES = {
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the Egardia platform."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
device = EgardiaAlarm(
|
||||
discovery_info['name'],
|
||||
hass.data[EGARDIA_DEVICE],
|
||||
|
||||
@@ -49,8 +49,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up an Arlo IP Camera."""
|
||||
arlo = hass.data.get(DATA_ARLO)
|
||||
if not arlo:
|
||||
@@ -60,7 +59,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||
for camera in arlo.cameras:
|
||||
cameras.append(ArloCam(hass, camera, config))
|
||||
|
||||
async_add_devices(cameras, True)
|
||||
add_devices(cameras, True)
|
||||
|
||||
|
||||
class ArloCam(Camera):
|
||||
|
||||
@@ -20,7 +20,7 @@ from homeassistant.helpers.aiohttp_client import (
|
||||
async_get_clientsession)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
REQUIREMENTS = ['py-synology==0.1.5']
|
||||
REQUIREMENTS = ['py-synology==0.2.0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ class GenericThermostat(ClimateDevice):
|
||||
"""List of available operation modes."""
|
||||
return self._operation_list
|
||||
|
||||
def set_operation_mode(self, operation_mode):
|
||||
async def async_set_operation_mode(self, operation_mode):
|
||||
"""Set operation mode."""
|
||||
if operation_mode == STATE_HEAT:
|
||||
self._current_operation = STATE_HEAT
|
||||
|
||||
@@ -68,22 +68,18 @@ class TadoDeviceScanner(DeviceScanner):
|
||||
self.websession = async_create_clientsession(
|
||||
hass, cookie_jar=aiohttp.CookieJar(unsafe=True, loop=hass.loop))
|
||||
|
||||
self.success_init = self._update_info()
|
||||
self.success_init = asyncio.run_coroutine_threadsafe(
|
||||
self._async_update_info(), hass.loop
|
||||
).result()
|
||||
|
||||
_LOGGER.info("Scanner initialized")
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_scan_devices(self):
|
||||
async def async_scan_devices(self):
|
||||
"""Scan for devices and return a list containing found device ids."""
|
||||
info = self._update_info()
|
||||
|
||||
# Don't yield if we got None
|
||||
if info is not None:
|
||||
yield from info
|
||||
|
||||
await self._async_update_info()
|
||||
return [device.mac for device in self.last_results]
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_get_device_name(self, device):
|
||||
async def async_get_device_name(self, device):
|
||||
"""Return the name of the given device or None if we don't know."""
|
||||
filter_named = [result.name for result in self.last_results
|
||||
if result.mac == device]
|
||||
@@ -93,7 +89,7 @@ class TadoDeviceScanner(DeviceScanner):
|
||||
return None
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def _update_info(self):
|
||||
async def _async_update_info(self):
|
||||
"""
|
||||
Query Tado for device marked as at home.
|
||||
|
||||
@@ -111,14 +107,14 @@ class TadoDeviceScanner(DeviceScanner):
|
||||
home_id=self.home_id, username=self.username,
|
||||
password=self.password)
|
||||
|
||||
response = yield from self.websession.get(url)
|
||||
response = await self.websession.get(url)
|
||||
|
||||
if response.status != 200:
|
||||
_LOGGER.warning(
|
||||
"Error %d on %s.", response.status, self.tadoapiurl)
|
||||
return
|
||||
return False
|
||||
|
||||
tado_json = yield from response.json()
|
||||
tado_json = await response.json()
|
||||
|
||||
except (asyncio.TimeoutError, aiohttp.ClientError):
|
||||
_LOGGER.error("Cannot load Tado data")
|
||||
@@ -139,7 +135,7 @@ class TadoDeviceScanner(DeviceScanner):
|
||||
|
||||
self.last_results = last_results
|
||||
|
||||
_LOGGER.info(
|
||||
_LOGGER.debug(
|
||||
"Tado presence query successful, %d device(s) at home",
|
||||
len(self.last_results)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,16 @@ from homeassistant.core import callback
|
||||
from homeassistant.const import (
|
||||
CONF_NAME, STATE_UNAVAILABLE, ATTR_SUPPORTED_FEATURES)
|
||||
from homeassistant.components import (
|
||||
switch, light, cover, media_player, group, fan, scene, script, climate,
|
||||
climate,
|
||||
cover,
|
||||
fan,
|
||||
group,
|
||||
input_boolean,
|
||||
light,
|
||||
media_player,
|
||||
scene,
|
||||
script,
|
||||
switch,
|
||||
)
|
||||
|
||||
from . import trait
|
||||
@@ -33,15 +42,16 @@ HANDLERS = Registry()
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN_TO_GOOGLE_TYPES = {
|
||||
climate.DOMAIN: TYPE_THERMOSTAT,
|
||||
cover.DOMAIN: TYPE_SWITCH,
|
||||
fan.DOMAIN: TYPE_SWITCH,
|
||||
group.DOMAIN: TYPE_SWITCH,
|
||||
input_boolean.DOMAIN: TYPE_SWITCH,
|
||||
light.DOMAIN: TYPE_LIGHT,
|
||||
media_player.DOMAIN: TYPE_SWITCH,
|
||||
scene.DOMAIN: TYPE_SCENE,
|
||||
script.DOMAIN: TYPE_SCENE,
|
||||
switch.DOMAIN: TYPE_SWITCH,
|
||||
fan.DOMAIN: TYPE_SWITCH,
|
||||
light.DOMAIN: TYPE_LIGHT,
|
||||
cover.DOMAIN: TYPE_SWITCH,
|
||||
media_player.DOMAIN: TYPE_SWITCH,
|
||||
climate.DOMAIN: TYPE_THERMOSTAT,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -157,12 +157,12 @@ class Thermostat(HomeAccessory):
|
||||
|
||||
# Update current temperature
|
||||
current_temp = new_state.attributes.get(ATTR_CURRENT_TEMPERATURE)
|
||||
if current_temp is not None:
|
||||
if isinstance(current_temp, (int, float)):
|
||||
self.char_current_temp.set_value(current_temp)
|
||||
|
||||
# Update target temperature
|
||||
target_temp = new_state.attributes.get(ATTR_TEMPERATURE)
|
||||
if target_temp is not None:
|
||||
if isinstance(target_temp, (int, float)):
|
||||
if not self.temperature_flag_target_state:
|
||||
self.char_target_temp.set_value(target_temp,
|
||||
should_callback=False)
|
||||
|
||||
@@ -181,6 +181,7 @@ class HueBridge(object):
|
||||
self.allow_in_emulated_hue = allow_in_emulated_hue
|
||||
self.allow_hue_groups = allow_hue_groups
|
||||
|
||||
self.available = True
|
||||
self.bridge = None
|
||||
self.lights = {}
|
||||
self.lightgroups = {}
|
||||
|
||||
@@ -17,7 +17,7 @@ import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.helpers.script import Script
|
||||
|
||||
REQUIREMENTS = ['xknx==0.8.4']
|
||||
REQUIREMENTS = ['xknx==0.8.5']
|
||||
|
||||
DOMAIN = "knx"
|
||||
DATA_KNX = "data_knx"
|
||||
@@ -241,7 +241,7 @@ class KNXModule(object):
|
||||
async def telegram_received_cb(self, telegram):
|
||||
"""Call invoked after a KNX telegram was received."""
|
||||
self.hass.bus.fire('knx_event', {
|
||||
'address': telegram.group_address.str(),
|
||||
'address': str(telegram.group_address),
|
||||
'data': telegram.payload.value
|
||||
})
|
||||
# False signals XKNX to proceed with processing telegrams.
|
||||
|
||||
@@ -123,15 +123,20 @@ def unthrottled_update_lights(hass, bridge, add_devices):
|
||||
api = bridge.get_api()
|
||||
except phue.PhueRequestTimeout:
|
||||
_LOGGER.warning("Timeout trying to reach the bridge")
|
||||
bridge.available = False
|
||||
return
|
||||
except ConnectionRefusedError:
|
||||
_LOGGER.error("The bridge refused the connection")
|
||||
bridge.available = False
|
||||
return
|
||||
except socket.error:
|
||||
# socket.error when we cannot reach Hue
|
||||
_LOGGER.exception("Cannot reach the bridge")
|
||||
bridge.available = False
|
||||
return
|
||||
|
||||
bridge.available = True
|
||||
|
||||
new_lights = process_lights(
|
||||
hass, api, bridge,
|
||||
lambda **kw: update_lights(hass, bridge, add_devices, **kw))
|
||||
@@ -261,10 +266,14 @@ class HueLight(Light):
|
||||
"""Return true if device is on."""
|
||||
if self.is_group:
|
||||
return self.info['state']['any_on']
|
||||
elif self.allow_unreachable:
|
||||
return self.info['state']['on']
|
||||
return self.info['state']['reachable'] and \
|
||||
self.info['state']['on']
|
||||
return self.info['state']['on']
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return if light is available."""
|
||||
return self.bridge.available and (self.is_group or
|
||||
self.allow_unreachable or
|
||||
self.info['state']['reachable'])
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
|
||||
@@ -17,7 +17,7 @@ from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.util.color as color_util
|
||||
|
||||
REQUIREMENTS = ['iglo==1.2.6']
|
||||
REQUIREMENTS = ['iglo==1.2.7']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -89,7 +89,7 @@ class IGloLamp(Light):
|
||||
@property
|
||||
def effect_list(self):
|
||||
"""Return the list of supported effects."""
|
||||
return self._lamp.effect_list
|
||||
return self._lamp.effect_list()
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
|
||||
@@ -7,7 +7,6 @@ https://home-assistant.io/components/media_player.cast/
|
||||
# pylint: disable=import-error
|
||||
import logging
|
||||
import threading
|
||||
import functools
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -35,7 +34,6 @@ CONF_IGNORE_CEC = 'ignore_cec'
|
||||
CAST_SPLASH = 'https://home-assistant.io/images/cast/splash.png'
|
||||
|
||||
DEFAULT_PORT = 8009
|
||||
SOCKET_CLIENT_RETRIES = 10
|
||||
|
||||
SUPPORT_CAST = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
|
||||
SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PREVIOUS_TRACK | \
|
||||
@@ -78,7 +76,7 @@ def _setup_internal_discovery(hass: HomeAssistantType) -> None:
|
||||
try:
|
||||
# pylint: disable=protected-access
|
||||
chromecast = pychromecast._get_chromecast_from_host(
|
||||
mdns, blocking=True, tries=SOCKET_CLIENT_RETRIES)
|
||||
mdns, blocking=True)
|
||||
except pychromecast.ChromecastConnectionError:
|
||||
_LOGGER.debug("Can't set up cast with mDNS info %s. "
|
||||
"Assuming it's not a Chromecast", mdns)
|
||||
@@ -183,9 +181,8 @@ async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
else:
|
||||
# Manually add a "normal" Chromecast, we can do that without discovery.
|
||||
try:
|
||||
func = functools.partial(pychromecast.Chromecast, *want_host,
|
||||
tries=SOCKET_CLIENT_RETRIES)
|
||||
chromecast = await hass.async_add_job(func)
|
||||
chromecast = await hass.async_add_job(
|
||||
pychromecast.Chromecast, *want_host)
|
||||
except pychromecast.ChromecastConnectionError as err:
|
||||
_LOGGER.warning("Can't set up chromecast on %s: %s",
|
||||
want_host[0], err)
|
||||
|
||||
@@ -31,7 +31,7 @@ from homeassistant.helpers import script, config_validation as cv
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.util.yaml import dump
|
||||
|
||||
REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.5']
|
||||
REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.6']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -426,7 +426,17 @@ class SonosDevice(MediaPlayerDevice):
|
||||
self._play_mode = self.soco.play_mode
|
||||
self._night_sound = self.soco.night_mode
|
||||
self._speech_enhance = self.soco.dialog_mode
|
||||
self._favorites = self.soco.music_library.get_sonos_favorites()
|
||||
|
||||
self._favorites = []
|
||||
for fav in self.soco.music_library.get_sonos_favorites():
|
||||
# SoCo 0.14 raises a generic Exception on invalid xml in favorites.
|
||||
# Filter those out now so our list is safe to use.
|
||||
try:
|
||||
if fav.reference.get_uri():
|
||||
self._favorites.append(fav)
|
||||
# pylint: disable=broad-except
|
||||
except Exception:
|
||||
_LOGGER.debug("Ignoring invalid favorite '%s'", fav.title)
|
||||
|
||||
def _subscribe_to_player_events(self):
|
||||
"""Add event subscriptions."""
|
||||
@@ -886,7 +896,8 @@ class SonosDevice(MediaPlayerDevice):
|
||||
self.soco.unjoin()
|
||||
|
||||
for slave in slaves:
|
||||
slave.soco.join(self.soco)
|
||||
if slave.unique_id != self.unique_id:
|
||||
slave.soco.join(self.soco)
|
||||
|
||||
@soco_error()
|
||||
def unjoin(self):
|
||||
|
||||
@@ -144,7 +144,7 @@ class SQLSensor(Entity):
|
||||
data = res[self._column_name]
|
||||
for key, value in res.items():
|
||||
if isinstance(value, decimal.Decimal):
|
||||
value = float(decimal)
|
||||
value = float(value)
|
||||
self._attributes[key] = value
|
||||
except sqlalchemy.exc.SQLAlchemyError as err:
|
||||
_LOGGER.error("Error executing query %s: %s", self._query, err)
|
||||
|
||||
@@ -4,16 +4,19 @@ Support for WeMo switches.
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/switch.wemo/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.util import convert
|
||||
from homeassistant.const import (
|
||||
STATE_OFF, STATE_ON, STATE_STANDBY, STATE_UNKNOWN)
|
||||
from homeassistant.loader import get_component
|
||||
|
||||
DEPENDENCIES = ['wemo']
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -54,29 +57,35 @@ class WemoSwitch(SwitchDevice):
|
||||
self.maker_params = None
|
||||
self.coffeemaker_mode = None
|
||||
self._state = None
|
||||
self._available = True
|
||||
self._update_lock = None
|
||||
# look up model name once as it incurs network traffic
|
||||
self._model_name = self.wemo.model_name
|
||||
|
||||
wemo = get_component('wemo')
|
||||
wemo.SUBSCRIPTION_REGISTRY.register(self.wemo)
|
||||
wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback)
|
||||
|
||||
def _update_callback(self, _device, _type, _params):
|
||||
def _subscription_callback(self, _device, _type, _params):
|
||||
"""Update the state by the Wemo device."""
|
||||
_LOGGER.info("Subscription update for %s", _device)
|
||||
_LOGGER.info("Subscription update for %s", self.name)
|
||||
updated = self.wemo.subscription_update(_type, _params)
|
||||
self._update(force_update=(not updated))
|
||||
self.hass.add_job(
|
||||
self._async_locked_subscription_callback(not updated))
|
||||
|
||||
if not hasattr(self, 'hass'):
|
||||
async def _async_locked_subscription_callback(self, force_update):
|
||||
"""Helper to handle an update from a subscription."""
|
||||
# If an update is in progress, we don't do anything
|
||||
if self._update_lock.locked():
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
await self._async_locked_update(force_update)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""No polling needed with subscriptions."""
|
||||
if self._model_name == 'Insight':
|
||||
return True
|
||||
return False
|
||||
"""Device should poll.
|
||||
|
||||
Subscriptions push the state, however it won't detect if a device
|
||||
is no longer available. Use polling to detect if a device is available.
|
||||
"""
|
||||
return True
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
@@ -172,13 +181,7 @@ class WemoSwitch(SwitchDevice):
|
||||
@property
|
||||
def available(self):
|
||||
"""Return true if switch is available."""
|
||||
if self._model_name == 'Insight' and self.insight_params is None:
|
||||
return False
|
||||
if self._model_name == 'Maker' and self.maker_params is None:
|
||||
return False
|
||||
if self._model_name == 'CoffeeMaker' and self.coffeemaker_mode is None:
|
||||
return False
|
||||
return True
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
@@ -189,21 +192,46 @@ class WemoSwitch(SwitchDevice):
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self._state = WEMO_ON
|
||||
self.wemo.on()
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self._state = WEMO_OFF
|
||||
self.wemo.off()
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def update(self):
|
||||
"""Update WeMo state."""
|
||||
self._update(force_update=True)
|
||||
async def async_added_to_hass(self):
|
||||
"""Wemo switch added to HASS."""
|
||||
# Define inside async context so we know our event loop
|
||||
self._update_lock = asyncio.Lock()
|
||||
|
||||
def _update(self, force_update=True):
|
||||
registry = self.hass.components.wemo.SUBSCRIPTION_REGISTRY
|
||||
await self.hass.async_add_job(registry.register, self.wemo)
|
||||
registry.on(self.wemo, None, self._subscription_callback)
|
||||
|
||||
async def async_update(self):
|
||||
"""Update WeMo state.
|
||||
|
||||
Wemo has an aggressive retry logic that sometimes can take over a
|
||||
minute to return. If we don't get a state after 5 seconds, assume the
|
||||
Wemo switch is unreachable. If update goes through, it will be made
|
||||
available again.
|
||||
"""
|
||||
# If an update is in progress, we don't do anything
|
||||
if self._update_lock.locked():
|
||||
return
|
||||
|
||||
try:
|
||||
with async_timeout.timeout(5):
|
||||
await asyncio.shield(self._async_locked_update(True))
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.warning('Lost connection to %s', self.name)
|
||||
self._available = False
|
||||
|
||||
async def _async_locked_update(self, force_update):
|
||||
"""Try updating within an async lock."""
|
||||
async with self._update_lock:
|
||||
await self.hass.async_add_job(self._update, force_update)
|
||||
|
||||
def _update(self, force_update):
|
||||
"""Update the device state."""
|
||||
try:
|
||||
self._state = self.wemo.get_state(force_update)
|
||||
@@ -215,6 +243,11 @@ class WemoSwitch(SwitchDevice):
|
||||
self.maker_params = self.wemo.maker_params
|
||||
elif self._model_name == 'CoffeeMaker':
|
||||
self.coffeemaker_mode = self.wemo.mode
|
||||
|
||||
if not self._available:
|
||||
_LOGGER.info('Reconnected to %s', self.name)
|
||||
self._available = True
|
||||
except AttributeError as err:
|
||||
_LOGGER.warning("Could not update status for %s (%s)",
|
||||
self.name, err)
|
||||
self._available = False
|
||||
|
||||
@@ -19,7 +19,7 @@ from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_STOP, CONF_LIGHTS, CONF_EXCLUDE)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
REQUIREMENTS = ['pyvera==0.2.41']
|
||||
REQUIREMENTS = ['pyvera==0.2.42']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 65
|
||||
PATCH_VERSION = '2'
|
||||
PATCH_VERSION = '5'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
REQUIRED_PYTHON_VER = (3, 5, 3)
|
||||
|
||||
@@ -398,7 +398,7 @@ https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0
|
||||
# i2csense==0.0.4
|
||||
|
||||
# homeassistant.components.light.iglo
|
||||
iglo==1.2.6
|
||||
iglo==1.2.7
|
||||
|
||||
# homeassistant.components.ihc
|
||||
ihcsdk==2.2.0
|
||||
@@ -421,7 +421,7 @@ jsonpath==0.75
|
||||
jsonrpc-async==0.6
|
||||
|
||||
# homeassistant.components.media_player.kodi
|
||||
jsonrpc-websocket==0.5
|
||||
jsonrpc-websocket==0.6
|
||||
|
||||
# homeassistant.scripts.keyring
|
||||
keyring==11.0.0
|
||||
@@ -632,7 +632,7 @@ py-cpuinfo==3.3.0
|
||||
py-melissa-climate==1.0.6
|
||||
|
||||
# homeassistant.components.camera.synology
|
||||
py-synology==0.1.5
|
||||
py-synology==0.2.0
|
||||
|
||||
# homeassistant.components.hdmi_cec
|
||||
pyCEC==0.4.13
|
||||
@@ -1021,7 +1021,7 @@ pyunifi==2.13
|
||||
# pyuserinput==0.1.11
|
||||
|
||||
# homeassistant.components.vera
|
||||
pyvera==0.2.41
|
||||
pyvera==0.2.42
|
||||
|
||||
# homeassistant.components.media_player.vizio
|
||||
pyvizio==0.0.2
|
||||
@@ -1274,7 +1274,7 @@ xbee-helper==0.0.7
|
||||
xboxapi==0.1.1
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==0.8.4
|
||||
xknx==0.8.5
|
||||
|
||||
# homeassistant.components.media_player.bluesound
|
||||
# homeassistant.components.sensor.startca
|
||||
|
||||
@@ -135,7 +135,7 @@ class TestTemplateCover(unittest.TestCase):
|
||||
entity = self.hass.states.get('cover.test')
|
||||
attrs = dict()
|
||||
attrs['position'] = 42
|
||||
self.hass.states.async_set(
|
||||
self.hass.states.set(
|
||||
entity.entity_id, entity.state,
|
||||
attributes=attrs)
|
||||
self.hass.block_till_done()
|
||||
@@ -148,7 +148,7 @@ class TestTemplateCover(unittest.TestCase):
|
||||
self.hass.block_till_done()
|
||||
entity = self.hass.states.get('cover.test')
|
||||
attrs['position'] = 0.0
|
||||
self.hass.states.async_set(
|
||||
self.hass.states.set(
|
||||
entity.entity_id, entity.state,
|
||||
attributes=attrs)
|
||||
self.hass.block_till_done()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Test Google Smart Home."""
|
||||
from homeassistant.core import State
|
||||
from homeassistant.const import (
|
||||
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS)
|
||||
from homeassistant.setup import async_setup_component
|
||||
@@ -244,3 +245,17 @@ async def test_raising_error_trait(hass):
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_serialize_input_boolean():
|
||||
"""Test serializing an input boolean entity."""
|
||||
state = State('input_boolean.bla', 'on')
|
||||
entity = sh._GoogleEntity(None, BASIC_CONFIG, state)
|
||||
assert entity.sync_serialize() == {
|
||||
'id': 'input_boolean.bla',
|
||||
'attributes': {},
|
||||
'name': {'name': 'bla'},
|
||||
'traits': ['action.devices.traits.OnOff'],
|
||||
'type': 'action.devices.types.SWITCH',
|
||||
'willReportState': False,
|
||||
}
|
||||
|
||||
@@ -501,3 +501,45 @@ class TestHueLight(unittest.TestCase):
|
||||
|
||||
light = self.buildLight(info={}, is_group=True)
|
||||
self.assertIsNone(light.unique_id)
|
||||
|
||||
|
||||
def test_available():
|
||||
"""Test available property."""
|
||||
light = hue_light.HueLight(
|
||||
info={'state': {'reachable': False}},
|
||||
allow_unreachable=False,
|
||||
is_group=False,
|
||||
|
||||
light_id=None,
|
||||
bridge=mock.Mock(),
|
||||
update_lights_cb=None,
|
||||
allow_in_emulated_hue=False,
|
||||
)
|
||||
|
||||
assert light.available is False
|
||||
|
||||
light = hue_light.HueLight(
|
||||
info={'state': {'reachable': False}},
|
||||
allow_unreachable=True,
|
||||
is_group=False,
|
||||
|
||||
light_id=None,
|
||||
bridge=mock.Mock(),
|
||||
update_lights_cb=None,
|
||||
allow_in_emulated_hue=False,
|
||||
)
|
||||
|
||||
assert light.available is True
|
||||
|
||||
light = hue_light.HueLight(
|
||||
info={'state': {'reachable': False}},
|
||||
allow_unreachable=False,
|
||||
is_group=True,
|
||||
|
||||
light_id=None,
|
||||
bridge=mock.Mock(),
|
||||
update_lights_cb=None,
|
||||
allow_in_emulated_hue=False,
|
||||
)
|
||||
|
||||
assert light.available is True
|
||||
|
||||
@@ -123,7 +123,7 @@ def test_internal_discovery_callback_only_generates_once(hass):
|
||||
return_value=chromecast) as gen_chromecast:
|
||||
discover_cast('the-service', chromecast)
|
||||
mdns = (chromecast.host, chromecast.port, chromecast.uuid, None, None)
|
||||
gen_chromecast.assert_called_once_with(mdns, blocking=True, tries=10)
|
||||
gen_chromecast.assert_called_once_with(mdns, blocking=True)
|
||||
|
||||
discover_cast('the-service', chromecast)
|
||||
gen_chromecast.reset_mock()
|
||||
|
||||
@@ -309,7 +309,7 @@ def test_value_discovery_existing_entity(hass, mock_openzwave):
|
||||
'current_temperature'] is None
|
||||
|
||||
def mock_update(self):
|
||||
self.hass.async_add_job(self.async_update_ha_state)
|
||||
self.hass.add_job(self.async_update_ha_state)
|
||||
|
||||
with patch.object(zwave.node_entity.ZWaveBaseEntity,
|
||||
'maybe_schedule_update', new=mock_update):
|
||||
@@ -356,7 +356,7 @@ def test_power_schemes(hass, mock_openzwave):
|
||||
'switch.mock_node_mock_value').attributes
|
||||
|
||||
def mock_update(self):
|
||||
self.hass.async_add_job(self.async_update_ha_state)
|
||||
self.hass.add_job(self.async_update_ha_state)
|
||||
|
||||
with patch.object(zwave.node_entity.ZWaveBaseEntity,
|
||||
'maybe_schedule_update', new=mock_update):
|
||||
|
||||
Reference in New Issue
Block a user