Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe

    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

    [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe

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

      Musste meinen Broker neu aufsetzen. Nun habe ich das Problem, dass die HTML Tabelle nicht mehr erstellt wird. Es wird die Nachricht erzeugt welches der aktuell niedrigste Bettriestand ist, aber die Tabelle mit den Geräten wird nicht erstellt. Hat jemand eine Idee woran das liegen kann?
      Ich glaube an dem hier liegt es... Habe ich einen Fehler gemacht?

      javascript.0	2021-10-16 23:33:41.605	error	(13463) at processImmediate (internal/timers.js:461:21)
      javascript.0	2021-10-16 23:33:41.604	error	(13463) at Immediate._onImmediate (/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js:5706:41)
      javascript.0	2021-10-16 23:33:41.604	error	(13463) at Object.stateChange (/opt/iobroker/node_modules/iobroker.javascript/main.js:530:29)
      javascript.0	2021-10-16 23:33:41.603	error	(13463) at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1087:38)
      javascript.0	2021-10-16 23:33:41.603	error	(13463) at Object.<anonymous> (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:636:13)
      javascript.0	2021-10-16 23:33:41.602	error	(13463) at CheckBatterys (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:449:5)
      javascript.0	2021-10-16 23:33:41.602	error	(13463) at CheckDeadBatt (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:351:13)
      javascript.0	2021-10-16 23:33:41.602	error	(13463) at MakeTable (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:587:75)
      javascript.0	2021-10-16 23:33:41.601	error	(13463) Error in callback: TypeError: Cannot read property 'toFixed' of undefined
      javascript.0	2021-10-16 23:33:31.754	error	(13463) at processImmediate (internal/timers.js:463:21)
      javascript.0	2021-10-16 23:33:31.754	error	(13463) at Immediate._onImmediate (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1988:38)
      javascript.0	2021-10-16 23:33:31.753	error	(13463) at Object.<anonymous> (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:110:13)
      javascript.0	2021-10-16 23:33:31.753	error	(13463) at main (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:252:5)
      javascript.0	2021-10-16 23:33:31.752	error	(13463) at MakeTable (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:587:75)
      javascript.0	2021-10-16 23:33:31.749	error	(13463) Error in callback: TypeError: Cannot read property 'toFixed' of undefined
      

      Das ist das Skript:

      const Version = "1.8.2"; // Batterieüberwachungsskript Stand 26.06.2021 - Git: https://github.com/Pittini/iobroker-Batterienauswertung - Forum: https://forum.iobroker.net/topic/31676/vorlage-generische-batteriestandsüberwachung-vis-ausgabe
      //Überwacht Batteriespannungen beliebig vieler Geräte 
      log("starting Batterieüberwachung V." + Version);
      //WICHTIG!!!
      //Vorraussetzungen: Den Gerätechannels müssen Räume, sowie die Funktion "BatterieSpannung_xx" für jeden entsprechenden Batteriespannungs Datenpunkt zugewiesen sein.
      //Bitte unbedingt Anleitung beachten
      // Nach der Zuweisung unbedingt den JS Adpter neu starten! 
      
      //Grund Einstellungen
      const praefix = "0_userdata.0.Skripte.BatterieUeberwachung."; //Grundpfad für Script DPs 
      const logging = false; //Logging aktivieren?
      const FunktionBaseName = "BatterieSpannung_"; //Name der Funktion welche für die Batterieüberwachung genutzt wird
      const DeadFunktionName = "DeadCheck"; //Name der Funktion welche für den DeadCheck genutzt wird
      const UseMail = true; // Sollen Nachrichten via Mail gesendet werden?
      const UseSay = false; // Sollen Nachrichten via Say ausgegeben werden? Funktion des Authors, sollte bei Anwendern auf false gesetzt werden.
      const UseEventLog = false; // Sollen Nachrichten ins Eventlog geschreiben werden? Funktion des Authors, sollte bei Anwendern auf false gesetzt werden.
      const UsePopUp = false // Soll PopUp angezeigt werden? Funktion des Authors, sollte bei Anwendern auf false gesetzt werden.
      const ProzMeansLive = true; //Zeigen Prozentwerte des Gerätedatenpunktes Batteriekapazität oder restliche Lebensdauer?
      let DeadIsAfter = 1440; // In Minuten - Zeit nach der ein Gerät als "tot" gewertet wird wenn keine Statusänderung (ts) erfolgte.
      const NotifyDeadDevices = true; //Sollen "tote" Geräte gemeldet werden?
      const NotifyWarnDevices = true;//Sollen Geräte unter Limit gemeldet werden?
      const DeconzNameFromDP = false; //Nimmt für Deconz den Namen aus dem Datenpunkt statt aus dem übergeordnetem Channel
      
      //Variablen für Alexa
      const UseAlexa = false; // Sollen Nachrichten via Alexa ausgegeben werden?
      const AlexaInstance = "alexa2.0";
      const AlexaId = ""; // Die Alexa Seriennummer
      const AlexaVolume = "50"; // Lautstärke der Nachrichten. Wert von 1 bis 100
      
      //Variablen für Pushover
      const UsePushover = false; //Sollen Nachrichten via Pushover versendet werden?
      const PushoverDevice = 'All'; //Welches Gerät soll die Nachricht bekommen
      const PushoverInstance = "pushover.0"; //Pushoverinstanz welche genutzt werden soll angeben
      const PushOverTitle = 'Batterien überprüfen';
      
      //Variablen für Telegram
      const UseTelegram = true; // Sollen Nachrichten via Telegram gesendet werden?
      const TelegramInstance = "telegram.0"; //Telegraminstanz welche genutzt werden soll angeben
      const TelegramUser = ''; //Welche User sollen die Nachricht bekommen? Leer lassen für alle User. Mehrere User getrennt durch Komma.
      
      //Tabellen Einstellungen
      const TblOkBgColor = "#4caf50"; //Hintergrundfarbe für Batteriestatus Ok
      const TblInfoBgColor = "#ffc107"; //Hintergrundfarbe für Batteriestatus Info, also die leerste Batterie welche noch nicht das Limit unterschreitet
      const TblWarnBgColor = "#f44336"; //Hintergrundfarbe für Batteriestatus Warnung, also jene Batterie welche unter das Limit kam.
      const TblDeadBgColor = "grey"; //Hintergrundfarbe für Batterie/Geräte Status tot.
      const HeadBgColor = "dimgrey"; //Hintergrundfarbe des Tabellenkopfes
      const FontColor = "black"; //Textfarbe für Tabelleninhalt
      const HeadFontColor = "white"; //Textfarbe für Tabellenkopf
      const TblShowLfdCol = true; //Tabellenspalte mit laufender Nummer anzeigen?
      const TblShowDeviceIDCol = false; //Tabellenspalte mit Geräte ID anzeigen?
      const TblShowDeviceNameCol = true; //Tabellenspalte mit Gerätenamen anzeigen?
      const TblShowRoomCol = false; //Tabellenspalte mit Raum anzeigen?
      const TblShowUmaxCol = false; //Tabellenspalte mit Batterie Nennspannung anzeigen? 
      const TblShowUistCol = true; //Tabellenspalte mit aktueller Batteriespannung anzeigen?
      const TblShowUlimitCol = false; //Tabellenspalte mit unterer Batterielimit Spannung anzeigen?
      const TblShowProzbatCol = true; //Tabellenspalte mit Batteriestand in Prozent anzeigen?
      const TblShowProzliveCol = false; //Tabellenspalte mit Restlebensdauer unter Berücksichtigung der Limitspannung in Prozent anzeigen? Beispiel: Batterie hat 3V Nennspannung, Limit ist bei 2V, aktueller Batteriestand ist 2.5V, dann wäre die Restlebensdauer 50%
      const TblShowStatusCol = true; //Tabellenspalte mit Status ausgeben?
      const TblShowHasDeadCheck = true; //Tabellenspalte mit DeadCheckstatus ausgeben?
      
      //Ab hier nix mehr ändern
      /** @type {{ id: string, initial: any, forceCreation: boolean, common: iobJS.StateCommon }[]} */
      const States = []; //States Array initialisieren
      let DpCount = 0; //Zähler für anzulegende Datenpunkte
      const Sensor = [] //Sensoren Array initialisieren
      const BatteryMinLimitDp = []; //Array mit den generierten MinLimit Einstellungsdatenpunkten
      const WelcheFunktionVerwenden = []; // Array mit allen Einträgen aus Funktionen welche den FunktionBaseName beinhalten
      let AllBatterysOk = true;
      let LastMessageSeparator = "<br>";
      let NextExpectedLowBatt = "";
      let EmptyBatCount = 0;
      let DeadDeviceCount = 0;
      let TickerObj;
      let IsInit = true;
      //Datenpunkte anlegen in javascript.0.BatterieUeberwachung.
      States[DpCount] = { id: praefix + "AllBatterysOk", initial: true, forceCreation: false, common: { read: true, write: false, name: "Alle Batterien Ok?", type: "boolean", role: "state", def: false } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "LastMessage", initial: "", forceCreation: false, common: { read: true, write: false, name: "Letzte Warnmeldung", type: "string", role: "state", def: "" } }; //
      DpCount++;
      FillWelcheFunktionVerwenden(); //Vorab Funktionen mit Umax Spannungen einlesen da diese für ID und Namen der MinLimit States benötigt werden
      
      for (let x = 0; x < WelcheFunktionVerwenden.length; x++) {
          let dummy = WelcheFunktionVerwenden[x].slice(FunktionBaseName.length) //Letzten Zeichen aus Funktionsnamen extrahieren
          let VoltInitial = CreateUmaxValueFromString(x) //Extrahierte Zeichen zu Kommazahl wandeln 
          VoltInitial = VoltInitial / 100 * 80; //Initialwert für Limit berechnen
          if (logging) log("InitialSpannung " + x + " gesetzt auf 80%= " + VoltInitial);
          States[DpCount] = { id: praefix + "BatteryMinLimit_" + dummy, initial: VoltInitial, forceCreation: false, common: { read: true, write: true, name: "Unteres Limit für Warnmeldung bei " + toFloat(dummy.slice(0, dummy.length - 1) + "." + dummy.slice(-1)) + "V Geräten", type: "number", role: "value", unit: "V", def: 2.6 } }; //
          BatteryMinLimitDp[x] = "BatteryMinLimit_" + dummy;
          DpCount++;
      };
      States[DpCount] = { id: praefix + "NextExpectedLowBatt", initial: "", forceCreation: false, common: { read: true, write: false, name: "Vorraussichtlich nächste zu wechselnde Batterie", type: "string", role: "state", def: "" } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "OverviewTable", initial: "", forceCreation: false, common: { read: true, write: false, name: "Einfache HTML Übersichtstabelle", type: "string", role: "state", def: "" } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "EmptyBatCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Zähler für Anzahl der zu wechselnden Batterien", type: "number", role: "state", def: 0 } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "DeadDeviceCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Zähler für Anzahl der nicht mehr aktualisierenden Geräte", type: "number", role: "state", def: 0 } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "DeviceCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Zähler für Anzahl der überwachten Geräte", type: "number", role: "state", def: 0 } }; //
      DpCount++;
      States[DpCount] = { id: praefix + "DeadCheckCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Zähler für Anzahl der gesetzten DeadChecks", type: "number", role: "state", def: 0 } }; //
      
      //Alle States anlegen, Main aufrufen wenn fertig
      let numStates = States.length;
      States.forEach(function (state) {
          createState(state.id, state.initial, state.forceCreation, state.common, function () {
              numStates--;
              if (numStates === 0) {
                  if (logging) log("CreateStates fertig!");
                  main();
              };
          });
      });
      
      function CreateUmaxValueFromString(x) {
          let dummy = WelcheFunktionVerwenden[x].slice(FunktionBaseName.length) //Aus der Funktionsbezeichnung die letzten Zeichen extrahieren= z.B. 33
          return toFloat(dummy.slice(0, dummy.length - 1) + "." + dummy.slice(-1)) //Die extrahierten Zeichen zu einer Kommazahl wandeln= z.B. 3.3
      }
      
      function Init() {
          if (logging) log("Reaching init()");
          let counter = 0; //Zähler für Devices
          let TempVal // Temporärer Sensorwert um nicht mehrere GetStates zu benötigen
          let TempUnit //Einheit für Unterscheidung ob % vorliegen
          //  let TempLiveWindow //Spannungsfensterbereich
          let Funktionen = getEnums('functions'); //Alle Funktionen der Aufzählung in Array Funktionen übertragen
          for (let x in Funktionen) {        // loop ueber alle Funktionen
              let Funktion = Funktionen[x].name; // Einzelne Funktion aus dem Array
              if (typeof Funktion == 'object') Funktion = Funktion.de; //Wenn Rückgabewert ein Objekt ist, ist die Funktion mehrsprachig und es wird die deutsche Bezeichnug verwendet
              let members = Funktionen[x].members; //Array mit allen Mitgliedern der Funktion erzeugen
              for (let z = 0; z < WelcheFunktionVerwenden.length; z++) { //Loop über alle Funktions welche zu WelcheFunktionVerwenden passen
                  if (Funktion == WelcheFunktionVerwenden[z]) { //Wenn Function ist WelcheFunktionVerwenden (BatterieSpannung)
                      let Umax = CreateUmaxValueFromString(z) //Batteriesollspannung aus der Funktionsbezeichnung extrahieren
                      let BattMinLimitTemp = getState(praefix + "BatteryMinLimit_" + WelcheFunktionVerwenden[z].slice(FunktionBaseName.length)).val; //Temporäres (für den jeweiligen Schleifendurchlauf) MinLimit einlesen
                      if (typeof (BattMinLimitTemp == "string")) { //Falls MinLimit Wert String ist zu float wandeln
                          //log("BattMinLimit Value is String, trying to convert");
                          BattMinLimitTemp = parseFloat(BattMinLimitTemp);
                          if (typeof (BattMinLimitTemp == "number")) {
                              if (logging) log("BattMinLimit Value conversion - success");
                          };
                      };
                      for (let y in members) { // Loop über alle WelcheFunktionVerwenden Members
                          Sensor[counter] = {};
                          Sensor[counter].id = members[y]; //Treffer in SenorIDarray einlesen
                          TempVal = getState(Sensor[counter].id).val;//Wert vom Sensor in Tempval einlesen um wiederholte Getstates zu vermeiden
                          if (typeof (TempVal) == "undefined") TempVal = 0; //Bei leeren Feldern 0 setzen um Fehler zu vermeiden
                          if (typeof (TempVal) == "string") { //Wenn Wert als String deklariert obwohl Zahl
                              if (!isNaN(parseFloat(TempVal))) { //Wenn konvertierung kein NaN ergibt
                                  TempVal = parseFloat(TempVal); //Konvertieren
                              };
                          };
                          if (logging) log("existsState(Sensor[counter].id)=" + existsState(Sensor[counter].id) + " typeof (getState(Sensor[counter].id).val)=" + typeof (getState(Sensor[counter].id).val) + " getState(Sensor[counter].id).val=" + getState(Sensor[counter].id).val)
                          Sensor[counter].state = "";
                          Sensor[counter].unit = GetUnit(counter);
                          if (logging) log("Tempval=" + TempVal + " TempUnit=" + TempUnit + " TypeOf=" + typeof (TempVal));
                          Sensor[counter].uMax = Umax; //Synchrones UmaxArray füllen
                          Sensor[counter].batteryMinLimit = BattMinLimitTemp;
      
                          MainCalc(TempVal, counter)
      
                          if (Sensor[counter].liveProz > 100) Sensor[counter].liveProz = 100; //Um bei übervollen Batterien mehr als 100% live zu vermeiden
                          if (logging) log(counter + " " + Funktion + ' found at ' + members[y] + " Umax= " + Sensor[counter].uMax + " BattMinLimit=" + BattMinLimitTemp + " Val= " + Sensor[counter].value + " SensorProzent= " + Sensor[counter].uProz);
                          counter++;
                      };
                      setState(praefix + "DeviceCount", counter, true);
                  };
              };
          };
      }
      
      function MainCalc(TempVal, counter) {
          if (logging) log("Reaching MainCalc, TempVal=" + TempVal + " counter=" + counter);
      
          let TempLiveWindow = Sensor[counter].uMax - Sensor[counter].batteryMinLimit;
      
          switch (typeof (TempVal)) { //Wenn der Sensorwert bool ist (wenn nur LowBatt mit true/false vom Sensor gemeldet wird)
              case "boolean": //Sensorval ist Bool
                  if (TempVal) { //Bei Lowbat=true
                      Sensor[counter].value = 0; //Batt wird als leer definiert und auf 0 gesetzt
                      Sensor[counter].uProz = 0; //Prozentwerte aus Umax und Sensorwert errechnen
                      Sensor[counter].liveProz = 0; //Lebensprozent auf 0%
                  }
                  else {
                      Sensor[counter].value = Sensor[counter].uMax; //Batt wird als voll definiert und auf Umax gesetzt
                      Sensor[counter].uProz = 100; //Prozentwerte aus Umax und Sensorwert errechnen
                      Sensor[counter].liveProz = 100; //Lebensprozent auf 100%
                  };
                  break;
              case "number": //Sensorval ist Zahl
                  switch (Sensor[counter].unit) { //Bei Zahlen nach Einheit unterscheiden um % Angaben mit zu verarbeiten
                      case "%": //Bei Datenpunkt Unit = %
                          //if (logging) log("unit= " + TempUnit + " should be %");
                          if (ProzMeansLive) { // Wenn die Prozentangabe bereits Lebensdauer zeigt (Einstellungsoption)
                              Sensor[counter].liveProz = TempVal; //Direkt zuweisen aus Sensorwert
                              Sensor[counter].value = Sensor[counter].uMax - TempLiveWindow + (TempLiveWindow / 100 * Sensor[counter].liveProz);
                              Sensor[counter].uProz = (Sensor[counter].value / Sensor[counter].uMax) * 100 //Errechne Batteriekapazität
                          }
                          else if (!ProzMeansLive) { //Wenn die Prozentangabe Batteriekapazität darstellt  (Einstellungsoption)
                              Sensor[counter].uProz = TempVal; //Batteriekapazität in % bestimmen
                              Sensor[counter].value = Sensor[counter].uMax / 100 * Sensor[counter].uProz; //Sensorwert aus Umax und Prozentwert bestimmen
                              Sensor[counter].liveProz = (Sensor[counter].value - Sensor[counter].batteryMinLimit) / (Sensor[counter].uMax - Sensor[counter].batteryMinLimit) * 100; //Restlebensdauer in % ermitteln
                          };
      
                          break;
                      default: // In allen anderen Fällen
                          Sensor[counter].value = TempVal; //Spannung ist Wert vom DP
                          Sensor[counter].uProz = Sensor[counter].value / Sensor[counter].uMax * 100; //Prozentwerte aus Umax und Sensorwert errechnen
                          Sensor[counter].liveProz = (Sensor[counter].value - Sensor[counter].batteryMinLimit) / (Sensor[counter].uMax - Sensor[counter].batteryMinLimit) * 100; //Restlebensdauer in % ermitteln
                  };
                  break;
              case "string": //Sensorval ist Text
                  if (TempVal == "ok" || TempVal == "NORMAL") {
                      Sensor[counter].value = Sensor[counter].uMax; //Batt wird als voll definiert und auf Umax gesetzt
                      Sensor[counter].uProz = 100; //Prozentwerte aus Umax und Sensorwert errechnen
                      Sensor[counter].liveProz = 100; //Lebensprozent auf 100%
                  }
                  else { //Bei BatteryState != ok
                      Sensor[counter].value = 0; //Batt wird als leer definiert und 0.1 unter MinLimit gesetzt
                      Sensor[counter].uProz = 0; //Prozentwerte aus Umax und Sensorwert errechnen
                      Sensor[counter].liveProz = 0; //Lebensprozent auf 0%
                  };
                  break;
              default:
          };
      
      }
      
      
      function FillWelcheFunktionVerwenden() {
          if (logging) log("Reaching FillWelcheFunktionVerwenden");
          let z = 0;
          let Funktionen = getEnums('functions'); //Alle Funktionen der Aufzählung in Array Funktionen übertragen
      
          for (let x in Funktionen) {        // loop ueber alle Funktionen
              let Funktion = Funktionen[x].name; // Einzelne Funktion aus dem Array
              if (typeof Funktion == 'object') Funktion = Funktion.de; //Wenn Rückgabewert ein Objekt ist, ist die Funktion mehrsprachig und es wird die deutsche Bezeichnung verwendet
              if (Funktion.includes(FunktionBaseName)) {
                  WelcheFunktionVerwenden[z] = Funktion;
                  if (logging) log("Found Function " + WelcheFunktionVerwenden[z]);
                  z++;
              };
          };
      }
      
      function main() {
          if (logging) log("Reaching main()");
          Init(); //Alle Werte einlesen, Arrays füllen, fehlende Werte errechnen
          if (IsInit) CreateTrigger(); // Trigger erzeugen
          CheckAllBatterys(); // Alle Batteriestände prüfen
          CheckAllBatterysOk();
          CheckNextLowBatt(); // Batterie mit niedrigster Spannung finden
          MakeTable(); //HTML Tabelle erzeugen
          if (IsInit) Ticker(); //Startet Intervallprüfung für nicht aktualisierende Geräte
          IsInit = false;
      }
      
      function Meldung(msg) {
          log("Reaching Meldung(), msg=" + msg);
          if (UseSay) Say(msg);
          if (UseTelegram) {
              sendTo(TelegramInstance, "send", {
                  user: TelegramUser,
                  text: msg
              });
          };
          if (UseMail) {
              sendTo("email", {
                  html: msg
              });
          };
          if (UseAlexa) {
              if (AlexaId != "") setState(AlexaInstance + ".Echo-Devices." + AlexaId + ".Commands.announcement"/*announcement*/, AlexaVolume + "; " + msg);
          };
          if (UsePushover) {
              sendTo(PushoverInstance, {
                  device: PushoverDevice,
                  message: msg,
                  title: PushOverTitle,
                  priority: 0,
                  retry: 60,
                  expire: 600,
                  html: 1
              });
          };
      
          if (logging) log(msg);
          if (UseEventLog) WriteEventLog(msg);
          if (UsePopUp) ShowPopUp(true, msg, "Batterys", "red");
      }
      
      function CheckDeadBatt() {
          if (logging) log("Reaching CheckDeadBatt()");
          let jetzt = new Date().getTime();
          let Funktionen = getEnums('functions'); //Alle Funktionen der Aufzählung in Array Funktionen übertragen
          DeadDeviceCount = 0;
          let members;
          let counter = 0;
          for (let y in Funktionen) {        // loop ueber alle Funktionen
              let Funktion = Funktionen[y].name; // Einzelne Funktion aus dem Array
              if (typeof Funktion == 'object') Funktion = Funktion.de; //Wenn Rückgabewert ein Objekt ist, ist die Funktion mehrsprachig und es wird die deutsche Bezeichnung verwendet
              if (Funktion.includes(DeadFunktionName)) {
                  members = Funktionen[y].members; //Array mit allen Mitgliedern der Funktion erzeugen
              };
          };
      
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen
              if (existsState(Sensor[x].id)) {
                  let ParentDeviceId = GetParentId(Sensor[x].id);
                  Sensor[x].isDead = false;
                  Sensor[x].hasDeadCheck = false;
      
                  //Check at Extra Function Datapoint DeadCheck
                  for (let z in members) {
                      if (members[z].includes(ParentDeviceId)) {    //Jetzt prüfen ob Funktion DeadCheck innerhalb des Channels
                          Sensor[x].hasDeadCheck = true;
                          if (logging) log("Device " + ParentDeviceId + " has Deadcheck, now checking");
                          if (logging) log("z=" + z + " Device " + ParentDeviceId + " check at  " + members[z]);
                          if ((getState(members[z]).ts + (DeadIsAfter * 60 * 1000)) < jetzt) {
                              if (logging) log("Deadcheck failed, " + ParentDeviceId + " seems to be dead");
                              Sensor[x].isDead = true;
                          } else {
                              if (logging) log(ParentDeviceId + " is not dead");
                              Sensor[x].isDead = false;
                          };
                          counter++;
                      };
                  };
                  setState(praefix + "DeadCheckCount", counter, true);
      
                  //Reaction after checks
                  if (Sensor[x].isDead) {
                      if (logging) log("Jim...he's dead")
                      if (Sensor[x].state != "dead") { //Wenn Sensor bei vorheriger Prüfung noch nicht tot, Meldung absetzen.
                          CheckForAlerts()
                      };
                      Sensor[x].state = "dead"; //Status auf tot setzen
                      DeadDeviceCount++; //Zähler ehöhen
                  } else {
                      if (Sensor[x].state == "dead") { //Wenn Sensor bisher als tot gelistet, aber wieder aktualisiert, Status prüfen
                          Sensor[x].state = "ok";
                          Sensor[x].isDead = false;
                          CheckBatterys(x);
                      };
                  };
              } else {
                  log("CheckDeadBatt() State for " + x + " doesnt exists");
              };
      
              if (x == Sensor.length - 1) { //Ausführung erst wenn Schleife komplett durch ist (async)
                  setState(praefix + "DeadDeviceCount", DeadDeviceCount, true);
                  MakeTable();
              };
          };
      }
      
      function Ticker() {
          CheckDeadBatt(); //Auf nicht mehr aktualisierende Geräte seit Zeit x (Einstellung) prüfen
          setInterval(function () { // Wenn 
              CheckDeadBatt();
          }, 60000);
      }
      
      
      function CheckNextLowBatt() { //Ermittelt die Batterie mit der geringsten Spannung, ignoriert Batterien welche das Limit bereits unterschritten haben da diese bereits in der LastMessage gemeldet werden
          if (logging) log("Reaching CheckNextLowBatt()");
      
          let LowestBattProz = 100; //Mit 100% initialisieren
          let LowestBattIndex = 0;
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen
              if (Sensor[x].state != "warn" && Sensor[x].state != "dead") Sensor[x].state = "ok";
              if (Sensor[x].value > Sensor[x].batteryMinLimit) { // Nur Sensoren berücksichtigen die das min Limit noch nicht unterschritten haben
                  if (Sensor[x].liveProz <= LowestBattProz) { //Wenn Sensorwert kleiner LowestBattProz, LowestBattVal auf neuen Wert setzen um das Gerät mit den wenigsten Prozent zu ermitteln
                      LowestBattProz = Sensor[x].liveProz;
                      LowestBattIndex = x;
                  };
              };
          };
      
          NextExpectedLowBatt = "Aktuell niedrigster Batteriestand (" + Sensor[LowestBattIndex].value.toFixed(2) + "V): " + GetRoom(LowestBattIndex) + " bei Gerät " + getObject(GetParentId(Sensor[LowestBattIndex].id), "common").common.name;
          setState(praefix + "NextExpectedLowBatt", NextExpectedLowBatt, true);
          Sensor[LowestBattIndex].state = "info";
          if (logging) log(NextExpectedLowBatt);
      }
      
      function CheckAllBatterysOk() {
          if (logging) log("Reaching CheckAllBatterysOk");
          AllBatterysOk = true;
          EmptyBatCount = 0;
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen
              if (Sensor[x].value <= Sensor[x].batteryMinLimit) { // Nur Sensoren berücksichtigen die das min Limit unterschritten haben
                  AllBatterysOk = false;
                  EmptyBatCount++; //Alle Sensoren zählen welche das Batt min Limit unterschritten haben
              };
          };
      
          if (DeadDeviceCount > 0) AllBatterysOk = false;
      
          setState(praefix + "EmptyBatCount", EmptyBatCount, true);
          setState(praefix + "AllBatterysOk", AllBatterysOk, true);
      }
      
      
      let OldTempMsg = "";
      function CheckForAlerts() {
          if (logging) log("Reaching CheckLastMessage, EmptyBatCount=" + EmptyBatCount + " DeadDeviceCount=" + DeadDeviceCount);
          let TempMsg = "";
      
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchgehen
              if (Sensor[x].message != "" && NotifyWarnDevices) { //Wenn msg vorhanden und Warnungen aktiv
                  if (TempMsg == "") {
                      TempMsg = Sensor[x].message;
                  } else {
                      TempMsg += LastMessageSeparator + Sensor[x].message;
                  };
              };
      
              if (Sensor[x].isDead && NotifyDeadDevices) { //Wenn msg vorhanden und Dead Warnungen aktiv
                  if (TempMsg == "") {
                      TempMsg = "Ausfall oder disconnect im " + GetRoom(x) + " bei Gerät " + getObject(GetParentId(Sensor[x].id)).common.name;
                  } else {
                      TempMsg += LastMessageSeparator + "Ausfall oder disconnect im " + GetRoom(x) + " bei Gerät " + getObject(GetParentId(Sensor[x].id)).common.name;
                  };
              };
          };
      
          if (TempMsg == "") {
              setState(praefix + "LastMessage", "", true); //Meldung in Datenpunkt LastMessage löschen
              if (logging) log("Alle Batterien ok, Lastmessage gelöscht");
          } else if (OldTempMsg != TempMsg) {
              setState(praefix + "LastMessage", TempMsg, true); //Meldung in Datenpunkt LastMessage schreiben
              Meldung(TempMsg);
          };
          OldTempMsg = TempMsg;
      }
      
      
      function CheckBatterys(x) { // Prüfung eines einzelnen Batteriestandes wenn getriggert
          if (logging) log("Reaching CheckBatterys(" + x + ") Val=" + Sensor[x].value + " Limit=" + Sensor[x].batteryMinLimit);
          if (Sensor[x].value <= Sensor[x].batteryMinLimit) { //Wenn Min. Wert unterschritten
              Sensor[x].message = "Batteriestand (" + parseInt(Sensor[x].value * 100) / 100 + " V) unter Limit (" + Sensor[x].batteryMinLimit + " V) im " + GetRoom(x) + " bei Gerät " + getObject(GetParentId(Sensor[x].id)).common.name;
              Sensor[x].state = "warn";
          }
          else {
              Sensor[x].state = "ok";
              Sensor[x].message = "";
          };
          CheckAllBatterysOk();
          CheckNextLowBatt();
          CheckDeadBatt();
          CheckForAlerts();
          MakeTable();
      }
      
      function CheckAllBatterys() { // Prüfung aller Batteriestände bei Skriptstart
          if (logging) log("Reaching CheckAllBatterys() found " + (Sensor.length) + " Devices");
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen
              if (Sensor[x].state == "dead") {
                  if (logging) log("Sensor[" + x + "] = ist ausgefallen oder disconnected");
                  Sensor[x].isDead = true;
              }
              else if (Sensor[x].value <= Sensor[x].batteryMinLimit) { //Wenn Min. Wert unterschritten
                  if (logging) log("SensorVal[" + x + "] = " + Sensor[x].value + "V, unterschreitet MinLimit von " + Sensor[x].batteryMinLimit + " V");
                  Sensor[x].message = "Batteriestand (" + parseInt(Sensor[x].value * 100) / 100 + " V) unter Limit (" + Sensor[x].batteryMinLimit + " V) im " + GetRoom(x) + " bei Gerät " + getObject(GetParentId(Sensor[x].id)).common.name;
                  Sensor[x].state = "warn";
              }
              else {
                  if (Sensor[x].state != "info" && Sensor[x].state != "dead") {
                      Sensor[x].state = "ok";
                      Sensor[x].isDead = false;
                      Sensor[x].message = "";
                  }
              };
          };
          CheckForAlerts();
      }
      
      function GetRoom(x) {  // Raum eines Gerätes ermitteln
          let room = getObject(Sensor[x].id, 'rooms').enumNames[0];
          if (room == undefined) room = "Nicht zugewiesen";
          if (typeof room == 'object') room = room.de;
          room = room.replace(/_/g, " "); //Unterstriche durch Leerzeichen ersetzen
          return room;
      }
      
      function GetUnit(x) {
          let unit = getObject(Sensor[x].id, 'common').common.unit
          return unit;
      }
      
      function GetParentId(Id) {
          let parentDevicelId;
          if (Id.indexOf("deconz.") > -1 || Id.indexOf("hm-rpc.") > -1 || Id.indexOf("shelly.") > -1) { //Wenn deconz, hm-rpc oder shelly dann zwei Ebenen zurück
              parentDevicelId = Id.split(".").slice(0, -2).join(".");// Id an den Punkten in Array schreiben (split), die 2 letzten Elemente von hinten entfernen (slice) und den Rest wieder zu String zusammensetzen
          }
          else if (Id.indexOf("hmip.") > -1) { //Wenn HMIP dann drei Ebenen zurück
              parentDevicelId = Id.split(".").slice(0, -3).join(".");// Id an den Punkten in Array schreiben (split), die 3 letzten Elemente von hinten entfernen (slice) und den Rest wieder zu String zusammensetzen
          }
          else { //Wenn kein deconz, kein HM und kein shelly Adapter, eine Ebene zurück
              parentDevicelId = Id.split(".").slice(0, -1).join(".");// Id an den Punkten in Array schreiben (split), das letzte Element von hinten entfernen (slice) und den Rest wieder zu String zusammensetzen
          };
          if (DeconzNameFromDP && Id.indexOf("deconz.") > -1) parentDevicelId = Id;
          //if (logging) log("Id= " + Id + " ParentDeviceId= " + parentDevicelId)
          return parentDevicelId;
      }
      
      function MakeTable() {
          if (logging) log("Reaching MakeTable");
          let BgColor = "";
          let style0 = "style='border: 1px solid black; padding-left: 5px; padding-right: 5px; font-size:0.8em; font-weight: normal; text-align: left; color:" + FontColor + "; background-color:"
          let style1 = "style='width: 40px; border: 1px solid black; padding-left: 5px; padding-right: 5px; font-size:0.8em; font-weight: normal; text-align: right; color:" + FontColor + "; background-color:"
          let headstyle0 = "style='border: 1px solid black; padding-left: 5px; padding-right: 5px; height: 30px; font-size:1.0em; font-weight: bold; text-align: left; color:" + HeadFontColor + "; background-color:"
          let headstyle1 = "style='width: 40px; border: 1px solid black; padding-left: 5px; padding-right: 5px; height: 30px; font-size:1.0em; font-weight: bold; text-align: center; color:" + HeadFontColor + "; background-color:"
      
          let MyTableHead = "<table style='width:100%; border: 1px solid black; border-collapse: collapse;'><tr>";
          let MyTable;
      
          if (TblShowLfdCol) {
              MyTableHead += "<th " + headstyle0 + HeadBgColor + "'>lfd</th>";
          };
          if (TblShowDeviceIDCol) {
              MyTableHead += "<th " + headstyle0 + HeadBgColor + "'>Sensor ID</th>";
          };
          if (TblShowDeviceNameCol) {
              MyTableHead += "<th " + headstyle0 + HeadBgColor + "'>Sensor Name</th>";
          };
          if (TblShowRoomCol) {
              MyTableHead += "<th " + headstyle0 + HeadBgColor + "'>Raum</th>";
          };
          if (TblShowUmaxCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>U<br>Nenn</th>";
          };
          if (TblShowUistCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>U<br>Ist</th>";
          };
          if (TblShowUlimitCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>U<br>Limit</th>";
          };
          if (TblShowProzbatCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>%bat</th>";
          };
          if (TblShowProzliveCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>%live</th>";
          };
          if (TblShowStatusCol) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>Status</th>";
          };
          if (TblShowHasDeadCheck) {
              MyTableHead += "<th " + headstyle1 + HeadBgColor + "'>DC</th>";
          };
          MyTableHead += "</tr>";
          MyTable = MyTableHead + "<tr>";
      
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen 
              switch (Sensor[x].state) {
                  case "ok":
                      BgColor = TblOkBgColor;
                      break;
                  case "info":
                      BgColor = TblInfoBgColor;
                      break;
                  case "warn":
                      BgColor = TblWarnBgColor;
                      break;
                  case "dead":
                      BgColor = TblDeadBgColor;
                      break;
                  default:
              };
      
              MyTable += "<tr>";
              if (TblShowLfdCol) {
                  MyTable += "<td " + style0 + BgColor + "'>" + (x + 1) + "</td>";
              };
              if (TblShowDeviceIDCol) {
                  MyTable += "<td " + style0 + BgColor + "'>" + GetParentId(Sensor[x].id) + "</td>";
              };
              if (TblShowDeviceNameCol) {
                  MyTable += "<td " + style0 + BgColor + "'>" + getObject(GetParentId(Sensor[x].id), "common").common.name + "</td>";
              };
              if (TblShowRoomCol) {
                  MyTable += "<td " + style0 + BgColor + "'>" + GetRoom(x) + "</td>";
              };
              if (TblShowUmaxCol) {
                  MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].uMax.toFixed(1) + "V</td>";
              };
              if (TblShowUistCol) {
                  MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].value.toFixed(2) + "V</td>";
              };
              if (TblShowUlimitCol) {
                  MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].batteryMinLimit.toFixed(2) + "V</td>";
              };
              if (TblShowProzbatCol) {
                  if (typeof (Sensor[x].uProz) == "number") {
                      MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].uProz.toFixed(1) + "%</td>";
                  }
                  else {
                      MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].uProz + "</td>";
                  };
              };
              if (TblShowProzliveCol) {
                  if (typeof (Sensor[x].liveProz) == "number") {
                      MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].liveProz.toFixed(1) + "%</td>";
                  }
                  else {
                      MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].liveProz + "</td>";
                  };
              };
              if (TblShowStatusCol) {
                  MyTable += "<td " + style1 + BgColor + "'>" + Sensor[x].state + "</td>";
              };
              if (TblShowHasDeadCheck) {
                  MyTable += "<td " + style1 + BgColor + "'>" + (Sensor[x].hasDeadCheck ? 'x' : '-') + "</td>";
              };
              MyTable = MyTable + "</tr>";
          };
      
          MyTable += "</table>";
          setState(praefix + "OverviewTable", MyTable, true);
      }
      
      //Trigger für Sensoren erzeugen
      function CreateTrigger() {
          for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen
              on(Sensor[x].id, function (dp) { //Trigger in Schleife erstellen
                  let TempVal = dp.state.val;
                  //  let TempUnit = GetUnit(x);
                  // let TempLiveWindow = Sensor[x].uMax - Sensor[x].batteryMinLimit;
                  if (typeof (TempVal == "string")) { //Falls MinLimit Wert String ist zu float wandeln
                      //log("Value is String, trying to convert");
                      if (!isNaN(parseFloat(TempVal))) { //Wenn konvertierung kein NaN ergibt
                          if (logging) log("Value conversion from String to number - success");
                          TempVal = parseFloat(TempVal); //Konvertieren
                      };
                  };
                  MainCalc(TempVal, x);
                  CheckBatterys(x); //Prüfen
              });
          };
      
          for (let x = 0; x < WelcheFunktionVerwenden.length; x++) { //Alle Batteriefunktionen durchlaufen
              on(praefix + BatteryMinLimitDp[x], function (dp) { //Trigger erstellen und auslösen wenn min Limit geändert wurde. Dann erneute Komplettprüfung aller Batteriestände
                  if (logging) log("Reaching Trigger for :" + praefix + BatteryMinLimitDp[x])
                  if (typeof (dp.state.val) != "number") {
                      log("MinLimit Value not a Number, rather " + typeof (dp.state.val) + ", converting to number", "warn");
                      setState(praefix + BatteryMinLimitDp[x], parseFloat(dp.state.val), true)
                  };
                  main(); //Neuzuweisung des geänderten Limits an alle Geräte
              });
          };
      
          onStop(function () { //Bei Scriptende alle Timer löschen
              if (typeof TickerObj == "object") clearInterval(TickerObj);
          }, 100);
      }
      
      P 1 Reply Last reply Reply Quote 0
      • P
        Pittini Developer @Dragon last edited by

        @dragon sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

        Ich glaube an dem hier liegt es... Habe ich einen Fehler gemacht?

        Ich tippe mal darauf, dass irgendwo noch keine Spannung drinsteht, sollte sich also von selber erledigen. Wenn nicht, nochmal melden, mit Screenshot der Objektliste wo ich die Zuweisungen der Funktion seh.

        D 3 Replies Last reply Reply Quote 0
        • D
          Dragon @Pittini last edited by

          @pittini Welche Funktion nutze ich denn bei Geräten die einen BatteryLow Datenpunkt haben? Oder geht bei dem Skript noch nicht?

          P 1 Reply Last reply Reply Quote 0
          • D
            Dragon @Pittini last edited by

            @pittini Nun sind nur noch Geräte mit einem Zahlenwert in der Liste

            
            javascript.0
            2021-10-17 11:16:13.928	error	at processImmediate (internal/timers.js:463:21)
            
            javascript.0
            2021-10-17 11:16:13.927	error	at Immediate._onImmediate (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1988:38)
            
            javascript.0
            2021-10-17 11:16:13.927	error	at Object.<anonymous> (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:110:13)
            
            javascript.0
            2021-10-17 11:16:13.927	error	at main (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:252:5)
            
            javascript.0
            2021-10-17 11:16:13.926	error	at MakeTable (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:587:75)
            
            javascript.0
            2021-10-17 11:16:13.916	error	Error in callback: TypeError: Cannot read property 'toFixed' of undefined
            

            Screenshot 2021-10-17 11.17.53.png

            Das ist nur ein Beispiel aber um sie alle zu zeigen sind es viel zu viele... Ist auch erst seit dem Update auf die 1.8.2

            P 1 Reply Last reply Reply Quote 0
            • P
              Pittini Developer @Dragon last edited by

              @dragon sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

              @pittini Welche Funktion nutze ich denn bei Geräten die einen BatteryLow Datenpunkt haben? Oder geht bei dem Skript noch nicht?

              Anleitung .1: Dies gilt auch für Geräte welche nur Lowbat oder % ausgeben, auch diese haben ja irgendeine, klar definierte, Batteriespannung.

              1 Reply Last reply Reply Quote 0
              • P
                Pittini Developer @Dragon last edited by

                @dragon sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

                Nun sind nur noch Geräte mit einem Zahlenwert in der Liste

                Muß nich nur Zahlenwert sein, darf auch % Wert sein oder Boolscher Wert (true/false) bei lowbat Datenpunkten.

                Die Meldung:

                2021-10-17 11:16:13.926	error	at MakeTable (script.js.common.Sicherheit.Sensoren.Andere.Batteriestandsüberwachung:587:75)
                

                weist ja auf Zeile 587 und genau da wird die IstSpannung ausgegeben, welche offenbar bei irgendeinem DAtenpunkt immer noch leer ist, grad nach neuinstallationen ist das typisch wenn z.B. ein Sensor nich richtig gepairt ist und keine Daten ankommen etc. Bitte kontrollier nochmal jeden Datenpunkt dem Du die Funktion BatterieSpannung_xx gegeben hast, ob da auch was drinsteht. Hilft das nicht, kannste mal das logging im Skript aktivieren und hier posten, evtl. seh ich dann mehr.

                1 Reply Last reply Reply Quote 0
                • Dominik F.
                  Dominik F. @Pittini last edited by Dominik F.

                  @pittini sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

                  @dominik-f sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

                  Wäre es vielleicht möglich, dass nur beim erstmaligen unterschreiten des Wertes eine Meldung verschickt wird?

                  Wird ja so gemacht, nur wenn der Wert danach wieder hochgeht, und dann wieder runter isses ja wieder ein erstmaliges Unterschreiten.

                  nicht ganz, der Wert hat sich ja die ganze Zeit unter dem Limit von 2,2V bewegt, das Limit war also die ganze Zeit unterschritten. Oder hab ich da einen Denkfehler?

                  P 1 Reply Last reply Reply Quote 0
                  • P
                    Pittini Developer @Dominik F. last edited by

                    @dominik-f
                    Versteh was Du meinst, das Problem ist, das ich den alten Wert ja nicht mehr hab. D.h. ich müßte den iwo zwischenspeichern und dann mit dem neuen Wert vergleichen. Aktuell wird gegen das Limit geprüft, daher das Verhalten. Relevant ist Zeile 439, evtl. magst ja selber bisserl "spielen". Ansonsten, mach bitte nen Git Issue, damit ichs nicht vergess.

                    if (Sensor[x].value <= Sensor[x].batteryMinLimit) { //Wenn Min. Wert unterschritten
                    
                    Dominik F. 1 Reply Last reply Reply Quote 0
                    • D
                      Dragon @Pittini last edited by

                      @pittini Hat einiges an Nerven gekostet, aber es gab tatsächlich Probleme mit einem Zigbee Gerät. Das war der Auslöser. Vielen Dank!

                      1 Reply Last reply Reply Quote 0
                      • Dominik F.
                        Dominik F. @Pittini last edited by

                        @pittini
                        Ich danke dir, habe ein Issue erstellt.

                        1 Reply Last reply Reply Quote 0
                        • K
                          Kosta last edited by

                          Hallo! Vielen Dank für die tolle Visualisierung. Alle meine Geräte werden zurzeit rot angezeigt obwohl die Prozentanteil für die Batterie noch über 80% liegt (teilweise 100%). Was mache ich falsch? Vielen Dank im Voraus!

                          K P 2 Replies Last reply Reply Quote 0
                          • K
                            Kosta @Kosta last edited by

                            IMG_3237 2.jpeg

                            1 Reply Last reply Reply Quote 0
                            • P
                              Pittini Developer @Kosta last edited by

                              @kgb sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

                              Vielen Dank für die tolle Visualisierung. Alle meine Geräte werden zurzeit rot angezeigt obwohl die Prozentanteil für die Batterie noch über 80% liegt (teilweise 100%). Was mache ich falsch? Vielen Dank im Voraus!

                              Der shelly ganz unten im Screenshot hat ne undefined Spannung, korrigier das mal, kann sein dass da das Problem liegt.

                              K 1 Reply Last reply Reply Quote 0
                              • K
                                Kosta @Pittini last edited by

                                @pittini ich habe das Gerät aus der Aufzählung gelöscht, hat aber leider nicht geholfen.
                                Was ich aber gemerkt habe, die Auswertung findet nur in der erste Zeile statt. Ich habe mehrer Geräte gelöscht und wieder hinzugefügt, aber jedes Mal ist das so, dass ab der 2 Zeile alle Geräte rot sind.

                                1 Reply Last reply Reply Quote 0
                                • K
                                  Kosta last edited by

                                  @pittini P.S.: ich habe auch ehrlich gesagt nicht ganz verstanden wie es mit der Messung von Volt funktioniert.. kann man diese Funktion ausschalten, damit einfach nur auf Prozente der Batterieladung geschaut wird? Vielleicht, liegt das Problem auch da..

                                  P 1 Reply Last reply Reply Quote 0
                                  • P
                                    Pittini Developer @Kosta last edited by

                                    @kgb sagte in [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe:

                                    @pittini P.S.: ich habe auch ehrlich gesagt nicht ganz verstanden wie es mit der Messung von Volt funktioniert.. kann man diese Funktion ausschalten, damit einfach nur auf Prozente der Batterieladung geschaut wird? Vielleicht, liegt das Problem auch da..

                                    Prozente sind ja nur ne andere Angabe der Spannung, also nein, kann man nicht ausschalten, braucht man nicht ausschalten. Zeig doch mal nen Screenshot aus der Objektliste wo ich seh wie Du die Batteriespannungsfunktion setzt und wo. Und falls Du Änderungen an den Skriptsettings gemacht hast, bitte auch davon nen Auszug.
                                    Wenn Du Geräte aus den Aufzählungen dazunimmst oder raus löschst, mußte den JS Controller danach neustarten damit der das neu einliest. Haste das gemacht?

                                    K 2 Replies Last reply Reply Quote 0
                                    • K
                                      Kosta @Pittini last edited by

                                      @pittini hier sind ein paar Screenshots. Danke für deine Unterstützung!!!IMG_3270.jpeg ![IMG_3269.jpeg](/assets/uploads/files/1636999083IMG_3267.jpeg 169-img_3269-resized.jpeg)

                                      P 1 Reply Last reply Reply Quote 0
                                      • K
                                        Kosta @Pittini last edited by

                                        @pittini IMG_3269.jpeg

                                        C 1 Reply Last reply Reply Quote 0
                                        • C
                                          Chrunchy @Kosta last edited by

                                          @kgb gemäß Script gibt es eine Variable "FunktionBaseName" (vorbelegt meine ich mit "BatterieSpannung_") diese muss dann für die jeweiligen Batteriespannungen verwendet werden.

                                          Beispiele:
                                          Geräte mit 3V Batteriespannung müssen in die Funktion "BatterieSpannung_30"
                                          Geräte mit 1,5V Batteriespannung müssen in die Funktion "BatterieSpannung_15"
                                          usw.

                                          Aus dem Zahlenwert wird ggf. die Sollspannung berechnet. Bei dir sind es 1V, was bei 50% dann eben nur 0,5V Ist-Spannung ergibt, also quasi 0.

                                          1 Reply Last reply Reply Quote 1
                                          • P
                                            Pittini Developer @Kosta last edited by

                                            @kgb Also zum einen ist der Raum falsch zugeordnet, das ganze Gerät ist in diesem Raum und nicht nur ein Datenpunkt. Zum anderen, wenn Du Bat_10 verwendest, mußte das auch in den Einstellungen im Skript anpassen. Wobei ich jetzt weder ein Gerät kenne, noch ne Batterie mit 1V. Siehe auch was @Chrunchy völlig korrekt anmerkte.

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

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            954
                                            Online

                                            31.7k
                                            Users

                                            79.9k
                                            Topics

                                            1.3m
                                            Posts

                                            javascript monitoring template
                                            81
                                            581
                                            110295
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo