Navigation

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

    NEWS

    • Wir empfehlen: Node.js 22.x

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker goes Matter ... Matter Adapter in Stable

    O
    • Profile
    • Following 0
    • Followers 4
    • Topics 30
    • Posts 975
    • Best 91
    • Groups 2

    oxident

    @oxident

    101
    Reputation
    127
    Profile views
    975
    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: 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: Test Adapter Samsung Smartthings v.0.0.x

      @adamk Verstehe, was Du meinst, aber "schlampig programmiert" ist der Adapter wirklich nicht!

      Letzten Endes ist es Samsung's Schuld, hier je nach Geräteklasse massenhaft (sinnfreier) Daten zur Verfügung zu stellen. Samsung selber verfügt natürlich über ein entsprechendes Team welches die diversen Clients (App, Alexa-Skill, TV, ...) genau kennt.

      Dieser Adapter hier kann nicht mehr machen, als die Smartthings-API möglichst ungefiltert durchzulassen. Filtern und Herausfinden, was wichtig ist kann ein privater Entwickler nicht leisten ... da musste selber ran.

      Und ja, Alexa dafür zu nutzen ist auch eine Möglichkeit 😉

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

      @dispo112 Mega! ... und: Bescheid 😁

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

      @dispo112 Ja, das wäre auf jeden Fall ein Anfang. Ich meine aber, dass SourceAnalytix das auch kann und dann halt bei jeder Änderung des Datenpunkts berechnet. Dürfte aber so oder so ungenau sein.

      Sieht mir auch leider danach aus, dass es wohl länger dauert, bis wir wieder an die offiziellen Daten kommen.

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

      @semmy Hab jetzt vieles versucht: Home Assistant oder auch Summieren verfügbarer Werte mit SourceAnalytix ... aber es scheint erstmal nichts zu funktionieren.

      Wir können nur hoffen, dass sich nach morgiger Umstellung der UI bei Senec jemand findet, der die Herausforderung annimmt 🙂

      posted in Entwicklung
      O
      oxident
    • RE: Test Adapter Grünbeck v0.0.x

      @tombox Wäre super, wenn Du mal schauen könntest. Manuelle Regeneration klappt leider auch nicht mehr.

      posted in Tester
      O
      oxident
    • RE: Test Adapter Grünbeck v0.0.x

      @oxident Okay, ich hab das jetzt über Home Assistant gelöst. Der dortige "Adapter" funktioniert und ich zieh mir die Daten dann einfach aus dem HASS.

      Wäre natürlich toll, wenn es bald wieder nativ klappen würde.

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

      @tonitl Hier ebenfalls. Dachte schon, es hat mit meiner Installation zu tun.

      posted in Entwicklung
      O
      oxident
    • RE: Test Adapter Grünbeck v0.0.x

      Nach einem Komplettabsturz und anschließendem Restore bekomme ich leider keine Daten mehr. Es hagelt 404-Fehler ... aber Befehle (z.B. Leuchtring) kann ich absetzen.

      Habt ihr eine Idee oder einen Vorschlag für mich? 😉

      posted in Tester
      O
      oxident
    • RE: [Javascript] Midas (Aquatemp) Poolheizung

      @diamand2k22 Ich hoffe es ... AquaTemp war in der Vergangenheit nicht gerade sehr "pflegeleicht" und diese China Cloud ist wirklich dämlich (und überflüssig). Wenn es mit Tuya local wirklich funktioniert, dann wäre das definitiv ein Argument!

      posted in Praktische Anwendungen (Showcase)
      O
      oxident
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo