Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. oxident

    NEWS

    • 15. 05. Wartungsarbeiten am ioBroker Forum

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    O
    • Profile
    • Following 0
    • Followers 4
    • Topics 29
    • Posts 955
    • Best 87
    • Groups 2

    oxident

    @oxident

    101
    Reputation
    123
    Profile views
    955
    Posts
    4
    Followers
    0
    Following
    Joined Last Online

    oxident Follow
    Pro Starter

    Best posts made by oxident

    • [Javascript] Midas (Aquatemp) Poolheizung

      Entwicklung des Skripts eingestellt -> bitte den Adapter https://github.com/MiRo1310/ioBroker.midas-aquatemp testen

      Hallo!

      Ich habe eine Poolsana InverPro Wärmepumpe (Hersteller ist Midas) mit WLAN-Modul für meinen Pool und dachte mir, das kann man bestimmt integrieren 😉

      Ihr müsst im oberen Teil des Skripts Eure Zugangsdaten eintragen. Dann noch, ganz wichtig, den apiLevel entweder auf 1 (für Anlagen, die schon vor einigen Monaten registriert wurden) oder 3 (für neuere Anlagen) setzen. Im Zweifelsfall beide Werte probieren.

      Hierbei auch wichtig: Bitte legt Euch einen Zweit-Account an und "teilt" Eure Anlage dann mit diesem. Dies kann man über die App erledigen. Hintergrund ist der, dass der Hersteller immer nur einen gleichzeitigen Login erlaubt.

      Ein- und Ausschalten der Wärmepumpe läuft über den DP "mode". Mit dem DP "silent" kann der Flüstermodus (verringerte Leistung) geschaltet werden und "tempSet" steuert die Zieltemperatur.
      Die restlichen DP sind nur-lesend und hoffentlich selbsterklärend.

      Wenn alles geklappt hat, dann findet ihr unter 0.userdata.0/Poolheizung folgende Datenpunkte:

      81109b84-4832-46ee-ad83-726589b4e626-image.png

      // Midas Poolheizung
      // v0.0.12
      // Changelog:
      // 0.0.12: Ausgangstemperatur des Kompressors (exhaust) sowie Produkt- und Geräte-ID hinzugefügt
      //         neue Produkt-IDs hinzugefügt (ungetestet)
      // 0.0.11: Request zu Acios migriert
      // 0.0.10: Weitere Parameter für andere Gerätetypen hinzugefügt
      // 0.0.8: Testweise Unterstützung von neu registrierten Anlagen
      // 0.0.7: Kleinigkeiten überarbeitet
      //        weitere Modelle hinzugefügt
      // 0.0.6: Gültigkeitsprüfung des Zertifikats deaktiviert (Dank an znyde)
      //        Kompatibilität mit Promo Next Modellen durch generische Product-ID (Dank an znyde)
      // 0.0.5: weitere Abfragewerte hinzugefügt (Kompressor- und Ansaugtemperatur)
      // 0.0.4: Tokenverfall jetzt 60min nach Skriptstart und nicht zu jeder vollen Stunde (Dank an dering)
      // 0.0.3: Datenpunkte beim Start automatisch anlegen (Dank an Andy200877)
      // 0.0.2: Token bei jedem Set-Vorgang prüfen und ggf. neu anfordern (Dank an dering)
      
      // ANFANG konfigurierbare Elemente -----
      const username = "EMAIL";
      var password = "KENNWORT";
      
      const interval = 30; // Abfrageintervall in Sekunden
      
      const dpRoot = "0_userdata.0.Poolheizung"; // Stammordner der Datenpunkte
      
      const apilevel = 3;   // 1: AquaTemp-Accounts, die vor v.1.5.8 erstellt wurden
                            // 2: HiTemp-Accounts
                            // 3: AquaTemp-Accounts, die mit neueren App-Versionen erstellt wurden
      
      var debugLevel = 0;   // 0: keine erweiterten Informationen protokollieren
                              // 1: Debug-Informationen protokollieren
      
      // ENDE --------------------------------
       
      var cloudURL;
      
      var token = "";
      var tokenRefreshTimer;
      var device = "";
      
      // ProductIDs:
      // Gruppe 1:
      // 1132174963097280512: Midas/Poolsana InverPro
      const AQUATEMP_POOLSANA="1132174963097280512";
      
      // Gruppe 2:
      // 1442284873216843776: 
      const AQUATEMP_OTHER1="1442284873216843776";
      
      var product = "";
      var reachable = false;
      
      const axios = require('axios');
      
      function setupEndpoints() {
          if(apilevel==1) {
              cloudURL = "https://cloud.linked-go.com/cloudservice/api";
          } else if(apilevel==2) {
              cloudURL = "https://cloud.linked-go.com/cloudservice/api";
          } else if(apilevel==3) {
              cloudURL = "https://cloud.linked-go.com:449/crmservice/api";
              password = require('crypto').createHash('md5').update(password).digest("hex");
          }
          printLog("API-Level " + apilevel, 1);
      }
       
      function clearValues() {
          saveValue("error", true, "boolean");
          saveValue("consumption", 0, "number");
          saveValue("state", false, "boolean");
          saveValue("rawJSON", null, "string");
      }
       
      function saveValue(key, value, sType) {
          var dp = dpRoot + "." + key;
       
          if ( !existsState(dp )) {
              printLog("Schreibe in NEUEN Datenpunkt: " + dp + " - " + value, 1);
              createState(dp,value,{name: key,  type: 'number', role: 'value'}, function () {}); 
          } else {
              printLog("Schreibe in Datenpunkt: " + dp + " - " + value, 1);
              setState(dp,value,true);
          }
      }
       
      function findCodeVal(result, code) {
          //log(code + " " + result.length);
          //log(result);
          printLog("Suche Wert " + code, 1);
          for(var i=0; i<result.length; i++) {
              //log(result[i].code);
              printLog(result[i].code, 1);
              if(result[i].code.indexOf(code) >= 0) {
                  printLog("Wert gefunden: " + result[i].value, 1);
                  return result[i].value;
              }
          }
          return "";
      }
       
      function createobjects() {
          log ("erstelle Objekte");
          createState(dpRoot + '.ambient', {read: true, write: false,  type: "number", unit:"°C", role: "value.temperature", name: "Umgebungstemperatur"});
          createState(dpRoot + '.connection', {read: true, write: false,  type: "boolean", role: "state", name: "Verbindung", def: false});
          createState(dpRoot + '.consumption', {read: true, write: false,  type: "number", unit:"W", role: "value.power", name: "Stromverbrauch", def: 0});
          createState(dpRoot + '.error', {read: true, write: false,  type: "boolean", role: "state", name: "Fehler", def: false});
          createState(dpRoot + '.errorCode', {read: true, write: false,  type: "string", name: "Fehlercode", def: ""});
          createState(dpRoot + '.errorLevel', {read: true, write: false,  type: "number", name: "Fehlerlevel"});
          createState(dpRoot + '.errorMessage', {read: true, write: false,  type: "string", name: "Fehlermeldung", def: ""});
          createState(dpRoot + '.mode', {read: true, write: true,  type: "string", states: "-1:off;0:cool;1:heat;2:auto", name: "Modus", def: ""});
          createState(dpRoot + '.rotor', {read: true, write: false,  type: "number", unit:"rpm", def: 0, name: "Lüfterdrehzahl"});
          createState(dpRoot + '.silent', {read: true, write: true,  type: "boolean", role: "state", name: "Silent", def: false});
          createState(dpRoot + '.state', {read: true, write: false,  type: "boolean", role: "state", name: "Status", def: false});
          createState(dpRoot + '.tempIn', {read: true, write: false,  type: "number", unit:"°C", role: "value.temperature", name: "Eingangstemperatur"});
          createState(dpRoot + '.tempOut', {read: true, write: false,  type: "number", unit:"°C", role: "value.temperature", name: "Ausgangstemperatur"});
          createState(dpRoot + '.tempSet', {read: true, write: true,  type: "number", unit:"°C", role: "level.temperature", name: "Solltemperatur"});
          createState(dpRoot + '.suctionTemp', {read: true, write: false,  type: "number", unit:"°C", name: "Luftansaugtemperatur"});
          createState(dpRoot + '.coilTemp', {read: true, write: false,  type: "number", unit:"°C", role: "value.temperature", name: "Kompressortemperatur"});
          createState(dpRoot + '.exhaust', {read: true, write: false,  type: "number", unit:"°C", role: "value.temperature", name: "Kompressorausgang"});
          createState(dpRoot + '.ProductCode', {read: true, write: false,  type: "string", name: "Produktcode"});
          createState(dpRoot + '.DeviceCode', {read: true, write: false,  type: "string", name: "Geräte-ID"});
          
          createState(dpRoot + '.rawJSON', {read: true, write: false,  type: "array", name: "komplette Rückgabe"});
      }
       
      function updateToken() {
       
          if(token=="") {
              printLog("Token Neuanforderung");
              var options;
              var sUrl="";
          
              if(apilevel<3) {
                  sUrl = cloudURL + '/app/user/login.json';
                  options = {
                      "user_name": username, "password": password, "type": "2"
                  };
              } else {
                  sUrl = cloudURL + '/app/user/login';
                  options = {
                      "userName": username, "password": password, "type": "2"
                  };
              }
              
      
              axios.post(sUrl, options)
      
                      .then(function (response) {
                          printLog("Login-Antwort: " + response.data);
                          if(response.status==200) {
                              if(apilevel<3) {
                                  token = response.data.object_result["x-token"];
                              } else {
                                  token = response.data.objectResult["x-token"];
                              }
                              printLog("Login ok! Token " + token);
                              //log("Token " + token);
                              updateDeviceID();
                          } else {
                              // Error!
                              printLog("Login-Fehler in updateToken(): " + response.data);
                              token = "";
                              saveValue("connection", false, "boolean");
                          }
                          })
                          .catch(function (error) {
                              // Error!
                              printLog("Login-Fehler in updateToken(): " + error);
                              token = "";
                              saveValue("connection", false, "boolean");        
                          });
          } else {
              // Token war ok
              updateDeviceID();
          }
       
          
       
          
       
      }
       
      function updateDeviceID() {
          if(token!="") {
              var sURL;
              if(apilevel<3) {
                  sURL = cloudURL + '/app/device/deviceList.json';
              } else {
                  sURL = cloudURL + '/app/device/deviceList';
              }
      
              axios.post(sURL, {
                  "productIds": [
                      "1132174963097280512",
                      "1245226668902080512",
                      "1656269521923575808", 
                      "1663080854333558784", 
                      "1596427678569979904", 
                      "1674238226096406528", 
                      "1650063968998252544", 
                      "1668781858447085568", 
                      "1186904563333062656", 
                      "1158905952238313472", 
                      "1442284873216843776", 
                      "1732565142225256450", 
                      "1548963836789501952", 
                      "1669159229372477440", 
                      "1650758828508766208", 
                      "1664085465655808000"
                      ]
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  if(response.status==200) {
                      printLog("DeviceList: " + JSON.stringify(response.data));
                      if(response.data.error_code==0) {
                          if(apilevel<3) {
                              device = response.data.object_result[0].device_code;
                              product = response.data.object_result[0].product_id;
                              reachable = (response.data.object_result[0].device_status=="ONLINE");
                          } else {
                              device = response.data.objectResult[0].deviceCode;
                              product = response.data.objectResult[0].productId;
                              reachable = (response.data.objectResult[0].deviceStatus=="ONLINE");
                          }
      
                          printLog("DeviceCode: " + device + ", ProductID: " + product + ", DeviceStatus: " + reachable);
                          saveValue("DeviceCode", device, "string");
                          saveValue("ProductCode", product, "string");
      
                          if(reachable) {
                              saveValue("connection", true, "boolean");
                              if(device!="") updateDeviceStatus(device);
                          } else {
                              // offline
                              device = "";
                              saveValue("connection", false, "boolean");
                          }
                      } else {
                          // Login-Fehler
                          log("Fehler in updateDeviceID(): " + JSON.stringify(response.data), "error");
                          token = "";
                          device = "";
                          reachable = false;
                          saveValue("connection", false, "boolean");
                      }
                  } else {
                      // Login-Fehler
                      log("Fehler in updateDeviceID(): " + JSON.stringify(response.data), "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
                  })
                  .catch(function (error) {
                      // Login-Fehler
                      log("Fehler in updateDeviceID(): " + error, "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  });
          }
      }
       
      function updateDeviceStatus(devicecode) {
          if(token!="") {
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/getDeviceStatus.json';
              } else {
                  sURL=cloudURL + '/app/device/getDeviceStatus';
              }
      
              axios.post(sURL, {
                  "device_code": devicecode,
                  "deviceCode": devicecode
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  printLog("DeviceStatus: " + response.data);
                  if(parseInt(response.data.error_code)==0) {
                      
                      if(apilevel<3) {
                          if(response.data.object_result["is_fault"]==true) {
                              // TODO: Fehlerbeschreibung abrufen
                              //clearValues();
                              saveValue("error", true, "boolean");
                              updateDeviceDetails(devicecode);
                              updateDeviceErrorMsg(devicecode);
                          } else {
                              // kein Fehler
                              saveValue("error", false, "boolean");
                              saveValue("errorMessage", "", "string");
                              saveValue("errorCode", "", "string");
                              saveValue("errorLevel", 0, "number");
                              updateDeviceDetails(devicecode);
                          }
                      } else {
                          if(response.data.objectResult["is_fault"]==true) {
                              // TODO: Fehlerbeschreibung abrufen
                              //clearValues();
                              saveValue("error", true, "boolean");
                              updateDeviceDetails(devicecode);
                              updateDeviceErrorMsg(devicecode);
                          } else {
                              // kein Fehler
                              saveValue("error", false, "boolean");
                              saveValue("errorMessage", "", "string");
                              saveValue("errorCode", "", "string");
                              saveValue("errorLevel", 0, "number");
                              updateDeviceDetails(devicecode);
                          }
                      }
                  } else {
                      log("Fehler in updateDeviceStatus(): " + JSON.stringify(response.data), "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceStatus(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
          }
      }
       
      function updateDeviceErrorMsg(devicecode) {
          if(token!="") {
              var optionsDev;
      
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/getFaultDataByDeviceCode.json';
              } else {
                  sURL=cloudURL + '/app/device/getFaultDataByDeviceCode';
              }
      
              axios.post(sURL, {
                  "device_code": devicecode,
                  "deviceCode": devicecode
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                 
                  if(parseInt(response.data.error_code)==0) {
       
                      
                      saveValue("error", true, "boolean");
      
                      if(apilevel<3) {
                          saveValue("errorMessage", response.data.object_result[0].description, "string");
                          saveValue("errorCode", response.data.object_result[0].fault_code, "string");
                          saveValue("errorLevel", response.data.object_result[0].error_level, "string");
                      } else {
                          saveValue("errorMessage", response.data.objectResult[0].description, "string");
                          saveValue("errorCode", response.data.objectResult[0].fault_code, "string");
                          saveValue("errorLevel", response.data.objectResult[0].error_level, "string");
                      }
                      
                      
                  } else {
                      // Login-Fehler
                      token = "";
                      device = "";
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceErrorMsg(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
       
          }
      }
      
      function updateDeviceDetails(devicecode) {
          // AXIOS
          if(token!="") {
              var optionsDev;
              var sURL;
              if(apilevel<3) {
                  sURL = cloudURL + '/app/device/getDataByCode.json';
              } else {
                  sURL = cloudURL + '/app/device/getDataByCode';
              }
      
              axios.post(sURL, {
                  "device_code": devicecode,
                  "deviceCode": devicecode,
                  "protocal_codes":[
                              "Power",
                              "Mode",
                              "Manual-mute",
                              "T01",
                              "T02",
                              "2074",
                              "2075",
                              "2076",
                              "2077",
                              "H03",
                              "Set_Temp",
                              "R08",
                              "R09",
                              "R10",
                              "R11",
                              "R01",
                              "R02",
                              "R03",
                              "T03",
                              "1158",
                              "1159",
                              "F17",
                              "H02",
                              "T04",
                              "T05",
                              "T06",
                              "T07",
                              "T14",
                              "T17",
                              "T1",
                              "T2",
                              "T3",
                              "T4",
                              "T5",
                              "T6",
                              "T7"],
                  "protocalCodes":[
                              "Power",
                              "Mode",
                              "Manual-mute",
                              "T01",
                              "T02",
                              "2074",
                              "2075",
                              "2076",
                              "2077",
                              "H03",
                              "Set_Temp",
                              "R08",
                              "R09",
                              "R10",
                              "R11",
                              "R01",
                              "R02",
                              "R03",
                              "T03",
                              "1158",
                              "1159",
                              "F17",
                              "H02",
                              "T04",
                              "T05",
                              "T06",
                              "T07",
                              "T14",
                              "T17",
                              "T1",
                              "T2",
                              "T3",
                              "T4",
                              "T5",
                              "T6",
                              "T7"]
      
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
      //            log(response.data)
                  
                  printLog("DeviceDetails: " + response.data);
       
                  if(parseInt(response.data.error_code)==0) {
      
                      if(apilevel<3) {
                          if(debugLevel==1) saveValue("rawJSON", response.data.object_result, "string");
                          
                          if(findCodeVal(response.data.object_result, "Power")=="1") {
                              if(product==AQUATEMP_POOLSANA) {
                                  // Stromverbrauch T07 x T14 in Watt
                                  saveValue("consumption", parseFloat(findCodeVal(response.data.object_result, "T07")) * parseFloat(findCodeVal(response.data.object_result, "T14")), "number");
                                  // Luftansaug-Temperatur T01
                                  saveValue("suctionTemp", parseFloat(findCodeVal(response.data.object_result, "T01")), "number");
                                  // Inlet-Temperatur T02
                                  saveValue("tempIn", parseFloat(findCodeVal(response.data.object_result, "T02")), "number");
                                  // outlet-Temperatur T03
                                  saveValue("tempOut", parseFloat(findCodeVal(response.data.object_result, "T03")), "number");
                                  // Coil-Temperatur T04
                                  saveValue("coilTemp", parseFloat(findCodeVal(response.data.object_result, "T04")), "number");
                                  // Umgebungs-Temperatur T05
                                  saveValue("ambient", parseFloat(findCodeVal(response.data.object_result, "T05")), "number");
                                  // Kompressorausgang-Temperatur T06
                                  saveValue("exhaust", parseFloat(findCodeVal(response.data.object_result, "T06")), "number");
                              } else if (product==AQUATEMP_OTHER1) {
                                  // Stromverbrauch T7 x T14 in Watt
                                  saveValue("consumption", parseFloat(findCodeVal(response.data.object_result, "T7")) * parseFloat(findCodeVal(response.data.object_result, "T14")), "number");
                                  // Luftansaug-Temperatur T1
                                  saveValue("suctionTemp", parseFloat(findCodeVal(response.data.object_result, "T1")), "number");
                                  // Inlet-Temperatur T2
                                  saveValue("tempIn", parseFloat(findCodeVal(response.data.object_result, "T2")), "number");
                                  // outlet-Temperatur T3
                                  saveValue("tempOut", parseFloat(findCodeVal(response.data.object_result, "T3")), "number");
                                  // Coil-Temperatur T4
                                  saveValue("coilTemp", parseFloat(findCodeVal(response.data.object_result, "T4")), "number");
                                  // Umgebungs-Temperatur T5
                                  saveValue("ambient", parseFloat(findCodeVal(response.data.object_result, "T5")), "number");
                                  // Kompressorausgang-Temperatur T6
                                  saveValue("exhaust", parseFloat(findCodeVal(response.data.object_result, "T6")), "number");
                              }
                          
                              // Lüfter-Drehzahl T17
                              saveValue("rotor", parseInt(findCodeVal(response.data.object_result, "T17")), "number");
                            
                              
                          } else {
                              saveValue("consumption", 0, "number");
                              saveValue("rotor", 0, "number");
                          }
          
                          // Ziel-Temperatur Set_Temp
                          //saveValue("tempSet", parseFloat(findCodeVal(body.object_result, "Set_Temp")), "number");
      
                          // Ziel-Temperatur anhand Modus
                          if(findCodeVal(response.data.object_result,"Mode") == 1) {
                              // Heiz-Modus (-> R02)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.object_result, "R02")), "number");
                          } else if(findCodeVal(response.data.object_result,"Mode") == 0) {
                              // Kühl-Modus (-> R01)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.object_result, "R01")), "number");
                          } else if(findCodeVal(response.data.object_result,"Mode") == 2) {
                              // Auto-Modus (-> R03)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.object_result, "R03")), "number");
                          }
      
              
                          // Flüstermodus Manual-mute
                          if(findCodeVal(response.data.object_result, "Manual-mute")=="1") {
                              saveValue("silent", true, "boolean");
                          } else {
                              saveValue("silent", false, "boolean");
                          }
          
                          // Zustand Power
                          if(findCodeVal(response.data.object_result, "Power")=="1") {
                              saveValue("state", true, "boolean");
                              saveValue("mode", findCodeVal(response.data.object_result,"Mode"), "string");
                          } else {
                              saveValue("state", false, "boolean");
                              saveValue("mode", "-1", "string");
                          }
                          
                          saveValue("connection", true, "boolean");
      
                          // Durchlauf ENDE
          
                          
                      } else {
                          if(debugLevel==1) saveValue("rawJSON", response.data.objectResult, "string");
                          
                          if(findCodeVal(response.data.objectResult, "Power")=="1") {
                              if(product==AQUATEMP_POOLSANA) {
                                  // Stromverbrauch T07 x T14 in Watt
                                  saveValue("consumption", parseFloat(findCodeVal(response.data.objectResult, "T07")) * parseFloat(findCodeVal(response.data.objectResult, "T14")), "number");
                                  // Luftansaug-Temperatur T01
                                  saveValue("suctionTemp", parseFloat(findCodeVal(response.data.objectResult, "T01")), "number");
                                  // Inlet-Temperatur T02
                                  saveValue("tempIn", parseFloat(findCodeVal(response.data.objectResult, "T02")), "number");
                                  // outlet-Temperatur T03
                                  saveValue("tempOut", parseFloat(findCodeVal(response.data.objectResult, "T03")), "number");
                                  // Coil-Temperatur T04
                                  saveValue("coilTemp", parseFloat(findCodeVal(response.data.objectResult, "T04")), "number");
                                  // Umgebungs-Temperatur T05
                                  saveValue("ambient", parseFloat(findCodeVal(response.data.objectResult, "T05")), "number");
                                  // Kompressorausgang-Temperatur T06
                                  saveValue("exhaust", parseFloat(findCodeVal(response.data.objectResult, "T06")), "number");
                              } else if (product==AQUATEMP_OTHER1) {
                                  // Stromverbrauch T7 x T14 in Watt
                                  saveValue("consumption", parseFloat(findCodeVal(response.data.objectResult, "T7")) * parseFloat(findCodeVal(response.data.objectResult, "T14")), "number");
                                  // Luftansaug-Temperatur T1
                                  saveValue("suctionTemp", parseFloat(findCodeVal(response.data.objectResult, "T1")), "number");
                                  // Inlet-Temperatur T2
                                  saveValue("tempIn", parseFloat(findCodeVal(response.data.objectResult, "T2")), "number");
                                  // outlet-Temperatur T3
                                  saveValue("tempOut", parseFloat(findCodeVal(response.data.objectResult, "T3")), "number");
                                  // Coil-Temperatur T4
                                  saveValue("coilTemp", parseFloat(findCodeVal(response.data.objectResult, "T4")), "number");
                                  // Umgebungs-Temperatur T5
                                  saveValue("ambient", parseFloat(findCodeVal(response.data.objectResult, "T5")), "number");
                                  // Kompressorausgang-Temperatur T6
                                  saveValue("exhaust", parseFloat(findCodeVal(response.data.objectResult, "T6")), "number");
                              }
                          
                              // Lüfter-Drehzahl T17
                              saveValue("rotor", parseInt(findCodeVal(response.data.objectResult, "T17")), "number");
                            
                              
                          } else {
                              saveValue("consumption", 0, "number");
                              saveValue("rotor", 0, "number");
                          }
          
                          // Ziel-Temperatur Set_Temp
                          //saveValue("tempSet", parseFloat(findCodeVal(body.objectResult, "Set_Temp")), "number");
      
                          // Ziel-Temperatur anhand Modus
                          if(findCodeVal(response.data.objectResult,"Mode") == 1) {
                              // Heiz-Modus (-> R02)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.objectResult, "R02")), "number");
                          } else if(findCodeVal(response.data.objectResult,"Mode") == 0) {
                              // Kühl-Modus (-> R01)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.objectResult, "R01")), "number");
                          } else if(findCodeVal(response.data.objectResult,"Mode") == 2) {
                              // Auto-Modus (-> R03)
                              saveValue("tempSet", parseFloat(findCodeVal(response.data.objectResult, "R03")), "number");
                          }
              
                          // Flüstermodus Manual-mute
                          if(findCodeVal(response.data.objectResult, "Manual-mute")=="1") {
                              saveValue("silent", true, "boolean");
                          } else {
                              saveValue("silent", false, "boolean");
                          }
          
                          // Zustand Power
                          if(findCodeVal(response.data.objectResult, "Power")=="1") {
                              saveValue("state", true, "boolean");
                              saveValue("mode", findCodeVal(response.data.objectResult,"Mode"), "string");
                          } else {
                              saveValue("state", false, "boolean");
                              saveValue("mode", "-1", "string");
                          }
                          
                          saveValue("connection", true, "boolean");
      
                          // Durchlauf ENDE
          
                          
                      }
      
                      
                  } else {
                      // Login-Fehler
                      log("Fehler in updateDeviceDetails(): " + JSON.stringify(response.data), "error");
                      token = "";
                      device = "";
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceDetails(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
                  
       
              
          }
      }
       
      function updateDevicePower(devicecode, power) {
          var powerOpt;
          var powerMode = 2;
       
          if(power==-1) {
              // aus
              powerOpt = 0;
              powerMode = -1;
          } else if(power==0) {
              // an und kühlen
              powerOpt = 1;
              powerMode = 0;
          } else if(power==1) {
              // an und heizen
              powerOpt = 1;
              powerMode = 1;
          } else if(power==2) {
              // an und auto
              powerOpt = 1;
              powerMode = 2;
          } else {
              log("ungülter Zustand!");
              return;
          }
       
          if(token!="") {
      
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/control.json';
              } else {
                  sURL=cloudURL + '/app/device/control';
              }
      
              axios.post(sURL, {
                  "param": [{
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "Power",
                      "protocolCode": "Power",
                      "value": powerOpt
                  }]
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  printLog("DeviceStatus: " + response.data);
                  if(parseInt(response.data.error_code)==0) {
                      
                      saveValue("mode", power.toString(), "string");
                      if(power>=0) updateDeviceMode(device, power);
                      
                  } else {
                      log("Fehler in updateDevicePower(): " + response.data, "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDevicePower(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
      
          }
      }
       
      function updateDeviceMode(devicecode, mode) {
          
       
          if(token!="") {
      
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/control.json';
              } else {
                  sURL=cloudURL + '/app/device/control';
              }
      
              axios.post(sURL, {
                  "param": [{
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "mode",
                      "protocolCode": "mode",
                      "value": mode
                  }]
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  printLog("DeviceStatus: " + response.data);
                  if(parseInt(response.data.error_code)==0) {
                      
                      saveValue("mode", mode, "string");
                      
                  } else {
                      log("Fehler in updateDeviceMode(): " + response.data, "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceMode(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
      
          }
      }
       
      function updateDeviceSilent(devicecode, silent) {
          
          var silentMode;
       
          if(silent) {
              silentMode = "1";
          } else {
              silentMode = "0";
          }
       
          if(token!="") {
      
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/control.json';
              } else {
                  sURL=cloudURL + '/app/device/control';
              }
      
              axios.post(sURL, {
                  "param": [{
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "Manual-mute",
                      "protocolCode": "Manual-mute",
                      "value": silentMode
                  }]
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  printLog("DeviceStatus: " + response.data);
                  if(parseInt(response.data.error_code)==0) {
                      
                      saveValue("silent", silent, "boolean");
                      
                  } else {
                      log("Fehler in updateDeviceSilent(): " + response.data, "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceSilent(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
      
          }
      }
       
      function updateDeviceSetTemp(devicecode, temperature) {
       
          var sTemperature = temperature.toString().replace(",", ".");
          var sMode = getState(dpRoot + ".mode").val;
          if(sMode=="-1") {
              //log("Gerät einschalten um Temperatur zu ändern!", 'warn');
              return;
          } else if(sMode=="0") {
              sMode = "R01"; // Kühlen
          } else if(sMode=="1") {
              sMode = "R02"; // Heizen
          } else if(sMode=="2") {
              sMode = "R03"; // Auto
          }
       
          
       
       
          if(token!="") {
      
              var sURL="";
      
              if(apilevel<3) {
                  sURL=cloudURL + '/app/device/control.json';
              } else {
                  sURL=cloudURL + '/app/device/control';
              }
      
              axios.post(sURL, {
                  "param": [
                      {
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "R01",
                      "protocolCode": "R01",
                      "value": sTemperature
                      },
                      {
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "R02",
                      "protocolCode": "R02",
                      "value": sTemperature
                      },
                      {
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "R03",
                      "protocolCode": "R03",
                      "value": sTemperature
                      },
                      {
                      "device_code": devicecode,
                      "deviceCode": devicecode,
                      "protocol_code": "Set_Temp",
                      "protocolCode": "Set_Temp",
                      "value": sTemperature
                      }
                      ]
              }, {
                  headers: { "x-token": token },
              })
              .then(function (response) {
                  printLog("DeviceStatus: " + response.data);
                  if(parseInt(response.data.error_code)==0) {
                      
                      saveValue("tempSet", temperature, "number");
                      
                  } else {
                      log("Fehler in updateDeviceSetTemp(): " + response.data, "error");
                      token = "";
                      device = "";
                      reachable = false;
                      saveValue("connection", false, "boolean");
                  }
              })
              .catch(function (error) {
                  // Login-Fehler
                  log("Fehler in updateDeviceSetTemp(): " + error, "error");
                  token = "";
                  device = "";
                  reachable = false;
                  saveValue("connection", false, "boolean");
              });
          }
      }
      
      function printLog(sMsg, minLevel = 1) {
          if(debugLevel>=minLevel) {
              log(sMsg);
          }
      }
      
      function productIsAquaTemp(productid) {
      
      }
       
      // Beginn des Skripts
      
      setupEndpoints();
      createobjects(); // DPs anlegen
      clearValues();
       
      updateToken(); // Zugriffstoken erfragen und aktuelle Werte lesen
       
      schedule('*/' + interval + ' * * * * *', function () {
          // regelmäßig Token und Zustand abfragen
          updateToken();
       
          // gewünschte Änderungen ausführen
          if(!getState(dpRoot + ".mode").ack) {
              updateDevicePower(device, getState(dpRoot + ".mode").val);
          }
          if(!getState(dpRoot + ".silent").ack) {
              updateDevicePower(device, getState(dpRoot + ".silent").val);
          }
      });
       
      tokenRefreshTimer = setInterval(function () {
          // Token verfällt nach 60min
          token = "";
          //log("Token nach Intervall verworfen.")
          updateToken();
      }, 3600000);
       
      on({id: dpRoot + ".mode", change: "ne", ack: false}, function (obj) {
          updateToken();
          updateDevicePower(device, getState(dpRoot + ".mode").val);
      });
       
      on({id: dpRoot + ".silent", change: "ne", ack: false}, function (obj) {
          updateToken();
          updateDeviceSilent(device, getState(dpRoot + ".silent").val);
      });
       
      on({id: dpRoot + ".tempSet", change: "ne", ack: false}, function (obj) {
          updateToken();
          updateDeviceSetTemp(device, getState(dpRoot + ".tempSet").val);
      });
      
      
      

      Getestet wurde das Skript bisher mit folgenden Wärmepumpen:
      Poolsana InverPro 21

      Andere Modelle müssten eigentlich auch funktionieren, jedoch gibt es im Skript noch einen Bug bei der Zuordnung der Werte. Schlaue Ideen sehr erwünscht 😉

      posted in Praktische Anwendungen (Showcase)
      O
      oxident
    • [Skript] Atlantic Wärmepumpe über Cozytouch abfragen

      WICHTIG: Derzeit gibt es große Probleme beim Server von Cozytouch. Ich weiß nicht, ob das Skript noch weiterentwickelt wird.
      Daher rate ich allen, sich https://github.com/tspopp/AquaMQTT anzuschauen. Ist cloudfrei und läuft super!

      Hallo!

      Ich habe eine Skript geschrieben, welches die Werte einer Atlantic / Austria Email Brauchwasserwärmepumpe abfragt. Leider habe ich keine Möglichkeit gefunden, direkt mit der Wärmepumpe zu kommunizieren (io-homecontrol -> wie Velux KLF).

      Daher klappt es nur in Verbindung mit der offiziellen Cozytouch-Bridge des Herstellers. Das Skript simuliert mehr oder weniger die App dieser Bridge.

      Leider ist das alles sehr "verwurschtelt" da die Abfrage recht komplex ist, aber ich erhalte schon brauchbare Ergebnisse.

      Bitte im nachfolgenden Skript Eure Zugangsdaten aus der App eintragen und einfach mal testen.

      Folgendes müsstet Ihr anpassen:
      username / password
      dpRoot: Hier wird der Gerätebaum erstellt
      dpSetTemp: Dies ist der DP mit dem ihr die Zieltemperatur vorgebt (also bitte selber anlegen)

      Beim ersten Aufruf wird es noch Warnungen hageln. Das legt sich dann aber.

      Da die Datenpunkte größtenteils generisch angelegt werden müsst ihr euch mal etwas durchkämpfen und brauchbare Details für euch selber herausfinden.

      Oder aber hier nachfragen 😉

      UPDATE 25.05.2024: Axios anstelle Request verwenden - dadurch keine Warnungen mehr im Log

      UPDATE 16.04.2024: Der Datenpunkt für die WW-Solltemperatur (standardmäßig 0_userdata.0.WW-Waermepumpe.WarmwasserSoll) wurde nicht angelegt.

      UPDATE 28.10.2023: Es werden jetzt manche Datenpunkte auch mit den richtigen Einheiten angelegt. Das klappt aber leider nur, wenn die Datenpunkte noch nicht vorhanden sind. Im Zweifelsfall also bitte alle DP löschen und das Skript neustarten.

      Bugs/Hinweise:

      • Der für viele sicherlich interessante Datenpunkt core:V40WaterVolumeEstimationState (geschätzter Gesamtverbrauch Warmwasser in Liter) läuft bei 65536 über, d.h. er fängt dann wieder bei 0 an. Dies kann man aber abfangen, in dem man SourceAnalytix zur Auswertung mit Reset-Erkennung verwendet.
      • Die PV-Überschussfunktion, also das manuelle Starten und Stoppen der Wärmepumpe, kann derzeit nicht via Skript gesteuert werden. Hier behelfe ich mir mit einem Shelly an dem SGReady-Kontakt. Der Heizstab kann jedoch mit dem Datenpunkt DHWBoostFull gesteuert werden.
      • Für den aktuellen Stromverbrauch sind die DP io:PowerHeatElectricalState und io:PowerHeatPumpState interessant. Sie liefern den aktuellen Verbrauch in Watt. Der DP core:ElectricEnergyConsumptionState hingegen liefert den Gesamtverbrauch in Wh.
      const dpRoot = "0_userdata.0.Atlantic";
      const dpSetTemp = "0_userdata.0.WW-Waermepumpe.WarmwasserSoll";
      const interval = 120; //sec
      
      
      const username = "eMail-Adresse";
      const password = "KENNWORT";
      
      // ------------- AB HIER NICHTS ÄNDERN ---------------- //
      // v2.0 - Migration von Request zu Axios
      // v1.0 - erstes Release
      
      const client_id = "ZThEMW5BM2h2djF0bmMxTXBvQTdHNXVENDZBYTo3aktaS1N3ZlVJNGRvaDdqRWZJVWRzR2VHNWth";
      const client_id_api = "alkxU3pBcnYwdWk3cW91OVVGTHRyOFVTNmUwYTpjWkFmYVlMNzVfYTlfcThlMGI4Unk4akU4eWdh"; // Wasserverbrauch (Token)
      const scope = "openid";
      const grant_type = "password";
      const token_url = "https://apis.groupe-atlantic.com/token";
      const jwt_url = "https://apis.groupe-atlantic.com/magellan/accounts/jwt";
      const overkiz_url = "https://ha110-1.overkiz.com/enduser-mobile-web/enduserAPI/";
      
      const atlantic_url = "https://apigam.groupe-atlantic.com:8243"; // Wasserverbrauch (über JWT)
      
      var access_token = "";
      var access_token_api = ""; // Wasserverbrauch
      var refresh_token = "";
      
      var id_token = "";
      var token_type = "";
      var expires_in = -1;
      
      var jwt = "";
      var jwt_overkiz = "";
      var session_cookie = "";
      
      var tokenRefreshTimer;
      
      var DHWP_URL = "";
      
      const axios = require('axios');
      
      function getToken() {
       
              createState(dpRoot + ".info.connection", 
                          false, 
                          {read: true, write: false,  type: "boolean", role: "indicator", def: false});
      
      
              axios.post(token_url, {
                  scope: scope,
                  username: "GA-PRIVATEPERSON/" + username,
                  password: password,
                  grant_type: grant_type
              }, {
                  headers: { 
                      "Authorization" : "Basic " + client_id,
                      "Content-Type": "application/x-www-form-urlencoded"
                      },
              })
                  .then(function (response) {
                      if(response.status==200) {
                          var jsonObject = response.data;
                          access_token = jsonObject.access_token;
                          refresh_token = jsonObject.refresh_token;
                          id_token = jsonObject.id_token;
                          expires_in = parseInt(jsonObject.expires_in);
                          session_cookie = "";
                          jwt = "";
                          //log(access_token);
                          getJWT(); // -------->
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getToken(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                      // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getToken(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
              
              
       
      }
      
      function getTokenApi() {
              // Wasserverbrauch
              axios.post(atlantic_url + "/token", {
                  grant_type: "client_credentials"
              }, {
                  headers: { 
                      "Authorization" : "Basic " +  client_id_api,
                      "Content-Type": "application/x-www-form-urlencoded"
                      },
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          var jsonObject = response.data;
                          access_token_api = jsonObject.access_token;
                          getJWTOverkiz(); // -------->
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getTokenAPI(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getTokenAPI(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
      }
      
      function getJWT() {
      
              axios.get(jwt_url, {
                  headers: { 
                      "Authorization" : "Bearer " + access_token,
                      "Content-Type": "application/json"
                      },
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          //log(response);
                          jwt = response.data.replace('"', '');
                          //log(jwt);
                          getSessionCookie(); // ------>
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getJWT(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getJWT(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
       
      }
      
      function getSessionCookie() {
              axios.post(overkiz_url + "login", {
                  'jwt': jwt
                  }, {
                  headers: { 
                      "charset": "UTF-8",
                      "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0",
                      "Content-Type": "application/x-www-form-urlencoded"
                      },
              })
      
                  .then(function (response) {
                      if(response.status==200) {
      
                          session_cookie = response.headers["set-cookie"][0];
                          //log(session_cookie);
                          session_cookie = session_cookie.substring(session_cookie.indexOf("JSESSIONID")+11);
                          session_cookie = session_cookie.substring(0, session_cookie.indexOf(";"));
      
                          
      
                          if(session_cookie!="") {
                              refreshStates(); // -------->
                          } else {
                              // Error!
                              log("Fehler bei getSessionCookie() - Cookie leer");
                              access_token = "";
                              refresh_token = "";
                              id_token = "";
                              expires_in = -1;
                              jwt = "";
                              session_cookie = "";
                          }
                          
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getSessionCookie(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getSessionCookie(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
          
             
              
       
      }
      
      function refreshStates() {
      
          axios.post(overkiz_url + "setup/devices/states/refresh", 
              null, 
              {
                  headers: { 
                      'Cookie': "JSESSIONID=" + session_cookie,
                      "Content-Type": "application/json",
                      "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                  }
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          getSetup(); // -------->
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getTokenAPI(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getTokenAPI(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
      
      
          
       
      }
      
      function getSetup() {
       
              axios.get(overkiz_url + "setup", {
                  headers: { 
                      "Cookie" : "JSESSIONID=" + session_cookie,
                      "Content-Type": "application/json"
                      },
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          //log(response.data);
                          //log("getSetup ok");
                          if(getState(dpRoot + ".debug").val) setState(dpRoot + ".rawJson", response.data, true);
                          enumStates(response.data); 
                          getTokenApi(); // ------>
      
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getSetup(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getSetup(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
          
             
       
      }
      
      function enumStates(devTree) {
          
          
      
          for(var iDev = 0; iDev < devTree["devices"].length; iDev++) {
              
              createState(dpRoot + "." + iDev, {name: devTree["devices"][iDev].label, type: "channel"});
      
              createState(dpRoot + "." + iDev + ".enabled", 
                          devTree["devices"][iDev].enabled, 
                          {read: true, write: false,  type: "boolean", role: "state", name: devTree["devices"][iDev].label + " enabled", def: false});
              setState(dpRoot + "." + iDev + ".enabled", devTree["devices"][iDev].enabled, true);
      
              createState(dpRoot + "." + iDev + ".available", 
                          devTree["devices"][iDev].available, 
                          {read: true, write: false,  type: "boolean", role: "state", name: devTree["devices"][iDev].label + " available", def: false});
              setState(dpRoot + "." + iDev + ".available", devTree["devices"][iDev].available, true);
      
              createState(dpRoot + "." + iDev + ".oid", 
                          devTree["devices"][iDev].oid, 
                          {read: true, write: false,  type: "string", role: "state", name: devTree["devices"][iDev].label + " oid", def: ""});
              setState(dpRoot + "." + iDev + ".oid", devTree["devices"][iDev].oid, true);
      
              createState(dpRoot + "." + iDev + ".url", 
                          devTree["devices"][iDev].deviceURL, 
                          {read: true, write: false,  type: "string", role: "state", name: devTree["devices"][iDev].label + " URL", def: ""});
              setState(dpRoot + "." + iDev + ".url", devTree["devices"][iDev].deviceURL, true);
      
              createState(dpRoot + "." + iDev + ".uiClass", 
                          devTree["devices"][iDev].uiClass, 
                          {read: true, write: false,  type: "string", role: "state", name: devTree["devices"][iDev].label + " uiClass", def: ""});
              setState(dpRoot + "." + iDev + ".uiClass", devTree["devices"][iDev].uiClass, true);
      
              if(devTree["devices"][iDev].uiClass=="WaterHeatingSystem") {
                  DHWP_URL = devTree["devices"][iDev].deviceURL;
              }
      
              
              
              if (typeof devTree["devices"][iDev].states != "undefined") {
                  createState(dpRoot + "." + iDev + ".states", {type: "channel"});
      
                  for(var iDevState = 0; iDevState < devTree["devices"][iDev].states.length; iDevState++) {
      
                      if((devTree["devices"][iDev].states[iDevState].type == "1") || (devTree["devices"][iDev].states[iDevState].type == "2") || (devTree["devices"][iDev].states[iDevState].type == "3")) {
                          createDHWPstate(dpRoot + "." + iDev + ".states." + devTree["devices"][iDev].states[iDevState].name, devTree["devices"][iDev].states[iDevState].value, devTree["devices"][iDev].states[iDevState].type);
                          setState(dpRoot + "." + iDev + ".states." + devTree["devices"][iDev].states[iDevState].name, devTree["devices"][iDev].states[iDevState].value, true);
                      }
      
      
                  }
              }
              
      
          }
           setState(dpRoot + ".info.connection", true, true);
           
      }
      
      function getJWTOverkiz() {
              axios.post(overkiz_url + "enduser/jwt/createToken", 
              null, 
              {
                  headers: { 
                      'Cookie': "JSESSIONID=" + session_cookie,
                      "Content-Type": "application/json",
                      "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                  }
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          jwt_overkiz = response.data.jwt;
                          if(jwt_overkiz!="") {
                              //log("jwt overkiz ok");
                              getWaterConsumption();
                              // -------->
                          } else {
                              // Error!
                              access_token = "";
                              refresh_token = "";
                              id_token = "";
                              expires_in = -1;
                              jwt = "";
                              session_cookie = "";
                              jwt_overkiz = "";
                          }
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getJWTOverkiz(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getJWTOverkiz(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
          
       
      }
      
      function getWaterConsumption() {
      
              axios.post(atlantic_url + "/gam/wcfservice/devicedhwrest/GetWaterConsumption", 
              {
                  'frequency': 1,
                  'deviceURL': DHWP_URL.replace("/", "\/"),
                  'jwtToken': jwt_overkiz
              }, 
              {
                  headers: { 
                      "Content-Type": "application/json",
                      "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0",
                      "Authorization" : "Bearer " + access_token_api,
                      "Locale": "de_DE",
                      //"UniqId": "648C91F2-CA6E-4870-AB47-40FF4A3C1D12",
                      "UniqId": CreateGuid(),
                      "Gfcuid": 3005,
                      "Userid": username,
                      "Platform": "ios 3.5.1 (3)"
                  }
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          createState(dpRoot + ".consumption.current", 
                              response.data.waterConsumptionDetail[response.data.waterConsumptionDetail.length-1].litersConsumed, 
                              {read: true, write: false,  type: "number", role: "state", name: " Water consumption today", unit: "l", def: 0});
                          setState(dpRoot + ".consumption.current", response.data.waterConsumptionDetail[response.data.waterConsumptionDetail.length-1].litersConsumed, true);
      
                          createState(dpRoot + ".consumption.previous", 
                              response.data.waterConsumptionDetail[response.data.waterConsumptionDetail.length-2].litersConsumed, 
                              {read: true, write: false,  type: "number", role: "state", name: " Water consumption yesterday", unit: "l", def: 0});
                          setState(dpRoot + ".consumption.previous", response.data.waterConsumptionDetail[response.data.waterConsumptionDetail.length-2].litersConsumed, true);
                              
                              if(!getState(dpSetTemp).ack) {
                                  setTemperature(getState(dpSetTemp).val);
                              }
      
                              if(!getState(dpRoot + ".DHWMode").ack) {
                                  setDHWMode();
                              }
      
      
                              if(!getState(dpRoot + ".DHWSchedule").ack) {
                                  setDHWSchedule();
                              }
      
                              if(getState(dpRoot + ".fetchHistory").val) {
                                  getHistory();
                              }
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getWaterConsumption(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getWaterConsumption(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
       
      }
      
      function setTemperature(setTemp) {
              axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "setTargetTemperature",
                              "parameters" : [
                                  setTemp
                              ]
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
          
                  .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  setState(dpSetTemp, setTemp, true);
                              } else {
                                  // Error!
                                  log("Fehler bei setTemperature()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei setTemperature()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                              // Error!
                              log("Fehler bei setTemperature()");
                              access_token = "";
                              refresh_token = "";
                              id_token = "";
                              expires_in = -1;
                              jwt = "";
                              session_cookie = "";
                              jwt_overkiz = "";
                      });
      }
      
      function setDHWMode() {
       
          /*
          "autoMode",
      	"manualEcoActive",
      	"manualEcoInactive"
          */
      
          axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "setDHWMode",
                              "parameters" : [
                                  getState(dpRoot + ".DHWMode").val
                              ]
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
          
                  .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  setState(dpRoot + ".DHWMode", getState(dpRoot + ".DHWMode").val, true);
                              } else {
                                  // Error!
                                  log("Fehler bei setDHWMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei setDHWMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  log("Fehler bei setDHWMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      function setDHWSchedule() {
       
          /*
          "pac24h_elec24h",
      	"pacProg_elecProg"
          */
      
          axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "setOperatingRange",
                              "parameters" : [
                                  getState(dpRoot + ".DHWSchedule").val
                              ]
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
          
                  .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  setState(dpRoot + ".DHWSchedule", getState(dpRoot + ".DHWSchedule").val, true);
                              } else {
                                  // Error!
                                  log("Fehler bei setDHWSchedule()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei setDHWSchedule()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  // Error!
                                  log("Fehler bei setDHWSchedule()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      function setDHWBooster() {
      
              var boostDuration = 0;
      
              if(getState(dpRoot + ".DHWBoostFull").val) {
                  boostDuration = 2;
              }
              else {
                  setOperatingMode(false, false);
                  return; 
              }
      
              axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "setBoostModeDuration",
                              "parameters" : [
                                  boostDuration
                              ]
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
          
                  .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  sleep(3000);
                                  setOperatingMode(true, false);
                                  
                                  sleep(3000);
                                  refreshBooster();
                                  // -------->
                              } else {
                                  // Error!
                                  log("Fehler bei setDHWBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei setDHWBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  // Error!
                                  log("Fehler bei setDHWBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      function refreshBooster() {
       
              
              axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "refreshBoostModeDuration",
                              "parameters" : []
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
      
             .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  
                                  // -------->
                              } else {
                                  // Error!
                                  log("Fehler bei refreshBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei refreshBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  // Error!
                                  log("Fehler bei refreshBooster()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      
      function setOperatingMode(relaunch, absence) {
       
          
              
              
              var sRelaunch;
              var sAbsence;
      
              if(relaunch) {
                  sRelaunch = "on";
              } else {
                  sRelaunch = "off";
              }
      
              if(absence) {
                  sAbsence = "on";
              } else {
                  sAbsence = "off";
              }
              
              axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : "setCurrentOperatingMode",
                              "parameters" : [
                                  {
                                      "relaunch": sRelaunch,
      							    "absence": sAbsence
                                  }
                              ]
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
      
             .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  setState(dpRoot + ".DHWBoostFull", getState(dpRoot + ".DHWBoostFull").val, true);
                                  sleep(3000);
                                  refreshBooster();
                                  // -------->
                              } else {
                                  // Error!
                                  log("Fehler bei setOperatingMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei setOperatingMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  // Error!
                                  log("Fehler bei setOperatingMode()");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      
      function execOverkizCmd(cmd) {
       
          
              
              axios.post(overkiz_url + "exec/apply",
                  {
                      "label" : "Cozytouch iOS: 3.5.1 (3)",
                      "actions" : [
                      {
                          "commands" : [
                              {
                              "name" : cmd
                              }
                          ],
                      "deviceURL" : DHWP_URL.replace("/", "\/")
                      }
                      ]
                  }, 
                  {
                      headers: { 
                          "Cookie" : "JSESSIONID=" + session_cookie,
                          "Content-Type": "application/json",
                          "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      }
                  })
      
             .then(function (response) {
                          if(response.status==200) {
                              if(response.data.execId!="") {
                                  if(cmd=="refreshWaterConsumption") getWaterConsumption(); // ------>
                              } else {
                                  // Error!
                                  log("Fehler bei execOverkizCmd(" + cmd + ")");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                                  
                              }
                          } else {
                               // Error!
                                  log("Fehler bei execOverkizCmd(" + cmd + ")");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                          }
                      })
                      .catch(function (error) {
                                  // Error!
                                  log("Fehler bei execOverkizCmd(" + cmd + ")");
                                  access_token = "";
                                  refresh_token = "";
                                  id_token = "";
                                  expires_in = -1;
                                  jwt = "";
                                  session_cookie = "";
                                  jwt_overkiz = "";
                      });
       
      }
      
      function getHistory() {
       
              axios.get(overkiz_url + "history", {
                  headers: { 
                      "Cookie" : "JSESSIONID=" + session_cookie,
                      "Content-Type": "application/json",
                      "User-Agent": "Cozytouch/3 CFNetwork/1335.0.3 Darwin/21.6.0"
                      },
              })
      
                  .then(function (response) {
                      if(response.status==200) {
                          setState(dpRoot + ".HistoryJson", response.data, true);
                          setState(dpRoot + ".fetchHistory", false, true);
                      } else {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getHistory(): " + response.status);
                          setState(dpRoot + ".info.connection", false, true);
                      }
                  })
                  .catch(function (error) {
                          // Error!
                          access_token = "";
                          refresh_token = "";
                          id_token = "";
                          expires_in = -1;
                          jwt = "";
                          session_cookie = "";
                          log("Fehler bei getHistory(): " + error);
                          setState(dpRoot + ".info.connection", false, true);
                  });
       
      }
      
      function CreateGuid() {  
         function _p8(s) {  
            var p = (Math.random().toString(16)+"000000000").substr(2,8);  
            return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;  
         }  
         return _p8() + _p8(true) + _p8(true) + _p8();  
      }
      
      function createDHWPstate(name, value, valType) {
          var stateSuffix = "";
      
          
          // bekannte Attribute behandeln:
          if(name.endsWith("RSSILevelState")) {
              stateSuffix = "db";
          } else if (name.endsWith("TemperatureState")) {
              stateSuffix = "°C";
          } else if (name.endsWith("PowerHeatElectricalState")) {
              stateSuffix = "W";
          } else if (name.endsWith("PowerHeatPumpState")) {
              stateSuffix = "W";
          } else if (name.endsWith("V40WaterVolumeEstimationState")) {
              // Wasserbrauch insgesamt -> Überlauf bei 65536!
              stateSuffix = "l";
          }
          else if (name.endsWith("ElectricEnergyConsumptionState")) {
              // Stromverbrauch insgesamt
              stateSuffix = "Wh";
          }
      
      
          
          
      
          switch (valType) {
              case 1:
                  //console.log("1 " + name);
                  if(existsObject(name)) {
      
                  } else {
                      createState(name, value, {read: true, write: false,  type: "number", role: "state", name: name, unit: stateSuffix, def: 0});
                  }
                  break;
      
              case 2:
                  //console.log("2 " + name);
                  if(existsObject(name)) {
      
                  } else {
                      createState(name, value, {read: true, write: false,  type: "number", role: "state", name: name, unit: stateSuffix, def: 0});
                  }
                  break;
      
              case 3:
                  //console.log("3 " + name);
                  if(existsObject(name)) {
      
                  } else {
                      createState(name, value, {read: true, write: false,  type: "string", role: "state", name: name, unit: stateSuffix, def: ""});
                  }
                  break;
          }
      
      
      
      }
      
      
      // --------------------------------------------------------------
      
      createState(dpRoot + ".fetchHistory", false, {
              name: dpRoot + ".fetchHistory",
              type: 'boolean',
              role: 'state',
              desc: 'Befehlsverlauf einmalig abrufen'
          });
      
      createState(dpRoot + ".forceUpdate", false, {
              name: dpRoot + ".forceUpdate",
              type: 'boolean',
              role: 'state',
              desc: 'erzwungenes einmaliges Aktualisieren der Werte'
          });
      
      createState(dpRoot + ".HistoryJson", "", {
              name: "History (JSON)",
              type: 'string',
              role: 'state',
              desc: 'Befehlsverlauf'
          });
      
      createState(dpRoot + ".DHWMode", "", {
              name: "DHW Operating mode",
              type: 'string',
              role: 'state',
              "states": {
                  "autoMode": "Auto",
                  "manualEcoActive": "ECO aktiv",
                  "manualEcoInactive": "ECO inaktiv"
              },
              desc: 'Betriebsmodus'
          });
      
      createState(dpRoot + ".DHWSchedule", "", {
              name: "DHW Schedule",
              type: 'string',
              role: 'state',
              "states": {
                  "pacProg_elecProg": "Zeitplanung",
                  "pac24h_elec24h": "dauerhaft"
              },
              desc: 'Zeitplanung'
          });
      
      createState(dpRoot + ".DHWBoostFull", "", {
              name: "DHW Boost",
              type: 'boolean',
              role: 'state',
              desc: 'Heizstab zuschalten'
          });
      
      createState(dpRoot + ".debug", "", {
              name: "debug",
              type: 'boolean',
              role: 'state',
              desc: 'Serverantwort protokollieren'
          });
      
      createState(dpRoot + ".rawJSON", "", {
              name: "rawJSON",
              type: 'string',
              role: 'state',
              desc: 'Serverantwort'
          });
      
      createState(dpSetTemp, "", {
              name: "WW-Solltemperatur",
              type: 'number',
              role: 'state',
              unit: '°C',
              desc: 'Solltemperatur der Wärmepumpe'
          });
      
      setState(dpSetTemp, getState(dpSetTemp), true);
      
      getToken();
      
      tokenRefreshTimer = setInterval(async function () {
          // Token verfällt nach 60min
          access_token = "";
          access_token_api = "";
      
          refresh_token = "";
          id_token = "";
          expires_in = -1;
          jwt = "";
          jwt_overkiz = "";
          session_cookie = "";
      
          //log("Token nach Intervall verworfen.")
          getToken();
      }, 600000);
      
      schedule('*/' + interval + ' * * * * *', function () {
          // regelmäßig Token und Zustand abfragen
          // access_token = ""; // Workaround...
          
          if(access_token != "") {
              getJWT();
          } else {
              getToken();
          }
          
      });
      
      on({id: dpRoot + ".fetchHistory", change: 'ne'}, function(obj) {
          if(getState(dpRoot + ".fetchHistory").val) {
              if(session_cookie != "") {
                  getHistory();
              }
          }
      });
      
      on({id: dpRoot + ".forceUpdate", change: 'ne'}, function(obj) {
          if(getState(dpRoot + ".forceUpdate").val) {
              if(session_cookie != "") {
                  execOverkizCmd("refreshMiddleWaterTemperature");
                  execOverkizCmd("refreshDHWCapacity");
                  execOverkizCmd("refreshWaterConsumption");
                  
      
                  setState(dpRoot + ".forceUpdate", false);
              }
          }
      });
      
      on({id: dpRoot + ".DHWMode", change: 'ne', ack: false}, function(obj) {
          
              if(session_cookie != "") {
                  setDHWMode();
              }
          
          
      });
      
      on({id: dpRoot + ".DHWSchedule", change: 'ne', ack: false}, function(obj) {
          
              if(session_cookie != "") {
                  setDHWSchedule();
              }
          
          
      });
      
      on({id: dpRoot + ".DHWBoostFull", change: 'ne', ack: false}, function(obj) {
          
              if(session_cookie != "") {
                  setDHWBooster();
              }
          
          
      });
      
      posted in JavaScript
      O
      oxident
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      Ich muss aber einwerfen, dass Pupeteer irgendwie derzeit noch nicht rund läuft. Habe nach einem iobroker-Umzug derzeit Probleme, den Adapter wieder lauffähig zu bekommen.

      Wenn das geklärt ist mache ich gerne eine Schritt für Schritt Anleitung.

      Andererseits fände ich diese Funktionalität eigentlich sehr gut im OpenEPaperLink-Adapter aufgehoben. Was denkt ihr?

      posted in Praktische Anwendungen (Showcase)
      O
      oxident
    • RE: Adapter: ioBroker.unifi

      @coyote Das undefined ist ein Folgefehler. Durch das Timeout ist das "site"-Objekt halt leer. Da muss irgendwie ein tieferes Problem sein ... haben viele von uns.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: [Neuer Adapter] Senec Home Adapter

      @homoran Okay, das ist natürlich ein Problem. Ich gehe da vermutlich zu "blauäugig" ran und installier die selber. Jedoch parallel zum Senec und Fronius-WR. Also quasi nur AC-seitig.

      Vielleicht finde ich später mal einen Installateur, der das dann abnickt oder verbessert. Aber meine Erfahrungen mit den Senec-Installateuren haben mir gezeigt, dass gestresste (Subunternehmer-)Elektriker leider auch nicht besser sind als mein gefährliches Halbwissen 😉

      posted in Entwicklung
      O
      oxident
    • RE: Mit Traccar eine geofence Alternative für Iphone und Android

      @braindead Habe Deinen POC einfach mal ausprobiert und muss sagen, er läuft jetzt seit einigen Tagen völlig perfekt. Es gibt keinerlei Probleme und er macht auch schon fast alles, was man sich wünschen kann.

      Ich weiß jetzt nicht, wie und ob Du damit eine Testphase bzw. sogar perspektivisch ein Stable-Release anstrebst, aber wenn ich helfen kann, dann gerne!

      Von meiner (User-)Seite gäbe es eigentlich nur eine kleine Sache:

      Man könnte die Websocket-API anstelle des festen Pollings nutzen. Das würde aber einen Session-Cookie und eventuell doch recht grundlegende Code-Anpassungen erfordern.

      posted in Praktische Anwendungen (Showcase)
      O
      oxident
    • RE: Test Adapter Growatt v3.3.1

      Prima Arbeit, bin schwer begeistert.
      Wie schon im anderen Thread geschrieben benutze ich den Adapter seit v0.0.6 (mittlerweile v0.0.9) absolut erfolgreich an meinem Balkonkraftwerk (Growatt 1300-S mit ShineWIFI-S).
      Die Daten kommen alle zuverlässig und ordentlich benannt an.

      Wäre toll, wenn es der Adapter in den Stable-Branch schafft!

      posted in Tester
      O
      oxident
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      Alles klar, habe es jetzt mal selber "gefrickelt". Hierzu habe ich im Vis eine View erstellt und mir dort als Hilfsmittel einen 296x128px Rahmen gezogen. Außerdem habe ich den Adapter "Puppeteer" installiert.

      Im Vis tobe ich mich dann innerhalb des Rahmens aus und nutze folgendes Javascript:

      sendTo('puppeteer.0', 'screenshot', { 
          url: 'http://localhost:8082/vis/index.html#NAME_DER_VIEW',
          ioBrokerOptions: {
              storagePath: 'test.jpg',
            },
            waitOption: {
              waitForTimeout: 5000,
            },
            viewportOptions: {
              width: 296,
              height: 128
            },
            type: "jpeg",
            quality: 100
      }, obj => {
            if (obj.error) {
              log(`Error taking screenshot: ${obj.error.message}`, 'error');
            } else {
              log('Sucessfully took screenshot');
              sendImageToEPaper(obj.result, "MAC-VOM-DISPLAY");
            }
      });
      
      function sendImageToEPaper(objImage, sMac) {
          var request = require('request');
          var options = {
                  url: 'http://IP-VOM-AP/imgupload',
                  method: 'POST',
                  formData: { 
                      "dither": "0", 
                      "mac": sMac,
                      "image": objImage },
                  
              };
              
          request(options,function (error, response, body){
              
                  //log("Login-Antwort: " + JSON.stringify(response));
                  if(parseInt(body.error_code)==0) {
                      
                  } else {
                      
                  }
                  
              });
      }
      
      posted in Praktische Anwendungen (Showcase)
      O
      oxident
    • RE: Beta Test js-controller Kiera (v6.0)

      @diamand2k22 Bin der, der sich für https://github.com/kopierschnitte/ioBroker.blueconnect verantwortlich fühlt. War eigentlich nur eine Bugfix-Übernahme des eigentlichen Erstellers. Aber der Adapter läuft bisher ohne Probleme.

      Leider fehlt mir die Ahnung und auch ein wenig die Zeit, das bei Github ordentlich zu pflegen. Daher auch die fehlende Liebe, die @Thomas-Braun korrekt angemerkt hat.

      Wie auch immer, bitte mal testen, ob der Fork unter https://github.com/kopierschnitte/ioBroker.blueconnect funktioniert.

      posted in Tester
      O
      oxident
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      Da ich bei der aktuellen Firmware jetzt öfters die Fehlermeldung "409 Come back later" erhalte dachte ich mir, ich versuche es mal anders.

      Und zwar kann der AP ja auch die JPG-Dateien selber vom ioBroker herunterladen. Eventuell ist das einfacher, als sie von iob immer auf den AP zu "schieben".

      Das Skript wäre dann erstmal wie folgt:

      function updateEPaperWithView(sView, sEPaperMac, imgWidth, imgHeight) {
          sendTo('puppeteer.0', 'screenshot', { 
              url: 'http://localhost:8082/vis/index.html#' + sView,
              ioBrokerOptions: {
                  storagePath: sView + '.jpg',
              },
              waitOption: {
                  waitForTimeout: 8000,
              },
              viewportOptions: {
                  width: imgWidth,
                  height: imgHeight
              },
              type: "jpeg",
              quality: 100
          }, obj => {
              if (obj.error) {
                  log(`Error taking screenshot: ${obj.error.message}`, 'error');
              } else {
                  //log('Sucessfully took screenshot');
                  
              }
          });
      }
      
      function runEPaperUpdates() {
      
          updateEPaperWithView("epaper_pool", "0000021B4F30XXXX", 296, 128);
          updateEPaperWithView("epaper_solar_verbrauch", "0000021EEB8DXXXX", 296, 128);
          updateEPaperWithView("epaper_solar", "0000021B7710XXXX", 296, 128);
      }
      
      runEPaperUpdates();
      
      schedule("*/1 * * * *", function () {
          runEPaperUpdates();
      });
      

      Im AP wählt man dann beim jeweiligen Tag die Funktion "Image URL" aus und nutzt als Adresse die des lokalen ioBrokers. Zum Beispiel http://iobroker.local:8082/0_userdata.0/epaper_solar.jpg

      Der Dateiname entspricht dem Namen der View.

      Als Interval kann man dann z. B. 3 (Minuten) angeben. Dies wäre auch das Minimum.

      Vielleicht bringt es ja etwas 😉

      posted in Praktische Anwendungen (Showcase)
      O
      oxident

    Latest posts made by oxident

    • RE: PV-Visualierung und Statistik aus 2 PV-Anlagen

      @bf0911 ... und hier von mir:
      130eacf3-f52c-4a00-b704-ecfd1a3552be-image.png
      Ich mache das ebenfalls mit Blockly und reagiere auf Änderungen an den Werten der jeweiligen Anlagen. Also sowohl die "Live-Werte" (kW) als auch die kummulierten Werte (kWh) von meinen drei PV-Anlagen und den zwei Akkus.

      Hierzu habe ich unter 0.userdata einfach entsprechende Datenpunkte angelegt und genau die "tracke" ich dann via SourceAnalytix. Wobei natürlich der Teil easy ist ... Blockly ist da schon etwas (aber nicht viel) anspruchsvoller.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: PV-Visualierung und Statistik aus 2 PV-Anlagen

      @bf0911 Also ich mache es seit Jahren exakt so, wie @paul53 es skizziert hat. Sogar noch mit zwei Akkus dabei.

      Bei mir ist es ein kleines Blockly, welches die Rechnung macht und das Ergebnis dann in einen Datenpunkt schreiben. Damit füttere ich dann Vis und SourceAnalytix.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Test Tesla-Motors v1.0.0

      Ich schreibe jetzt einfach mal wild meine Fortschritte hier rein. Vielleicht hilft es ja dem ein oder anderen.

      Nachdem mir die lokale Möglichkeit via ESPHome dann doch zu fummelig war und der ESP dafür ja auch immer irgendwie in BLE-Reichweite sein musste dachte ich mir, ich setze mich doch mal an die offizielle Fleet API ran.

      Letzten Endes habe ich extra dafür eine Home Assistant Installation aufgesetzt und bin strikt dieser Anleitung hier gefolgt: https://www.smartmotion.life/2024/04/06/tesla-integration-with-home-assistant/?srsltid=AfmBOopyzjl5ICox3n1JECMTOHLGdosnThWjFVpx4Lc43o3pqFg-eJcf&v=5f02f0889301

      Eigentlich hat das alles wunderbar geklappt, jedoch hatte ich die entsprechende Infrastruktur (NGINX-Proxy) eh schon am Laufen.

      Dann mittel HASS-Adapter iobroker und Home Assistant verbunden und nun kann ich alles wieder direkt im iobroker regeln, egal wo das Auto gerade steht.

      posted in Tester
      O
      oxident
    • RE: Pool Thermometer und Chlormesser

      @willywonka89 Letzten Endes des WROOM ... der M5 hatte leider immer Stress gemacht, wenn ich Wifi und BLE gleichzeitig genutzt habe. Kann aber auch am schlechten (BLE-)Empfang gelegen haben.

      Ansonsten wäre der M5 natürlich super geeignet.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Pool Thermometer und Chlormesser

      @willywonka89 Also eigentlich war escein ganz normaler ESP32-WROOM mit externer Antenne.
      Schau mal hier: https://www.ebay.de/itm/286506582655?mkcid=16&mkevt=1&mkrid=707-127634-2357-0&ssspo=IA0Xwa_pTMi&sssrc=4429486&ssuid=l3eyvw_dRxm&var=&widget_ver=artemis&media=COPY

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Wolf Link Home, ISM7i, ISM8i - Was ist nötig?

      @obstbauer Meiner Meinung nach ist der Funktionsumfang generell identisch.

      Aber, der wesentliche Unterschied ist, dass ism7mqtt direkt mit der Wolf spricht und der iobroker-Adapter die Cloud abfragt. Außerdem kommt hinzu, dass es bei der Cloud-Variante mal vorkommen kann, dass sich Bezeichnungen auf der Webseite ändern ... dann ändern sich prinzipbedingt auch die Namen der Datenpunkte. Könnte für eine Automatisierung lästig sein.

      Ich kann Dir daher nur dringend raten, den Web über ism7mqtt zu gehen. Jedoch weiß ich spontan nicht, ob das mit dem iSM8i auch funktioniert da ich selber das 7er Modul an'ner ollen Gastherme nutze.

      Alternativ gäbe es natürlich noch die harte Tour mit einem ebus-Adapter direkt am Bus. Dann bräuchtest Du nichtmal das iSM. Da wird's aber schwierig, die Befehle herauszufinden. Hatte ich ein Jahr lang und war mir dann doch zu unvollständig.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Batterie erweitern bei Victron Anlage

      Eventuell können die BMS auch parallel via Bluetooth abgefragt werden. Das ist bei meinem Zweitakku beispielsweise der Fall ... und da kann dann z.B. ein ESPHome-Projekt ansetzen.

      Alternativ haben manche BMS ja auch zusätzlich einen RS232-Port (via RJ11).

      Nur so als Gedanke.

      posted in Off Topic
      O
      oxident
    • RE: Batterie erweitern bei Victron Anlage

      Habe folgenden, recht interessanten Thread hierzu gefunden:
      https://akkudoktor.net/t/2-x-16-zellen-lifepo4-parallel-zusammenschalten/10440

      posted in Off Topic
      O
      oxident
    • RE: Batterie erweitern bei Victron Anlage

      @homoran Also ich persönlich dachte eher an klassische EVE-Zellen mit 3,2V. Da werde ja vermutlich schon innerhalb des kompletten Moduls bei 16 solcher Zellen gewisse Unterschiede sein.

      Aber ja, verstehe Deinen Punkt 😉

      posted in Off Topic
      O
      oxident
    • RE: Batterie erweitern bei Victron Anlage

      @homoran Danke für's Abtrennen!

      @tugsi Das sind auf jeden Fall wertvolle Tipps ... und damit hast Du mir auch Hoffnung gemacht. Ich werde es auf jeden Fall jetzt ganz koordiniert angehen und mir auch nochmal Rat beim Akkudoktor-Forum holen.

      Zellchemie ist bei mir auf jeden Fall gleich wie auch die Anzahl der Zellen (16S). Habe sogar beim gleichen Chinesen bestellt und das (Noname-)BMS ist zumindest "vergleichbar", aber leider eine neue Revision.

      Hoffe, es knallt nicht und wünsche allen hier frohe Ostern und guten Appetit 😉

      posted in Off Topic
      O
      oxident
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo