From 021cfc941eccbf5a6df97c1b51fac873fc4ae8d3 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sat, 1 Feb 2025 21:47:08 -0800 Subject: [PATCH] Bump aiovantage to 0.18.0 --- custom_components/vantage/binary_sensor.py | 2 +- custom_components/vantage/climate.py | 43 +++++---------- custom_components/vantage/cover.py | 62 ++------------------- custom_components/vantage/device.py | 4 +- custom_components/vantage/entity.py | 2 +- custom_components/vantage/events.py | 2 +- custom_components/vantage/light.py | 64 ++++++++-------------- custom_components/vantage/manifest.json | 2 +- custom_components/vantage/number.py | 7 ++- custom_components/vantage/services.py | 4 +- custom_components/vantage/switch.py | 21 ++++--- custom_components/vantage/text.py | 7 ++- pyproject.toml | 2 +- 13 files changed, 73 insertions(+), 149 deletions(-) diff --git a/custom_components/vantage/binary_sensor.py b/custom_components/vantage/binary_sensor.py index 856f1b2..4e67648 100644 --- a/custom_components/vantage/binary_sensor.py +++ b/custom_components/vantage/binary_sensor.py @@ -39,4 +39,4 @@ def __post_init__(self) -> None: @property def is_on(self) -> bool | None: """Return True if entity is on.""" - return self.obj.triggered + return self.obj.is_down diff --git a/custom_components/vantage/climate.py b/custom_components/vantage/climate.py index 686c056..84cb47b 100644 --- a/custom_components/vantage/climate.py +++ b/custom_components/vantage/climate.py @@ -30,21 +30,21 @@ # Map Vantage enums to HA enums VANTAGE_HVAC_MODE_MAP = { - Thermostat.OperationMode.HEAT: HVACMode.HEAT, - Thermostat.OperationMode.COOL: HVACMode.COOL, - Thermostat.OperationMode.AUTO: HVACMode.HEAT_COOL, - Thermostat.OperationMode.OFF: HVACMode.OFF, + Thermostat.OperationMode.Heat: HVACMode.HEAT, + Thermostat.OperationMode.Cool: HVACMode.COOL, + Thermostat.OperationMode.Auto: HVACMode.HEAT_COOL, + Thermostat.OperationMode.Off: HVACMode.OFF, } VANTAGE_HVAC_ACTION_MAP = { - Thermostat.Status.HEATING: HVACAction.HEATING, - Thermostat.Status.COOLING: HVACAction.COOLING, - Thermostat.Status.OFF: HVACAction.OFF, + Thermostat.Status.Heating: HVACAction.HEATING, + Thermostat.Status.Cooling: HVACAction.COOLING, + Thermostat.Status.Off: HVACAction.OFF, } VANTAGE_FAN_MODE_MAP = { - Thermostat.FanMode.AUTO: FAN_AUTO, - Thermostat.FanMode.ON: FAN_ON, + Thermostat.FanMode.Off: FAN_AUTO, + Thermostat.FanMode.On: FAN_ON, } @@ -175,9 +175,7 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: LOGGER.error("Invalid mode for async_set_hvac_mode: %s", hvac_mode) return - await self.async_request_call( - self.client.thermostats.set_operation_mode(self.obj.id, vantage_hvac_mode) - ) + await self.async_request_call(self.obj.set_operation_mode(vantage_hvac_mode)) async def async_set_fan_mode(self, fan_mode: str) -> None: """Set new target fan mode.""" @@ -190,9 +188,7 @@ async def async_set_fan_mode(self, fan_mode: str) -> None: LOGGER.error("Invalid mode for async_set_fan_mode: %s", fan_mode) return - await self.async_request_call( - self.client.thermostats.set_fan_mode(self.obj.id, vantage_fan_mode) - ) + await self.async_request_call(self.obj.set_fan_mode(vantage_fan_mode)) async def async_set_temperature(self, **kwargs: Any) -> None: """Set new target temperature.""" @@ -201,21 +197,12 @@ async def async_set_temperature(self, **kwargs: Any) -> None: temp = kwargs.get(ATTR_TEMPERATURE) if self.hvac_mode == HVACMode.HEAT_COOL and low_temp and high_temp: - await self.async_request_call( - self.client.thermostats.set_cool_set_point(self.obj.id, high_temp) - ) - - await self.async_request_call( - self.client.thermostats.set_heat_set_point(self.obj.id, low_temp) - ) + await self.async_request_call(self.obj.set_cool_set_point(high_temp)) + await self.async_request_call(self.obj.set_heat_set_point(low_temp)) elif self.hvac_mode == HVACMode.HEAT and temp: - await self.async_request_call( - self.client.thermostats.set_heat_set_point(self.obj.id, temp) - ) + await self.async_request_call(self.obj.set_heat_set_point(temp)) elif self.hvac_mode == HVACMode.COOL and temp: - await self.async_request_call( - self.client.thermostats.set_cool_set_point(self.obj.id, temp) - ) + await self.async_request_call(self.obj.set_cool_set_point(temp)) else: LOGGER.error("Invalid arguments for async_set_temperature in %s", kwargs) diff --git a/custom_components/vantage/cover.py b/custom_components/vantage/cover.py index 6188380..ab8aa69 100644 --- a/custom_components/vantage/cover.py +++ b/custom_components/vantage/cover.py @@ -4,7 +4,7 @@ from typing import Any from aiovantage import Vantage -from aiovantage.objects import Blind, BlindGroup +from aiovantage.controllers.blinds import BlindTypes from homeassistant.components.cover import ( CoverDeviceClass, @@ -31,10 +31,9 @@ async def async_setup_entry( # Set up all cover entities register_items(vantage.blinds, VantageCover) - register_items(vantage.blind_groups, VantageCoverGroup) -class VantageCover(VantageEntity[Blind], CoverEntity): +class VantageCover(VantageEntity[BlindTypes], CoverEntity): """Vantage blind cover entity.""" def __post_init__(self) -> None: @@ -67,67 +66,18 @@ def current_cover_position(self) -> int | None: async def async_open_cover(self, **kwargs: Any) -> None: """Open the cover.""" - await self.async_request_call(self.client.blinds.open(self.obj.id)) + await self.async_request_call(self.obj.open()) async def async_close_cover(self, **kwargs: Any) -> None: """Close cover.""" - await self.async_request_call(self.client.blinds.close(self.obj.id)) + await self.async_request_call(self.obj.close()) async def async_stop_cover(self, **kwargs: Any) -> None: """Stop the cover.""" - await self.async_request_call(self.client.blinds.stop(self.obj.id)) + await self.async_request_call(self.obj.stop()) async def async_set_cover_position(self, **kwargs: Any) -> None: """Move the cover to a specific position.""" if ATTR_POSITION in kwargs: position = kwargs[ATTR_POSITION] - await self.async_request_call( - self.client.blinds.set_position(self.obj.id, position) - ) - - -class VantageCoverGroup(VantageEntity[BlindGroup], CoverEntity): - """Vantage blind group cover entity.""" - - def __post_init__(self) -> None: - """Initialize a Vantage Cover Group.""" - self._attr_supported_features = ( - CoverEntityFeature.OPEN - | CoverEntityFeature.CLOSE - | CoverEntityFeature.STOP - | CoverEntityFeature.SET_POSITION - ) - - @property - def is_closed(self) -> bool | None: - """Return if the cover is closed or not.""" - if self.obj.position is None: - return None - return self.obj.position < 1 - - @property - def current_cover_position(self) -> int | None: - """Return the current position of cover.""" - if self.obj.position is None: - return None - return int(self.obj.position) - - async def async_open_cover(self, **kwargs: Any) -> None: - """Open the cover.""" - await self.async_request_call(self.client.blind_groups.open(self.obj.id)) - - async def async_close_cover(self, **kwargs: Any) -> None: - """Close cover.""" - await self.async_request_call(self.client.blind_groups.close(self.obj.id)) - - async def async_stop_cover(self, **kwargs: Any) -> None: - """Stop the cover.""" - await self.async_request_call(self.client.blind_groups.stop(self.obj.id)) - - async def async_set_cover_position(self, **kwargs: Any) -> None: - """Move the cover to a specific position.""" - if ATTR_POSITION in kwargs: - position = kwargs[ATTR_POSITION] - await self.async_request_call( - self.client.blind_groups.set_position(self.obj.id, position) - ) + await self.async_request_call(self.obj.set_position(position)) diff --git a/custom_components/vantage/device.py b/custom_components/vantage/device.py index 0988ca6..bb11dfb 100644 --- a/custom_components/vantage/device.py +++ b/custom_components/vantage/device.py @@ -124,7 +124,7 @@ def vantage_device_info(client: Vantage, obj: SystemObject) -> DeviceInfo: device_info["via_device"] = (DOMAIN, str(obj.master)) # Attach the firmware version for Master devices - if isinstance(obj, Master): - device_info["sw_version"] = obj.firmware_version + # if isinstance(obj, Master): + # device_info["sw_version"] = obj.firmware_version return device_info diff --git a/custom_components/vantage/entity.py b/custom_components/vantage/entity.py index 6e3a846..5d44d2b 100644 --- a/custom_components/vantage/entity.py +++ b/custom_components/vantage/entity.py @@ -144,7 +144,7 @@ async def async_added_to_hass(self) -> None: async def async_update(self) -> None: """Update the state of an entity manully, typically when polling.""" - await self.async_request_call(self.controller.fetch_object_state(self.obj.id)) + await self.async_request_call(self.obj.fetch_state()) @callback def _handle_event( diff --git a/custom_components/vantage/events.py b/custom_components/vantage/events.py index d425659..b3afcb6 100644 --- a/custom_components/vantage/events.py +++ b/custom_components/vantage/events.py @@ -40,7 +40,7 @@ def handle_button_event(_event: VantageEvent, obj: Button, data: Any) -> None: payload["station_name"] = station.name hass.bus.async_fire( - EVENT_BUTTON_PRESSED if obj.pressed else EVENT_BUTTON_RELEASED, + EVENT_BUTTON_PRESSED if obj.is_down else EVENT_BUTTON_RELEASED, payload, ) diff --git a/custom_components/vantage/light.py b/custom_components/vantage/light.py index bb5345f..91ece10 100644 --- a/custom_components/vantage/light.py +++ b/custom_components/vantage/light.py @@ -1,11 +1,11 @@ """Support for Vantage light entities.""" -from collections.abc import Callable import functools from typing import Any, TypeVar, cast from aiovantage import Vantage -from aiovantage.objects import Load, LoadGroup, RGBLoadBase +from aiovantage.objects import Load, LoadGroup +from aiovantage.controllers.rgb_loads import RGBLoadTypes from homeassistant.components.light import ( ATTR_BRIGHTNESS, @@ -45,7 +45,9 @@ async def async_setup_entry( ) # Set up all light-type objects - load_filter: Callable[[Load], bool] = lambda obj: obj.is_light + def load_filter(obj: Load) -> bool: + return obj.is_light + register_items(vantage.loads, VantageLight, load_filter) register_items(vantage.rgb_loads, VantageRGBLight) register_items(vantage.load_groups, VantageLightGroup) @@ -81,27 +83,23 @@ def brightness(self) -> int | None: if self.obj.level is None: return None - return value_to_brightness(LEVEL_RANGE, self.obj.level) + return value_to_brightness(LEVEL_RANGE, float(self.obj.level)) async def async_turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" transition = kwargs.get(ATTR_TRANSITION, 0) level = brightness_to_value(LEVEL_RANGE, kwargs.get(ATTR_BRIGHTNESS, 255)) - await self.async_request_call( - self.client.loads.turn_on(self.obj.id, transition, level) - ) + await self.async_request_call(self.obj.turn_on(transition, level)) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" transition = kwargs.get(ATTR_TRANSITION, 0) - await self.async_request_call( - self.client.loads.turn_off(self.obj.id, transition) - ) + await self.async_request_call(self.obj.turn_off(transition)) -class VantageRGBLight(VantageEntity[RGBLoadBase], LightEntity): +class VantageRGBLight(VantageEntity[RGBLoadTypes], LightEntity): """Vantage RGB load light entity.""" def __post_init__(self) -> None: @@ -110,18 +108,18 @@ def __post_init__(self) -> None: self._attr_supported_color_modes: set[str] = set() match self.obj.color_type: - case RGBLoadBase.ColorType.HSL: + case self.obj.ColorType.HSL: self._attr_supported_color_modes.add(ColorMode.HS) self._attr_color_mode = ColorMode.HS self._attr_supported_features |= LightEntityFeature.TRANSITION - case RGBLoadBase.ColorType.RGB: + case self.obj.ColorType.RGB: self._attr_supported_color_modes.add(ColorMode.RGB) self._attr_color_mode = ColorMode.RGB self._attr_supported_features |= LightEntityFeature.TRANSITION - case RGBLoadBase.ColorType.RGBW: + case self.obj.ColorType.RGBW: self._attr_supported_color_modes.add(ColorMode.RGBW) self._attr_color_mode = ColorMode.RGBW - case RGBLoadBase.ColorType.CCT: + case self.obj.ColorType.CCT: self._attr_supported_color_modes.add(ColorMode.COLOR_TEMP) self._attr_color_mode = ColorMode.COLOR_TEMP self._attr_min_color_temp_kelvin = self.obj.min_temp @@ -150,7 +148,7 @@ def brightness(self) -> int | None: if self.obj.level is None: return None - return value_to_brightness(LEVEL_RANGE, self.obj.level) + return value_to_brightness(LEVEL_RANGE, float(self.obj.level)) @property def hs_color(self) -> tuple[float, float] | None: @@ -185,9 +183,7 @@ async def async_turn_on(self, **kwargs: Any) -> None: if brightness := kwargs.get(ATTR_BRIGHTNESS) is not None: rgbw = scale_color_brightness(rgbw, brightness) - await self.async_request_call( - self.client.rgb_loads.set_rgbw(self.obj.id, *rgbw) - ) + await self.async_request_call(self.obj.set_rgbw(*rgbw)) elif ATTR_RGB_COLOR in kwargs: # Turn on the light with the provided RGB color @@ -198,9 +194,7 @@ async def async_turn_on(self, **kwargs: Any) -> None: if brightness := kwargs.get(ATTR_BRIGHTNESS) is not None: rgb = scale_color_brightness(rgb, brightness) - await self.async_request_call( - self.client.rgb_loads.dissolve_rgb(self.obj.id, *rgb, transition) - ) + await self.async_request_call(self.obj.dissolve_rgb(*rgb, transition)) elif ATTR_HS_COLOR in kwargs: # Turn on the light with the provided HS color and brightness, default to @@ -210,9 +204,7 @@ async def async_turn_on(self, **kwargs: Any) -> None: transition = kwargs.get(ATTR_TRANSITION, 0) await self.async_request_call( - self.client.rgb_loads.dissolve_hsl( - self.obj.id, hue, saturation, level, transition - ) + self.obj.dissolve_hsl(hue, saturation, level, transition) ) else: @@ -220,25 +212,19 @@ async def async_turn_on(self, **kwargs: Any) -> None: if ATTR_COLOR_TEMP_KELVIN in kwargs: color_temp: int = kwargs[ATTR_COLOR_TEMP_KELVIN] - await self.async_request_call( - self.client.rgb_loads.set_color_temp(self.obj.id, color_temp) - ) + await self.async_request_call(self.obj.set_color_temp(color_temp)) # Turn on the light with the provided brightness, default to 100% transition = kwargs.get(ATTR_TRANSITION, 0) level = brightness_to_value(LEVEL_RANGE, kwargs.get(ATTR_BRIGHTNESS, 255)) - await self.async_request_call( - self.client.rgb_loads.turn_on(self.obj.id, transition, level) - ) + await self.async_request_call(self.obj.turn_on(transition, level)) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" transition = kwargs.get(ATTR_TRANSITION, 0) - await self.async_request_call( - self.client.rgb_loads.turn_off(self.obj.id, transition) - ) + await self.async_request_call(self.obj.turn_off(transition)) class VantageLightGroup(VantageEntity[LoadGroup], LightEntity): @@ -273,24 +259,20 @@ def brightness(self) -> int | None: if self.obj.level is None: return None - return value_to_brightness(LEVEL_RANGE, self.obj.level) + return value_to_brightness(LEVEL_RANGE, float(self.obj.level)) async def async_turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" transition = kwargs.get(ATTR_TRANSITION, 0) level = brightness_to_value(LEVEL_RANGE, kwargs.get(ATTR_BRIGHTNESS, 255)) - await self.async_request_call( - self.client.load_groups.turn_on(self.obj.id, transition, level) - ) + await self.async_request_call(self.obj.turn_on(transition, level)) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" transition = kwargs.get(ATTR_TRANSITION, 0) - await self.async_request_call( - self.client.load_groups.turn_off(self.obj.id, transition) - ) + await self.async_request_call(self.obj.turn_off(transition)) def scale_color_brightness(color: ColorT, brightness: int | None) -> ColorT: diff --git a/custom_components/vantage/manifest.json b/custom_components/vantage/manifest.json index 7493be1..113620d 100644 --- a/custom_components/vantage/manifest.json +++ b/custom_components/vantage/manifest.json @@ -17,7 +17,7 @@ "custom_components.vantage" ], "requirements": [ - "aiovantage==0.17.2" + "aiovantage==0.18.0" ], "version": "0.13.5", "zeroconf": [ diff --git a/custom_components/vantage/number.py b/custom_components/vantage/number.py index 6b97128..631793b 100644 --- a/custom_components/vantage/number.py +++ b/custom_components/vantage/number.py @@ -1,7 +1,6 @@ """Support for Vantage number entities.""" import functools -from collections.abc import Callable from aiovantage import Vantage from aiovantage.objects import GMem @@ -26,7 +25,9 @@ async def async_setup_entry( ) # Register all number entities - gmem_filter: Callable[[GMem], bool] = lambda obj: obj.is_int or obj.is_fixed + def gmem_filter(obj: GMem) -> bool: + return obj.is_int or obj.is_fixed + register_items(vantage.gmem, VantageNumberVariable, gmem_filter) @@ -105,4 +106,4 @@ async def async_set_native_value(self, value: float) -> None: else: value = int(value) - await self.async_request_call(self.client.gmem.set_value(self.obj.id, value)) + await self.async_request_call(self.obj.set_value(value)) diff --git a/custom_components/vantage/services.py b/custom_components/vantage/services.py index e3989fc..0532767 100644 --- a/custom_components/vantage/services.py +++ b/custom_components/vantage/services.py @@ -34,7 +34,7 @@ async def start_task(call: ServiceCall) -> None: vantage: Vantage for vantage in hass.data[DOMAIN].values(): if task := _get_task(vantage, task_id_or_name): - await vantage.tasks.start(task.id) + await task.start() task_found = True if not task_found: @@ -50,7 +50,7 @@ async def stop_task(call: ServiceCall) -> None: vantage: Vantage for vantage in hass.data[DOMAIN].values(): if task := _get_task(vantage, task_id_or_name): - await vantage.tasks.stop(task.id) + await task.stop() task_found = True if not task_found: diff --git a/custom_components/vantage/switch.py b/custom_components/vantage/switch.py index c83eb08..cd9150d 100644 --- a/custom_components/vantage/switch.py +++ b/custom_components/vantage/switch.py @@ -1,6 +1,5 @@ """Support for Vantage switch entities.""" -from collections.abc import Callable import functools from typing import Any @@ -26,11 +25,15 @@ async def async_setup_entry( ) # Register Load switch entities - load_filter: Callable[[Load], bool] = lambda obj: obj.is_relay or obj.is_motor + def load_filter(obj: Load) -> bool: + return obj.is_relay or obj.is_motor + register_items(vantage.loads, VantageLoadSwitch, load_filter) # Register GMem switch entities - gmem_filter: Callable[[GMem], bool] = lambda obj: obj.is_bool + def gmem_filter(obj: GMem) -> bool: + return obj.is_bool + register_items(vantage.gmem, VantageVariableSwitch, gmem_filter) @@ -44,11 +47,11 @@ def is_on(self) -> bool | None: async def async_turn_on(self, **kwargs: Any) -> None: """Turn the switch on.""" - await self.async_request_call(self.client.loads.turn_on(self.obj.id)) + await self.async_request_call(self.obj.turn_on()) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the switch off.""" - await self.async_request_call(self.client.loads.turn_off(self.obj.id)) + await self.async_request_call(self.obj.turn_off()) class VantageVariableSwitch(VantageVariableEntity, SwitchEntity): @@ -57,15 +60,15 @@ class VantageVariableSwitch(VantageVariableEntity, SwitchEntity): @property def is_on(self) -> bool | None: """Return True if entity is on.""" - if isinstance(self.obj.value, bool): - return self.obj.value + if isinstance(self.obj.value, int): + return bool(self.obj.value) return None async def async_turn_on(self, **kwargs: Any) -> None: """Turn the switch on.""" - await self.async_request_call(self.client.gmem.set_value(self.obj.id, True)) + await self.async_request_call(self.obj.set_value(True)) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the switch off.""" - await self.async_request_call(self.client.gmem.set_value(self.obj.id, False)) + await self.async_request_call(self.obj.set_value(False)) diff --git a/custom_components/vantage/text.py b/custom_components/vantage/text.py index d44a93e..9275d27 100644 --- a/custom_components/vantage/text.py +++ b/custom_components/vantage/text.py @@ -1,6 +1,5 @@ """Support for Vantage text entities.""" -from collections.abc import Callable import functools from aiovantage import Vantage @@ -27,7 +26,9 @@ async def async_setup_entry( ) # Register all text entities - gmem_filter: Callable[[GMem], bool] = lambda obj: obj.is_str + def gmem_filter(obj: GMem) -> bool: + return obj.is_str + register_items(vantage.gmem, VantageTextVariable, gmem_filter) @@ -44,4 +45,4 @@ def native_value(self) -> str | None: async def async_set_value(self, value: str) -> None: """Change the value.""" - await self.async_request_call(self.client.gmem.set_value(self.obj.id, value)) + await self.async_request_call(self.obj.set_value(value)) diff --git a/pyproject.toml b/pyproject.toml index b55bba6..9ea4271 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ requires-python = ">=3.12" authors = [{ name = "James Smith", email = "james@loopj.com" }] classifiers = ["Private :: Do Not Upload"] dependencies = [ - "aiovantage==0.17.2", + "aiovantage==0.18.0", "homeassistant==2024.12.3", "colorlog==6.9.0", ]