Velbus code cleanup (#97584)

* Some cleanup and code improvements for the velbus integration

* Comments

* More comments

* Update homeassistant/components/velbus/entity.py

Co-authored-by: G Johansson <goran.johansson@shiftit.se>

* More comments

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
Maikel Punie 2023-08-06 19:12:19 +02:00 committed by GitHub
parent 6bc5b8989d
commit 0535578440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 52 additions and 18 deletions

View File

@ -18,10 +18,9 @@ async def async_setup_entry(
"""Set up Velbus switch based on config_entry."""
await hass.data[DOMAIN][entry.entry_id]["tsk"]
cntrl = hass.data[DOMAIN][entry.entry_id]["cntrl"]
entities = []
for channel in cntrl.get_all("binary_sensor"):
entities.append(VelbusBinarySensor(channel))
async_add_entities(entities)
async_add_entities(
VelbusBinarySensor(channel) for channel in cntrl.get_all("binary_sensor")
)
class VelbusBinarySensor(VelbusEntity, BinarySensorEntity):

View File

@ -13,7 +13,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -24,10 +24,7 @@ async def async_setup_entry(
"""Set up Velbus switch based on config_entry."""
await hass.data[DOMAIN][entry.entry_id]["tsk"]
cntrl = hass.data[DOMAIN][entry.entry_id]["cntrl"]
entities = []
for channel in cntrl.get_all("button"):
entities.append(VelbusButton(channel))
async_add_entities(entities)
async_add_entities(VelbusButton(channel) for channel in cntrl.get_all("button"))
class VelbusButton(VelbusEntity, ButtonEntity):
@ -37,6 +34,7 @@ class VelbusButton(VelbusEntity, ButtonEntity):
_attr_entity_registry_enabled_default = False
_attr_entity_category = EntityCategory.CONFIG
@api_call
async def async_press(self) -> None:
"""Handle the button press."""
await self._channel.press()

View File

@ -16,7 +16,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN, PRESET_MODES
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -27,10 +27,7 @@ async def async_setup_entry(
"""Set up Velbus switch based on config_entry."""
await hass.data[DOMAIN][entry.entry_id]["tsk"]
cntrl = hass.data[DOMAIN][entry.entry_id]["cntrl"]
entities = []
for channel in cntrl.get_all("climate"):
entities.append(VelbusClimate(channel))
async_add_entities(entities)
async_add_entities(VelbusClimate(channel) for channel in cntrl.get_all("climate"))
class VelbusClimate(VelbusEntity, ClimateEntity):
@ -67,6 +64,7 @@ class VelbusClimate(VelbusEntity, ClimateEntity):
"""Return the current temperature."""
return self._channel.get_state()
@api_call
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperatures."""
if (temp := kwargs.get(ATTR_TEMPERATURE)) is None:
@ -74,6 +72,7 @@ class VelbusClimate(VelbusEntity, ClimateEntity):
await self._channel.set_temp(temp)
self.async_write_ha_state()
@api_call
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the new preset mode."""
await self._channel.set_preset(PRESET_MODES[preset_mode])

View File

@ -15,7 +15,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -81,18 +81,22 @@ class VelbusCover(VelbusEntity, CoverEntity):
return 100 - pos
return None
@api_call
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
await self._channel.open()
@api_call
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the cover."""
await self._channel.close()
@api_call
async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop the cover."""
await self._channel.stop()
@api_call
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
await self._channel.set_position(100 - kwargs[ATTR_POSITION])

View File

@ -1,8 +1,13 @@
"""Support for Velbus devices."""
from __future__ import annotations
from collections.abc import Awaitable, Callable, Coroutine
from functools import wraps
from typing import Any, Concatenate, ParamSpec, TypeVar
from velbusaio.channels import Channel as VelbusChannel
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import DOMAIN
@ -35,3 +40,25 @@ class VelbusEntity(Entity):
async def _on_update(self) -> None:
self.async_write_ha_state()
_T = TypeVar("_T", bound="VelbusEntity")
_P = ParamSpec("_P")
def api_call(
func: Callable[Concatenate[_T, _P], Awaitable[None]]
) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, None]]:
"""Catch command exceptions."""
@wraps(func)
async def cmd_wrapper(self: _T, *args: _P.args, **kwargs: _P.kwargs) -> None:
"""Wrap all command methods."""
try:
await func(self, *args, **kwargs)
except OSError as exc:
raise HomeAssistantError(
f"Could not execute {func.__name__} service for {self.name}"
) from exc
return cmd_wrapper

View File

@ -26,7 +26,7 @@ from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -63,6 +63,7 @@ class VelbusLight(VelbusEntity, LightEntity):
"""Return the brightness of the light."""
return int((self._channel.get_dimmer_state() * 255) / 100)
@api_call
async def async_turn_on(self, **kwargs: Any) -> None:
"""Instruct the Velbus light to turn on."""
if ATTR_BRIGHTNESS in kwargs:
@ -83,6 +84,7 @@ class VelbusLight(VelbusEntity, LightEntity):
)
await getattr(self._channel, attr)(*args)
@api_call
async def async_turn_off(self, **kwargs: Any) -> None:
"""Instruct the velbus light to turn off."""
attr, *args = (
@ -113,6 +115,7 @@ class VelbusButtonLight(VelbusEntity, LightEntity):
"""Return true if the light is on."""
return self._channel.is_on()
@api_call
async def async_turn_on(self, **kwargs: Any) -> None:
"""Instruct the Velbus light to turn on."""
if ATTR_FLASH in kwargs:
@ -126,6 +129,7 @@ class VelbusButtonLight(VelbusEntity, LightEntity):
attr, *args = "set_led_state", "on"
await getattr(self._channel, attr)(*args)
@api_call
async def async_turn_off(self, **kwargs: Any) -> None:
"""Instruct the velbus light to turn off."""
attr, *args = "set_led_state", "off"

View File

@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -37,6 +37,7 @@ class VelbusSelect(VelbusEntity, SelectEntity):
self._attr_options = self._channel.get_options()
self._attr_unique_id = f"{self._attr_unique_id}-program_select"
@api_call
async def async_select_option(self, option: str) -> None:
"""Update the program on the module."""
await self._channel.set_selected_program(option)

View File

@ -9,7 +9,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import VelbusEntity
from .entity import VelbusEntity, api_call
async def async_setup_entry(
@ -36,10 +36,12 @@ class VelbusSwitch(VelbusEntity, SwitchEntity):
"""Return true if the switch is on."""
return self._channel.is_on()
@api_call
async def async_turn_on(self, **kwargs: Any) -> None:
"""Instruct the switch to turn on."""
await self._channel.turn_on()
@api_call
async def async_turn_off(self, **kwargs: Any) -> None:
"""Instruct the switch to turn off."""
await self._channel.turn_off()