Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Entwicklung
    4. [Projekt] ETA Heizung

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    [Projekt] ETA Heizung

    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      Roman last edited by

      Hallo @catnipper,

      vielen Dank für die super Arbeit.
      Wann kommt den das erste Youtube Video wo du es auch den weniger programmierbegabten von Uns erklärst? 😉
      Denke dein Adapter würde dadurch auch eine größere Reichweite bekommen.

      Grüße Demero

      1 Reply Last reply Reply Quote 0
      • ronin_mn
        ronin_mn @tcfigge last edited by

        @tcfigge
        Ich habe das Script überarbeitet bzw. größtenteils neu geschrieben. Leider habe ich zurzeit keine Zeit mehr mich mit ioBroker zu beschäftigen. Hier mein fast fertiges Script, welches im Adapter "javascript" auf meinem Raspberry läuft und einigermaßen zuverlässig alle Werte ausliest, falls jemand Lust hat, um es weiter zu entwickeln 🙂
        Den Ordner "0_userdata.0.etatouch" muss man zuvor manuell unter Objekte anlegen.

        Screenshot userdata.JPG

        var http = require('http');
        var etaip = 'http://ETA-IP-ADRESSE:8080';
        var TasksQueue = [];
        const util = require('util');
        
        
        MainLoop();
        
        function MainLoop() { 
            getETAerrors();
        
            var request = require('request');
            var parseString = require('xml2js').parseString;
            var options = {url: etaip + '/user/menu', method: 'GET'};
            TasksQueue = [];
            
            request(options, function(error, response, body) {
                if (!error && response.statusCode == 200) {
                    //DEBUG: console.log(body);
                    //Example: <eta version="1.0"><menu><fub uri="/79/10531" name="FWM"><object uri="/79/10531/0/0/10990" name="Eingänge"><object uri="/79/10531/0/2310/0" name="Durchflusssensor"/><object uri="/79/10531/0/11148/0" name="Warmwasser">....
                    try {
                        parseString(body, {explicitArray: false, attrkey : 'attribs', charkey: 'val' }, function (err, EtaMenuTree) {
                            console.log("ETA: Query Menu tree complete.");
                            EtaMenuTree.eta.menu.fub.forEach((fub, index) => {  //"fub" level with forEach
                                walkThroughMenuTree(fub,0, "0_userdata.0.etatouch"); //other levels recursive
                            });
                        });
                        console.log("ETA: Found " + TasksQueue.length + " menu items. Start querying...");
                        var nextFunct = TasksQueue.shift(); //nextFunct is filled by walkThroughMenuTree()
                        nextFunct();
                    } catch (e) {
                        console.error("Unparsable XML-Data from ETAtouch Webservice (" + etaip + "): " + e)
                    }
                } else {
                    console.error("Connection error to ETAtouch Webservice (" + etaip + "): " + error);
                }
            });
        }
        
        function walkThroughMenuTree(EtaMenuTree, recursivLevel, recursivName) {
            var statename = recursivName + "." + EtaMenuTree.attribs.name.replace("?","").replace(".","");
           
            if (recursivLevel == 0) {
                if (!existsState(statename)) {
                    //for first level of menu tree ("FUBs") there are now values. just create an empty folder.
                    createState(statename, "", {name: EtaMenuTree.attribs.uri, desc: "", type: 'string', unit: "", role: "text"});
                }
            } else {
                if (!existsState(statename)) {
                    //Create only new state. at next MainLoop the state value will be queried
                    //The following functions runs async. Eta has more the 600 states. Don't query all at the same time. will not work due to max current connections and so on. 
                    TasksQueue.push(function() {InitialRequestVariable(EtaMenuTree.attribs.uri, statename)});     
                } else {
                    TasksQueue.push(function() {RequestValue(EtaMenuTree.attribs.uri, statename, getObject(statename))});          
                }
            }
        
            //"object" is the name of the array with sub-items 
            if (EtaMenuTree.object !== undefined) {
                if (! Array.isArray(EtaMenuTree.object)) {
                    walkThroughMenuTree(EtaMenuTree.object, recursivLevel+1,statename);
                } else {
                    EtaMenuTree.object.forEach((el, index) => {
                        walkThroughMenuTree(el, recursivLevel+1, statename);
                    });
                }
            }
        }
        
        function RequestValue(uri, statename, thisstate) {
            var request = require('request');
            var options = {url: 'http://ETA-IP-ADRESSE:8080/user/var/'+uri , method: 'GET' };
        
            request(options, function(error, response, body) {
                var tmpdec=0.0; var tmpint=0;
                var parseString = require('xml2js').parseString;
        
                if (!error && response.statusCode == 200) {
                    try {
                        parseString(body, {explicitArray: false, attrkey : 'attribs', charkey: 'val'}, function (err, result) {
                            if (thisstate.common.unit != result.eta.value.attribs.unit) {
                                //sometimes the unit is not set in /usr/varinfo. 
                                extendObject(statename,{common: { unit: result.eta.value.attribs.unit }});
                            }
        
                            if (thisstate.common.type == 'string') {
                                //Example: <value uri="/user/var/40/10021/0/0/19402" strValue="Bereit" unit="" decPlaces="0" scaleFactor="1" advTextOffset="4000">4001</value>
                                //unit "" means it is a string value. then the field value is empty. use strValue instead
                                if (Array.isArray(thisstate.common.states)) {
                                    setState(statename, {val: result.eta.value.val, q: 0x00}, true);
                                } else {
                                    //States which does not have a value list gets the attirb strValue to the state (e.g. ON instead of 4000)
                                    setState(statename, {val: result.eta.value.attribs.strValue, q: 0x00}, true);
                                }
                            } else {
                                //Example1: <value uri="/user/var/40/10211/0/0/12015" strValue="2668" unit="kg" decPlaces="0" scaleFactor="10" advTextOffset="0">26675</value>
                                //    --> tmpdec = 2667.5
                                //Example2: <value uri="/user/var/40/10021/0/0/12299" strValue="7602h 3m" unit="s" decPlaces="0" scaleFactor="1" advTextOffset="0">2.73674e+07</value>
                                tmpint = parseInt(result.eta.value.attribs.scaleFactor);
                                tmpdec = parseFloat(result.eta.value.val) / tmpint;                  
                                setState(statename, {val: tmpdec, q: 0x00}, true);
                            }
                        });
                    } catch (e) {
                        console.error("Query ETA-variable processing error (" + statename + "): " + e)
                    }
                } else {
                    setState(statename, {val: getState(statename).val, q: 0x02}, true);
                    console.error("Query ETA-variable connection error (" + statename + "): " + error)
                }
        
                if (TasksQueue.length % 50 == 0) {
                    console.log("ETA: Remaining menu items: " + TasksQueue.length);
                }
        
                //DEBUG: if (TasksQueue.length < 760) return;
                var nextFunct = TasksQueue.shift();
                nextFunct();
            });
        }
        
        function InitialRequestVariable(uri, statename) {
            var request = require('request');
            var options = {url: 'http://ETA-IP-ADRESSE:8080/user/varinfo/'+uri , method: 'GET' };
            
            request(options, function(error, response, body) {
                var tmpdec=0.0; var tmpint=0;
                var parseString = require('xml2js').parseString;
                //DEBUG: console.log(body);
            
                if (!error && response.statusCode == 200) {
                    try {
                        parseString(body, {explicitArray: false, attrkey : 'attribs', charkey: 'val'}, function (err, result) {
                            //DEBUG: log(util.inspect(result, { showHidden: true, depth: null }));
        
                            var isReadable=true;
                            var validValues = {"test": "test-val"}; //create array/object with two strings: Record<string,string>
                            delete validValues.test; //empty validValues
                            
                            var isWriteable=false;   
                            if (result.eta.varInfo.variable.attribs.isWritable == "1" ) {
                                isWriteable = true;
                            }
        
                            if (result.eta.varInfo.variable.type == "TEXT") {
                                if (result.eta.varInfo.variable.validValues !== undefined) {                    
                                    //Example: <validValues><value strValue="Aus">1802</value><value strValue="Ein">1803</value></validValues></variable>
                                    //  -->    { val: '1802', attribs: { strValue: 'Aus' } }, { val: '1803', attribs: { strValue: 'Ein' }
                                    if (Array.isArray(result.eta.varInfo.variable.validValues.value)) { 
                                        result.eta.varInfo.variable.validValues.value.forEach((el, index) => {
                                            validValues[el.val] = el.attribs.strValue;
                                        });
                                    } else {
                                        console.log(statename);
                                        var el = result.eta.varInfo.variable.validValues.value;
                                        validValues[el.val] = el.attribs.strValue;
                                    }
                                }
                                createState(statename, "", {name: uri, desc: result.eta.varInfo.variable.attribs.fullName, type: 'string', unit: "", role: "text", read: isReadable, write: isWriteable , states: validValues});    
                            } else {
                                //Example: <variable uri="120/10601/0/0/13191" name="Puffer oben" fullName="Puffer > Erzeuger Kessel/Puffer > Puffer oben" unit="°C" decPlaces="0" scaleFactor="10" advTextOffset="0" isWritable="0">  <type>DEFAULT</type>   </variable>
                                if (result.eta.varInfo.variable.attribs.unit == "°C") {
                                    createState(statename, 0.0, {name: uri, desc: result.eta.varInfo.variable.attribs.fullName, type: 'number', unit: result.eta.varInfo.variable.attribs.unit, role: "value.temperature", read: isReadable, write: isWriteable });
                                } else {
                                    createState(statename, 0.0, {name: uri, desc: result.eta.varInfo.variable.attribs.fullName, type: 'number', unit: result.eta.varInfo.variable.attribs.unit, role: "value", read: isReadable, write: isWriteable });
                                }
                            }
                        });
        
                    } catch (e) {
                        console.error("Query ETA-variable-info processing error (" + statename + "): " + e)
                    }
                } else {
                    console.error("Query ETA-variable-info connection error (" + statename + "): " + error)
                }
        
                if (TasksQueue.length % 50 == 0) {
                    console.log("ETA: Remaining menu items: " + TasksQueue.length);
                }
        
                //DEBUG: if (TasksQueue.length < 700) return;      
                var nextFunct = TasksQueue.shift();
                nextFunct();
        
            //ToDo: Request error
            });
        }
        
        function getETAerrors() {
            var request = require('request');
            var options = {url: 'http://ETA-IP-ADRESSE:8080/user/errors' , method: 'GET' };
            
            request(options, function(error, response, body) {
                var parseString = require('xml2js').parseString;
                var resultString = "";
        
                if (!error && response.statusCode == 200) {
                    parseString(body, {explicitArray: true, attrkey : 'attribs', charkey: 'val'}, function (err, result) {
                        //DEBUG: log(util.inspect(result, { showHidden: true, depth: null }));
                        resultString="";
                        result.eta.errors[0].fub.forEach((el, index) => {
                            /*<fub uri="/40/10021" name="Kessel">
                                <error msg="Reinigung durch Kunde " priority="Nachricht" time="2023-02-17 08:47:46">
                                    Die jährliche Reinigung muss durchgeführt werden. Die einzelnen Schritte sind in der Bedienungsanleitung des Kessels angeführt.
                                </error>*/
                            if (el.error !== undefined) {
                                el.error.forEach((el, index) => {
                                    if (el.attribs.priority == "Error") { 
                                        //Put error messages at the beginning
                                        if (resultString != "") {
                                             resultString =  "\n" + resultString;
                                        }
                                        resultString = el.attribs.priority + ': ' + el.attribs.msg + ' - "' + el.val + '"' + resultString;
                                    } else {
                                        if (resultString != "") {
                                             resultString = resultString + "\n";
                                        }
                                        resultString = resultString + "\n" + el.attribs.priority + ': ' + el.attribs.msg + ' - "' + el.val + '"';
                                    }
                                });
                            }
                        });
                    });
                    if (!existsState("0_userdata.0.etatouch.Messages")){
                        createState("0_userdata.0.etatouch.Messages", resultString, {name: "Error(s), Messages", desc: "Error(s) and other Messages", type: 'string', unit: "", role: "text", read: true, write: false});    
                    } else {
                        setState("0_userdata.0.etatouch.Messages", resultString, true);
                    }
                }
            });
        }
        
        
        
        /*
            ToDos:
            - () createChannel für erste Ebene
            - () Doku verbessern
            Nice to Have:
            - () States schreiben / ändern
            - () pollinterval oder so einbauen, damit wichtige States jede Minuten abgefragt werden
        */ 
        
        
        
        
        
        
        
        1 Reply Last reply Reply Quote 0
        • K
          Kapsville @Rille06 last edited by

          @rille06
          Wollte mich noch bedanken - so klappt es, ist mir aber zu umständlich 🙂 Ich lese es nun via HomeAssistant aus, da gibts eine fertige Integration.

          1 Reply Last reply Reply Quote 0
          • T
            tcfigge @warp735 last edited by

            @warp735
            Moin!
            Gibt es da irgenwo eine Step by Step Anleitung für DAUs? 😉

            W 1 Reply Last reply Reply Quote 0
            • W
              warp735 @tcfigge last edited by

              @tcfigge
              Kenne keine... aber ist eigentlich selbsterklärend. Modbus Variablen an der Heizung anlegen (die die benötigt werden) und die dann in ioBroker abfragen.

              1 Reply Last reply Reply Quote 0
              • ?
                A Former User last edited by

                Tag habe das script etwas umgeschrieben. Benötige nur die Abfrage der Parameter. Leider ein Fehlschlag! Hab auch nicht wirklich Ahnung davon. ist mehr probieren. Muß ich außer Modbus noch was laden? Würde mich über Hilfe freuen.

                var http = require('http');
                //var xpath = require('xpath');
                //var dom = require('@xmldom/xmldom').DOMParser;
                var objectInstanz = '0_userdata.0.Heizung.';

                var etaIP = 'http://192.168.48.23:8080/user/var';

                var etaVars = [
                ["/120/10601/0/11327/0", "eta.Puffer.oben", true, false, "Puffer oben", "string", "°C", "value.temperature", ""]
                ,["/120/10601/0/11328/0", "eta.Puffer.mitte", true, false, "Puffer mitte", "string", "°C", "value.temperature", ""]
                ,["/120/10601/0/11329/0", "eta.Puffer.unten", true, false, "Puffer unten", "string", "°C", "value.temperature", ""]
                ,["/120/10601/0/0/12528", "eta.Puffer.ladezustand", true, false, "Puffer Ladezustand", "number", "%", "state", ""]

                ,["/120/10101/0/11125/2120",	"eta.HK.vorlauf",		            true, false, "Heizkreis Vorlauf Soll Temp",		"number",	"°C",		"value.temperature",    ""] 
                ,["/120/10101/0/11125/2121",	"eta.HK.vorlaufIst",		        true, false, "Heizkreis Vorlauf Ist Temp",		"number",	"°C",		"value.temperature",    ""] 
                
                
                ,["/40/10021/0/0/12153",		"eta.kessel.vollast",			    true, false, "Kessel Vollaststunden",			"string",	"",		    "state",                ""]
                ,["/40/10021/0/0/12016",		"eta.kessel.verbrauch",			    true, false, "Kessel Gesmtverbrauch",			"number",	"kg",		"state",                ""]
                ,["/40/10021/0/0/12013",		"eta.kessel.aschebox",			    true, false, "Kessel Verbrauch seit Aschebox",	"number",	"kg",		"state",                ""]
                ,["/40/10021/0/0/12180",		"eta.kessel.druck",				    true, false, "Kessel Druck",					"number",	"bar",		"state",                ""]
                ,["/40/10021/0/0/12001",		"eta.kessel.soll",				    true, false, "Kessel Soll",						"number",	"°C",		"state",                ""]
                ,["/40/10021/0/0/12161",		"eta.kessel.ist",				    true, false, "Kessel Ist",						"number",	"°C",		"state",                ""]
                ,["/40/10021/0/0/12162",		"eta.kessel.abgasgtemp",		    true, false, "Kessel Abgastemperatur",			"number",	"°C",	    "state",                ""]
                ,["/40/10021/0/0/12165",		"eta.kessel.abgasgeblaese",		    true, false, "Kessel Abgasgebläse",				"number",	"U/min",	"state",                ""]
                ,["/40/10021/0/0/12164",		"eta.kessel.restsauerstoff",	    true, false, "Kessel Restsauerstoff",			"number",	"%",		"state",                ""]
                ,["/40/10021/0/0/12080",		"eta.kessel.zustand",			    true, false, "Kessel Zustand",					"string",	"",			"state",                ""]
                ,["/40/10021/0/0/12077",		"eta.kessel.angeforderteLeistung",	true, false, "Kessel angeforderte Leistung",	"number",	"kW",		"state",                ""]
                
                ,["/40/10201/0/0/12015",		"eta.lager.silo",				    true, false, "Pellets Silo",					"number",	"kg",		"state",                ""]
                ,["/40/10021/0/0/12011",		"eta.lager.tag",				    true, false, "Pellets Tagesbehälter",			"number",	"kg",		"state",                ""]
                ,["/120/10601/0/0/12197",		"eta.system.aussentemperatur",	    true, false, "Aussentemperatur",				"number",	"°C",		"state",                ""]
                
                ,["/79/10531/0/11137/2001",		"eta.FWM.Zirkulation",	            true, false, "Anforderung Zirkulation",			"string",	"",		    "state",                ""]
                
                ,["/120/10101/0/11125/2001",	"eta.FBH.HKmischerAnforderung",	    true, false, "Anforderung Heizkreismischer",	"string",	"",		    "state",                ""]
                ,["/120/10101/0/11125/2120",	"eta.FBH.HKmischerSoll",	        true, false, "Soll Temp Heizkreismischer",	    "number",	"°C",		"value.temperature",    ""]
                ,["/120/10101/0/11125/2121",	"eta.FBH.HKmischerIst",	            true, false, "Ist Temp Heizkreismischer",	    "number",	"°C",		"value.temperature",    ""]
                ,["/120/10101/0/11125/2002",	"eta.FBH.HKmischerZustand",	        true, false, "Zustand Heizkreismischer",	    "string",	"",		    "state",                ""]
                ,["/120/10101/0/11125/2127",	"eta.FBH.HKmischerPosition",	    true, false, "Position Heizkreismischer",	    "number",	"%",	    "value.percent",        ""]
                ,["/120/10101/0/11125/2124",	"eta.FBH.Laufzeit",	                true, false, "Laufzeit Heizkreismischer",	    "number",	"s",		"",           ""]
                ,["/120/10101/0/11125/0",	    "eta.FBH.HKpumpeAusgang",	        true, false, "Heizkreispumpe Ausgang",	        "number",	"°C",		"value.temperature",    ""]
                ,["/120/10101/0/11125/2001",	"eta.FBH.HKpumpeAnforderung",       true, false, "Heizkreispumpe Anforderung",      "string",	"",		    "state",                ""]
                

                ];

                1 Reply Last reply Reply Quote 0
                • M
                  Maik last edited by

                  Re: [Projekt] ETA Heizung hab ein Problem: ich möchte im iObroker im Adapter" energiefluß-erweitert" die Einstellung der Raumtemperaturen regeln über das auslesen des Modbuses. Hat dies jemand schon gelöst?

                  arteck 1 Reply Last reply Reply Quote 0
                  • arteck
                    arteck Developer Most Active @Maik last edited by

                    @maik

                    die Einstellung der Raumtemperaturen regeln

                    Regeln oder anzeigen.. ?? der Adapter ist prmär zum anzeigen gedacht

                    M 1 Reply Last reply Reply Quote 0
                    • M
                      Maik @arteck last edited by

                      @arteck zum regeln ich verwende den Adapter "Energiefluß-erweitert".
                      Danke

                      Homoran 1 Reply Last reply Reply Quote 0
                      • Homoran
                        Homoran Global Moderator Administrators @Maik last edited by Homoran

                        @maik sagte in [Projekt] ETA Heizung:

                        zum regeln ich verwende den Adapter "Energiefluß-erweitert".

                        wie schon @arteck schrieb

                        @arteck sagte in [Projekt] ETA Heizung:

                        der Adapter ist prmär zum anzeigen gedacht

                        wie, bitte, regelst du damit?

                        W M 2 Replies Last reply Reply Quote 0
                        • W
                          warp735 @Homoran last edited by warp735

                          @homoran
                          Denk dir den fehlenden Punkt dazu 😉

                          @maik sagte in [Projekt] ETA Heizung:

                          Zum regeln. Ich verwende den Adapter "Energiefluß-erweitert".
                          Danke

                          M 1 Reply Last reply Reply Quote 0
                          • M
                            m4 @warp735 last edited by

                            Wieso kann ich den ETA Adapter nicht finden? 🙈

                            d79c241a-3c4e-47da-94b6-7f15a4964ad2-image.png

                            Homoran 1 Reply Last reply Reply Quote 0
                            • Homoran
                              Homoran Global Moderator Administrators @m4 last edited by

                              @m4 sagte in [Projekt] ETA Heizung:

                              Wieso kann ich den ETA Adapter nicht finden?

                              siehe ersten Post.
                              der Adapter ist in keinem offiziellen Repository verfügbar

                              1 Reply Last reply Reply Quote 0
                              • M
                                Maik @Homoran last edited by Maik

                                @homoran vielleicht ist regeln nicht der richtige Ausdruck. Ich möchte die Heiztemperatur in "Energiefluß-erweitert" einstellen und nicht am Kessel. Danke
                                9c79a08d-c9ec-4a33-a0f8-fc930f9021f0-image.png

                                Homoran 1 Reply Last reply Reply Quote 0
                                • Homoran
                                  Homoran Global Moderator Administrators @Maik last edited by

                                  @maik sagte in [Projekt] ETA Heizung:

                                  Ich möchte die Heiztemperatur in "Energiefluß-erweitert" einstellen

                                  das wäre dann aber ein Thema für einen anderen Thread

                                  M 2 Replies Last reply Reply Quote 1
                                  • M
                                    Maik @Homoran last edited by

                                    @homoran köntest Du mir ein Link geben. Finde mich in der vielfalt nicht wirklich zu recht . Danke

                                    1 Reply Last reply Reply Quote 0
                                    • M
                                      Maik @Homoran last edited by

                                      @homoran Köntest Du mir einen Link schicken?

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

                                      Support us

                                      ioBroker
                                      Community Adapters
                                      Donate

                                      568
                                      Online

                                      31.8k
                                      Users

                                      80.0k
                                      Topics

                                      1.3m
                                      Posts

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