Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Praktische Anwendungen (Showcase)
  4. Fensterkontakte mit offen/geschlossen-Erkennung - preisgünstige Umsetzung

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    17
    1
    2.8k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    1.1k

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.4k

Fensterkontakte mit offen/geschlossen-Erkennung - preisgünstige Umsetzung

Geplant Angeheftet Gesperrt Verschoben Praktische Anwendungen (Showcase)
5 Beiträge 3 Kommentatoren 4.6k Aufrufe
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • S Offline
    S Offline
    stef.73
    schrieb am zuletzt editiert von
    #1

    Moin,

    im Bereich günstige Fensterkontakte habe ich hier bisher nur entweder Ideen gelesen, die

    • nicht wirklich günstig

    • nur offen-Meldung

    • selbstgelötet

    • mit Firmware-flashen

    umgesetzt sind. Das Alles wollte ich so nicht haben.

    Die jetzt umgesetzt Lösung funktioniert komplett ohne die oben genannten Punkte.

    Hardware

    • Fenstermelder:

    Zum Einsatz kommen günstige Reedkontakte mit EV1527-Chip. Meine sind vom Ali, 6Stck. für 22€ (versandkostenfrei). Link gerne per PN, ich weiss nicht ob das hier gern gesehen wird. Sie können auf/zu senden, sind recht klein, haben eine normale AA-Batterie.
    8645_433mhz-ev1527-two-way.png

    • Empfänger

    Ein USB-DVB-T-Empfänger mit RTL2832U. Gibt es bei Amazon für 10-15€, bei Ali deutlich billiger.

    • Ein freier USB-Port an einem unter Linux laufenden Rechner, der 24h an ist. Das kann der iobroker-Raspi sein, muss es aber nicht

    Wie funktionierts?

    Der Signalweg ist grob gesagt wie folgt:

    EV1527 –> RTL2832U --> RTL_433 (Software) --> MQTT --> iobroker --> abgewandeltes Fensterkontakte-Script

    Ergebnis:
    8645_screenshot_1.png vo

    Umsetzung

    • Der Empfänger wird über das geniale Programm RTL_433 eingebunden. Zu finden unter https://github.com/merbanan/rtl_433

    Die Installationsanleitung ist prima, könnte ich hier nur abschreiben. Hier: https://github.com/merbanan/rtl_433/blo … UILDING.md

    • Die Anbindung an MQTT ist nicht wie des öfteren zu lesen über mosquitto_pub. Das geht zwar, aber man bekommt halt nur die komplette JSON-Info in ein Topic im MQTT. Ziel ist aber ein netter Zustand der genau sagt ob auf oder zu..

    Es wird stattdessen eine abgewandelte Version des netten python-Scriptes von mervleun (https://github.com/mverleun/RTL433-to-mqtt) verwendet.

    Ich habe mir für die beiden Dateien ein Verzeichnis rtl2mqtt unter /usr/local/lib angelegt, aber alles wie man selber möchte...

    Es wird das python-Modul paho.mqtt benötigt:

    pip3 install paho-mqtt
    

    Sofern man noch kein pip3 installiert hat, ggf. vorneweg noch

    sudo apt install python3-pip
    sudo pip3 install wheel setuptools
    
    

    Hier die angepasste Version des Scriptes. Unterschiede:

    • Pro Fensterkontakt (also ID) wird ein eigenes Topic generiert. Das Original sendet alles unter demselben Topic.

    • Ich "höre" nur mit dem Decoder 30, der für die EV1527 gut ist. Wenn man weitere Sachen will, dann nimmt man -G in der Zeile mit dem rtl_433_cmd

    • Gleiche Zeilen werden nicht gesendet.

    ! Datei rtl2mqtt

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    >! import subprocess
    import sys
    import time
    import paho.mqtt.client as mqtt
    import os
    import json
    >! from config import *
    >! rtl_433_cmd = "/usr/local/bin/rtl_433 -R 30 -F json" # linux
    >! # Define MQTT event callbacks
    def on_connect(client, userdata, flags, rc):
        print("Connected with result code "+str(rc))
    >! def on_disconnect(client, userdata, rc):
        if rc != 0:
            print("Unexpected disconnection.")
    >! def on_message(client, obj, msg):
        print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
    >! def on_publish(client, obj, mid):
        print("mid: " + str(mid))
    >! def on_subscribe(client, obj, mid, granted_qos):
        print("Subscribed: " + str(mid) + " " + str(granted_qos))
    >! def on_log(client, obj, level, string):
        print(string)
    >! # Setup MQTT connection
    >! mqttc = mqtt.Client(MQTT_CLIENT_ID)
    # Assign event callbacks
    #mqttc.on_message = on_message
    mqttc.on_connect = on_connect
    #mqttc.on_publish = on_publish
    mqttc.on_subscribe = on_subscribe
    mqttc.on_disconnect = on_disconnect
    >! # Uncomment to enable debug messages
    #mqttc.on_log = on_log
    >! # Uncomment the next line if your MQTT server requires authentication
    #mqttc.username_pw_set(MQTT_USER, password=MQTT_PASS)
    mqttc.connect(MQTT_HOST, MQTT_PORT, 60)
    >! mqttc.loop_start()
    >! # Start RTL433 listener
    rtl433_proc = subprocess.Popen(rtl_433_cmd.split(),stdout=subprocess.PIPE,stderr=subprocess.STDOUT,universal_newlines=True)
    >! while True:
        lastline/    for line in iter(rtl433_proc.stdout.readline, '\n'):
            if line == lastline:
                continue
    >!         if "time" in line:
                mqttc.publish(MQTT_TOPIC, payload=line,qos=MQTT_QOS)
                json_dict = json.loads(line)
                for item in json_dict:
                    value = json_dict[item]
                    if "model" in item:
                        subtopic=value
                    elif "id" in item:
                        id=value
    >!             for item in json_dict:
                    value = json_dict[item]
                    if not "model" in item and not "id" in item:
                        mqttc.publish(MQTT_TOPIC+"/"+subtopic+"/"+str(id)+"/"+item, payload=value,qos=MQTT_QOS)
    >!             lastline=line
    >! ````
    >! und als config.py:
    

    Config section

    Uncomment these lines if your MQTT server requires authentication

    #MQTT_USER="mqtt-user"
    #MQTT_PASS="mqtt-password"
    MQTT_HOST="iobroker-adresse"
    MQTT_PORT=1883
    MQTT_TOPIC="sensors/rtl_433"
    MQTT_QOS=0
    MQTT_CLIENT_ID="RTL_433"

    End config section

    ! ````

    Um das ganze als Service laufen zu lassen, dient die folgende service-Datei. Diese als rtl_433-mqtt.service in /etc/systemd/system anlegen.

    ! [Unit] Description=rtl_433 to MQTT publisher After=network.target [Service] ExecStart=/usr/bin/python3 /usr/local/lib/rtl2mqtt/rtl2mqtt.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target !

    • Das ganze via
    sudo systemctl daemon-reload
    sudo systemctl start rtl_433-mqtt
    
    

    starten.

    In ioBroker sollte der mqtt-Adapter als broker laufen. Sofern es auf demselben Host wie der rest ist oder in einem gesicherten Netz, sind auch keine Passwörter/SSL etc. notwendig.

    Wenn ihr die Reeds jetzt öffnet und schließt, solltet ihr in iobroker schon sehen, dass neue States unterhalb des mqtt-Adapters angelegt werden und sich die Werte ändern. Jeder Kontakt hat eine eigene 4-stellige ID.

    Das Fensterscript

    Es kommt das Fensterscript von http://www.iobroker.net/docu/?page_id=5158&lang=de zum Einsatz.

    Dazu sind Vorarbeiten und Anpassungen nötig.

    Vorarbeiten: Der MQTT-Adapter legt nur States, aber keine Channels an. Das Script arbeitet aber mit Channels. Das macht aber nicht, man kann die entsprechenden Channel einfach selbst anlegen. Unterhalb von mqtt.0.sensors.rtl_433.Generic_Remote Einfach einen channel mit der id = Ordner-Name des Fensterkontaktes anlegen, dieser "ersetzt" dann den vorhandenen Ordner und die States (cmd, time, tristate) werden darunter einsortiert.

    Rolle ist switch, als Name kann z.B. Das Zimmer angegeben werden.

    Die Channel sollten lt. Script dem Gewerk Fenster zugeordnet werden. Damit funktioniert bei mir der Trigger nicht, warum kann ich nicht sagen.
    8645_channel.png

    Jetzt das abgewandelte Script.

    ! ````
    /* System Zahl Fenster

    zählt die Fenster in allen Räumen und meldet die offenen Fenster namentlich
    Daten kommen vom Gewerk 'Fenster'

    erstellt: 17.06.2015 nach diesem Vorbild: http://forum.iobroker.net/viewtopic.php?f=21&t=869&sid=f9ba5657489ff431a1990884f90779c1#p6564
    05.08.2015 STATE aus der Ausgabe entfernt nach Idee von stephan61 http://forum.iobroker.org/viewtopic.php?f=21&t=473&start=20#p9267
    02.12.2015 Fehler beseitigt bei Anzahl Fenster, wenn offen (Unterscheidung RHS und TFK)
    Überprüfung des Zustandes (function fensterstatus) und Übergabe an Text
    25.01.2016 Fenster Nummer in Log korrigiert (+1)
    02.03.2016 Ansage für TTS aufbereitet
    02.07.2016 Regulärer Ausdruck (gierig) bei Aufbereitung für Ansage
    */

    function fensterstatus(zustand) {
    var meldung;
    switch (zustand) {
    case 10:
    meldung = 'TFK offen';
    break;
    case 14:
    meldung = 'geschlossen';
    break;
    }
    return(meldung);
    }

    createState('zählen_Fenster.anzahlFenster', { // wenn benötigt: Anzahl der vorhandenen Fenster
    type: 'number',
    min: 0,
    def: 0,
    role: 'value'
    });
    createState('zählen_Fenster.anzahlFensterauf', { // Anzahl der Fenster, die auf sind als Variable unter Javascript.0 anlegen
    type: 'number',
    min: 0,
    def: 0,
    role: 'value'
    });
    createState('zählen_Fenster.textFensterauf', { // Anzahl der offenen Fenster und deren Namen als Variable unter Javascript.0 anlegen
    type: 'string',
    def: ' ',
    role: 'value'
    });

    var cacheSelectorState = $('channel[role=switch][state.id=*.cmd]'); // funktioniert leider aktuell nicht bei Einschränkung mit functions=Fenster

    function countFenster(obj) {
    // Setzt die Zähler vor dem Durchlauf aller Elemente *.cmd im Gewerk Fenster auf 0
    var anzahlFenster = 0;
    var anzahlFensterauf = 0;
    var textFensterauf = [];

    log('Auslösender Aktor: ' + obj.id + ': ' + obj.newState.val);              // Info im Log, welcher Zustand sich geändert hat
    
    cacheSelectorState.each(function (id, i) {                                  // Schleife für jedes gefundenen Element *.cmd im Gewerk Fenster
        var status = getState(id).val;                                          // Zustand *.cmd abfragen (jedes Element)
        var obj    = getObject(id);
        var name = getObject(id).common.name;
        var devicename = id.substring(0, id.indexOf(".cmd"));             //.state aus Text entfernen
        var channame = getObject(devicename).common.name;
        if (status === 10) {  // wenn Zustand offen, dann wird die Anzahl der Fenster hochgezählt
             ++anzahlFensterauf;
             textFensterauf.push(channame + ' (' + fensterstatus(status) + ')');  // Name und Zustand zum Array hinzufügen
        }                
        log('Fenster #' + (i+1) + ': ' + channame + ' ' + fensterstatus(status)/* + ' (' + status + ' / ' + typeof status + ')'*/);
        ++anzahlFenster;                                                        // Zählt die Anzahl der vorhandenen Fenster unabhängig vom Status
    }); 
    
    // Schleife ist durchlaufen. Im Log wird der aktuelle Status (Anzahl, davon an) ausgegeben
        log("Text: " + textFensterauf);
        log("Anzahl Fenster: " + anzahlFenster + " - davon Fenster auf: " +  anzahlFensterauf);
    
    // die ermittelten Werte werden als javascript.0\. Variable in ioBroker gespeichert (z.B. für die Verarbeitung in VIS)
    setState("zählen_Fenster.textFensterauf", textFensterauf.join(',
    

    ')); // Schreibt die aktuelle Namen der offenen Fenster
    setState("zählen_Fenster.anzahlFensterauf", textFensterauf.length); // Schreibt die aktuelle Anzahl der offenen Fenster
    setState("zählen_Fenster.anzahlFenster", anzahlFenster); // Schreibt die aktuelle Anzahl der vorhandene Elemente im Gewerk Fenster
    }

    cacheSelectorState.on(function(obj) { // bei Zustandänderung *. cmd im Gewerk Fenster
    countFenster(obj);
    });

    // Variable für Ansage aufbereiten
    createState('zählen_Fenster.textFensteraufAnsage', {
    type: 'string',
    def: ' ',
    role: 'value'
    });
    // Anzahl der Fenster, die auf sind, für Ansage aufbereitet
    var idQuelle = 'javascript.0.zählen_Fenster.textFensterauf',
    idAnsage = 'javascript.0.zählen_Fenster.textFensteraufAnsage';

    on(idQuelle, function (obj) {
    var text = obj.state.val;
    text = text.replace(/RHS/g, 'Drehgriff');
    text = text.replace(/TFK/g, 'Reedkontakt');
    text = (text.length > 1) ? 'Geöffnete Fenster: ' + text : 'Alle Fenster sind verschlossen';
    setState(idAnsage, text);
    });

    ! ````

    Anregungen, Vorschläge, Verbesserungen gerne hier.

    Gruß

    Stef

    1 Antwort Letzte Antwort
    0
    • J Offline
      J Offline
      Jan1
      schrieb am zuletzt editiert von
      #2

      Und wenn Dir den Aufwand mit der Einbindung des Empfänger sparen willst, dann nimmst die Sonoff RF Bridge und es läuft ohne irgendwelche extra Scrips unterm Sonoff oder MQTT Adapter. Die Bridge kostet ebenfalls um die 9€ ;)

      So wie das die meisten hier schon am Laufen haben. Den Link zu den Kontakten kannst aber mal posten, da die wirklich sehr günstig sind. Ob das mit der AA Batterie ein Vorteil ist, wird sich an der Lebensdauer zeigen. Poste auf alle Fälle mal wie lange die gehalten haben.

      1 Antwort Letzte Antwort
      0
      • S Offline
        S Offline
        stef.73
        schrieb am zuletzt editiert von
        #3

        Jo, nur halt mit Tasmota, also flashen. Und (soweit ich es verstanden habe), ist das flashen nicht mal nur USB anstecken und los, sondern mit löten..

        Vorteil ist natürlich das es auch senden kann, Vorteil meiner Umsetzung wäre, dass es auch noch die Wetterstation vom Nachbarn oder die Reifendruckkontrolle übernehmen kann. RTL_433 ist einfach prima. :-)

        Aber jeder wie er möchte. Die Kontakte sind von https://de.aliexpress.com/item/6pcs-great-promotion-433MHz-EV1527-two-way-door-sensor-window-detector-door-gap-sensor-for-alarma/32713418101.html?spm=a2g0x.search0104.3.1.502242f2bPwYqk&ws_ab_test=searchweb0_0,searchweb201602_3_10320_10065_10068_10843_10547_10059_10548_10696_100031_10319_10084_10083_10103_451_10618_452_10304_10307_10820_10821_10302,searchweb201603_16,ppcSwitch_5&algo_expid=477ae2db-bd1f-469f-94b1-48cd9de943d6-0&algo_pvid=477ae2db-bd1f-469f-94b1-48cd9de943d6&priceBeautifyAB=0. Stehen jetzt leider bei 26,32€ :-(

        1 Antwort Letzte Antwort
        0
        • J Offline
          J Offline
          Jan1
          schrieb am zuletzt editiert von
          #4

          Löten ist nicht nötig, kann man einfach mit ner Stiftleiste ran halten. Die Kontakte sind selbst für den Preis noch recht günstig ;)

          1 Antwort Letzte Antwort
          0
          • nukleuzN Offline
            nukleuzN Offline
            nukleuz
            schrieb am zuletzt editiert von
            #5

            Hallo,

            super Sache das mit MQTT zu machen.

            Ich habe ebenfalls rtl_433 laufen und nutze dein abgeändertes Skript.

            Allerdings versuche ich damit Temperatursensoren abzurufen - klappt bis auf eine Kleinigkeit echt gut.

            Mir fehlt in den Datenpunkten (states) die Luftfeuchtigkeit also "humidity".

            9401_humidity.png

            Kannst du mir sagen, wie ich die bekomme - mit dem Code werde ich so schnell nicht schlau ;)

            Danke vorab…

            Intel NUC -> ProxMox -> Debian -> ioBroker (Master)| RPI3B+ -> rtl_433 (Slave) | CCU2

            1 Antwort Letzte Antwort
            0
            Antworten
            • In einem neuen Thema antworten
            Anmelden zum Antworten
            • Älteste zuerst
            • Neuste zuerst
            • Meiste Stimmen


            Support us

            ioBroker
            Community Adapters
            Donate

            659

            Online

            32.6k

            Benutzer

            82.3k

            Themen

            1.3m

            Beiträge
            Community
            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
            ioBroker Community 2014-2025
            logo
            • Anmelden

            • Du hast noch kein Konto? Registrieren

            • Anmelden oder registrieren, um zu suchen
            • Erster Beitrag
              Letzter Beitrag
            0
            • Home
            • Aktuell
            • Tags
            • Ungelesen 0
            • Kategorien
            • Unreplied
            • Beliebt
            • GitHub
            • Docu
            • Hilfe