diff --git a/homeassistant/components/alarm_control_panel/alarmdotcom.py b/homeassistant/components/alarm_control_panel/alarmdotcom.py index 8bf36e176e5..cd37fc6a828 100644 --- a/homeassistant/components/alarm_control_panel/alarmdotcom.py +++ b/homeassistant/components/alarm_control_panel/alarmdotcom.py @@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) - add_devices([AlarmDotCom(hass, name, code, username, password)]) + add_devices([AlarmDotCom(hass, name, code, username, password)], True) class AlarmDotCom(alarm.AlarmControlPanel): @@ -54,12 +54,17 @@ class AlarmDotCom(alarm.AlarmControlPanel): self._code = str(code) if code else None self._username = username self._password = password + self._state = STATE_UNKNOWN @property def should_poll(self): """No polling needed.""" return True + def update(self): + """Fetch the latest state.""" + self._state = self._alarm.state + @property def name(self): """Return the name of the alarm.""" @@ -73,11 +78,11 @@ class AlarmDotCom(alarm.AlarmControlPanel): @property def state(self): """Return the state of the device.""" - if self._alarm.state == 'Disarmed': + if self._state == 'Disarmed': return STATE_ALARM_DISARMED - elif self._alarm.state == 'Armed Stay': + elif self._state == 'Armed Stay': return STATE_ALARM_ARMED_HOME - elif self._alarm.state == 'Armed Away': + elif self._state == 'Armed Away': return STATE_ALARM_ARMED_AWAY else: return STATE_UNKNOWN diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index c6664ed70b2..e4d97987dbf 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -91,7 +91,7 @@ class GenericCamera(Camera): if url == self._last_url and self._limit_refetch: return self._last_image - # aiohttp don't support DigestAuth jet + # aiohttp don't support DigestAuth yet if self._authentication == HTTP_DIGEST_AUTHENTICATION: def fetch(): """Read image from a URL.""" @@ -109,15 +109,17 @@ class GenericCamera(Camera): else: try: with async_timeout.timeout(10, loop=self.hass.loop): - respone = yield from self.hass.websession.get( - url, - auth=self._auth - ) - self._last_image = yield from respone.read() - yield from respone.release() + response = yield from self.hass.websession.get( + url, auth=self._auth) + self._last_image = yield from response.read() + yield from response.release() except asyncio.TimeoutError: _LOGGER.error('Timeout getting camera image') return self._last_image + except (aiohttp.errors.ClientError, + aiohttp.errors.ClientDisconnectedError) as err: + _LOGGER.error('Error getting new camera image: %s', err) + return self._last_image self._last_url = url return self._last_image diff --git a/homeassistant/components/camera/synology.py b/homeassistant/components/camera/synology.py index 4ca63c16d7d..bbca25fd6b6 100644 --- a/homeassistant/components/camera/synology.py +++ b/homeassistant/components/camera/synology.py @@ -9,13 +9,14 @@ import logging import voluptuous as vol +import aiohttp from aiohttp import web from aiohttp.web_exceptions import HTTPGatewayTimeout import async_timeout from homeassistant.const import ( CONF_NAME, CONF_USERNAME, CONF_PASSWORD, - CONF_URL, CONF_WHITELIST, CONF_VERIFY_SSL) + CONF_URL, CONF_WHITELIST, CONF_VERIFY_SSL, EVENT_HOMEASSISTANT_STOP) from homeassistant.components.camera import ( Camera, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv @@ -57,6 +58,16 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Setup a Synology IP Camera.""" + if not config.get(CONF_VERIFY_SSL): + connector = aiohttp.TCPConnector(verify_ssl=False) + else: + connector = None + + websession_init = aiohttp.ClientSession( + loop=hass.loop, + connector=connector + ) + # Determine API to use for authentication syno_api_url = SYNO_API_URL.format( config.get(CONF_URL), WEBAPI_PATH, QUERY_CGI) @@ -69,13 +80,12 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): } try: with async_timeout.timeout(TIMEOUT, loop=hass.loop): - query_req = yield from hass.websession.get( + query_req = yield from websession_init.get( syno_api_url, - params=query_payload, - verify_ssl=config.get(CONF_VERIFY_SSL) + params=query_payload ) - except asyncio.TimeoutError: - _LOGGER.error("Timeout on %s", syno_api_url) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error on %s", syno_api_url) return False query_resp = yield from query_req.json() @@ -93,12 +103,26 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): session_id = yield from get_session_id( hass, + websession_init, config.get(CONF_USERNAME), config.get(CONF_PASSWORD), - syno_auth_url, - config.get(CONF_VERIFY_SSL) + syno_auth_url ) + websession_init.detach() + + # init websession + websession = aiohttp.ClientSession( + loop=hass.loop, connector=connector, cookies={'id': session_id}) + + @asyncio.coroutine + def _async_close_websession(event): + """Close webssesion on shutdown.""" + yield from websession.close() + + hass.bus.async_listen_once( + EVENT_HOMEASSISTANT_STOP, _async_close_websession) + # Use SessionID to get cameras in system syno_camera_url = SYNO_API_URL.format( config.get(CONF_URL), WEBAPI_PATH, camera_api) @@ -110,14 +134,12 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): } try: with async_timeout.timeout(TIMEOUT, loop=hass.loop): - camera_req = yield from hass.websession.get( + camera_req = yield from websession.get( syno_camera_url, - params=camera_payload, - verify_ssl=config.get(CONF_VERIFY_SSL), - cookies={'id': session_id} + params=camera_payload ) - except asyncio.TimeoutError: - _LOGGER.error("Timeout on %s", syno_camera_url) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error on %s", syno_camera_url) return False camera_resp = yield from camera_req.json() @@ -126,13 +148,14 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): # add cameras devices = [] - tasks = [] for camera in cameras: if not config.get(CONF_WHITELIST): camera_id = camera['id'] snapshot_path = camera['snapshot_path'] device = SynologyCamera( + hass, + websession, config, camera_id, camera['name'], @@ -141,15 +164,13 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): camera_path, auth_path ) - tasks.append(device.async_read_sid()) devices.append(device) - yield from asyncio.gather(*tasks, loop=hass.loop) - hass.loop.create_task(async_add_devices(devices)) + yield from async_add_devices(devices) @asyncio.coroutine -def get_session_id(hass, username, password, login_url, valid_cert): +def get_session_id(hass, websession, username, password, login_url): """Get a session id.""" auth_payload = { 'api': AUTH_API, @@ -162,13 +183,12 @@ def get_session_id(hass, username, password, login_url, valid_cert): } try: with async_timeout.timeout(TIMEOUT, loop=hass.loop): - auth_req = yield from hass.websession.get( + auth_req = yield from websession.get( login_url, - params=auth_payload, - verify_ssl=valid_cert + params=auth_payload ) - except asyncio.TimeoutError: - _LOGGER.error("Timeout on %s", login_url) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error on %s", login_url) return False auth_resp = yield from auth_req.json() @@ -180,36 +200,22 @@ def get_session_id(hass, username, password, login_url, valid_cert): class SynologyCamera(Camera): """An implementation of a Synology NAS based IP camera.""" - def __init__(self, config, camera_id, camera_name, - snapshot_path, streaming_path, camera_path, auth_path): + def __init__(self, hass, websession, config, camera_id, + camera_name, snapshot_path, streaming_path, camera_path, + auth_path): """Initialize a Synology Surveillance Station camera.""" super().__init__() + self.hass = hass + self._websession = websession self._name = camera_name - self._username = config.get(CONF_USERNAME) - self._password = config.get(CONF_PASSWORD) self._synology_url = config.get(CONF_URL) - self._api_url = config.get(CONF_URL) + 'webapi/' - self._login_url = config.get(CONF_URL) + '/webapi/' + 'auth.cgi' self._camera_name = config.get(CONF_CAMERA_NAME) self._stream_id = config.get(CONF_STREAM_ID) - self._valid_cert = config.get(CONF_VERIFY_SSL) self._camera_id = camera_id self._snapshot_path = snapshot_path self._streaming_path = streaming_path self._camera_path = camera_path self._auth_path = auth_path - self._session_id = None - - @asyncio.coroutine - def async_read_sid(self): - """Get a session id.""" - self._session_id = yield from get_session_id( - self.hass, - self._username, - self._password, - self._login_url, - self._valid_cert - ) def camera_image(self): """Return bytes of camera image.""" @@ -230,14 +236,12 @@ class SynologyCamera(Camera): } try: with async_timeout.timeout(TIMEOUT, loop=self.hass.loop): - response = yield from self.hass.websession.get( + response = yield from self._websession.get( image_url, - params=image_payload, - verify_ssl=self._valid_cert, - cookies={'id': self._session_id} + params=image_payload ) - except asyncio.TimeoutError: - _LOGGER.error("Timeout on %s", image_url) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error on %s", image_url) return None image = yield from response.read() @@ -260,13 +264,12 @@ class SynologyCamera(Camera): } try: with async_timeout.timeout(TIMEOUT, loop=self.hass.loop): - stream = yield from self.hass.websession.get( + stream = yield from self._websession.get( streaming_url, - payload=streaming_payload, - verify_ssl=self._valid_cert, - cookies={'id': self._session_id} + params=streaming_payload ) - except asyncio.TimeoutError: + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error on %s", streaming_url) raise HTTPGatewayTimeout() response = web.StreamResponse() @@ -281,7 +284,7 @@ class SynologyCamera(Camera): break response.write(data) finally: - self.hass.loop.create_task(stream.release()) + self.hass.async_add_job(stream.release()) yield from response.write_eof() @property diff --git a/homeassistant/components/climate/knx.py b/homeassistant/components/climate/knx.py index ef7445c35fd..888a217d90c 100644 --- a/homeassistant/components/climate/knx.py +++ b/homeassistant/components/climate/knx.py @@ -56,6 +56,8 @@ class KNXThermostat(KNXMultiAddressDevice, ClimateDevice): self._unit_of_measurement = TEMP_CELSIUS # KNX always used celsius self._away = False # not yet supported self._is_fan_on = False # not yet supported + self._current_temp = None + self._target_temp = None @property def should_poll(self): @@ -70,16 +72,12 @@ class KNXThermostat(KNXMultiAddressDevice, ClimateDevice): @property def current_temperature(self): """Return the current temperature.""" - from knxip.conversion import knx2_to_float - - return knx2_to_float(self.value('temperature')) + return self._current_temp @property def target_temperature(self): """Return the temperature we try to reach.""" - from knxip.conversion import knx2_to_float - - return knx2_to_float(self.value('setpoint')) + return self._target_temp def set_temperature(self, **kwargs): """Set new target temperature.""" @@ -94,3 +92,12 @@ class KNXThermostat(KNXMultiAddressDevice, ClimateDevice): def set_operation_mode(self, operation_mode): """Set operation mode.""" raise NotImplementedError() + + def update(self): + """Update KNX climate.""" + from knxip.conversion import knx2_to_float + + super().update() + + self._current_temp = knx2_to_float(self.value('temperature')) + self._target_temp = knx2_to_float(self.value('setpoint')) diff --git a/homeassistant/components/knx.py b/homeassistant/components/knx.py index 5d096b30ee0..8653f33c663 100644 --- a/homeassistant/components/knx.py +++ b/homeassistant/components/knx.py @@ -161,8 +161,6 @@ class KNXGroupAddress(Entity): @property def is_on(self): """Return True if the value is not 0 is on, else False.""" - if self.should_poll: - self.update() return self._state != 0 @property diff --git a/homeassistant/components/light/flux_led.py b/homeassistant/components/light/flux_led.py index 095733afd8e..9de4aa6b0fc 100644 --- a/homeassistant/components/light/flux_led.py +++ b/homeassistant/components/light/flux_led.py @@ -23,6 +23,7 @@ REQUIREMENTS = ['https://github.com/Danielhiversen/flux_led/archive/0.8.zip' _LOGGER = logging.getLogger(__name__) CONF_AUTOMATIC_ADD = 'automatic_add' +ATTR_MODE = 'mode' DOMAIN = 'flux_led' @@ -31,6 +32,8 @@ SUPPORT_FLUX_LED = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | DEVICE_SCHEMA = vol.Schema({ vol.Optional(CONF_NAME): cv.string, + vol.Optional(ATTR_MODE, default='rgbw'): + vol.All(cv.string, vol.In(['rgbw', 'rgb'])), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -48,6 +51,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): device = {} device['name'] = device_config[CONF_NAME] device['ipaddr'] = ipaddr + device[ATTR_MODE] = device_config[ATTR_MODE] light = FluxLight(device) if light.is_valid: lights.append(light) @@ -65,6 +69,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if ipaddr in light_ips: continue device['name'] = device['id'] + " " + ipaddr + device[ATTR_MODE] = 'rgbw' light = FluxLight(device) if light.is_valid: lights.append(light) @@ -82,6 +87,7 @@ class FluxLight(Light): self._name = device['name'] self._ipaddr = device['ipaddr'] + self._mode = device[ATTR_MODE] self.is_valid = True self._bulb = None try: @@ -132,7 +138,11 @@ class FluxLight(Light): if rgb: self._bulb.setRgb(*tuple(rgb)) elif brightness: - self._bulb.setWarmWhite255(brightness) + if self._mode == 'rgbw': + self._bulb.setWarmWhite255(brightness) + elif self._mode == 'rgb': + (red, green, blue) = self._bulb.getRgb() + self._bulb.setRgb(red, green, blue, brightness=brightness) elif effect == EFFECT_RANDOM: self._bulb.setRgb(random.randrange(0, 255), random.randrange(0, 255), diff --git a/homeassistant/components/media_player/panasonic_viera.py b/homeassistant/components/media_player/panasonic_viera.py index d1a971eb91e..987364bbf63 100644 --- a/homeassistant/components/media_player/panasonic_viera.py +++ b/homeassistant/components/media_player/panasonic_viera.py @@ -79,16 +79,16 @@ class PanasonicVieraTVDevice(MediaPlayerDevice): self._playing = True self._state = STATE_UNKNOWN self._remote = remote + self._volume = 0 def update(self): """Retrieve the latest data.""" try: self._muted = self._remote.get_mute() + self._volume = self._remote.get_volume() / 100 self._state = STATE_ON except OSError: self._state = STATE_OFF - return False - return True def send_key(self, key): """Send a key to the tv and handles exceptions.""" @@ -113,13 +113,7 @@ class PanasonicVieraTVDevice(MediaPlayerDevice): @property def volume_level(self): """Volume level of the media player (0..1).""" - volume = 0 - try: - volume = self._remote.get_volume() / 100 - self._state = STATE_ON - except OSError: - self._state = STATE_OFF - return volume + return self._volume @property def is_volume_muted(self): diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index 89f5d7b07ed..ebc8d58874a 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -21,9 +21,7 @@ from homeassistant.const import ( from homeassistant.config import load_yaml_config_file import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['https://github.com/SoCo/SoCo/archive/' - 'cf8c2701165562eccbf1ecc879bf7060ceb0993e.zip#' - 'SoCo==0.12'] +REQUIREMENTS = ['SoCo==0.12'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/media_player/yamaha.py b/homeassistant/components/media_player/yamaha.py index 94191862f44..0e265199fce 100644 --- a/homeassistant/components/media_player/yamaha.py +++ b/homeassistant/components/media_player/yamaha.py @@ -18,7 +18,7 @@ from homeassistant.const import (CONF_NAME, CONF_HOST, STATE_OFF, STATE_ON, STATE_PLAYING, STATE_IDLE) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['rxv==0.3.0'] +REQUIREMENTS = ['rxv==0.3.1'] _LOGGER = logging.getLogger(__name__) @@ -35,6 +35,7 @@ CONF_SOURCE_IGNORE = 'source_ignore' CONF_ZONE_IGNORE = 'zone_ignore' DEFAULT_NAME = 'Yamaha Receiver' +KNOWN = 'yamaha_known_receivers' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, @@ -50,6 +51,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Yamaha platform.""" import rxv + # keep track of configured receivers so that we don't end up + # discovering a receiver dynamically that we have static config + # for. + if hass.data.get(KNOWN, None) is None: + hass.data[KNOWN] = set() name = config.get(CONF_NAME) host = config.get(CONF_HOST) @@ -62,12 +68,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): model = discovery_info[1] ctrl_url = discovery_info[2] desc_url = discovery_info[3] + if ctrl_url in hass.data[KNOWN]: + _LOGGER.info("%s already manually configured", ctrl_url) + return receivers = rxv.RXV( ctrl_url, model_name=model, friendly_name=name, unit_desc_url=desc_url).zone_controllers() _LOGGER.info("Receivers: %s", receivers) + # when we are dynamically discovered config is empty + zone_ignore = [] elif host is None: receivers = [] for recv in rxv.find(): @@ -78,6 +89,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for receiver in receivers: if receiver.zone not in zone_ignore: + hass.data[KNOWN].add(receiver.ctrl_url) add_devices([ YamahaDevice(name, receiver, source_ignore, source_names)]) diff --git a/homeassistant/components/sensor/knx.py b/homeassistant/components/sensor/knx.py index 007291f5fb1..1f5c9a76520 100644 --- a/homeassistant/components/sensor/knx.py +++ b/homeassistant/components/sensor/knx.py @@ -113,15 +113,24 @@ class KNXSensorFloatClass(KNXGroupAddress, KNXSensorBaseClass): self._unit_of_measurement = unit_of_measurement self._minimum_value = minimum_sensor_value self._maximum_value = maximum_sensor_value + self._value = None KNXGroupAddress.__init__(self, hass, config) @property def state(self): """Return the Value of the KNX Sensor.""" + return self._value + + def update(self): + """Update KNX sensor.""" + from knxip.conversion import knx2_to_float + + super().update() + + self._value = None + if self._data: - from knxip.conversion import knx2_to_float value = knx2_to_float(self._data) if self._minimum_value <= value <= self._maximum_value: - return value - return None + self._value = value diff --git a/homeassistant/components/sensor/tellstick.py b/homeassistant/components/sensor/tellstick.py index 464e3554324..08e15cd332f 100644 --- a/homeassistant/components/sensor/tellstick.py +++ b/homeassistant/components/sensor/tellstick.py @@ -98,6 +98,7 @@ class TellstickSensor(Entity): self.datatype = datatype self.sensor = sensor self._unit_of_measurement = sensor_info.unit or None + self._value = None self._name = '{} {}'.format(name, sensor_info.name) @@ -109,9 +110,13 @@ class TellstickSensor(Entity): @property def state(self): """Return the state of the sensor.""" - return self.sensor.value(self.datatype).value + return self._value @property def unit_of_measurement(self): """Return the unit of measurement of this entity, if any.""" return self._unit_of_measurement + + def update(self): + """Update tellstick sensor.""" + self._value = self.sensor.value(self.datatype).value diff --git a/homeassistant/components/sensor/yr.py b/homeassistant/components/sensor/yr.py index 51616062475..ab1e2da5852 100644 --- a/homeassistant/components/sensor/yr.py +++ b/homeassistant/components/sensor/yr.py @@ -10,7 +10,7 @@ import logging from xml.parsers.expat import ExpatError import async_timeout -from aiohttp.web import HTTPException +import aiohttp import voluptuous as vol import homeassistant.helpers.config_validation as cv @@ -154,12 +154,9 @@ class YrData(object): try_again('{} returned {}'.format(self._url, resp.status)) return text = yield from resp.text() - self.hass.loop.create_task(resp.release()) - except asyncio.TimeoutError as err: - try_again(err) - return - except HTTPException as err: - resp.close() + self.hass.async_add_job(resp.release) + except (asyncio.TimeoutError, aiohttp.errors.ClientError, + aiohttp.errors.ClientDisconnectedError) as err: try_again(err) return @@ -218,4 +215,5 @@ class YrData(object): dev._state = new_state tasks.append(dev.async_update_ha_state()) - yield from asyncio.gather(*tasks, loop=self.hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=self.hass.loop) diff --git a/homeassistant/components/switch/pilight.py b/homeassistant/components/switch/pilight.py index f07d91ca9fb..80a36756d79 100644 --- a/homeassistant/components/switch/pilight.py +++ b/homeassistant/components/switch/pilight.py @@ -27,10 +27,10 @@ DEPENDENCIES = ['pilight'] COMMAND_SCHEMA = pilight.RF_CODE_SCHEMA.extend({ vol.Optional('on'): cv.positive_int, vol.Optional('off'): cv.positive_int, - vol.Optional(CONF_UNIT): cv.string, + vol.Optional(CONF_UNIT): cv.positive_int, vol.Optional(CONF_ID): cv.positive_int, vol.Optional(CONF_STATE): cv.string, - vol.Optional(CONF_SYSTEMCODE): cv.string, + vol.Optional(CONF_SYSTEMCODE): cv.positive_int, }) SWITCHES_SCHEMA = vol.Schema({ diff --git a/homeassistant/components/switch/rest.py b/homeassistant/components/switch/rest.py index 056bcef0281..36674c16d16 100644 --- a/homeassistant/components/switch/rest.py +++ b/homeassistant/components/switch/rest.py @@ -12,11 +12,12 @@ import voluptuous as vol from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import (CONF_NAME, CONF_RESOURCE, CONF_TIMEOUT) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.template import Template CONF_BODY_OFF = 'body_off' CONF_BODY_ON = 'body_on' -DEFAULT_BODY_OFF = 'OFF' -DEFAULT_BODY_ON = 'ON' +DEFAULT_BODY_OFF = Template('OFF') +DEFAULT_BODY_ON = Template('ON') DEFAULT_NAME = 'REST Switch' DEFAULT_TIMEOUT = 10 CONF_IS_ON_TEMPLATE = 'is_on_template' diff --git a/homeassistant/components/weather/openweathermap.py b/homeassistant/components/weather/openweathermap.py index b029b4d44bb..a93b0142d90 100644 --- a/homeassistant/components/weather/openweathermap.py +++ b/homeassistant/components/weather/openweathermap.py @@ -67,7 +67,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): data = WeatherData(owm, latitude, longitude) add_devices([OpenWeatherMapWeather( - name, data, hass.config.units.temperature_unit)]) + name, data, hass.config.units.temperature_unit)], True) class OpenWeatherMapWeather(WeatherEntity): @@ -78,8 +78,7 @@ class OpenWeatherMapWeather(WeatherEntity): self._name = name self._owm = owm self._temperature_unit = temperature_unit - self.date = None - self.update() + self.data = None @property def name(self): diff --git a/homeassistant/const.py b/homeassistant/const.py index 0eb2384517d..cdc846c49d3 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 32 -PATCH_VERSION = '2' +PATCH_VERSION = '3' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index ecb04aca9d9..ac058f89143 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -242,7 +242,7 @@ class Entity(object): end = timer() - if end - start > 0.2: + if end - start > 0.4: _LOGGER.warning('Updating state for %s took %.3f seconds. ' 'Please report platform to the developers at ' 'https://goo.gl/Nvioub', self.entity_id, diff --git a/requirements_all.txt b/requirements_all.txt index af5519f1d15..e6ccf11cbed 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -24,6 +24,9 @@ PyMata==2.13 # homeassistant.components.rpi_gpio # RPi.GPIO==0.6.1 +# homeassistant.components.media_player.sonos +SoCo==0.12 + # homeassistant.components.notify.twitter TwitterAPI==2.4.2 @@ -157,9 +160,6 @@ https://github.com/GadgetReactor/pyHS100/archive/1f771b7d8090a91c6a58931532e4273 # homeassistant.components.switch.dlink https://github.com/LinuxChristian/pyW215/archive/v0.3.5.zip#pyW215==0.3.5 -# homeassistant.components.media_player.sonos -https://github.com/SoCo/SoCo/archive/cf8c2701165562eccbf1ecc879bf7060ceb0993e.zip#SoCo==0.12 - # homeassistant.components.media_player.webostv # homeassistant.components.notify.webostv https://github.com/TheRealLink/pylgtv/archive/v0.1.2.zip#pylgtv==0.1.2 @@ -464,7 +464,7 @@ radiotherm==1.2 # rpi-rf==0.9.5 # homeassistant.components.media_player.yamaha -rxv==0.3.0 +rxv==0.3.1 # homeassistant.components.media_player.samsungtv samsungctl==0.5.1