Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
a2ddcf7de2
|
|||
|
3cc3683e8c
|
|||
|
e0810c72ea
|
|||
|
3c1253da08
|
|||
|
0efb6fab02
|
|||
|
a48d189f85
|
|||
|
40c3faa128
|
|||
|
5cca44638c
|
|||
|
fb2eef2a42
|
|||
|
0a2007ee65
|
|||
|
bdb25e3550
|
|||
|
6c284fa1f6
|
|||
|
5346d1b72c
|
|||
|
d8780b1790
|
|||
|
3d5010b4a1
|
|||
|
b471ab5edc
|
|||
|
3e0a1b49ab
|
|||
|
befdc8a46c
|
|||
|
da16c59238
|
|||
|
5f3185894d
|
|||
|
fb828c9a2c
|
|||
|
064ee6bbed
|
|||
|
d39bcfce26
|
|||
|
1fd275186a
|
|||
|
da370c9050
|
|||
|
08294ca294
|
|||
|
e5eb368dca
|
@@ -19,6 +19,8 @@ from apps.abstraction.vendors import (
|
|||||||
tasmota,
|
tasmota,
|
||||||
hottis_pv_modbus,
|
hottis_pv_modbus,
|
||||||
hottis_wago_modbus,
|
hottis_wago_modbus,
|
||||||
|
hottis_wifi_relay,
|
||||||
|
hottis_led_stripe
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -42,6 +44,8 @@ for vendor_name, vendor_module in [
|
|||||||
("tasmota", tasmota),
|
("tasmota", tasmota),
|
||||||
("hottis_pv_modbus", hottis_pv_modbus),
|
("hottis_pv_modbus", hottis_pv_modbus),
|
||||||
("hottis_wago_modbus", hottis_wago_modbus),
|
("hottis_wago_modbus", hottis_wago_modbus),
|
||||||
|
("hottis_wifi_relay", hottis_wifi_relay),
|
||||||
|
("hottis_led_stripe", hottis_led_stripe),
|
||||||
]:
|
]:
|
||||||
for (device_type, direction), handler in vendor_module.HANDLERS.items():
|
for (device_type, direction), handler in vendor_module.HANDLERS.items():
|
||||||
key = (device_type, vendor_name, direction)
|
key = (device_type, vendor_name, direction)
|
||||||
|
|||||||
38
apps/abstraction/vendors/hottis_led_stripe.py
vendored
Normal file
38
apps/abstraction/vendors/hottis_led_stripe.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
"""Hottis WiFi Relay vendor transformations."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def transform_relay_to_vendor(payload: dict[str, Any]) -> str:
|
||||||
|
"""Transform abstract relay payload to Hottis WiFi Relay format.
|
||||||
|
|
||||||
|
Hottis WiFi Relay expects plain text 'on' or 'off' (not JSON).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- Abstract: {'power': 'on'}
|
||||||
|
- Hottis WiFi Relay: 'ON'
|
||||||
|
"""
|
||||||
|
power = payload.get("power", "off").upper()
|
||||||
|
return power
|
||||||
|
|
||||||
|
|
||||||
|
def transform_relay_to_abstract(payload: str) -> dict[str, Any]:
|
||||||
|
"""Transform Hottis WiFi Relay relay payload to abstract format.
|
||||||
|
|
||||||
|
Hottis WiFi Relay sends plain text 'on' or 'off'.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- Hottis WiFi Relay: 'ON'
|
||||||
|
- Abstract: {'power': 'on'}
|
||||||
|
"""
|
||||||
|
return {"power": payload.strip().lower()}
|
||||||
|
|
||||||
|
|
||||||
|
# Registry of handlers for this vendor
|
||||||
|
HANDLERS = {
|
||||||
|
("relay", "to_vendor"): transform_relay_to_vendor,
|
||||||
|
("relay", "to_abstract"): transform_relay_to_abstract,
|
||||||
|
}
|
||||||
38
apps/abstraction/vendors/hottis_wifi_relay.py
vendored
Normal file
38
apps/abstraction/vendors/hottis_wifi_relay.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
"""Hottis WiFi Relay vendor transformations."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def transform_relay_to_vendor(payload: dict[str, Any]) -> str:
|
||||||
|
"""Transform abstract relay payload to Hottis WiFi Relay format.
|
||||||
|
|
||||||
|
Hottis WiFi Relay expects plain text 'on' or 'off' (not JSON).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- Abstract: {'power': 'on'}
|
||||||
|
- Hottis WiFi Relay: 'ON'
|
||||||
|
"""
|
||||||
|
power = payload.get("power", "off").upper()
|
||||||
|
return power
|
||||||
|
|
||||||
|
|
||||||
|
def transform_relay_to_abstract(payload: str) -> dict[str, Any]:
|
||||||
|
"""Transform Hottis WiFi Relay relay payload to abstract format.
|
||||||
|
|
||||||
|
Hottis WiFi Relay sends plain text 'on' or 'off'.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- Hottis WiFi Relay: 'ON'
|
||||||
|
- Abstract: {'power': 'on'}
|
||||||
|
"""
|
||||||
|
return {"power": payload.strip().lower()}
|
||||||
|
|
||||||
|
|
||||||
|
# Registry of handlers for this vendor
|
||||||
|
HANDLERS = {
|
||||||
|
("relay", "to_vendor"): transform_relay_to_vendor,
|
||||||
|
("relay", "to_abstract"): transform_relay_to_abstract,
|
||||||
|
}
|
||||||
@@ -8,9 +8,9 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
MQTT_BROKER=172.16.2.16 \
|
MQTT_BROKER=172.16.2.16 \
|
||||||
MQTT_PORT=1883 \
|
MQTT_PORT=1883 \
|
||||||
REDIS_HOST=localhost \
|
REDIS_HOST=172.23.1.116 \
|
||||||
REDIS_PORT=6379 \
|
REDIS_PORT=6379 \
|
||||||
REDIS_DB=0 \
|
REDIS_DB=8 \
|
||||||
REDIS_CHANNEL=ui:updates
|
REDIS_CHANNEL=ui:updates
|
||||||
|
|
||||||
# Create non-root user
|
# Create non-root user
|
||||||
|
|||||||
146
apps/api/config.py
Normal file
146
apps/api/config.py
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
"""Configuration loading and caching for API application.
|
||||||
|
|
||||||
|
This module provides centralized configuration management for devices and layout,
|
||||||
|
with startup validation and in-memory caching for performance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from packages.home_capabilities.layout import UiLayout
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Global caches (loaded once at startup)
|
||||||
|
devices_cache: list[dict[str, Any]] = []
|
||||||
|
layout_cache: UiLayout | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def load_devices_from_file() -> list[dict[str, Any]]:
|
||||||
|
"""Load devices from configuration file and validate.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: List of device configurations
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If devices.yaml doesn't exist
|
||||||
|
KeyError: If any device is missing required homekit_aid field
|
||||||
|
ValueError: If devices.yaml is invalid or contains duplicate homekit_aid values
|
||||||
|
"""
|
||||||
|
config_path = Path(__file__).parent.parent.parent / "config" / "devices.yaml"
|
||||||
|
|
||||||
|
if not config_path.exists():
|
||||||
|
raise FileNotFoundError(f"devices.yaml not found at {config_path}")
|
||||||
|
|
||||||
|
with open(config_path, "r") as f:
|
||||||
|
config = yaml.safe_load(f)
|
||||||
|
|
||||||
|
if not config or "devices" not in config:
|
||||||
|
raise ValueError("devices.yaml must contain 'devices' key")
|
||||||
|
|
||||||
|
# Normalize device entries: accept both 'id' and 'device_id', use 'device_id' internally
|
||||||
|
devices = config.get("devices", [])
|
||||||
|
for device in devices:
|
||||||
|
device["device_id"] = device.pop("device_id", device.pop("id", None))
|
||||||
|
|
||||||
|
# Validate required homekit_aid field
|
||||||
|
if "homekit_aid" not in device:
|
||||||
|
raise KeyError(f"Device {device.get('device_id', 'unknown')} is missing required 'homekit_aid' field")
|
||||||
|
|
||||||
|
# Validate unique homekit_aid values
|
||||||
|
aids = [d["homekit_aid"] for d in devices]
|
||||||
|
if len(aids) != len(set(aids)):
|
||||||
|
duplicates = [aid for aid in aids if aids.count(aid) > 1]
|
||||||
|
raise ValueError(f"Duplicate homekit_aid values found: {set(duplicates)}")
|
||||||
|
|
||||||
|
logger.info(f"Loaded {len(devices)} devices with unique homekit_aid values (range: {min(aids)}-{max(aids)})")
|
||||||
|
|
||||||
|
return devices
|
||||||
|
|
||||||
|
|
||||||
|
def load_layout_from_file() -> UiLayout:
|
||||||
|
"""Load UI layout from configuration file and validate.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
UiLayout: Parsed and validated layout configuration
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If layout.yaml doesn't exist
|
||||||
|
ValueError: If layout validation fails
|
||||||
|
yaml.YAMLError: If YAML parsing fails
|
||||||
|
"""
|
||||||
|
config_path = Path(__file__).parent.parent.parent / "config" / "layout.yaml"
|
||||||
|
|
||||||
|
if not config_path.exists():
|
||||||
|
raise FileNotFoundError(
|
||||||
|
f"Layout configuration not found: {config_path}. "
|
||||||
|
f"Please create a layout.yaml file with room and device definitions."
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_path, "r", encoding="utf-8") as f:
|
||||||
|
data = yaml.safe_load(f)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
raise yaml.YAMLError(f"Failed to parse YAML in {config_path}: {e}")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
raise ValueError(f"Layout file is empty: {config_path}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
layout = UiLayout(**data)
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f"Invalid layout configuration in {config_path}: {e}")
|
||||||
|
|
||||||
|
total_devices = layout.total_devices()
|
||||||
|
room_names = [room.name for room in layout.rooms]
|
||||||
|
logger.info(
|
||||||
|
f"Loaded layout: {len(layout.rooms)} rooms, "
|
||||||
|
f"{total_devices} total devices (Rooms: {', '.join(room_names)})"
|
||||||
|
)
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
def load_devices() -> list[dict[str, Any]]:
|
||||||
|
"""Get devices from in-memory cache.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: List of device configurations (loaded at startup)
|
||||||
|
"""
|
||||||
|
return devices_cache
|
||||||
|
|
||||||
|
|
||||||
|
def load_layout() -> UiLayout:
|
||||||
|
"""Get layout from in-memory cache.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
UiLayout: Layout configuration (loaded at startup)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RuntimeError: If layout cache is not initialized
|
||||||
|
"""
|
||||||
|
if layout_cache is None:
|
||||||
|
raise RuntimeError("Layout cache not initialized. Application startup may have failed.")
|
||||||
|
return layout_cache
|
||||||
|
|
||||||
|
|
||||||
|
def initialize_config() -> None:
|
||||||
|
"""Initialize configuration by loading devices and layout.
|
||||||
|
|
||||||
|
This function should be called once during application startup.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Exception: If configuration loading or validation fails
|
||||||
|
"""
|
||||||
|
global devices_cache, layout_cache
|
||||||
|
|
||||||
|
# Load devices with validation
|
||||||
|
devices_cache = load_devices_from_file()
|
||||||
|
|
||||||
|
# Load layout with validation
|
||||||
|
layout_cache = load_layout_from_file()
|
||||||
|
|
||||||
|
logger.info("Configuration initialization complete")
|
||||||
@@ -24,9 +24,11 @@ from packages.home_capabilities import (
|
|||||||
ContactState,
|
ContactState,
|
||||||
TempHumidityState,
|
TempHumidityState,
|
||||||
RelayState,
|
RelayState,
|
||||||
load_layout,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Import configuration management
|
||||||
|
from apps.api.config import initialize_config, load_devices, load_layout
|
||||||
|
|
||||||
# Import resolvers (must be before router imports to avoid circular dependency)
|
# Import resolvers (must be before router imports to avoid circular dependency)
|
||||||
from apps.api.resolvers import (
|
from apps.api.resolvers import (
|
||||||
DeviceDTO,
|
DeviceDTO,
|
||||||
@@ -99,30 +101,6 @@ async def get_device_state(device_id: str):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise HTTPException(status_code=404, detail="Device state not found")
|
raise HTTPException(status_code=404, detail="Device state not found")
|
||||||
|
|
||||||
# --- Minimal-invasive: Einzelgerät-Layout-Endpunkt ---
|
|
||||||
@app.get("/devices/{device_id}/layout")
|
|
||||||
async def get_device_layout(device_id: str):
|
|
||||||
"""Gibt die layout-spezifischen Informationen für ein einzelnes Gerät zurück."""
|
|
||||||
layout = load_layout()
|
|
||||||
for room in layout.get("rooms", []):
|
|
||||||
for device in room.get("devices", []):
|
|
||||||
if device.get("device_id") == device_id:
|
|
||||||
# Rückgabe: Layout-Infos + Raumname
|
|
||||||
return {
|
|
||||||
"device_id": device_id,
|
|
||||||
"room": room.get("name"),
|
|
||||||
"title": device.get("title"),
|
|
||||||
"icon": device.get("icon"),
|
|
||||||
"rank": device.get("rank"),
|
|
||||||
}
|
|
||||||
raise HTTPException(status_code=404, detail="Device layout not found")
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
|
||||||
async def startup_event():
|
|
||||||
"""Include routers after app is initialized to avoid circular imports."""
|
|
||||||
from apps.api.routes.groups_scenes import router as groups_scenes_router
|
|
||||||
app.include_router(groups_scenes_router, prefix="")
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health() -> dict[str, str]:
|
async def health() -> dict[str, str]:
|
||||||
@@ -188,6 +166,21 @@ async def redis_state_listener():
|
|||||||
async def startup_event():
|
async def startup_event():
|
||||||
"""Start background tasks on application startup."""
|
"""Start background tasks on application startup."""
|
||||||
global background_task
|
global background_task
|
||||||
|
|
||||||
|
# Include routers
|
||||||
|
from apps.api.routes.groups_scenes import router as groups_scenes_router
|
||||||
|
from apps.api.routes.rooms import router as rooms_router
|
||||||
|
|
||||||
|
app.include_router(groups_scenes_router, prefix="")
|
||||||
|
app.include_router(rooms_router, prefix="")
|
||||||
|
|
||||||
|
# Load and validate configuration (devices + layout)
|
||||||
|
try:
|
||||||
|
initialize_config()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to initialize configuration: {e}")
|
||||||
|
raise # Fatal error - application will not start
|
||||||
|
|
||||||
background_task = asyncio.create_task(redis_state_listener())
|
background_task = asyncio.create_task(redis_state_listener())
|
||||||
logger.info("Started background Redis state listener")
|
logger.info("Started background Redis state listener")
|
||||||
|
|
||||||
@@ -235,32 +228,11 @@ class DeviceInfo(BaseModel):
|
|||||||
device_id: str
|
device_id: str
|
||||||
type: str
|
type: str
|
||||||
name: str
|
name: str
|
||||||
|
homekit_aid: int
|
||||||
features: dict[str, Any] = {}
|
features: dict[str, Any] = {}
|
||||||
|
|
||||||
|
|
||||||
# Configuration helpers
|
# Configuration helpers
|
||||||
def load_devices() -> list[dict[str, Any]]:
|
|
||||||
"""Load devices from configuration file.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: List of device configurations
|
|
||||||
"""
|
|
||||||
config_path = Path(__file__).parent.parent.parent / "config" / "devices.yaml"
|
|
||||||
|
|
||||||
if not config_path.exists():
|
|
||||||
return []
|
|
||||||
|
|
||||||
with open(config_path, "r") as f:
|
|
||||||
config = yaml.safe_load(f)
|
|
||||||
|
|
||||||
# Normalize device entries: accept both 'id' and 'device_id', use 'device_id' internally
|
|
||||||
devices = config.get("devices", [])
|
|
||||||
for device in devices:
|
|
||||||
device["device_id"] = device.pop("device_id", device.pop("id", None))
|
|
||||||
|
|
||||||
return devices
|
|
||||||
|
|
||||||
|
|
||||||
def get_mqtt_settings() -> tuple[str, int]:
|
def get_mqtt_settings() -> tuple[str, int]:
|
||||||
"""Get MQTT broker settings from environment.
|
"""Get MQTT broker settings from environment.
|
||||||
|
|
||||||
@@ -388,6 +360,7 @@ async def get_device(device_id: str) -> DeviceInfo:
|
|||||||
device_id=device["device_id"],
|
device_id=device["device_id"],
|
||||||
type=device["type"],
|
type=device["type"],
|
||||||
name=device.get("name", device["device_id"]),
|
name=device.get("name", device["device_id"]),
|
||||||
|
homekit_aid=device["homekit_aid"],
|
||||||
features=device.get("features", {})
|
features=device.get("features", {})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -406,6 +379,7 @@ async def get_devices() -> list[DeviceInfo]:
|
|||||||
device_id=device["device_id"],
|
device_id=device["device_id"],
|
||||||
type=device["type"],
|
type=device["type"],
|
||||||
name=device.get("name", device["device_id"]),
|
name=device.get("name", device["device_id"]),
|
||||||
|
homekit_aid=device["homekit_aid"],
|
||||||
features=device.get("features", {})
|
features=device.get("features", {})
|
||||||
)
|
)
|
||||||
for device in devices
|
for device in devices
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, TypedDict
|
from typing import Any, TypedDict
|
||||||
|
|
||||||
|
from apps.api.config import load_layout
|
||||||
from packages.home_capabilities import (
|
from packages.home_capabilities import (
|
||||||
GroupConfig,
|
GroupConfig,
|
||||||
GroupsConfigRoot,
|
GroupsConfigRoot,
|
||||||
SceneStep,
|
SceneStep,
|
||||||
get_group_by_id,
|
get_group_by_id,
|
||||||
load_layout,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
219
apps/api/routes/rooms.py
Normal file
219
apps/api/routes/rooms.py
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
"""
|
||||||
|
Room-based device control endpoints.
|
||||||
|
|
||||||
|
Provides bulk control operations for devices within rooms:
|
||||||
|
- /rooms/{room_name}/lights - Control all lights in a room
|
||||||
|
- /rooms/{room_name}/heating - Control all thermostats in a room
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from fastapi import APIRouter, HTTPException, status
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from apps.api.config import load_layout
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
router = APIRouter(tags=["Rooms"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/rooms")
|
||||||
|
async def get_rooms() -> list[dict[str, str]]:
|
||||||
|
"""Get list of all room IDs and names.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of dicts with room id and name
|
||||||
|
"""
|
||||||
|
layout = load_layout()
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"id": room.id,
|
||||||
|
"name": room.name
|
||||||
|
}
|
||||||
|
for room in layout.rooms
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class LightsControlRequest(BaseModel):
|
||||||
|
"""Request model for controlling lights in a room."""
|
||||||
|
power: str # "on" or "off"
|
||||||
|
brightness: int | None = None # Optional brightness 0-100
|
||||||
|
|
||||||
|
|
||||||
|
class HeatingControlRequest(BaseModel):
|
||||||
|
"""Request model for controlling heating in a room."""
|
||||||
|
target: float # Target temperature
|
||||||
|
|
||||||
|
|
||||||
|
def get_room_devices(room_id: str) -> list[dict[str, Any]]:
|
||||||
|
"""Get all devices in a specific room from layout.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
room_id: ID of the room
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of device dicts with device_id, title, icon, rank, excluded
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HTTPException: If room not found
|
||||||
|
"""
|
||||||
|
layout = load_layout()
|
||||||
|
|
||||||
|
for room in layout.rooms:
|
||||||
|
if room.id == room_id:
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"device_id": device.device_id,
|
||||||
|
"title": device.title,
|
||||||
|
"icon": device.icon,
|
||||||
|
"rank": device.rank,
|
||||||
|
"excluded": device.excluded
|
||||||
|
}
|
||||||
|
for device in room.devices
|
||||||
|
]
|
||||||
|
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"Room '{room_id}' not found"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/rooms/{room_id}/lights", status_code=status.HTTP_202_ACCEPTED)
|
||||||
|
async def control_room_lights(room_id: str, request: LightsControlRequest) -> dict[str, Any]:
|
||||||
|
"""Control all lights (light and relay devices) in a room.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
room_id: ID of the room
|
||||||
|
request: Light control parameters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict with affected device_ids and command summary
|
||||||
|
"""
|
||||||
|
from apps.api.main import load_devices, publish_abstract_set
|
||||||
|
|
||||||
|
# Get all devices in room
|
||||||
|
room_devices = get_room_devices(room_id)
|
||||||
|
|
||||||
|
# Filter out excluded devices
|
||||||
|
room_device_ids = {d["device_id"] for d in room_devices if not d.get("excluded", False)}
|
||||||
|
|
||||||
|
# Load all devices to filter by type
|
||||||
|
all_devices = load_devices()
|
||||||
|
|
||||||
|
# Filter for light/relay devices in this room
|
||||||
|
light_devices = [
|
||||||
|
d for d in all_devices
|
||||||
|
if d["device_id"] in room_device_ids and d["type"] in ("light", "relay")
|
||||||
|
]
|
||||||
|
|
||||||
|
if not light_devices:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"No light devices found in room '{room_id}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build payload
|
||||||
|
payload = {"power": request.power}
|
||||||
|
if request.brightness is not None and request.power == "on":
|
||||||
|
payload["brightness"] = request.brightness
|
||||||
|
|
||||||
|
# Send commands to all light devices
|
||||||
|
affected_ids = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for device in light_devices:
|
||||||
|
try:
|
||||||
|
await publish_abstract_set(
|
||||||
|
device_type=device["type"],
|
||||||
|
device_id=device["device_id"],
|
||||||
|
payload=payload
|
||||||
|
)
|
||||||
|
affected_ids.append(device["device_id"])
|
||||||
|
logger.info(f"Sent command to {device['device_id']}: {payload}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to control {device['device_id']}: {e}")
|
||||||
|
errors.append({
|
||||||
|
"device_id": device["device_id"],
|
||||||
|
"error": str(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"room": room_id,
|
||||||
|
"command": "lights",
|
||||||
|
"payload": payload,
|
||||||
|
"affected_devices": affected_ids,
|
||||||
|
"success_count": len(affected_ids),
|
||||||
|
"error_count": len(errors),
|
||||||
|
"errors": errors if errors else None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/rooms/{room_id}/heating", status_code=status.HTTP_202_ACCEPTED)
|
||||||
|
async def control_room_heating(room_id: str, request: HeatingControlRequest) -> dict[str, Any]:
|
||||||
|
"""Control all thermostats in a room.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
room_id: ID of the room
|
||||||
|
request: Heating control parameters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict with affected device_ids and command summary
|
||||||
|
"""
|
||||||
|
from apps.api.main import load_devices, publish_abstract_set
|
||||||
|
|
||||||
|
# Get all devices in room
|
||||||
|
room_devices = get_room_devices(room_id)
|
||||||
|
|
||||||
|
# Filter out excluded devices
|
||||||
|
room_device_ids = {d["device_id"] for d in room_devices if not d.get("excluded", False)}
|
||||||
|
|
||||||
|
# Load all devices to filter by type
|
||||||
|
all_devices = load_devices()
|
||||||
|
|
||||||
|
# Filter for thermostat devices in this room
|
||||||
|
thermostat_devices = [
|
||||||
|
d for d in all_devices
|
||||||
|
if d["device_id"] in room_device_ids and d["type"] == "thermostat"
|
||||||
|
]
|
||||||
|
|
||||||
|
if not thermostat_devices:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"No thermostat devices found in room '{room_name}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build payload
|
||||||
|
payload = {"target": request.target}
|
||||||
|
|
||||||
|
# Send commands to all thermostat devices
|
||||||
|
affected_ids = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for device in thermostat_devices:
|
||||||
|
try:
|
||||||
|
await publish_abstract_set(
|
||||||
|
device_type="thermostat",
|
||||||
|
device_id=device["device_id"],
|
||||||
|
payload=payload
|
||||||
|
)
|
||||||
|
affected_ids.append(device["device_id"])
|
||||||
|
logger.info(f"Sent heating command to {device['device_id']}: {payload}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to control {device['device_id']}: {e}")
|
||||||
|
errors.append({
|
||||||
|
"device_id": device["device_id"],
|
||||||
|
"error": str(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"room": room_id,
|
||||||
|
"command": "heating",
|
||||||
|
"payload": payload,
|
||||||
|
"affected_devices": affected_ids,
|
||||||
|
"success_count": len(affected_ids),
|
||||||
|
"error_count": len(errors),
|
||||||
|
"errors": errors if errors else None
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ FROM python:3.12-slim
|
|||||||
|
|
||||||
# Environment defaults (can be overridden at runtime)
|
# Environment defaults (can be overridden at runtime)
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
|
LOG_LEVEL="INFO" \
|
||||||
HOMEKIT_NAME="Home Automation Bridge" \
|
HOMEKIT_NAME="Home Automation Bridge" \
|
||||||
HOMEKIT_PIN="031-45-154" \
|
HOMEKIT_PIN="031-45-154" \
|
||||||
HOMEKIT_PORT="51826" \
|
HOMEKIT_PORT="51826" \
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Device:
|
|||||||
device_id: str
|
device_id: str
|
||||||
type: str # "light", "thermostat", "relay", "contact", "temp_humidity", "cover"
|
type: str # "light", "thermostat", "relay", "contact", "temp_humidity", "cover"
|
||||||
name: str # Short name from /devices
|
name: str # Short name from /devices
|
||||||
|
homekit_aid: int # HomeKit Accessory ID
|
||||||
features: Dict[str, bool] # Feature flags (e.g., {"power": true, "brightness": true})
|
features: Dict[str, bool] # Feature flags (e.g., {"power": true, "brightness": true})
|
||||||
read_only: bool # True for sensors that don't accept commands
|
read_only: bool # True for sensors that don't accept commands
|
||||||
|
|
||||||
@@ -57,6 +58,12 @@ class DeviceRegistry:
|
|||||||
logger.warning(f"Device without device_id: {dev_data}")
|
logger.warning(f"Device without device_id: {dev_data}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Check for required homekit_aid field
|
||||||
|
homekit_aid = dev_data.get('homekit_aid')
|
||||||
|
if homekit_aid is None:
|
||||||
|
logger.error(f"Device {device_id} is missing required homekit_aid field - skipping")
|
||||||
|
continue
|
||||||
|
|
||||||
# Determine if read-only (sensors don't accept set commands)
|
# Determine if read-only (sensors don't accept set commands)
|
||||||
device_type = dev_data.get('type', '')
|
device_type = dev_data.get('type', '')
|
||||||
read_only = device_type in ['contact', 'temp_humidity', 'motion', 'smoke']
|
read_only = device_type in ['contact', 'temp_humidity', 'motion', 'smoke']
|
||||||
@@ -65,6 +72,7 @@ class DeviceRegistry:
|
|||||||
device_id=device_id,
|
device_id=device_id,
|
||||||
type=device_type,
|
type=device_type,
|
||||||
name=device_id,
|
name=device_id,
|
||||||
|
homekit_aid=homekit_aid,
|
||||||
features=dev_data.get('features', {}),
|
features=dev_data.get('features', {}),
|
||||||
read_only=read_only
|
read_only=read_only
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
services:
|
services:
|
||||||
homekit-bridge:
|
homekit-bridge:
|
||||||
image: gitea.hottis.de/wn/home-automation/homekit:0.5.0
|
image: gitea.hottis.de/wn/home-automation/homekit:0.5.0
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: apps/homekit/Dockerfile
|
||||||
container_name: homekit-bridge
|
container_name: homekit-bridge
|
||||||
|
|
||||||
# Required for mDNS/Bonjour to work properly
|
# Required for mDNS/Bonjour to work properly
|
||||||
network_mode: host
|
network_mode: host
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
- LOG_LEVEL=INFO
|
||||||
- HOMEKIT_NAME=Hottis Home Automation Bridge
|
- HOMEKIT_NAME=Hottis Home Automation Bridge
|
||||||
- HOMEKIT_PIN=031-45-154
|
- HOMEKIT_PIN=031-45-154
|
||||||
- HOMEKIT_PORT=51826
|
- HOMEKIT_PORT=51826
|
||||||
|
|||||||
@@ -31,8 +31,9 @@ from .api_client import ApiClient
|
|||||||
from .device_registry import DeviceRegistry
|
from .device_registry import DeviceRegistry
|
||||||
|
|
||||||
# Configure logging
|
# Configure logging
|
||||||
|
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=getattr(logging, LOG_LEVEL, logging.INFO),
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
)
|
)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -71,9 +72,11 @@ def build_bridge(driver: AccessoryDriver, api_client: ApiClient) -> Bridge:
|
|||||||
try:
|
try:
|
||||||
accessory = create_accessory_for_device(device, api_client, driver)
|
accessory = create_accessory_for_device(device, api_client, driver)
|
||||||
if accessory:
|
if accessory:
|
||||||
|
# Set AID from device configuration
|
||||||
|
accessory.aid = device.homekit_aid
|
||||||
bridge.add_accessory(accessory)
|
bridge.add_accessory(accessory)
|
||||||
accessory_map[device.device_id] = accessory
|
accessory_map[device.device_id] = accessory
|
||||||
logger.info(f"Added accessory: {device.name} ({device.type}, {accessory.__class__.__name__})")
|
logger.info(f"Added accessory: {device.name} ({device.type}, AID={device.homekit_aid}, {accessory.__class__.__name__})")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"No accessory mapping for device: {device.name} ({device.type})")
|
logger.warning(f"No accessory mapping for device: {device.name} ({device.type})")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -416,6 +416,7 @@
|
|||||||
if (feedbackDevice) {
|
if (feedbackDevice) {
|
||||||
const feedbackSection = document.createElement('div');
|
const feedbackSection = document.createElement('div');
|
||||||
feedbackSection.className = 'device-section';
|
feedbackSection.className = 'device-section';
|
||||||
|
feedbackSection.dataset.deviceId = feedbackDevice.device_id;
|
||||||
renderFeedbackDisplay(feedbackSection, feedbackDevice);
|
renderFeedbackDisplay(feedbackSection, feedbackDevice);
|
||||||
container.appendChild(feedbackSection);
|
container.appendChild(feedbackSection);
|
||||||
}
|
}
|
||||||
@@ -465,19 +466,10 @@
|
|||||||
|
|
||||||
console.log(`Rendering feedback for ${device.device_id}:`, state);
|
console.log(`Rendering feedback for ${device.device_id}:`, state);
|
||||||
|
|
||||||
const values = Object.values(state || {});
|
if (state.contact === 'closed') {
|
||||||
const isActive = values.some(v =>
|
label.textContent = 'Schütz ✅ eingeschaltet';
|
||||||
v === true ||
|
|
||||||
v === 'on' ||
|
|
||||||
v === 1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (values.length === 0) {
|
|
||||||
label.textContent = 'Kein Status verfügbar';
|
|
||||||
} else {
|
} else {
|
||||||
label.textContent = isActive
|
label.textContent = 'Schütz 🅾️ ausgeschaltet';
|
||||||
? 'Fahrzeug verbunden'
|
|
||||||
: 'Kein Fahrzeug verbunden';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
controlGroup.appendChild(label);
|
controlGroup.appendChild(label);
|
||||||
@@ -616,12 +608,14 @@
|
|||||||
const state = deviceStates[deviceId];
|
const state = deviceStates[deviceId];
|
||||||
console.log(`Updating UI for ${deviceId}:`, state);
|
console.log(`Updating UI for ${deviceId}:`, state);
|
||||||
|
|
||||||
switch (device.type) {
|
switch (deviceId) {
|
||||||
case 'relay':
|
case 'power_relay_caroutlet':
|
||||||
case 'outlet':
|
|
||||||
updateOutletUI(deviceId, state);
|
updateOutletUI(deviceId, state);
|
||||||
break;
|
break;
|
||||||
case 'three_phase_powermeter':
|
case 'sensor_caroutlet':
|
||||||
|
updateFeedbackDisplay(deviceId, state);
|
||||||
|
break;
|
||||||
|
case 'powermeter_caroutlet':
|
||||||
updateThreePhasePowerUI(deviceId, state);
|
updateThreePhasePowerUI(deviceId, state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -652,6 +646,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateFeedbackDisplay(deviceId, state) {
|
||||||
|
const section = document.querySelector(`[data-device-id="${deviceId}"]`);
|
||||||
|
if (!section) return;
|
||||||
|
|
||||||
|
const label = section.querySelector('.toggle-label');
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
const isOn = state.contact === 'closed';
|
||||||
|
label.textContent = isOn ? 'Schütz ✅ eingeschaltet' : 'Schütz 🅾️ ausgeschaltet';
|
||||||
|
|
||||||
|
// Update state display in separate card
|
||||||
|
const cards = section.querySelectorAll('.card');
|
||||||
|
if (cards.length >= 3) { // Header, Control, State
|
||||||
|
const stateCard = cards[2];
|
||||||
|
stateCard.innerHTML = `
|
||||||
|
<div style="font-size: 18px; font-weight: 600; color: ${isOn ? '#34c759' : '#666'};">
|
||||||
|
Status: ${isOn ? 'Eingeschaltet' : 'Ausgeschaltet'}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateThreePhasePowerUI(deviceId, state) {
|
function updateThreePhasePowerUI(deviceId, state) {
|
||||||
// Update overview
|
// Update overview
|
||||||
const totalPower = document.getElementById(`total-power-${deviceId}`);
|
const totalPower = document.getElementById(`total-power-${deviceId}`);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
version: 1
|
version: 1
|
||||||
devices:
|
devices:
|
||||||
- device_id: lampe_semeniere_wohnzimmer
|
- device_id: lampe_semeniere_wohnzimmer
|
||||||
|
homekit_aid: 2
|
||||||
name: Semeniere
|
name: Semeniere
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -16,6 +17,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: stehlampe_esszimmer_spiegel
|
- device_id: stehlampe_esszimmer_spiegel
|
||||||
|
homekit_aid: 3
|
||||||
name: Stehlampe Spiegel
|
name: Stehlampe Spiegel
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -27,6 +29,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0x001788010d06ea09"
|
state: "zigbee2mqtt/0x001788010d06ea09"
|
||||||
set: "zigbee2mqtt/0x001788010d06ea09/set"
|
set: "zigbee2mqtt/0x001788010d06ea09/set"
|
||||||
- device_id: stehlampe_esszimmer_schrank
|
- device_id: stehlampe_esszimmer_schrank
|
||||||
|
homekit_aid: 4
|
||||||
name: Stehlampe Schrank
|
name: Stehlampe Schrank
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -38,6 +41,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0x001788010d09176c"
|
state: "zigbee2mqtt/0x001788010d09176c"
|
||||||
set: "zigbee2mqtt/0x001788010d09176c/set"
|
set: "zigbee2mqtt/0x001788010d09176c/set"
|
||||||
- device_id: grosse_lampe_wohnzimmer
|
- device_id: grosse_lampe_wohnzimmer
|
||||||
|
homekit_aid: 5
|
||||||
name: grosse Lampe
|
name: grosse Lampe
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -53,6 +57,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: lampe_naehtischchen_wohnzimmer
|
- device_id: lampe_naehtischchen_wohnzimmer
|
||||||
|
homekit_aid: 6
|
||||||
name: Nähtischchen
|
name: Nähtischchen
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -68,6 +73,7 @@ devices:
|
|||||||
model: "HG06337"
|
model: "HG06337"
|
||||||
vendor: "Lidl"
|
vendor: "Lidl"
|
||||||
- device_id: kleine_lampe_links_esszimmer
|
- device_id: kleine_lampe_links_esszimmer
|
||||||
|
homekit_aid: 7
|
||||||
name: kleine Lampe
|
name: kleine Lampe
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -83,6 +89,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: leselampe_esszimmer
|
- device_id: leselampe_esszimmer
|
||||||
|
homekit_aid: 8
|
||||||
name: Leselampe
|
name: Leselampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -99,6 +106,7 @@ devices:
|
|||||||
model: "LED1842G3"
|
model: "LED1842G3"
|
||||||
vendor: "IKEA"
|
vendor: "IKEA"
|
||||||
- device_id: medusalampe_schlafzimmer
|
- device_id: medusalampe_schlafzimmer
|
||||||
|
homekit_aid: 9
|
||||||
name: Medusa-Lampe
|
name: Medusa-Lampe
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -114,6 +122,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: sportlicht_am_fernseher_studierzimmer
|
- device_id: sportlicht_am_fernseher_studierzimmer
|
||||||
|
homekit_aid: 10
|
||||||
type: light
|
type: light
|
||||||
name: am Fernseher
|
name: am Fernseher
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -131,6 +140,7 @@ devices:
|
|||||||
model: "LED1733G7"
|
model: "LED1733G7"
|
||||||
vendor: "IKEA"
|
vendor: "IKEA"
|
||||||
- device_id: deckenlampe_schlafzimmer
|
- device_id: deckenlampe_schlafzimmer
|
||||||
|
homekit_aid: 11
|
||||||
name: Deckenlampe
|
name: Deckenlampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -147,6 +157,7 @@ devices:
|
|||||||
model: "8718699688882"
|
model: "8718699688882"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: bettlicht_wolfgang
|
- device_id: bettlicht_wolfgang
|
||||||
|
homekit_aid: 12
|
||||||
name: Bettlicht Wolfgang
|
name: Bettlicht Wolfgang
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -163,6 +174,7 @@ devices:
|
|||||||
model: "9290020399"
|
model: "9290020399"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: bettlicht_patty
|
- device_id: bettlicht_patty
|
||||||
|
homekit_aid: 13
|
||||||
name: Bettlicht Patty
|
name: Bettlicht Patty
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -179,6 +191,7 @@ devices:
|
|||||||
model: "9290020399"
|
model: "9290020399"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: schranklicht_hinten_patty
|
- device_id: schranklicht_hinten_patty
|
||||||
|
homekit_aid: 14
|
||||||
name: Schranklicht hinten
|
name: Schranklicht hinten
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -195,6 +208,7 @@ devices:
|
|||||||
model: "8718699673147"
|
model: "8718699673147"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: schranklicht_vorne_patty
|
- device_id: schranklicht_vorne_patty
|
||||||
|
homekit_aid: 15
|
||||||
name: Schranklicht vorne
|
name: Schranklicht vorne
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -210,6 +224,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: leselampe_patty
|
- device_id: leselampe_patty
|
||||||
|
homekit_aid: 16
|
||||||
name: Leselampe
|
name: Leselampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -226,6 +241,7 @@ devices:
|
|||||||
model: "8718699673147"
|
model: "8718699673147"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: deckenlampe_esszimmer
|
- device_id: deckenlampe_esszimmer
|
||||||
|
homekit_aid: 17
|
||||||
name: Deckenlampe
|
name: Deckenlampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -242,6 +258,7 @@ devices:
|
|||||||
model: "929002241201"
|
model: "929002241201"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: deckenlampe_flur_oben
|
- device_id: deckenlampe_flur_oben
|
||||||
|
homekit_aid: 18
|
||||||
name: Deckenlampe oben
|
name: Deckenlampe oben
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -259,6 +276,7 @@ devices:
|
|||||||
model: "929003099001"
|
model: "929003099001"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: kueche_deckenlampe
|
- device_id: kueche_deckenlampe
|
||||||
|
homekit_aid: 19
|
||||||
name: Deckenlampe
|
name: Deckenlampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -275,6 +293,7 @@ devices:
|
|||||||
model: "929002469202"
|
model: "929002469202"
|
||||||
vendor: "Philips"
|
vendor: "Philips"
|
||||||
- device_id: sportlicht_tisch
|
- device_id: sportlicht_tisch
|
||||||
|
homekit_aid: 20
|
||||||
name: am Tisch
|
name: am Tisch
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -291,6 +310,7 @@ devices:
|
|||||||
model: "4058075729063"
|
model: "4058075729063"
|
||||||
vendor: "LEDVANCE"
|
vendor: "LEDVANCE"
|
||||||
- device_id: sportlicht_regal
|
- device_id: sportlicht_regal
|
||||||
|
homekit_aid: 21
|
||||||
name: am Regal
|
name: am Regal
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -307,6 +327,7 @@ devices:
|
|||||||
model: "4058075729063"
|
model: "4058075729063"
|
||||||
vendor: "LEDVANCE"
|
vendor: "LEDVANCE"
|
||||||
- device_id: licht_flur_oben_am_spiegel
|
- device_id: licht_flur_oben_am_spiegel
|
||||||
|
homekit_aid: 22
|
||||||
name: Spiegel
|
name: Spiegel
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -324,6 +345,7 @@ devices:
|
|||||||
model: "LED1732G11"
|
model: "LED1732G11"
|
||||||
vendor: "IKEA"
|
vendor: "IKEA"
|
||||||
- device_id: experimentlabtest
|
- device_id: experimentlabtest
|
||||||
|
homekit_aid: 23
|
||||||
name: Test Lampe
|
name: Test Lampe
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -340,6 +362,7 @@ devices:
|
|||||||
model: "4058075208421"
|
model: "4058075208421"
|
||||||
vendor: "LEDVANCE"
|
vendor: "LEDVANCE"
|
||||||
- device_id: thermostat_wolfgang
|
- device_id: thermostat_wolfgang
|
||||||
|
homekit_aid: 24
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -359,6 +382,7 @@ devices:
|
|||||||
model: "GS361A-H04"
|
model: "GS361A-H04"
|
||||||
vendor: "Siterwell"
|
vendor: "Siterwell"
|
||||||
- device_id: thermostat_kueche
|
- device_id: thermostat_kueche
|
||||||
|
homekit_aid: 25
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -378,6 +402,7 @@ devices:
|
|||||||
model: "GS361A-H04"
|
model: "GS361A-H04"
|
||||||
vendor: "Siterwell"
|
vendor: "Siterwell"
|
||||||
- device_id: thermostat_schlafzimmer
|
- device_id: thermostat_schlafzimmer
|
||||||
|
homekit_aid: 26
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -397,6 +422,7 @@ devices:
|
|||||||
peer_id: "42"
|
peer_id: "42"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: thermostat_esszimmer
|
- device_id: thermostat_esszimmer
|
||||||
|
homekit_aid: 27
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -416,6 +442,7 @@ devices:
|
|||||||
peer_id: "45"
|
peer_id: "45"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: thermostat_wohnzimmer
|
- device_id: thermostat_wohnzimmer
|
||||||
|
homekit_aid: 28
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -435,6 +462,7 @@ devices:
|
|||||||
peer_id: "46"
|
peer_id: "46"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: thermostat_patty
|
- device_id: thermostat_patty
|
||||||
|
homekit_aid: 29
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -454,6 +482,7 @@ devices:
|
|||||||
peer_id: "39"
|
peer_id: "39"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: thermostat_bad_oben
|
- device_id: thermostat_bad_oben
|
||||||
|
homekit_aid: 30
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -473,6 +502,7 @@ devices:
|
|||||||
peer_id: "41"
|
peer_id: "41"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: thermostat_bad_unten
|
- device_id: thermostat_bad_unten
|
||||||
|
homekit_aid: 31
|
||||||
name: Heizung
|
name: Heizung
|
||||||
type: thermostat
|
type: thermostat
|
||||||
cap_version: "thermostat@1.0.0"
|
cap_version: "thermostat@1.0.0"
|
||||||
@@ -492,6 +522,7 @@ devices:
|
|||||||
peer_id: "48"
|
peer_id: "48"
|
||||||
channel: "1"
|
channel: "1"
|
||||||
- device_id: sterne_wohnzimmer
|
- device_id: sterne_wohnzimmer
|
||||||
|
homekit_aid: 32
|
||||||
name: Sterne
|
name: Sterne
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -507,6 +538,7 @@ devices:
|
|||||||
model: "AC10691"
|
model: "AC10691"
|
||||||
vendor: "OSRAM"
|
vendor: "OSRAM"
|
||||||
- device_id: kontakt_schlafzimmer_strasse
|
- device_id: kontakt_schlafzimmer_strasse
|
||||||
|
homekit_aid: 33
|
||||||
name: Fenster
|
name: Fenster
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -515,6 +547,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/52/1/STATE
|
state: homegear/instance1/plain/52/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_esszimmer_strasse_rechts
|
- device_id: kontakt_esszimmer_strasse_rechts
|
||||||
|
homekit_aid: 34
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster rechts
|
name: Fenster rechts
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -523,6 +556,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/26/1/STATE
|
state: homegear/instance1/plain/26/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_esszimmer_strasse_links
|
- device_id: kontakt_esszimmer_strasse_links
|
||||||
|
homekit_aid: 35
|
||||||
name: Fenster links
|
name: Fenster links
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -531,6 +565,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/27/1/STATE
|
state: homegear/instance1/plain/27/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_wohnzimmer_garten_rechts
|
- device_id: kontakt_wohnzimmer_garten_rechts
|
||||||
|
homekit_aid: 36
|
||||||
name: Fenster rechts
|
name: Fenster rechts
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -539,6 +574,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/28/1/STATE
|
state: homegear/instance1/plain/28/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_wohnzimmer_garten_links
|
- device_id: kontakt_wohnzimmer_garten_links
|
||||||
|
homekit_aid: 37
|
||||||
name: Fenster links
|
name: Fenster links
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -547,6 +583,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/29/1/STATE
|
state: homegear/instance1/plain/29/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_kueche_garten_fenster
|
- device_id: kontakt_kueche_garten_fenster
|
||||||
|
homekit_aid: 38
|
||||||
name: Fenster Garten
|
name: Fenster Garten
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -555,6 +592,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b332785
|
state: zigbee2mqtt/0x00158d008b332785
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_kueche_garten_tuer
|
- device_id: kontakt_kueche_garten_tuer
|
||||||
|
homekit_aid: 39
|
||||||
type: contact
|
type: contact
|
||||||
name: Terrassentür
|
name: Terrassentür
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -563,6 +601,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b332788
|
state: zigbee2mqtt/0x00158d008b332788
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_kueche_strasse_rechts
|
- device_id: kontakt_kueche_strasse_rechts
|
||||||
|
homekit_aid: 40
|
||||||
name: Fenster Straße rechts
|
name: Fenster Straße rechts
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -571,6 +610,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b151803
|
state: zigbee2mqtt/0x00158d008b151803
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_kueche_strasse_links
|
- device_id: kontakt_kueche_strasse_links
|
||||||
|
homekit_aid: 41
|
||||||
name: Fenster Straße links
|
name: Fenster Straße links
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -579,6 +619,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b331d0b
|
state: zigbee2mqtt/0x00158d008b331d0b
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_patty_garten_rechts
|
- device_id: kontakt_patty_garten_rechts
|
||||||
|
homekit_aid: 42
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster Garten rechts
|
name: Fenster Garten rechts
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -587,6 +628,8 @@ devices:
|
|||||||
state: homegear/instance1/plain/18/1/STATE
|
state: homegear/instance1/plain/18/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_patty_garten_links
|
- device_id: kontakt_patty_garten_links
|
||||||
|
homekit_aid: 43
|
||||||
|
homekit_aid: 43
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster Garten links
|
name: Fenster Garten links
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -595,6 +638,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/22/1/STATE
|
state: homegear/instance1/plain/22/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_patty_strasse
|
- device_id: kontakt_patty_strasse
|
||||||
|
homekit_aid: 44
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster Straße
|
name: Fenster Straße
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -603,6 +647,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d000af457cf
|
state: zigbee2mqtt/0x00158d000af457cf
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_wolfgang_garten
|
- device_id: kontakt_wolfgang_garten
|
||||||
|
homekit_aid: 45
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster
|
name: Fenster
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -611,6 +656,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b3328da
|
state: zigbee2mqtt/0x00158d008b3328da
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_bad_oben_strasse
|
- device_id: kontakt_bad_oben_strasse
|
||||||
|
homekit_aid: 46
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster
|
name: Fenster
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -619,6 +665,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d008b333aec
|
state: zigbee2mqtt/0x00158d008b333aec
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: kontakt_bad_unten_strasse
|
- device_id: kontakt_bad_unten_strasse
|
||||||
|
homekit_aid: 47
|
||||||
type: contact
|
type: contact
|
||||||
name: Fenster
|
name: Fenster
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -627,6 +674,7 @@ devices:
|
|||||||
state: homegear/instance1/plain/44/1/STATE
|
state: homegear/instance1/plain/44/1/STATE
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_schlafzimmer
|
- device_id: sensor_schlafzimmer
|
||||||
|
homekit_aid: 48
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -635,6 +683,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d00043292dc
|
state: zigbee2mqtt/0x00158d00043292dc
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_wohnzimmer
|
- device_id: sensor_wohnzimmer
|
||||||
|
homekit_aid: 49
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -643,6 +692,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d0008975707
|
state: zigbee2mqtt/0x00158d0008975707
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_kueche
|
- device_id: sensor_kueche
|
||||||
|
homekit_aid: 50
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -651,6 +701,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d00083299bb
|
state: zigbee2mqtt/0x00158d00083299bb
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_arbeitszimmer_patty
|
- device_id: sensor_arbeitszimmer_patty
|
||||||
|
homekit_aid: 51
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -659,6 +710,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d0003f052b7
|
state: zigbee2mqtt/0x00158d0003f052b7
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_arbeitszimmer_wolfgang
|
- device_id: sensor_arbeitszimmer_wolfgang
|
||||||
|
homekit_aid: 52
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -667,6 +719,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d000543fb99
|
state: zigbee2mqtt/0x00158d000543fb99
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_bad_oben
|
- device_id: sensor_bad_oben
|
||||||
|
homekit_aid: 53
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -675,6 +728,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d00093e8987
|
state: zigbee2mqtt/0x00158d00093e8987
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_bad_unten
|
- device_id: sensor_bad_unten
|
||||||
|
homekit_aid: 54
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -683,6 +737,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d00093e662a
|
state: zigbee2mqtt/0x00158d00093e662a
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_flur
|
- device_id: sensor_flur
|
||||||
|
homekit_aid: 55
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -691,6 +746,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d000836ccc6
|
state: zigbee2mqtt/0x00158d000836ccc6
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_waschkueche
|
- device_id: sensor_waschkueche
|
||||||
|
homekit_aid: 56
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -699,6 +755,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d000449f3bc
|
state: zigbee2mqtt/0x00158d000449f3bc
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: sensor_sportzimmer
|
- device_id: sensor_sportzimmer
|
||||||
|
homekit_aid: 57
|
||||||
type: temp_humidity_sensor
|
type: temp_humidity_sensor
|
||||||
name: Thermometer
|
name: Thermometer
|
||||||
cap_version: temp_humidity_sensor@1.0.0
|
cap_version: temp_humidity_sensor@1.0.0
|
||||||
@@ -707,6 +764,7 @@ devices:
|
|||||||
state: zigbee2mqtt/0x00158d0009421422
|
state: zigbee2mqtt/0x00158d0009421422
|
||||||
features: {}
|
features: {}
|
||||||
- device_id: licht_spuele_kueche
|
- device_id: licht_spuele_kueche
|
||||||
|
homekit_aid: 58
|
||||||
name: Spüle
|
name: Spüle
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -717,6 +775,7 @@ devices:
|
|||||||
set: "shellies/shellyplug-s-DED4E4/relay/0/command"
|
set: "shellies/shellyplug-s-DED4E4/relay/0/command"
|
||||||
state: "shellies/shellyplug-s-DED4E4/relay/0"
|
state: "shellies/shellyplug-s-DED4E4/relay/0"
|
||||||
- device_id: putzlicht_kueche
|
- device_id: putzlicht_kueche
|
||||||
|
homekit_aid: 59
|
||||||
name: Putzlicht
|
name: Putzlicht
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -728,6 +787,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0xa4c138563834406c"
|
state: "zigbee2mqtt/0xa4c138563834406c"
|
||||||
set: "zigbee2mqtt/0xa4c138563834406c/set"
|
set: "zigbee2mqtt/0xa4c138563834406c/set"
|
||||||
- device_id: licht_schrank_esszimmer
|
- device_id: licht_schrank_esszimmer
|
||||||
|
homekit_aid: 60
|
||||||
name: Schrank
|
name: Schrank
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -738,6 +798,7 @@ devices:
|
|||||||
set: "shellies/schrankesszimmer/relay/0/command"
|
set: "shellies/schrankesszimmer/relay/0/command"
|
||||||
state: "shellies/schrankesszimmer/relay/0"
|
state: "shellies/schrankesszimmer/relay/0"
|
||||||
- device_id: licht_regal_wohnzimmer
|
- device_id: licht_regal_wohnzimmer
|
||||||
|
homekit_aid: 61
|
||||||
type: relay
|
type: relay
|
||||||
name: Regal
|
name: Regal
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -747,17 +808,8 @@ devices:
|
|||||||
topics:
|
topics:
|
||||||
set: "shellies/wohnzimmer-regal/relay/0/command"
|
set: "shellies/wohnzimmer-regal/relay/0/command"
|
||||||
state: "shellies/wohnzimmer-regal/relay/0"
|
state: "shellies/wohnzimmer-regal/relay/0"
|
||||||
- device_id: licht_flur_schrank
|
|
||||||
type: relay
|
|
||||||
name: Schrank
|
|
||||||
cap_version: "relay@1.0.0"
|
|
||||||
technology: shelly
|
|
||||||
features:
|
|
||||||
power: true
|
|
||||||
topics:
|
|
||||||
set: "shellies/schrankflur/relay/0/command"
|
|
||||||
state: "shellies/schrankflur/relay/0"
|
|
||||||
- device_id: licht_terasse
|
- device_id: licht_terasse
|
||||||
|
homekit_aid: 62
|
||||||
name: Terrasse
|
name: Terrasse
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -768,6 +820,7 @@ devices:
|
|||||||
set: "shellies/lichtterasse/relay/0/command"
|
set: "shellies/lichtterasse/relay/0/command"
|
||||||
state: "shellies/lichtterasse/relay/0"
|
state: "shellies/lichtterasse/relay/0"
|
||||||
- device_id: kugellampe_patty
|
- device_id: kugellampe_patty
|
||||||
|
homekit_aid: 63
|
||||||
name: Kugellampe Patty
|
name: Kugellampe Patty
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -779,6 +832,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0xbc33acfffe21f547"
|
state: "zigbee2mqtt/0xbc33acfffe21f547"
|
||||||
set: "zigbee2mqtt/0xbc33acfffe21f547/set"
|
set: "zigbee2mqtt/0xbc33acfffe21f547/set"
|
||||||
- device_id: kueche_fensterbank_licht
|
- device_id: kueche_fensterbank_licht
|
||||||
|
homekit_aid: 64
|
||||||
name: Fensterbank Küche
|
name: Fensterbank Küche
|
||||||
type: light
|
type: light
|
||||||
cap_version: "light@1.2.0"
|
cap_version: "light@1.2.0"
|
||||||
@@ -790,6 +844,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0xf0d1b8000017515d"
|
state: "zigbee2mqtt/0xf0d1b8000017515d"
|
||||||
set: "zigbee2mqtt/0xf0d1b8000017515d/set"
|
set: "zigbee2mqtt/0xf0d1b8000017515d/set"
|
||||||
- device_id: licht_kommode_schlafzimmer
|
- device_id: licht_kommode_schlafzimmer
|
||||||
|
homekit_aid: 65
|
||||||
name: Kommode Schlafzimmer
|
name: Kommode Schlafzimmer
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -800,6 +855,7 @@ devices:
|
|||||||
set: "cmnd/tasmota/04/POWER"
|
set: "cmnd/tasmota/04/POWER"
|
||||||
state: "stat/tasmota/04/POWER"
|
state: "stat/tasmota/04/POWER"
|
||||||
- device_id: licht_fensterbank_esszimmer
|
- device_id: licht_fensterbank_esszimmer
|
||||||
|
homekit_aid: 66
|
||||||
name: Fensterbank Esszimmer
|
name: Fensterbank Esszimmer
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -810,6 +866,7 @@ devices:
|
|||||||
set: "cmnd/tasmota/02/POWER"
|
set: "cmnd/tasmota/02/POWER"
|
||||||
state: "stat/tasmota/02/POWER"
|
state: "stat/tasmota/02/POWER"
|
||||||
- device_id: licht_schreibtisch_patty
|
- device_id: licht_schreibtisch_patty
|
||||||
|
homekit_aid: 67
|
||||||
name: Schreibtisch Patty
|
name: Schreibtisch Patty
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -820,6 +877,7 @@ devices:
|
|||||||
set: "cmnd/tasmota/03/POWER"
|
set: "cmnd/tasmota/03/POWER"
|
||||||
state: "stat/tasmota/03/POWER"
|
state: "stat/tasmota/03/POWER"
|
||||||
- device_id: kugeln_regal_flur
|
- device_id: kugeln_regal_flur
|
||||||
|
homekit_aid: 68
|
||||||
name: Kugeln Regal Flur
|
name: Kugeln Regal Flur
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -829,7 +887,8 @@ devices:
|
|||||||
topics:
|
topics:
|
||||||
set: "cmnd/tasmota/01/POWER"
|
set: "cmnd/tasmota/01/POWER"
|
||||||
state: "stat/tasmota/01/POWER"
|
state: "stat/tasmota/01/POWER"
|
||||||
- device_id: schrank_flur_haustür
|
- device_id: schrank_flur_haustuer
|
||||||
|
homekit_aid: 69
|
||||||
name: Schrank Flur Haustür
|
name: Schrank Flur Haustür
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -840,6 +899,7 @@ devices:
|
|||||||
set: "cmnd/tasmota/05/POWER"
|
set: "cmnd/tasmota/05/POWER"
|
||||||
state: "stat/tasmota/05/POWER"
|
state: "stat/tasmota/05/POWER"
|
||||||
- device_id: gartenlicht_vorne
|
- device_id: gartenlicht_vorne
|
||||||
|
homekit_aid: 70
|
||||||
name: Gartenlicht vorne
|
name: Gartenlicht vorne
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -851,6 +911,7 @@ devices:
|
|||||||
state: "stat/tasmota/06/POWER"
|
state: "stat/tasmota/06/POWER"
|
||||||
|
|
||||||
- device_id: power_relay_caroutlet
|
- device_id: power_relay_caroutlet
|
||||||
|
homekit_aid: 71
|
||||||
name: Car Outlet
|
name: Car Outlet
|
||||||
type: relay
|
type: relay
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -861,6 +922,7 @@ devices:
|
|||||||
set: "IoT/Car/Control"
|
set: "IoT/Car/Control"
|
||||||
state: "IoT/Car/Control/State"
|
state: "IoT/Car/Control/State"
|
||||||
- device_id: powermeter_caroutlet
|
- device_id: powermeter_caroutlet
|
||||||
|
homekit_aid: 72
|
||||||
name: Car Outlet
|
name: Car Outlet
|
||||||
type: three_phase_powermeter
|
type: three_phase_powermeter
|
||||||
cap_version: "three_phase_powermeter@1.0.0"
|
cap_version: "three_phase_powermeter@1.0.0"
|
||||||
@@ -868,6 +930,7 @@ devices:
|
|||||||
topics:
|
topics:
|
||||||
state: "IoT/Car/Values"
|
state: "IoT/Car/Values"
|
||||||
- device_id: sensor_caroutlet
|
- device_id: sensor_caroutlet
|
||||||
|
homekit_aid: 73
|
||||||
name: Car Outlet
|
name: Car Outlet
|
||||||
type: contact
|
type: contact
|
||||||
cap_version: contact_sensor@1.0.0
|
cap_version: contact_sensor@1.0.0
|
||||||
@@ -876,6 +939,7 @@ devices:
|
|||||||
state: IoT/Car/Feedback/State
|
state: IoT/Car/Feedback/State
|
||||||
|
|
||||||
- device_id: schranklicht_flur_vor_kueche
|
- device_id: schranklicht_flur_vor_kueche
|
||||||
|
homekit_aid: 74
|
||||||
name: Schranklicht Flur vor Küche
|
name: Schranklicht Flur vor Küche
|
||||||
type: light
|
type: light
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -886,6 +950,7 @@ devices:
|
|||||||
state: "zigbee2mqtt/0xf0d1b80000155a1f"
|
state: "zigbee2mqtt/0xf0d1b80000155a1f"
|
||||||
set: "zigbee2mqtt/0xf0d1b80000155a1f/set"
|
set: "zigbee2mqtt/0xf0d1b80000155a1f/set"
|
||||||
- device_id: deckenlampe_wohnzimmer
|
- device_id: deckenlampe_wohnzimmer
|
||||||
|
homekit_aid: 75
|
||||||
name: Deckenlampe Wohnzimmer
|
name: Deckenlampe Wohnzimmer
|
||||||
type: light
|
type: light
|
||||||
cap_version: "relay@1.0.0"
|
cap_version: "relay@1.0.0"
|
||||||
@@ -898,3 +963,94 @@ devices:
|
|||||||
set: "zigbee2mqtt/0x842e14fffea72027/set"
|
set: "zigbee2mqtt/0x842e14fffea72027/set"
|
||||||
|
|
||||||
|
|
||||||
|
- device_id: keller_flur_licht
|
||||||
|
homekit_aid: 76
|
||||||
|
name: Keller Flur Licht
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wago_modbus
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "pulsegen/command/10/21"
|
||||||
|
state: "pulsegen/status/10"
|
||||||
|
- device_id: waschkueche_licht
|
||||||
|
homekit_aid: 77
|
||||||
|
name: Waschküche Licht
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wago_modbus
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "pulsegen/command/8/22"
|
||||||
|
state: "pulsegen/status/8"
|
||||||
|
- device_id: werkstatt_licht
|
||||||
|
homekit_aid: 78
|
||||||
|
name: Werkstatt Licht
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wago_modbus
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "pulsegen/command/7/19"
|
||||||
|
state: "pulsegen/status/7"
|
||||||
|
- device_id: sportzimmer_licht
|
||||||
|
homekit_aid: 79
|
||||||
|
name: Sportzimmer Licht
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wago_modbus
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "pulsegen/command/9/20"
|
||||||
|
state: "pulsegen/status/9"
|
||||||
|
- device_id: deckenlampe_patty
|
||||||
|
homekit_aid: 80
|
||||||
|
name: Deckenlampe Patty
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wago_modbus
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "pulsegen/command/4/16"
|
||||||
|
state: "pulsegen/status/4"
|
||||||
|
- device_id: regallampe_esszimmer
|
||||||
|
homekit_aid: 81
|
||||||
|
name: Regallampe Esszimmer
|
||||||
|
type: relay
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_wifi_relay
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
set: "IoT/WifiRelay1/State"
|
||||||
|
state: "IoT/WifiRelay1/State"
|
||||||
|
|
||||||
|
- device_id: herdlicht
|
||||||
|
homekit_aid: 82
|
||||||
|
name: Herdlicht
|
||||||
|
type: light
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: zigbee2mqtt
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
brightness: true
|
||||||
|
topics:
|
||||||
|
state: "zigbee2mqtt/herdlicht"
|
||||||
|
set: "zigbee2mqtt/herdlicht/set"
|
||||||
|
|
||||||
|
- device_id: regallicht_kueche
|
||||||
|
homekit_aid: 83
|
||||||
|
name: Regallicht
|
||||||
|
type: light
|
||||||
|
cap_version: "relay@1.0.0"
|
||||||
|
technology: hottis_led_stripe
|
||||||
|
features:
|
||||||
|
power: true
|
||||||
|
topics:
|
||||||
|
state: "IoT/RgbLedStripeKitchen/ColorCommand"
|
||||||
|
set: "IoT/RgbLedStripeKitchen/ColorCommand"
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
version: 1
|
version: 1
|
||||||
groups:
|
groups:
|
||||||
- id: "kueche_lichter"
|
- id: "kueche_lichter"
|
||||||
name: "Küche – alle Lampen"
|
name: "Küche – alle Lampen ausser Putzlicht"
|
||||||
selector:
|
device_ids:
|
||||||
type: "light"
|
- kueche_deckenlampe
|
||||||
room: "Küche"
|
- licht_spuele_kueche
|
||||||
|
- herdlicht
|
||||||
|
- kueche_fensterbank_licht
|
||||||
|
- regallicht_kueche
|
||||||
capabilities:
|
capabilities:
|
||||||
power: true
|
power: true
|
||||||
brightness: true
|
brightness: true
|
||||||
@@ -16,21 +19,25 @@ groups:
|
|||||||
capabilities:
|
capabilities:
|
||||||
power: true
|
power: true
|
||||||
|
|
||||||
- id: "schlafzimmer_lichter"
|
|
||||||
name: "Schlafzimmer – alle Lampen"
|
|
||||||
selector:
|
|
||||||
type: "light"
|
|
||||||
room: "Schlafzimmer"
|
|
||||||
capabilities:
|
|
||||||
power: true
|
|
||||||
brightness: true
|
|
||||||
|
|
||||||
- id: "schlafzimmer_schlummer_licht"
|
- id: "schlafzimmer_schlummer_licht"
|
||||||
name: "Schlafzimmer – Schlummerlicht"
|
name: "Schlafzimmer – Schlummerlicht"
|
||||||
device_ids:
|
device_ids:
|
||||||
- bettlicht_patty
|
- bettlicht_patty
|
||||||
- bettlicht_wolfgang
|
- bettlicht_wolfgang
|
||||||
- medusalampe_schlafzimmer
|
- medusalampe_schlafzimmer
|
||||||
|
- licht_kommode_schlafzimmer
|
||||||
|
capabilities:
|
||||||
|
power: true
|
||||||
|
brightness: true
|
||||||
|
|
||||||
|
- id: "arbeitslicht_patty"
|
||||||
|
name: "Patty – Arbeitslicht"
|
||||||
|
device_ids:
|
||||||
|
- schranklicht_hinten_patty
|
||||||
|
- schranklicht_vorne_patty
|
||||||
|
- leselampe_patty
|
||||||
|
- kugellampe_patty
|
||||||
|
- licht_schreibtisch_patty
|
||||||
capabilities:
|
capabilities:
|
||||||
power: true
|
power: true
|
||||||
brightness: true
|
brightness: true
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
rooms:
|
rooms:
|
||||||
- name: Schlafzimmer
|
- id: schlafzimmer
|
||||||
|
name: Schlafzimmer
|
||||||
devices:
|
devices:
|
||||||
- device_id: bettlicht_patty
|
- device_id: bettlicht_patty
|
||||||
title: Bettlicht Patty
|
title: Bettlicht Patty
|
||||||
@@ -33,7 +34,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 47
|
rank: 47
|
||||||
- name: Esszimmer
|
- id: esszimmer
|
||||||
|
name: Esszimmer
|
||||||
devices:
|
devices:
|
||||||
- device_id: deckenlampe_esszimmer
|
- device_id: deckenlampe_esszimmer
|
||||||
title: Deckenlampe Esszimmer
|
title: Deckenlampe Esszimmer
|
||||||
@@ -59,10 +61,10 @@ rooms:
|
|||||||
title: Stehlampe Esszimmer Schrank
|
title: Stehlampe Esszimmer Schrank
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 82
|
rank: 82
|
||||||
# - device_id: kleine_lampe_rechts_esszimmer
|
- device_id: regallampe_esszimmer
|
||||||
# title: kleine Lampe rechts Esszimmer
|
title: Regallampe Esszimmer
|
||||||
# icon: 💡
|
icon: 💡
|
||||||
# rank: 90
|
rank: 90
|
||||||
- device_id: licht_schrank_esszimmer
|
- device_id: licht_schrank_esszimmer
|
||||||
title: Schranklicht Esszimmer
|
title: Schranklicht Esszimmer
|
||||||
icon: 💡
|
icon: 💡
|
||||||
@@ -79,7 +81,8 @@ rooms:
|
|||||||
title: Kontakt Straße links
|
title: Kontakt Straße links
|
||||||
icon: 🪟
|
icon: 🪟
|
||||||
rank: 97
|
rank: 97
|
||||||
- name: Wohnzimmer
|
- id: wohnzimmer
|
||||||
|
name: Wohnzimmer
|
||||||
devices:
|
devices:
|
||||||
- device_id: lampe_naehtischchen_wohnzimmer
|
- device_id: lampe_naehtischchen_wohnzimmer
|
||||||
title: Lampe Naehtischchen Wohnzimmer
|
title: Lampe Naehtischchen Wohnzimmer
|
||||||
@@ -121,7 +124,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 138
|
rank: 138
|
||||||
- name: Küche
|
- id: kueche
|
||||||
|
name: Küche
|
||||||
devices:
|
devices:
|
||||||
- device_id: kueche_deckenlampe
|
- device_id: kueche_deckenlampe
|
||||||
title: Küche Deckenlampe
|
title: Küche Deckenlampe
|
||||||
@@ -135,10 +139,19 @@ rooms:
|
|||||||
title: Küche Putzlicht
|
title: Küche Putzlicht
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 143
|
rank: 143
|
||||||
|
excluded: true
|
||||||
- device_id: kueche_fensterbank_licht
|
- device_id: kueche_fensterbank_licht
|
||||||
title: Küche Fensterbank
|
title: Küche Fensterbank
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 144
|
rank: 144
|
||||||
|
- device_id: herdlicht
|
||||||
|
title: Herdlicht
|
||||||
|
icon: 💡
|
||||||
|
rank: 145
|
||||||
|
- device_id: regallicht_kueche
|
||||||
|
title: Regallicht Küche
|
||||||
|
icon: 💡
|
||||||
|
rank: 146
|
||||||
- device_id: thermostat_kueche
|
- device_id: thermostat_kueche
|
||||||
title: Kueche
|
title: Kueche
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
@@ -163,30 +176,35 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 155
|
rank: 155
|
||||||
- name: Arbeitszimmer Patty
|
- id: arbeitszimmer_patty
|
||||||
|
name: Arbeitszimmer Patty
|
||||||
devices:
|
devices:
|
||||||
- device_id: leselampe_patty
|
- device_id: leselampe_patty
|
||||||
title: Leselampe Patty
|
title: Leselampe Patty
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 160
|
rank: 160
|
||||||
- device_id: schranklicht_hinten_patty
|
- device_id: schranklicht_hinten_patty
|
||||||
title: Schranklicht hinten Patty
|
title: Schranklicht hinten
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 170
|
rank: 170
|
||||||
- device_id: schranklicht_vorne_patty
|
- device_id: schranklicht_vorne_patty
|
||||||
title: Schranklicht vorne Patty
|
title: Schranklicht vorne
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 180
|
rank: 180
|
||||||
- device_id: kugellampe_patty
|
- device_id: kugellampe_patty
|
||||||
title: Kugellampe Patty
|
title: Kugellampe
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 181
|
rank: 181
|
||||||
- device_id: licht_schreibtisch_patty
|
- device_id: licht_schreibtisch_patty
|
||||||
title: Licht Schreibtisch Patty
|
title: Licht Schreibtisch
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 182
|
rank: 182
|
||||||
|
- device_id: deckenlampe_patty
|
||||||
|
title: Deckenlampe
|
||||||
|
icon: 💡
|
||||||
|
rank: 183
|
||||||
- device_id: thermostat_patty
|
- device_id: thermostat_patty
|
||||||
title: Thermostat Patty
|
title: Thermostat
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 185
|
rank: 185
|
||||||
- device_id: kontakt_patty_garten_rechts
|
- device_id: kontakt_patty_garten_rechts
|
||||||
@@ -205,7 +223,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 189
|
rank: 189
|
||||||
- name: Arbeitszimmer Wolfgang
|
- id: arbeitszimmer_wolfgang
|
||||||
|
name: Arbeitszimmer Wolfgang
|
||||||
devices:
|
devices:
|
||||||
- device_id: thermostat_wolfgang
|
- device_id: thermostat_wolfgang
|
||||||
title: Wolfgang
|
title: Wolfgang
|
||||||
@@ -223,7 +242,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 202
|
rank: 202
|
||||||
- name: Flur
|
- id: flur
|
||||||
|
name: Flur
|
||||||
devices:
|
devices:
|
||||||
- device_id: deckenlampe_flur_oben
|
- device_id: deckenlampe_flur_oben
|
||||||
title: Deckenlampe Flur oben
|
title: Deckenlampe Flur oben
|
||||||
@@ -237,7 +257,7 @@ rooms:
|
|||||||
title: Licht oben am Spiegel
|
title: Licht oben am Spiegel
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 230
|
rank: 230
|
||||||
- device_id: schrank_flur_haustür
|
- device_id: schrank_flur_haustuer
|
||||||
title: Schranklicht an der Haustür
|
title: Schranklicht an der Haustür
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 231
|
rank: 231
|
||||||
@@ -249,7 +269,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 235
|
rank: 235
|
||||||
- name: Sportzimmer
|
- id: sportzimmer
|
||||||
|
name: Sportzimmer
|
||||||
devices:
|
devices:
|
||||||
- device_id: sportlicht_regal
|
- device_id: sportlicht_regal
|
||||||
title: Sportlicht Regal
|
title: Sportlicht Regal
|
||||||
@@ -263,11 +284,16 @@ rooms:
|
|||||||
title: Sportlicht am Fernseher, Studierzimmer
|
title: Sportlicht am Fernseher, Studierzimmer
|
||||||
icon: 🏃
|
icon: 🏃
|
||||||
rank: 260
|
rank: 260
|
||||||
|
- device_id: sportzimmer_licht
|
||||||
|
title: Deckenlampe
|
||||||
|
icon: 💡
|
||||||
|
rank: 262
|
||||||
- device_id: sensor_sportzimmer
|
- device_id: sensor_sportzimmer
|
||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 265
|
rank: 265
|
||||||
- name: Bad Oben
|
- id: bad_oben
|
||||||
|
name: Bad Oben
|
||||||
devices:
|
devices:
|
||||||
- device_id: thermostat_bad_oben
|
- device_id: thermostat_bad_oben
|
||||||
title: Thermostat Bad Oben
|
title: Thermostat Bad Oben
|
||||||
@@ -281,7 +307,8 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 272
|
rank: 272
|
||||||
- name: Bad Unten
|
- id: bad_unten
|
||||||
|
name: Bad Unten
|
||||||
devices:
|
devices:
|
||||||
- device_id: thermostat_bad_unten
|
- device_id: thermostat_bad_unten
|
||||||
title: Thermostat Bad Unten
|
title: Thermostat Bad Unten
|
||||||
@@ -295,13 +322,20 @@ rooms:
|
|||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 282
|
rank: 282
|
||||||
- name: Waschküche
|
- id: waschkueche
|
||||||
|
name: Waschküche
|
||||||
devices:
|
devices:
|
||||||
- device_id: sensor_waschkueche
|
- device_id: sensor_waschkueche
|
||||||
title: Temperatur & Luftfeuchte
|
title: Temperatur & Luftfeuchte
|
||||||
icon: 🌡️
|
icon: 🌡️
|
||||||
rank: 290
|
rank: 290
|
||||||
- name: Outdoor
|
- device_id: waschkueche_licht
|
||||||
|
title: Waschküche Licht
|
||||||
|
icon: 💡
|
||||||
|
rank: 340
|
||||||
|
|
||||||
|
- id: outdoor
|
||||||
|
name: Outdoor
|
||||||
devices:
|
devices:
|
||||||
- device_id: licht_terasse
|
- device_id: licht_terasse
|
||||||
title: Licht Terasse
|
title: Licht Terasse
|
||||||
@@ -311,19 +345,33 @@ rooms:
|
|||||||
title: Gartenlicht vorne
|
title: Gartenlicht vorne
|
||||||
icon: 💡
|
icon: 💡
|
||||||
rank: 291
|
rank: 291
|
||||||
- name: Garage
|
- id: garage
|
||||||
|
name: Garage
|
||||||
devices:
|
devices:
|
||||||
- device_id: power_relay_caroutlet
|
- device_id: power_relay_caroutlet
|
||||||
title: Ladestrom
|
title: Ladestrom
|
||||||
icon: ⚡
|
icon: ⚡
|
||||||
rank: 310
|
rank: 310
|
||||||
- device_id: sensor_caroutlet
|
- device_id: sensor_caroutlet
|
||||||
title: Kabelstatus
|
title: Schützzustand
|
||||||
icon: 🔌
|
icon: 🔌
|
||||||
rank: 315
|
rank: 315
|
||||||
- device_id: powermeter_caroutlet
|
- device_id: powermeter_caroutlet
|
||||||
title: Messwerte
|
title: Messwerte
|
||||||
icon: 📊
|
icon: 📊
|
||||||
rank: 320
|
rank: 320
|
||||||
|
- id: keller
|
||||||
|
name: Keller
|
||||||
|
devices:
|
||||||
|
- device_id: keller_flur_licht
|
||||||
|
title: Keller Flur Licht
|
||||||
|
icon: 💡
|
||||||
|
rank: 330
|
||||||
|
- device_id: werkstatt_licht
|
||||||
|
title: Werkstatt Licht
|
||||||
|
icon: 💡
|
||||||
|
rank: 350
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class DeviceTile(BaseModel):
|
|||||||
title: Display title for the device
|
title: Display title for the device
|
||||||
icon: Icon name or emoji for the device
|
icon: Icon name or emoji for the device
|
||||||
rank: Sort order within the room (lower = first)
|
rank: Sort order within the room (lower = first)
|
||||||
|
excluded: Optional flag to exclude device from certain operations
|
||||||
"""
|
"""
|
||||||
|
|
||||||
device_id: str = Field(
|
device_id: str = Field(
|
||||||
@@ -40,16 +41,27 @@ class DeviceTile(BaseModel):
|
|||||||
ge=0,
|
ge=0,
|
||||||
description="Sort order (lower values appear first)"
|
description="Sort order (lower values appear first)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
excluded: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="Exclude device from bulk operations"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Room(BaseModel):
|
class Room(BaseModel):
|
||||||
"""Represents a room containing devices.
|
"""Represents a room containing devices.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
id: Unique room identifier (used for API endpoints)
|
||||||
name: Room name (e.g., "Wohnzimmer", "Küche")
|
name: Room name (e.g., "Wohnzimmer", "Küche")
|
||||||
devices: List of device tiles in this room
|
devices: List of device tiles in this room
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
id: str = Field(
|
||||||
|
...,
|
||||||
|
description="Unique room identifier"
|
||||||
|
)
|
||||||
|
|
||||||
name: str = Field(
|
name: str = Field(
|
||||||
...,
|
...,
|
||||||
description="Room name"
|
description="Room name"
|
||||||
|
|||||||
Reference in New Issue
Block a user