Compare commits

...

9 Commits

Author SHA1 Message Date
f1dbd9344d homekit names 2
All checks were successful
ci/woodpecker/tag/build/5 Pipeline was successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/tag/build/4 Pipeline was successful
ci/woodpecker/tag/build/6 Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
ci/woodpecker/tag/build/3 Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/deploy/2 Pipeline was successful
ci/woodpecker/tag/deploy/1 Pipeline was successful
ci/woodpecker/tag/deploy/5 Pipeline was successful
ci/woodpecker/tag/deploy/4 Pipeline was successful
ci/woodpecker/tag/deploy/3 Pipeline was successful
ci/woodpecker/tag/ingress Pipeline was successful
2025-12-08 11:36:17 +01:00
5a67d7b330 homekit names
Some checks failed
ci/woodpecker/tag/config unknown status
ci/woodpecker/tag/namespace Pipeline is pending
ci/woodpecker/tag/build/5 Pipeline failed
ci/woodpecker/tag/build/1 Pipeline failed
ci/woodpecker/tag/build/2 Pipeline failed
ci/woodpecker/tag/build/3 Pipeline failed
ci/woodpecker/tag/build/4 Pipeline failed
ci/woodpecker/tag/build/6 Pipeline failed
ci/woodpecker/tag/deploy/1 unknown status
ci/woodpecker/tag/deploy/2 unknown status
ci/woodpecker/tag/deploy/3 unknown status
ci/woodpecker/tag/deploy/4 unknown status
ci/woodpecker/tag/deploy/5 unknown status
ci/woodpecker/tag/ingress unknown status
2025-12-08 11:20:27 +01:00
cc342245f8 gartenlicht vorne
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-08 10:48:23 +01:00
50253d536d more lights 6
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-08 10:28:30 +01:00
e0aa50c9d2 more lights 5
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-08 09:22:38 +01:00
dc20d9f4b2 more lights 4
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-08 09:15:32 +01:00
ffb35928b4 more lights 3
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-07 22:12:23 +01:00
ac84ff7103 more lights 2
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-07 21:49:34 +01:00
c185494da3 more lights
All checks were successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
2025-12-07 21:44:57 +01:00
10 changed files with 122 additions and 121 deletions

View File

@@ -14,7 +14,7 @@ class ContactAccessory(Accessory):
category = CATEGORY_SENSOR
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
"""
Initialize the contact sensor accessory.
@@ -22,9 +22,8 @@ class ContactAccessory(Accessory):
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
name = device.name
super().__init__(driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client

View File

@@ -16,7 +16,7 @@ class OnOffLightAccessory(Accessory):
category = CATEGORY_LIGHTBULB
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
"""
Initialize the light accessory.
@@ -24,9 +24,8 @@ class OnOffLightAccessory(Accessory):
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
name = device.name
super().__init__(driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client
@@ -57,9 +56,9 @@ class OnOffLightAccessory(Accessory):
class DimmableLightAccessory(OnOffLightAccessory):
"""Dimmable Light with brightness control."""
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *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
name = device.name
Accessory.__init__(self, driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client
@@ -106,9 +105,9 @@ class DimmableLightAccessory(OnOffLightAccessory):
class ColorLightAccessory(DimmableLightAccessory):
"""RGB Light with full color control."""
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
# Don't call super().__init__() - build everything from scratch
name = display_name or device.friendly_name or device.name
name = device.name
Accessory.__init__(self, driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client

View File

@@ -15,7 +15,7 @@ class OutletAccessory(Accessory):
category = CATEGORY_OUTLET
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
"""
Initialize the outlet accessory.
@@ -23,9 +23,8 @@ class OutletAccessory(Accessory):
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
name = device.name
super().__init__(driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client

View File

@@ -15,7 +15,7 @@ class TempHumidityAccessory(Accessory):
category = CATEGORY_SENSOR
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
"""
Initialize the temp/humidity sensor accessory.
@@ -23,9 +23,8 @@ class TempHumidityAccessory(Accessory):
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
name = device.name
super().__init__(driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client

View File

@@ -17,7 +17,7 @@ class ThermostatAccessory(Accessory):
category = CATEGORY_THERMOSTAT
def __init__(self, driver, device, api_client, display_name=None, *args, **kwargs):
def __init__(self, driver, device, api_client, *args, **kwargs):
"""
Initialize the thermostat accessory.
@@ -25,9 +25,8 @@ class ThermostatAccessory(Accessory):
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
name = device.name
super().__init__(driver, name, *args, **kwargs)
self.device = device
self.api_client = api_client

View File

@@ -51,25 +51,6 @@ class ApiClient:
logger.error(f"Failed to get devices: {e}")
raise
def get_layout(self) -> Dict:
"""
Get layout information (rooms and device assignments).
Returns:
Layout dictionary with room structure
"""
try:
response = httpx.get(
f'{self.base_url}/layout',
headers=self.headers,
timeout=self.timeout
)
response.raise_for_status()
return response.json()
except Exception as e:
logger.error(f"Failed to get layout: {e}")
raise
def get_device_state(self, device_id: str) -> Dict:
"""
Get current state of a specific device.

View File

@@ -18,8 +18,6 @@ class Device:
device_id: str
type: str # "light", "thermostat", "relay", "contact", "temp_humidity", "cover"
name: str # Short name from /devices
friendly_name: str # Display title from /layout (fallback to name)
room: Optional[str] # Room name from layout
features: Dict[str, bool] # Feature flags (e.g., {"power": true, "brightness": true})
read_only: bool # True for sensors that don't accept commands
@@ -50,23 +48,6 @@ class DeviceRegistry:
"""
# Get devices and layout
devices_data = api_client.get_devices()
layout_data = api_client.get_layout()
# Build lookup: device_id -> (room_name, title)
layout_map = {}
if isinstance(layout_data, dict) and 'rooms' in layout_data:
rooms_list = layout_data['rooms']
if isinstance(rooms_list, list):
for room in rooms_list:
if isinstance(room, dict):
room_name = room.get('name', 'Unknown')
devices_in_room = room.get('devices', [])
for device_info in devices_in_room:
if isinstance(device_info, dict):
device_id = device_info.get('device_id')
title = device_info.get('title', '')
if device_id:
layout_map[device_id] = (room_name, title)
# Create Device objects
devices = []
@@ -76,9 +57,6 @@ class DeviceRegistry:
logger.warning(f"Device without device_id: {dev_data}")
continue
# Get layout info
room_name, title = layout_map.get(device_id, (None, ''))
# Determine if read-only (sensors don't accept set commands)
device_type = dev_data.get('type', '')
read_only = device_type in ['contact', 'temp_humidity', 'motion', 'smoke']
@@ -86,9 +64,7 @@ class DeviceRegistry:
device = Device(
device_id=device_id,
type=device_type,
name=dev_data.get('name', device_id),
friendly_name=title or dev_data.get('name', device_id),
room=room_name,
name=device_id,
features=dev_data.get('features', {}),
read_only=read_only
)

View File

@@ -71,14 +71,9 @@ def build_bridge(driver: AccessoryDriver, api_client: ApiClient) -> Bridge:
try:
accessory = create_accessory_for_device(device, api_client, driver)
if accessory:
# Set room information in the accessory (HomeKit will use this for suggestions)
if device.room:
# Store room info for potential future use
accessory._room_name = device.room
bridge.add_accessory(accessory)
accessory_map[device.device_id] = accessory
logger.info(f"Added accessory: {device.friendly_name} ({device.type}, {accessory.__class__.__name__}) in room: {device.room or 'Unknown'}")
logger.info(f"Added accessory: {device.name} ({device.type}, {accessory.__class__.__name__})")
else:
logger.warning(f"No accessory mapping for device: {device.name} ({device.type})")
except Exception as e:
@@ -90,23 +85,6 @@ def build_bridge(driver: AccessoryDriver, api_client: ApiClient) -> Bridge:
logger.info(f"Bridge built with {len(accessory_map)} accessories")
return bridge
def get_accessory_name(device) -> str:
"""
Build accessory name including room information.
Args:
device: Device object from DeviceRegistry
Returns:
Name string like "Device Name (Room)" or just "Device Name" if no room
"""
base_name = device.friendly_name or device.name
if device.room:
return f"{base_name} ({device.room})"
return base_name
def create_accessory_for_device(device, api_client: ApiClient, driver: AccessoryDriver):
"""
Create appropriate HomeKit accessory based on device type and features.
@@ -115,12 +93,11 @@ def create_accessory_for_device(device, api_client: ApiClient, driver: Accessory
"""
device_type = device.type
features = device.features
display_name = get_accessory_name(device)
# Light accessories
if device_type == "light":
if features.get("color_hsb"):
return ColorLightAccessory(driver, device, api_client, display_name=display_name)
return ColorLightAccessory(driver, device, api_client)
elif features.get("brightness"):
return DimmableLightAccessory(driver, device, api_client, display_name=display_name)
else:
@@ -128,19 +105,18 @@ def create_accessory_for_device(device, api_client: ApiClient, driver: Accessory
# Thermostat
elif device_type == "thermostat":
return ThermostatAccessory(driver, device, api_client, display_name=display_name)
return ThermostatAccessory(driver, device, api_client)
# Contact sensor
elif device_type == "contact":
return ContactAccessory(driver, device, api_client, display_name=display_name)
return ContactAccessory(driver, device, api_client)
# Temperature/Humidity sensor
elif device_type == "temp_humidity_sensor":
return TempHumidityAccessory(driver, device, api_client, display_name=display_name)
return TempHumidityAccessory(driver, device, api_client)
# Relay/Outlet
elif device_type == "relay":
return OutletAccessory(driver, device, api_client, display_name=display_name)
return OutletAccessory(driver, device, api_client)
# Cover/Blinds (optional)
elif device_type == "cover":

View File

@@ -241,22 +241,6 @@ devices:
ieee_address: "0x0017880108a03e45"
model: "929002241201"
vendor: "Philips"
- device_id: haustuer
name: Haustür-Lampe
type: light
cap_version: "light@1.2.0"
technology: zigbee2mqtt
features:
power: true
brightness: true
topics:
state: "zigbee2mqtt/0xec1bbdfffea6a3da"
set: "zigbee2mqtt/0xec1bbdfffea6a3da/set"
metadata:
friendly_name: "Haustür"
ieee_address: "0xec1bbdfffea6a3da"
model: "LED1842G3"
vendor: "IKEA"
- device_id: deckenlampe_flur_oben
name: Deckenlampe oben
type: light
@@ -794,6 +778,17 @@ devices:
topics:
state: "zigbee2mqtt/0xbc33acfffe21f547"
set: "zigbee2mqtt/0xbc33acfffe21f547/set"
- device_id: kueche_fensterbank_licht
name: Fensterbank Küche
type: light
cap_version: "light@1.2.0"
technology: zigbee2mqtt
features:
power: true
brightness: true
topics:
state: "zigbee2mqtt/0xf0d1b8000017515d"
set: "zigbee2mqtt/0xf0d1b8000017515d/set"
- device_id: licht_kommode_schlafzimmer
name: Kommode Schlafzimmer
type: relay
@@ -804,6 +799,56 @@ devices:
topics:
set: "cmnd/tasmota/04/POWER"
state: "stat/tasmota/04/POWER"
- device_id: licht_fensterbank_esszimmer
name: Fensterbank Esszimmer
type: relay
cap_version: "relay@1.0.0"
technology: tasmota
features:
power: true
topics:
set: "cmnd/tasmota/02/POWER"
state: "stat/tasmota/02/POWER"
- device_id: licht_schreibtisch_patty
name: Schreibtisch Patty
type: relay
cap_version: "relay@1.0.0"
technology: tasmota
features:
power: true
topics:
set: "cmnd/tasmota/03/POWER"
state: "stat/tasmota/03/POWER"
- device_id: kugeln_regal_flur
name: Kugeln Regal Flur
type: relay
cap_version: "relay@1.0.0"
technology: tasmota
features:
power: true
topics:
set: "cmnd/tasmota/01/POWER"
state: "stat/tasmota/01/POWER"
- device_id: schrank_flur_haustür
name: Schrank Flur Haustür
type: relay
cap_version: "relay@1.0.0"
technology: tasmota
features:
power: true
topics:
set: "cmnd/tasmota/05/POWER"
state: "stat/tasmota/05/POWER"
- device_id: gartenlicht_vorne
name: Gartenlicht vorne
type: relay
cap_version: "relay@1.0.0"
technology: tasmota
features:
power: true
topics:
set: "cmnd/tasmota/06/POWER"
state: "stat/tasmota/06/POWER"
- device_id: power_relay_caroutlet
name: Car Outlet
@@ -824,4 +869,16 @@ devices:
topics:
state: "IoT/Car/Values"
- device_id: schranklicht_flur_vor_kueche
name: Schranklicht Flur vor Küche
type: light
cap_version: "relay@1.0.0"
technology: zigbee2mqtt
features:
power: true
topics:
state: "zigbee2mqtt/0xf0d1b80000155a1f"
set: "zigbee2mqtt/0xf0d1b80000155a1f/set"

View File

@@ -43,10 +43,10 @@ rooms:
title: Leselampe Esszimmer
icon: 💡
rank: 60
# - device_id: standlampe_esszimmer
# title: Standlampe Esszimmer
# icon: 💡
# rank: 70
- device_id: licht_fensterbank_esszimmer
title: Fensterbank Esszimmer
icon: 💡
rank: 70
- device_id: kleine_lampe_links_esszimmer
title: kleine Lampe links Esszimmer
icon: 💡
@@ -131,6 +131,10 @@ rooms:
title: Küche Putzlicht
icon: 💡
rank: 143
- device_id: kueche_fensterbank_licht
title: Küche Fensterbank
icon: 💡
rank: 144
- device_id: thermostat_kueche
title: Kueche
icon: 🌡️
@@ -173,6 +177,10 @@ rooms:
title: Kugellampe Patty
icon: 💡
rank: 181
- device_id: licht_schreibtisch_patty
title: Licht Schreibtisch Patty
icon: 💡
rank: 182
- device_id: thermostat_patty
title: Thermostat Patty
icon: 🌡️
@@ -217,18 +225,22 @@ rooms:
title: Deckenlampe Flur oben
icon: 💡
rank: 210
- device_id: haustuer
title: Haustür
icon: 💡
rank: 220
- device_id: licht_flur_schrank
title: Schranklicht Flur
- device_id: kugeln_regal_flur
title: Kugeln Regal
icon: 💡
rank: 222
- device_id: licht_flur_oben_am_spiegel
title: Licht Flur oben am Spiegel
title: Licht oben am Spiegel
icon: 💡
rank: 230
- device_id: schrank_flur_haustür
title: Schranklicht an der Haustür
icon: 💡
rank: 231
- device_id: schranklicht_flur_vor_kueche
title: Schranklicht vor Küche
icon: 💡
rank: 232
- device_id: sensor_flur
title: Temperatur & Luftfeuchte
icon: 🌡️
@@ -291,6 +303,10 @@ rooms:
title: Licht Terasse
icon: 💡
rank: 290
- device_id: gartenlicht_vorne
title: Gartenlicht vorne
icon: 💡
rank: 291
- name: Garage
devices:
- device_id: power_relay_caroutlet