Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions custom_components/vesync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
_LOGGER.error("Unable to login to the VeSync server")
return False

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

Expand Down Expand Up @@ -88,34 +86,48 @@ async def async_update_data():

device_dict = await async_process_devices(hass, manager)

platforms_to_setup = []
for p, vs_p in PLATFORMS.items():
hass.data[DOMAIN][config_entry.entry_id][vs_p] = []
if device_dict[vs_p]:
hass.data[DOMAIN][config_entry.entry_id][vs_p].extend(device_dict[vs_p])
hass.async_create_task(forward_setup(config_entry, p))
platforms_to_setup.append(p)

if platforms_to_setup:
await hass.config_entries.async_forward_entry_setups(
config_entry, platforms_to_setup
)

async def async_new_device_discovery(service: ServiceCall) -> None:
"""Discover if new devices should be added."""
manager = hass.data[DOMAIN][config_entry.entry_id][VS_MANAGER]
dev_dict = await async_process_devices(hass, manager)

def _add_new_devices(platform: str) -> None:
new_platforms: list[Platform] = []

def _add_new_devices(platform: Platform) -> None:
"""Add new devices to hass."""
old_devices = hass.data[DOMAIN][config_entry.entry_id][PLATFORMS[platform]]
if new_devices := list(
set(dev_dict.get(VS_SWITCHES, [])).difference(old_devices)
):
had_devices = bool(old_devices)
old_devices.extend(new_devices)
if old_devices:
if had_devices:
async_dispatcher_send(
hass, VS_DISCOVERY.format(PLATFORMS[platform]), new_devices
)
else:
hass.async_create_task(forward_setup(config_entry, platform))
new_platforms.append(platform)

for k in PLATFORMS:
_add_new_devices(k)

if new_platforms:
await hass.config_entries.async_forward_entry_setups(
config_entry, new_platforms
)

hass.services.async_register(
DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery
)
Expand Down
78 changes: 41 additions & 37 deletions custom_components/vesync/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_TEMP,
COLOR_MODE_BRIGHTNESS,
COLOR_MODE_COLOR_TEMP,
ATTR_COLOR_TEMP_KELVIN,
ColorMode,
LightEntity,
)

MIN_COLOR_TEMP_KELVIN = 2700
MAX_COLOR_TEMP_KELVIN = 6500
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
Expand Down Expand Up @@ -102,18 +104,23 @@ def turn_on(self, **kwargs):
"""Turn the device on."""
attribute_adjustment_only = False
# set white temperature
if self.color_mode in (COLOR_MODE_COLOR_TEMP,) and ATTR_COLOR_TEMP in kwargs:
# get white temperature from HA data
color_temp = int(kwargs[ATTR_COLOR_TEMP])
# ensure value between min-max supported Mireds
color_temp = max(self.min_mireds, min(color_temp, self.max_mireds))
# convert Mireds to Percent value that api expects
if (
self.color_mode == ColorMode.COLOR_TEMP
and ATTR_COLOR_TEMP_KELVIN in kwargs
):
# get white temperature from HA data (in Kelvin)
kelvin = int(kwargs[ATTR_COLOR_TEMP_KELVIN])
# ensure value within supported Kelvin range
kelvin = max(
self.min_color_temp_kelvin, min(kelvin, self.max_color_temp_kelvin)
)
# convert Kelvin to percent value that api expects
# (pyvesync scale: 0 = warmest, 100 = coldest — matches Kelvin direction)
color_temp = round(
((color_temp - self.min_mireds) / (self.max_mireds - self.min_mireds))
(kelvin - self.min_color_temp_kelvin)
/ (self.max_color_temp_kelvin - self.min_color_temp_kelvin)
* 100
)
# flip cold/warm to what pyvesync api expects
color_temp = 100 - color_temp
# ensure value between 0-100
color_temp = max(0, min(color_temp, 100))
# call pyvesync library api method to set color_temp
Expand All @@ -122,7 +129,7 @@ def turn_on(self, **kwargs):
attribute_adjustment_only = True
# set brightness level
if (
self.color_mode in (COLOR_MODE_BRIGHTNESS, COLOR_MODE_COLOR_TEMP)
self.color_mode in (ColorMode.BRIGHTNESS, ColorMode.COLOR_TEMP)
and ATTR_BRIGHTNESS in kwargs
):
# get brightness from HA data
Expand All @@ -147,12 +154,12 @@ def __init__(self, device, coordinator) -> None:
@property
def color_mode(self):
"""Set color mode for this entity."""
return COLOR_MODE_BRIGHTNESS
return ColorMode.BRIGHTNESS

@property
def supported_color_modes(self):
"""Flag supported color_modes (in an array format)."""
return [COLOR_MODE_BRIGHTNESS]
return {ColorMode.BRIGHTNESS}


class VeSyncTunableWhiteLightHA(VeSyncBaseLight, LightEntity):
Expand All @@ -163,51 +170,48 @@ def __init__(self, device, coordinator) -> None:
super().__init__(device, coordinator)

@property
def color_temp(self):
"""Get device white temperature."""
# get value from pyvesync library api,
def color_temp_kelvin(self):
"""Get device white temperature in Kelvin."""
result = self.device.color_temp_pct
try:
# check for validity of brightness value received
color_temp_value = int(result)
except ValueError:
# deal if any unexpected/non numeric value
_LOGGER.debug(
"VeSync - received unexpected 'color_temp_pct' value from pyvesync api: %s",
result,
)
return 0
# flip cold/warm
color_temp_value = 100 - color_temp_value
return None
# ensure value between 0-100
color_temp_value = max(0, min(color_temp_value, 100))
# convert percent value to Mireds
color_temp_value = round(
self.min_mireds
+ ((self.max_mireds - self.min_mireds) / 100 * color_temp_value)
# convert percent value to Kelvin
# (pyvesync scale: 0 = warmest, 100 = coldest — matches Kelvin direction)
kelvin = round(
self.min_color_temp_kelvin
+ (self.max_color_temp_kelvin - self.min_color_temp_kelvin)
* color_temp_value
/ 100
)
# ensure value between minimum and maximum Mireds
return max(self.min_mireds, min(color_temp_value, self.max_mireds))
return max(self.min_color_temp_kelvin, min(kelvin, self.max_color_temp_kelvin))

@property
def min_mireds(self):
"""Set device coldest white temperature."""
return 154 # 154 Mireds ( 1,000,000 divided by 6500 Kelvin = 154 Mireds)
def min_color_temp_kelvin(self):
"""Set device warmest white temperature."""
return MIN_COLOR_TEMP_KELVIN

@property
def max_mireds(self):
"""Set device warmest white temperature."""
return 370 # 370 Mireds ( 1,000,000 divided by 2700 Kelvin = 370 Mireds)
def max_color_temp_kelvin(self):
"""Set device coldest white temperature."""
return MAX_COLOR_TEMP_KELVIN

@property
def color_mode(self):
"""Set color mode for this entity."""
return COLOR_MODE_COLOR_TEMP
return ColorMode.COLOR_TEMP

@property
def supported_color_modes(self):
"""Flag supported color_modes (in an array format)."""
return [COLOR_MODE_COLOR_TEMP]
return {ColorMode.COLOR_TEMP}


class VeSyncNightLightHA(VeSyncDimmableLightHA):
Expand Down
Loading