From 2e2f77a95ea471d4717e4bff2dc6b1c0f7c6bd66 Mon Sep 17 00:00:00 2001 From: Vincent Le Bourlot Date: Fri, 28 Apr 2023 09:57:43 +0200 Subject: [PATCH] Fix/api calls (#138) * add update coordinator * down to 30s coordinator update. * fix style. * bump pyvesync * bump pyvesync * sourcery refactor. * Fix missing vs_mode_auto (#143) * Update manifest.json --- custom_components/vesync/__init__.py | 28 +++++++++++- custom_components/vesync/binary_sensor.py | 18 +++++--- custom_components/vesync/common.py | 19 +++++--- custom_components/vesync/fan.py | 18 +++++--- custom_components/vesync/humidifier.py | 33 ++++++++------ custom_components/vesync/light.py | 32 ++++++++++---- custom_components/vesync/manifest.json | 2 +- custom_components/vesync/number.py | 38 +++++++++------- custom_components/vesync/sensor.py | 51 +++++++++++++++------ custom_components/vesync/switch.py | 54 ++++++++++++++++------- 10 files changed, 205 insertions(+), 88 deletions(-) diff --git a/custom_components/vesync/__init__.py b/custom_components/vesync/__init__.py index 8ae086a..29e3ddc 100644 --- a/custom_components/vesync/__init__.py +++ b/custom_components/vesync/__init__.py @@ -1,11 +1,13 @@ """VeSync integration.""" import logging +from datetime import timedelta from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.helpers import config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_send +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from pyvesync.vesync import VeSync from .common import async_process_devices @@ -53,13 +55,35 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b _LOGGER.error("Unable to login to the VeSync server") return False - device_dict = await async_process_devices(hass, manager) - forward_setup = hass.config_entries.async_forward_entry_setup hass.data[DOMAIN] = {config_entry.entry_id: {}} hass.data[DOMAIN][config_entry.entry_id][VS_MANAGER] = manager + # Create a DataUpdateCoordinator for the manager + async def async_update_data(): + """Fetch data from API endpoint.""" + try: + await hass.async_add_executor_job(manager.update) + except Exception as err: + raise UpdateFailed(f"Update failed: {err}") + + coordinator = DataUpdateCoordinator( + hass, + _LOGGER, + name="vesync", + update_method=async_update_data, + update_interval=timedelta(seconds=30), + ) + + # Fetch initial data so we have data when entities subscribe + await coordinator.async_refresh() + + # Store the coordinator instance in hass.data + hass.data[DOMAIN][config_entry.entry_id]["coordinator"] = coordinator + + device_dict = await async_process_devices(hass, manager) + for p, vs_p in PLATFORMS.items(): hass.data[DOMAIN][config_entry.entry_id][vs_p] = [] if device_dict[vs_p]: diff --git a/custom_components/vesync/binary_sensor.py b/custom_components/vesync/binary_sensor.py index 25da20d..f587dac 100644 --- a/custom_components/vesync/binary_sensor.py +++ b/custom_components/vesync/binary_sensor.py @@ -21,29 +21,33 @@ async def async_setup_entry( ) -> None: """Set up binary sensors.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_BINARY_SENSORS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_BINARY_SENSORS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_BINARY_SENSORS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" entities = [] for dev in devices: if has_feature(dev, "details", "water_lacks"): - entities.append(VeSyncOutOfWaterSensor(dev)) + entities.append(VeSyncOutOfWaterSensor(dev, coordinator)) if has_feature(dev, "details", "water_tank_lifted"): - entities.append(VeSyncWaterTankLiftedSensor(dev)) + entities.append(VeSyncWaterTankLiftedSensor(dev, coordinator)) async_add_entities(entities, update_before_add=True) @@ -51,9 +55,9 @@ def _setup_entities(devices, async_add_entities): class VeSyncBinarySensorEntity(VeSyncBaseEntity, BinarySensorEntity): """Representation of a binary sensor describing diagnostics of a VeSync humidifier.""" - def __init__(self, humidifier): + def __init__(self, humidifier, coordinator): """Initialize the VeSync humidifier device.""" - super().__init__(humidifier) + super().__init__(humidifier, coordinator) self.smarthumidifier = humidifier @property diff --git a/custom_components/vesync/common.py b/custom_components/vesync/common.py index e8d9e8c..ddfeb01 100644 --- a/custom_components/vesync/common.py +++ b/custom_components/vesync/common.py @@ -3,6 +3,7 @@ import logging from homeassistant.components.diagnostics import async_redact_data from homeassistant.helpers.entity import Entity, ToggleEntity +from homeassistant.helpers.update_coordinator import CoordinatorEntity from pyvesync.vesyncfan import model_features from .const import ( @@ -48,7 +49,6 @@ async def async_process_devices(hass, manager): VS_BINARY_SENSORS: [], } - await hass.async_add_executor_job(manager.update) redacted = async_redact_data( {k: [d.__dict__ for d in v] for k, v in manager._dev_list.items()}, ["cid", "uuid", "mac_id"], @@ -105,12 +105,13 @@ async def async_process_devices(hass, manager): return devices -class VeSyncBaseEntity(Entity): +class VeSyncBaseEntity(CoordinatorEntity, Entity): """Base class for VeSync Entity Representations.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the VeSync device.""" self.device = device + super().__init__(coordinator, context=device) @property def base_unique_id(self): @@ -152,14 +153,20 @@ class VeSyncBaseEntity(Entity): "sw_version": self.device.current_firm_version, } - def update(self): - """Update vesync device.""" - self.device.update() + async def async_added_to_hass(self): + """When entity is added to hass.""" + self.async_on_remove( + self.coordinator.async_add_listener(self.async_write_ha_state) + ) class VeSyncDevice(VeSyncBaseEntity, ToggleEntity): """Base class for VeSync Device Representations.""" + def __init__(self, device, coordinator): + """Initialize the VeSync device.""" + super().__init__(device, coordinator) + @property def is_on(self): """Return True if device is on.""" diff --git a/custom_components/vesync/fan.py b/custom_components/vesync/fan.py index 2c39f49..ea64b84 100644 --- a/custom_components/vesync/fan.py +++ b/custom_components/vesync/fan.py @@ -33,32 +33,38 @@ async def async_setup_entry( ) -> None: """Set up the VeSync fan platform.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_FANS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_FANS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_FANS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" - async_add_entities([VeSyncFanHA(dev) for dev in devices], update_before_add=True) + async_add_entities( + [VeSyncFanHA(dev, coordinator) for dev in devices], update_before_add=True + ) class VeSyncFanHA(VeSyncDevice, FanEntity): """Representation of a VeSync fan.""" - def __init__(self, fan): + def __init__(self, fan, coordinator): """Initialize the VeSync fan device.""" - super().__init__(fan) + super().__init__(fan, coordinator) self.smartfan = fan self._speed_range = (1, 1) self._attr_preset_modes = [VS_MODE_MANUAL, VS_MODE_AUTO, VS_MODE_SLEEP] diff --git a/custom_components/vesync/humidifier.py b/custom_components/vesync/humidifier.py index 394fbf3..431e295 100644 --- a/custom_components/vesync/humidifier.py +++ b/custom_components/vesync/humidifier.py @@ -22,6 +22,7 @@ from .const import ( DOMAIN, VS_DISCOVERY, VS_HUMIDIFIERS, + VS_MODE_AUTO, VS_MODE_HUMIDITY, VS_MODE_MANUAL, VS_MODE_SLEEP, @@ -36,8 +37,9 @@ MIN_HUMIDITY = 30 VS_TO_HA_MODE_MAP = { - VS_MODE_MANUAL: MODE_NORMAL, + VS_MODE_AUTO: MODE_AUTO, VS_MODE_HUMIDITY: MODE_AUTO, + VS_MODE_MANUAL: MODE_NORMAL, VS_MODE_SLEEP: MODE_SLEEP, } @@ -51,25 +53,30 @@ async def async_setup_entry( ) -> None: """Set up the VeSync humidifier platform.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_HUMIDIFIERS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_HUMIDIFIERS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_HUMIDIFIERS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" async_add_entities( - [VeSyncHumidifierHA(dev) for dev in devices], update_before_add=True + [VeSyncHumidifierHA(dev, coordinator) for dev in devices], + update_before_add=True, ) @@ -93,9 +100,9 @@ class VeSyncHumidifierHA(VeSyncDevice, HumidifierEntity): _attr_max_humidity = MAX_HUMIDITY _attr_min_humidity = MIN_HUMIDITY - def __init__(self, humidifier: VeSyncHumid200300S): + def __init__(self, humidifier: VeSyncHumid200300S, coordinator): """Initialize the VeSync humidifier device.""" - super().__init__(humidifier) + super().__init__(humidifier, coordinator) self.smarthumidifier = humidifier @property @@ -157,10 +164,10 @@ class VeSyncHumidifierHA(VeSyncDevice, HumidifierEntity): raise ValueError( "{humidity} is not between {self.min_humidity} and {self.max_humidity} (inclusive)" ) - success = self.smarthumidifier.set_humidity(humidity) - if not success: + if self.smarthumidifier.set_humidity(humidity): + self.schedule_update_ha_state() + else: raise ValueError("An error occurred while setting humidity.") - self.schedule_update_ha_state() def set_mode(self, mode: str) -> None: """Set the mode of the device.""" @@ -168,10 +175,10 @@ class VeSyncHumidifierHA(VeSyncDevice, HumidifierEntity): raise ValueError( "{mode} is not one of the valid available modes: {self.available_modes}" ) - success = self.smarthumidifier.set_humidity_mode(_get_vs_mode(mode)) - if not success: + if self.smarthumidifier.set_humidity_mode(_get_vs_mode(mode)): + self.schedule_update_ha_state() + else: raise ValueError("An error occurred while setting mode.") - self.schedule_update_ha_state() def turn_on( self, diff --git a/custom_components/vesync/light.py b/custom_components/vesync/light.py index 61cc635..fd45cd7 100644 --- a/custom_components/vesync/light.py +++ b/custom_components/vesync/light.py @@ -27,31 +27,35 @@ async def async_setup_entry( ) -> None: """Set up lights.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_LIGHTS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_LIGHTS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_LIGHTS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" entities = [] for dev in devices: if DEV_TYPE_TO_HA.get(dev.device_type) in ("walldimmer", "bulb-dimmable"): - entities.append(VeSyncDimmableLightHA(dev)) + entities.append(VeSyncDimmableLightHA(dev, coordinator)) if DEV_TYPE_TO_HA.get(dev.device_type) in ("bulb-tunable-white",): - entities.append(VeSyncTunableWhiteLightHA(dev)) + entities.append(VeSyncTunableWhiteLightHA(dev, coordinator)) if hasattr(dev, "night_light") and dev.night_light: - entities.append(VeSyncNightLightHA(dev)) + entities.append(VeSyncNightLightHA(dev, coordinator)) async_add_entities(entities, update_before_add=True) @@ -84,6 +88,10 @@ def _ha_brightness_to_vesync(ha_brightness): class VeSyncBaseLight(VeSyncDevice, LightEntity): """Base class for VeSync Light Devices Representations.""" + def __init_(self, light, coordinator): + """Initialize the VeSync light device.""" + super().__init__(light, coordinator) + @property def brightness(self): """Get light brightness.""" @@ -132,6 +140,10 @@ class VeSyncBaseLight(VeSyncDevice, LightEntity): class VeSyncDimmableLightHA(VeSyncBaseLight, LightEntity): """Representation of a VeSync dimmable light device.""" + def __init__(self, device, coordinator): + """Initialize the VeSync dimmable light device.""" + super().__init__(device, coordinator) + @property def color_mode(self): """Set color mode for this entity.""" @@ -146,6 +158,10 @@ class VeSyncDimmableLightHA(VeSyncBaseLight, LightEntity): class VeSyncTunableWhiteLightHA(VeSyncBaseLight, LightEntity): """Representation of a VeSync Tunable White Light device.""" + def __init__(self, device, coordinator): + """Initialize the VeSync Tunable White Light device.""" + super().__init__(device, coordinator) + @property def color_temp(self): """Get device white temperature.""" @@ -197,9 +213,9 @@ class VeSyncTunableWhiteLightHA(VeSyncBaseLight, LightEntity): class VeSyncNightLightHA(VeSyncDimmableLightHA): """Representation of the night light on a VeSync device.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the VeSync device.""" - super().__init__(device) + super().__init__(device, coordinator) self.device = device self.has_brightness = has_feature( self.device, "details", "night_light_brightness" diff --git a/custom_components/vesync/manifest.json b/custom_components/vesync/manifest.json index 57a194a..61b4787 100644 --- a/custom_components/vesync/manifest.json +++ b/custom_components/vesync/manifest.json @@ -13,5 +13,5 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/vlebourl/custom_vesync", "requirements": ["pyvesync==2.1.6"], - "version": "0.2.5" + "version": "1.0.0" } diff --git a/custom_components/vesync/number.py b/custom_components/vesync/number.py index 299399c..306044a 100644 --- a/custom_components/vesync/number.py +++ b/custom_components/vesync/number.py @@ -23,33 +23,37 @@ async def async_setup_entry( ) -> None: """Set up numbers.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_NUMBERS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_NUMBERS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_NUMBERS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" entities = [] for dev in devices: if has_feature(dev, "details", "mist_virtual_level"): - entities.append(VeSyncHumidifierMistLevelHA(dev)) + entities.append(VeSyncHumidifierMistLevelHA(dev, coordinator)) if has_feature(dev, "config", "auto_target_humidity"): - entities.append(VeSyncHumidifierTargetLevelHA(dev)) + entities.append(VeSyncHumidifierTargetLevelHA(dev, coordinator)) if has_feature(dev, "details", "warm_mist_level"): - entities.append(VeSyncHumidifierWarmthLevelHA(dev)) + entities.append(VeSyncHumidifierWarmthLevelHA(dev, coordinator)) if has_feature(dev, "config_dict", "levels"): - entities.append(VeSyncFanSpeedLevelHA(dev)) + entities.append(VeSyncFanSpeedLevelHA(dev, coordinator)) async_add_entities(entities, update_before_add=True) @@ -57,9 +61,9 @@ def _setup_entities(devices, async_add_entities): class VeSyncNumberEntity(VeSyncBaseEntity, NumberEntity): """Representation of a number for configuring a VeSync fan.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the VeSync fan device.""" - super().__init__(device) + super().__init__(device, coordinator) @property def entity_category(self): @@ -70,9 +74,9 @@ class VeSyncNumberEntity(VeSyncBaseEntity, NumberEntity): class VeSyncFanSpeedLevelHA(VeSyncNumberEntity): """Representation of the fan speed level of a VeSync fan.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the number entity.""" - super().__init__(device) + super().__init__(device, coordinator) self._attr_native_min_value = device.config_dict["levels"][0] self._attr_native_max_value = device.config_dict["levels"][-1] self._attr_native_step = 1 @@ -105,9 +109,9 @@ class VeSyncFanSpeedLevelHA(VeSyncNumberEntity): class VeSyncHumidifierMistLevelHA(VeSyncNumberEntity): """Representation of the mist level of a VeSync humidifier.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the number entity.""" - super().__init__(device) + super().__init__(device, coordinator) self._attr_native_min_value = device.config_dict["mist_levels"][0] self._attr_native_max_value = device.config_dict["mist_levels"][-1] self._attr_native_step = 1 @@ -140,9 +144,9 @@ class VeSyncHumidifierMistLevelHA(VeSyncNumberEntity): class VeSyncHumidifierWarmthLevelHA(VeSyncNumberEntity): """Representation of the warmth level of a VeSync humidifier.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the number entity.""" - super().__init__(device) + super().__init__(device, coordinator) self._attr_native_min_value = device.config_dict["warm_mist_levels"][0] self._attr_native_max_value = device.config_dict["warm_mist_levels"][-1] self._attr_native_step = 1 @@ -175,9 +179,9 @@ class VeSyncHumidifierWarmthLevelHA(VeSyncNumberEntity): class VeSyncHumidifierTargetLevelHA(VeSyncNumberEntity): """Representation of the target humidity level of a VeSync humidifier.""" - def __init__(self, device): + def __init__(self, device, coordinator): """Initialize the number entity.""" - super().__init__(device) + super().__init__(device, coordinator) self._attr_native_min_value = MIN_HUMIDITY self._attr_native_max_value = MAX_HUMIDITY self._attr_native_step = 1 diff --git a/custom_components/vesync/sensor.py b/custom_components/vesync/sensor.py index 89fecda..77bbdcd 100644 --- a/custom_components/vesync/sensor.py +++ b/custom_components/vesync/sensor.py @@ -26,33 +26,42 @@ async def async_setup_entry( ) -> None: """Set up switches.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SENSORS), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_SENSORS], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_SENSORS], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" entities = [] for dev in devices: if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet": - entities.extend((VeSyncPowerSensor(dev), VeSyncEnergySensor(dev))) + entities.extend( + ( + VeSyncPowerSensor(dev, coordinator), + VeSyncEnergySensor(dev, coordinator), + ) + ) if has_feature(dev, "details", "humidity"): - entities.append(VeSyncHumiditySensor(dev)) + entities.append(VeSyncHumiditySensor(dev, coordinator)) if has_feature(dev, "details", "air_quality"): - entities.append(VeSyncAirQualitySensor(dev)) + entities.append(VeSyncAirQualitySensor(dev, coordinator)) if has_feature(dev, "details", "filter_life"): - entities.append(VeSyncFilterLifeSensor(dev)) + entities.append(VeSyncFilterLifeSensor(dev, coordinator)) async_add_entities(entities, update_before_add=True) @@ -60,9 +69,9 @@ def _setup_entities(devices, async_add_entities): class VeSyncOutletSensorEntity(VeSyncBaseEntity, SensorEntity): """Representation of a sensor describing diagnostics of a VeSync outlet.""" - def __init__(self, plug): + def __init__(self, plug, coordinator): """Initialize the VeSync outlet device.""" - super().__init__(plug) + super().__init__(plug, coordinator) self.smartplug = plug @property @@ -74,6 +83,10 @@ class VeSyncOutletSensorEntity(VeSyncBaseEntity, SensorEntity): class VeSyncPowerSensor(VeSyncOutletSensorEntity): """Representation of current power use for a VeSync outlet.""" + def __init__(self, plug, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(plug, coordinator) + @property def unique_id(self): """Return unique ID for power sensor on device.""" @@ -113,9 +126,9 @@ class VeSyncPowerSensor(VeSyncOutletSensorEntity): class VeSyncEnergySensor(VeSyncOutletSensorEntity): """Representation of current day's energy use for a VeSync outlet.""" - def __init__(self, plug): + def __init__(self, plug, coordinator): """Initialize the VeSync outlet device.""" - super().__init__(plug) + super().__init__(plug, coordinator) self.smartplug = plug @property @@ -157,9 +170,9 @@ class VeSyncEnergySensor(VeSyncOutletSensorEntity): class VeSyncHumidifierSensorEntity(VeSyncBaseEntity, SensorEntity): """Representation of a sensor describing diagnostics of a VeSync humidifier.""" - def __init__(self, humidifier): + def __init__(self, humidifier, coordinator): """Initialize the VeSync humidifier device.""" - super().__init__(humidifier) + super().__init__(humidifier, coordinator) self.smarthumidifier = humidifier @property @@ -174,6 +187,10 @@ class VeSyncAirQualitySensor(VeSyncHumidifierSensorEntity): _attr_state_class = SensorStateClass.MEASUREMENT _attr_device_class = SensorDeviceClass.AQI + def __init__(self, plug, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(plug, coordinator) + @property def unique_id(self): """Return unique ID for air quality sensor on device.""" @@ -198,6 +215,10 @@ class VeSyncAirQualitySensor(VeSyncHumidifierSensorEntity): class VeSyncFilterLifeSensor(VeSyncHumidifierSensorEntity): """Representation of a filter life sensor.""" + def __init__(self, plug, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(plug, coordinator) + @property def unique_id(self): """Return unique ID for filter life sensor on device.""" @@ -245,6 +266,10 @@ class VeSyncFilterLifeSensor(VeSyncHumidifierSensorEntity): class VeSyncHumiditySensor(VeSyncHumidifierSensorEntity): """Representation of current humidity for a VeSync humidifier.""" + def __init__(self, humidity, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(humidity, coordinator) + @property def unique_id(self): """Return unique ID for humidity sensor on device.""" diff --git a/custom_components/vesync/switch.py b/custom_components/vesync/switch.py index 52e2f61..65887b1 100644 --- a/custom_components/vesync/switch.py +++ b/custom_components/vesync/switch.py @@ -21,37 +21,41 @@ async def async_setup_entry( ) -> None: """Set up switches.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] + @callback def discover(devices): """Add new devices to platform.""" - _setup_entities(devices, async_add_entities) + _setup_entities(devices, async_add_entities, coordinator) config_entry.async_on_unload( async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SWITCHES), discover) ) _setup_entities( - hass.data[DOMAIN][config_entry.entry_id][VS_SWITCHES], async_add_entities + hass.data[DOMAIN][config_entry.entry_id][VS_SWITCHES], + async_add_entities, + coordinator, ) @callback -def _setup_entities(devices, async_add_entities): +def _setup_entities(devices, async_add_entities, coordinator): """Check if device is online and add entity.""" entities = [] for dev in devices: if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet": - entities.append(VeSyncSwitchHA(dev)) + entities.append(VeSyncSwitchHA(dev, coordinator)) if DEV_TYPE_TO_HA.get(dev.device_type) == "switch": - entities.append(VeSyncLightSwitch(dev)) + entities.append(VeSyncLightSwitch(dev, coordinator)) if getattr(dev, "set_auto_mode", None): - entities.append(VeSyncHumidifierAutoOnHA(dev)) + entities.append(VeSyncHumidifierAutoOnHA(dev, coordinator)) if getattr(dev, "automatic_stop_on", None): - entities.append(VeSyncHumidifierAutomaticStopHA(dev)) + entities.append(VeSyncHumidifierAutomaticStopHA(dev, coordinator)) if getattr(dev, "turn_on_display", None): - entities.append(VeSyncHumidifierDisplayHA(dev)) + entities.append(VeSyncHumidifierDisplayHA(dev, coordinator)) if getattr(dev, "child_lock_on", None): - entities.append(VeSyncFanChildLockHA(dev)) + entities.append(VeSyncFanChildLockHA(dev, coordinator)) async_add_entities(entities, update_before_add=True) @@ -59,6 +63,10 @@ def _setup_entities(devices, async_add_entities): class VeSyncBaseSwitch(VeSyncDevice, SwitchEntity): """Base class for VeSync switch Device Representations.""" + def __init__(self, plug, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(plug, coordinator) + def turn_on(self, **kwargs): """Turn the device on.""" self.device.turn_on() @@ -67,9 +75,9 @@ class VeSyncBaseSwitch(VeSyncDevice, SwitchEntity): class VeSyncSwitchHA(VeSyncBaseSwitch, SwitchEntity): """Representation of a VeSync switch.""" - def __init__(self, plug): + def __init__(self, plug, coordinator): """Initialize the VeSync switch device.""" - super().__init__(plug) + super().__init__(plug, coordinator) self.smartplug = plug @property @@ -95,18 +103,18 @@ class VeSyncSwitchHA(VeSyncBaseSwitch, SwitchEntity): class VeSyncLightSwitch(VeSyncBaseSwitch, SwitchEntity): """Handle representation of VeSync Light Switch.""" - def __init__(self, switch): + def __init__(self, switch, coordinator): """Initialize Light Switch device class.""" - super().__init__(switch) + super().__init__(switch, coordinator) self.switch = switch class VeSyncSwitchEntity(VeSyncBaseEntity, SwitchEntity): """Representation of a switch for configuring a VeSync humidifier.""" - def __init__(self, humidifier): + def __init__(self, humidifier, coordinator): """Initialize the VeSync humidifier device.""" - super().__init__(humidifier) + super().__init__(humidifier, coordinator) self.smarthumidifier = humidifier @property @@ -118,6 +126,10 @@ class VeSyncSwitchEntity(VeSyncBaseEntity, SwitchEntity): class VeSyncFanChildLockHA(VeSyncSwitchEntity): """Representation of the child lock switch.""" + def __init__(self, lock, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(lock, coordinator) + @property def unique_id(self): """Return the ID of this display.""" @@ -145,6 +157,10 @@ class VeSyncFanChildLockHA(VeSyncSwitchEntity): class VeSyncHumidifierDisplayHA(VeSyncSwitchEntity): """Representation of the child lock switch.""" + def __init__(self, lock, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(lock, coordinator) + @property def unique_id(self): """Return the ID of this display.""" @@ -172,6 +188,10 @@ class VeSyncHumidifierDisplayHA(VeSyncSwitchEntity): class VeSyncHumidifierAutomaticStopHA(VeSyncSwitchEntity): """Representation of the automatic stop toggle on a VeSync humidifier.""" + def __init__(self, automatic, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(automatic, coordinator) + @property def unique_id(self): """Return the ID of this device.""" @@ -199,6 +219,10 @@ class VeSyncHumidifierAutomaticStopHA(VeSyncSwitchEntity): class VeSyncHumidifierAutoOnHA(VeSyncSwitchEntity): """Provide switch to turn off auto mode and set manual mist level 1 on a VeSync humidifier.""" + def __init__(self, autooff, coordinator): + """Initialize the VeSync outlet device.""" + super().__init__(autooff, coordinator) + @property def unique_id(self): """Return the ID of this device."""