Cast types in wemo rather than converting (#62454)

This commit is contained in:
Eric Severance 2021-12-20 20:34:34 -08:00 committed by GitHub
parent a7cae02725
commit d60540d4f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 49 deletions

View File

@ -1,5 +1,6 @@
"""Support for WeMo binary sensors.""" """Support for WeMo binary sensors."""
import asyncio import asyncio
from typing import cast
from pywemo import Insight, Maker from pywemo import Insight, Maker
@ -10,7 +11,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN as WEMO_DOMAIN from .const import DOMAIN as WEMO_DOMAIN
from .entity import WemoEntity from .entity import WemoBinaryStateEntity, WemoEntity
from .wemo_device import DeviceCoordinator from .wemo_device import DeviceCoordinator
@ -40,14 +41,9 @@ async def async_setup_entry(
) )
class WemoBinarySensor(WemoEntity, BinarySensorEntity): class WemoBinarySensor(WemoBinaryStateEntity, BinarySensorEntity):
"""Representation a WeMo binary sensor.""" """Representation a WeMo binary sensor."""
@property
def is_on(self) -> bool:
"""Return true if the state is on. Standby is on."""
return bool(self.wemo.get_state())
class MakerBinarySensor(WemoEntity, BinarySensorEntity): class MakerBinarySensor(WemoEntity, BinarySensorEntity):
"""Maker device's sensor port.""" """Maker device's sensor port."""
@ -57,7 +53,7 @@ class MakerBinarySensor(WemoEntity, BinarySensorEntity):
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if the Maker's sensor is pulled low.""" """Return true if the Maker's sensor is pulled low."""
return bool(self.wemo.has_sensor) and self.wemo.sensor_state == 0 return cast(int, self.wemo.has_sensor) != 0 and self.wemo.sensor_state == 0
class InsightBinarySensor(WemoBinarySensor): class InsightBinarySensor(WemoBinarySensor):

View File

@ -4,6 +4,7 @@ from __future__ import annotations
from collections.abc import Generator from collections.abc import Generator
import contextlib import contextlib
import logging import logging
from typing import cast
from pywemo.exceptions import ActionException from pywemo.exceptions import ActionException
@ -40,9 +41,10 @@ class WemoEntity(CoordinatorEntity):
@property @property
def name(self) -> str: def name(self) -> str:
"""Return the name of the device if any.""" """Return the name of the device if any."""
wemo_name: str = self.wemo.name
if suffix := self.name_suffix: if suffix := self.name_suffix:
return f"{self.wemo.name} {suffix}" return f"{wemo_name} {suffix}"
return str(self.wemo.name) return wemo_name
@property @property
def available(self) -> bool: def available(self) -> bool:
@ -59,9 +61,10 @@ class WemoEntity(CoordinatorEntity):
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:
"""Return the id of this WeMo device.""" """Return the id of this WeMo device."""
serial_number: str = self.wemo.serialnumber
if suffix := self.unique_id_suffix: if suffix := self.unique_id_suffix:
return f"{self.wemo.serialnumber}_{suffix}" return f"{serial_number}_{suffix}"
return str(self.wemo.serialnumber) return serial_number
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
@ -82,3 +85,12 @@ class WemoEntity(CoordinatorEntity):
except ActionException as err: except ActionException as err:
_LOGGER.warning("Could not %s for %s (%s)", message, self.name, err) _LOGGER.warning("Could not %s for %s (%s)", message, self.name, err)
self._available = False self._available = False
class WemoBinaryStateEntity(WemoEntity):
"""Base for devices that return on/off state via device.get_state()."""
@property
def is_on(self) -> bool:
"""Return true if the state is on."""
return cast(int, self.wemo.get_state()) != 0

View File

@ -25,7 +25,7 @@ from .const import (
SERVICE_RESET_FILTER_LIFE, SERVICE_RESET_FILTER_LIFE,
SERVICE_SET_HUMIDITY, SERVICE_SET_HUMIDITY,
) )
from .entity import WemoEntity from .entity import WemoBinaryStateEntity
from .wemo_device import DeviceCoordinator from .wemo_device import DeviceCoordinator
SCAN_INTERVAL = timedelta(seconds=10) SCAN_INTERVAL = timedelta(seconds=10)
@ -38,10 +38,6 @@ ATTR_FILTER_LIFE = "filter_life"
ATTR_FILTER_EXPIRED = "filter_expired" ATTR_FILTER_EXPIRED = "filter_expired"
ATTR_WATER_LEVEL = "water_level" ATTR_WATER_LEVEL = "water_level"
# The WEMO_ constants below come from pywemo itself
WEMO_ON = 1
WEMO_OFF = 0
WEMO_HUMIDITY_45 = 0 WEMO_HUMIDITY_45 = 0
WEMO_HUMIDITY_50 = 1 WEMO_HUMIDITY_50 = 1
WEMO_HUMIDITY_55 = 2 WEMO_HUMIDITY_55 = 2
@ -102,7 +98,7 @@ async def async_setup_entry(
) )
class WemoHumidifier(WemoEntity, FanEntity): class WemoHumidifier(WemoBinaryStateEntity, FanEntity):
"""Representation of a WeMo humidifier.""" """Representation of a WeMo humidifier."""
def __init__(self, coordinator: DeviceCoordinator) -> None: def __init__(self, coordinator: DeviceCoordinator) -> None:
@ -152,11 +148,6 @@ class WemoHumidifier(WemoEntity, FanEntity):
self._last_fan_on_mode = self.wemo.fan_mode self._last_fan_on_mode = self.wemo.fan_mode
super()._handle_coordinator_update() super()._handle_coordinator_update()
@property
def is_on(self) -> bool:
"""Return true if the state is on."""
return bool(self.wemo.get_state())
def turn_on( def turn_on(
self, self,
speed: str | None = None, speed: str | None = None,

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from typing import Any from typing import Any, Optional, cast
from pywemo.ouimeaux_device import bridge from pywemo.ouimeaux_device import bridge
@ -26,7 +26,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.color as color_util import homeassistant.util.color as color_util
from .const import DOMAIN as WEMO_DOMAIN from .const import DOMAIN as WEMO_DOMAIN
from .entity import WemoEntity from .entity import WemoBinaryStateEntity, WemoEntity
from .wemo_device import DeviceCoordinator from .wemo_device import DeviceCoordinator
SUPPORT_WEMO = ( SUPPORT_WEMO = (
@ -101,7 +101,7 @@ class WemoLight(WemoEntity, LightEntity):
@property @property
def name(self) -> str: def name(self) -> str:
"""Return the name of the device if any.""" """Return the name of the device if any."""
return str(self.light.name) return cast(str, self.light.name)
@property @property
def available(self) -> bool: def available(self) -> bool:
@ -111,7 +111,7 @@ class WemoLight(WemoEntity, LightEntity):
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:
"""Return the ID of this light.""" """Return the ID of this light."""
return str(self.light.uniqueID) return cast(str, self.light.uniqueID)
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
@ -127,7 +127,7 @@ class WemoLight(WemoEntity, LightEntity):
@property @property
def brightness(self) -> int: def brightness(self) -> int:
"""Return the brightness of this light between 0..255.""" """Return the brightness of this light between 0..255."""
return int(self.light.state.get("level", 255)) return cast(int, self.light.state.get("level", 255))
@property @property
def hs_color(self) -> tuple[float, float] | None: def hs_color(self) -> tuple[float, float] | None:
@ -139,14 +139,12 @@ class WemoLight(WemoEntity, LightEntity):
@property @property
def color_temp(self) -> int | None: def color_temp(self) -> int | None:
"""Return the color temperature of this light in mireds.""" """Return the color temperature of this light in mireds."""
if (temp := self.light.state.get("temperature_mireds")) is not None: return cast(Optional[int], self.light.state.get("temperature_mireds"))
return int(temp)
return None
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if device is on.""" """Return true if device is on."""
return bool(self.light.state.get("onoff") != WEMO_OFF) return cast(int, self.light.state.get("onoff")) != WEMO_OFF
@property @property
def supported_features(self) -> int: def supported_features(self) -> int:
@ -194,7 +192,7 @@ class WemoLight(WemoEntity, LightEntity):
self.schedule_update_ha_state() self.schedule_update_ha_state()
class WemoDimmer(WemoEntity, LightEntity): class WemoDimmer(WemoBinaryStateEntity, LightEntity):
"""Representation of a WeMo dimmer.""" """Representation of a WeMo dimmer."""
@property @property
@ -205,14 +203,9 @@ class WemoDimmer(WemoEntity, LightEntity):
@property @property
def brightness(self) -> int: def brightness(self) -> int:
"""Return the brightness of this light between 1 and 100.""" """Return the brightness of this light between 1 and 100."""
wemo_brightness = int(self.wemo.get_brightness()) wemo_brightness: int = self.wemo.get_brightness()
return int((wemo_brightness * 255) / 100) return int((wemo_brightness * 255) / 100)
@property
def is_on(self) -> bool:
"""Return true if the state is on."""
return bool(self.wemo.get_state())
def turn_on(self, **kwargs: Any) -> None: def turn_on(self, **kwargs: Any) -> None:
"""Turn the dimmer on.""" """Turn the dimmer on."""
# Wemo dimmer switches use a range of [0, 100] to control # Wemo dimmer switches use a range of [0, 100] to control

View File

@ -49,7 +49,8 @@ class InsightSensor(WemoEntity, SensorEntity):
@property @property
def name_suffix(self) -> str: def name_suffix(self) -> str:
"""Return the name of the entity if any.""" """Return the name of the entity if any."""
return str(self.entity_description.name) assert self.entity_description.name
return self.entity_description.name
@property @property
def unique_id_suffix(self) -> str: def unique_id_suffix(self) -> str:

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import asyncio import asyncio
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any from typing import Any, cast
from pywemo import CoffeeMaker, Insight, Maker from pywemo import CoffeeMaker, Insight, Maker
@ -16,7 +16,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import convert from homeassistant.util import convert
from .const import DOMAIN as WEMO_DOMAIN from .const import DOMAIN as WEMO_DOMAIN
from .entity import WemoEntity from .entity import WemoBinaryStateEntity
from .wemo_device import DeviceCoordinator from .wemo_device import DeviceCoordinator
SCAN_INTERVAL = timedelta(seconds=10) SCAN_INTERVAL = timedelta(seconds=10)
@ -57,7 +57,7 @@ async def async_setup_entry(
) )
class WemoSwitch(WemoEntity, SwitchEntity): class WemoSwitch(WemoBinaryStateEntity, SwitchEntity):
"""Representation of a WeMo switch.""" """Representation of a WeMo switch."""
@property @property
@ -133,7 +133,7 @@ class WemoSwitch(WemoEntity, SwitchEntity):
def detail_state(self) -> str: def detail_state(self) -> str:
"""Return the state of the device.""" """Return the state of the device."""
if isinstance(self.wemo, CoffeeMaker): if isinstance(self.wemo, CoffeeMaker):
return str(self.wemo.mode_string) return cast(str, self.wemo.mode_string)
if isinstance(self.wemo, Insight): if isinstance(self.wemo, Insight):
standby_state = int(self.wemo.insight_params.get("state", 0)) standby_state = int(self.wemo.insight_params.get("state", 0))
if standby_state == WEMO_ON: if standby_state == WEMO_ON:
@ -152,11 +152,6 @@ class WemoSwitch(WemoEntity, SwitchEntity):
return "mdi:coffee" return "mdi:coffee"
return None return None
@property
def is_on(self) -> bool:
"""Return true if the state is on. Standby is on."""
return bool(self.wemo.get_state())
def turn_on(self, **kwargs: Any) -> None: def turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on.""" """Turn the switch on."""
with self._wemo_exception_handler("turn on"): with self._wemo_exception_handler("turn on"):