Navigation

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

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    O
    • Profile
    • Following 0
    • Followers 4
    • Topics 29
    • Posts 963
    • Best 88
    • Groups 2

    oxident

    @oxident

    102
    Reputation
    123
    Profile views
    963
    Posts
    4
    Followers
    0
    Following
    Joined Last Online

    oxident Follow
    Pro Starter

    Best posts made by oxident

    • [Javascript] Midas (Aquatemp) Poolheizung

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

      Hallo!

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

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

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

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

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

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

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

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

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

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

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

      Hallo!

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

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

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

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

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

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

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

      Oder aber hier nachfragen 😉

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

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

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

      Bugs/Hinweise:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      Das Skript wäre dann erstmal wie folgt:

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

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

      Der Dateiname entspricht dem Namen der View.

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

      Vielleicht bringt es ja etwas 😉

      posted in Praktische Anwendungen (Showcase)
      O
      oxident

    Latest posts made by oxident

    • RE: Test Adapter Energiefluss-erweitert v0.7.x GitHub/Latest

      @skb Okay, krass. Die hatte ich ja direkt übersprungen. Bei mir war das Problem bei der 0.7.6 noch da. Aber wie gesagt, durch manuelles Editieren im Datenpunkt konnte ich es lösen.

      Vielleicht hing ja auch noch eine Altlast in der Config 😉

      Danke!

      posted in Tester
      O
      oxident
    • RE: Test Adapter Energiefluss-erweitert v0.7.x GitHub/Latest

      @skb Sorry, jetzt genauer: Update war von 0.6.2 auf 0.7.6 (mit 0.7.5 als Zwischenschritt)

      posted in Tester
      O
      oxident
    • RE: Test Adapter Energiefluss-erweitert v0.7.x GitHub/Latest

      Nach dem Update auf 0.7.x wurde bei mir die Einheit "" (also keine) ignoriert und alle Datenpunkte wurden mit den Units aus der DP-Definition angezeigt.

      Das konnte ich nur lösen, indem ich manuell im Config-DP des Adapters bei allen Datenquellen ein Leerzeichen bei der Einheit eingefügt habe.

      posted in Tester
      O
      oxident
    • RE: Test Adapter AI Toolbox v0.1.3 GitHub/Latest

      @randyandy Guter Hinweis mit Gemini! Ich für meinen Teil fahre mit Qwen-12B unter Ollama (via Open WebUI) auch ganz gut.

      Ich glaube, der Adapter ist einfach "zu früh". Will sagen, es fehlen vielleicht noch richtige Use-Cases mit praktischen Beispielen. Dann könnte das vielleicht noch zünden...

      posted in Tester
      O
      oxident
    • RE: Wolf Smart Set

      @manrum1 Du kannst in der Smartset-App beim Einloggen unten rechts auf "Nutzung ohne Internet" klicken. Wenn das funktioniert, dann sind die Voraussetzungen für ism7mqtt gegeben:

      Screenshot_20250523_194107.png

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Wolf Smart Set

      @manrum1 Sehe irgendwie noch keinen Fehler bei Dir. Hast Du mal versucht, ob Fu via Handy oder Tablet direkten Zugriff (ohne Cloud) bekommen kannst?

      Nicht, dass es doch irgendein Firmware-Update braucht...

      posted in ioBroker Allgemein
      O
      oxident
    • RE: Wolf Smart Set

      @manrum1 Hmm. also bei mir läuft auch beides parallel und teilweise sogar noch der Wolf-Adapter. Ist vielleicht nicht optimal, funktioniert aber...

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

      @vanom-vine Jepp, anders geht es leider nicht. Man kann es aber mit einem ESP32 und ESPHome versuchen. Ist zwar noch etwas hakelig, aber prinzipiell zu schaffen.

      Davon bekommt dann aber weder die App noch mein Adapter etwas mit (und umgekehrt)...

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

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

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

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

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

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

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