178 lines
6.6 KiB
Python
178 lines
6.6 KiB
Python
"""
|
|
Light Accessory Implementations for HomeKit
|
|
|
|
Implements different light types:
|
|
- OnOffLightAccessory: Simple on/off light
|
|
- DimmableLightAccessory: Light with brightness control
|
|
- ColorLightAccessory: RGB light with full color control
|
|
"""
|
|
|
|
from pyhap.accessory import Accessory
|
|
from pyhap.const import CATEGORY_LIGHTBULB
|
|
|
|
|
|
class OnOffLightAccessory(Accessory):
|
|
"""Simple On/Off Light without dimming or color."""
|
|
|
|
category = CATEGORY_LIGHTBULB
|
|
|
|
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
|
|
"""
|
|
Initialize the light accessory.
|
|
|
|
Args:
|
|
driver: HAP driver instance
|
|
device: Device object from DeviceRegistry
|
|
api_client: ApiClient for sending commands
|
|
display_name: Optional display name (defaults to device.friendly_name)
|
|
"""
|
|
name = display_name or device.friendly_name or device.name
|
|
super().__init__(driver, name, *args, **kwargs)
|
|
self.device = device
|
|
self.api_client = api_client
|
|
|
|
# Add Lightbulb service with On characteristic
|
|
self.lightbulb_service = self.add_preload_service('Lightbulb')
|
|
|
|
# Get the On characteristic and set callback
|
|
self.on_char = self.lightbulb_service.get_characteristic('On')
|
|
self.on_char.setter_callback = self.set_on
|
|
|
|
def set_on(self, value):
|
|
"""Called when HomeKit wants to turn light on/off."""
|
|
power_state = "on" if value else "off"
|
|
payload = {
|
|
"type": "light",
|
|
"payload": {"power": power_state}
|
|
}
|
|
self.api_client.post_device_set(self.device.device_id, payload["type"], payload["payload"])
|
|
|
|
def update_state(self, state_payload):
|
|
"""Update state from API event."""
|
|
if "power" in state_payload:
|
|
is_on = state_payload["power"] == "on"
|
|
self.on_char.set_value(is_on)
|
|
|
|
|
|
class DimmableLightAccessory(OnOffLightAccessory):
|
|
"""Dimmable Light with brightness control."""
|
|
|
|
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
|
|
# Don't call super().__init__() yet - we need to set up service first
|
|
name = display_name or device.friendly_name or device.name
|
|
Accessory.__init__(self, driver, name, *args, **kwargs)
|
|
self.device = device
|
|
self.api_client = api_client
|
|
self.category = CATEGORY_LIGHTBULB
|
|
|
|
# Create Lightbulb service with all characteristics at once
|
|
from pyhap.loader import Loader
|
|
loader = Loader()
|
|
|
|
# Create the service
|
|
lightbulb_service = loader.get_service('Lightbulb')
|
|
|
|
# Add On characteristic
|
|
on_char = lightbulb_service.get_characteristic('On')
|
|
on_char.setter_callback = self.set_on
|
|
self.on_char = on_char
|
|
|
|
# Add Brightness characteristic
|
|
brightness_char = loader.get_char('Brightness')
|
|
brightness_char.set_value(0)
|
|
brightness_char.setter_callback = self.set_brightness
|
|
lightbulb_service.add_characteristic(brightness_char)
|
|
self.brightness_char = brightness_char
|
|
|
|
# Now add the complete service to the accessory
|
|
self.add_service(lightbulb_service)
|
|
self.lightbulb_service = lightbulb_service
|
|
|
|
def set_brightness(self, value):
|
|
"""Called when HomeKit wants to change brightness."""
|
|
payload = {
|
|
"type": "light",
|
|
"payload": {"brightness": int(value)}
|
|
}
|
|
self.api_client.post_device_set(self.device.device_id, payload["type"], payload["payload"])
|
|
|
|
def update_state(self, state_payload):
|
|
"""Update state from API event."""
|
|
super().update_state(state_payload)
|
|
if "brightness" in state_payload:
|
|
self.brightness_char.set_value(state_payload["brightness"])
|
|
|
|
|
|
class ColorLightAccessory(DimmableLightAccessory):
|
|
"""RGB Light with full color control."""
|
|
|
|
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
|
|
# Don't call super().__init__() - build everything from scratch
|
|
name = display_name or device.friendly_name or device.name
|
|
Accessory.__init__(self, driver, name, *args, **kwargs)
|
|
self.device = device
|
|
self.api_client = api_client
|
|
self.category = CATEGORY_LIGHTBULB
|
|
|
|
# Create Lightbulb service with all characteristics at once
|
|
from pyhap.loader import Loader
|
|
loader = Loader()
|
|
|
|
# Create the service
|
|
lightbulb_service = loader.get_service('Lightbulb')
|
|
|
|
# Add On characteristic
|
|
on_char = lightbulb_service.get_characteristic('On')
|
|
on_char.setter_callback = self.set_on
|
|
self.on_char = on_char
|
|
|
|
# Add Brightness characteristic
|
|
brightness_char = loader.get_char('Brightness')
|
|
brightness_char.set_value(0)
|
|
brightness_char.setter_callback = self.set_brightness
|
|
lightbulb_service.add_characteristic(brightness_char)
|
|
self.brightness_char = brightness_char
|
|
|
|
# Add Hue characteristic
|
|
hue_char = loader.get_char('Hue')
|
|
hue_char.set_value(0)
|
|
hue_char.setter_callback = self.set_hue
|
|
lightbulb_service.add_characteristic(hue_char)
|
|
self.hue_char = hue_char
|
|
|
|
# Add Saturation characteristic
|
|
saturation_char = loader.get_char('Saturation')
|
|
saturation_char.set_value(0)
|
|
saturation_char.setter_callback = self.set_saturation
|
|
lightbulb_service.add_characteristic(saturation_char)
|
|
self.saturation_char = saturation_char
|
|
|
|
# Now add the complete service to the accessory
|
|
self.add_service(lightbulb_service)
|
|
self.lightbulb_service = lightbulb_service
|
|
|
|
def set_hue(self, value):
|
|
"""Called when HomeKit wants to change hue."""
|
|
payload = {
|
|
"type": "light",
|
|
"payload": {"hue": int(value)}
|
|
}
|
|
self.api_client.post_device_set(self.device.device_id, payload["type"], payload["payload"])
|
|
|
|
def set_saturation(self, value):
|
|
"""Called when HomeKit wants to change saturation."""
|
|
payload = {
|
|
"type": "light",
|
|
"payload": {"sat": int(value)}
|
|
}
|
|
self.api_client.post_device_set(self.device.device_id, payload["type"], payload["payload"])
|
|
|
|
def update_state(self, state_payload):
|
|
"""Update state from API event."""
|
|
super().update_state(state_payload)
|
|
if "hue" in state_payload:
|
|
self.hue_char.set_value(state_payload["hue"])
|
|
if "sat" in state_payload:
|
|
self.saturation_char.set_value(state_payload["sat"])
|
|
|