Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Praktische Anwendungen (Showcase)
    4. Fensterkontakte mit offen/geschlossen-Erkennung - preisgünstige Umsetzung

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

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

    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      stef.73 last edited by

      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 Reply Last reply Reply Quote 0
      • J
        Jan1 last edited by

        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 Reply Last reply Reply Quote 0
        • S
          stef.73 last edited by

          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 Reply Last reply Reply Quote 0
          • J
            Jan1 last edited by

            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 Reply Last reply Reply Quote 0
            • nukleuz
              nukleuz last edited by

              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…

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              929
              Online

              31.9k
              Users

              80.3k
              Topics

              1.3m
              Posts

              3
              5
              4468
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo