🧬Datenmodell
Vom Funkstick bis zur Zahl im Dashboard: Wie Home Assistant Integrationen, Geräte und Entitäten ordnet – und was genau in einem State-Objekt steht.
🪜Die Kette: Integration → Config Entry → Gerät → Entität
Integration zha (Code im Core: homeassistant/components/zha)
│
└─ Config Entry „Zigbee-Stick (USB)“ ← eingerichtet über UI / Discovery
│
├─ Gerät „Wohnzimmer Decke“ ← Device Registry (Hersteller, Modell, Area)
│ └─ Entität light.wohnzimmer_decke ← Entity Registry (unique_id ↔ entity_id)
│ └─ State on · {brightness: 255, …} ← State Machine (aktueller Wert)
│
└─ Gerät „Flur Bewegungsmelder“
├─ Entität binary_sensor.flur_bewegung
└─ Entität sensor.flur_bewegungsmelder_batterie (entity_category: diagnostic)input_boolean, counter, timer), sun.sun oder Template-Sensoren haben kein Gerät. Ohne unique_id landet eine Entität gar nicht in der Registry – dann lässt sie sich in der UI nicht bearbeiten.🗂️Musterhaus-Explorer
light.wohnzimmer_decke
Entität der Plattform „zha“. Oben der Eintrag in der Entity Registry (dauerhaft, .storage), unten das State-Objekt in der State Machine (flüchtig, aktuelle Werte).
{"entity_registry": {"labels": ["nachtmodus"],"has_entity_name": true,"name": null,"entity_id": "light.wohnzimmer_decke","unique_id": "0a:bc:de:01:00:00:00:a1-11","platform": "zha","device_id": "dev_wz_decke","config_entry_id": "01JCE0ZHA000000000000000AA","original_name": null,"area_id": null,"→ area (effektiv)": "Wohnzimmer","→ gerät": "Wohnzimmer Decke"}}
{"entity_id": "light.wohnzimmer_decke","state": "off","attributes": {"supported_color_modes": ["color_temp"],"color_mode": null,"brightness": null,"min_color_temp_kelvin": 2202,"max_color_temp_kelvin": 6535,"friendly_name": "Wohnzimmer Decke","supported_features": 40},"last_changed": "2026-09-25T19:30:00.000+00:00","last_reported": "2026-09-25T19:30:00.000+00:00","last_updated": "2026-09-25T19:30:00.000+00:00","context": {"id": "01M3D0QHP0WPZBZBVX18BX041H","parent_id": null,"user_id": null}}
🔤Die entity_id: domain.object_id
Domain light: bekannte Entitäts-Plattform bzw. Helfer-Domain.
Regel aus homeassistant/core.py: nur a–z, 0–9 und „_“, kein „_“ am Anfang/Ende eines Teils, kein „__“. Die object_id entsteht meist aus Geräte- und Entitätsname (slugify: „Wohnzimmer Decke“ → wohnzimmer_decke, „Küche“ → kuche) und ist in der UI umbenennbar – die interne unique_id bleibt.
# Home Assistant Core (homeassistant/core.py), gekürzt
_OBJECT_ID = r"(?!_)[\da-z_]+(?<!_)"
_DOMAIN = r"(?!.+__)" + _OBJECT_ID
VALID_ENTITY_ID = re.compile(r"^" + _DOMAIN + r"\." + _OBJECT_ID + r"$")
def split_entity_id(entity_id: str) -> tuple[str, str]:
domain, _, object_id = entity_id.partition(".")
if not domain or not object_id:
raise ValueError(f"Invalid entity ID {entity_id}")
return domain, object_idlight, sensor, binary_sensor …) und damit, welche Actions passen: light.turn_on geht nur auf light.*. Die Integration (zha, mqtt …) steht nicht in der ID.📦Das State-Objekt
{
"entity_id": "sensor.wohnzimmer_temperatur",
"state": "21.4", ← Text, max. 255 Zeichen
"attributes": {
"state_class": "measurement",
"unit_of_measurement": "°C",
"device_class": "temperature",
"friendly_name": "Wohnzimmer Temperatur"
},
"last_changed": "2026-09-25T19:30:00.000+00:00", ← UTC
"last_reported": "2026-09-25T19:30:00.000+00:00",
"last_updated": "2026-09-25T19:30:00.000+00:00",
"context": {
"id": "01K6…", ← ULID
"parent_id": null, ← wer hat es ausgelöst?
"user_id": null ← Mensch? dann dessen ID
}
}| Feld | Bedeutung |
|---|---|
| state | Aktueller Zustand als Text: on/off, 21.4, open, unknown, unavailable … |
| attributes | Zusätzliche Eigenschaften: Einheit, device_class, Helligkeit, friendly_name … |
| last_changed | Zeit der letzten Zustandsänderung – nicht bei reinen Attributänderungen |
| last_updated | Zeit der letzten Änderung von Zustand oder Attributen |
| last_reported | Zeit des letzten Schreibens, auch ohne Änderung |
| context.id | Eindeutige ID dieser Änderung |
| context.parent_id | ID des auslösenden Contexts (z. B. Automation → Taster) |
| context.user_id | Benutzer, der es ausgelöst hat; bei Automationen None |
Zusätzlich abgeleitet: domain, object_id, name (aus friendly_name). Sonderzustände: unavailable (Integration erreicht das Gerät nicht), unknown (noch kein Wert).
⏱️Simulator: last_changed vs. last_updated vs. last_reported
last_changed21:00:00nur wenn sich der Zustand (state) ändertlast_updated21:00:00wenn sich Zustand ODER Attribute ändernlast_reported21:00:00bei jedem Schreiben – auch ohne Änderung (neu seit 2024)Was ist passiert?
Noch nichts – drücken Sie links einen Knopf. Zwischendurch „+10 s“, damit man die Zeitstempel unterscheiden kann.
last_changed. „Wann hat sich zuletzt irgendetwas getan?“ → last_updated. „Meldet sich der Sensor noch?“ → last_reported.🏢Areas, Floors, Labels
🚪 Area
Ein Raum oder Bereich. Geräte bekommen eine Area, ihre Entitäten erben sie – einzelne Entitäten dürfen abweichen (im Musterhaus: der Zähler-Helfer im Flur).
🏢 Floor
Etage mit Ebene (level). Eine Area gehört zu höchstens einem Floor. Seit 2024.4, zusammen mit Labels eingeführt.
🏷️ Label
Freie Schlagworte mit Farbe und Icon – quer zu allem, auch an Automationen. Beliebig viele pro Objekt.
actions:
- action: light.turn_off
target:
floor_id: obergeschoss # alle Lichter im Obergeschoss
- action: homeassistant.turn_off
target:
label_id: nachtmodus # alles mit dem Label „Nachtmodus“
- action: light.turn_on
target:
area_id: wohnzimmer
entity_id: light.flur # Ziele lassen sich kombinieren