diff --git a/homeassistant/components/alarm_control_panel/totalconnect.py b/homeassistant/components/alarm_control_panel/totalconnect.py index ba8155fde93..a272a22abe5 100644 --- a/homeassistant/components/alarm_control_panel/totalconnect.py +++ b/homeassistant/components/alarm_control_panel/totalconnect.py @@ -18,7 +18,7 @@ from homeassistant.const import ( STATE_ALARM_ARMED_CUSTOM_BYPASS) -REQUIREMENTS = ['total_connect_client==0.24'] +REQUIREMENTS = ['total_connect_client==0.25'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/cloud/__init__.py b/homeassistant/components/cloud/__init__.py index ff1b2344ac8..9517971b16d 100644 --- a/homeassistant/components/cloud/__init__.py +++ b/homeassistant/components/cloud/__init__.py @@ -24,7 +24,7 @@ from .const import ( CONF_USER_POOL_ID, DOMAIN, MODE_DEV, MODE_PROD) from .prefs import CloudPreferences -REQUIREMENTS = ['hass-nabucasa==0.8'] +REQUIREMENTS = ['hass-nabucasa==0.10'] DEPENDENCIES = ['http'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 6e05299ec52..30b9d350df6 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -21,7 +21,7 @@ from homeassistant.loader import bind_hass from .storage import async_setup_frontend_storage -REQUIREMENTS = ['home-assistant-frontend==20190320.0'] +REQUIREMENTS = ['home-assistant-frontend==20190321.0'] DOMAIN = 'frontend' DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log', diff --git a/homeassistant/components/smartthings/smartapp.py b/homeassistant/components/smartthings/smartapp.py index 0b64bac5956..548a38711bd 100644 --- a/homeassistant/components/smartthings/smartapp.py +++ b/homeassistant/components/smartthings/smartapp.py @@ -65,6 +65,8 @@ def validate_webhook_requirements(hass: HomeAssistantType) -> bool: """Ensure HASS is setup properly to receive webhooks.""" if cloud.async_active_subscription(hass): return True + if hass.data[DOMAIN][CONF_CLOUDHOOK_URL] is not None: + return True return get_webhook_url(hass).lower().startswith('https://') diff --git a/homeassistant/components/stream/worker.py b/homeassistant/components/stream/worker.py index 3a3e19d9703..d0196761968 100644 --- a/homeassistant/components/stream/worker.py +++ b/homeassistant/components/stream/worker.py @@ -63,21 +63,29 @@ def stream_worker(hass, stream, quit_event): first_packet = True sequence = 1 audio_packets = {} + last_dts = None while not quit_event.is_set(): try: packet = next(container.demux(video_stream)) if packet.dts is None: + if first_packet: + continue # If we get a "flushing" packet, the stream is done - raise StopIteration + raise StopIteration("No dts in packet") except (av.AVError, StopIteration) as ex: # End of stream, clear listeners and stop thread for fmt, _ in outputs.items(): hass.loop.call_soon_threadsafe( stream.outputs[fmt].put, None) - _LOGGER.error("Error demuxing stream: %s", ex) + _LOGGER.error("Error demuxing stream: %s", str(ex)) break + # Skip non monotonically increasing dts in feed + if not first_packet and last_dts >= packet.dts: + continue + last_dts = packet.dts + # Reset segment on every keyframe if packet.is_keyframe: # Save segment to outputs diff --git a/homeassistant/components/tado/__init__.py b/homeassistant/components/tado/__init__.py index 56fc0cb704c..6808729685e 100644 --- a/homeassistant/components/tado/__init__.py +++ b/homeassistant/components/tado/__init__.py @@ -10,7 +10,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.const import CONF_USERNAME, CONF_PASSWORD from homeassistant.util import Throttle -REQUIREMENTS = ['python-tado==0.2.8'] +REQUIREMENTS = ['python-tado==0.2.9'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/tado/climate.py b/homeassistant/components/tado/climate.py index d5f152bbd76..f698906caa7 100644 --- a/homeassistant/components/tado/climate.py +++ b/homeassistant/components/tado/climate.py @@ -1,12 +1,12 @@ """Support for Tado to create a climate device for each zone.""" import logging -from homeassistant.const import (PRECISION_TENTHS, TEMP_CELSIUS) from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( - SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE) + SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE, SUPPORT_ON_OFF) +from homeassistant.const import ( + ATTR_TEMPERATURE, PRECISION_TENTHS, TEMP_CELSIUS) from homeassistant.util.temperature import convert as convert_temperature -from homeassistant.const import ATTR_TEMPERATURE from homeassistant.components.tado import DATA_TADO _LOGGER = logging.getLogger(__name__) @@ -41,7 +41,8 @@ OPERATION_LIST = { CONST_MODE_OFF: 'Off', } -SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE +SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE | + SUPPORT_ON_OFF) def setup_platform(hass, config, add_entities, discovery_info=None): @@ -199,6 +200,27 @@ class TadoClimate(ClimateDevice): """Return the temperature we try to reach.""" return self._target_temp + @property + def is_on(self): + """Return true if heater is on.""" + return self._device_is_active + + def turn_off(self): + """Turn device off.""" + _LOGGER.info("Switching mytado.com to OFF for zone %s", + self.zone_name) + + self._current_operation = CONST_MODE_OFF + self._control_heating() + + def turn_on(self): + """Turn device on.""" + _LOGGER.info("Switching mytado.com to %s mode for zone %s", + self._overlay_mode, self.zone_name) + + self._current_operation = self._overlay_mode + self._control_heating() + def set_temperature(self, **kwargs): """Set new target temperature.""" temperature = kwargs.get(ATTR_TEMPERATURE) diff --git a/homeassistant/components/tado/device_tracker.py b/homeassistant/components/tado/device_tracker.py index 8804bef5616..7812bbd812b 100644 --- a/homeassistant/components/tado/device_tracker.py +++ b/homeassistant/components/tado/device_tracker.py @@ -52,9 +52,9 @@ class TadoDeviceScanner(DeviceScanner): # If there's a home_id, we need a different API URL if self.home_id is None: - self.tadoapiurl = 'https://auth.tado.com/api/v2/me' + self.tadoapiurl = 'https://my.tado.com/api/v2/me' else: - self.tadoapiurl = 'https://auth.tado.com/api/v2' \ + self.tadoapiurl = 'https://my.tado.com/api/v2' \ '/homes/{home_id}/mobileDevices' # The API URL always needs a username and password diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index d0848222549..1e98118e09f 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -179,7 +179,7 @@ class ZhaEntity(RestoreEntity, entity.Entity): async def async_update(self): """Retrieve latest state.""" - for channel in self.cluster_channels: + for channel in self.cluster_channels.values(): if hasattr(channel, 'async_update'): await channel.async_update() diff --git a/homeassistant/const.py b/homeassistant/const.py index df0146cde62..ba33a566c9a 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 90 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 5, 3) diff --git a/requirements_all.txt b/requirements_all.txt index 87e9f53bba9..45d9386cbd8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -524,7 +524,7 @@ habitipy==0.2.0 hangups==0.4.6 # homeassistant.components.cloud -hass-nabucasa==0.8 +hass-nabucasa==0.10 # homeassistant.components.mqtt.server hbmqtt==0.9.4 @@ -554,7 +554,7 @@ hole==0.3.0 holidays==0.9.9 # homeassistant.components.frontend -home-assistant-frontend==20190320.0 +home-assistant-frontend==20190321.0 # homeassistant.components.zwave homeassistant-pyozw==0.1.2 @@ -1394,7 +1394,7 @@ python-songpal==0.0.9.1 python-synology==0.2.0 # homeassistant.components.tado -python-tado==0.2.8 +python-tado==0.2.9 # homeassistant.components.telegram_bot python-telegram-bot==11.1.0 @@ -1710,7 +1710,7 @@ todoist-python==7.0.17 toonapilib==3.2.2 # homeassistant.components.alarm_control_panel.totalconnect -total_connect_client==0.24 +total_connect_client==0.25 # homeassistant.components.tplink_lte tp-connected==0.0.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 935bc5689e1..3340bb40d9c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -114,7 +114,7 @@ ha-ffmpeg==1.11 hangups==0.4.6 # homeassistant.components.cloud -hass-nabucasa==0.8 +hass-nabucasa==0.10 # homeassistant.components.mqtt.server hbmqtt==0.9.4 @@ -126,7 +126,7 @@ hdate==0.8.7 holidays==0.9.9 # homeassistant.components.frontend -home-assistant-frontend==20190320.0 +home-assistant-frontend==20190321.0 # homeassistant.components.homekit_controller homekit[IP]==0.13.0 diff --git a/tests/components/smartthings/test_init.py b/tests/components/smartthings/test_init.py index a5edc93fce6..4daf37cac55 100644 --- a/tests/components/smartthings/test_init.py +++ b/tests/components/smartthings/test_init.py @@ -189,6 +189,33 @@ async def test_config_entry_loads_platforms( assert forward_mock.call_count == len(SUPPORTED_PLATFORMS) +async def test_config_entry_loads_unconnected_cloud( + hass, config_entry, app, installed_app, + device, smartthings_mock, subscription_factory, scene): + """Test entry loads during startup when cloud isn't connected.""" + setattr(hass.config_entries, '_entries', [config_entry]) + hass.data[DOMAIN][CONF_CLOUDHOOK_URL] = "https://test.cloud" + hass.config.api.base_url = 'http://0.0.0.0' + api = smartthings_mock.return_value + api.app.return_value = mock_coro(return_value=app) + api.installed_app.return_value = mock_coro(return_value=installed_app) + api.devices.side_effect = \ + lambda *args, **kwargs: mock_coro(return_value=[device]) + api.scenes.return_value = mock_coro(return_value=[scene]) + mock_token = Mock() + mock_token.access_token.return_value = str(uuid4()) + mock_token.refresh_token.return_value = str(uuid4()) + api.generate_tokens.return_value = mock_coro(return_value=mock_token) + subscriptions = [subscription_factory(capability) + for capability in device.capabilities] + api.subscriptions.return_value = mock_coro(return_value=subscriptions) + with patch.object(hass.config_entries, 'async_forward_entry_setup', + return_value=mock_coro()) as forward_mock: + assert await smartthings.async_setup_entry(hass, config_entry) + await hass.async_block_till_done() + assert forward_mock.call_count == len(SUPPORTED_PLATFORMS) + + async def test_unload_entry(hass, config_entry): """Test entries are unloaded correctly.""" connect_disconnect = Mock()