Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. [erledigt]Skript zum Einsammeln von Batteriestatus von ...

    NEWS

    • Amazon Alexa - ioBroker Skill läuft aus ?

    • Monatsrückblick – September 2025

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

    [erledigt]Skript zum Einsammeln von Batteriestatus von ...

    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      mguenther @paul53 last edited by

      @paul53
      nicht das ich wüsste - die Geräte werden in Zigbee gepaired und bekommen diese Object ID Zuweisung. Ich wollte es mir einfach machen und quasi nen Platzhalter verwenden. Klappt aber irgendwie nicht

      1 Reply Last reply Reply Quote 0
      • paul53
        paul53 @mguenther last edited by

        @mguenther sagte: Zu denen ich bis jetzt etwas gemacht habe, ja - da gibts auch nen Alias.

        Dann verwende den Alias, wenn die ID-Struktur einheitlich ist.

        M 1 Reply Last reply Reply Quote 0
        • M
          mguenther @paul53 last edited by

          @paul53
          ja, aber dann habe ich nicht alle zigbee geräte. ich wollte je eigentlich gerne alle zigbee geräte auswerten.

          Homoran 1 Reply Last reply Reply Quote 0
          • Homoran
            Homoran Global Moderator Administrators @mguenther last edited by

            @mguenther sagte in Skript zum Einsammeln von Batteriestatus von Zigbeegeräten?:

            ich wollte je eigentlich gerne alle zigbee geräte auswerten.

            und zu denen gibt es keine alias?

            M 1 Reply Last reply Reply Quote 0
            • M
              mguenther @Homoran last edited by

              @homoran
              hi homoran,
              nein, nicht zu allen. ich habe so etwas:

              4173b22d-2136-40cf-8753-f1fffe12dff9-grafik.png

              unter Sensordaten finde ich auch für einige Zigbeegeräte den "Batteriestatus"

              paul53 1 Reply Last reply Reply Quote 0
              • paul53
                paul53 @mguenther last edited by

                @mguenther sagte: nein, nicht zu allen.

                Das ist schlecht.
                Du zeigst uns nie die Namen. Ist die Bildschirmauflösung so niedrig?

                Teste mal, was damit im Log erscheint:

                const ids = $('zigbee.0.*.battery').toArray();
                
                function batterien() {
                    for(let id of ids) {
                        const val = getState(id).val;
                        id = id.substring(0, id.lastIndexOf('.')); // Geräte-ID
                        log(getObject(id).common.name + ': ' + val);        
                    } 
                }
                
                schedule('0 18 * * *', batterien); 
                batterien();
                
                M 1 Reply Last reply Reply Quote 0
                • M
                  mguenther @paul53 last edited by

                  @paul53
                  dann habe ich noch nicht verstanden, was du mit "Namen" meinst. Anbei der Log-Auszug:

                  javascript.0
                  	2025-09-30 14:33:24.904	info	script.js.System.TEST2Batterie: registered 0 subscriptions, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
                  javascript.0
                  	2025-09-30 14:33:24.903	info	script.js.System.TEST2Batterie: Taster_Sonnenrollo: 16
                  javascript.0
                  	2025-09-30 14:33:24.903	info	script.js.System.TEST2Batterie: Zimmer1_Fernsehtaster_Paulina: 60
                  javascript.0
                  	2025-09-30 14:33:24.902	info	script.js.System.TEST2Batterie: Zimmer1_Fernsehtaster_Marcus: 60
                  javascript.0
                  	2025-09-30 14:33:24.902	info	script.js.System.TEST2Batterie: Garagenwand_Heizung: 83
                  javascript.0
                  	2025-09-30 14:33:24.901	info	script.js.System.TEST2Batterie: Garagenwand_Tor_Sued: 70
                  javascript.0
                  	2025-09-30 14:33:24.901	info	script.js.System.TEST2Batterie: Garagenwand_Raum_Sued: 100
                  javascript.0
                  	2025-09-30 14:33:24.900	info	script.js.System.TEST2Batterie: Garagenwand_Briefkasten: 0
                  javascript.0
                  	2025-09-30 14:33:24.899	info	script.js.System.TEST2Batterie: Tuerklingel: 0
                  javascript.0
                  	2025-09-30 14:33:24.897	info	script.js.System.TEST2Batterie: Technikraum: 0
                  javascript.0
                  	2025-09-30 14:33:24.897	info	script.js.System.TEST2Batterie: Garage: 100
                  javascript.0
                  	2025-09-30 14:33:24.896	info	script.js.System.TEST2Batterie: Server: 37
                  javascript.0
                  	2025-09-30 14:33:24.896	info	script.js.System.TEST2Batterie: Arbeitszimmer: 0
                  javascript.0
                  	2025-09-30 14:33:24.893	info	script.js.System.TEST2Batterie: Bad_klein: 97
                  javascript.0
                  	2025-09-30 14:33:24.893	info	script.js.System.TEST2Batterie: Bad_klein: 0
                  javascript.0
                  	2025-09-30 14:33:24.892	info	script.js.System.TEST2Batterie: WC: 83
                  javascript.0
                  	2025-09-30 14:33:24.891	info	script.js.System.TEST2Batterie: Garderobe: 57
                  javascript.0
                  	2025-09-30 14:33:24.891	info	script.js.System.TEST2Batterie: Bad_gross: 23
                  javascript.0
                  	2025-09-30 14:33:24.890	info	script.js.System.TEST2Batterie: Aussen: 43
                  javascript.0
                  	2025-09-30 14:33:24.890	info	script.js.System.TEST2Batterie: Zimmer3: 30
                  javascript.0
                  	2025-09-30 14:33:24.889	info	script.js.System.TEST2Batterie: EG: 17
                  javascript.0
                  	2025-09-30 14:33:24.889	info	script.js.System.TEST2Batterie: Zimmer2: 43
                  javascript.0
                  	2025-09-30 14:33:24.889	info	script.js.System.TEST2Batterie: Bad_gross: 3
                  javascript.0
                  	2025-09-30 14:33:24.888	info	script.js.System.TEST2Batterie: Zimmer1: 0
                  javascript.0
                  	2025-09-30 14:33:24.888	info	script.js.System.TEST2Batterie: Zimmer3: 100
                  javascript.0
                  	2025-09-30 14:33:24.888	info	script.js.System.TEST2Batterie: Zimmer2: 100
                  javascript.0
                  	2025-09-30 14:33:24.887	info	script.js.System.TEST2Batterie: Zimmer1_rechts: 90
                  javascript.0
                  	2025-09-30 14:33:24.887	info	script.js.System.TEST2Batterie: Zimmer1_links: 100
                  javascript.0
                  	2025-09-30 14:33:24.802	info	Start JavaScript script.js.System.TEST2Batterie (Javascript/js)
                  
                  paul53 1 Reply Last reply Reply Quote 0
                  • paul53
                    paul53 @mguenther last edited by

                    @mguenther sagte: Anbei der Log-Auszug:

                    Der sieht gut aus. Also haben die Zigbee-Geräte sinnvolle Namen. Manche Namen sind allerdings doppelt vorhanden.
                    Die Namen kann man auch im Tab "Objekte" zeigen:

                    Namen_Tab_Objekte.JPG

                    M 1 Reply Last reply Reply Quote 1
                    • M
                      mguenther @paul53 last edited by

                      @paul53
                      aber Paul, dein Ansatz mit const ids = $('zigbee.0.*.battery').toArray(); hat geholfen. ich bastle weiter und poste dann hier das Ergebnis.

                      danke

                      M 1 Reply Last reply Reply Quote 0
                      • M
                        mguenther @mguenther last edited by mguenther

                        hier mein Skript - chatgpt hat mit draufgeschaut - ich schließe hier.

                        // ===== Einstellungen =====
                        const OUT = "0_userdata.0.vis.BatterieListeDebug"; // Datenpunkt für VIS
                        const THRESH_LOW = 30;
                        const THRESH_MED = 60;
                        const MAX_HEIGHT = 660;
                        const WIDTH = 405; // Gesamtbreite
                        const STALE_HOURS = 168; // >7 Tage ohne Meldung = "nicht aktiv"
                        
                        // === Helfer ===
                        function colorByVal(v) {
                          if (!isFinite(v)) return "#9e9e9e";
                          if (v < THRESH_LOW) return "#e53935";   // rot
                          if (v < THRESH_MED) return "#fdd835";   // gelb
                          return "#43a047";                       // grün
                        }
                        
                        function devRoot(id) {
                          const p = id.split(".");
                          return [p[0], p[1], p[2]].join(".");
                        }
                        
                        function niceNameFromRoot(rootId) {
                          const obj = getObject(rootId);
                          return obj?.common?.name || rootId;
                        }
                        
                        function voltageToPercent(v) {
                          if (!isFinite(v)) return null;
                          const min = 2.0, max = 3.0;
                          let pct = ((v - min) / (max - min)) * 100;
                          return Math.max(0, Math.min(100, Math.round(pct)));
                        }
                        
                        // Liefert den letzten Änderungszeitpunkt aller States eines Geräts
                        function lastSeenDevice(root) {
                          let last = 0;
                          $('' + root + '.*').each(id => {
                            const st = getState(id);
                            if (st && st.lc && st.lc > last) last = st.lc;
                          });
                          return last;
                        }
                        
                        // === Rendering ===
                        function render() {
                          const map = {};
                        
                          // Zigbee: echte %
                          $('zigbee.0.*.battery').each(id => {
                            const root = devRoot(id);
                            const name = niceNameFromRoot(root);
                            const raw = getState(id)?.val;
                            const val = isFinite(raw) ? Math.max(0, Math.min(100, Math.round(Number(raw)))) : null;
                            if (val !== null) map[root] = { type: "percent", name, val, sys: "Zigbee" };
                          });
                        
                          // HmIP: Operating Voltage -> %
                          $('hm-rpc.0.*.OPERATING_VOLTAGE').each(id => {
                            const root = devRoot(id);
                            const name = niceNameFromRoot(root);
                            const val = voltageToPercent(getState(id)?.val);
                            if (val !== null) map[root] = { type: "percent", name, val, sys: "HmIP" };
                          });
                        
                          // Homematic: LOWBAT
                          $('hm-rpc.0.*.LOWBAT').each(id => {
                            const root = devRoot(id);
                            const name = niceNameFromRoot(root);
                            const lowbat = !!(getState(id)?.val);
                            const unreach = !!(getState(root + ".0.UNREACH")?.val);
                        
                            const last = lastSeenDevice(root);
                            const ageH = (Date.now() - last) / (1000 * 60 * 60);
                        
                            if (unreach) {
                              map[root] = { type: "unreach", name, sys: "HM" };
                            } else if (ageH > STALE_HOURS) {
                              map[root] = { type: "stale", name, sys: "HM" };
                            } else {
                              map[root] = { type: "lowbat", name, lowbat, sys: "HM" };
                            }
                          });
                        
                          // Homematic: LOW_BAT
                          $('hm-rpc.0.*.LOW_BAT').each(id => {
                            const root = devRoot(id);
                            const name = niceNameFromRoot(root);
                            const lowbat = !!(getState(id)?.val);
                            const unreach = !!(getState(root + ".0.UNREACH")?.val);
                        
                            const last = lastSeenDevice(root);
                            const ageH = (Date.now() - last) / (1000 * 60 * 60);
                        
                            if (unreach) {
                              map[root] = { type: "unreach", name, sys: "HmIP" };
                            } else if (ageH > STALE_HOURS) {
                              map[root] = { type: "stale", name, sys: "HmIP" };
                            } else {
                              map[root] = { type: "lowbat", name, lowbat, sys: "HmIP" };
                            }
                          });
                        
                          // Liste bauen
                          let list = Object.values(map);
                        
                          // Sortierung (angepasst)
                          list.sort((a, b) => {
                            function weight(it) {
                              if (it.type === "unreach") return 0;                                   // HM keine Meldung
                              if (it.type === "percent" && it.sys === "Zigbee" && it.val === 0) return 1; // Zigbee 0%
                              if (it.type === "stale") return 2;                                     // HM nicht aktiv
                              if (it.type === "percent" && it.sys === "Zigbee" && it.val < THRESH_LOW) return 3; // Zigbee rot
                              if (it.type === "lowbat" && it.lowbat === true) return 4;              // HM low
                              if (it.type === "percent" && it.sys === "Zigbee" && it.val < THRESH_MED) return 5; // Zigbee gelb
                              if (it.type === "percent" && it.sys === "Zigbee" && it.val >= THRESH_MED) return 6; // Zigbee grün
                              if (it.type === "lowbat" && it.lowbat === false) return 7;             // HM grün
                              return 99;
                            }
                        
                            const wa = weight(a), wb = weight(b);
                            if (wa !== wb) return wa - wb;
                        
                            // Falls gleiche Kategorie: nach Wert sortieren
                            if (a.type === "percent" && b.type === "percent") {
                              if (a.val == null) return 1;
                              if (b.val == null) return -1;
                              return a.val - b.val;
                            }
                            return 0;
                          });
                        
                          // Zeilen bauen
                          const rows = list.map(it => {
                            if (it.type === "percent") {
                              return `
                                <tr style="border-bottom:1px solid #444;">
                                  <td style="width:55px; color:#f5f5f5;">${it.sys}</td>
                                  <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td>
                                  <td style="width:55px; text-align:right; color:#f5f5f5;">${it.val == null ? "-" : it.val + " %"}</td>
                                  <td style="width:175px;">
                                    <div style="width:100%; height:10px; border-radius:5px; background:#333; overflow:hidden;">
                                      <div style="height:100%; width:${it.val ?? 0}%; background:${colorByVal(it.val)};"></div>
                                    </div>
                                  </td>
                                </tr>`;
                            }
                            if (it.type === "lowbat") {
                              const ok = it.lowbat === false;
                              const color = ok ? "#43a047" : "#e53935";
                              const text  = ok ? "OK" : "LOW";
                              return `
                                <tr style="border-bottom:1px solid #444;">
                                  <td style="width:55px; color:#f5f5f5;">${it.sys}</td>
                                  <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td>
                                  <td style="width:55px; text-align:right; color:#f5f5f5;">–</td>
                                  <td style="width:175px; color:${color}; font-weight:bold;">${text}</td>
                                </tr>`;
                            }
                            if (it.type === "unreach") {
                              return `
                                <tr style="border-bottom:1px solid #444;">
                                  <td style="width:55px; color:#f5f5f5;">${it.sys}</td>
                                  <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td>
                                  <td style="width:55px; text-align:right; color:#f5f5f5;">–</td>
                                  <td style="width:175px; color:#ff9800; font-weight:bold;">KEINE MELDUNG</td>
                                </tr>`;
                            }
                            if (it.type === "stale") {
                              return `
                                <tr style="border-bottom:1px solid #444;">
                                  <td style="width:55px; color:#f5f5f5;">${it.sys}</td>
                                  <td style="width:120px; color:#f5f5f5; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${it.name}">${it.name}</td>
                                  <td style="width:55px; text-align:right; color:#f5f5f5;">–</td>
                                  <td style="width:175px; color:#ff5722; font-weight:bold;">NICHT AKTIV</td>
                                </tr>`;
                            }
                          }).join("");
                        
                          // HTML mit sticky Header
                          const html = `
                            <div style="font-family: system-ui, Segoe UI, Roboto, Arial; font-size:13px;
                                        width:${WIDTH}px; max-height:${MAX_HEIGHT}px; overflow-y:auto;
                                        padding:0; background:transparent;">
                              <table style="width:${WIDTH}px; border-collapse:collapse; background:transparent;">
                                <thead style="background:#212121;">
                                  <tr style="border-bottom:1px solid #666;">
                                    <th style="width:55px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Typ</th>
                                    <th style="width:120px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Gerät</th>
                                    <th style="width:55px; text-align:right; color:#f5f5f5; position:sticky; top:0; background:#212121;">Batterie</th>
                                    <th style="width:175px; text-align:left; color:#f5f5f5; position:sticky; top:0; background:#212121;">Status</th>
                                  </tr>
                                </thead>
                                <tbody>${rows}</tbody>
                              </table>
                            </div>`;
                        
                          setState(OUT, html, true);
                        }
                        
                        // === Setup ===
                        createState(OUT, "", { type: "string", role: "html", read: true, write: false }, () => {
                          render();
                        
                          $('zigbee.0.*.battery').each(id => on({ id, change: "ne" }, render));
                          $('hm-rpc.0.*.OPERATING_VOLTAGE').each(id => on({ id, change: "ne" }, render));
                          $('hm-rpc.0.*.LOWBAT').each(id => on({ id, change: "ne" }, render));
                          $('hm-rpc.0.*.LOW_BAT').each(id => on({ id, change: "ne" }, render));
                          $('hm-rpc.0.*.UNREACH').each(id => on({ id, change: "ne" }, render));
                        
                          // Refresh alle 12 Stunden
                          schedule("0 */12 * * *", render);
                        });
                        
                        

                        6b5592ae-b6ff-4685-8d3d-b1c59447e64e-grafik.png

                        Tabelle ist html und lässt sich scrollen in meiner VIS

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

                        Support us

                        ioBroker
                        Community Adapters
                        Donate

                        894
                        Online

                        32.3k
                        Users

                        81.0k
                        Topics

                        1.3m
                        Posts

                        3
                        17
                        420
                        Loading More Posts
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes
                        Reply
                        • Reply as topic
                        Log in to reply
                        Community
                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                        The ioBroker Community 2014-2023
                        logo