Bump PyWeMo version to 0.4.43 (#35693)

* PyWeMo version bump to 0.4.43

Changes necessary to safely upgrade to pyWeMo 0.4.43. This includes catching ActionExceptions that may be thrown by pyWeMo when it is unable to interact with a physical device.

* Black formatting fix

* Fix isort issues

* Code review changes

* More code review fixes

* Linting fix

* Undo dict.get change

* Change a couple instances of dict[key] to dict.get
This commit is contained in:
Adam Belebczuk 2020-05-17 16:13:38 -04:00 committed by GitHub
parent b42a197293
commit 5104b79b4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 144 additions and 62 deletions

View File

@ -3,6 +3,7 @@ import asyncio
import logging
import async_timeout
from pywemo.ouimeaux_device.api.service import ActionException
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -40,7 +41,7 @@ class WemoBinarySensor(BinarySensorEntity):
self._update_lock = None
self._model_name = self.wemo.model_name
self._name = self.wemo.name
self._serialnumber = self.wemo.serialnumber
self._serial_number = self.wemo.serialnumber
def _subscription_callback(self, _device, _type, _params):
"""Update the state by the Wemo sensor."""
@ -98,14 +99,15 @@ class WemoBinarySensor(BinarySensorEntity):
if not self._available:
_LOGGER.info("Reconnected to %s", self.name)
self._available = True
except AttributeError as err:
except (AttributeError, ActionException) as err:
_LOGGER.warning("Could not update status for %s (%s)", self.name, err)
self._available = False
self.wemo.reconnect_with_device()
@property
def unique_id(self):
"""Return the id of this WeMo sensor."""
return self._serialnumber
return self._serial_number
@property
def name(self):
@ -126,8 +128,8 @@ class WemoBinarySensor(BinarySensorEntity):
def device_info(self):
"""Return the device info."""
return {
"name": self.wemo.name,
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
"model": self.wemo.model_name,
"name": self._name,
"identifiers": {(WEMO_DOMAIN, self._serial_number)},
"model": self._model_name,
"manufacturer": "Belkin",
}

View File

@ -4,6 +4,7 @@ from datetime import timedelta
import logging
import async_timeout
from pywemo.ouimeaux_device.api.service import ActionException
import voluptuous as vol
from homeassistant.components.fan import (
@ -128,7 +129,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
# Register service(s)
hass.services.async_register(
WEMO_DOMAIN, SERVICE_SET_HUMIDITY, service_handle, schema=SET_HUMIDITY_SCHEMA
WEMO_DOMAIN, SERVICE_SET_HUMIDITY, service_handle, schema=SET_HUMIDITY_SCHEMA,
)
hass.services.async_register(
@ -198,9 +199,9 @@ class WemoHumidifier(FanEntity):
def device_info(self):
"""Return the device info."""
return {
"name": self.wemo.name,
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
"model": self.wemo.model_name,
"name": self._name,
"identifiers": {(WEMO_DOMAIN, self._serialnumber)},
"model": self._model_name,
"manufacturer": "Belkin",
}
@ -287,38 +288,67 @@ class WemoHumidifier(FanEntity):
if not self._available:
_LOGGER.info("Reconnected to %s", self.name)
self._available = True
except AttributeError as err:
except (AttributeError, ActionException) as err:
_LOGGER.warning("Could not update status for %s (%s)", self.name, err)
self._available = False
self.wemo.reconnect_with_device()
def turn_on(self, speed: str = None, **kwargs) -> None:
"""Turn the switch on."""
if speed is None:
self.wemo.set_state(self._last_fan_on_mode)
try:
self.wemo.set_state(self._last_fan_on_mode)
except ActionException as err:
_LOGGER.warning("Error while turning on device %s (%s)", self.name, err)
self._available = False
else:
self.set_speed(speed)
def turn_off(self, **kwargs) -> None:
"""Turn the switch off."""
self.wemo.set_state(WEMO_FAN_OFF)
try:
self.wemo.set_state(WEMO_FAN_OFF)
except ActionException as err:
_LOGGER.warning("Error while turning off device %s (%s)", self.name, err)
self._available = False
def set_speed(self, speed: str) -> None:
"""Set the fan_mode of the Humidifier."""
self.wemo.set_state(HASS_FAN_SPEED_TO_WEMO.get(speed))
try:
self.wemo.set_state(HASS_FAN_SPEED_TO_WEMO.get(speed))
except ActionException as err:
_LOGGER.warning(
"Error while setting speed of device %s (%s)", self.name, err
)
self._available = False
def set_humidity(self, humidity: float) -> None:
"""Set the target humidity level for the Humidifier."""
if humidity < 50:
self.wemo.set_humidity(WEMO_HUMIDITY_45)
target_humidity = WEMO_HUMIDITY_45
elif 50 <= humidity < 55:
self.wemo.set_humidity(WEMO_HUMIDITY_50)
target_humidity = WEMO_HUMIDITY_50
elif 55 <= humidity < 60:
self.wemo.set_humidity(WEMO_HUMIDITY_55)
target_humidity = WEMO_HUMIDITY_55
elif 60 <= humidity < 100:
self.wemo.set_humidity(WEMO_HUMIDITY_60)
target_humidity = WEMO_HUMIDITY_60
elif humidity >= 100:
self.wemo.set_humidity(WEMO_HUMIDITY_100)
target_humidity = WEMO_HUMIDITY_100
try:
self.wemo.set_humidity(target_humidity)
except ActionException as err:
_LOGGER.warning(
"Error while setting humidity of device: %s (%s)", self.name, err
)
self._available = False
def reset_filter_life(self) -> None:
"""Reset the filter life to 100%."""
self.wemo.reset_filter_life()
try:
self.wemo.reset_filter_life()
except ActionException as err:
_LOGGER.warning(
"Error while resetting filter life on device: %s (%s)", self.name, err
)
self._available = False

View File

@ -4,6 +4,7 @@ from datetime import timedelta
import logging
import async_timeout
from pywemo.ouimeaux_device.api.service import ActionException
from homeassistant import util
from homeassistant.components.light import (
@ -92,6 +93,7 @@ class WemoLight(LightEntity):
self._is_on = None
self._name = self.wemo.name
self._unique_id = self.wemo.uniqueID
self._model_name = type(self.wemo).__name__
async def async_added_to_hass(self):
"""Wemo light added to Home Assistant."""
@ -112,9 +114,9 @@ class WemoLight(LightEntity):
def device_info(self):
"""Return the device info."""
return {
"name": self.wemo.name,
"identifiers": {(WEMO_DOMAIN, self.wemo.uniqueID)},
"model": type(self.wemo).__name__,
"name": self._name,
"identifiers": {(WEMO_DOMAIN, self._unique_id)},
"model": self._model_name,
"manufacturer": "Belkin",
}
@ -150,45 +152,65 @@ class WemoLight(LightEntity):
def turn_on(self, **kwargs):
"""Turn the light on."""
transitiontime = int(kwargs.get(ATTR_TRANSITION, 0))
xy_color = None
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255)
color_temp = kwargs.get(ATTR_COLOR_TEMP)
hs_color = kwargs.get(ATTR_HS_COLOR)
transition_time = int(kwargs.get(ATTR_TRANSITION, 0))
if hs_color is not None:
xy_color = color_util.color_hs_to_xy(*hs_color)
self.wemo.set_color(xy_color, transition=transitiontime)
if ATTR_COLOR_TEMP in kwargs:
colortemp = kwargs[ATTR_COLOR_TEMP]
self.wemo.set_temperature(mireds=colortemp, transition=transitiontime)
turn_on_kwargs = {
"level": brightness,
"transition": transition_time,
"force_update": False,
}
if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255)
self.wemo.turn_on(level=brightness, transition=transitiontime)
else:
self.wemo.turn_on(transition=transitiontime)
try:
if xy_color is not None:
self.wemo.set_color(xy_color, transition=transition_time)
if color_temp is not None:
self.wemo.set_temperature(mireds=color_temp, transition=transition_time)
self.wemo.turn_on(**turn_on_kwargs)
except ActionException as err:
_LOGGER.warning("Error while turning on device %s (%s)", self.name, err)
self._available = False
def turn_off(self, **kwargs):
"""Turn the light off."""
transitiontime = int(kwargs.get(ATTR_TRANSITION, 0))
self.wemo.turn_off(transition=transitiontime)
transition_time = int(kwargs.get(ATTR_TRANSITION, 0))
try:
self.wemo.turn_off(transition=transition_time)
except ActionException as err:
_LOGGER.warning("Error while turning off device %s (%s)", self.name, err)
self._available = False
def _update(self, force_update=True):
"""Synchronize state with bridge."""
self._update_lights(no_throttle=force_update)
self._state = self.wemo.state
self._is_on = self._state.get("onoff") != 0
self._brightness = self._state.get("level", 255)
self._color_temp = self._state.get("temperature_mireds")
self._available = True
xy_color = self._state.get("color_xy")
if xy_color:
self._hs_color = color_util.color_xy_to_hs(*xy_color)
try:
self._update_lights(no_throttle=force_update)
self._state = self.wemo.state
except (AttributeError, ActionException) as err:
_LOGGER.warning("Could not update status for %s (%s)", self.name, err)
self._available = False
self.wemo.reconnect_with_device()
else:
self._hs_color = None
self._is_on = self._state.get("onoff") != 0
self._brightness = self._state.get("level", 255)
self._color_temp = self._state.get("temperature_mireds")
self._available = True
xy_color = self._state.get("color_xy")
if xy_color:
self._hs_color = color_util.color_xy_to_hs(*xy_color)
else:
self._hs_color = None
async def async_update(self):
"""Synchronize state with bridge."""
@ -265,7 +287,6 @@ class WemoDimmer(LightEntity):
except asyncio.TimeoutError:
_LOGGER.warning("Lost connection to %s", self.name)
self._available = False
self.wemo.reconnect_with_device()
async def _async_locked_update(self, force_update):
"""Try updating within an async lock."""
@ -282,6 +303,16 @@ class WemoDimmer(LightEntity):
"""Return the name of the dimmer if any."""
return self._name
@property
def device_info(self):
"""Return the device info."""
return {
"name": self._name,
"identifiers": {(WEMO_DOMAIN, self._serialnumber)},
"model": self._model_name,
"manufacturer": "Belkin",
}
@property
def supported_features(self):
"""Flag supported features."""
@ -308,14 +339,13 @@ class WemoDimmer(LightEntity):
if not self._available:
_LOGGER.info("Reconnected to %s", self.name)
self._available = True
except AttributeError as err:
except (AttributeError, ActionException) as err:
_LOGGER.warning("Could not update status for %s (%s)", self.name, err)
self._available = False
self.wemo.reconnect_with_device()
def turn_on(self, **kwargs):
"""Turn the dimmer on."""
self.wemo.on()
# Wemo dimmer switches use a range of [0, 100] to control
# brightness. Level 255 might mean to set it to previous value
if ATTR_BRIGHTNESS in kwargs:
@ -323,11 +353,21 @@ class WemoDimmer(LightEntity):
brightness = int((brightness / 255) * 100)
else:
brightness = 255
self.wemo.set_brightness(brightness)
try:
self.wemo.on()
self.wemo.set_brightness(brightness)
except ActionException as err:
_LOGGER.warning("Error while turning on device %s (%s)", self.name, err)
self._available = False
def turn_off(self, **kwargs):
"""Turn the dimmer off."""
self.wemo.off()
try:
self.wemo.off()
except ActionException as err:
_LOGGER.warning("Error while turning on device %s (%s)", self.name, err)
self._available = False
@property
def available(self):

View File

@ -3,7 +3,7 @@
"name": "Belkin WeMo",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/wemo",
"requirements": ["pywemo==0.4.34"],
"requirements": ["pywemo==0.4.43"],
"ssdp": [
{
"manufacturer": "Belkin International Inc."

View File

@ -4,6 +4,7 @@ from datetime import datetime, timedelta
import logging
import async_timeout
from pywemo.ouimeaux_device.api.service import ActionException
from homeassistant.components.switch import SwitchEntity
from homeassistant.const import STATE_OFF, STATE_ON, STATE_STANDBY, STATE_UNKNOWN
@ -93,9 +94,9 @@ class WemoSwitch(SwitchEntity):
def device_info(self):
"""Return the device info."""
return {
"name": self.wemo.name,
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
"model": self.wemo.model_name,
"name": self._name,
"identifiers": {(WEMO_DOMAIN, self._serialnumber)},
"model": self._model_name,
"manufacturer": "Belkin",
}
@ -189,11 +190,19 @@ class WemoSwitch(SwitchEntity):
def turn_on(self, **kwargs):
"""Turn the switch on."""
self.wemo.on()
try:
self.wemo.on()
except ActionException as err:
_LOGGER.warning("Error while turning on device %s (%s)", self.name, err)
self._available = False
def turn_off(self, **kwargs):
"""Turn the switch off."""
self.wemo.off()
try:
self.wemo.off()
except ActionException as err:
_LOGGER.warning("Error while turning off device %s (%s)", self.name, err)
self._available = False
async def async_added_to_hass(self):
"""Wemo switch added to Home Assistant."""
@ -245,6 +254,7 @@ class WemoSwitch(SwitchEntity):
if not self._available:
_LOGGER.info("Reconnected to %s", self.name)
self._available = True
except AttributeError as err:
except (AttributeError, ActionException) as err:
_LOGGER.warning("Could not update status for %s (%s)", self.name, err)
self._available = False
self.wemo.reconnect_with_device()

View File

@ -1808,7 +1808,7 @@ pyvlx==0.2.14
pywebpush==1.9.2
# homeassistant.components.wemo
pywemo==0.4.34
pywemo==0.4.43
# homeassistant.components.xeoma
pyxeoma==1.4.1