Navigation

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

    NEWS

    • Neues Video "KI im Smart Home" - ioBroker plus n8n

    • Neues Video über Aliase, virtuelle Geräte und Kategorien

    • Wir empfehlen: Node.js 22.x

    O
    • Profile
    • Following 0
    • Followers 4
    • Topics 31
    • Posts 990
    • Best 94
    • Groups 2

    oxident

    @oxident

    104
    Reputation
    127
    Profile views
    990
    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: [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

      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: Test Adapter Samsung Smartthings v.0.0.x

      Ich denke, das Problem ist hier, dass es halt ein "generischer" Adapter ist. Bei dem riesigen Zoo an Geräten im Samsung-Universum wäre es auch unmöglich, hier seitens der Entwickler alle Sonderlocken abzubilden.

      Schuld dürfte jedoch eher Samsung haben.

      Daher auch mein Rat: Selektiv schauen, was überhaupt benötigt wird und den Rest dann ausfiltern. Ja, das ist komplex. Glaubt mir, mit einem Samsung Familyhub Kühlschrank weiß ich, wovon ich rede 😞

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

      @beowolf Dann ist etwas Handarbeit gefragt. Schau mal mein Issue (mit Workaround):

      https://github.com/foxriver76/ioBroker.puppeteer/issues/13

      kopierschnitte created this issue in foxriver76/ioBroker.puppeteer

      closed Installation/Usage not possible on ARM64 platforms (RPi, etc.) #13

      posted in Praktische Anwendungen (Showcase)
      O
      oxident

    Latest posts made by oxident

    • RE: MieleCloudService Adapter

      @fernetmenta Sehe ich leider ebenso. Dürfte der Grund sein, wieso Firmen wie Tesla bei bestimmten Konsumenten kurzfristig so "durchschlagen".

      Verstehe nicht, warum Hersteller nicht einfach (zusätzlich) direkten Zugang zu den Geräten ermöglichen. Würde die Cloud-Last verringern und die Absatzzahlen pushen.

      Grünbeck ist auch so ein Kandidat. MQTT lange versprochen und letzten Endes wieder verworfen.

      posted in Tester
      O
      oxident
    • RE: cod.m ZigBee Coordinator (PoE/non-PoE) - made in Germany

      Bei mir lief alles super durch und gefühlt ist die Latenz jetzt noch geringer. Gerade mit meinen geliebten Senic/FoH-Schaltern ist jetzt alles so viel besser als mit der vorherigen Deconz-Konstellation.

      Zumindest nachdem ich ein paar Router in's Netz genommen hab 😉

      posted in Marktplatz
      O
      oxident
    • RE: Test Adapter smartloadmanager v0.0.x-alpha GitHub

      @quorle Ok, da hab ich wahrscheinlich noch ein Brett vorm Kopf oder aber, die Akkus spielen mir einen Streich beim Denken.

      Bisher habe ich immer Ertrag - Verbrauch + Akkubeladung als Grundlage genommen. Will sagen: 2000W kommen vom Dach, Haus verbraucht gerade 600W und Akku lädt (logischerweise) mit 1400W. Exakt diese 1400W würde ich lieber z.B. in meine Brauchwasserwärmepumpe (700W) stecken.

      Daher check ich gerade den Sinn der Grundlast nicht. Wenn ich jetzt zwischendurch auf die Idee komme, Backofen oder Auto zu "befeuern", dann übersteigt der Hausverbrauch ja sofort den PV-Ertrag und auch der Akku wird entladen. Dann soll die Wärmepumpe na klar ausgehen...

      posted in Tester
      O
      oxident
    • RE: Tester wanted - Zigbee Adapter 3.1

      @asgothian Habe ehrlich gesagt nur eine einzelne Hue-Lampe angelernt. Da gab es keine Probleme bei der 3.0.1

      posted in Tester
      O
      oxident
    • RE: Test Adapter smartloadmanager v0.0.x-alpha GitHub

      @quorle Super Adapter! Dann kann ich endlich meine JS-Basteleien wegoptimieren 😉

      Ich hab jedoch eine grundsätzliche Verständnisfrage: Da ich mehrere Wechselrichter und Batterien habe würde ich die Logik des Adapters gerne auf die Einspeisung am Zähler (und nicht die PV-Produktion) loslassen.

      Will sagen: Der Adapter soll Verbraucher einschalten, wenn X Watt in den Speicher (oder in's Netz) fließen und wieder abschalten, wenn Y Watt aus dem Speicher (oder dem Netz) bezogen werden.

      Hast Du eine Idee, wie ich das umsetzen kann?
      Würde es Sinn machen, wenn ich einen Datenpunkt berechnen lasse, der die PV-Produktion summiert und davon dann den aktuellen Hausverbrauch (ohne Speicherladung) abzieht?

      Dann wäre die "Basislast-Schwelle" im Adapter jedoch vermutlich auf 0 zu setzen, da ja der Hausverbrauch schon abgezogen wurde, oder?

      posted in Tester
      O
      oxident
    • RE: Tester wanted - Zigbee Adapter 3.1

      Ich habe ein Test-Netz aufgebaut und möchte da mittelfristig meine (über 100) Geräte/Sensoren von Deconz rüberholen.

      Daher kann ich ganz entspannt schon direkt ein paar Dinge mit dem latest Release testen.

      Spontan aufgefallen ist mir, dass der iot-Adapter scheinbar versucht, benannte Farben in den Hex-Datenpunkt eine Hue-Lampe zu schreiben.

      Bitte steinigt mich nicht, falls das die völlig falsche Baustelle ist 😉

      posted in Tester
      O
      oxident
    • RE: Probleme mit Zigbee-Schaltern mit cod.m Modul

      @homoran said in Probleme mit Zigbee-Schaltern mit cod.m Modul:

      weil der als Router fungiert

      Ja, denke ich auch. Habe jetzt testweise mal einen weiteren Zwischenstecker in's Netz eingebunden und den ersten stromlos gelassen.
      Schalter klappt auch direkt wieder (obwohl er den neuen Router ja gar nicht kannte).

      Dann noch direkt einen weiteren Senic-Schalter angelernt. Klappte auch.

      Die Events von beiden Schaltern kommen aber trotzdem nur beim Coordinator an, wenn mindestens einer der Zwischenstecker unter Spannung steht.
      Selbst, wenn der im Obergeschoss ist und der Schalter direkt neben dem Coordinator liegt 😉

      Für mich soweit okay ... war trotzdem eine fiese Hürde.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Probleme mit Zigbee-Schaltern mit cod.m Modul

      @homoran Nee, mein Testaufbau war wirklich sehr simpel und überschaubar:

      Coordinator liegt vor mir auf dem Schreibtisch und Schalter sowie (neuerdings) der Zwischenstecker ebenfalls.
      Wenn ich nun den Zwischenstecker stromlos mache komme auch sofort keinerlei Events mehr an.

      Vorher hatte ich auch schon diverse Abstände zwischen Coordinator und Schalter getestet. Auch mal testweise aus dem Nebenraum heraus.

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Probleme mit Zigbee-Schaltern mit cod.m Modul

      Jetzt kam ich endlich zum Testen. Ja, es ist exakt so, wie vermutet:
      Sobald ein "normales" Gerät im Netz ist (hier testweise ein Zigbee-Zwischenstecker) funktionieren die Senic-Schalter problemlos.

      f3058e31-2202-416e-a185-ced6f40df49a-image.png

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Probleme mit Zigbee-Schaltern mit cod.m Modul

      Hier noch die Doku, die das Problem beschreibt: https://www.zigbee2mqtt.io/advanced/zigbee/01_zigbee_network.html#green-power-devices

      Mir scheint, als wäre das abhängig vom Chip. Bei den Silabs-Varianten scheint es zu funktionieren, die TI-Chips brauchen wohl einen "Proxy" (z.B. Hue-Lampe).

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