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. WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten

NEWS

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    11
    1
    343

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    24
    1
    1.6k

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    9.5k

WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten

Geplant Angeheftet Gesperrt Verschoben Praktische Anwendungen (Showcase)
esp8266 projektjavasriptjson stringmqtt-broker-client-adapternodemcu tasmota mqttrelay-switchtasmota 1wire
45 Beiträge 19 Kommentatoren 11.7k Aufrufe 28 Watching
  • Ä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.
  • alkA Offline
    alkA Offline
    alk
    schrieb am zuletzt editiert von alk
    #1

    Anwendungsbeschreibung
    Komponenten

    • Brauchwasserspeicher (Warmwasser)
    • Zirkulationspumpe in der Steigleitung
    • NodeMCU V2.0 (ESP8266) OS:tasmota Doris 8.1
    • 3x Temperaturfühler DS18B20 (1wire) zum Messen von der Vorlauftemperatur
    • Relaismodul zum Schalten der Zirkulationspumpe

    Ziel
    Ich möchte mit der Steuerung Energiekosten sparen. Der aktuell Aufbau startet die Zirkulationspumpe mit einer Zeitschaltuhr, z.B. Morgens 30min, Mittag 30min und Abends 30min. Der Aufbau ist wohl sehr weit verbreitet und ist mir schon eine ganze Weile in Dorn im Auge weil wenig innovativ.

    Die Zirkulationspumpe soll bedarfsgerecht eingeschaltet werden und die aktuelle Zeitschaltuhr kommt weg. Bedarfsgerecht meint beim Aufdrehen vom Warmwasser im Gebäude soll die Zirkulationspumpe starten und die Steigleitung mit Warmwasser befüllen. Damit ist das Warmwasser schneller an der Bedarfsstelle im Bad/WC.

    Kurzbeschreibung der Steuerhardware
    Ein 5V Netzteil versorgt den NodeMCU und das Relaismodul mit 5.0V Spannung. Auf dem NodeMCU steht eine geregelte 3.3.V Versorgung für die DS18B20 zur Verfügung.
    Als Betriebssystem für den NodeMCU verwende ich tasmota in einer damals neuen Version 8.1. Alle Hardwarekomponenten sind günstig und leicht am Markt verfügbar.
    Begonnen habe ich drei Temperatursensoren einzusetzen - ich wusste noch nicht so genau wie es werden wird. Am Ende braucht man nur einen Sensor am Heizungsrohr für den Warmwasservorlauf vom Brauchwasserspeicher in die Steigleitung.
    Wichtig: Der NodeMCU ist echt billig gemacht und verträgt wenig Spannungsschwankungen. Schon beim Einschalten des Radios gibt es den einen oder anderen Effekt und tasmota hängt sich auf. Also umbedingt reichlich (~2) Cbulk ~330uF außen an die 3.3V Versorgungspins anschließen.

    Kurzbeschreibung der Steuersoftware auf dem NodeMCU
    Tasmota bietet eine schicke Möglichkeit mit "Rules" direkt und schnell auf Events zu reagieren und neue Events auszulösen. Damit lässt sich eine tolle Steuerung umsetzen. Inspiriert hat mich ein Beispiel in der Tasmotat Dokumentation der eine Poolheizung realisiert hat. Dazu gibt es noch Variablen (var) und Konstante (mem) für mehr Transparenz des Ganzen nach außen.

    Tasmota rule1
    Der Thermostat
    Nachdem die Zirkulationsregelung gestartet ist stellt sich der Thermostat auf die aktuellen Temperaturen des Vorlauf ( DS18B20_2) und Rücklauf ( DS18B20_1 )ein. Es werden Grenzen zum Einschalten der Pumpe festgelegt um zu erkennen wenn Warmwasser entnommen wird. Dann erwärmt sich das Vorlaufrohr nach dem Brauchwasserspeicher, der Vorlaufsensor signalisiert einen Temperaturanstieg.

    Event

    • DS18B20_2:
      -- Obere Vorlaufgrenze (UpperVL): var1
      -- Untere Vorlaufgrenze (LowerVL): var2
    • DS18B20_1: Aktuell nicht benutzt, LowerRL Limit: var3
    ------------------------------------------------------------------
    -- rule1 Thermostat und Regelung. Entscheidung ob Pumpe eingeschaltet werden soll.
    -- 
    -- Rücklauf DS18B20-1#temperature  
    -- Vorlauf  DS18B20-2#temperature  
    -- Intern   DS18B20-3#temperature  
    --
    -- var1 obere Temperaturschwelle Vorlauf (VL)
    -- var2 untere Temperaturschwelle Vorlauf (VL)
    -- var3 maximale Rücklaufschwelle (RL)
    -- Löse event aus wenn Vorlauf temp ausserhalb oberer (var1) und unterer (var2) Schwelle, Pumpe an.
    rule1
    on system#boot do Backlog var1 26; var2 25; var3 25 endon
    on DS18B20_2#temperature>%var1% do Backlog var1 %value%;var2 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event UpperVL=%value% endon
    on DS18B20_2#temperature<%var2% do Backlog var2 %value%;var1 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event LowerVL=%value% endon
    

    590ca147-9635-4d3a-9bfe-433e1f634e00-grafik.png

    Es wird Warmwasser entnommen
    Die Zirkulationsregelung läuft und hat die obere und untere Vorlauftemperaturgrenzen ( DS18B20_2 ) eingestellt, die Pumpe ist aus ( power1 0 ).
    Es wird Warmwasser aus dem Brauchwasserspeicher entnommen und das Vorlaufrohr erwärmt sich. Der Vorlaufsensor signalisiert einen Temperaturanstieg und die obere Vorlauftemperaturgrenze ( DS18B20_2 ) wird überschritten.
    Beim Überschreiten wird der Thermostat neu definiert und eine Event ausgelöst UpperVL der die Pumpe einschalten soll.
    Die Pumpe wird über rule2 gesteuert. Wenn die Zirkulationspumpe eine definierte Zeit ( mem5 ) gelaufen ist gibt es eine Wartezeit vor dem nächsten Pumpenanlauf ( mem4 ) um eine schnelles Ein-/Ausschalten zu vermeiden.

    Tasmota rule1

    Event

    • UpperVL: Event zum einschalten der Pumpe für eine bestimmte Zeit.
    • LowerVL: Event Pumpe aus
    • LowerRL: Event Pumpe aus
    • PumpOn=0: Pumpe/Power1 aus.
    • PumpOn>0: Entscheiden ob und wie lange die Pumpe power1 eingeschaltet werden soll.
    • Var4: Pumpenfreigabe in minuten, zählt von 0 aufwärts.
    • Mem4: Grenze in Minuten wann die Pumpe wieder freigegeben wird und einschalten darf.
    ------------------------------------------------------------------
    -- rule2 	Controller: Pumpe einschalten und ausschalten
    -- rule2 1	Regel einschalten
    -- rule2 0	Regel ausschalten
    --
    -- Pumpe einschalten, delay %value%, Pumpe abschalten.
    -- PumpOn=0 	Pumpe aus
    -- PumpOn=10	Pumpe an, setze timer zum ausschalten
    -- PumpOn=180	Pumpe an, setze timer zum ausschalten
    -- 
    -- Benutze Rule timer zum abschalten der pumpe
    -- RuleTimer2 60		60sec
    -- on Rules#Timer=2 o 		when countdown RuleTimer2 expires
    -- var4		Wird beim löschen von power verwendet und es wird das wiedereinschalten verzögert. Die Einheit ist minuten.
    --              Jede Minute zählt var4 im eines hoch. Nach z.B. 5 minuten kann die Pumpe wieder eingeschaltet werden.
    -- mem4	45	Warte mem4 Minuten bis wiedereinschalten, e.g. 45 (Minuten)
    -- mem5	19	Pumpenlaufzeit in sekunden, e.g. 19 (Sekunden)
    rule2
     on system#boot do Backlog var4 0.0 ; ruletimer2 0 endon
     on event#UpperVL do event PumpOn=1 endon
     on event#LowerVL do event PumpOn=0 endon
     on event#PumpOn=0 do power1 off endon  
     on event#PumpOn>0 do event ChkWait=%var4% endif endon  
     on event#ChkWait>%mem4% do Backlog var4 0; ruletimer2 %mem5%; power1 on endon
     on Rules#Timer=2 do power1 off endon 
     on Time#Minute|1 do add4 1 endon
     on var4#state==3 do power1 off endon
    

    Sperrzeit nach einem Pumpenlauf / Pumpenfreigabe
    Pause für die Pumpe nach einer Zirkulationspumpzeit. Hier wird verhindert, dass die Pumpe rythmisch wieder ein und ausgeschaltet wird.

    Event

    • event#PumpOn>0:
      -- Wenn die Pumpe über var4 freigegeben ist:
      if (%var4%>=%mem4%)
    • Time#Minute|1
      -- Vorwärtszählen der Pumpenfreigabe pro Minute.
    rule2
    ...
    on event#PumpOn>0 do if (%var4%>=%mem4%) power1 on; ruletimer2 %value%; var4 0.0 endif endon
    ...
    on Time#Minute|1 do add4 1 endon
    ...
    

    MQTT Verbindung in der Applikation mit Tasmota

    ------------------------------------------------------------------
    -- MQTT Verbindung über rule3
    -- 
    -- Vorlauf  DS18B20-2#temperature  
    -- var1
    -- var4
    rule3
    on tele-DS18B20_2#temperature do Backlog publish stat/zirkulation/vlUpper %var1%; publish stat/zirkulation/PumpWait %var4% endon
    on power1#state do Backlog publish stat/zirkulation/Pump %value% endon 
    

    Konfiguration der Applikation in Tasmota

    -- SetOption53 1 Display hostname and IP address in GUI 0=default
    -- SetOption0 0  Save power state and use after restart (=SaveState) 1=default
    -- SetOption64 1   Switch between - or _ as sensor name separator, 0 = sensor name index separator is - (hyphen) (default), 1 = sensor name index separator is _ (underscore)
    -- mem4 legt die Wartezeit bis zum Wiedereinschalten der Pumpe fest. Bei mir 45Minuten. Gerne auch anpassen.
    -- mem5 legt die Laufzeit der Pumpe fest. Bei mir reichen 19Sekunden. Gerne auch anpassen.
    
    Backlog PowerOnState 0; TelePeriod 61; rule3 1; rule1 1; rule2 1; SetOption0 0; SetOption53 1; SetOption64 1; mem4 45; mem5 19
    

    Und wie läuft das Ganze jetzt los?
    Mit dem folgende Kommando wird alle 61Sekunden eine Messung der Sensoren an den MQTT Broker geschickt:.

    TelePeriod 61
    

    Davor ist die Option 64 wichtig, die einfach ein Problem (im iobroker) behebt, wenn man ein Eventnamen ein Bindestrich enthalten ist ;-). Daran kann man verzweifeln.

    SetOption64 1;
    

    Und folgend werden die rules aktiviert, damit es auch eine Steuerung gibt:

    rule3 1; rule1 1; rule2 1;
    

    Typischer Log aus der Tasmota console

    8:50:57 MQT: tele/zirkulation/STATE = {"Time":"2020-03-01T18:50:57","Uptime":"0T02:27:12","UptimeSec":8832,"Heap":23,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"blabla","BSSId":"Z0:B0:VV:3K:D6:20","Channel":11,"RSSI":100,"Signal":-50,"LinkCount":1,"Downtime":"0T00:00:06"}}
    
    18:50:57 MQT: tele/zirkulation/SENSOR = {"Time":"2020-03-01T18:50:57","DS18B20_1":{"Id":"01143B9799AA","Temperature":26.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":33.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.1},"TempUnit":"C"}
    
    18:50:57 RUL: TELE-DS18B20_1#TEMPERATURE performs "Backlog publish stat/zirkulation/rl 26.1; publish stat/zirkulation/rlUpper 29.100"
    
    18:50:57 RUL: TELE-DS18B20_2#TEMPERATURE performs "Backlog publish stat/zirkulation/vl 33.9; publish stat/zirkulation/vlUpper 34.600; publish stat/zirkulation/vlLower 33.600"
    
    18:50:57 RUL: TELE-DS18B20_3#TEMPERATURE performs "publish stat/zirkulation/int 22.1"
    18:50:57 MQT: stat/zirkulation/int = 22.1
    18:50:57 MQT: stat/zirkulation/rl = 26.1
    18:50:58 MQT: stat/zirkulation/rlUpper = 29.100
    18:50:58 MQT: stat/zirkulation/vl = 33.9
    18:50:58 MQT: stat/zirkulation/vlUpper = 34.600
    18:50:58 MQT: stat/zirkulation/vlLower = 33.600
    18:51:00 RUL: TIME#MINUTE|1 performs "add4 1"
    18:51:00 MQT: stat/zirkulation/RESULT = {"Add4":"31.000"}
    18:51:00 RUL: VAR4#STATE performs "publish stat/zirkulation/PumpWait 31.000"
    18:51:00 MQT: stat/zirkulation/PumpWait = 31.000
    

    Kurzbeschreibung iobroker
    Info

        Plattform: linux
        Betriebssystem: linux
        Die Architektur: arm
        CPUs: 4
        Geschwindigkeit: 1500 MHz
        Modell: ARMv7 Processor rev 3 (v7l)
        RAM: 3.7 GB
        System-Betriebszeit: 19 T. 00:08:11
        Node.js: v12.22.6
        NPM: 6.14.15
        Datenträgergröße: 29.0 GiB
        Datenträger verfügbar: 26.0 GiB
        Adapter-Anzahl: 362
        Betriebszeit: 16 T. 00:39:00
        Aktive Instanzen: 17
        location: /opt/iobroker/
    

    JS zirkulation ZirkParseSTATE
    Bei mir heisst der Tasmota MQTT client "zirkulation". Damit kommt der Name relativ oft in dem JS vor.
    Hier werden die vom MQTT Client/Server glieferten Daten vom Tasmota client verarbeitet und umgewandelt. Das liegt daran dass ich keinen besseren Weg gefunden habe die Daten im VIS json table vom tasmota client zu bekommen.

    Hier nun das JS:

    //
    const util = require('util');
    // STATE
    // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
    //
    createState('zirkulation.TimeStampSTATE'); 
    createState('zirkulation.UpTimeSTATE'); 
    
    createState('zirkulation.jsonSENSOR'); 
    createState('zirkulation.jsonSTATE'); 
    
    // prepare tasmota format for json format
    createState('zirkulation.PowerSTATE'); 
    
    //////////////////////////////////////////////////////////////////////////
    // Convert map to JSON string
    // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
    // 
    // @param 
    // @return 
    function mapToJson(map) {
      return JSON.stringify([...map]);
    }
    
    //////////////////////////////////////////////////////////////////////////
    // convert JSON string key value pairs to Map key value pairs
    // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
    //
    // @param jsonStr key value pairs
    // @return map converted from jsonStr to map key value pairs.
    function jsonToMap(jsonStr) {
      return new Map(JSON.parse(jsonStr));
    }
    
    on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
    
    var jsonSensorText = '';
    jsonSensorText = obj.state.val;
    
    // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
    try {obj = JSON.parse(jsonSensorText);
       } catch (e) {
               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
               return;
        }
    
    //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
    
    var sTimeStamp =    obj.Time;
    var fUptimeSec =    obj.UptimeSec;
    var sPOWER =        obj.POWER;       // "POWER":"OFF"
    var fPOWER = 0;
    
    if (sPOWER == "OFF") {
        fPOWER = 0;
    } else {
        fPOWER = 1;
    }
    
    setState('javascript.0.zirkulation.TimeStampSTATE', sTimeStamp , true);
    setState('javascript.0.zirkulation.UpTimeSTATE', fUptimeSec , true);
    setState('javascript.0.zirkulation.PowerSTATE', fPOWER , true);
    
    });
    
    
    /////////////////////////////////////////////////////////////////////////
    // preapre tasmota json format to use in iobroker vis jason table
    // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
    on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
    
        var jsonSensorText = '';
        jsonSensorText = obj.state.val;
    
        var myMap = new Map();
        
        try {obj = JSON.parse(jsonSensorText);
            } catch (e) {
               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
               return;
            }
    
        // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
        for (let [key, value] of Object.entries(obj)) {
            
            if ( typeof value === 'object' ) {
                // iterate one level down
                for (let [key2, value2] of Object.entries(value)) {
                    // log level 2
                    // console.log(key + ":" + key2 + "=" + value2);
                    myMap.set(key + ":" + key2, value2);
                }
            } else {
                // log level 1
                // console.log(key + "=" + value);
                myMap.set(key , value);
            }       
    
        }
        
        var jsonString = mapToJson(myMap);
        //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
        //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
    
        setState('javascript.0.zirkulation.jsonSTATE', jsonString , true);
    
    });
    
    /////////////////////////////////////////////////////////////////////////
    // preapre tasmota json format to use in iobroker vis jason table
    // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
    on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
    
        var jsonSensorText = '';
        jsonSensorText = obj.state.val;
    
        var myMap = new Map();
        
        try {obj = JSON.parse(jsonSensorText);
            } catch (e) {
               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
               return;
            }
    
        // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
        for (let [key, value] of Object.entries(obj)) {
            
            if ( typeof value === 'object' ) {
                // iterate one level down
                for (let [key2, value2] of Object.entries(value)) {
                    // log level 2
                    // console.log(key + ":" + key2 + "=" + value2);
                    myMap.set(key + ":" + key2, value2);
                }
            } else {
                // log level 1
                // console.log(key + "=" + value);
                myMap.set(key , value);
            }       
    
        }
        
        var jsonString = mapToJson(myMap);
        //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
        //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
    
        setState('javascript.0.zirkulation.jsonSENSOR', jsonString , true);
    
    });
    
    

    JS zirkulation ZirkParseSENSOR
    Hier wirkt nun die spezielle Option aus der Tasmota Konfiguration um das "-" in ein "_" zu wandeln.

    //
    const util = require('util');
    // SENSOR
    // {"Time":"2020-03-28T19:07:12","DS18B20_1":{"Id":"01143B9799AA","Temperature":30.4},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":36.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":24.6},"TempUnit":"C"}
    // 
    createState('zirkulation.TimeStampSENSOR'); 
    createState('zirkulation.VorlaufTempSENSOR');
    createState('zirkulation.RuecklaufTempSENSOR');
    createState('zirkulation.InnerhalbTempSENSOR');
    
    on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
    
    var jsonSensorText = '';
    jsonSensorText = obj.state.val;
    
    try {obj = JSON.parse(jsonSensorText);
       } catch (e) {
               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
               return;
        }
    //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
    
    // {"Time":"2020-06-06T15:11:44","DS18B20_1":{"Id":"01143B9799AA","Temperature":21.8},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":35.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.6},"TempUnit":"C"}   
    var fRLTemp = obj.DS18B20_1.Temperature; // RL
    var fVLTemp = obj.DS18B20_2.Temperature; // VL
    var fINTemp = obj.DS18B20_3.Temperature; // IN
    var sTimeStamp = obj.Time;
    
    setState('javascript.0.zirkulation.TimeStampSENSOR', sTimeStamp , true);
    setState('javascript.0.zirkulation.InnerhalbTempSENSOR', fINTemp , true);
    setState('javascript.0.zirkulation.VorlaufTempSENSOR', fVLTemp   , true);
    setState('javascript.0.zirkulation.RuecklaufTempSENSOR', fRLTemp , true);
    
    
    });
    
    
    
    • DIY Electronics that do their job
    • EV, WB, PV + Battery and optimized charging ;-)
    AndreiosA C I 3 Antworten Letzte Antwort
    0
    • H Offline
      H Offline
      h07d0q
      schrieb am zuletzt editiert von h07d0q
      #2

      Möchte mich hier mit meinen Gedanken anschließen, da ich die gleiche Idee / gleiche Ziel hatte, selber aber einen etwas anderen Weg gegangen bin.

      Zeitschaltuhr
      Ursprünglich war eine Zeitschaltuhr an der Zirkulationspumpe angeschlossen, welche die auf niedrigster Stufe laufende WW Zirkulationspumpe jeweils eine halbe Stunde über den Tag verteilt anschmiss.
      Danach tauschte ich die Zeitschaltuhr gegen ein Sonoff/Tasmota Relais. Die Zirkulation musste ca. 10 Minuten auf höchster Stufe laufen, bis die Temperatur im Rücklauf nicht mehr stieg. Also baute ich eine Rule mit einer Dauer von ca. 10 Minuten und schaltete mit den Timern die Pumpe an, über die Rule aus.

      Smarte Lösungsideen
      Folgende Lösungen standen/stehen zur Wahl:

      • Zeitschaltuhr nur bei Anwesenheit aktiv
      • Temperaturabhängig VL zu RL Temperatur
      • Bedarfsabhängig
        • Temperatursteigerung
        • Durchflussschalter (HT-120) oder Durchflusssensor (YF-B5 als Counter - ungenau, aber ausreichend als Schalter)

      Die Zeitschaltuhr in Tasmota über iobroker nur bei Anwesenheit mindestens einer Person zu aktivieren war mir nicht smart genug. Auch ein Schalten ab einer definierten Differenz, oder dem Verhältnis zwischen Vor und Rücklauftemperatur schied aus, da hier zwar ebenfalls mit der Anwesenheit gearbeitet werden könnte, aber trotzdem zu viel Wärmeverlust im WW Speicher auftreten würde.
      Bleiben also die Bedarfsabhängigen Lösungen übrig. Der Durchflussensor, oder -schalter war nicht vorhanden und müsse hinter/vor die Pumpe eingebaut werden, was ich mir nicht zutraute, wäre aber vermutlich die technisch bessere Lösung, da sie schneller reagiert.
      Aktuell habe ich es über die Temperatursteigerung gelöst, da (bis auf die Temperatursensoren) kein großartiger Umbauaufwand notwendig war.

      Umsetzung
      Ich stieß auf das Skript in diesem Post und passte es so an, dass ich nur die Temperaturänderung in einen Datenpunkt schrieb und diese mit Grafana loggte und erst mal die Lösung mit der Zeitschaltuhr analysierte:

      c8951f0c-a856-4c92-a02a-d18be9735757-image.png
      Die Zirkulationspumpe wird regelmäßig 14x am Tag eingeschaltet, ob Warmwasser benötigt wird, oder nicht. Ob jemand daheim ist, oder nicht.

      Deaktiviere ich die Zeitschaltuhr und aktiviere das Bedarfsskript, sieht das schon mal anders aus:
      efbb0096-b60d-446d-ba15-1c75ff451f91-image.png
      Es wurde seltener WW benötigt und die Pumpe bei jedem Bedarf aktiviert.
      Die Pumpe läuft nur noch so lange, bis der Rücklauf keine Temperatursteigerung mehr (unter angegebener Grenze) hat (ca. 8 Minuten, schwankend).
      Damit die Pumpe nicht gleich wieder abschaltet, weil die Temperatursteigerung im Rücklauf noch zu gering ist, ist eine Mindestlaufzeit eingebaut nach welcher erst die Temperaturänderung im Rücklauf geprüft wird.
      Um ein unnötiges weiteres Erhöhen der Temperatur zu vermeiden, habe ich eine Untergrenze für den Vorlauf eingebaut:
      ba4551fa-8481-4768-86e1-1c9cba82d021-image.png Man sieht schön wie um ca. 7 Uhr WW erzeugt wird und sich die Zuleitung aufgrund der aufsteigenden Temperatur erwärmt und wie ich um 0:30 Uhr noch Zähne geputzt habe :) Zwischen 17 und 19 Uhr war die Temperatur im Vorlauf wegen häufigen Bedarfen über dem Mindestwert, sodass die Pumpe nicht nachhelfen musste.

      Bei einem Tag mit Abwesenheit läuft die Pumpe noch seltener:
      8f22a265-250e-433b-9066-2d988a3113fe-image.png

      Ausreißer
      Da sie DS18B20 Sensoren hin und wieder seltsame Temperaturen zurückgeben und sich so Ausreißer nach oben und unten ergeben, habe ich im Skript ab einem Höchstwert von 5 die Spitzen abgeschnitten, bzw. wird der Datenpunkt nicht aktualisiert. Diese Ausreißer werden zusätzlich noch mit Hilfe des alten Messwerts vermittelt (h1 + speedVLold).

      Nachteile:

      • Verzögerung durch Aktualisierungsintervall von 10s und Trägheit des Temperaturanstiegs am Rohr zzgl. bis das WW an die Stichleitung gepumpt wird
      • iobroker muss laufen

      Fazit:
      Bisher läuft das Skript sehr gut, Bedarfe werden gut erkannt und nicht auf zu kleine Mengen reagiert. Wird immer wieder Warmwasser gezapft, bleibt die Leitung warm und die Pumpe aus, bedeutet jedoch, dass das Warmwasser in der Leitung bis zur letzten Zapfstelle abkühlt...
      Noch besser wäre wie beschrieben mit einem Durchflussensor schneller darauf zu reagieren, oder die gesammelten Daten in eine Art KI zu schieben und schon im Voraus zu erkennen, ob man gleich Warmwasser braucht :D aber dafür ist unser Bedarf vermutlich nicht regelmäßig genug...
      Eine Ersparnis konnte ich bisher nicht feststellen und werde ich im Nachhinein auch nicht auswerten können, da die Heizung noch nicht ganz korrekt am iobroker angebunden ist, aber sie müsste allein aufgrund der Tage in Abwesenheit, oder im Urlaub (habe nie die Zeitschaltuhr deaktiviert) da sein.
      Ich hoffe ich kann manch einem mit meinem Erfahrungsbericht helfen und somit auch mal was an die Community zurückgeben.

      hier noch der aktuelle Stand des Skripts mit allen (deaktivierten) Debug Meldungen während der Analyse:

      //https://forum.iobroker.net/post/133815
      //VL
      const idTempVL = 'sonoff.0.HWR.DS18B20-2_Temperature';
      const iddTVL = '0_userdata.0.WWZirkulationspumpe.dTVL';
      const swOn = 0.7;  // Grenzwert in K/min
      var speedVL
      var speedVLold = 0;
      //RL
      const idTempRL = 'sonoff.0.HWR.DS18B20-1_Temperature';
      const iddTRL = '0_userdata.0.WWZirkulationspumpe.dTRL';
      const swOff = 0.3;  // Grenzwert in K/min
      var speedRL
      var speedRLold = 0;
      
      var timer = null;
      const minTime = 60000   // Minimum Zeit in Millisekunden, welche die Pumpe laufen soll, bevor abgeschalten werden kann (TRL ist noch unter swOff)
      const minTemp = 36      // Minimum Temperatur, bevor die Pumpe wieder läuft
      var check = false;      // Check für minTime
      var check2 = 1;         // Check für minimalen speedVL für Ausschalten, sonst wird zu früh abgeschalten
      var h1, h2
      const idAktor = 'sonoff.0.HWR.POWER2';
      var aktor = getState(idAktor).val;
      on({id: idAktor, ack: true}, function(dp) {aktor = dp.state.val;});
      //////////////////////////////////////////////////////////
      /* Einschalten bei steigender Vorlauftemperatur */
      on(idTempVL, function(dp) {  // Triggern bei Wertänderung
         h1 = 60000 * (dp.state.val - dp.oldState.val) / (dp.state.lc - dp.oldState.lc);  // K/min
         speedVL = (h1 + speedVLold)/2;
         //console.debug(([Math.round(speedVL*100)/100,' speedVL = (',Math.round(h1*100)/100,' + ',Math.round(speedVLold*100)/100,')/2 K/min'].join('')));
         speedVLold = h1;
         if (speedVL < -5 || speedVL > 5) {return;}
         //console.debug((['state - oldState: ',dp.state.val,' - ',dp.oldState.val,' = ',Math.round((dp.state.val - dp.oldState.val)*100)/100].join('')));
         //console.debug((['TDiff: ',(dp.state.lc - dp.oldState.lc),'ms'].join('')));
         //console.debug(([speed,' K/min.'].join('')));
         setState(iddTVL, Math.round(speedVL*1000)/1000, true);
         
         if (speedVL >= swOn && !aktor && getState(idTempVL).val <= minTemp) {
            setState(idAktor,true);
            var messageText =['Zirkulationspumpe an.  (*dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
            //sendTo("telegram", "send", { text: messageText });
            console.log((messageText));
            
            /* Prüfung mit Alarm */
            if (!getState("0_userdata.0.Anwesenheit.Status.anyonePresent").val) {
                var messageText =['Zirkulationspumpe an, obwohl niemand da ist!\r\n(*dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
                sendTo("telegram", "send", { text: messageText });
                console.error((messageText));
            }
            //console.debug(([Math.round(speed*100)/100,' K/min'].join('')));
            //console.debug((['Temperatur ist um mehr als ',gw,' K/min gestiegen.'].join('')));
            //clearTimeout(timer);
            timer = setTimeout(function() {
                //if(aktor) setState(idAktor, false);
              check = true
            }, minTime);
         }
      });
      
      /* Ausschalten bei fallender Rücklauftemperatur, nach minimaler Zeit, bei stagnierender Vorlauftemperatur */
      on(idTempRL, function(dp) {  // Triggern bei Wertänderung
         h2 = 60000 * (dp.state.val - dp.oldState.val) / (dp.state.lc - dp.oldState.lc);  // K/min
         speedRL = (h2 + speedRLold)/2;
         //console.debug(([Math.round(speedRL*100)/100,' speedRL = (',Math.round(h2*100)/100,' + ',Math.round(speedRLold*100)/100,')/2 K/min'].join('')));
         speedRLold = h2;
         if (speedRL < -5 || speedRL > 5) {return;}
         setState(iddTRL, Math.round(speedRL*1000)/1000, true);
          if(speedRL <= swOff && speedRL > 0 && aktor && check && speedVL <= check2) {
              clearTimeout(timer);
              check = false
              setState(idAktor,false);
              var messageText =['Zirkulationspumpe aus. (dTVL: ',Math.round(speedVL*1000)/1000,', *dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
              //sendTo("telegram", "send", { text: messageText });
              console.log((messageText));
          }
      });
      
      //Debug
      /*
      on({id: new RegExp(idTempVL + "$|" + idTempRL + "$"), change: "ne"}, async function (obj) {
          console.debug((['(dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,', aktor: ',aktor,', timeout: ',check,')'].join('')));
      });
      */
      
      alkA I 2 Antworten Letzte Antwort
      0
      • H h07d0q

        Möchte mich hier mit meinen Gedanken anschließen, da ich die gleiche Idee / gleiche Ziel hatte, selber aber einen etwas anderen Weg gegangen bin.

        Zeitschaltuhr
        Ursprünglich war eine Zeitschaltuhr an der Zirkulationspumpe angeschlossen, welche die auf niedrigster Stufe laufende WW Zirkulationspumpe jeweils eine halbe Stunde über den Tag verteilt anschmiss.
        Danach tauschte ich die Zeitschaltuhr gegen ein Sonoff/Tasmota Relais. Die Zirkulation musste ca. 10 Minuten auf höchster Stufe laufen, bis die Temperatur im Rücklauf nicht mehr stieg. Also baute ich eine Rule mit einer Dauer von ca. 10 Minuten und schaltete mit den Timern die Pumpe an, über die Rule aus.

        Smarte Lösungsideen
        Folgende Lösungen standen/stehen zur Wahl:

        • Zeitschaltuhr nur bei Anwesenheit aktiv
        • Temperaturabhängig VL zu RL Temperatur
        • Bedarfsabhängig
          • Temperatursteigerung
          • Durchflussschalter (HT-120) oder Durchflusssensor (YF-B5 als Counter - ungenau, aber ausreichend als Schalter)

        Die Zeitschaltuhr in Tasmota über iobroker nur bei Anwesenheit mindestens einer Person zu aktivieren war mir nicht smart genug. Auch ein Schalten ab einer definierten Differenz, oder dem Verhältnis zwischen Vor und Rücklauftemperatur schied aus, da hier zwar ebenfalls mit der Anwesenheit gearbeitet werden könnte, aber trotzdem zu viel Wärmeverlust im WW Speicher auftreten würde.
        Bleiben also die Bedarfsabhängigen Lösungen übrig. Der Durchflussensor, oder -schalter war nicht vorhanden und müsse hinter/vor die Pumpe eingebaut werden, was ich mir nicht zutraute, wäre aber vermutlich die technisch bessere Lösung, da sie schneller reagiert.
        Aktuell habe ich es über die Temperatursteigerung gelöst, da (bis auf die Temperatursensoren) kein großartiger Umbauaufwand notwendig war.

        Umsetzung
        Ich stieß auf das Skript in diesem Post und passte es so an, dass ich nur die Temperaturänderung in einen Datenpunkt schrieb und diese mit Grafana loggte und erst mal die Lösung mit der Zeitschaltuhr analysierte:

        c8951f0c-a856-4c92-a02a-d18be9735757-image.png
        Die Zirkulationspumpe wird regelmäßig 14x am Tag eingeschaltet, ob Warmwasser benötigt wird, oder nicht. Ob jemand daheim ist, oder nicht.

        Deaktiviere ich die Zeitschaltuhr und aktiviere das Bedarfsskript, sieht das schon mal anders aus:
        efbb0096-b60d-446d-ba15-1c75ff451f91-image.png
        Es wurde seltener WW benötigt und die Pumpe bei jedem Bedarf aktiviert.
        Die Pumpe läuft nur noch so lange, bis der Rücklauf keine Temperatursteigerung mehr (unter angegebener Grenze) hat (ca. 8 Minuten, schwankend).
        Damit die Pumpe nicht gleich wieder abschaltet, weil die Temperatursteigerung im Rücklauf noch zu gering ist, ist eine Mindestlaufzeit eingebaut nach welcher erst die Temperaturänderung im Rücklauf geprüft wird.
        Um ein unnötiges weiteres Erhöhen der Temperatur zu vermeiden, habe ich eine Untergrenze für den Vorlauf eingebaut:
        ba4551fa-8481-4768-86e1-1c9cba82d021-image.png Man sieht schön wie um ca. 7 Uhr WW erzeugt wird und sich die Zuleitung aufgrund der aufsteigenden Temperatur erwärmt und wie ich um 0:30 Uhr noch Zähne geputzt habe :) Zwischen 17 und 19 Uhr war die Temperatur im Vorlauf wegen häufigen Bedarfen über dem Mindestwert, sodass die Pumpe nicht nachhelfen musste.

        Bei einem Tag mit Abwesenheit läuft die Pumpe noch seltener:
        8f22a265-250e-433b-9066-2d988a3113fe-image.png

        Ausreißer
        Da sie DS18B20 Sensoren hin und wieder seltsame Temperaturen zurückgeben und sich so Ausreißer nach oben und unten ergeben, habe ich im Skript ab einem Höchstwert von 5 die Spitzen abgeschnitten, bzw. wird der Datenpunkt nicht aktualisiert. Diese Ausreißer werden zusätzlich noch mit Hilfe des alten Messwerts vermittelt (h1 + speedVLold).

        Nachteile:

        • Verzögerung durch Aktualisierungsintervall von 10s und Trägheit des Temperaturanstiegs am Rohr zzgl. bis das WW an die Stichleitung gepumpt wird
        • iobroker muss laufen

        Fazit:
        Bisher läuft das Skript sehr gut, Bedarfe werden gut erkannt und nicht auf zu kleine Mengen reagiert. Wird immer wieder Warmwasser gezapft, bleibt die Leitung warm und die Pumpe aus, bedeutet jedoch, dass das Warmwasser in der Leitung bis zur letzten Zapfstelle abkühlt...
        Noch besser wäre wie beschrieben mit einem Durchflussensor schneller darauf zu reagieren, oder die gesammelten Daten in eine Art KI zu schieben und schon im Voraus zu erkennen, ob man gleich Warmwasser braucht :D aber dafür ist unser Bedarf vermutlich nicht regelmäßig genug...
        Eine Ersparnis konnte ich bisher nicht feststellen und werde ich im Nachhinein auch nicht auswerten können, da die Heizung noch nicht ganz korrekt am iobroker angebunden ist, aber sie müsste allein aufgrund der Tage in Abwesenheit, oder im Urlaub (habe nie die Zeitschaltuhr deaktiviert) da sein.
        Ich hoffe ich kann manch einem mit meinem Erfahrungsbericht helfen und somit auch mal was an die Community zurückgeben.

        hier noch der aktuelle Stand des Skripts mit allen (deaktivierten) Debug Meldungen während der Analyse:

        //https://forum.iobroker.net/post/133815
        //VL
        const idTempVL = 'sonoff.0.HWR.DS18B20-2_Temperature';
        const iddTVL = '0_userdata.0.WWZirkulationspumpe.dTVL';
        const swOn = 0.7;  // Grenzwert in K/min
        var speedVL
        var speedVLold = 0;
        //RL
        const idTempRL = 'sonoff.0.HWR.DS18B20-1_Temperature';
        const iddTRL = '0_userdata.0.WWZirkulationspumpe.dTRL';
        const swOff = 0.3;  // Grenzwert in K/min
        var speedRL
        var speedRLold = 0;
        
        var timer = null;
        const minTime = 60000   // Minimum Zeit in Millisekunden, welche die Pumpe laufen soll, bevor abgeschalten werden kann (TRL ist noch unter swOff)
        const minTemp = 36      // Minimum Temperatur, bevor die Pumpe wieder läuft
        var check = false;      // Check für minTime
        var check2 = 1;         // Check für minimalen speedVL für Ausschalten, sonst wird zu früh abgeschalten
        var h1, h2
        const idAktor = 'sonoff.0.HWR.POWER2';
        var aktor = getState(idAktor).val;
        on({id: idAktor, ack: true}, function(dp) {aktor = dp.state.val;});
        //////////////////////////////////////////////////////////
        /* Einschalten bei steigender Vorlauftemperatur */
        on(idTempVL, function(dp) {  // Triggern bei Wertänderung
           h1 = 60000 * (dp.state.val - dp.oldState.val) / (dp.state.lc - dp.oldState.lc);  // K/min
           speedVL = (h1 + speedVLold)/2;
           //console.debug(([Math.round(speedVL*100)/100,' speedVL = (',Math.round(h1*100)/100,' + ',Math.round(speedVLold*100)/100,')/2 K/min'].join('')));
           speedVLold = h1;
           if (speedVL < -5 || speedVL > 5) {return;}
           //console.debug((['state - oldState: ',dp.state.val,' - ',dp.oldState.val,' = ',Math.round((dp.state.val - dp.oldState.val)*100)/100].join('')));
           //console.debug((['TDiff: ',(dp.state.lc - dp.oldState.lc),'ms'].join('')));
           //console.debug(([speed,' K/min.'].join('')));
           setState(iddTVL, Math.round(speedVL*1000)/1000, true);
           
           if (speedVL >= swOn && !aktor && getState(idTempVL).val <= minTemp) {
              setState(idAktor,true);
              var messageText =['Zirkulationspumpe an.  (*dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
              //sendTo("telegram", "send", { text: messageText });
              console.log((messageText));
              
              /* Prüfung mit Alarm */
              if (!getState("0_userdata.0.Anwesenheit.Status.anyonePresent").val) {
                  var messageText =['Zirkulationspumpe an, obwohl niemand da ist!\r\n(*dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
                  sendTo("telegram", "send", { text: messageText });
                  console.error((messageText));
              }
              //console.debug(([Math.round(speed*100)/100,' K/min'].join('')));
              //console.debug((['Temperatur ist um mehr als ',gw,' K/min gestiegen.'].join('')));
              //clearTimeout(timer);
              timer = setTimeout(function() {
                  //if(aktor) setState(idAktor, false);
                check = true
              }, minTime);
           }
        });
        
        /* Ausschalten bei fallender Rücklauftemperatur, nach minimaler Zeit, bei stagnierender Vorlauftemperatur */
        on(idTempRL, function(dp) {  // Triggern bei Wertänderung
           h2 = 60000 * (dp.state.val - dp.oldState.val) / (dp.state.lc - dp.oldState.lc);  // K/min
           speedRL = (h2 + speedRLold)/2;
           //console.debug(([Math.round(speedRL*100)/100,' speedRL = (',Math.round(h2*100)/100,' + ',Math.round(speedRLold*100)/100,')/2 K/min'].join('')));
           speedRLold = h2;
           if (speedRL < -5 || speedRL > 5) {return;}
           setState(iddTRL, Math.round(speedRL*1000)/1000, true);
            if(speedRL <= swOff && speedRL > 0 && aktor && check && speedVL <= check2) {
                clearTimeout(timer);
                check = false
                setState(idAktor,false);
                var messageText =['Zirkulationspumpe aus. (dTVL: ',Math.round(speedVL*1000)/1000,', *dTRL: ',Math.round(speedRL*1000)/1000,')'].join('');
                //sendTo("telegram", "send", { text: messageText });
                console.log((messageText));
            }
        });
        
        //Debug
        /*
        on({id: new RegExp(idTempVL + "$|" + idTempRL + "$"), change: "ne"}, async function (obj) {
            console.debug((['(dTVL: ',Math.round(speedVL*1000)/1000,', dTRL: ',Math.round(speedRL*1000)/1000,', aktor: ',aktor,', timeout: ',check,')'].join('')));
        });
        */
        
        alkA Offline
        alkA Offline
        alk
        schrieb am zuletzt editiert von
        #3

        @h07d0q Vielen Dank für den Austausch - auch eine sehr schöne Lösung.
        Wie ich verstanden habe läuft das Java Script auf dem Iobroker und due hast zwei Sensoren, eines am Vorlauf und eines am Rücklauf der Zirkulation? Und die Sensorwerte werden mit einenm Sonoff schalter + DS18B20 aufgenommen, mittels MQTT an den iobroker gesendet?

        • DIY Electronics that do their job
        • EV, WB, PV + Battery and optimized charging ;-)
        1 Antwort Letzte Antwort
        0
        • HomoranH Nicht stören
          HomoranH Nicht stören
          Homoran
          Global Moderator Administrators
          schrieb am zuletzt editiert von Homoran
          #4

          habt ihr euch mal bei stall.biz den wiffi-pump angesehen?

          kein Support per PN! - Fragen im Forum stellen - es gibt fast nichts, was nicht auch für andere interessant ist.

          Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.

          der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

          alkA NoschvieN 2 Antworten Letzte Antwort
          0
          • HomoranH Homoran

            habt ihr euch mal bei stall.biz den wiffi-pump angesehen?

            alkA Offline
            alkA Offline
            alk
            schrieb am zuletzt editiert von
            #5

            @homoran Vielen Dank für's teilen. Darauf bin ich anfangs auch gestossen. Sieht sehr gut aus, schönes Gehäuse, PCB etc.
            Auch gibt es noch viele andere schöne Lösungen auf der Seite :fist:

            • DIY Electronics that do their job
            • EV, WB, PV + Battery and optimized charging ;-)
            HomoranH 1 Antwort Letzte Antwort
            0
            • alkA alk

              @homoran Vielen Dank für's teilen. Darauf bin ich anfangs auch gestossen. Sieht sehr gut aus, schönes Gehäuse, PCB etc.
              Auch gibt es noch viele andere schöne Lösungen auf der Seite :fist:

              HomoranH Nicht stören
              HomoranH Nicht stören
              Homoran
              Global Moderator Administrators
              schrieb am zuletzt editiert von Homoran
              #6

              @alk sagte in WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten:

              Auch gibt es noch viele andere schöne Lösungen auf der Seite

              so ist es!
              Eugen ist da sehr aktiv. Schon bevor es ioBroker gab hat er einiges für Homematic gebastelt.
              Hält sich preislich auch im Rahmen.

              kein Support per PN! - Fragen im Forum stellen - es gibt fast nichts, was nicht auch für andere interessant ist.

              Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.

              der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

              1 Antwort Letzte Antwort
              0
              • H Offline
                H Offline
                h07d0q
                schrieb am zuletzt editiert von
                #7

                @alk Richtig, genau so ist es aufgebaut (in diesem Fall ein Sonoff Dual R2, der auch die Außenbeleuchtung schaltet)
                wiffi-pump habe ich davor auch gesehen, möglicherweise hat er mich inspiriert ;)

                Ich hab das Skript oben mit meiner aktuellen Version aktualisiert - es kamen ein paar Kommentare dazu und eine Alarmmeldung wenn niemand im Haus ist und die Zirkulationspumpe aktiviert wird (zu Testzwecken und jetzt drin geblieben).
                731ece0d-0d2e-4460-a279-2a772a1dad46-image.png
                Zu Analysezwecken habe ich auch eine Heatmap in Grafana aufgebaut :D

                Natürlich wäre es schicker wenn die Logik wie bei Eugen Stall alles im Mikrocontroller umgesetzt wäre, dann hätte man eine kürzere Verzögerung für das Zuschalten der Pumpe. Das mit der Auswertung und Analyse müsste man dann anders lösen wenn man das möchte. Und ich bräuchte dann einen weiteren ESP nur für diese Aufgabe, außer man bekommt das irgendwie auch mit Tasmota Rules hin.
                Naja wer weiß... "irgendwann" mal ;)

                NoschvieN 1 Antwort Letzte Antwort
                0
                • S Offline
                  S Offline
                  SmartesHome
                  schrieb am zuletzt editiert von
                  #8

                  Guten Morgen :)

                  Auch wenn ich gleich wahrscheinlich gesteinigt werde und verstehen kann, dass Energiekosten und generell Energie, gerade in der aktuellen weltpolitischen Situation, eingespart werden sollen, möchte ich bei diesem Thema auf die Trinkwasserhygiene hinweisen. Das soll kein Post mit dem erhobenen Zeigefinger sein, sondern einfach der Sensibilisierung für dieses Thema dienen.

                  Wie ich den Diagrammen oben entnehmen kann, werden die WW-Leitungen generell unter 50°C betrieben. Die Temperatur in der Leitung sinkt zwischenzeitlich sogar bis unter 25°C ab und das Wasser in den Leitungen steht zusätzlich noch still. Das ist trinkwasserhygienisch gesehen mehr als bedenklich und ist auch nicht im Sinne der TrinkwV.

                  Durch den Betrieb einer Anlage mit den oben genannten Parametern werden diverse Bakterien, wie z.B. Legionellen in den Leitungen regelrecht provoziert und gezüchtet. Dazu gibt es die VDI6023 und die DVGW Arbeitsblätter W551-554, die den Betrieb einer WW-Zirkulation und die Hygiene regeln. Eine WW-Zirkulation ist immer oberhalb von 55°C zu betreiben. Weiterhin muss Wasser immer fließen, gerade dann, wenn sie in den oben genannten Temperaturbereichen betrieben werden. Legionellen sind problematisch, wenn damit kontaminiertes Wasser zum Duschen genutzt wird. Man atmet die Legionellen durch die beim Duschen entstehenden Aerosole ein, was zu einer Legionellose führen kann.

                  Es geht mittlerweile sogar so weit, dass Kaltwasserzirkulationen in die Gebäude Einzug halten, um zu gewährleisten, dass das KW immer unter 25° bleibt, denn gerade der Temperaturbereich zwischen 25° und 50° ist trinkwasserhygienisch absolut kritisch. Andere Lösungen sind Hygienespülsystem, die eine regelmäßige Nutzung einer Anlage simulieren und die Temperaturen überwachen.

                  frana120500F H 2 Antworten Letzte Antwort
                  0
                  • S SmartesHome

                    Guten Morgen :)

                    Auch wenn ich gleich wahrscheinlich gesteinigt werde und verstehen kann, dass Energiekosten und generell Energie, gerade in der aktuellen weltpolitischen Situation, eingespart werden sollen, möchte ich bei diesem Thema auf die Trinkwasserhygiene hinweisen. Das soll kein Post mit dem erhobenen Zeigefinger sein, sondern einfach der Sensibilisierung für dieses Thema dienen.

                    Wie ich den Diagrammen oben entnehmen kann, werden die WW-Leitungen generell unter 50°C betrieben. Die Temperatur in der Leitung sinkt zwischenzeitlich sogar bis unter 25°C ab und das Wasser in den Leitungen steht zusätzlich noch still. Das ist trinkwasserhygienisch gesehen mehr als bedenklich und ist auch nicht im Sinne der TrinkwV.

                    Durch den Betrieb einer Anlage mit den oben genannten Parametern werden diverse Bakterien, wie z.B. Legionellen in den Leitungen regelrecht provoziert und gezüchtet. Dazu gibt es die VDI6023 und die DVGW Arbeitsblätter W551-554, die den Betrieb einer WW-Zirkulation und die Hygiene regeln. Eine WW-Zirkulation ist immer oberhalb von 55°C zu betreiben. Weiterhin muss Wasser immer fließen, gerade dann, wenn sie in den oben genannten Temperaturbereichen betrieben werden. Legionellen sind problematisch, wenn damit kontaminiertes Wasser zum Duschen genutzt wird. Man atmet die Legionellen durch die beim Duschen entstehenden Aerosole ein, was zu einer Legionellose führen kann.

                    Es geht mittlerweile sogar so weit, dass Kaltwasserzirkulationen in die Gebäude Einzug halten, um zu gewährleisten, dass das KW immer unter 25° bleibt, denn gerade der Temperaturbereich zwischen 25° und 50° ist trinkwasserhygienisch absolut kritisch. Andere Lösungen sind Hygienespülsystem, die eine regelmäßige Nutzung einer Anlage simulieren und die Temperaturen überwachen.

                    frana120500F Offline
                    frana120500F Offline
                    frana120500
                    schrieb am zuletzt editiert von
                    #9

                    @smarteshome Ich lebe seit 21 Jahren mit meiner Frau zusammen und fahre meine WW Temperatur immer schon auf 47 Grad. Wir trinken auch seit vielen Jahre Wasser nur aus der Leitung und sprudeln selber.

                    Ich habe weder dünnen Stuhlgang, noch leide ich an Übelkeit oder bin häufig krank.

                    Also Danke für deine Worte, aber ich bleib dabei und mach es so weiter wie bisher.

                    1 Antwort Letzte Antwort
                    0
                    • S SmartesHome

                      Guten Morgen :)

                      Auch wenn ich gleich wahrscheinlich gesteinigt werde und verstehen kann, dass Energiekosten und generell Energie, gerade in der aktuellen weltpolitischen Situation, eingespart werden sollen, möchte ich bei diesem Thema auf die Trinkwasserhygiene hinweisen. Das soll kein Post mit dem erhobenen Zeigefinger sein, sondern einfach der Sensibilisierung für dieses Thema dienen.

                      Wie ich den Diagrammen oben entnehmen kann, werden die WW-Leitungen generell unter 50°C betrieben. Die Temperatur in der Leitung sinkt zwischenzeitlich sogar bis unter 25°C ab und das Wasser in den Leitungen steht zusätzlich noch still. Das ist trinkwasserhygienisch gesehen mehr als bedenklich und ist auch nicht im Sinne der TrinkwV.

                      Durch den Betrieb einer Anlage mit den oben genannten Parametern werden diverse Bakterien, wie z.B. Legionellen in den Leitungen regelrecht provoziert und gezüchtet. Dazu gibt es die VDI6023 und die DVGW Arbeitsblätter W551-554, die den Betrieb einer WW-Zirkulation und die Hygiene regeln. Eine WW-Zirkulation ist immer oberhalb von 55°C zu betreiben. Weiterhin muss Wasser immer fließen, gerade dann, wenn sie in den oben genannten Temperaturbereichen betrieben werden. Legionellen sind problematisch, wenn damit kontaminiertes Wasser zum Duschen genutzt wird. Man atmet die Legionellen durch die beim Duschen entstehenden Aerosole ein, was zu einer Legionellose führen kann.

                      Es geht mittlerweile sogar so weit, dass Kaltwasserzirkulationen in die Gebäude Einzug halten, um zu gewährleisten, dass das KW immer unter 25° bleibt, denn gerade der Temperaturbereich zwischen 25° und 50° ist trinkwasserhygienisch absolut kritisch. Andere Lösungen sind Hygienespülsystem, die eine regelmäßige Nutzung einer Anlage simulieren und die Temperaturen überwachen.

                      H Offline
                      H Offline
                      h07d0q
                      schrieb am zuletzt editiert von
                      #10

                      @smarteshome vielen Dank für die Sensibilisierung!
                      Das Thema ist mir bekannt und dessen bin ich mir bewusst.
                      Die dargestellten Temperaturen stellen nicht die realen Wassertemperaturen dar, sondern nur irrelevante Sensor Temperaturen in Relation zu einander.

                      Um einer Legionellenbildung vorzubeugen soll die Zirkulationspumpe bei einer hohen Temperatur, die über die Solaranlage erreicht wird, ebenfalls laufen. Damit werden die möglichen Keime ebenfalls verringert.

                      Ein befreundeter Fachmann hat mich ebenfalls beruhigt, da ich festgestellt habe, dass die Heizung trotz höher eingestellter Temperatur das Warmwasser auch nicht immer über 50°C hält und es auch erst unter einem programmieren Schwellwert wieder darüber erwärmt. Insgesamt ist bei einem kleinen WW Speicher wie ich ihn habe bei unserer Anzahl von Personen im Haushalt das Thema nicht ganz so kritisch zu sehen wir in einem Mehrfamilienhaus - da sind die Richtlinien auch strikt einzuhalten.

                      Selbst mit meiner Idee, oder den von dir beschriebenen Richtlinien bleibt immer ein letzter Stich als Totleitung der nicht zirkuliert wird - das lässt sich nicht vermeiden, jedoch bei der Planung schon reduzieren. Viel wichtiger ist also eine richtige Planung der Wasserleitungen.

                      @frana120500 Wir trinken unser Wasser seit neuestem hinter einer Osmoseanlage, aber das ist wie bei dir auch eher das Kaltwasser und somit weniger problematisch. Wie smarteshome schon geschrieben hat, geht es eher um die Aeorosole beim Duschen.

                      Wie schon oben geschrieben ist das natürlich auch wichtige Thema hier in Deutschland vielleicht zurecht sehr hoch aufgehangen, da es unser wichtigstes Gut ist, aber schaut man in andere Länder wo städtische Wasserleitungen oberirdisch, in schwarzen Zinkrohren, praller Sonne und brütender Hitze liegen, sind dort nicht überproportional mehr Leute an der Legionärskrankheit erkrankt...

                      1 Antwort Letzte Antwort
                      0
                      • alkA alk

                        Anwendungsbeschreibung
                        Komponenten

                        • Brauchwasserspeicher (Warmwasser)
                        • Zirkulationspumpe in der Steigleitung
                        • NodeMCU V2.0 (ESP8266) OS:tasmota Doris 8.1
                        • 3x Temperaturfühler DS18B20 (1wire) zum Messen von der Vorlauftemperatur
                        • Relaismodul zum Schalten der Zirkulationspumpe

                        Ziel
                        Ich möchte mit der Steuerung Energiekosten sparen. Der aktuell Aufbau startet die Zirkulationspumpe mit einer Zeitschaltuhr, z.B. Morgens 30min, Mittag 30min und Abends 30min. Der Aufbau ist wohl sehr weit verbreitet und ist mir schon eine ganze Weile in Dorn im Auge weil wenig innovativ.

                        Die Zirkulationspumpe soll bedarfsgerecht eingeschaltet werden und die aktuelle Zeitschaltuhr kommt weg. Bedarfsgerecht meint beim Aufdrehen vom Warmwasser im Gebäude soll die Zirkulationspumpe starten und die Steigleitung mit Warmwasser befüllen. Damit ist das Warmwasser schneller an der Bedarfsstelle im Bad/WC.

                        Kurzbeschreibung der Steuerhardware
                        Ein 5V Netzteil versorgt den NodeMCU und das Relaismodul mit 5.0V Spannung. Auf dem NodeMCU steht eine geregelte 3.3.V Versorgung für die DS18B20 zur Verfügung.
                        Als Betriebssystem für den NodeMCU verwende ich tasmota in einer damals neuen Version 8.1. Alle Hardwarekomponenten sind günstig und leicht am Markt verfügbar.
                        Begonnen habe ich drei Temperatursensoren einzusetzen - ich wusste noch nicht so genau wie es werden wird. Am Ende braucht man nur einen Sensor am Heizungsrohr für den Warmwasservorlauf vom Brauchwasserspeicher in die Steigleitung.
                        Wichtig: Der NodeMCU ist echt billig gemacht und verträgt wenig Spannungsschwankungen. Schon beim Einschalten des Radios gibt es den einen oder anderen Effekt und tasmota hängt sich auf. Also umbedingt reichlich (~2) Cbulk ~330uF außen an die 3.3V Versorgungspins anschließen.

                        Kurzbeschreibung der Steuersoftware auf dem NodeMCU
                        Tasmota bietet eine schicke Möglichkeit mit "Rules" direkt und schnell auf Events zu reagieren und neue Events auszulösen. Damit lässt sich eine tolle Steuerung umsetzen. Inspiriert hat mich ein Beispiel in der Tasmotat Dokumentation der eine Poolheizung realisiert hat. Dazu gibt es noch Variablen (var) und Konstante (mem) für mehr Transparenz des Ganzen nach außen.

                        Tasmota rule1
                        Der Thermostat
                        Nachdem die Zirkulationsregelung gestartet ist stellt sich der Thermostat auf die aktuellen Temperaturen des Vorlauf ( DS18B20_2) und Rücklauf ( DS18B20_1 )ein. Es werden Grenzen zum Einschalten der Pumpe festgelegt um zu erkennen wenn Warmwasser entnommen wird. Dann erwärmt sich das Vorlaufrohr nach dem Brauchwasserspeicher, der Vorlaufsensor signalisiert einen Temperaturanstieg.

                        Event

                        • DS18B20_2:
                          -- Obere Vorlaufgrenze (UpperVL): var1
                          -- Untere Vorlaufgrenze (LowerVL): var2
                        • DS18B20_1: Aktuell nicht benutzt, LowerRL Limit: var3
                        ------------------------------------------------------------------
                        -- rule1 Thermostat und Regelung. Entscheidung ob Pumpe eingeschaltet werden soll.
                        -- 
                        -- Rücklauf DS18B20-1#temperature  
                        -- Vorlauf  DS18B20-2#temperature  
                        -- Intern   DS18B20-3#temperature  
                        --
                        -- var1 obere Temperaturschwelle Vorlauf (VL)
                        -- var2 untere Temperaturschwelle Vorlauf (VL)
                        -- var3 maximale Rücklaufschwelle (RL)
                        -- Löse event aus wenn Vorlauf temp ausserhalb oberer (var1) und unterer (var2) Schwelle, Pumpe an.
                        rule1
                        on system#boot do Backlog var1 26; var2 25; var3 25 endon
                        on DS18B20_2#temperature>%var1% do Backlog var1 %value%;var2 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event UpperVL=%value% endon
                        on DS18B20_2#temperature<%var2% do Backlog var2 %value%;var1 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event LowerVL=%value% endon
                        

                        590ca147-9635-4d3a-9bfe-433e1f634e00-grafik.png

                        Es wird Warmwasser entnommen
                        Die Zirkulationsregelung läuft und hat die obere und untere Vorlauftemperaturgrenzen ( DS18B20_2 ) eingestellt, die Pumpe ist aus ( power1 0 ).
                        Es wird Warmwasser aus dem Brauchwasserspeicher entnommen und das Vorlaufrohr erwärmt sich. Der Vorlaufsensor signalisiert einen Temperaturanstieg und die obere Vorlauftemperaturgrenze ( DS18B20_2 ) wird überschritten.
                        Beim Überschreiten wird der Thermostat neu definiert und eine Event ausgelöst UpperVL der die Pumpe einschalten soll.
                        Die Pumpe wird über rule2 gesteuert. Wenn die Zirkulationspumpe eine definierte Zeit ( mem5 ) gelaufen ist gibt es eine Wartezeit vor dem nächsten Pumpenanlauf ( mem4 ) um eine schnelles Ein-/Ausschalten zu vermeiden.

                        Tasmota rule1

                        Event

                        • UpperVL: Event zum einschalten der Pumpe für eine bestimmte Zeit.
                        • LowerVL: Event Pumpe aus
                        • LowerRL: Event Pumpe aus
                        • PumpOn=0: Pumpe/Power1 aus.
                        • PumpOn>0: Entscheiden ob und wie lange die Pumpe power1 eingeschaltet werden soll.
                        • Var4: Pumpenfreigabe in minuten, zählt von 0 aufwärts.
                        • Mem4: Grenze in Minuten wann die Pumpe wieder freigegeben wird und einschalten darf.
                        ------------------------------------------------------------------
                        -- rule2 	Controller: Pumpe einschalten und ausschalten
                        -- rule2 1	Regel einschalten
                        -- rule2 0	Regel ausschalten
                        --
                        -- Pumpe einschalten, delay %value%, Pumpe abschalten.
                        -- PumpOn=0 	Pumpe aus
                        -- PumpOn=10	Pumpe an, setze timer zum ausschalten
                        -- PumpOn=180	Pumpe an, setze timer zum ausschalten
                        -- 
                        -- Benutze Rule timer zum abschalten der pumpe
                        -- RuleTimer2 60		60sec
                        -- on Rules#Timer=2 o 		when countdown RuleTimer2 expires
                        -- var4		Wird beim löschen von power verwendet und es wird das wiedereinschalten verzögert. Die Einheit ist minuten.
                        --              Jede Minute zählt var4 im eines hoch. Nach z.B. 5 minuten kann die Pumpe wieder eingeschaltet werden.
                        -- mem4	45	Warte mem4 Minuten bis wiedereinschalten, e.g. 45 (Minuten)
                        -- mem5	19	Pumpenlaufzeit in sekunden, e.g. 19 (Sekunden)
                        rule2
                         on system#boot do Backlog var4 0.0 ; ruletimer2 0 endon
                         on event#UpperVL do event PumpOn=1 endon
                         on event#LowerVL do event PumpOn=0 endon
                         on event#PumpOn=0 do power1 off endon  
                         on event#PumpOn>0 do event ChkWait=%var4% endif endon  
                         on event#ChkWait>%mem4% do Backlog var4 0; ruletimer2 %mem5%; power1 on endon
                         on Rules#Timer=2 do power1 off endon 
                         on Time#Minute|1 do add4 1 endon
                         on var4#state==3 do power1 off endon
                        

                        Sperrzeit nach einem Pumpenlauf / Pumpenfreigabe
                        Pause für die Pumpe nach einer Zirkulationspumpzeit. Hier wird verhindert, dass die Pumpe rythmisch wieder ein und ausgeschaltet wird.

                        Event

                        • event#PumpOn>0:
                          -- Wenn die Pumpe über var4 freigegeben ist:
                          if (%var4%>=%mem4%)
                        • Time#Minute|1
                          -- Vorwärtszählen der Pumpenfreigabe pro Minute.
                        rule2
                        ...
                        on event#PumpOn>0 do if (%var4%>=%mem4%) power1 on; ruletimer2 %value%; var4 0.0 endif endon
                        ...
                        on Time#Minute|1 do add4 1 endon
                        ...
                        

                        MQTT Verbindung in der Applikation mit Tasmota

                        ------------------------------------------------------------------
                        -- MQTT Verbindung über rule3
                        -- 
                        -- Vorlauf  DS18B20-2#temperature  
                        -- var1
                        -- var4
                        rule3
                        on tele-DS18B20_2#temperature do Backlog publish stat/zirkulation/vlUpper %var1%; publish stat/zirkulation/PumpWait %var4% endon
                        on power1#state do Backlog publish stat/zirkulation/Pump %value% endon 
                        

                        Konfiguration der Applikation in Tasmota

                        -- SetOption53 1 Display hostname and IP address in GUI 0=default
                        -- SetOption0 0  Save power state and use after restart (=SaveState) 1=default
                        -- SetOption64 1   Switch between - or _ as sensor name separator, 0 = sensor name index separator is - (hyphen) (default), 1 = sensor name index separator is _ (underscore)
                        -- mem4 legt die Wartezeit bis zum Wiedereinschalten der Pumpe fest. Bei mir 45Minuten. Gerne auch anpassen.
                        -- mem5 legt die Laufzeit der Pumpe fest. Bei mir reichen 19Sekunden. Gerne auch anpassen.
                        
                        Backlog PowerOnState 0; TelePeriod 61; rule3 1; rule1 1; rule2 1; SetOption0 0; SetOption53 1; SetOption64 1; mem4 45; mem5 19
                        

                        Und wie läuft das Ganze jetzt los?
                        Mit dem folgende Kommando wird alle 61Sekunden eine Messung der Sensoren an den MQTT Broker geschickt:.

                        TelePeriod 61
                        

                        Davor ist die Option 64 wichtig, die einfach ein Problem (im iobroker) behebt, wenn man ein Eventnamen ein Bindestrich enthalten ist ;-). Daran kann man verzweifeln.

                        SetOption64 1;
                        

                        Und folgend werden die rules aktiviert, damit es auch eine Steuerung gibt:

                        rule3 1; rule1 1; rule2 1;
                        

                        Typischer Log aus der Tasmota console

                        8:50:57 MQT: tele/zirkulation/STATE = {"Time":"2020-03-01T18:50:57","Uptime":"0T02:27:12","UptimeSec":8832,"Heap":23,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"blabla","BSSId":"Z0:B0:VV:3K:D6:20","Channel":11,"RSSI":100,"Signal":-50,"LinkCount":1,"Downtime":"0T00:00:06"}}
                        
                        18:50:57 MQT: tele/zirkulation/SENSOR = {"Time":"2020-03-01T18:50:57","DS18B20_1":{"Id":"01143B9799AA","Temperature":26.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":33.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.1},"TempUnit":"C"}
                        
                        18:50:57 RUL: TELE-DS18B20_1#TEMPERATURE performs "Backlog publish stat/zirkulation/rl 26.1; publish stat/zirkulation/rlUpper 29.100"
                        
                        18:50:57 RUL: TELE-DS18B20_2#TEMPERATURE performs "Backlog publish stat/zirkulation/vl 33.9; publish stat/zirkulation/vlUpper 34.600; publish stat/zirkulation/vlLower 33.600"
                        
                        18:50:57 RUL: TELE-DS18B20_3#TEMPERATURE performs "publish stat/zirkulation/int 22.1"
                        18:50:57 MQT: stat/zirkulation/int = 22.1
                        18:50:57 MQT: stat/zirkulation/rl = 26.1
                        18:50:58 MQT: stat/zirkulation/rlUpper = 29.100
                        18:50:58 MQT: stat/zirkulation/vl = 33.9
                        18:50:58 MQT: stat/zirkulation/vlUpper = 34.600
                        18:50:58 MQT: stat/zirkulation/vlLower = 33.600
                        18:51:00 RUL: TIME#MINUTE|1 performs "add4 1"
                        18:51:00 MQT: stat/zirkulation/RESULT = {"Add4":"31.000"}
                        18:51:00 RUL: VAR4#STATE performs "publish stat/zirkulation/PumpWait 31.000"
                        18:51:00 MQT: stat/zirkulation/PumpWait = 31.000
                        

                        Kurzbeschreibung iobroker
                        Info

                            Plattform: linux
                            Betriebssystem: linux
                            Die Architektur: arm
                            CPUs: 4
                            Geschwindigkeit: 1500 MHz
                            Modell: ARMv7 Processor rev 3 (v7l)
                            RAM: 3.7 GB
                            System-Betriebszeit: 19 T. 00:08:11
                            Node.js: v12.22.6
                            NPM: 6.14.15
                            Datenträgergröße: 29.0 GiB
                            Datenträger verfügbar: 26.0 GiB
                            Adapter-Anzahl: 362
                            Betriebszeit: 16 T. 00:39:00
                            Aktive Instanzen: 17
                            location: /opt/iobroker/
                        

                        JS zirkulation ZirkParseSTATE
                        Bei mir heisst der Tasmota MQTT client "zirkulation". Damit kommt der Name relativ oft in dem JS vor.
                        Hier werden die vom MQTT Client/Server glieferten Daten vom Tasmota client verarbeitet und umgewandelt. Das liegt daran dass ich keinen besseren Weg gefunden habe die Daten im VIS json table vom tasmota client zu bekommen.

                        Hier nun das JS:

                        //
                        const util = require('util');
                        // STATE
                        // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                        //
                        createState('zirkulation.TimeStampSTATE'); 
                        createState('zirkulation.UpTimeSTATE'); 
                        
                        createState('zirkulation.jsonSENSOR'); 
                        createState('zirkulation.jsonSTATE'); 
                        
                        // prepare tasmota format for json format
                        createState('zirkulation.PowerSTATE'); 
                        
                        //////////////////////////////////////////////////////////////////////////
                        // Convert map to JSON string
                        // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
                        // 
                        // @param 
                        // @return 
                        function mapToJson(map) {
                          return JSON.stringify([...map]);
                        }
                        
                        //////////////////////////////////////////////////////////////////////////
                        // convert JSON string key value pairs to Map key value pairs
                        // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
                        //
                        // @param jsonStr key value pairs
                        // @return map converted from jsonStr to map key value pairs.
                        function jsonToMap(jsonStr) {
                          return new Map(JSON.parse(jsonStr));
                        }
                        
                        on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                        
                        var jsonSensorText = '';
                        jsonSensorText = obj.state.val;
                        
                        // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                        try {obj = JSON.parse(jsonSensorText);
                           } catch (e) {
                                   console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                   return;
                            }
                        
                        //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                        
                        var sTimeStamp =    obj.Time;
                        var fUptimeSec =    obj.UptimeSec;
                        var sPOWER =        obj.POWER;       // "POWER":"OFF"
                        var fPOWER = 0;
                        
                        if (sPOWER == "OFF") {
                            fPOWER = 0;
                        } else {
                            fPOWER = 1;
                        }
                        
                        setState('javascript.0.zirkulation.TimeStampSTATE', sTimeStamp , true);
                        setState('javascript.0.zirkulation.UpTimeSTATE', fUptimeSec , true);
                        setState('javascript.0.zirkulation.PowerSTATE', fPOWER , true);
                        
                        });
                        
                        
                        /////////////////////////////////////////////////////////////////////////
                        // preapre tasmota json format to use in iobroker vis jason table
                        // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                        on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                        
                            var jsonSensorText = '';
                            jsonSensorText = obj.state.val;
                        
                            var myMap = new Map();
                            
                            try {obj = JSON.parse(jsonSensorText);
                                } catch (e) {
                                   console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                   return;
                                }
                        
                            // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                            for (let [key, value] of Object.entries(obj)) {
                                
                                if ( typeof value === 'object' ) {
                                    // iterate one level down
                                    for (let [key2, value2] of Object.entries(value)) {
                                        // log level 2
                                        // console.log(key + ":" + key2 + "=" + value2);
                                        myMap.set(key + ":" + key2, value2);
                                    }
                                } else {
                                    // log level 1
                                    // console.log(key + "=" + value);
                                    myMap.set(key , value);
                                }       
                        
                            }
                            
                            var jsonString = mapToJson(myMap);
                            //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                            //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                        
                            setState('javascript.0.zirkulation.jsonSTATE', jsonString , true);
                        
                        });
                        
                        /////////////////////////////////////////////////////////////////////////
                        // preapre tasmota json format to use in iobroker vis jason table
                        // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                        on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                        
                            var jsonSensorText = '';
                            jsonSensorText = obj.state.val;
                        
                            var myMap = new Map();
                            
                            try {obj = JSON.parse(jsonSensorText);
                                } catch (e) {
                                   console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                   return;
                                }
                        
                            // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                            for (let [key, value] of Object.entries(obj)) {
                                
                                if ( typeof value === 'object' ) {
                                    // iterate one level down
                                    for (let [key2, value2] of Object.entries(value)) {
                                        // log level 2
                                        // console.log(key + ":" + key2 + "=" + value2);
                                        myMap.set(key + ":" + key2, value2);
                                    }
                                } else {
                                    // log level 1
                                    // console.log(key + "=" + value);
                                    myMap.set(key , value);
                                }       
                        
                            }
                            
                            var jsonString = mapToJson(myMap);
                            //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                            //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                        
                            setState('javascript.0.zirkulation.jsonSENSOR', jsonString , true);
                        
                        });
                        
                        

                        JS zirkulation ZirkParseSENSOR
                        Hier wirkt nun die spezielle Option aus der Tasmota Konfiguration um das "-" in ein "_" zu wandeln.

                        //
                        const util = require('util');
                        // SENSOR
                        // {"Time":"2020-03-28T19:07:12","DS18B20_1":{"Id":"01143B9799AA","Temperature":30.4},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":36.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":24.6},"TempUnit":"C"}
                        // 
                        createState('zirkulation.TimeStampSENSOR'); 
                        createState('zirkulation.VorlaufTempSENSOR');
                        createState('zirkulation.RuecklaufTempSENSOR');
                        createState('zirkulation.InnerhalbTempSENSOR');
                        
                        on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                        
                        var jsonSensorText = '';
                        jsonSensorText = obj.state.val;
                        
                        try {obj = JSON.parse(jsonSensorText);
                           } catch (e) {
                                   console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                   return;
                            }
                        //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                        
                        // {"Time":"2020-06-06T15:11:44","DS18B20_1":{"Id":"01143B9799AA","Temperature":21.8},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":35.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.6},"TempUnit":"C"}   
                        var fRLTemp = obj.DS18B20_1.Temperature; // RL
                        var fVLTemp = obj.DS18B20_2.Temperature; // VL
                        var fINTemp = obj.DS18B20_3.Temperature; // IN
                        var sTimeStamp = obj.Time;
                        
                        setState('javascript.0.zirkulation.TimeStampSENSOR', sTimeStamp , true);
                        setState('javascript.0.zirkulation.InnerhalbTempSENSOR', fINTemp , true);
                        setState('javascript.0.zirkulation.VorlaufTempSENSOR', fVLTemp   , true);
                        setState('javascript.0.zirkulation.RuecklaufTempSENSOR', fRLTemp , true);
                        
                        
                        });
                        
                        
                        
                        AndreiosA Offline
                        AndreiosA Offline
                        Andreios
                        Forum Testing
                        schrieb am zuletzt editiert von
                        #11

                        Sehr interessant, hier zu lesen.
                        Ich bin gerade dabei, meine eigene Heizung(über)steuerung zu bauen und da soll auch die Zirkulation mit einbezogen werden.
                        Wie bei vielen Anderen hängt die bei mir aktuell auch an einer Zeitschaltuhr und das ist mir schon lange ein Dorn im Auge.

                        Die Idee zur eigenen Heizungssteuerung habe ich auch schon etwas länger.
                        Um das Verhalten der Heizung und die Änderung im Verhalten durch den Einbau der automatischen Heizungsventile (Zuerst Max!, inzwischen Homematic) zu beobachten hatte ich schon Temperaturen über DS18B20-Sensoren an einem Arduino gemessen und ioBroker (früher FHEM) per MQTT übermittelt und dort auch die Historie aufgezeichnet.
                        Wie man an dem "früher" sieht, beschäftige ich mich nicht erst ein paar Tage mit dem Thema.

                        Zum Thema Zirkulationspumpe bin ich mir aber noch nicht so richtig einig, wie ich diese sinnvoll schalte.

                        Ein paar Parameter/Ideen dazu:

                        • Die Anwesenheit von Personen im Haushalt wird festgestellt. Falls also niemand im/am Haus ist, kann die Pumpe erst einmal aus bleiben. Einziges Problem ist, wenn andere Personen im Haus sind, die nicht durch die alktuelle Erkennung erkannt werden (Erkennung geht aktuell über die Mobiltelefone).

                        • Wenn jemand im Haus ist, kann eine Nachtzeit eingeplant werden, so dass zu normalen Schlafenszeiten die Pumpe auch aus bleibt.

                        • Vor- und Rücklauf wird gemessen, bei kleiner Differenz kann die Pumpe aus bleiben.
                          (Hier muss ich noch sehen, ob ich den Vorlauf-Sensor weiter vom Speicher entfernt montieren kann. Dann könnte ich feststellen, ob genügend Wasser entnommen wird, um warm zu bleiben. Da jedoch die Zirkulationsleitung keine Ringleitung ist, sondern sich, weiter entfernt und wahrscheinlich nicht erreichbar, in verschiedene Richtungen teilt, kann es auch sein, dass nur eine Zapfstelle noch warmes Wasser hat und die anderen bleiben kalt.)

                        • Wegen dem Salmonellenthema muss die Leitung regelmäßig gespült werden, es darf also nicht passieren, dass die Pumpe dauerhaft aus bleibt.

                        • Was ich nicht so prickelnd finde ist, wenn zuerst Wasser verbraucht werden muss, damit die Pumpe anspringt. Das entspricht nicht dem normalen Gebrauch, weil man dann ja warmes Wasser entnehmen will und dann lässt man das so lange laufen, bis es warm wird. Das widerspricht dem (Komfort-)Gedanken bei der Zirkulationspumpe.

                        Fazit:

                        Eine Anwesenheitserkennung auch für Haushaltsfremde muss einfach auf den Datenpunkt "Jemand anwesend" geführt werden. Dies kann auch später nachgerüstet werden, wenn ich dafür eine handlebare Lösung habe.

                        Vielleicht läuft die Pumpe dann öfter, als sie wirklich muss, aber ich denke, der Start der Zirkulationspumpe wird aus der Anwesenheit, der Nachtzeit und der Temperaturdifferenz Vor-/Rücklauf erfolgen.
                        Der Fetenschalter kann da auch noch mit einfliessen und die Nachtzeit übersteuern.

                        Ich denke, damit läuft es immer noch deutlich besser, als über die Zeitschaltuhr!

                        Schöne Grüße
                        Andreas

                        ioBroker auf Raspberry 4 mit SSD. Homematik IP mit CCU 3. Shelly. MySQL. Arduino. ...

                        Meine Posts sind subjektiv und manipulativ, erheben Anspruch auf Allwissenheit und können Spuren von Ironie oder Sarkasmus enthalten. ;-)

                        HomoranH 1 Antwort Letzte Antwort
                        0
                        • AndreiosA Andreios

                          Sehr interessant, hier zu lesen.
                          Ich bin gerade dabei, meine eigene Heizung(über)steuerung zu bauen und da soll auch die Zirkulation mit einbezogen werden.
                          Wie bei vielen Anderen hängt die bei mir aktuell auch an einer Zeitschaltuhr und das ist mir schon lange ein Dorn im Auge.

                          Die Idee zur eigenen Heizungssteuerung habe ich auch schon etwas länger.
                          Um das Verhalten der Heizung und die Änderung im Verhalten durch den Einbau der automatischen Heizungsventile (Zuerst Max!, inzwischen Homematic) zu beobachten hatte ich schon Temperaturen über DS18B20-Sensoren an einem Arduino gemessen und ioBroker (früher FHEM) per MQTT übermittelt und dort auch die Historie aufgezeichnet.
                          Wie man an dem "früher" sieht, beschäftige ich mich nicht erst ein paar Tage mit dem Thema.

                          Zum Thema Zirkulationspumpe bin ich mir aber noch nicht so richtig einig, wie ich diese sinnvoll schalte.

                          Ein paar Parameter/Ideen dazu:

                          • Die Anwesenheit von Personen im Haushalt wird festgestellt. Falls also niemand im/am Haus ist, kann die Pumpe erst einmal aus bleiben. Einziges Problem ist, wenn andere Personen im Haus sind, die nicht durch die alktuelle Erkennung erkannt werden (Erkennung geht aktuell über die Mobiltelefone).

                          • Wenn jemand im Haus ist, kann eine Nachtzeit eingeplant werden, so dass zu normalen Schlafenszeiten die Pumpe auch aus bleibt.

                          • Vor- und Rücklauf wird gemessen, bei kleiner Differenz kann die Pumpe aus bleiben.
                            (Hier muss ich noch sehen, ob ich den Vorlauf-Sensor weiter vom Speicher entfernt montieren kann. Dann könnte ich feststellen, ob genügend Wasser entnommen wird, um warm zu bleiben. Da jedoch die Zirkulationsleitung keine Ringleitung ist, sondern sich, weiter entfernt und wahrscheinlich nicht erreichbar, in verschiedene Richtungen teilt, kann es auch sein, dass nur eine Zapfstelle noch warmes Wasser hat und die anderen bleiben kalt.)

                          • Wegen dem Salmonellenthema muss die Leitung regelmäßig gespült werden, es darf also nicht passieren, dass die Pumpe dauerhaft aus bleibt.

                          • Was ich nicht so prickelnd finde ist, wenn zuerst Wasser verbraucht werden muss, damit die Pumpe anspringt. Das entspricht nicht dem normalen Gebrauch, weil man dann ja warmes Wasser entnehmen will und dann lässt man das so lange laufen, bis es warm wird. Das widerspricht dem (Komfort-)Gedanken bei der Zirkulationspumpe.

                          Fazit:

                          Eine Anwesenheitserkennung auch für Haushaltsfremde muss einfach auf den Datenpunkt "Jemand anwesend" geführt werden. Dies kann auch später nachgerüstet werden, wenn ich dafür eine handlebare Lösung habe.

                          Vielleicht läuft die Pumpe dann öfter, als sie wirklich muss, aber ich denke, der Start der Zirkulationspumpe wird aus der Anwesenheit, der Nachtzeit und der Temperaturdifferenz Vor-/Rücklauf erfolgen.
                          Der Fetenschalter kann da auch noch mit einfliessen und die Nachtzeit übersteuern.

                          Ich denke, damit läuft es immer noch deutlich besser, als über die Zeitschaltuhr!

                          HomoranH Nicht stören
                          HomoranH Nicht stören
                          Homoran
                          Global Moderator Administrators
                          schrieb am zuletzt editiert von
                          #12

                          @andreas-5 sagte in WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten:

                          Wegen dem Salmonellenthema

                          nix Salmo, Legio!

                          kein Support per PN! - Fragen im Forum stellen - es gibt fast nichts, was nicht auch für andere interessant ist.

                          Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.

                          der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

                          AndreiosA 1 Antwort Letzte Antwort
                          0
                          • HomoranH Homoran

                            @andreas-5 sagte in WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten:

                            Wegen dem Salmonellenthema

                            nix Salmo, Legio!

                            AndreiosA Offline
                            AndreiosA Offline
                            Andreios
                            Forum Testing
                            schrieb am zuletzt editiert von
                            #13

                            @homoran sagte in WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten:

                            @andreas-5 sagte in WW Zirkulationspumpe bedarfsgerecht ein- und ausschalten:

                            Wegen dem Salmonellenthema

                            nix Salmo, Legio!

                            Uuuppsss. Na, dann muss ich halt Eier durch die Leitung schicken. ;-)

                            Schöne Grüße
                            Andreas

                            ioBroker auf Raspberry 4 mit SSD. Homematik IP mit CCU 3. Shelly. MySQL. Arduino. ...

                            Meine Posts sind subjektiv und manipulativ, erheben Anspruch auf Allwissenheit und können Spuren von Ironie oder Sarkasmus enthalten. ;-)

                            1 Antwort Letzte Antwort
                            1
                            • Oliver HirschO Offline
                              Oliver HirschO Offline
                              Oliver Hirsch
                              schrieb am zuletzt editiert von
                              #14

                              vielen Dank für die tolle Anleitung, ich möchte genau dies umsetzen.
                              Ich verwende aktuell einen ESP32 mit dem ich auch schon einige Versuche gemacht habe.
                              Leider hat er kein Script Feld nur dieses Berry Scritping Console.
                              Die Zeilen aus deinem Programm, Rules kann ich nur einzeln in die Console eintragen, so funktioniert es aber nicht?
                              Sehe ich das richtig?
                              Wäre super wenn mir jemand ein paar Tipps geben könnte.
                              Ich bin leider Anfänger.

                              Viele Grüße
                              Oliver

                              alkA 1 Antwort Letzte Antwort
                              0
                              • M Online
                                M Online
                                mading
                                schrieb am zuletzt editiert von mading
                                #15

                                Ich hoffe ich schiebe das Thema nicht zu weit mit meinem Post in eine etwas andere Richtung, möchte aber dennoch den Tipp geben: wer eine Wilo Zirkulationspumpe hat (die m.W.n recht weit verbreitet ist), kann statt der Verkabelung zur Heizung ein Kabel mit Schukostecker anbringen. Mit einer Schaltsteckdose und z.B. einem Homematic Taster im Bad lässt sich dann die ZP einschalten, da sie läuft, wenn sie Strom bekommt. Ein einfaches Blockly mit Timeout ermöglicht ein Bedarfsgerechtes Einschalten. Ich plane einen homematic Taster (Aufputz) anzubringen, damit die ZP eingeschaltet werden kann.

                                Beispiel ZP von Wilo (man beachte den Stecker unten, der einfach raus gezogen werden kann):

                                0A17679C-0217-493F-A7E4-037F39815711.jpeg

                                Und das Kabel: https://www.heiz24.de/Wilo-Elektrisches-Zubehoer-Connector-NEU?curr=EUR&gclid=Cj0KCQjwhY-aBhCUARIsALNIC06gspkP9luaXC_5Y0oVk1ULUGd2xwHOsL3tzYE_mYYKPe0GCmSD4JsaAjAZEALw_wcB

                                Das Kabel ist nicht billig, ein Elektriker wäre aber teurer, wenn er was an der Verkabelung ändern müsste.

                                1 Antwort Letzte Antwort
                                0
                                • Oliver HirschO Oliver Hirsch

                                  vielen Dank für die tolle Anleitung, ich möchte genau dies umsetzen.
                                  Ich verwende aktuell einen ESP32 mit dem ich auch schon einige Versuche gemacht habe.
                                  Leider hat er kein Script Feld nur dieses Berry Scritping Console.
                                  Die Zeilen aus deinem Programm, Rules kann ich nur einzeln in die Console eintragen, so funktioniert es aber nicht?
                                  Sehe ich das richtig?
                                  Wäre super wenn mir jemand ein paar Tipps geben könnte.
                                  Ich bin leider Anfänger.

                                  Viele Grüße
                                  Oliver

                                  alkA Offline
                                  alkA Offline
                                  alk
                                  schrieb am zuletzt editiert von alk
                                  #16

                                  @oliver-hirsch Servus Oliver,
                                  Ich kann dir nur beim Einsatz von Tasmota weiterhelfen. Das gibt es auch für den ESP32, wenn ich nicht irre. Und dafür kannst du die Script Beschreibung oben in den schwarzen Feldern als copy & paste verwenden. Und genau so einfach jede rule in die Script Console von Tasmota kopieren. Mit einem anschließenden Enter wird das Kommando übernommen.
                                  Z.b. Wie aus der Beschreibung ist dies in die Tasmota Konsole für die erste rule komplett zu kopieren:

                                  rule1
                                  on system#boot do Backlog var1 26; var2 25; var3 25 endon
                                  on DS18B20_2#temperature>%var1% do Backlog var1 %value%;var2 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event UpperVL=%value% endon
                                  on DS18B20_2#temperature<%var2% do Backlog var2 %value%;var1 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event LowerVL=%value% endon
                                  

                                  Das wars für rule1. Und dann rule2 und rule3 gleich hinterher kopieren.

                                  Alle Zeilen mit

                                  — kannst du weglassen, nur Kommentar
                                  

                                  Dann alles starten mit diesem Kommando:

                                  Backlog PowerOnState 0; TelePeriod 61; rule3 1; rule1 1; rule2 1; SetOption0 0; SetOption53 1; SetOption64 1; mem4 45; mem5 19
                                  

                                  Dann läuft die Nummer auf dem ESP8266 oder ESP32.

                                  Ich hoffe das hat Dir weiter geholfen ?

                                  LG
                                  alk

                                  • DIY Electronics that do their job
                                  • EV, WB, PV + Battery and optimized charging ;-)
                                  1 Antwort Letzte Antwort
                                  0
                                  • alkA alk

                                    Anwendungsbeschreibung
                                    Komponenten

                                    • Brauchwasserspeicher (Warmwasser)
                                    • Zirkulationspumpe in der Steigleitung
                                    • NodeMCU V2.0 (ESP8266) OS:tasmota Doris 8.1
                                    • 3x Temperaturfühler DS18B20 (1wire) zum Messen von der Vorlauftemperatur
                                    • Relaismodul zum Schalten der Zirkulationspumpe

                                    Ziel
                                    Ich möchte mit der Steuerung Energiekosten sparen. Der aktuell Aufbau startet die Zirkulationspumpe mit einer Zeitschaltuhr, z.B. Morgens 30min, Mittag 30min und Abends 30min. Der Aufbau ist wohl sehr weit verbreitet und ist mir schon eine ganze Weile in Dorn im Auge weil wenig innovativ.

                                    Die Zirkulationspumpe soll bedarfsgerecht eingeschaltet werden und die aktuelle Zeitschaltuhr kommt weg. Bedarfsgerecht meint beim Aufdrehen vom Warmwasser im Gebäude soll die Zirkulationspumpe starten und die Steigleitung mit Warmwasser befüllen. Damit ist das Warmwasser schneller an der Bedarfsstelle im Bad/WC.

                                    Kurzbeschreibung der Steuerhardware
                                    Ein 5V Netzteil versorgt den NodeMCU und das Relaismodul mit 5.0V Spannung. Auf dem NodeMCU steht eine geregelte 3.3.V Versorgung für die DS18B20 zur Verfügung.
                                    Als Betriebssystem für den NodeMCU verwende ich tasmota in einer damals neuen Version 8.1. Alle Hardwarekomponenten sind günstig und leicht am Markt verfügbar.
                                    Begonnen habe ich drei Temperatursensoren einzusetzen - ich wusste noch nicht so genau wie es werden wird. Am Ende braucht man nur einen Sensor am Heizungsrohr für den Warmwasservorlauf vom Brauchwasserspeicher in die Steigleitung.
                                    Wichtig: Der NodeMCU ist echt billig gemacht und verträgt wenig Spannungsschwankungen. Schon beim Einschalten des Radios gibt es den einen oder anderen Effekt und tasmota hängt sich auf. Also umbedingt reichlich (~2) Cbulk ~330uF außen an die 3.3V Versorgungspins anschließen.

                                    Kurzbeschreibung der Steuersoftware auf dem NodeMCU
                                    Tasmota bietet eine schicke Möglichkeit mit "Rules" direkt und schnell auf Events zu reagieren und neue Events auszulösen. Damit lässt sich eine tolle Steuerung umsetzen. Inspiriert hat mich ein Beispiel in der Tasmotat Dokumentation der eine Poolheizung realisiert hat. Dazu gibt es noch Variablen (var) und Konstante (mem) für mehr Transparenz des Ganzen nach außen.

                                    Tasmota rule1
                                    Der Thermostat
                                    Nachdem die Zirkulationsregelung gestartet ist stellt sich der Thermostat auf die aktuellen Temperaturen des Vorlauf ( DS18B20_2) und Rücklauf ( DS18B20_1 )ein. Es werden Grenzen zum Einschalten der Pumpe festgelegt um zu erkennen wenn Warmwasser entnommen wird. Dann erwärmt sich das Vorlaufrohr nach dem Brauchwasserspeicher, der Vorlaufsensor signalisiert einen Temperaturanstieg.

                                    Event

                                    • DS18B20_2:
                                      -- Obere Vorlaufgrenze (UpperVL): var1
                                      -- Untere Vorlaufgrenze (LowerVL): var2
                                    • DS18B20_1: Aktuell nicht benutzt, LowerRL Limit: var3
                                    ------------------------------------------------------------------
                                    -- rule1 Thermostat und Regelung. Entscheidung ob Pumpe eingeschaltet werden soll.
                                    -- 
                                    -- Rücklauf DS18B20-1#temperature  
                                    -- Vorlauf  DS18B20-2#temperature  
                                    -- Intern   DS18B20-3#temperature  
                                    --
                                    -- var1 obere Temperaturschwelle Vorlauf (VL)
                                    -- var2 untere Temperaturschwelle Vorlauf (VL)
                                    -- var3 maximale Rücklaufschwelle (RL)
                                    -- Löse event aus wenn Vorlauf temp ausserhalb oberer (var1) und unterer (var2) Schwelle, Pumpe an.
                                    rule1
                                    on system#boot do Backlog var1 26; var2 25; var3 25 endon
                                    on DS18B20_2#temperature>%var1% do Backlog var1 %value%;var2 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event UpperVL=%value% endon
                                    on DS18B20_2#temperature<%var2% do Backlog var2 %value%;var1 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event LowerVL=%value% endon
                                    

                                    590ca147-9635-4d3a-9bfe-433e1f634e00-grafik.png

                                    Es wird Warmwasser entnommen
                                    Die Zirkulationsregelung läuft und hat die obere und untere Vorlauftemperaturgrenzen ( DS18B20_2 ) eingestellt, die Pumpe ist aus ( power1 0 ).
                                    Es wird Warmwasser aus dem Brauchwasserspeicher entnommen und das Vorlaufrohr erwärmt sich. Der Vorlaufsensor signalisiert einen Temperaturanstieg und die obere Vorlauftemperaturgrenze ( DS18B20_2 ) wird überschritten.
                                    Beim Überschreiten wird der Thermostat neu definiert und eine Event ausgelöst UpperVL der die Pumpe einschalten soll.
                                    Die Pumpe wird über rule2 gesteuert. Wenn die Zirkulationspumpe eine definierte Zeit ( mem5 ) gelaufen ist gibt es eine Wartezeit vor dem nächsten Pumpenanlauf ( mem4 ) um eine schnelles Ein-/Ausschalten zu vermeiden.

                                    Tasmota rule1

                                    Event

                                    • UpperVL: Event zum einschalten der Pumpe für eine bestimmte Zeit.
                                    • LowerVL: Event Pumpe aus
                                    • LowerRL: Event Pumpe aus
                                    • PumpOn=0: Pumpe/Power1 aus.
                                    • PumpOn>0: Entscheiden ob und wie lange die Pumpe power1 eingeschaltet werden soll.
                                    • Var4: Pumpenfreigabe in minuten, zählt von 0 aufwärts.
                                    • Mem4: Grenze in Minuten wann die Pumpe wieder freigegeben wird und einschalten darf.
                                    ------------------------------------------------------------------
                                    -- rule2 	Controller: Pumpe einschalten und ausschalten
                                    -- rule2 1	Regel einschalten
                                    -- rule2 0	Regel ausschalten
                                    --
                                    -- Pumpe einschalten, delay %value%, Pumpe abschalten.
                                    -- PumpOn=0 	Pumpe aus
                                    -- PumpOn=10	Pumpe an, setze timer zum ausschalten
                                    -- PumpOn=180	Pumpe an, setze timer zum ausschalten
                                    -- 
                                    -- Benutze Rule timer zum abschalten der pumpe
                                    -- RuleTimer2 60		60sec
                                    -- on Rules#Timer=2 o 		when countdown RuleTimer2 expires
                                    -- var4		Wird beim löschen von power verwendet und es wird das wiedereinschalten verzögert. Die Einheit ist minuten.
                                    --              Jede Minute zählt var4 im eines hoch. Nach z.B. 5 minuten kann die Pumpe wieder eingeschaltet werden.
                                    -- mem4	45	Warte mem4 Minuten bis wiedereinschalten, e.g. 45 (Minuten)
                                    -- mem5	19	Pumpenlaufzeit in sekunden, e.g. 19 (Sekunden)
                                    rule2
                                     on system#boot do Backlog var4 0.0 ; ruletimer2 0 endon
                                     on event#UpperVL do event PumpOn=1 endon
                                     on event#LowerVL do event PumpOn=0 endon
                                     on event#PumpOn=0 do power1 off endon  
                                     on event#PumpOn>0 do event ChkWait=%var4% endif endon  
                                     on event#ChkWait>%mem4% do Backlog var4 0; ruletimer2 %mem5%; power1 on endon
                                     on Rules#Timer=2 do power1 off endon 
                                     on Time#Minute|1 do add4 1 endon
                                     on var4#state==3 do power1 off endon
                                    

                                    Sperrzeit nach einem Pumpenlauf / Pumpenfreigabe
                                    Pause für die Pumpe nach einer Zirkulationspumpzeit. Hier wird verhindert, dass die Pumpe rythmisch wieder ein und ausgeschaltet wird.

                                    Event

                                    • event#PumpOn>0:
                                      -- Wenn die Pumpe über var4 freigegeben ist:
                                      if (%var4%>=%mem4%)
                                    • Time#Minute|1
                                      -- Vorwärtszählen der Pumpenfreigabe pro Minute.
                                    rule2
                                    ...
                                    on event#PumpOn>0 do if (%var4%>=%mem4%) power1 on; ruletimer2 %value%; var4 0.0 endif endon
                                    ...
                                    on Time#Minute|1 do add4 1 endon
                                    ...
                                    

                                    MQTT Verbindung in der Applikation mit Tasmota

                                    ------------------------------------------------------------------
                                    -- MQTT Verbindung über rule3
                                    -- 
                                    -- Vorlauf  DS18B20-2#temperature  
                                    -- var1
                                    -- var4
                                    rule3
                                    on tele-DS18B20_2#temperature do Backlog publish stat/zirkulation/vlUpper %var1%; publish stat/zirkulation/PumpWait %var4% endon
                                    on power1#state do Backlog publish stat/zirkulation/Pump %value% endon 
                                    

                                    Konfiguration der Applikation in Tasmota

                                    -- SetOption53 1 Display hostname and IP address in GUI 0=default
                                    -- SetOption0 0  Save power state and use after restart (=SaveState) 1=default
                                    -- SetOption64 1   Switch between - or _ as sensor name separator, 0 = sensor name index separator is - (hyphen) (default), 1 = sensor name index separator is _ (underscore)
                                    -- mem4 legt die Wartezeit bis zum Wiedereinschalten der Pumpe fest. Bei mir 45Minuten. Gerne auch anpassen.
                                    -- mem5 legt die Laufzeit der Pumpe fest. Bei mir reichen 19Sekunden. Gerne auch anpassen.
                                    
                                    Backlog PowerOnState 0; TelePeriod 61; rule3 1; rule1 1; rule2 1; SetOption0 0; SetOption53 1; SetOption64 1; mem4 45; mem5 19
                                    

                                    Und wie läuft das Ganze jetzt los?
                                    Mit dem folgende Kommando wird alle 61Sekunden eine Messung der Sensoren an den MQTT Broker geschickt:.

                                    TelePeriod 61
                                    

                                    Davor ist die Option 64 wichtig, die einfach ein Problem (im iobroker) behebt, wenn man ein Eventnamen ein Bindestrich enthalten ist ;-). Daran kann man verzweifeln.

                                    SetOption64 1;
                                    

                                    Und folgend werden die rules aktiviert, damit es auch eine Steuerung gibt:

                                    rule3 1; rule1 1; rule2 1;
                                    

                                    Typischer Log aus der Tasmota console

                                    8:50:57 MQT: tele/zirkulation/STATE = {"Time":"2020-03-01T18:50:57","Uptime":"0T02:27:12","UptimeSec":8832,"Heap":23,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"blabla","BSSId":"Z0:B0:VV:3K:D6:20","Channel":11,"RSSI":100,"Signal":-50,"LinkCount":1,"Downtime":"0T00:00:06"}}
                                    
                                    18:50:57 MQT: tele/zirkulation/SENSOR = {"Time":"2020-03-01T18:50:57","DS18B20_1":{"Id":"01143B9799AA","Temperature":26.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":33.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.1},"TempUnit":"C"}
                                    
                                    18:50:57 RUL: TELE-DS18B20_1#TEMPERATURE performs "Backlog publish stat/zirkulation/rl 26.1; publish stat/zirkulation/rlUpper 29.100"
                                    
                                    18:50:57 RUL: TELE-DS18B20_2#TEMPERATURE performs "Backlog publish stat/zirkulation/vl 33.9; publish stat/zirkulation/vlUpper 34.600; publish stat/zirkulation/vlLower 33.600"
                                    
                                    18:50:57 RUL: TELE-DS18B20_3#TEMPERATURE performs "publish stat/zirkulation/int 22.1"
                                    18:50:57 MQT: stat/zirkulation/int = 22.1
                                    18:50:57 MQT: stat/zirkulation/rl = 26.1
                                    18:50:58 MQT: stat/zirkulation/rlUpper = 29.100
                                    18:50:58 MQT: stat/zirkulation/vl = 33.9
                                    18:50:58 MQT: stat/zirkulation/vlUpper = 34.600
                                    18:50:58 MQT: stat/zirkulation/vlLower = 33.600
                                    18:51:00 RUL: TIME#MINUTE|1 performs "add4 1"
                                    18:51:00 MQT: stat/zirkulation/RESULT = {"Add4":"31.000"}
                                    18:51:00 RUL: VAR4#STATE performs "publish stat/zirkulation/PumpWait 31.000"
                                    18:51:00 MQT: stat/zirkulation/PumpWait = 31.000
                                    

                                    Kurzbeschreibung iobroker
                                    Info

                                        Plattform: linux
                                        Betriebssystem: linux
                                        Die Architektur: arm
                                        CPUs: 4
                                        Geschwindigkeit: 1500 MHz
                                        Modell: ARMv7 Processor rev 3 (v7l)
                                        RAM: 3.7 GB
                                        System-Betriebszeit: 19 T. 00:08:11
                                        Node.js: v12.22.6
                                        NPM: 6.14.15
                                        Datenträgergröße: 29.0 GiB
                                        Datenträger verfügbar: 26.0 GiB
                                        Adapter-Anzahl: 362
                                        Betriebszeit: 16 T. 00:39:00
                                        Aktive Instanzen: 17
                                        location: /opt/iobroker/
                                    

                                    JS zirkulation ZirkParseSTATE
                                    Bei mir heisst der Tasmota MQTT client "zirkulation". Damit kommt der Name relativ oft in dem JS vor.
                                    Hier werden die vom MQTT Client/Server glieferten Daten vom Tasmota client verarbeitet und umgewandelt. Das liegt daran dass ich keinen besseren Weg gefunden habe die Daten im VIS json table vom tasmota client zu bekommen.

                                    Hier nun das JS:

                                    //
                                    const util = require('util');
                                    // STATE
                                    // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                                    //
                                    createState('zirkulation.TimeStampSTATE'); 
                                    createState('zirkulation.UpTimeSTATE'); 
                                    
                                    createState('zirkulation.jsonSENSOR'); 
                                    createState('zirkulation.jsonSTATE'); 
                                    
                                    // prepare tasmota format for json format
                                    createState('zirkulation.PowerSTATE'); 
                                    
                                    //////////////////////////////////////////////////////////////////////////
                                    // Convert map to JSON string
                                    // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
                                    // 
                                    // @param 
                                    // @return 
                                    function mapToJson(map) {
                                      return JSON.stringify([...map]);
                                    }
                                    
                                    //////////////////////////////////////////////////////////////////////////
                                    // convert JSON string key value pairs to Map key value pairs
                                    // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
                                    //
                                    // @param jsonStr key value pairs
                                    // @return map converted from jsonStr to map key value pairs.
                                    function jsonToMap(jsonStr) {
                                      return new Map(JSON.parse(jsonStr));
                                    }
                                    
                                    on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                                    
                                    var jsonSensorText = '';
                                    jsonSensorText = obj.state.val;
                                    
                                    // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                                    try {obj = JSON.parse(jsonSensorText);
                                       } catch (e) {
                                               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                               return;
                                        }
                                    
                                    //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                                    
                                    var sTimeStamp =    obj.Time;
                                    var fUptimeSec =    obj.UptimeSec;
                                    var sPOWER =        obj.POWER;       // "POWER":"OFF"
                                    var fPOWER = 0;
                                    
                                    if (sPOWER == "OFF") {
                                        fPOWER = 0;
                                    } else {
                                        fPOWER = 1;
                                    }
                                    
                                    setState('javascript.0.zirkulation.TimeStampSTATE', sTimeStamp , true);
                                    setState('javascript.0.zirkulation.UpTimeSTATE', fUptimeSec , true);
                                    setState('javascript.0.zirkulation.PowerSTATE', fPOWER , true);
                                    
                                    });
                                    
                                    
                                    /////////////////////////////////////////////////////////////////////////
                                    // preapre tasmota json format to use in iobroker vis jason table
                                    // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                                    on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                                    
                                        var jsonSensorText = '';
                                        jsonSensorText = obj.state.val;
                                    
                                        var myMap = new Map();
                                        
                                        try {obj = JSON.parse(jsonSensorText);
                                            } catch (e) {
                                               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                               return;
                                            }
                                    
                                        // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                                        for (let [key, value] of Object.entries(obj)) {
                                            
                                            if ( typeof value === 'object' ) {
                                                // iterate one level down
                                                for (let [key2, value2] of Object.entries(value)) {
                                                    // log level 2
                                                    // console.log(key + ":" + key2 + "=" + value2);
                                                    myMap.set(key + ":" + key2, value2);
                                                }
                                            } else {
                                                // log level 1
                                                // console.log(key + "=" + value);
                                                myMap.set(key , value);
                                            }       
                                    
                                        }
                                        
                                        var jsonString = mapToJson(myMap);
                                        //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                                        //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                                    
                                        setState('javascript.0.zirkulation.jsonSTATE', jsonString , true);
                                    
                                    });
                                    
                                    /////////////////////////////////////////////////////////////////////////
                                    // preapre tasmota json format to use in iobroker vis jason table
                                    // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                                    on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                                    
                                        var jsonSensorText = '';
                                        jsonSensorText = obj.state.val;
                                    
                                        var myMap = new Map();
                                        
                                        try {obj = JSON.parse(jsonSensorText);
                                            } catch (e) {
                                               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                               return;
                                            }
                                    
                                        // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                                        for (let [key, value] of Object.entries(obj)) {
                                            
                                            if ( typeof value === 'object' ) {
                                                // iterate one level down
                                                for (let [key2, value2] of Object.entries(value)) {
                                                    // log level 2
                                                    // console.log(key + ":" + key2 + "=" + value2);
                                                    myMap.set(key + ":" + key2, value2);
                                                }
                                            } else {
                                                // log level 1
                                                // console.log(key + "=" + value);
                                                myMap.set(key , value);
                                            }       
                                    
                                        }
                                        
                                        var jsonString = mapToJson(myMap);
                                        //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                                        //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                                    
                                        setState('javascript.0.zirkulation.jsonSENSOR', jsonString , true);
                                    
                                    });
                                    
                                    

                                    JS zirkulation ZirkParseSENSOR
                                    Hier wirkt nun die spezielle Option aus der Tasmota Konfiguration um das "-" in ein "_" zu wandeln.

                                    //
                                    const util = require('util');
                                    // SENSOR
                                    // {"Time":"2020-03-28T19:07:12","DS18B20_1":{"Id":"01143B9799AA","Temperature":30.4},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":36.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":24.6},"TempUnit":"C"}
                                    // 
                                    createState('zirkulation.TimeStampSENSOR'); 
                                    createState('zirkulation.VorlaufTempSENSOR');
                                    createState('zirkulation.RuecklaufTempSENSOR');
                                    createState('zirkulation.InnerhalbTempSENSOR');
                                    
                                    on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                                    
                                    var jsonSensorText = '';
                                    jsonSensorText = obj.state.val;
                                    
                                    try {obj = JSON.parse(jsonSensorText);
                                       } catch (e) {
                                               console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                               return;
                                        }
                                    //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                                    
                                    // {"Time":"2020-06-06T15:11:44","DS18B20_1":{"Id":"01143B9799AA","Temperature":21.8},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":35.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.6},"TempUnit":"C"}   
                                    var fRLTemp = obj.DS18B20_1.Temperature; // RL
                                    var fVLTemp = obj.DS18B20_2.Temperature; // VL
                                    var fINTemp = obj.DS18B20_3.Temperature; // IN
                                    var sTimeStamp = obj.Time;
                                    
                                    setState('javascript.0.zirkulation.TimeStampSENSOR', sTimeStamp , true);
                                    setState('javascript.0.zirkulation.InnerhalbTempSENSOR', fINTemp , true);
                                    setState('javascript.0.zirkulation.VorlaufTempSENSOR', fVLTemp   , true);
                                    setState('javascript.0.zirkulation.RuecklaufTempSENSOR', fRLTemp , true);
                                    
                                    
                                    });
                                    
                                    
                                    
                                    C Offline
                                    C Offline
                                    Cumulus 0
                                    schrieb am zuletzt editiert von
                                    #17

                                    @alk
                                    Das Problem dieser Lösung ist doch, dass warmes Wasser zu spät kommt. Wenn ich warmes Wasser brauche, dann in dem Augenblick, wenn ich den Hahn öffne. Das Warmwasser kommt aber erst zwei Minuten später. Gut, man kann ja auch mal kalt duschen. Tut aber der Scheidungsquote nicht gut.
                                    Ich habe eine Funklösung realisiert, die wunderbar funktioniert. Im Bad und am Zugang zur Küche sind Taster, die die Umwälzpumpe einschalten. Das passt zeitlich fast immer. Und die Lösung ist käuflich und Plug'nPlay. Übrigens hatte ich eine manuelle Lösung ca. 20 Jahre drahtgebunden realisiert.

                                    Und in der Gästetoilette ist ein 16 A Klein-Durchlauferhitzer installiert. Der funktioniert sehr gut und ist kompatibel mit einer normalen Steckdose da nur Kurzzeitbetrieb. Eine sehr energiesparende Lösung, die auch einfach zu installieren ist, wenn eine Steckdose vorhanden ist.

                                    alkA 1 Antwort Letzte Antwort
                                    1
                                    • alkA alk

                                      Anwendungsbeschreibung
                                      Komponenten

                                      • Brauchwasserspeicher (Warmwasser)
                                      • Zirkulationspumpe in der Steigleitung
                                      • NodeMCU V2.0 (ESP8266) OS:tasmota Doris 8.1
                                      • 3x Temperaturfühler DS18B20 (1wire) zum Messen von der Vorlauftemperatur
                                      • Relaismodul zum Schalten der Zirkulationspumpe

                                      Ziel
                                      Ich möchte mit der Steuerung Energiekosten sparen. Der aktuell Aufbau startet die Zirkulationspumpe mit einer Zeitschaltuhr, z.B. Morgens 30min, Mittag 30min und Abends 30min. Der Aufbau ist wohl sehr weit verbreitet und ist mir schon eine ganze Weile in Dorn im Auge weil wenig innovativ.

                                      Die Zirkulationspumpe soll bedarfsgerecht eingeschaltet werden und die aktuelle Zeitschaltuhr kommt weg. Bedarfsgerecht meint beim Aufdrehen vom Warmwasser im Gebäude soll die Zirkulationspumpe starten und die Steigleitung mit Warmwasser befüllen. Damit ist das Warmwasser schneller an der Bedarfsstelle im Bad/WC.

                                      Kurzbeschreibung der Steuerhardware
                                      Ein 5V Netzteil versorgt den NodeMCU und das Relaismodul mit 5.0V Spannung. Auf dem NodeMCU steht eine geregelte 3.3.V Versorgung für die DS18B20 zur Verfügung.
                                      Als Betriebssystem für den NodeMCU verwende ich tasmota in einer damals neuen Version 8.1. Alle Hardwarekomponenten sind günstig und leicht am Markt verfügbar.
                                      Begonnen habe ich drei Temperatursensoren einzusetzen - ich wusste noch nicht so genau wie es werden wird. Am Ende braucht man nur einen Sensor am Heizungsrohr für den Warmwasservorlauf vom Brauchwasserspeicher in die Steigleitung.
                                      Wichtig: Der NodeMCU ist echt billig gemacht und verträgt wenig Spannungsschwankungen. Schon beim Einschalten des Radios gibt es den einen oder anderen Effekt und tasmota hängt sich auf. Also umbedingt reichlich (~2) Cbulk ~330uF außen an die 3.3V Versorgungspins anschließen.

                                      Kurzbeschreibung der Steuersoftware auf dem NodeMCU
                                      Tasmota bietet eine schicke Möglichkeit mit "Rules" direkt und schnell auf Events zu reagieren und neue Events auszulösen. Damit lässt sich eine tolle Steuerung umsetzen. Inspiriert hat mich ein Beispiel in der Tasmotat Dokumentation der eine Poolheizung realisiert hat. Dazu gibt es noch Variablen (var) und Konstante (mem) für mehr Transparenz des Ganzen nach außen.

                                      Tasmota rule1
                                      Der Thermostat
                                      Nachdem die Zirkulationsregelung gestartet ist stellt sich der Thermostat auf die aktuellen Temperaturen des Vorlauf ( DS18B20_2) und Rücklauf ( DS18B20_1 )ein. Es werden Grenzen zum Einschalten der Pumpe festgelegt um zu erkennen wenn Warmwasser entnommen wird. Dann erwärmt sich das Vorlaufrohr nach dem Brauchwasserspeicher, der Vorlaufsensor signalisiert einen Temperaturanstieg.

                                      Event

                                      • DS18B20_2:
                                        -- Obere Vorlaufgrenze (UpperVL): var1
                                        -- Untere Vorlaufgrenze (LowerVL): var2
                                      • DS18B20_1: Aktuell nicht benutzt, LowerRL Limit: var3
                                      ------------------------------------------------------------------
                                      -- rule1 Thermostat und Regelung. Entscheidung ob Pumpe eingeschaltet werden soll.
                                      -- 
                                      -- Rücklauf DS18B20-1#temperature  
                                      -- Vorlauf  DS18B20-2#temperature  
                                      -- Intern   DS18B20-3#temperature  
                                      --
                                      -- var1 obere Temperaturschwelle Vorlauf (VL)
                                      -- var2 untere Temperaturschwelle Vorlauf (VL)
                                      -- var3 maximale Rücklaufschwelle (RL)
                                      -- Löse event aus wenn Vorlauf temp ausserhalb oberer (var1) und unterer (var2) Schwelle, Pumpe an.
                                      rule1
                                      on system#boot do Backlog var1 26; var2 25; var3 25 endon
                                      on DS18B20_2#temperature>%var1% do Backlog var1 %value%;var2 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event UpperVL=%value% endon
                                      on DS18B20_2#temperature<%var2% do Backlog var2 %value%;var1 %value%;add1 0.5;sub2 0.5;var3 %value%;sub3 5;event LowerVL=%value% endon
                                      

                                      590ca147-9635-4d3a-9bfe-433e1f634e00-grafik.png

                                      Es wird Warmwasser entnommen
                                      Die Zirkulationsregelung läuft und hat die obere und untere Vorlauftemperaturgrenzen ( DS18B20_2 ) eingestellt, die Pumpe ist aus ( power1 0 ).
                                      Es wird Warmwasser aus dem Brauchwasserspeicher entnommen und das Vorlaufrohr erwärmt sich. Der Vorlaufsensor signalisiert einen Temperaturanstieg und die obere Vorlauftemperaturgrenze ( DS18B20_2 ) wird überschritten.
                                      Beim Überschreiten wird der Thermostat neu definiert und eine Event ausgelöst UpperVL der die Pumpe einschalten soll.
                                      Die Pumpe wird über rule2 gesteuert. Wenn die Zirkulationspumpe eine definierte Zeit ( mem5 ) gelaufen ist gibt es eine Wartezeit vor dem nächsten Pumpenanlauf ( mem4 ) um eine schnelles Ein-/Ausschalten zu vermeiden.

                                      Tasmota rule1

                                      Event

                                      • UpperVL: Event zum einschalten der Pumpe für eine bestimmte Zeit.
                                      • LowerVL: Event Pumpe aus
                                      • LowerRL: Event Pumpe aus
                                      • PumpOn=0: Pumpe/Power1 aus.
                                      • PumpOn>0: Entscheiden ob und wie lange die Pumpe power1 eingeschaltet werden soll.
                                      • Var4: Pumpenfreigabe in minuten, zählt von 0 aufwärts.
                                      • Mem4: Grenze in Minuten wann die Pumpe wieder freigegeben wird und einschalten darf.
                                      ------------------------------------------------------------------
                                      -- rule2 	Controller: Pumpe einschalten und ausschalten
                                      -- rule2 1	Regel einschalten
                                      -- rule2 0	Regel ausschalten
                                      --
                                      -- Pumpe einschalten, delay %value%, Pumpe abschalten.
                                      -- PumpOn=0 	Pumpe aus
                                      -- PumpOn=10	Pumpe an, setze timer zum ausschalten
                                      -- PumpOn=180	Pumpe an, setze timer zum ausschalten
                                      -- 
                                      -- Benutze Rule timer zum abschalten der pumpe
                                      -- RuleTimer2 60		60sec
                                      -- on Rules#Timer=2 o 		when countdown RuleTimer2 expires
                                      -- var4		Wird beim löschen von power verwendet und es wird das wiedereinschalten verzögert. Die Einheit ist minuten.
                                      --              Jede Minute zählt var4 im eines hoch. Nach z.B. 5 minuten kann die Pumpe wieder eingeschaltet werden.
                                      -- mem4	45	Warte mem4 Minuten bis wiedereinschalten, e.g. 45 (Minuten)
                                      -- mem5	19	Pumpenlaufzeit in sekunden, e.g. 19 (Sekunden)
                                      rule2
                                       on system#boot do Backlog var4 0.0 ; ruletimer2 0 endon
                                       on event#UpperVL do event PumpOn=1 endon
                                       on event#LowerVL do event PumpOn=0 endon
                                       on event#PumpOn=0 do power1 off endon  
                                       on event#PumpOn>0 do event ChkWait=%var4% endif endon  
                                       on event#ChkWait>%mem4% do Backlog var4 0; ruletimer2 %mem5%; power1 on endon
                                       on Rules#Timer=2 do power1 off endon 
                                       on Time#Minute|1 do add4 1 endon
                                       on var4#state==3 do power1 off endon
                                      

                                      Sperrzeit nach einem Pumpenlauf / Pumpenfreigabe
                                      Pause für die Pumpe nach einer Zirkulationspumpzeit. Hier wird verhindert, dass die Pumpe rythmisch wieder ein und ausgeschaltet wird.

                                      Event

                                      • event#PumpOn>0:
                                        -- Wenn die Pumpe über var4 freigegeben ist:
                                        if (%var4%>=%mem4%)
                                      • Time#Minute|1
                                        -- Vorwärtszählen der Pumpenfreigabe pro Minute.
                                      rule2
                                      ...
                                      on event#PumpOn>0 do if (%var4%>=%mem4%) power1 on; ruletimer2 %value%; var4 0.0 endif endon
                                      ...
                                      on Time#Minute|1 do add4 1 endon
                                      ...
                                      

                                      MQTT Verbindung in der Applikation mit Tasmota

                                      ------------------------------------------------------------------
                                      -- MQTT Verbindung über rule3
                                      -- 
                                      -- Vorlauf  DS18B20-2#temperature  
                                      -- var1
                                      -- var4
                                      rule3
                                      on tele-DS18B20_2#temperature do Backlog publish stat/zirkulation/vlUpper %var1%; publish stat/zirkulation/PumpWait %var4% endon
                                      on power1#state do Backlog publish stat/zirkulation/Pump %value% endon 
                                      

                                      Konfiguration der Applikation in Tasmota

                                      -- SetOption53 1 Display hostname and IP address in GUI 0=default
                                      -- SetOption0 0  Save power state and use after restart (=SaveState) 1=default
                                      -- SetOption64 1   Switch between - or _ as sensor name separator, 0 = sensor name index separator is - (hyphen) (default), 1 = sensor name index separator is _ (underscore)
                                      -- mem4 legt die Wartezeit bis zum Wiedereinschalten der Pumpe fest. Bei mir 45Minuten. Gerne auch anpassen.
                                      -- mem5 legt die Laufzeit der Pumpe fest. Bei mir reichen 19Sekunden. Gerne auch anpassen.
                                      
                                      Backlog PowerOnState 0; TelePeriod 61; rule3 1; rule1 1; rule2 1; SetOption0 0; SetOption53 1; SetOption64 1; mem4 45; mem5 19
                                      

                                      Und wie läuft das Ganze jetzt los?
                                      Mit dem folgende Kommando wird alle 61Sekunden eine Messung der Sensoren an den MQTT Broker geschickt:.

                                      TelePeriod 61
                                      

                                      Davor ist die Option 64 wichtig, die einfach ein Problem (im iobroker) behebt, wenn man ein Eventnamen ein Bindestrich enthalten ist ;-). Daran kann man verzweifeln.

                                      SetOption64 1;
                                      

                                      Und folgend werden die rules aktiviert, damit es auch eine Steuerung gibt:

                                      rule3 1; rule1 1; rule2 1;
                                      

                                      Typischer Log aus der Tasmota console

                                      8:50:57 MQT: tele/zirkulation/STATE = {"Time":"2020-03-01T18:50:57","Uptime":"0T02:27:12","UptimeSec":8832,"Heap":23,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"blabla","BSSId":"Z0:B0:VV:3K:D6:20","Channel":11,"RSSI":100,"Signal":-50,"LinkCount":1,"Downtime":"0T00:00:06"}}
                                      
                                      18:50:57 MQT: tele/zirkulation/SENSOR = {"Time":"2020-03-01T18:50:57","DS18B20_1":{"Id":"01143B9799AA","Temperature":26.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":33.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.1},"TempUnit":"C"}
                                      
                                      18:50:57 RUL: TELE-DS18B20_1#TEMPERATURE performs "Backlog publish stat/zirkulation/rl 26.1; publish stat/zirkulation/rlUpper 29.100"
                                      
                                      18:50:57 RUL: TELE-DS18B20_2#TEMPERATURE performs "Backlog publish stat/zirkulation/vl 33.9; publish stat/zirkulation/vlUpper 34.600; publish stat/zirkulation/vlLower 33.600"
                                      
                                      18:50:57 RUL: TELE-DS18B20_3#TEMPERATURE performs "publish stat/zirkulation/int 22.1"
                                      18:50:57 MQT: stat/zirkulation/int = 22.1
                                      18:50:57 MQT: stat/zirkulation/rl = 26.1
                                      18:50:58 MQT: stat/zirkulation/rlUpper = 29.100
                                      18:50:58 MQT: stat/zirkulation/vl = 33.9
                                      18:50:58 MQT: stat/zirkulation/vlUpper = 34.600
                                      18:50:58 MQT: stat/zirkulation/vlLower = 33.600
                                      18:51:00 RUL: TIME#MINUTE|1 performs "add4 1"
                                      18:51:00 MQT: stat/zirkulation/RESULT = {"Add4":"31.000"}
                                      18:51:00 RUL: VAR4#STATE performs "publish stat/zirkulation/PumpWait 31.000"
                                      18:51:00 MQT: stat/zirkulation/PumpWait = 31.000
                                      

                                      Kurzbeschreibung iobroker
                                      Info

                                          Plattform: linux
                                          Betriebssystem: linux
                                          Die Architektur: arm
                                          CPUs: 4
                                          Geschwindigkeit: 1500 MHz
                                          Modell: ARMv7 Processor rev 3 (v7l)
                                          RAM: 3.7 GB
                                          System-Betriebszeit: 19 T. 00:08:11
                                          Node.js: v12.22.6
                                          NPM: 6.14.15
                                          Datenträgergröße: 29.0 GiB
                                          Datenträger verfügbar: 26.0 GiB
                                          Adapter-Anzahl: 362
                                          Betriebszeit: 16 T. 00:39:00
                                          Aktive Instanzen: 17
                                          location: /opt/iobroker/
                                      

                                      JS zirkulation ZirkParseSTATE
                                      Bei mir heisst der Tasmota MQTT client "zirkulation". Damit kommt der Name relativ oft in dem JS vor.
                                      Hier werden die vom MQTT Client/Server glieferten Daten vom Tasmota client verarbeitet und umgewandelt. Das liegt daran dass ich keinen besseren Weg gefunden habe die Daten im VIS json table vom tasmota client zu bekommen.

                                      Hier nun das JS:

                                      //
                                      const util = require('util');
                                      // STATE
                                      // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                                      //
                                      createState('zirkulation.TimeStampSTATE'); 
                                      createState('zirkulation.UpTimeSTATE'); 
                                      
                                      createState('zirkulation.jsonSENSOR'); 
                                      createState('zirkulation.jsonSTATE'); 
                                      
                                      // prepare tasmota format for json format
                                      createState('zirkulation.PowerSTATE'); 
                                      
                                      //////////////////////////////////////////////////////////////////////////
                                      // Convert map to JSON string
                                      // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
                                      // 
                                      // @param 
                                      // @return 
                                      function mapToJson(map) {
                                        return JSON.stringify([...map]);
                                      }
                                      
                                      //////////////////////////////////////////////////////////////////////////
                                      // convert JSON string key value pairs to Map key value pairs
                                      // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
                                      //
                                      // @param jsonStr key value pairs
                                      // @return map converted from jsonStr to map key value pairs.
                                      function jsonToMap(jsonStr) {
                                        return new Map(JSON.parse(jsonStr));
                                      }
                                      
                                      on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                                      
                                      var jsonSensorText = '';
                                      jsonSensorText = obj.state.val;
                                      
                                      // {"Time":"2020-06-06T15:19:52","Uptime":"0T21:11:25","UptimeSec":76285,"Heap":25,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":3,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"F0:B0:14:3F:D6:20","Channel":1,"RSSI":78,"Signal":-61,"LinkCount":1,"Downtime":"0T00:00:03"}}
                                      try {obj = JSON.parse(jsonSensorText);
                                         } catch (e) {
                                                 console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                                 return;
                                          }
                                      
                                      //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                                      
                                      var sTimeStamp =    obj.Time;
                                      var fUptimeSec =    obj.UptimeSec;
                                      var sPOWER =        obj.POWER;       // "POWER":"OFF"
                                      var fPOWER = 0;
                                      
                                      if (sPOWER == "OFF") {
                                          fPOWER = 0;
                                      } else {
                                          fPOWER = 1;
                                      }
                                      
                                      setState('javascript.0.zirkulation.TimeStampSTATE', sTimeStamp , true);
                                      setState('javascript.0.zirkulation.UpTimeSTATE', fUptimeSec , true);
                                      setState('javascript.0.zirkulation.PowerSTATE', fPOWER , true);
                                      
                                      });
                                      
                                      
                                      /////////////////////////////////////////////////////////////////////////
                                      // preapre tasmota json format to use in iobroker vis jason table
                                      // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                                      on({id: 'mqtt.0.tele.zirkulation.STATE', change: "any"}, function (obj) {
                                      
                                          var jsonSensorText = '';
                                          jsonSensorText = obj.state.val;
                                      
                                          var myMap = new Map();
                                          
                                          try {obj = JSON.parse(jsonSensorText);
                                              } catch (e) {
                                                 console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.STATE').val);
                                                 return;
                                              }
                                      
                                          // {"Time":"2021-08-17T16:04:47","Uptime":"16T23:08:54","UptimeSec":1465734,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":30,"POWER":"OFF","Wifi":{"AP":1,"SSId":"Kreuzspitz","BSSId":"3C:A6:2F:26:25:8B","Channel":11,"RSSI":88,"Signal":-56,"LinkCount":24,"Downtime":"0T00:01:15"}}
                                          for (let [key, value] of Object.entries(obj)) {
                                              
                                              if ( typeof value === 'object' ) {
                                                  // iterate one level down
                                                  for (let [key2, value2] of Object.entries(value)) {
                                                      // log level 2
                                                      // console.log(key + ":" + key2 + "=" + value2);
                                                      myMap.set(key + ":" + key2, value2);
                                                  }
                                              } else {
                                                  // log level 1
                                                  // console.log(key + "=" + value);
                                                  myMap.set(key , value);
                                              }       
                                      
                                          }
                                          
                                          var jsonString = mapToJson(myMap);
                                          //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                                          //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                                      
                                          setState('javascript.0.zirkulation.jsonSTATE', jsonString , true);
                                      
                                      });
                                      
                                      /////////////////////////////////////////////////////////////////////////
                                      // preapre tasmota json format to use in iobroker vis jason table
                                      // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                                      on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                                      
                                          var jsonSensorText = '';
                                          jsonSensorText = obj.state.val;
                                      
                                          var myMap = new Map();
                                          
                                          try {obj = JSON.parse(jsonSensorText);
                                              } catch (e) {
                                                 console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                                 return;
                                              }
                                      
                                          // {"Time":"2021-08-17T16:05:48","DS18B20_1":{"Id":"01143B9799AA","Temperature":24.1},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":37.9},"DS18B20_3":{"Id":"03209779E6D3","Temperature":25.2},"TempUnit":"C"}
                                          for (let [key, value] of Object.entries(obj)) {
                                              
                                              if ( typeof value === 'object' ) {
                                                  // iterate one level down
                                                  for (let [key2, value2] of Object.entries(value)) {
                                                      // log level 2
                                                      // console.log(key + ":" + key2 + "=" + value2);
                                                      myMap.set(key + ":" + key2, value2);
                                                  }
                                              } else {
                                                  // log level 1
                                                  // console.log(key + "=" + value);
                                                  myMap.set(key , value);
                                              }       
                                      
                                          }
                                          
                                          var jsonString = mapToJson(myMap);
                                          //console.log( util.inspect(myMap, {showHidden:true, depth: null}) );
                                          //console.log( util.inspect(jsonSENSOR, {showHidden:true, depth: null}) );
                                      
                                          setState('javascript.0.zirkulation.jsonSENSOR', jsonString , true);
                                      
                                      });
                                      
                                      

                                      JS zirkulation ZirkParseSENSOR
                                      Hier wirkt nun die spezielle Option aus der Tasmota Konfiguration um das "-" in ein "_" zu wandeln.

                                      //
                                      const util = require('util');
                                      // SENSOR
                                      // {"Time":"2020-03-28T19:07:12","DS18B20_1":{"Id":"01143B9799AA","Temperature":30.4},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":36.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":24.6},"TempUnit":"C"}
                                      // 
                                      createState('zirkulation.TimeStampSENSOR'); 
                                      createState('zirkulation.VorlaufTempSENSOR');
                                      createState('zirkulation.RuecklaufTempSENSOR');
                                      createState('zirkulation.InnerhalbTempSENSOR');
                                      
                                      on({id: 'mqtt.0.tele.zirkulation.SENSOR', change: "any"}, function (obj) {
                                      
                                      var jsonSensorText = '';
                                      jsonSensorText = obj.state.val;
                                      
                                      try {obj = JSON.parse(jsonSensorText);
                                         } catch (e) {
                                                 console.error('Cannot parse: ' + getState('mqtt.0.tele.zirkulation.SENSOR').val);
                                                 return;
                                          }
                                      //console.debug( util.inspect(jsonSensorText, {showHidden:true, depth: null}) );
                                      
                                      // {"Time":"2020-06-06T15:11:44","DS18B20_1":{"Id":"01143B9799AA","Temperature":21.8},"DS18B20_2":{"Id":"01143BDE6DAA","Temperature":35.1},"DS18B20_3":{"Id":"03209779E6D3","Temperature":22.6},"TempUnit":"C"}   
                                      var fRLTemp = obj.DS18B20_1.Temperature; // RL
                                      var fVLTemp = obj.DS18B20_2.Temperature; // VL
                                      var fINTemp = obj.DS18B20_3.Temperature; // IN
                                      var sTimeStamp = obj.Time;
                                      
                                      setState('javascript.0.zirkulation.TimeStampSENSOR', sTimeStamp , true);
                                      setState('javascript.0.zirkulation.InnerhalbTempSENSOR', fINTemp , true);
                                      setState('javascript.0.zirkulation.VorlaufTempSENSOR', fVLTemp   , true);
                                      setState('javascript.0.zirkulation.RuecklaufTempSENSOR', fRLTemp , true);
                                      
                                      
                                      });
                                      
                                      
                                      
                                      I Offline
                                      I Offline
                                      Ingmar
                                      schrieb am zuletzt editiert von
                                      #18

                                      @alk ich habe ein Sonoff Pow R2 mit Tasmota vor die Zirkulationspumpe gesetzt. Jetzt kann ich über die Zeitschaltuhr (Tasmota Funktion) zu den tapischen Zeiten die Pumpe ein oder aus schalten. Mit dem Handy kann ich die Zeitschaltuhr übersteuern und wenn ich in der Küche bin und zwischendrinnen (Kuchen backen etc.) warmes Wasser für den Abwasch brauche die Pumpe einfach einschalten....
                                      Das funktioniert ganz gut und jeder im Haushalt kann so mit dem eigenen Smartphone die Pumpe wenn nötig einschalten...

                                      1 Antwort Letzte Antwort
                                      0
                                      • D Offline
                                        D Offline
                                        disaster123
                                        schrieb am zuletzt editiert von
                                        #19

                                        Wie messt Ihr denn vernünftig die Temperatur an einem Kupferrohr? Ich habe das bisher mit Zigbee Funkfühlern nicht hinbekommen....

                                        A BananaJoeB 2 Antworten Letzte Antwort
                                        0
                                        • D disaster123

                                          Wie messt Ihr denn vernünftig die Temperatur an einem Kupferrohr? Ich habe das bisher mit Zigbee Funkfühlern nicht hinbekommen....

                                          A Offline
                                          A Offline
                                          AndyGR42
                                          schrieb am zuletzt editiert von AndyGR42
                                          #20

                                          So wirklich smart wird das mit BWM. Da wir faktisch überall das Licht per Hue Motion Sensoren steuern wird dies im neuen Haus auch die Zirkulationspumpe aktivieren.

                                          Ach ja, die Legionellenspülung mit hoher Temperatur 1x die Woche kann man da auch automatisieren. Ich weiß ja, wann der Kessel hochheizt.

                                          wendy2702W 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

                                          742

                                          Online

                                          32.5k

                                          Benutzer

                                          81.7k

                                          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