diff --git a/homeassistant/components/blink/__init__.py b/homeassistant/components/blink/__init__.py index ac2a4574b9c..57500fcc8a6 100644 --- a/homeassistant/components/blink/__init__.py +++ b/homeassistant/components/blink/__init__.py @@ -15,7 +15,7 @@ from homeassistant.const import ( CONF_BINARY_SENSORS, CONF_SENSORS, CONF_FILENAME, CONF_MONITORED_CONDITIONS, TEMP_FAHRENHEIT) -REQUIREMENTS = ['blinkpy==0.11.1'] +REQUIREMENTS = ['blinkpy==0.11.2'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/lovelace/__init__.py b/homeassistant/components/lovelace/__init__.py index e6f122bce19..c3254d84a73 100644 --- a/homeassistant/components/lovelace/__init__.py +++ b/homeassistant/components/lovelace/__init__.py @@ -101,6 +101,8 @@ class LovelaceStorage: async def async_save(self, config): """Save config.""" + if self._data is None: + self._data = {'config': None} self._data['config'] = config await self._store.async_save(self._data) diff --git a/homeassistant/components/sensor/gtt.py b/homeassistant/components/sensor/gtt.py index f0e141f3549..a64c743381d 100644 --- a/homeassistant/components/sensor/gtt.py +++ b/homeassistant/components/sensor/gtt.py @@ -79,8 +79,7 @@ class GttSensor(Entity): def update(self): """Update device state.""" self.data.get_data() - next_time = datetime.strptime( - self.data.state_bus['time'][0]['run'], "%H:%M") + next_time = get_datetime(self.data.state_bus) self._state = next_time.isoformat() @@ -99,8 +98,7 @@ class GttData: def get_data(self): """Get the data from the api.""" self.bus_list = self._pygtt.get_by_stop(self._stop) - self.bus_list.sort(key=lambda b: - datetime.strptime(b['time'][0]['run'], "%H:%M")) + self.bus_list.sort(key=get_datetime) if self._bus_name is not None: self.state_bus = self.get_bus_by_name() @@ -113,3 +111,13 @@ class GttData: for bus in self.bus_list: if bus['bus_name'] == self._bus_name: return bus + + +def get_datetime(bus): + """Get the datetime from a bus.""" + bustime = datetime.strptime(bus['time'][0]['run'], "%H:%M") + now = datetime.now() + bustime = bustime.replace(year=now.year, month=now.month, day=now.day) + if bustime < now: + bustime = bustime + timedelta(days=1) + return bustime diff --git a/homeassistant/components/weather/ipma.py b/homeassistant/components/weather/ipma.py index a2f5058ac1e..fda0fef4f25 100644 --- a/homeassistant/components/weather/ipma.py +++ b/homeassistant/components/weather/ipma.py @@ -116,6 +116,9 @@ class IPMAWeather(WeatherEntity): @property def condition(self): """Return the current condition.""" + if not self._forecast: + return + return next((k for k, v in CONDITION_CLASSES.items() if self._forecast[0].idWeatherType in v), None) diff --git a/homeassistant/const.py b/homeassistant/const.py index ef9f7b38384..aaac6fecb73 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 86 -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/homeassistant/helpers/restore_state.py b/homeassistant/helpers/restore_state.py index 33b612b555a..355555ec9dc 100644 --- a/homeassistant/helpers/restore_state.py +++ b/homeassistant/helpers/restore_state.py @@ -4,7 +4,8 @@ import logging from datetime import timedelta, datetime from typing import Any, Dict, List, Set, Optional # noqa pylint_disable=unused-import -from homeassistant.core import HomeAssistant, callback, State, CoreState +from homeassistant.core import ( + HomeAssistant, callback, State, CoreState, valid_entity_id) from homeassistant.const import ( EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) import homeassistant.util.dt as dt_util @@ -80,7 +81,8 @@ class RestoreStateData(): else: data.last_states = { item['state']['entity_id']: StoredState.from_dict(item) - for item in stored_states} + for item in stored_states + if valid_entity_id(item['state']['entity_id'])} _LOGGER.debug( 'Created cache with %s', list(data.last_states)) diff --git a/requirements_all.txt b/requirements_all.txt index 4f96d15c61f..549b8fe3503 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -196,7 +196,7 @@ bellows==0.7.0 bimmer_connected==0.5.3 # homeassistant.components.blink -blinkpy==0.11.1 +blinkpy==0.11.2 # homeassistant.components.light.blinksticklight blinkstick==1.1.8 diff --git a/tests/components/lovelace/test_init.py b/tests/components/lovelace/test_init.py index 15548b28cfb..20490f8c0cd 100644 --- a/tests/components/lovelace/test_init.py +++ b/tests/components/lovelace/test_init.py @@ -50,6 +50,27 @@ async def test_lovelace_from_storage(hass, hass_ws_client, hass_storage): } +async def test_lovelace_from_storage_save_before_load(hass, hass_ws_client, + hass_storage): + """Test we can load lovelace config from storage.""" + assert await async_setup_component(hass, 'lovelace', {}) + client = await hass_ws_client(hass) + + # Store new config + await client.send_json({ + 'id': 6, + 'type': 'lovelace/config/save', + 'config': { + 'yo': 'hello' + } + }) + response = await client.receive_json() + assert response['success'] + assert hass_storage[lovelace.STORAGE_KEY]['data'] == { + 'config': {'yo': 'hello'} + } + + async def test_lovelace_from_yaml(hass, hass_ws_client): """Test we load lovelace config from yaml.""" assert await async_setup_component(hass, 'lovelace', { diff --git a/tests/helpers/test_restore_state.py b/tests/helpers/test_restore_state.py index b13bc87421b..bc2ab6937c3 100644 --- a/tests/helpers/test_restore_state.py +++ b/tests/helpers/test_restore_state.py @@ -6,7 +6,8 @@ from homeassistant.core import CoreState, State from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity import Entity from homeassistant.helpers.restore_state import ( - RestoreStateData, RestoreEntity, StoredState, DATA_RESTORE_STATE_TASK) + RestoreStateData, RestoreEntity, StoredState, DATA_RESTORE_STATE_TASK, + STORAGE_KEY) from homeassistant.util import dt as dt_util from asynctest import patch @@ -218,3 +219,34 @@ async def test_state_saved_on_remove(hass): # We should store the input boolean state when it is removed assert data.last_states['input_boolean.b0'].state.state == 'on' + + +async def test_restoring_invalid_entity_id(hass, hass_storage): + """Test restoring invalid entity IDs.""" + entity = RestoreEntity() + entity.hass = hass + entity.entity_id = 'test.invalid__entity_id' + now = dt_util.utcnow().isoformat() + hass_storage[STORAGE_KEY] = { + 'version': 1, + 'key': STORAGE_KEY, + 'data': [ + { + 'state': { + 'entity_id': 'test.invalid__entity_id', + 'state': 'off', + 'attributes': {}, + 'last_changed': now, + 'last_updated': now, + 'context': { + 'id': '3c2243ff5f30447eb12e7348cfd5b8ff', + 'user_id': None + } + }, + 'last_seen': dt_util.utcnow().isoformat() + } + ] + } + + state = await entity.async_get_last_state() + assert state is None