[HowTo] X-Sense Melder (SBS50 + XS01-M / XC01-M / XH02-M) nativ via MQTT2

Begonnen von Blablubblaber, 12 Mai 2026, 20:17:01

Vorheriges Thema - Nächstes Thema

Blablubblaber

Hallo zusammen,

nach einigem Basteln und Optimieren möchte ich hier eine Anleitung teilen, wie man das X-Sense Rauchmelder-System nativ, lokal und komplett Cloud-frei über MQTT2 in FHEM integriert.

X-Sense hat mittlerweile eine native MQTT-Funktion in den SBS50 Basisstationen freigeschaltet. Das Problem beim direkten Einbinden über autocreate: FHEM wirft alle Melder in ein einziges Device, übermüllt die Readings mit Home-Assistant-Config-Daten und bei mehreren Basisstationen überschreiben sich die Melder gegenseitig.

Mit diesem Setup erreicht man folgendes:

  • Cloud-frei: Direkte, lokale MQTT-Verbindung.
  • Aufgeräumt: Die Basisstation arbeitet unsichtbar im Hintergrund als Router (bridgeRegexp).
  • Einzelgeräte: Jeder physikalische Melder bekommt ein eigenes FHEM-Device mit sauberen Readings (smokealarm_status, battery_status etc.).
  • Multi-Base Support: Mehrere Basisstationen stören sich nicht gegenseitig.
  • Rename-safe: Die Zuweisung erfolgt über die feste Hardware-ID ($DEF), man kann die Melder also völlig frei umbenennen (z.B. in XSense_Kueche), ohne dass die Zuordnung bricht.

Hier ist die Schritt-für-Schritt Anleitung:

Voraussetzung
  • FHEM MQTT2_SERVER ist aktiv (Port 1883).
  • In der X-Sense App bei der Basisstation in den Einstellungen unter "Mit Home Assistant verbinden" die IP eures FHEM-Servers eintragen (User/Passwort habe ich einfach einen . rein geschrieben da die Felder nicht leer bleiben dürfen) anschließend oben "MQTT-Verbindung" Aktivieren und unten auf "Speichern" klicken.

Schritt 1: Die Basisstation(en) zum "Router" machen
Sobald die Basisstation funkt, legt FHEM ein Device (z.B. SBS501500C04F) an. Wir löschen den Config-Müll, sperren autocreate und leiten die Signale an neue Geräte weiter.

Hinweis: Ersetzt in den folgenden Befehlen SBS501500C04F und SBS501500935D durch die tatsächliche ID eurer Basisstation!

Kopiert dies nacheinander in die FHEM-Kommandozeile:

deleteattr SBS501500C04F readingListdeletereading SBS501500C04F .*attr SBS501500C04F autocreate 0Die Magie passiert über bridgeRegexp. Signale von Basis 1 leiten wir an Geräte namens XSense_... weiter:

attr SBS501500C04F bridgeRegexp homeassistant/[^/]+/SBS501500C04F_([0-9A-F]+)/.*state:.* "XSense_$1"(Optional) Falls ihr eine 2. Basisstation habt (z.B. ID: SBS501500935D), macht ihr das Gleiche, leitet aber an XSense2_... weiter:

deleteattr SBS501500935D readingListdeletereading SBS501500935D .*attr SBS501500935D autocreate 0attr SBS501500935D bridgeRegexp homeassistant/[^/]+/SBS501500935D_([0-9A-F]+)/.*state:.* "XSense2_$1"Jetzt in der X-Sense App MQTT Deaktivieren und wieder Aktivieren, damit FHEM die Einzelgeräte (z.B. XSense_00000001, XSense2_00000001) anlegt!

Schritt 2: Die Melder filtern (readingList)
Jetzt filtern wir den JSON-Pfad sauber auf englische Begriffe runter und binden die Auswertung fest an die Hardware-DEF, um Übersprechen und Umbenennungs-Fehler zu vermeiden.

Für alle Melder der 1. Basisstation (XSense_...):
(Wichtig: Die ID der Basisstation SBS501500C04F im Pfad anpassen!)

attr XSense_.* autocreate 0attr XSense_.* readingList homeassistant/binary_sensor/SBS501500C04F_[^/]+/[^/]+/state:.* { my @t = split('/',$TOPIC);; my @p = split('_',$t[3]);; return if (InternalVal($NAME,"DEF","") !~ m/$p[1]$/);; return json2nameValue($EVENT, $p[-1].'_', $JSONMAP) }deletereading XSense_.* .*(Optional) Für alle Melder der 2. Basisstation (XSense2_...):


attr XSense2_.* autocreate 0attr XSense2_.* readingList homeassistant/binary_sensor/SBS501500935D_[^/]+/[^/]+/state:.* { my @t = split('/',$TOPIC);; my @p = split('_',$t[3]);; return if (InternalVal($NAME,"DEF","") !~ m/$p[1]$/);; return json2nameValue($EVENT, $p[-1].'_', $JSONMAP) }deletereading XSense2_.* .*Alles abspeichern:

saveDeaktiviert und Aktiviert nun noch mal MQTT in der X-Sense App. Eure FHEM-Geräte haben jetzt wunderschöne Readings wie smokealarm_status, online_status oder battery_status.

Schritt 3: Freies Umbenennen
Da die Filterung nun über InternalVal($NAME,"DEF","") läuft, könnt ihr die erzeugten Melder ab sofort kreuz und quer umbenennen, damit ihr wisst, wo es brennt. Das Routing bricht nicht ab!

rename XSense_00000001 XSense_Wohnzimmerrename XSense2_00000001 XSense2_FeWo_Schlafzimmer
Schritt 4: Globales Notify für den Feueralarm
Da die Readings jetzt bei allen Meldern absolut einheitlich heißen (egal ob Rauch, Hitze oder CO), reicht ein einziges, zentrales Notify für das ganze Haus. Dieser Code ist bereits für den FHEM-Optimierer angepasst, sodass keine Regex-Fehlermeldungen im Log landen.

define N_Haus_Feueralarm notify XSense.*:.*alarm_status:.*Detected|XSense.*:.*alarm_status:.*Cleared {
    my $melder = $NAME;;
    my $event = $EVENT;;
    my $status = $EVTPART1;;
   
    # Sensortyp extrahieren
    my ($typ) = $event =~ m/(smoke|co|heat)alarm_status/;;
    $typ //= "Unbekannt";;
   
    # Nachricht je nach Status anpassen
    my $msg;;
    if ($status =~ /Cleared/i) {
        $msg = "✅ ENTWARNUNG: Melder '$melder' meldet: $typ ($status)!";;
    } else {
        $msg = "🚨 ALARM! Melder '$melder' meldet: $typ ($status)!";;
    }
   
    fhem("set TelegramBot message $msg");;
}
(Natürlich TelegramBot durch euer eigenes Benachrichtigungs-Device ersetzen).

Testen lässt sich das notify mit
trigger XSense_FeWo_Schlafzimmer smokealarm_status: Detectedund
trigger XSense_FeWo_Schlafzimmer smokealarm_status: Cleared


Ich hoffe, diese Anleitung erspart dem ein oder anderen die nächtelange Fehlersuche mit Regulären Ausdrücken und Crosstalking-Effekten. Viel Spaß beim Nachbauen!