diff --git a/homeassistant/components/alexa.py b/homeassistant/components/alexa.py index c121268f93d551..3547e86dad161b 100644 --- a/homeassistant/components/alexa.py +++ b/homeassistant/components/alexa.py @@ -171,7 +171,7 @@ def post(self, request): if 'simple' in intent_response.card: alexa_response.add_card( - 'simple', intent_response.card['simple']['title'], + CardType.simple, intent_response.card['simple']['title'], intent_response.card['simple']['content']) return self.json(alexa_response) @@ -208,8 +208,8 @@ def add_card(self, card_type, title, content): self.card = card return - card["title"] = title.async_render(self.variables) - card["content"] = content.async_render(self.variables) + card["title"] = title + card["content"] = content self.card = card def add_speech(self, speech_type, text): @@ -218,9 +218,6 @@ def add_speech(self, speech_type, text): key = 'ssml' if speech_type == SpeechType.ssml else 'text' - if isinstance(text, template.Template): - text = text.async_render(self.variables) - self.speech = { 'type': speech_type.value, key: text diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py index b8daab8150320f..3c038125616790 100644 --- a/homeassistant/components/cover/zwave.py +++ b/homeassistant/components/cover/zwave.py @@ -27,10 +27,12 @@ def get_device(hass, values, node_config, **kwargs): zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and values.primary.index == 0): return ZwaveRollershutter(hass, values, invert_buttons) - elif (values.primary.command_class in [ - zwave.const.COMMAND_CLASS_SWITCH_BINARY, - zwave.const.COMMAND_CLASS_BARRIER_OPERATOR]): - return ZwaveGarageDoor(values) + elif (values.primary.command_class == + zwave.const.COMMAND_CLASS_SWITCH_BINARY): + return ZwaveGarageDoorSwitch(values) + elif (values.primary.command_class == + zwave.const.COMMAND_CLASS_BARRIER_OPERATOR): + return ZwaveGarageDoorBarrier(values) return None @@ -104,8 +106,8 @@ def stop_cover(self, **kwargs): self._network.manager.releaseButton(self._open_id) -class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice): - """Representation of an Zwave garage door device.""" +class ZwaveGarageDoorBase(zwave.ZWaveDeviceEntity, CoverDevice): + """Base class for a Zwave garage door device.""" def __init__(self, values): """Initialize the zwave garage door.""" @@ -118,6 +120,37 @@ def update_properties(self): self._state = self.values.primary.data _LOGGER.debug("self._state=%s", self._state) + @property + def device_class(self): + """Return the class of this device, from component DEVICE_CLASSES.""" + return 'garage' + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_GARAGE + + +class ZwaveGarageDoorSwitch(ZwaveGarageDoorBase): + """Representation of a switch based Zwave garage door device.""" + + @property + def is_closed(self): + """Return the current position of Zwave garage door.""" + return not self._state + + def close_cover(self): + """Close the garage door.""" + self.values.primary.data = False + + def open_cover(self): + """Open the garage door.""" + self.values.primary.data = True + + +class ZwaveGarageDoorBarrier(ZwaveGarageDoorBase): + """Representation of a barrier operator Zwave garage door device.""" + @property def is_opening(self): """Return true if cover is in an opening state.""" @@ -140,13 +173,3 @@ def close_cover(self): def open_cover(self): """Open the garage door.""" self.values.primary.data = "Opened" - - @property - def device_class(self): - """Return the class of this device, from component DEVICE_CLASSES.""" - return 'garage' - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORT_GARAGE diff --git a/homeassistant/components/light/tplink.py b/homeassistant/components/light/tplink.py index 333661870d14d2..beca5fc6aec728 100644 --- a/homeassistant/components/light/tplink.py +++ b/homeassistant/components/light/tplink.py @@ -31,7 +31,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): def brightness_to_percentage(byt): """Convert brightness from absolute 0..255 to percentage.""" - return (byt*100.0)/255.0 + return int((byt*100.0)/255.0) def brightness_from_percentage(percent): @@ -53,6 +53,8 @@ def __init__(self, smartbulb, name): self._name = name self._state = None + self._color_temp = None + self._brightness = None _LOGGER.debug("Setting up TP-Link Smart Bulb") @property @@ -70,7 +72,6 @@ def turn_on(self, **kwargs): if ATTR_BRIGHTNESS in kwargs: brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) self.smartbulb.brightness = brightness_to_percentage(brightness) - self.smartbulb.state = self.smartbulb.BULB_STATE_ON def turn_off(self): @@ -80,33 +81,31 @@ def turn_off(self): @property def color_temp(self): """Return the color temperature of this light in mireds for HA.""" - if self.smartbulb.is_color: - if (self.smartbulb.color_temp is not None and - self.smartbulb.color_temp != 0): - return kelvin_to_mired(self.smartbulb.color_temp) - else: - return None - else: - return None + return self._color_temp @property def brightness(self): """Return the brightness of this light between 0..255.""" - return brightness_from_percentage(self.smartbulb.brightness) + return self._brightness @property def is_on(self): """True if device is on.""" - return self.smartbulb.state == \ - self.smartbulb.BULB_STATE_ON + return self._state def update(self): """Update the TP-Link Bulb's state.""" from pyHS100 import SmartPlugException try: - self._state = self.smartbulb.state == \ - self.smartbulb.BULB_STATE_ON - + self._state = ( + self.smartbulb.state == self.smartbulb.BULB_STATE_ON) + self._brightness = brightness_from_percentage( + self.smartbulb.brightness) + if self.smartbulb.is_color: + if (self.smartbulb.color_temp is not None and + self.smartbulb.color_temp != 0): + self._color_temp = kelvin_to_mired( + self.smartbulb.color_temp) except (SmartPlugException, OSError) as ex: _LOGGER.warning('Could not read state for %s: %s', self.name, ex) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 28c42c5699c778..b04640d7a8a6ed 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -71,7 +71,7 @@ def brightness(self): def turn_off(self, **kwargs): """Instruct the group lights to turn off.""" - return self._group.set_state(0) + self._group.set_state(0) def turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" @@ -82,7 +82,11 @@ def turn_on(self, **kwargs): def update(self): """Fetch new state data for this group.""" - self._group.update() + from pytradfri import RequestTimeout + try: + self._group.update() + except RequestTimeout: + _LOGGER.warning("Tradfri update request timed out") class Tradfri(Light): @@ -153,7 +157,7 @@ def rgb_color(self): def turn_off(self, **kwargs): """Instruct the light to turn off.""" - return self._light_control.set_state(False) + self._light_control.set_state(False) def turn_on(self, **kwargs): """ @@ -181,7 +185,11 @@ def turn_on(self, **kwargs): def update(self): """Fetch new state data for this light.""" - self._light.update() + from pytradfri import RequestTimeout + try: + self._light.update() + except RequestTimeout: + _LOGGER.warning("Tradfri update request timed out") # Handle Hue lights paired with the gateway # hex_color is 0 when bulb is unreachable diff --git a/homeassistant/components/media_player/kodi.py b/homeassistant/components/media_player/kodi.py index 3764677c84732b..7f339796466bbe 100644 --- a/homeassistant/components/media_player/kodi.py +++ b/homeassistant/components/media_player/kodi.py @@ -361,7 +361,7 @@ def async_on_quit(self, sender, data): self._properties = {} self._item = {} self._app_properties = {} - self.hass.async_add_job(self.async_update_ha_state()) + self.hass.async_add_job(self._ws_server.close()) @asyncio.coroutine def _get_players(self): @@ -410,6 +410,8 @@ def ws_loop_wrapper(): # Kodi abruptly ends ws connection when exiting. We will try # to reconnect on the next poll. pass + # Update HA state after Kodi disconnects + self.hass.async_add_job(self.async_update_ha_state()) # Create a task instead of adding a tracking job, since this task will # run until the websocket connection is closed. diff --git a/homeassistant/components/media_player/pioneer.py b/homeassistant/components/media_player/pioneer.py index ba08003b9bf01e..25424224c703ec 100644 --- a/homeassistant/components/media_player/pioneer.py +++ b/homeassistant/components/media_player/pioneer.py @@ -85,14 +85,13 @@ def telnet_request(cls, telnet, command, expected_prefix): return None def telnet_command(self, command): - """Establish a telnet connection and sends `command`.""" + """Establish a telnet connection and sends command.""" try: try: - telnet = telnetlib.Telnet(self._host, - self._port, - self._timeout) - except ConnectionRefusedError: - _LOGGER.debug("Pioneer %s refused connection", self._name) + telnet = telnetlib.Telnet( + self._host, self._port, self._timeout) + except (ConnectionRefusedError, OSError): + _LOGGER.warning("Pioneer %s refused connection", self._name) return telnet.write(command.encode("ASCII") + b"\r") telnet.read_very_eager() # skip response @@ -105,8 +104,8 @@ def update(self): """Get the latest details from the device.""" try: telnet = telnetlib.Telnet(self._host, self._port, self._timeout) - except ConnectionRefusedError: - _LOGGER.debug("Pioneer %s refused connection", self._name) + except (ConnectionRefusedError, OSError): + _LOGGER.warning("Pioneer %s refused connection", self._name) return False pwstate = self.telnet_request(telnet, "?P", "PWR") diff --git a/homeassistant/components/sensor/google_wifi.py b/homeassistant/components/sensor/google_wifi.py index d878f4f8d20b3f..ba3dbfeacc8e72 100644 --- a/homeassistant/components/sensor/google_wifi.py +++ b/homeassistant/components/sensor/google_wifi.py @@ -37,32 +37,32 @@ MONITORED_CONDITIONS = { ATTR_CURRENT_VERSION: [ - 'Current Version', + ['software', 'softwareVersion'], None, 'mdi:checkbox-marked-circle-outline' ], ATTR_NEW_VERSION: [ - 'New Version', + ['software', 'updateNewVersion'], None, 'mdi:update' ], ATTR_UPTIME: [ - 'Uptime', + ['system', 'uptime'], 'days', 'mdi:timelapse' ], ATTR_LAST_RESTART: [ - 'Last Network Restart', + ['system', 'uptime'], None, 'mdi:restart' ], ATTR_LOCAL_IP: [ - 'Local IP Address', + ['wan', 'localIpAddress'], None, 'mdi:access-point-network' ], ATTR_STATUS: [ - 'Status', + ['wan', 'online'], None, 'mdi:google' ] @@ -80,13 +80,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Google Wifi sensor.""" name = config.get(CONF_NAME) host = config.get(CONF_HOST) + conditions = config.get(CONF_MONITORED_CONDITIONS) - api = GoogleWifiAPI(host) + api = GoogleWifiAPI(host, conditions) + dev = [] + for condition in conditions: + dev.append(GoogleWifiSensor(hass, api, name, condition)) - sensors = [GoogleWifiSensor(hass, api, name, condition) - for condition in config[CONF_MONITORED_CONDITIONS]] - - add_devices(sensors, True) + add_devices(dev, True) class GoogleWifiSensor(Entity): @@ -141,13 +142,13 @@ def update(self): class GoogleWifiAPI(object): """Get the latest data and update the states.""" - def __init__(self, host): + def __init__(self, host, conditions): """Initialize the data object.""" uri = 'http://' resource = "{}{}{}".format(uri, host, ENDPOINT) - self._request = requests.Request('GET', resource).prepare() self.raw_data = None + self.conditions = conditions self.data = { ATTR_CURRENT_VERSION: STATE_UNKNOWN, ATTR_NEW_VERSION: STATE_UNKNOWN, @@ -163,39 +164,49 @@ def __init__(self, host): def update(self): """Get the latest data from the router.""" try: - _LOGGER.error("Before request") with requests.Session() as sess: response = sess.send( self._request, timeout=10) self.raw_data = response.json() - _LOGGER.error(self.raw_data) self.data_format() self.availiable = True except ValueError: - _LOGGER.error("Unable to fetch data from Google Wifi") + _LOGGER.error('Unable to fetch data from Google Wifi') self.availiable = False self.raw_data = None def data_format(self): """Format raw data into easily accessible dict.""" - for key, value in self.raw_data.items(): - if key == 'software': - self.data[ATTR_CURRENT_VERSION] = value['softwareVersion'] - if value['updateNewVersion'] == '0.0.0.0': - self.data[ATTR_NEW_VERSION] = 'Latest' - else: - self.data[ATTR_NEW_VERSION] = value['updateNewVersion'] - elif key == 'system': - self.data[ATTR_UPTIME] = value['uptime'] / (3600 * 24) - last_restart = dt.now() - timedelta(seconds=value['uptime']) - self.data[ATTR_LAST_RESTART] = \ - last_restart.strftime("%Y-%m-%d %H:%M:%S") - elif key == 'wan': - if value['online']: - self.data[ATTR_STATUS] = 'Online' - else: - self.data[ATTR_STATUS] = 'Offline' - if not value['ipAddress']: - self.data[ATTR_LOCAL_IP] = STATE_UNKNOWN - else: - self.data[ATTR_LOCAL_IP] = value['localIpAddress'] + for attr_key in self.conditions: + value = MONITORED_CONDITIONS[attr_key] + try: + primary_key = value[0][0] + sensor_key = value[0][1] + if primary_key in self.raw_data: + sensor_value = self.raw_data[primary_key][sensor_key] + # Format sensor for better readability + if (attr_key == ATTR_NEW_VERSION and + sensor_value == '0.0.0.0'): + sensor_value = 'Latest' + elif attr_key == ATTR_UPTIME: + sensor_value /= 3600 * 24 + elif attr_key == ATTR_LAST_RESTART: + last_restart = (dt.now() - + timedelta(seconds=sensor_value)) + sensor_value = last_restart.strftime(('%Y-%m-%d ' + '%H:%M:%S')) + elif attr_key == ATTR_STATUS: + if sensor_value: + sensor_value = 'Online' + else: + sensor_value = 'Offline' + elif attr_key == ATTR_LOCAL_IP: + if not self.raw_data['wan']['online']: + sensor_value = STATE_UNKNOWN + + self.data[attr_key] = sensor_value + except KeyError: + _LOGGER.error('Router does not support %s field. ' + 'Please remove %s from monitored_conditions.', + sensor_key, attr_key) + self.data[attr_key] = STATE_UNKNOWN diff --git a/homeassistant/components/telegram_bot/webhooks.py b/homeassistant/components/telegram_bot/webhooks.py index 30d81930b44665..055f68884a6f3e 100644 --- a/homeassistant/components/telegram_bot/webhooks.py +++ b/homeassistant/components/telegram_bot/webhooks.py @@ -6,7 +6,6 @@ """ import asyncio import datetime as dt -from functools import partial from ipaddress import ip_network import logging @@ -70,9 +69,18 @@ def async_setup_platform(hass, config): _LOGGER.error("Invalid telegram webhook %s must be https", handler_url) return False + def _try_to_set_webhook(): + retry_num = 0 + while retry_num < 3: + try: + return bot.setWebhook(handler_url, timeout=5) + except telegram.error.TimedOut: + retry_num += 1 + _LOGGER.warning("Timeout trying to set webhook (retry #%d)", + retry_num) + if current_status and current_status['url'] != handler_url: - result = yield from hass.async_add_job( - partial(bot.setWebhook, handler_url, timeout=10)) + result = yield from hass.async_add_job(_try_to_set_webhook) if result: _LOGGER.info("Set new telegram webhook %s", handler_url) else: diff --git a/homeassistant/components/zwave/const.py b/homeassistant/components/zwave/const.py index 4b18ef464750d4..b72d9eb0cffa3f 100644 --- a/homeassistant/components/zwave/const.py +++ b/homeassistant/components/zwave/const.py @@ -345,6 +345,9 @@ INDEX_ALARM_LEVEL = 1 INDEX_ALARM_ACCESS_CONTROL = 9 +# https://github.com/OpenZWave/open-zwave/blob/de1c0e60edf1d1bee81f1ae54b1f58e66c6fd8ed/cpp/src/command_classes/BarrierOperator.cpp#L69 +INDEX_BARRIER_OPERATOR_LABEL = 1 + # https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/DoorLock.cpp#L77 INDEX_DOOR_LOCK_LOCK = 0 diff --git a/homeassistant/components/zwave/discovery_schemas.py b/homeassistant/components/zwave/discovery_schemas.py index c880aeb3b316ec..f38bc308649863 100644 --- a/homeassistant/components/zwave/discovery_schemas.py +++ b/homeassistant/components/zwave/discovery_schemas.py @@ -92,7 +92,7 @@ const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_DIM], const.DISC_OPTIONAL: True, }})}, - {const.DISC_COMPONENT: 'cover', # Garage Door + {const.DISC_COMPONENT: 'cover', # Garage Door Switch const.DISC_GENERIC_DEVICE_CLASS: [ const.GENERIC_TYPE_SWITCH_MULTILEVEL, const.GENERIC_TYPE_ENTRY_CONTROL], @@ -105,11 +105,36 @@ const.SPECIFIC_TYPE_SECURE_DOOR], const.DISC_VALUES: dict(DEFAULT_VALUES_SCHEMA, **{ const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_BARRIER_OPERATOR, - const.COMMAND_CLASS_SWITCH_BINARY], + const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_BINARY], const.DISC_GENRE: const.GENRE_USER, }})}, + {const.DISC_COMPONENT: 'cover', # Garage Door Barrier + const.DISC_GENERIC_DEVICE_CLASS: [ + const.GENERIC_TYPE_SWITCH_MULTILEVEL, + const.GENERIC_TYPE_ENTRY_CONTROL], + const.DISC_SPECIFIC_DEVICE_CLASS: [ + const.SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL, + const.SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL, + const.SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL, + const.SPECIFIC_TYPE_MOTOR_MULTIPOSITION, + const.SPECIFIC_TYPE_SECURE_BARRIER_ADDON, + const.SPECIFIC_TYPE_SECURE_DOOR], + const.DISC_VALUES: dict(DEFAULT_VALUES_SCHEMA, **{ + const.DISC_PRIMARY: { + const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_BARRIER_OPERATOR], + const.DISC_INDEX: [const.INDEX_BARRIER_OPERATOR_LABEL], + }})}, + {const.DISC_COMPONENT: 'fan', + const.DISC_GENERIC_DEVICE_CLASS: [ + const.GENERIC_TYPE_SWITCH_MULTILEVEL], + const.DISC_SPECIFIC_DEVICE_CLASS: [ + const.SPECIFIC_TYPE_FAN_SWITCH], + const.DISC_VALUES: dict(DEFAULT_VALUES_SCHEMA, **{ + const.DISC_PRIMARY: { + const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], + const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_LEVEL], + const.DISC_TYPE: const.TYPE_BYTE, + }})}, {const.DISC_COMPONENT: 'light', const.DISC_GENERIC_DEVICE_CLASS: [ const.GENERIC_TYPE_SWITCH_MULTILEVEL, diff --git a/homeassistant/const.py b/homeassistant/const.py index 9bec41ea8f4f68..fd73817f9b7400 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 50 -PATCH_VERSION = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) diff --git a/homeassistant/scripts/__init__.py b/homeassistant/scripts/__init__.py index f6934aef8f6591..be39540682c194 100644 --- a/homeassistant/scripts/__init__.py +++ b/homeassistant/scripts/__init__.py @@ -51,7 +51,7 @@ def run(args: List) -> int: req, target=deps_dir, constraints=os.path.join( os.path.dirname(__file__), os.pardir, CONSTRAINT_FILE)) if not returncode: - print('Aborting scipt, could not install dependency', req) + print('Aborting script, could not install dependency', req) return 1 return script.run(args[1:]) # type: ignore diff --git a/tests/components/cover/test_zwave.py b/tests/components/cover/test_zwave.py index fe9abe7172c685..4b9be9f5e00a4a 100644 --- a/tests/components/cover/test_zwave.py +++ b/tests/components/cover/test_zwave.py @@ -32,16 +32,30 @@ def test_get_device_detects_rollershutter(hass, mock_openzwave): assert isinstance(device, zwave.ZwaveRollershutter) -def test_get_device_detects_garagedoor(hass, mock_openzwave): +def test_get_device_detects_garagedoor_switch(hass, mock_openzwave): """Test device returns garage door.""" node = MockNode() - value = MockValue(data=0, node=node, + value = MockValue(data=False, node=node, + command_class=const.COMMAND_CLASS_SWITCH_BINARY) + values = MockEntityValues(primary=value, node=node) + + device = zwave.get_device(hass=hass, node=node, values=values, + node_config={}) + assert isinstance(device, zwave.ZwaveGarageDoorSwitch) + assert device.device_class == "garage" + assert device.supported_features == SUPPORT_OPEN | SUPPORT_CLOSE + + +def test_get_device_detects_garagedoor_barrier(hass, mock_openzwave): + """Test device returns garage door.""" + node = MockNode() + value = MockValue(data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR) values = MockEntityValues(primary=value, node=node) device = zwave.get_device(hass=hass, node=node, values=values, node_config={}) - assert isinstance(device, zwave.ZwaveGarageDoor) + assert isinstance(device, zwave.ZwaveGarageDoorBarrier) assert device.device_class == "garage" assert device.supported_features == SUPPORT_OPEN | SUPPORT_CLOSE @@ -158,7 +172,39 @@ def test_roller_reverse_open_close(hass, mock_openzwave): assert value_id == close_value.value_id -def test_garage_value_changed(hass, mock_openzwave): +def test_switch_garage_value_changed(hass, mock_openzwave): + """Test position changed.""" + node = MockNode() + value = MockValue(data=False, node=node, + command_class=const.COMMAND_CLASS_SWITCH_BINARY) + values = MockEntityValues(primary=value, node=node) + device = zwave.get_device(hass=hass, node=node, values=values, + node_config={}) + + assert device.is_closed + + value.data = True + value_changed(value) + assert not device.is_closed + + +def test_switch_garage_commands(hass, mock_openzwave): + """Test position changed.""" + node = MockNode() + value = MockValue(data=False, node=node, + command_class=const.COMMAND_CLASS_SWITCH_BINARY) + values = MockEntityValues(primary=value, node=node) + device = zwave.get_device(hass=hass, node=node, values=values, + node_config={}) + + assert value.data is False + device.open_cover() + assert value.data is True + device.close_cover() + assert value.data is False + + +def test_barrier_garage_value_changed(hass, mock_openzwave): """Test position changed.""" node = MockNode() value = MockValue(data="Closed", node=node, @@ -190,7 +236,7 @@ def test_garage_value_changed(hass, mock_openzwave): assert device.is_closing -def test_garage_commands(hass, mock_openzwave): +def test_barrier_garage_commands(hass, mock_openzwave): """Test position changed.""" node = MockNode() value = MockValue(data="Closed", node=node, diff --git a/tests/components/sensor/test_google_wifi.py b/tests/components/sensor/test_google_wifi.py index 978ec99236c224..b45261b6daa092 100644 --- a/tests/components/sensor/test_google_wifi.py +++ b/tests/components/sensor/test_google_wifi.py @@ -26,6 +26,10 @@ '"wan": {"localIpAddress":"next", "online":false,' '"ipAddress":false}}') +MOCK_DATA_MISSING = ('{"software": {},' + '"system": {},' + '"wan": {}}') + class TestGoogleWifiSetup(unittest.TestCase): """Tests for setting up the Google Wifi switch platform.""" @@ -47,9 +51,11 @@ def test_setup_minimum(self, mock_req): mock_req.get(resource, status_code=200) self.assertTrue(setup_component(self.hass, 'sensor', { 'sensor': { - 'platform': 'google_wifi' + 'platform': 'google_wifi', + 'monitored_conditions': ['uptime'] } })) + assert_setup_component(1, 'sensor') @requests_mock.Mocker() def test_setup_get(self, mock_req): @@ -95,7 +101,9 @@ def setup_api(self, data, mock_req): now = datetime(1970, month=1, day=1) with patch('homeassistant.util.dt.now', return_value=now): mock_req.get(resource, text=data, status_code=200) - self.api = google_wifi.GoogleWifiAPI("localhost") + conditions = google_wifi.MONITORED_CONDITIONS.keys() + self.api = google_wifi.GoogleWifiAPI("localhost", + conditions) self.name = NAME self.sensor_dict = dict() for condition, cond_list in google_wifi.MONITORED_CONDITIONS.items(): @@ -188,6 +196,18 @@ def test_update_when_value_changed(self, mock_req): else: self.assertEqual('next', sensor.state) + @requests_mock.Mocker() + def test_when_api_data_missing(self, mock_req): + """Test state logs an error when data is missing.""" + self.setup_api(MOCK_DATA_MISSING, mock_req) + now = datetime(1970, month=1, day=1) + with patch('homeassistant.util.dt.now', return_value=now): + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.fake_delay(2) + sensor.update() + self.assertEqual(STATE_UNKNOWN, sensor.state) + def test_update_when_unavailiable(self): """Test state updates when Google Wifi unavailiable.""" self.api.update = Mock('google_wifi.GoogleWifiAPI.update', diff --git a/tests/components/test_alexa.py b/tests/components/test_alexa.py index eb8391c3e0d045..4e082441064d11 100644 --- a/tests/components/test_alexa.py +++ b/tests/components/test_alexa.py @@ -86,7 +86,12 @@ def mock_service(call): "CallServiceIntent": { "speech": { "type": "plain", - "text": "Service called", + "text": "Service called for {{ ZodiacSign }}", + }, + "card": { + "type": "simple", + "title": "Card title for {{ ZodiacSign }}", + "content": "Card content: {{ ZodiacSign }}", }, "action": { "service": "test.alexa", @@ -319,6 +324,13 @@ def test_intent_request_calling_service(alexa_client): assert call.data.get("entity_id") == ["switch.test"] assert call.data.get("hello") == "virgo" + data = yield from req.json() + assert data['response']['card']['title'] == 'Card title for virgo' + assert data['response']['card']['content'] == 'Card content: virgo' + assert data['response']['outputSpeech']['type'] == 'PlainText' + assert data['response']['outputSpeech']['text'] == \ + 'Service called for virgo' + @asyncio.coroutine def test_intent_session_ended_request(alexa_client):