Skip to content

Add necessary support for Adaptive Lightning #428

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

Merged
merged 2 commits into from
Dec 4, 2022
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ pip-selfcheck.json

# HAP-python-generated files
accessory.pickle
accessory.state
/*.state
93 changes: 93 additions & 0 deletions adaptive_lightbulb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""This virtual lightbulb implements the bare minimum needed for HomeKit
controller to recognize it as having AdaptiveLightning
"""
import logging
import signal
import random
import tlv8
import base64

from pyhap.accessory import Accessory
from pyhap.accessory_driver import AccessoryDriver
from pyhap.const import (CATEGORY_LIGHTBULB,
HAP_REPR_IID)
from pyhap.loader import get_loader

# Define tlv8 Keys and Values
SUPPORTED_TRANSITION_CONFIGURATION = 1
CHARACTERISTIC_IID = 1
TRANSITION_TYPE = 2

BRIGHTNESS = 1
COLOR_TEMPERATURE = 2

logging.basicConfig(level=logging.DEBUG, format="[%(module)s] %(message)s")

def bytes_to_base64_string(value: bytes) -> str:
return base64.b64encode(value).decode('ASCII')

class LightBulb(Accessory):
"""Fake lightbulb, logs what the client sets."""

category = CATEGORY_LIGHTBULB

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

serv_light = self.add_preload_service('Lightbulb', [
# The names here refer to the Characteristic name defined
# in characteristic.json
"Brightness",
"ColorTemperature",
"ActiveTransitionCount",
"TransitionControl",
"SupportedTransitionConfiguration"])

self.char_on = serv_light.configure_char(
'On', setter_callback=self.set_on)
self.char_br = serv_light.configure_char(
'Brightness', setter_callback=self.set_brightness)
self.char_ct = serv_light.configure_char(
'ColorTemperature', setter_callback=self.set_ct, value=140)

# Via this structure we advertise to the controller that we are
# capable of autonomous transitions between states on brightness
# and color temperature.
supported_transitions = [tlv8.Entry(SUPPORTED_TRANSITION_CONFIGURATION, [
tlv8.Entry(CHARACTERISTIC_IID, self.char_br.to_HAP()[HAP_REPR_IID]),
tlv8.Entry(TRANSITION_TYPE, BRIGHTNESS),
tlv8.Entry(CHARACTERISTIC_IID, self.char_ct.to_HAP()[HAP_REPR_IID]),
tlv8.Entry(TRANSITION_TYPE, COLOR_TEMPERATURE)
])]

bytes_data = tlv8.encode(supported_transitions)
b64str = bytes_to_base64_string(bytes_data)

self.char_atc = serv_light.configure_char(
'ActiveTransitionCount', setter_callback=self.set_atc)
self.char_tc = serv_light.configure_char(
'TransitionControl', setter_callback=self.set_tc)
self.char_stc = serv_light.configure_char(
'SupportedTransitionConfiguration',
value=b64str)

def set_on(self, value):
logging.info("Write On State: %s", value)

def set_ct(self, value):
logging.info("Bulb color temp: %s", value)

def set_atc(self, value):
logging.info("Write to ActiveTransactionCount: %s", value)

def set_tc(self, value):
logging.info("Write to TransitionControl: %s", value)

def set_brightness(self, value):
logging.info("Bulb brightness: %s", value)

driver = AccessoryDriver(port=51826, persist_file='adaptive_lightbulb.state')
driver.add_accessory(accessory=LightBulb(driver, 'Lightbulb'))
signal.signal(signal.SIGTERM, driver.signal_handler)
driver.start()

24 changes: 24 additions & 0 deletions pyhap/resources/characteristics.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
],
"UUID": "000000E7-0000-1000-8000-0026BB765291"
},
"ActiveTransitionCount": {
"Format": "uint8",
"Permissions": [
"pr",
"ev"
],
"UUID": "0000024B-0000-1000-8000-0026BB765291"
},
"AdministratorOnlyAccess": {
"Format": "bool",
"Permissions": [
Expand Down Expand Up @@ -1318,6 +1326,13 @@
],
"UUID": "00000114-0000-1000-8000-0026BB765291"
},
"SupportedTransitionConfiguration": {
"Format": "tlv8",
"Permissions": [
"pr"
],
"UUID": "00000144-0000-1000-8000-0026BB765291"
},
"SwingMode": {
"Format": "uint8",
"Permissions": [
Expand Down Expand Up @@ -1558,6 +1573,15 @@
"Fahrenheit": 1
}
},
"TransitionControl": {
"Format": "tlv8",
"Permissions": [
"pr",
"pw",
"wr"
],
"UUID": "00000143-0000-1000-8000-0026BB765291"
},
"VOCDensity": {
"Format": "float",
"Permissions": [
Expand Down
7 changes: 5 additions & 2 deletions pyhap/resources/services.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@
"Brightness",
"Hue",
"Saturation",
"Name"
"Name",
"ActiveTransitionCount",
"TransitionControl",
"SupportedTransitionConfiguration"
],
"RequiredCharacteristics": [
"On"
Expand Down Expand Up @@ -574,4 +577,4 @@
],
"UUID": "0000008C-0000-1000-8000-0026BB765291"
}
}
}