Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. [Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.9k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.3k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    3.4k

[Vorlage] Generische Batteriestandsüberwachung + Vis-ausgabe

Geplant Angeheftet Gesperrt Verschoben Skripten / Logik
javascripttemplatemonitoring
581 Beiträge 81 Kommentatoren 136.8k Aufrufe 84 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • Dominik F.D Dominik F.

    @pittini

    ganz genau. Manchmal ist dann für ein paar Stunden ruhe, dann geht es ca 1 Stunde alle 5 min los, dann ist wieder n bissel ruhe.

    P Offline
    P Offline
    Pittini
    Developer
    schrieb am zuletzt editiert von
    #446

    @dominik-f Schau mal bitte ob Du das loggen kannst, iwas muß das Verhalten ja triggern.

    Dominik F.D 1 Antwort Letzte Antwort
    0
    • P Pittini

      @dominik-f Schau mal bitte ob Du das loggen kannst, iwas muß das Verhalten ja triggern.

      Dominik F.D Offline
      Dominik F.D Offline
      Dominik F.
      schrieb am zuletzt editiert von
      #447

      @pittini

      Vielleicht hilft das ja weiter. Es sieht danach aus, als ob der Batteriestand sich immer verändert und dann jedes mal ne Nachricht geschickt wird.

      
      javascript.0
      2021-10-11 07:32:16.916	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 07:26:31.868	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 07:24:21.870	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 05:51:47.457	info	script.js.common.Astrozeiten: nächste kommende Tagezeit: Sonnenaufgang
      
      javascript.0
      2021-10-11 05:51:47.455	info	script.js.common.Astrozeiten: neue Tagezeit: Morgendämmerung
      
      javascript.0
      2021-10-11 03:01:00.023	info	script.js.common.Gast: +++ Wlan Gast QR-Code neu erstellt +++
      
      javascript.0
      2021-10-11 00:56:12.357	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 00:54:01.357	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 00:39:05.096	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 00:36:17.346	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 00:11:05.637	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      javascript.0
      2021-10-11 00:06:22.118	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
      
      
      P 1 Antwort Letzte Antwort
      0
      • Dominik F.D Dominik F.

        @pittini

        Vielleicht hilft das ja weiter. Es sieht danach aus, als ob der Batteriestand sich immer verändert und dann jedes mal ne Nachricht geschickt wird.

        
        javascript.0
        2021-10-11 07:32:16.916	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 07:26:31.868	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 07:24:21.870	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 05:51:47.457	info	script.js.common.Astrozeiten: nächste kommende Tagezeit: Sonnenaufgang
        
        javascript.0
        2021-10-11 05:51:47.455	info	script.js.common.Astrozeiten: neue Tagezeit: Morgendämmerung
        
        javascript.0
        2021-10-11 03:01:00.023	info	script.js.common.Gast: +++ Wlan Gast QR-Code neu erstellt +++
        
        javascript.0
        2021-10-11 00:56:12.357	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 00:54:01.357	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 00:39:05.096	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 00:36:17.346	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 00:11:05.637	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2.1 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        javascript.0
        2021-10-11 00:06:22.118	info	script.js.common.Batterie_Ueberwachung: Reaching Meldung(), msg=Batteriestand (2 V) unter Limit (2.2 V) im Wohnzimmer bei Gerät EG_Kaminzimmer_Rechts_Heizung
        
        
        P Offline
        P Offline
        Pittini
        Developer
        schrieb am zuletzt editiert von
        #448

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

        Es sieht danach aus, als ob der Batteriestand sich immer verändert und dann jedes mal ne Nachricht geschickt wird.

        Hmm, dann arbeitet das Skript aber wie geplant. Bei Änderung Meldung schicken. Das Problem is das rumgehüpfe der Werte, daran kann ich aber nix ändern.

        Dominik F.D 1 Antwort Letzte Antwort
        0
        • P Pittini

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

          Es sieht danach aus, als ob der Batteriestand sich immer verändert und dann jedes mal ne Nachricht geschickt wird.

          Hmm, dann arbeitet das Skript aber wie geplant. Bei Änderung Meldung schicken. Das Problem is das rumgehüpfe der Werte, daran kann ich aber nix ändern.

          Dominik F.D Offline
          Dominik F.D Offline
          Dominik F.
          schrieb am zuletzt editiert von
          #449

          @pittini

          Wäre es vielleicht möglich, dass nur beim erstmaligen unterschreiten des Wertes eine Meldung verschickt wird? Für Leute, die mehr Erinnerungen brauchen könnte man dann ein Intervall einfügen wo eingestellt werden kann, in welchem Intervall eine Meldung dann verschickt wird solange der Wert unterschritten bleibt z.B. alle 24h.

          P 1 Antwort Letzte Antwort
          0
          • Dominik F.D Dominik F.

            @pittini

            Wäre es vielleicht möglich, dass nur beim erstmaligen unterschreiten des Wertes eine Meldung verschickt wird? Für Leute, die mehr Erinnerungen brauchen könnte man dann ein Intervall einfügen wo eingestellt werden kann, in welchem Intervall eine Meldung dann verschickt wird solange der Wert unterschritten bleibt z.B. alle 24h.

            P Offline
            P Offline
            Pittini
            Developer
            schrieb am zuletzt editiert von
            #450

            @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.

            Dominik F.D 1 Antwort Letzte Antwort
            0
            • D Offline
              D Offline
              Dragon
              schrieb am zuletzt editiert von Dragon
              #451

              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 Antwort Letzte Antwort
              0
              • D 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 Offline
                P Offline
                Pittini
                Developer
                schrieb am zuletzt editiert von
                #452

                @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 Antworten Letzte Antwort
                0
                • P Pittini

                  @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 Offline
                  D Offline
                  Dragon
                  schrieb am zuletzt editiert von
                  #453

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

                  P 1 Antwort Letzte Antwort
                  0
                  • P Pittini

                    @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 Offline
                    D Offline
                    Dragon
                    schrieb am zuletzt editiert von
                    #454

                    @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 Antwort Letzte Antwort
                    0
                    • D Dragon

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

                      P Offline
                      P Offline
                      Pittini
                      Developer
                      schrieb am zuletzt editiert von
                      #455

                      @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 Antwort Letzte Antwort
                      0
                      • D Dragon

                        @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 Offline
                        P Offline
                        Pittini
                        Developer
                        schrieb am zuletzt editiert von
                        #456

                        @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 Antwort Letzte Antwort
                        0
                        • P Pittini

                          @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.

                          Dominik F.D Offline
                          Dominik F.D Offline
                          Dominik F.
                          schrieb am zuletzt editiert von Dominik F.
                          #457

                          @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 Antwort Letzte Antwort
                          0
                          • Dominik F.D 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 Offline
                            P Offline
                            Pittini
                            Developer
                            schrieb am zuletzt editiert von
                            #458

                            @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.D 1 Antwort Letzte Antwort
                            0
                            • P Pittini

                              @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 Offline
                              D Offline
                              Dragon
                              schrieb am zuletzt editiert von
                              #459

                              @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 Antwort Letzte Antwort
                              0
                              • P Pittini

                                @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.D Offline
                                Dominik F.D Offline
                                Dominik F.
                                schrieb am zuletzt editiert von
                                #460

                                @pittini
                                Ich danke dir, habe ein Issue erstellt.

                                1 Antwort Letzte Antwort
                                0
                                • K Offline
                                  K Offline
                                  Kosta
                                  schrieb am zuletzt editiert von
                                  #461

                                  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 Antworten Letzte Antwort
                                  0
                                  • K Kosta

                                    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 Offline
                                    K Offline
                                    Kosta
                                    schrieb am zuletzt editiert von
                                    #462

                                    IMG_3237 2.jpeg

                                    1 Antwort Letzte Antwort
                                    0
                                    • K Kosta

                                      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!

                                      P Offline
                                      P Offline
                                      Pittini
                                      Developer
                                      schrieb am zuletzt editiert von
                                      #463

                                      @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 Antwort Letzte Antwort
                                      0
                                      • P Pittini

                                        @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 Offline
                                        K Offline
                                        Kosta
                                        schrieb am zuletzt editiert von
                                        #464

                                        @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 Antwort Letzte Antwort
                                        0
                                        • K Offline
                                          K Offline
                                          Kosta
                                          schrieb am zuletzt editiert von
                                          #465

                                          @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 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          373

                                          Online

                                          32.5k

                                          Benutzer

                                          81.6k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe