“Ich bin C-3PO, mein Dienstprogramm ist das Home-Assistant-Interface. Ich bin in über sechs Millionen Automationsformen versiert.”

— C-3PO, der endlich ein Update bekommt

Das Problem

Dienstagabend. Ich scrolle durch YouTube und sehe ein Video über Home Assistant 2026.7 — Performance-Verbesserungen, neues Z-Wave-Schema, Bluetooth-Auto-Scan, der ganze Kram.

Interessant. Nur läuft mein HA noch auf 2026.2.1.

Fünf Monate. Fünf Hauptversionen. Jede mit ihren eigenen Breaking Changes.

Der C-3PO meiner Smart-Home-Zentrale hatte seit Februar kein Update mehr gesehen. Zeit, den Protokolldroiden auf den neuesten Stand zu bringen.


Der Plan: Nur Core-Update, nicht OS (HAOS 17.1 bleibt erstmal). Direkter Sprung von 2026.2.1 auf 2026.7.1 — mit Snapshot-Sicherheitsnetz, versteht sich. Kein schrittweises Version-für-Version-Upgrade, das macht Core selbst beim Start intern.


Phase 1: Analyse — was erwartet mich?

Bevor ich den Reset-Knopf drücke, will ich wissen, was auf mich zukommt. Home Assistant stellt dafür einen API-Call bereit, den die meisten nie nutzen: ha_get_updates.

# Über den Supervisor-API-Endpunkt die Release-Notes aller
# ausstehenden Versionen abrufen, gefiltert auf installierte Domains
curl -s -H "Authorization: Bearer $SUPERVISOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"entity_id": "homeassistant", "include_release_notes": true}' \
  http://supervisor/core/api/services/homeassistant/check_config

Der Aufruf ist der falsche — richtig ist über den Supervisor:

# Alle Breaking Changes aus den Release-Notes extrahieren
curl -s http://supervisor/core/api/services/homeassistant/update \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" | jq '.release_notes'

Praktischer ist die direkte Nutzung des Supervisor API-Endpunkts:

# Verfügbare Core-Updates abfragen
curl -s http://supervisor/core/info \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" | jq '.data'

Breaking Changes pro Version

So sah mein Analyse-Spreadsheet aus — jede Breaking Change der Versionen 2026.3 bis 2026.7, gefiltert auf meine installierten Domains:

VersionBreaking ChangeBetrifft mich?Grund
2026.3mqtt.agent entferntLäuft auf Embedded MQTT
2026.3history_stats MindestzeitraumAlle >1h
2026.4BMW Connected Drive entfernt⚠️ FALSCHER ALARMGarage nutzt VLinker BLE, nicht Cloud
2026.5core.update_entity entfernt⚠️ Bereits deaktiviertWar seit 2025 deprecated
2026.6Bluetooth Auto-Scan geändertBLE Monitor nutzt eigenen aioblescan-HCI
2026.7Z-Wave Schema 49 Pflicht⚠️ Bereits erfülltZ-Wave JS 3.10.0 / UI 11.21.0

Zwei “Blocker” waren also gar keine:

  1. BMW Connected Drive (2026.4): Der wird abgeschaltet, aber ich nutze den gar nicht. Die Garage trackt über VLinker BLE — ein ESP32 der die BT-Signale des Autos erfasst und per MQTT an HA schickt. Keine Cloud-Integration.
  2. Z-Wave Schema 49 (2026.7): Klingt nach Zwangsmigration. Ich checke meine Z-Wave-JS-Version: 3.10.0 — Schema 49 wird seit 3.9.x unterstützt. Z-Wave JS UI auf 11.21.0. Alles bestens.

Der Rest: Template-Sensoren sind alle im modernen template:-Stil (nicht Legacy), core.update_entity war längst deaktiviert. Grün.


Phase 2: Vorbereitung

Spook deaktivieren (kritisch!)

Spook ist ein geniales Tool für HA-Debugging — aber es monkeypatcht HA-internals. Bei einem Core-Update über fünf Versionen ist die Wahrscheinlichkeit hoch, dass Spook v4 startup-fail macht und den ganzen Core mitreißt.

# Spook-Ordner umbenennen — HACS lässt ihn sonst nach einem Restart wieder aktivieren
mv /config/custom_components/spook /config/custom_components/spook_DISABLED

Disk-Speicher freiräumen

Mein droide-c3po (die HA-VM auf Proxmox) hatte 90 % Disk-Belegung — zu knapp für ein Upgrade.

# Docker-Images aufräumen — alte Zwischen-Images, dangling layers
docker image prune -a

# Ergebnis: 90 % → 80 %, ~4 GB frei

Warum nicht früher gemacht? Weil es funktioniert hat. Ein Klassiker.

Proxmox ZFS-Snapshot

# Vor dem Upgrade: einen ZFS-Snapshot der ganzen VM
zfs snapshot -r rpool/data/vm-100-disk-0@vor_update_2026_7

Damit kann ich die gesamte VM auf den Stand vor dem Update zurückrollen — Core-Update hin oder her, der Snapshot ist OS-agnostisch und unzerstörbar.


Phase 3: Das Upgrade — API-First, ohne UI

Home Assistant bietet zwei Wege für ein Core-Update: UI-Klicken (Settings → System → Updates) oder API. Ich wähle die API — sie ist reproduzierbar, headless-fähig und übersteht einen WebSocket-Disconnect.

Warum ist das wichtig? Wenn ich das Update über die Web-UI starte und der MCP-Addon (der auf demselben HA-Container läuft) während des Neustarts die Verbindung verliert — kein Problem mit der API. Der Supervisor läuft getrennt vom Core.

# Core-Update auf 2026.7.1 via Supervisor API
curl -s -X POST http://supervisor/core/update \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"version": "2026.7.1", "background": true}'

Der background: true-Parameter bedeutet: Der Supervisor startet das Update und meldet sich asynchron zurück. HA erstellt automatisch ein Backup bevor es den Core aktualisiert — das ist eingebaute Safety, kein Extra-Schritt.

Nach dem Restart: Home Assistant Core 2026.7.1 steht. Config-Check: sauber. Logs: keine setup_error, ERROR oder CRITICAL.

Spook v5 installieren

# Nach dem Core-Update: Spook-Ordner löschen (alt war disabled) und neu installieren
rm -rf /config/custom_components/spook_DISABLED
# HACS-Installation von Spook v5.0.0 über die UI
# Spook-Inverse-Symlink setzen (wenn genutzt)
ln -s /config/custom_components/spook/inverse /config/custom_components/spook_inverse

Zweiter Restart, zweite Verifikation: Spook v5 geladen — Service-Domain spook ist da, random_fail und boo funktionieren, homeassistant.ignore_all_discovered aktiv.

Snapshot nach dem Update

# Nach erfolgreichem Update: zweiten Snapshot setzen
zfs snapshot -r rpool/data/vm-100-disk-0@nach_update_2026_7_ok

Snapshots während des Upgrade-Fensters:

  1. vor_update_2026_7 — vor dem Core-Update, mit Spook deaktiviert
  2. Automatisches HA-Backup — erstellt vom Supervisor beim Update
  3. nach_update_2026_7_ok — nach erfolgreichem Update, mit Spook v5

Dreifaches Netz. Wenn du kein ZFS hast: Proxmox Backup Server macht den Job genauso.


Phase 4: Post-Upgrade-Verifikation

Ein Core-Update ist erst fertig, wenn ich weiß, dass alles tut, was vorher getan hat — nicht nur, dass HA gestartet ist.

# 1. Core-Version prüfen
curl -s http://supervisor/core/info \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" | jq '.data.version'
# → "core-2026.7.1"

# 2. Config-Check bestanden?
curl -s -X POST http://supervisor/core/api/services/homeassistant/check_config \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN"
# → valid

# 3. Log-Check: ERRORs?
curl -s http://supervisor/core/api/error_log \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN"
# → leer (keine Errors)

Meine persönliche Critical-Service-Checkliste (nach jedem Update):

ServiceCheckStatus
GaragentorTür-Sensor + Sicherheitsautomation aktiv
7 Bike-AutomationenAlle aktiv (Tür-offen-Erinnerung, Helm-Check, etc.)
BLE Device Trackersensor.c3po_ble_status vorhanden
Tasmota NachtmodusSchaltet um 22 Uhr korrekt
Tasmota SolarWechselrichter-Daten live
Yamaha ReceiverZone 2 im Büro spielt
Zigbee MeshAlle 50+ Router/Endgeräte erreichbar
Music AssistantLäuft, Bibliothek vollständig

Phase 5: Die Überraschungen — was ich nicht erwartet hatte

Jedes Upgrade bringt Dinge ans Licht, die vorher sauber unter der Oberfläche lagen. Dieses Mal waren es vier.

1. Roborock: Reauth nach Core-Update

Nach dem Neustart: Roborock-Integration zeigt „Erneut anmelden". Der Cloud-Token war durch das Update ungültig geworden.

Der Reauth-Flow über die REST-API (headless, weil HA auf dem Rechner in meinem Server-Rack läuft und niemand vor dem Bilderechner sitzt):

// 1. Roborock-Reauth triggern
POST /api/services/roborock/reauth
{}

// 2. Email-Code anfordern (an user@example.com gesendet — 
//    leia.organa@rebellion-base.net in meinem Fall)
//    → Code per Mail abgerufen
//    → Als Sensor in HA ablegen für den nächsten Step

// 3. Code im Reauth-Flow verwenden
POST /api/services/roborock/reauth_confirm
{
  "code": "123456"
}

// 4. Prüfen
GET /api/states/vacuum.roborock_s7
// → online, available: true

Funktioniert. Der Haken: Man braucht Zugriff auf das Postfach das bei Roborock hinterlegt ist, um den Code zu sehen. In meinem Fall lag die Mail im grommunio-Postfach auf dem separaten Mailserver (executor.rebellion.local). Also ssh auf den Mailserver, Mail lesen, Code in HA REST-API-Sensor senden, fertig.

2. Roborock Segment Cleaning — seit Monaten tot

Das war der interessanteste Fund: vacuum_clean_segment existiert nicht mehr. Der Service wurde irgendwann um 2025.08 aus dem Roborock-Integration entfernt.

Die Shell-Bereinigung in 7 meiner Automationen nutzte ihn:

# ALT (funktioniert nicht mehr)
action:
  service: vacuum_clean_segment
  target:
    entity_id: vacuum.roborock_s7
  data:
    segments: [16]

Ersatz:

# NEU (funktioniert)
action:
  service: vacuum.send_command
  target:
    entity_id: vacuum.roborock_s7
  data:
    command: app_segment_clean
    params: { segment_ids: [16], repeat: 1 }

Wichtig: Die Segment-IDs nicht raten! Ich habe sie direkt aus dem Roborock-Integration-Code gezogen:

# Auf dem HA-Host: Segment-IDs aus dem Roborock-Component-Code extrahieren
grep -r "segment" /config/custom_components/roborock/vacuum.py | head -5

In der Datei homeassistant/components/roborock/vacuum.py:318 sind die erlaubten segment_ids definiert. Nicht aus der App oder einem Screenshot geraten — die App zeigt visuelle Segmente, die intern andere IDs haben können.

3. HAOS 18.1: Kernel-Update unbemerkt mitgenommen

Irgendwann zwischen den beiden Restarts hat der Supervisor auch HAOS 17.1 → 18.1 aktualisiert. Kernel von 6.12.67 auf 6.18.37.

Mein erster Gedanke: BLE Stick tot (RTL8761BU — berüchtigt für Kernel-Regressionen).

Zweiter Gedanke: Testen.

# BLE-Adapter prüfen
hciconfig -a
# hci0: Type: Primary, BD Address: AA:BB:CC:DD:EE:FF
# UP RUNNING
# Features: 0xff 0xff 0xff...

# Signalstärke im BLE Monitor UI prüfen
# → Alle Xiaomi-Sensoren liefern Daten, RSSI normal

Läuft sauber. Glück gehabt — nicht jedes Kernel-Update überlebt ein RTL8761BU so elegant.

4. Z-Wave Mesh: ein Node fiel raus

Nach dem OS-Reboot initialisiert der Z-Wave-Controller neu — das triggert eine vollständige Mesh-Neuaufbau.

Alle 7 Nodes initialisiert, aber einer (Garagentor Shelly Wave 1PM) blieb offline: "No ACK"-Error auf dem Controller.

In HA 2026.7 wurden die Z-Wave-Heal/Re-build-Services entfernt (nur noch Z-Wave JS UI unterstützt das). Fix:

  1. Shelly Wave 1PM stromlos schalten — Sicherung im Unterverteiler für eine Minute raus.
  2. Nach Wiedereinschalten: Der Shelly sendet einen NIF (Node Information Frame) — der Controller nimmt ihn sofort wieder auf.
  3. Mesh-Nachbarschaftsliste wird automatisch aktualisiert.
# Prüfen ob Mesh vollständig
curl -s http://zwave-js-ui:8091/api/nodes \
  -H "Authorization: Bearer $ZWAVE_TOKEN" | jq '.[].status'
# → alle "Alive"

Kein Heal nötig. Power-Cycle des stromlosen Geräts reicht in 90 % der Fälle.

5. (Bonus) BLE-Interferenz — ein alter Hut, neu entdeckt

Der BLE-Stick (RTL8761BU) lieferte nach dem Update unverändert schwache Signale: ~ -84 dBm auf 3 Meter durch zwei Wände. Erwartet wären -55 bis -65 dBm für diese Distanz.

Die Ursache ist kein Update-Effekt, aber sie wurde beim Durchchecken wieder bewusst:

BLE-Stick, Zigbee-Dongle (Z-Wave ist USB-Seriell) und das CP2102-UART für den ESP-Flasher hängen alle am selben xHCI-USB-Controller der VM.

Das Problem ist 2.4-GHz-Koexistenz + Breitband-Interferenz auf dem USB-Root-Controller. Selbst ein USB-Verlängerungskabel hilft nicht — die Interferenz koppelt am USB-Root, nicht in der Luft. Der einzige Fix: den BLE-Stick an einen separaten USB-Controller hängen (zweite USB-Karte, oder PCIe-Passthrough eines dedizierten USB-Controllers).

War wichtig als Erkenntnis, hat aber nichts mit dem Update zu tun — und ich dokumentiere es hier als “Prüfpunkt fürs nächste Mal”.


Was ist garantierter Unsinn

Fünf Dinge, die ich vor diesem Upgrade geglaubt habe und die sich als falsch herausgestellt haben:

MythosRealität
„Du musst Version für Version upgraden, sonst explodiert alles"Falsch. Der Core macht beim Start eine interne Durchlauf-Migration. Ob du von 2026.2 → 2026.7 oder von 2026.4 → 2026.7 kommst — der Code migriert sauber. Einzige Ausnahme: Wenn eine Zwischenversion ein Datenbankschema ändert, das der alte Code nicht lesen kann. Aber das patcht der Core selbst.
„Ohne UI-Klick geht kein Upgrade"Falsch. Die Supervisor API (und die REST API des Core) können alles, was die UI kann. curl ist reproduzierbar, protokollierbar und überlebt WebSocket-Abrisse.
„Breaking Changes = dein Setup geht kaputt"Falsch. Breaking Changes betreffen meist deprecated Features, die du längt ersetzt hast. Die Release Notes lesen > panisch auf Version X bleiben.
„Ein Snapshot reicht"Falsch. Ich hatte drei Snapshots im Fenster (vor Update, automatisches HA-Backup, nach Update). Der Witz: Zurückgerollt hab ich gar nichts — aber hätte ich müssen, wäre einer allein wenig. Was wenn der Snapshot selbst korrupt ist?
„Upgrade auf neueste Version = Feature-Gewinn"Teils teils. Ich habe keine einzige der 2026.7-Features aktiv genutzt. Der Upgrade-Lohn war Sicherheit (aktueller Code, weniger CVEs), nicht neue Funktionen. Das muss man sich bewusst machen.

Design-Entscheidungen

1. API-First statt UI-Click

Die Supervisor-API ist der bessere Weg für jedes Upgrade — sie ist scriptbar, loggt die Requests, und der background: true-Modus erlaubt paralleles Arbeiten. Das MCP-WebSocket-Addon bricht beim Core-Restart ab? Egal, der Supervisor läuft weiter.

2. Release Notes als Code

Der API-Call ha_get_updates(include_release_notes=True) ist besser als YouTube-Videos. Ein Video zeigt die Kirsche obendrauf; die Release Notes zeigen, was unten wegbricht. Immer als primäre Quelle nehmen.

3. Mehrere Snapshots im Fenster

Drei Snapshots (vor, automatisch, nach) sind kein Overkill. Der vor-Snapshot ist die VM-Ebene (rollt OS + Core komplett zurück). Das automatische HA-Backup ist App-Ebene. Der nach-Snapshot ist die neue Baseline. Mit ZFS sind Snapshots kostenlos (nur Metadaten).

4. Spook-deaktivieren-dann-migrieren

Spook vor dem Update deaktivieren, Core updaten, Spook neu installieren. Das Pattern vermeidet Startup-Failures von custom_components, die auf alte API-Versionen angewiesen sind. Gilt nicht nur für Spook, sondern für alle Monkeypatch-Addons.


Checkliste für dein nächstes HA-Core-Upgrade

  • Release Notes gelesen: ha_get_updates(include_release_notes=True) für alle Versionen zwischen alt und neu, gefiltert auf installierte Domains
  • Custom Components gescheckt: Welche monkeypatchen HA-internals? (Spook, HACS custom_repo, etc.) → deaktivieren vor Update
  • Disk-Speicher: docker image prune -a, mindestens 30 % frei
  • Snapshot vorher: ZFS/Proxmox/PBS-Snapshot der gesamten VM
  • Update über API statt UI: POST /core/update {background: true} — reproduzierbar, disconnect-resistent
  • Nach dem Update: Core-Version + Config-Check + Logs (0 Errors) prüfen
  • Custom Components reaktivieren: Neu installieren, Restart, auf setup_errors prüfen
  • HACS-Updates: Alle custom components und Cards aktualisieren (10+ bei mir)
  • Kritische Automations-Checkliste abhaken: Jede Automation die Geld/Sicherheit/Wohlfühlfaktor betrifft (Garage, Alarme, Heizung)
  • Cloud-Reauth prüfen: Roborock, Bosch, Tuya, etc. — Cloud-Token können nach Update ungültig werden
  • Z-Wave/Zigbee Mesh prüfen: Alle Nodes alive? Fallen Geräte nach Controller-Neustart raus?
  • Snapshot nachher: Neue Baseline setzen
  • Verification-Log schreiben: Was wurde geprüft? Was war anders als erwartet?

Verifikation

# 1. Core-Version bestätigen
curl -s http://supervisor/core/info \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" | jq '.data.version'
# → "core-2026.7.1"

# 2. HACS-Übersicht aller custom components
curl -s http://supervisor/core/api/states \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN" | \
  jq '.[] | select(.entity_id | startswith("sensor.hacs")) | .state'

# 3. HA-Log auf Fehler scannen
curl -s http://supervisor/core/api/error_log \
  -H "Authorization: Bearer $SUPERVISOR_TOKEN"
# → leer ist gut

# 4. Z-Wave-Status
curl -s -H "Authorization: Bearer $ZWAVE_TOKEN" \
  http://zwave-js-ui:8091/api/nodes | jq '[.[] | {id: .id, status: .status}]'

# 5. Alle Automations-Calls des Roborock-Segment-Cleanings checken
grep -rn "vacuum_clean_segment" /config/automations.yaml
# → keine Treffer mehr (alle auf send_command migriert)

Lessons Learned

  • Breaking Changes lesen ≠ Setup kaputt. Zwei meiner “Blocker” waren keine. Die Release Notes haben mir trotzdem die Ruhe gegeben, das Update durchzuziehen — weil ich jede Zeile vorher gesehen hatte.
  • Service-Entfernungen leben lange im Schatten. Der vacuum_clean_segment-Service war seit fast einem Jahr weg, und keiner meiner 7 Automations-Workflows hatte das gemerkt (weil sie einfach nichts getan haben, ohne dass es auffiel). Ein ha_get_services-Diff vor/nach Update deckt das auf.
  • API ist besser als UI. Klingt nach Entwickler-Gehabe, aber die API loggt Requests, ist reproduzierbar, und überlebt Verbindungsabbrüche. Ein curl-Befehl in den Session-Notes ist mehr wert als drei Screenshots.
  • Snapshots sind kein Backup, aber ein gutes Netz. ZFS-Snapshots sind sekundenschnell und kosten fast keinen Speicher. Drei Stück im Upgrade-Fenster sind kein Overhead — sie sind das Sicherheitsnetz, das du nicht brauchst, bis du es brauchst.

Referenzen