Add missing entities to core 300S (#37)

* Add filter life sensor

* Add switch for child_lock

* Update switch.py

* Update switch.py

* Update common.py

* bump trunk version

* improve feature discovery

* fix style

* improve feature discovery
This commit is contained in:
Vincent Le Bourlot 2022-07-30 09:59:00 +02:00 committed by GitHub
parent 89f6e3b552
commit 84ad318e35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 102 deletions

View File

@ -8,7 +8,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .common import VeSyncBaseEntity, is_humidifier
from .common import VeSyncBaseEntity, has_feature
from .const import DOMAIN, VS_BINARY_SENSORS, VS_DISCOVERY
_LOGGER = logging.getLogger(__name__)
@ -40,20 +40,15 @@ def _setup_entities(devices, async_add_entities):
"""Check if device is online and add entity."""
entities = []
for dev in devices:
if is_humidifier(dev.device_type):
entities.extend(
(VeSyncOutOfWaterSensor(dev), VeSyncWaterTankLiftedSensor(dev))
)
else:
_LOGGER.warning(
"%s - Unknown device type - %s", dev.device_name, dev.device_type
)
if has_feature(dev, "details", "water_lacks"):
entities.append(VeSyncOutOfWaterSensor(dev))
if has_feature(dev, "details", "water_tank_lifted"):
entities.append(VeSyncWaterTankLiftedSensor(dev))
async_add_entities(entities, update_before_add=True)
class VeSyncHumidifierBinarySensorEntity(VeSyncBaseEntity, BinarySensorEntity):
class VeSyncBinarySensorEntity(VeSyncBaseEntity, BinarySensorEntity):
"""Representation of a binary sensor describing diagnostics of a VeSync humidifier."""
def __init__(self, humidifier):
@ -67,7 +62,7 @@ class VeSyncHumidifierBinarySensorEntity(VeSyncBaseEntity, BinarySensorEntity):
return EntityCategory.DIAGNOSTIC
class VeSyncOutOfWaterSensor(VeSyncHumidifierBinarySensorEntity):
class VeSyncOutOfWaterSensor(VeSyncBinarySensorEntity):
"""Out of Water Sensor."""
@property
@ -86,7 +81,7 @@ class VeSyncOutOfWaterSensor(VeSyncHumidifierBinarySensorEntity):
return self.smarthumidifier.details["water_lacks"]
class VeSyncWaterTankLiftedSensor(VeSyncHumidifierBinarySensorEntity):
class VeSyncWaterTankLiftedSensor(VeSyncBinarySensorEntity):
"""Tank Lifted Sensor."""
@property

View File

@ -18,6 +18,11 @@ from .const import (
_LOGGER = logging.getLogger(__name__)
def has_feature(device, dictionary, attribute):
"""Return the detail of the attribute."""
return getattr(device, dictionary, None).get(attribute, None) is not None
def is_humidifier(device_type: str) -> bool:
"""Return true if the device type is a humidifier."""
return model_features(device_type)["module"].find("VeSyncHumid") > -1
@ -48,21 +53,14 @@ async def async_process_devices(hass, manager):
_LOGGER.debug("Found a fan: %s", fan.__dict__)
if is_humidifier(fan.device_type):
devices[VS_HUMIDIFIERS].append(fan)
devices[VS_NUMBERS].append(fan) # for night light and mist level
devices[VS_SWITCHES].append(fan) # for automatic stop and display
devices[VS_SENSORS].append(fan) # for humidity sensor
devices[VS_BINARY_SENSORS].append(
fan
) # for out of water and water tank lifted sensors
if fan.night_light:
devices[VS_LIGHTS].append(fan) # for night light
else:
if hasattr(fan, "config_dict"):
devices[VS_NUMBERS].append(fan)
if "air_quality" in fan.config_dict["features"]:
devices[VS_SENSORS].append(fan)
devices[VS_SWITCHES].append(fan) # for automatic stop and display
devices[VS_FANS].append(fan)
devices[VS_NUMBERS].append(fan)
devices[VS_SWITCHES].append(fan)
devices[VS_SENSORS].append(fan)
devices[VS_BINARY_SENSORS].append(fan)
devices[VS_LIGHTS].append(fan)
_LOGGER.info("%d VeSync fans found", len(manager.fans))
if manager.bulbs:

View File

@ -14,7 +14,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .common import VeSyncDevice, is_humidifier
from .common import VeSyncDevice
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_LIGHTS
_LOGGER = logging.getLogger(__name__)
@ -48,15 +48,10 @@ def _setup_entities(devices, async_add_entities):
for dev in devices:
if DEV_TYPE_TO_HA.get(dev.device_type) in ("walldimmer", "bulb-dimmable"):
entities.append(VeSyncDimmableLightHA(dev))
elif DEV_TYPE_TO_HA.get(dev.device_type) in ("bulb-tunable-white",):
if DEV_TYPE_TO_HA.get(dev.device_type) in ("bulb-tunable-white",):
entities.append(VeSyncTunableWhiteLightHA(dev))
elif is_humidifier(dev.device_type):
if dev.night_light:
entities.append(VeSyncHumidifierNightLightHA(dev))
else:
_LOGGER.debug(
"%s - Unknown device type - %s", dev.device_name, dev.device_type
)
continue
async_add_entities(entities, update_before_add=True)

View File

@ -8,7 +8,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .common import VeSyncBaseEntity, is_air_purifier, is_humidifier
from .common import VeSyncBaseEntity, has_feature, is_air_purifier, is_humidifier
from .const import DOMAIN, VS_DISCOVERY, VS_NUMBERS
MAX_HUMIDITY = 80
@ -43,29 +43,28 @@ def _setup_entities(devices, async_add_entities):
"""Check if device is online and add entity."""
entities = []
for dev in devices:
if is_humidifier(dev.device_type):
ext = (VeSyncHumidifierMistLevelHA(dev), VeSyncHumidifierTargetLevelHA(dev))
if dev.warm_mist_feature:
ext = (*ext, VeSyncHumidifierWarmthLevelHA(dev))
entities.extend(ext)
elif is_air_purifier(dev.device_type):
entities.extend((VeSyncFanSpeedLevelHA(dev),))
else:
_LOGGER.debug(
"%s - Unknown device type - %s", dev.device_name, dev.device_type
)
continue
if has_feature(dev, "details", "mist_virtual_level"):
entities.append(VeSyncHumidifierMistLevelHA(dev))
if has_feature(dev, "config", "auto_target_humidity"):
entities.append(VeSyncHumidifierTargetLevelHA(dev))
if has_feature(dev, "details", "warm_mist_level"):
entities.append(VeSyncHumidifierWarmthLevelHA(dev))
if has_feature(dev, "config_dict", "levels"):
entities.append((VeSyncFanSpeedLevelHA(dev),))
async_add_entities(entities, update_before_add=True)
class VeSyncFanNumberEntity(VeSyncBaseEntity, NumberEntity):
class VeSyncNumberEntity(VeSyncBaseEntity, NumberEntity):
"""Representation of a number for configuring a VeSync fan."""
def __init__(self, fan):
def __init__(self, device):
"""Initialize the VeSync fan device."""
super().__init__(fan)
self.smartfan = fan
super().__init__(device)
if is_air_purifier(device.device_type):
self.smartfan = device
if is_humidifier(device.device_type):
self.smarthumidifier = device
@property
def entity_category(self):
@ -73,7 +72,7 @@ class VeSyncFanNumberEntity(VeSyncBaseEntity, NumberEntity):
return EntityCategory.CONFIG
class VeSyncFanSpeedLevelHA(VeSyncFanNumberEntity):
class VeSyncFanSpeedLevelHA(VeSyncNumberEntity):
"""Representation of the fan speed level of a VeSync fan."""
@property
@ -116,21 +115,7 @@ class VeSyncFanSpeedLevelHA(VeSyncFanNumberEntity):
self.device.change_fan_speed(int(value))
class VeSyncHumidifierNumberEntity(VeSyncBaseEntity, NumberEntity):
"""Representation of a number for configuring a VeSync humidifier."""
def __init__(self, humidifier):
"""Initialize the VeSync humidifier device."""
super().__init__(humidifier)
self.smarthumidifier = humidifier
@property
def entity_category(self):
"""Return the diagnostic entity category."""
return EntityCategory.CONFIG
class VeSyncHumidifierMistLevelHA(VeSyncHumidifierNumberEntity):
class VeSyncHumidifierMistLevelHA(VeSyncNumberEntity):
"""Representation of the mist level of a VeSync humidifier."""
@property
@ -173,7 +158,7 @@ class VeSyncHumidifierMistLevelHA(VeSyncHumidifierNumberEntity):
self.device.set_mist_level(int(value))
class VeSyncHumidifierWarmthLevelHA(VeSyncHumidifierNumberEntity):
class VeSyncHumidifierWarmthLevelHA(VeSyncNumberEntity):
"""Representation of the warmth level of a VeSync humidifier."""
@property
@ -216,7 +201,7 @@ class VeSyncHumidifierWarmthLevelHA(VeSyncHumidifierNumberEntity):
self.device.set_warm_level(int(value))
class VeSyncHumidifierTargetLevelHA(VeSyncHumidifierNumberEntity):
class VeSyncHumidifierTargetLevelHA(VeSyncNumberEntity):
"""Representation of the target humidity level of a VeSync humidifier."""
@property

View File

@ -13,7 +13,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .common import VeSyncBaseEntity, is_humidifier
from .common import VeSyncBaseEntity, has_feature
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_SENSORS
_LOGGER = logging.getLogger(__name__)
@ -47,14 +47,12 @@ def _setup_entities(devices, async_add_entities):
for dev in devices:
if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet":
entities.extend((VeSyncPowerSensor(dev), VeSyncEnergySensor(dev)))
elif is_humidifier(dev.device_type):
if has_feature(dev, "details", "humidity"):
entities.append(VeSyncHumiditySensor(dev))
elif "air_quality" in dev.config_dict["features"]:
if has_feature(dev, "details", "air_quality"):
entities.append(VeSyncAirQualitySensor(dev))
else:
_LOGGER.warning(
"%s - Unknown device type - %s", dev.device_name, dev.device_type
)
if has_feature(dev, "details", "filter_life"):
entities.append(VeSyncFilterLifeSensor(dev))
async_add_entities(entities, update_before_add=True)
@ -204,6 +202,40 @@ class VeSyncAirQualitySensor(VeSyncHumidifierSensorEntity):
return SensorStateClass.MEASUREMENT
class VeSyncFilterLifeSensor(VeSyncHumidifierSensorEntity):
"""Representation of a filter life sensor."""
@property
def unique_id(self):
"""Return unique ID for filter life sensor on device."""
return f"{super().unique_id}-filter-life"
@property
def name(self):
"""Return sensor name."""
return f"{super().name} filter life"
@property
def device_class(self):
"""Return the filter life device class."""
return None
@property
def native_value(self):
"""Return the filter life index."""
return self.smarthumidifier.details["filter_life"]
@property
def native_unit_of_measurement(self):
"""Return the % unit of measurement."""
return PERCENTAGE
@property
def state_class(self):
"""Return the measurement state class."""
return SensorStateClass.MEASUREMENT
class VeSyncHumiditySensor(VeSyncHumidifierSensorEntity):
"""Representation of current humidity for a VeSync humidifier."""

View File

@ -8,7 +8,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .common import VeSyncBaseEntity, VeSyncDevice, is_humidifier
from .common import VeSyncBaseEntity, VeSyncDevice
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_SWITCHES
_LOGGER = logging.getLogger(__name__)
@ -42,24 +42,16 @@ def _setup_entities(devices, async_add_entities):
for dev in devices:
if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet":
entities.append(VeSyncSwitchHA(dev))
elif DEV_TYPE_TO_HA.get(dev.device_type) == "switch":
if DEV_TYPE_TO_HA.get(dev.device_type) == "switch":
entities.append(VeSyncLightSwitch(dev))
elif is_humidifier(dev.device_type):
entities.extend(
(
VeSyncHumidifierDisplayHA(dev),
VeSyncHumidifierAutomaticStopHA(dev),
VeSyncHumidifierAutoOnHA(dev),
)
)
elif getattr(dev, "turn_on_display", None):
if getattr(dev, "set_auto_mode", None):
entities.append(VeSyncHumidifierAutoOnHA(dev))
if getattr(dev, "automatic_stop_on", None):
entities.append(VeSyncHumidifierAutomaticStopHA(dev))
if getattr(dev, "turn_on_display", None):
entities.append(VeSyncHumidifierDisplayHA(dev))
else:
_LOGGER.warning(
"%s - Unknown device type - %s", dev.device_name, dev.device_type
)
continue
if getattr(dev, "child_lock_on", None):
entities.append(VeSyncFanChildLockHA(dev))
async_add_entities(entities, update_before_add=True)
@ -109,7 +101,7 @@ class VeSyncLightSwitch(VeSyncBaseSwitch, SwitchEntity):
self.switch = switch
class VeSyncHumidifierSwitchEntity(VeSyncBaseEntity, SwitchEntity):
class VeSyncSwitchEntity(VeSyncBaseEntity, SwitchEntity):
"""Representation of a switch for configuring a VeSync humidifier."""
def __init__(self, humidifier):
@ -123,8 +115,35 @@ class VeSyncHumidifierSwitchEntity(VeSyncBaseEntity, SwitchEntity):
return EntityCategory.CONFIG
class VeSyncHumidifierDisplayHA(VeSyncHumidifierSwitchEntity):
"""Representation of the display on a VeSync humidifier."""
class VeSyncFanChildLockHA(VeSyncSwitchEntity):
"""Representation of the child lock switch."""
@property
def unique_id(self):
"""Return the ID of this display."""
return f"{super().unique_id}-child-lock"
@property
def name(self):
"""Return the name of the entity."""
return f"{super().name} child lock"
@property
def is_on(self):
"""Return True if it is locked."""
return self.device.details["child_locked"]
def turn_on(self, **kwargs):
"""Turn the lock on."""
self.device.child_lock_on()
def turn_off(self, **kwargs):
"""Turn the lock off."""
self.device.child_lock_off()
class VeSyncHumidifierDisplayHA(VeSyncSwitchEntity):
"""Representation of the child lock switch."""
@property
def unique_id(self):
@ -133,24 +152,24 @@ class VeSyncHumidifierDisplayHA(VeSyncHumidifierSwitchEntity):
@property
def name(self):
"""Return the name of the display."""
"""Return the name of the entity."""
return f"{super().name} display"
@property
def is_on(self):
"""Return True if display is on."""
"""Return True if it is locked."""
return self.device.details["display"]
def turn_on(self, **kwargs):
"""Turn the display on."""
"""Turn the lock on."""
self.device.turn_on_display()
def turn_off(self, **kwargs):
"""Turn the display off."""
"""Turn the lock off."""
self.device.turn_off_display()
class VeSyncHumidifierAutomaticStopHA(VeSyncHumidifierSwitchEntity):
class VeSyncHumidifierAutomaticStopHA(VeSyncSwitchEntity):
"""Representation of the automatic stop toggle on a VeSync humidifier."""
@property
@ -177,7 +196,7 @@ class VeSyncHumidifierAutomaticStopHA(VeSyncHumidifierSwitchEntity):
self.device.automatic_stop_off()
class VeSyncHumidifierAutoOnHA(VeSyncHumidifierSwitchEntity):
class VeSyncHumidifierAutoOnHA(VeSyncSwitchEntity):
"""Provide switch to turn off auto mode and set manual mist level 1 on a VeSync humidifier."""
@property