Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Zigbee Lights #60

Merged
merged 1 commit into from
Sep 23, 2024
Merged
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
30 changes: 30 additions & 0 deletions homepilot/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
APICAP_STOP_SLAT_CMD,
APICAP_VENTIL_POS_CFG,
APICAP_VENTIL_POS_MODE_CFG,
APICAP_RGB_CFG,
APICAP_COLOR_TEMP_CFG,
APICAP_COLOR_MODE_CFG,
)


Expand Down Expand Up @@ -385,6 +388,33 @@ async def async_set_temperature_thresh_cfg(self, did, thresh_number, temperature
) as response:
return await response.json()

async def async_set_rgb(self, did, rgb_value):
await self.authenticate()
async with aiohttp.ClientSession(cookie_jar=self.cookie_jar) as session:
async with session.put(
f"http://{self._host}{self._base_path}/devices/{did}",
json={"name": APICAP_RGB_CFG, "value": rgb_value},
) as response:
return await response.json()

async def async_set_color_temp(self, did, color_temp_value):
await self.authenticate()
async with aiohttp.ClientSession(cookie_jar=self.cookie_jar) as session:
async with session.put(
f"http://{self._host}{self._base_path}/devices/{did}",
json={"name": APICAP_COLOR_TEMP_CFG, "value": color_temp_value},
) as response:
return await response.json()

async def async_set_color_temp(self, did, color_mode_value):
await self.authenticate()
async with aiohttp.ClientSession(cookie_jar=self.cookie_jar) as session:
async with session.put(
f"http://{self._host}{self._base_path}/devices/{did}",
json={"name": APICAP_COLOR_MODE_CFG, "value": color_mode_value},
) as response:
return await response.json()

async def async_turn_led_on(self):
await self.authenticate()
async with aiohttp.ClientSession(cookie_jar=self.cookie_jar) as session:
Expand Down
4 changes: 4 additions & 0 deletions homepilot/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
APICAP_TEMPERATURE_THRESH_2_CFG = "TEMPERATURE_THRESH_2_CFG"
APICAP_TEMPERATURE_THRESH_3_CFG = "TEMPERATURE_THRESH_3_CFG"
APICAP_TEMPERATURE_THRESH_4_CFG = "TEMPERATURE_THRESH_4_CFG"
# Light
APICAP_RGB_CFG = "RGB_CFG"
APICAP_COLOR_TEMP_CFG = "COLOR_TEMP_CFG"
APICAP_COLOR_MODE_CFG = "COLOR_MODE_CFG"

SUPPORTED_DEVICES = {
"35001164": {"name": "DuoFern Switch actuator",
Expand Down
192 changes: 192 additions & 0 deletions homepilot/light.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import asyncio
from .const import (
APICAP_DEVICE_TYPE_LOC,
APICAP_ID_DEVICE_LOC,
APICAP_NAME_DEVICE_LOC,
APICAP_PING_CMD,
APICAP_PROD_CODE_DEVICE_LOC,
APICAP_PROT_ID_DEVICE_LOC,
APICAP_VERSION_CFG,
APICAP_RGB_CFG,
APICAP_COLOR_TEMP_CFG,
APICAP_COLOR_MODE_CFG,
SUPPORTED_DEVICES,
)
from .api import HomePilotApi
from .device import HomePilotDevice

class HomePilotLight(HomePilotDevice):
_is_on: bool
_brightness: int
_has_rgb: bool
_r_value: int
_g_value: int
_b_value: int
_has_color_temp: bool
_color_temp_value: int
_has_color_mode: int
_color_mode: str

def __init__(
self,
api: HomePilotApi,
did: int,
uid: str,
name: str,
device_number: str,
model: str,
fw_version: str,
device_group: int,
has_ping_cmd: bool = False,
has_rgb: bool = False,
has_color_temp: bool = False,
has_color_mode: bool = False,
) -> None:
super().__init__(
api=api,
did=did,
uid=uid,
name=name,
device_number=device_number,
model=model,
fw_version=fw_version,
device_group=device_group,
has_ping_cmd=has_ping_cmd,
)
self._has_rgb = has_rgb
self._has_color_temp = has_color_temp
self._has_color_mode = has_color_mode


@staticmethod
def build_from_api(api: HomePilotApi, did: str):
return asyncio.run(HomePilotLight.async_build_from_api(api, did))

@staticmethod
async def async_build_from_api(api: HomePilotApi, did):
"""Build a new HomePilotDevice from the response of API"""
device = await api.get_device(did)
device_map = HomePilotDevice.get_capabilities_map(device)
return HomePilotLight(
api=api,
did=device_map[APICAP_ID_DEVICE_LOC]["value"],
uid=device_map[APICAP_PROT_ID_DEVICE_LOC]["value"],
name=device_map[APICAP_NAME_DEVICE_LOC]["value"],
device_number=device_map[APICAP_PROD_CODE_DEVICE_LOC]["value"],
model=SUPPORTED_DEVICES[device_map[APICAP_PROD_CODE_DEVICE_LOC]["value"]][
"name"
]
if device_map[APICAP_PROD_CODE_DEVICE_LOC]["value"] in SUPPORTED_DEVICES
else "Generic Device",
fw_version=device_map[APICAP_VERSION_CFG]["value"] if APICAP_VERSION_CFG in device_map else ""
if APICAP_VERSION_CFG in device_map else "",
device_group=device_map[APICAP_DEVICE_TYPE_LOC]["value"],
has_ping_cmd=APICAP_PING_CMD in device_map,
has_rgb=APICAP_RGB_CFG in device_map,
has_color_temp=APICAP_COLOR_TEMP_CFG in device_map,
has_color_mode=APICAP_COLOR_MODE_CFG in device_map,
)

async def update_state(self, state, api):
await super().update_state(state, api)
self.is_on = state["statusesMap"]["Position"] != 0
self.brightness = state["statusesMap"]["Position"]
if self.has_rgb:
self.r_value: int = int(["statusesMap"]["rgb"][2:4], 16)
self.g_value: int = int(["statusesMap"]["rgb"][4:6], 16)
self.b_value: int = int(["statusesMap"]["rgb"][6:8], 16)
self.color_temp_value = state["statusesMap"]["colortemperature"] if self.has_color_temp else 0
self.color_mode_value = state["statusesMap"]["colormode"] if self.has_color_mode else 0

@property
def is_on(self) -> bool:
return self._is_on

@is_on.setter
def is_on(self, is_on):
self._is_on = is_on

@property
def brightness(self) -> int:
return self._brightness

@brightness.setter
def brightness(self, brightness):
self._brightness = brightness

@property
def has_rgb(self) -> int:
return self._has_rgb

@property
def has_color_temp(self) -> int:
return self._has_color_temp

@property
def has_color_mode(self) -> int:
return self._has_color_mode

@property
def r_value(self) -> int:
return self._r_value

@r_value.setter
def r_value(self, r_value):
self._r_value = r_value

@property
def g_value(self) -> int:
return self._g_value

@g_value.setter
def g_value(self, g_value):
self._g_value = g_value

@property
def b_value(self) -> int:
return self._b_value

@b_value.setter
def b_value(self, b_value):
self._b_value = b_value

@property
def color_temp_value(self) -> int:
return self._color_temp_value

@color_temp_value.setter
def color_temp_value(self, color_temp_value):
self._color_temp_value = color_temp_value

@property
def color_mode_value(self) -> int:
return self._color_mode_value

@color_mode_value.setter
def color_mode_value(self, color_mode_value):
self.color_mode_value = color_mode_value

async def async_turn_on(self) -> None:
await self.api.async_turn_on(self.did)

async def async_turn_off(self) -> None:
await self.api.async_turn_off(self.did)

async def async_set_brightness(self, new_brightness) -> None:
await self.api.async_set_cover_position(self.did, new_brightness)

async def async_set_rgb(self, r, g, b) -> None:
new_rgb: str = "0x%0.6X" % (r * (2,16) + g * pow(2,8) + b)
await self.api.async_set_rgb(self.did, new_rgb)

async def async_set_color_temp(self, new_color_temp) -> None:
await self.api.async_set_color_temp(self.did, new_color_temp)

async def async_set_color_mode(self, new_color_mode) -> None:
await self.api.async_set_color_mode(self.did, new_color_mode)

async def async_toggle(self) -> None:
if self.is_on:
await self.async_turn_off()
else:
await self.async_turn_on()
11 changes: 10 additions & 1 deletion homepilot/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .api import HomePilotApi, AuthError
from .wallcontroller import HomePilotWallController
from .scenes import HomePilotScene
from .light import HomePilotLight

from .device import HomePilotDevice

Expand All @@ -35,7 +36,7 @@ async def async_build_manager(api: HomePilotApi):
manager.devices = {
id_type["did"]: await HomePilotManager.async_build_device(manager.api, id_type)
for id_type in await manager.get_device_ids_types()
if id_type["type"] in ["-1", "1", "2", "3", "4", "5", "8", "10"]
if id_type["type"] in ["-1", "1", "2", "3", "4", "5", "8", "10", "73", "74", "75", "76"]
}
try:
manager.scenes = {
Expand Down Expand Up @@ -65,6 +66,14 @@ async def async_build_device(api, id_type):
return await HomePilotCover.async_build_from_api(api, id_type["did"])
if id_type["type"] == "10":
return await HomePilotWallController.async_build_from_api(api, id_type["did"])
if id_type["type"] == "73":
return await HomePilotLight.async_build_from_api(api, id_type["did"])
if id_type["type"] == "74":
return await HomePilotLight.async_build_from_api(api, id_type["did"])
if id_type["type"] == "75":
return await HomePilotLight.async_build_from_api(api, id_type["did"])
if id_type["type"] == "76":
return await HomePilotLight.async_build_from_api(api, id_type["did"])
return None

async def get_hub_macaddress(self):
Expand Down
Loading