Skip to content

Commit

Permalink
fix: effect brightness (#469)
Browse files Browse the repository at this point in the history
* improved coordinator creation handling

* support for brightness light effects
  • Loading branch information
petretiandrea authored Aug 8, 2023
1 parent 610a0f5 commit a79c708
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 27 deletions.
39 changes: 25 additions & 14 deletions custom_components/tapo/coordinators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from plugp100.api.light_device import LightDevice
from plugp100.api.plug_device import EnergyInfo, PlugDevice, PowerInfo
from plugp100.api.tapo_client import TapoClient
from plugp100.common.functional.either import Either
from plugp100.common.functional.either import Either, Right, Left
from plugp100.responses.device_state import (
DeviceInfo,
LedStripDeviceState,
Expand All @@ -30,6 +30,7 @@
SUPPORTED_DEVICE_AS_LIGHT,
SUPPORTED_DEVICE_AS_SWITCH,
)
from custom_components.tapo.errors import DeviceNotSupported
from custom_components.tapo.helpers import get_short_model, value_or_raise

_LOGGER = logging.getLogger(__name__)
Expand All @@ -47,25 +48,35 @@ class HassTapoDeviceData:

async def create_coordinator(
hass: HomeAssistant, client: TapoClient, host: str, polling_interval: timedelta
) -> Optional["TapoCoordinator"]:
) -> Either["TapoCoordinator", Exception]:
logged_in = await client.login(host)
_LOGGER.info("Login to %s, success: %s", str(host), str(logged_in))
model = (
model_or_error = (
(await client.get_device_info())
.map(lambda x: DeviceInfo(**x))
.fold(lambda info: get_short_model(info.model), lambda _: None)
.map(lambda info: get_short_model(info.model))
)
_LOGGER.info("Detected model of %s: %s", str(host), str(model))
_LOGGER.info("Detected model of %s: %s", str(host), str(model_or_error))

if isinstance(model_or_error, Right):
if model_or_error.value in SUPPORTED_DEVICE_AS_SWITCH:
return Right(
PlugTapoCoordinator(hass, PlugDevice(client, host), polling_interval)
)
elif model_or_error.value in SUPPORTED_DEVICE_AS_LED_STRIP:
return Right(
LightTapoCoordinator(
hass, LedStripDevice(client, host), polling_interval
)
)
elif model_or_error.value in SUPPORTED_DEVICE_AS_LIGHT:
return Right(
LightTapoCoordinator(hass, LightDevice(client, host), polling_interval)
)
else:
return Left(DeviceNotSupported(f"Device {host} not supported!"))

if model in SUPPORTED_DEVICE_AS_SWITCH:
return PlugTapoCoordinator(hass, PlugDevice(client, host), polling_interval)
elif model in SUPPORTED_DEVICE_AS_LED_STRIP:
return LightTapoCoordinator(
hass, LedStripDevice(client, host), polling_interval
)
elif model in SUPPORTED_DEVICE_AS_LIGHT:
return LightTapoCoordinator(hass, LightDevice(client, host), polling_interval)
return None
return model_or_error


@dataclass
Expand Down
20 changes: 15 additions & 5 deletions custom_components/tapo/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __init__(
supported_effects: list[LightEffectPreset] = None,
):
super().__init__(coordinator)
self._effects = {effect.name: effect for effect in supported_effects}
self._effects = {effect.name.lower(): effect for effect in supported_effects}
# set homeassistant light entity attributes
self._attr_max_color_temp_kelvin = 6500
self._attr_min_color_temp_kelvin = 2500
Expand All @@ -96,7 +96,10 @@ def is_on(self):

@property
def brightness(self):
return round((self.coordinator.data.brightness * 255) / 100)
if self._effects and self.coordinator.data.lighting_effect is not None:
return round((self.coordinator.data.lighting_effect.brightness * 255) / 100)
else:
return round((self.coordinator.data.brightness * 255) / 100)

@property
def hs_color(self):
Expand Down Expand Up @@ -183,8 +186,16 @@ async def async_turn_off(self, **kwargs):
async def _change_brightness(self, new_brightness):
brightness_to_set = round((new_brightness / 255) * 100)
_LOGGER.debug("Change brightness to: %s", str(brightness_to_set))

value_or_raise(await self.coordinator.device.set_brightness(brightness_to_set))
if self.effect is not None:
value_or_raise(
await self.coordinator.device.set_light_effect_brightness(
self._effects[self.effect].to_effect(), brightness_to_set
)
)
else:
value_or_raise(
await self.coordinator.device.set_brightness(brightness_to_set)
)

async def _change_color_temp(self, color_temp):
_LOGGER.debug("Change color temp to: %s", str(color_temp))
Expand All @@ -201,7 +212,6 @@ async def _change_color_temp(self, color_temp):

async def _change_color(self, hue, saturation):
_LOGGER.debug("Change colors to: (%s, %s)", str(hue), str(saturation))

value_or_raise(
await self.coordinator.device.set_hue_saturation(hue, saturation)
)
2 changes: 1 addition & 1 deletion custom_components/tapo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"documentation": "https://github.com/petretiandrea/home-assistant-tapo-p100",
"issue_tracker": "https://github.com/petretiandrea/home-assistant-tapo-p100/issues",
"requirements": [
"plugp100==3.4.0"
"plugp100==3.5.0"
],
"dependencies": [],
"integration_type": "hub",
Expand Down
13 changes: 7 additions & 6 deletions custom_components/tapo/tapo_device.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from dataclasses import dataclass
from datetime import timedelta
from typing import cast

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_SCAN_INTERVAL
from homeassistant.core import HomeAssistant
from plugp100.api.tapo_client import TapoClient
from plugp100.common.functional.either import Right, Left

from custom_components.tapo.const import (
CONF_HOST,
Expand All @@ -13,7 +15,6 @@
PLATFORMS,
)
from custom_components.tapo.coordinators import HassTapoDeviceData, create_coordinator
from custom_components.tapo.errors import DeviceNotSupported


@dataclass
Expand All @@ -27,18 +28,18 @@ async def initialize_device(self, hass: HomeAssistant) -> bool:
)
host = self.entry.data.get(CONF_HOST)
coordinator = await create_coordinator(hass, self.client, host, polling_rate)
if coordinator is None:
raise DeviceNotSupported(f"Device {host} not supported!")
else:
await coordinator.async_config_entry_first_refresh() # could raise ConfigEntryNotReady
if isinstance(coordinator, Right):
await coordinator.value.async_config_entry_first_refresh() # could raise ConfigEntryNotReady
hass.data[DOMAIN][self.entry.entry_id] = HassTapoDeviceData(
coordinator=coordinator,
coordinator=coordinator.value,
config_entry_update_unsub=self.entry.add_update_listener(
_on_options_update_listener
),
)
await hass.config_entries.async_forward_entry_setups(self.entry, PLATFORMS)
return True
else:
raise cast(Left, coordinator).error


async def _on_options_update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
homeassistant==2022.12.8
plugp100==3.4.0
plugp100==3.5.0

0 comments on commit a79c708

Please sign in to comment.