Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Tester
    4. Neuer Adapter pi-hole2 für pihole>=V6

    NEWS

    • Wartung am 15.11. – Forum ab 22:00 Uhr nicht erreichbar

    • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?

    • Monatsrückblick – September 2025

    Neuer Adapter pi-hole2 für pihole>=V6

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

      Neue Version 0.4.0

      • Die Extraktion von Detailwerten für Version/Summary kann deaktiviert werden.
      1 Reply Last reply Reply Quote 0
      • Negalein
        Negalein Global Moderator @OliverIO last edited by

        @oliverio sagte in Neuer Adapter pi-hole2 für pihole>=V6:

        Fehler, Ideen, Anregungen dann bitte hier.

        Hallo Oliver

        Ist das Grau so gewollt?

        6da702df-e619-4046-99d0-f6336343b3ce-image.png

        OliverIO 1 Reply Last reply Reply Quote 0
        • OliverIO
          OliverIO @Negalein last edited by

          @negalein

          ah, danke. habe nicht mit hellem hintergrund getestet.
          hatte aber einen ähnlichen effekt bei dunkel.
          ist leider ein automatismus des admin.
          muss mir für hell dann eine anderen grünton suchen, bei rot ist es ja ok.
          der admin prüft den kontrast der farbe und schaltet dann halt einen anderen grünton dazu.

          1 Reply Last reply Reply Quote 1
          • OliverIO
            OliverIO last edited by OliverIO

            Neue Version 0.4.1

            • Das Problem mit der Farbgebung bei grünen Datenpunkten wurde behoben.
            SBorg 1 Reply Last reply Reply Quote 1
            • SBorg
              SBorg Forum Testing Most Active @OliverIO last edited by

              @oliverio
              Danke, wollte die Tage schon die API per NodeRED Flow abfragen 😊
              Pi-hole.png

              Richtet sich eher an den "Unbedarften":


              sendTo(
              "pi-hole2.0",
              "piholeapi",
              {
              method: "GET",
              endpoint: "/stats/summary"
              },
              function (data) {
              console.log(data.queries.percent_blocked);
              },
              );

              const json=getState('pi-hole2.0.Summary').val;
              const obj = JSON.parse(json);

              console.log(obj.queries.percent_blocked);


              Blockly.png

              Man sieht, man kommt auch so relativ einfach an die gewünschten Daten heran. Von daher sehe ich nicht unbedingt eine Notwendigkeit alles als Datenpunkt anbieten zu müssen.

              OliverIO 2 Replies Last reply Reply Quote 0
              • OliverIO
                OliverIO @SBorg last edited by

                @sborg

                Wenn es eine hohe Nachfrage gibt, dann ist es kein Problem datenpunkte noch hinzuzunehmen.
                Daher auch meine Frage oben
                Bisher kam aber noch nicht soviel Anforderungen.
                Gut der Adapter ist jung und es ist Sommer.

                Summary wird halt im Standard jede Sekunde abgefragt und ich wollte im Standard jetzt nicht so hohe Last auf den iobroker legen.
                Gut den Abfrage Intervall kann man ggfs. auch in der Konfiguration senken, ich habe daher die Konfiguration auch etwas detaillierter aufgedröselt.

                1 Reply Last reply Reply Quote 0
                • OliverIO
                  OliverIO @SBorg last edited by

                  @sborg

                  Du hast nur 5% geblockt?
                  Bei mir ist der Anteil bei über 50%
                  Microsoft, Amazon,Samsung und Netflix telefonieren schon viel nach Hause.

                  SBorg 1 Reply Last reply Reply Quote 0
                  • SBorg
                    SBorg Forum Testing Most Active @OliverIO last edited by

                    @oliverio
                    Meine Blocklist wurde offenbar nicht mehr geupdated. Habe ich aber nicht bemerkt, da ich fast nur mit meinem Laptop im Internet unterwegs bin. Da filtert der FF alles aus. Geladen habe ich den ganzen Kram natürlich dann aber doch, da ist das blocken per Pi-hole wesentlich effizienter. Dafür habe ich ihn ja auch.

                    1 Reply Last reply Reply Quote -1
                    • OliverIO
                      OliverIO last edited by OliverIO

                      Der Adapter müsste nun im beta auftauchen

                      • Der erste Post wurde aufgrund dessen überarbeitet
                      • Um eine fertige Version zu signalisieren wurde eine V1.0.0 released
                      1 Reply Last reply Reply Quote 1
                      • OliverIO
                        OliverIO last edited by OliverIO

                        Neue Version 1.1.0

                        • Unter Data/Versions wurden Update Indikatoren hinzugefügt, um mittels true/false anzuzeigen, das ein Update für die einzelne Komponente vorliegt.
                        L OliverIO 2 Replies Last reply Reply Quote 0
                        • L
                          Labersack @OliverIO last edited by Labersack

                          @oliverio
                          Habe den Adapter heute auch mal installiert.
                          Was soll ich sagen... Ich finde, der Adapter ist ein Pi-Loch! lol
                          Pi-Loch.jpg

                          OliverIO 1 Reply Last reply Reply Quote -1
                          • OliverIO
                            OliverIO @Labersack last edited by

                            @labersack

                            Ja sowas, die automatische Übersetzung.

                            Danke fürs Bescheid geben.

                            1 Reply Last reply Reply Quote 0
                            • OliverIO
                              OliverIO @OliverIO last edited by

                              Neue Version 1.1.1

                              • Die Übersetzung wurde optimiert
                              S 1 Reply Last reply Reply Quote 0
                              • S
                                sol21 @OliverIO last edited by

                                @oliverio
                                Könnte man den Adapter in auf "stable" setzen?

                                Ich benutze normalerwiese auf nur die "stable" Versionen. Für den pi-hole2 habe ich bisher gezwungenermassen eine Ausnahme gemacht. Die 1.1.1 scheint ja recht gut zu laufen. Wenn man ihn nun auf "stable" setzt würde, würde er auch bei Leuten wie mir die nur das "stable"-Repository angewählt haben angezeigt.

                                PS: Aber grundsätzlich vielen Dank für die neue Version. Die hat mein IOBroker-PiHole Problem gelöst!

                                OliverIO 1 Reply Last reply Reply Quote 0
                                • OliverIO
                                  OliverIO @sol21 last edited by OliverIO

                                  @sol21
                                  Normalerweise wird nach 15 Tagen automatisch ein issue eröffnet, aufgrund dessen ich dann die Versionen auf Stable setze.
                                  Kam wohl diesmal nicht. Eventuell sind für manche Adapter die Regeln anderst oder es hat mit den github Problemen zu tun.

                                  mcm1957 1 Reply Last reply Reply Quote 0
                                  • mcm1957
                                    mcm1957 @OliverIO last edited by mcm1957

                                    @oliverio
                                    Nö 15 Tage Erinnering kommt nur bei existierenden Adapter u mind 5% der User spätestens aber nach 30 Tagen.

                                    Die Regeln f eine Erinnerung sind immer gleich. 🙂

                                    An eine ERST Aufnahme wird erst nach 30 Tagen erinnert.

                                    Kannst den Stable Request aber jederzeit stellen. Erinnerung dazu ist keine Erfordernis.

                                    1 Reply Last reply Reply Quote 0
                                    • OliverIO
                                      OliverIO last edited by OliverIO

                                      pi-hole2 v1.1.1 befindet sich nun im stable repository

                                      1 Reply Last reply Reply Quote 1
                                      • OliverIO
                                        OliverIO last edited by OliverIO

                                        Hier mal ein größerer Anwendungsfall für den pihole2 Adapter.
                                        Bitte um Rückmeldungen, positive wie negative Erfahrungen.
                                        Evtl baue ich das dann als widgets in den Adapter ein.

                                        Bitte auch die Verwendung des Adapters vis-jsontemplate 4.1.3 weiter unten beachten
                                        https://forum.iobroker.net/topic/31521/test-widget-json-template/32?_=1762189668521


                                        Ich habe immer wieder den folgenden Anwendungsfall, der sich mit pihole Bordmitteln nicht so einfach lösen lässt.

                                        Ich habe immer wieder mal Seiten, die aufgrund eines pihole Blocks nicht funktionieren. Darüber hinaus funken hier mehrere Geräte wirklich sehr oft nach Hause, deren requests durch pihole geblockt werden. Dies verhindert leider effizient die Suche nach den betroffenen domains des blocks, der wieder aufgehoben werden soll, da das logfile relativ voll ist.

                                        Auch interessiert mich immer wieder mal, wer hier so nach Hause telefoniert.
                                        Diejenigen domains, die ich aber schon mal geprüft habe will ich nicht erneut prüfen.

                                        Daher nun der folgende Versuch einer Lösung mittels 2er Widgets die ich mit dem jsontemplate Adapter erstellt habe.

                                        Widget 1

                                        listet alle domains absteigend nach vorkommen über alle clients dar.
                                        jede einzelne domain kann dann auf die Merkliste gesetzt werden.
                                        die Liste kann nach einem Suchbegriff oder Regex gefiltert werden.
                                        Mehrere Sichtbare domains können über ein Sammel-Checkbox ebenfalls in einem Schritt gemerkt werden.
                                        Das widfget besteht 2 Reitern, einmal alle gemerkten domains, sowie alle die Nicht gemerkt worden sind.

                                        2b733665-5606-4cb2-915a-a319c511ef3c-image.png

                                        Die Konfiguration erfolgt im ersten Abschnitt des Templates

                                        // config area
                                        // adapter instance
                                        const pihole_adapter_instance = 0; //Nummer der Instanz
                                        const domain_count=200;  //maximale Anzahl der abzufragenden domains
                                        const domain_blocked=true; //Abfrage der geblockten Domains im standard, Alternativ geht das auch mit den nicht geblockten domänen
                                        

                                        Das Template muss im entsprechenden Feld eingetragen werden. Zusätzlich muss noch ein Datenpunkt vom typ String angelegt werden und wie hier verknüpft werden.
                                        Darin werden die bekannten domänen gespeichert.
                                        9cf63a60-9a51-458d-b42a-c7a063d0b1aa-image.png

                                        Template

                                        <%
                                        // config area
                                        // adapter instance
                                        const pihole_adapter_instance = 0;
                                        const domain_count=200;
                                        const domain_blocked=true;
                                        %>
                                        <%
                                        //javascript code der per ejs interpretiert wird
                                        const knownDP = Object.keys(dp)[0] || "";
                                        const knownValue = dp[knownDP] || "[]";
                                        const knownValueSet = new Set(JSON.parse(knownValue));
                                        const adapterinstance = "pi-hole2."+pihole_adapter_instance;
                                        //debugger;
                                        const cookieKey = widgetID+"selectedTab";
                                        const selectedTab = localStorage.getItem(cookieKey)||"tab-all";
                                        
                                        // Abruf der Daten vom pihole2 adapter
                                        const apiresult = await getTopDomains(domain_count,domain_blocked); 
                                        
                                        // Aufbau Index
                                        const domainCountMap = new Map((apiresult.domains || []).map(d => [d.domain, d.count]));
                                        
                                        // Aufbau der Tabellendaten knownDomains
                                        const savedList = [...knownValueSet].map(domain => ({
                                         domain,
                                         count: domainCountMap.get(domain) || 0
                                        }));
                                        // Hilfsfunktion für async SendTo
                                        async function sendToAsync(instance, command, sendData) {
                                        return new Promise((resolve, reject) => {
                                         try {
                                             vis.conn.sendTo(instance, command, sendData, function (receiveData) {
                                                 resolve(receiveData);
                                             });
                                         } catch (error) {
                                             reject(error);
                                         }
                                        });
                                        }
                                        //Hilfsfunktion Abruf der TopDomains blocked/not blocked 
                                        async function getTopDomains(count,blocked) {
                                        const blockedText = blocked ? "true":"false";
                                        return await sendToAsync(adapterinstance,"piholeapi", {
                                           method: 'GET',
                                           endpoint: "/stats/top_domains?count="+count+"&blocked="+blockedText,
                                        });
                                        };
                                        %>
                                        
                                        <style>
                                        .pihole.select .tabs {
                                           display: flex;
                                           gap: .1rem;
                                        }
                                        
                                        .pihole.select .tabs button {
                                           padding: .4rem .8rem;
                                           border: 1px solid #ccc;
                                           background: #f7f7f7;
                                           cursor: pointer;
                                        }
                                        
                                        .pihole.select .tabs button.active {
                                           background: #e9eefc;
                                           border-color: #8aa3ff;
                                        }
                                        
                                        .pihole.select .tabpanel {
                                           display: none;
                                        }
                                        
                                        .pihole.select .tabpanel.active {
                                           display: block;
                                        }
                                        
                                        .pihole.select table {
                                           width: 100%;
                                           border-collapse: collapse;
                                        }
                                        
                                        .pihole.select th,
                                        .pihole.select td {
                                           padding: .3rem .4rem;
                                           xborder-bottom: 1px solid #eee;
                                        }
                                        
                                        .pihole.select .check {
                                           text-align: center;
                                           width: 10%;
                                        }
                                        .pihole.select .domain {
                                           text-align: left;
                                           xwidth: 70%;
                                           display: flex;
                                           align-items: center;
                                           gap: .4rem;            /* optional */	
                                        }
                                        .pihole.select .domain .filter-all {
                                         flex: 1;               /* <-- restliche Breite */
                                         min-width: 0;          /* wichtig für Firefox/Edge */
                                         box-sizing: border-box;
                                        }
                                        
                                        .pihole.select .count {
                                           text-align: end;
                                           width: 20%;
                                        }
                                        
                                        .muted {
                                           color: #888;
                                           font-size: .9em;
                                        }
                                        .pihole.select th .filter {
                                           display:block; margin-top:.25rem;
                                        }
                                        .pihole.select th .filter input {
                                           width:100%; 
                                           box-sizing:border-box; 
                                           padding:.25rem .35rem;
                                           border:1px solid #ccc; 
                                           border-radius:4px; 
                                           font-size:.9rem;
                                        }
                                        .pihole.select th .filter small { 
                                           color:#666; 
                                        }
                                        </style>
                                        
                                        <div class="pihole select">
                                         <div class="tabs" role="tablist">
                                           <button type="button" role="tab" aria-controls="tab-all" class="tabbtn <%= selectedTab=="tab-all"?"active":""%>">Alle Domains</button>
                                           <button type="button" role="tab" aria-controls="tab-saved" class="tabbtn <%= selectedTab=="tab-saved"?"active":""%>">Gemerkte Domains</button>
                                         </div>
                                        
                                         <div id="tab-all" class="tabpanel <%= selectedTab=="tab-all"?"active":""%>" role="tabpanel" aria-label="Alle Domains">
                                           <table data-table="all">
                                             <thead>
                                               <tr>
                                                 <th class="check">
                                                   <span><input class="bulk" type="checkbox" data-action="check" checked></span>
                                                 </th>
                                                 <th class="domain">
                                                   <span>domain</span>
                                                   <input type="text" autofocus value="" class="filter-all">
                                                 </th>
                                                 <th class="count"><span>#</span></th>
                                               </tr>
                                             </thead>
                                             <tbody>
                                               <% (apiresult.domains || []).forEach(domain => { 
                                                    if (!knownValueSet.has(domain.domain)) { %>
                                                 <tr data-domain="<%= domain.domain %>">
                                                   <td class="check">
                                                     <input type="checkbox" data-id="<%= domain.domain %>">
                                                   </td>
                                                   <td class="domain"><%= domain.domain %></td>
                                                   <td class="count"><%= domain.count %></td>
                                                 </tr>
                                               <% } }) %>
                                             </tbody>
                                           </table>
                                         </div>
                                        
                                         <div id="tab-saved" class="tabpanel <%= selectedTab=="tab-saved"?"active":""%>" role="tabpanel" aria-label="Gemerkte Domains">
                                           <table data-table="saved">
                                             <thead>
                                               <tr>
                                                 <th class="check">
                                                   <input class="bulk" type="checkbox" data-action="uncheck">
                                                 </th>
                                                 <th class="domain">
                                                   <span>domain</span>
                                                   <input type="text" autofocus value="" class="filter-all">
                                                 </th>
                                                 <th class="count">#</th>
                                               </tr>
                                             </thead>
                                             <tbody>
                                               <% savedList.forEach(item => { %>
                                                 <tr data-domain="<%= item.domain %>">
                                                   <td class="check">
                                                     <input type="checkbox" data-id="<%= item.domain %>" checked>
                                                   </td>
                                                   <td class="domain">
                                                     <%= item.domain %>
                                                     <% if (!domainCountMap.has(item.domain)) { %>
                                                       <span class="muted">(derzeit nicht in Liste)</span>
                                                     <% } %>
                                                   </td>
                                                   <td class="count"><%= item.count %></td>
                                                 </tr>
                                               <% }) %>
                                             </tbody>
                                           </table>
                                         </div>
                                        </div>
                                        
                                        <script>
                                        //Javascript code der im browser läuft
                                        (async () => {
                                         // Funktionen für Tabs umschalten
                                         const cookieKey = "<%= widgetID %>selectedTab";
                                         const selectedTab = localStorage.getItem(cookieKey)||"tab-all";
                                         const $tabs = $(".tabbtn");
                                         const $panels = $(".tabpanel");
                                         $tabs.on("click", function() {
                                         //debugger;
                                           $tabs.removeClass("active");
                                           $(this).addClass("active");
                                           const id = $(this).attr("aria-controls");
                                           $panels.removeClass("active");
                                           $("#"+id).addClass("active");
                                           localStorage.setItem(cookieKey,id);
                                         });
                                        
                                         // Daten aus den Datenpunkt wird ins Skriptn übernommen
                                        //debugger;
                                         const knownDP   = "<%- knownDP %>";
                                         const initial   = JSON.parse(atob("<%= btoa(knownValue) %>"));
                                         const knownSet  = new Set(initial);
                                        
                                         // Helpers
                                         function writeDP() {
                                           //debugger;
                                           vis.setValue(knownDP, JSON.stringify(Array.from(knownSet)));
                                         }
                                         function makeRow(domain, count, checked=true) {
                                           return $(`
                                             <tr data-domain="${domain}">
                                               <td class="check"><input type="checkbox" data-id="${domain}" ${checked ? "checked":""}></td>
                                               <td class="domain">${domain}</td>
                                               <td class="count">${Number.isFinite(count) ? count : 0}</td>
                                             </tr>
                                           `);
                                         }
                                        
                                         // Eventhandler Merken einer Domain bzw auch wieder entfernen
                                         $('.pihole').on("change", 'tbody .check input', function(evt) {
                                           const id = $(evt.target).data("id");
                                           const isChecked = $(evt.target).is(":checked");
                                           const $row = $(evt.target).closest('tr');
                                        
                                           //hinzufügen oder entfernen der gewählten informationen
                                           if (isChecked) {
                                             // nach "saved" verschieben
                                             knownSet.add(id);
                                             // Count aus aktueller Zeile holen
                                             const cnt = parseInt($row.find('.count').text(), 10) || 0;
                                             // In saved hinzufügen, falls noch nicht vorhanden
                                             if ($('[data-table="saved"] tr[data-domain="'+id+'"]').length === 0) {
                                               $('[data-table="saved"] tbody').append(makeRow(id, cnt, true));
                                             } else {
                                               // sicherstellen, dass dort gecheckt ist
                                               $('[data-table="saved"] tr[data-domain="'+id+'"] input[type="checkbox"]').prop('checked', true);
                                             }
                                             // Falls Änderung aus "all" kam: Zeile dort entfernen (weil nun gemerkt)
                                             if ($row.closest('table').attr('data-table') === 'all') {
                                               $row.remove();
                                             }
                                           } else {
                                             // -> zurück nach "all" verschieben
                                             knownSet.delete(id);
                                             // Count aus aktueller Zeile holen
                                             const cnt = parseInt($row.find('.count').text(), 10) || 0;
                                             // In all hinzufügen, falls noch nicht vorhanden
                                             if ($('[data-table="all"] tr[data-domain="'+id+'"]').length === 0) {
                                               $('[data-table="all"] tbody').append(makeRow(id, cnt, false));
                                             } else {
                                               // sicherstellen, dass dort ungecheckt ist
                                               $('[data-table="all"] tr[data-domain="'+id+'"] input[type="checkbox"]').prop('checked', false);
                                             }
                                             // Falls Änderung aus "saved" kam: Zeile dort entfernen
                                             if ($row.closest('table').attr('data-table') === 'saved') {
                                               $row.remove();
                                             }
                                           }
                                           writeDP();
                                         });
                                        
                                         // Ereignishandler zum hinzufügen/entfernen aller sichtbaren Elemente
                                         $('.pihole').on('click', 'thead .bulk', function() {
                                         //debugger;
                                           const action = $(this).data('action'); // "check" | "uncheck"
                                           const $table = $(this).closest('table');
                                           const ids = $table.find('tbody tr:visible .check input').map((_,el)=>$(el).data('id')).get();
                                           //debugger;
                                           if (!ids.length) return;
                                           if (action === 'check') {
                                             ids.forEach(id => knownSet.add(id));
                                           } else {
                                             ids.forEach(id => knownSet.delete(id));
                                           }
                                           writeDP();
                                         });
                                         
                                         // Domain Filter
                                         const filterKey = "<%= widgetID %>filterAll";
                                         const $filter   = $('.filter-all');
                                         const $rowsAll  = $('[data-table="all"] tbody tr');
                                         const $visCount = $('#all-visible-count');
                                        
                                         //Funktion zum filtern
                                         function applyAllFilter(qRaw,table) {
                                           //debugger;
                                           const q = (qRaw || '').trim();
                                           let shown = 0;
                                        
                                           // Modus erkennen: /regex/ oder Wildcards
                                           let isRegex = false, re = null;
                                           if (q.startsWith('/') && q.endsWith('/') && q.length > 2) {
                                               try {
                                                   re = new RegExp(q.slice(1, -1), 'i'); 
                                                   isRegex = true;
                                               } catch(e) { 
                                                   /* fallback unten */ 
                                               }
                                           }
                                           if (!isRegex) {
                                             // * als Wildcard; rest escapen
                                             const esc = q.replace(/[.*+?^${}()|[]\]/g, '\\$&').replace(/\\\*/g, '.*');
                                             re = new RegExp(esc, 'i');
                                           }
                                        
                                           $('[data-table="'+table+'"] tbody tr').each((_, tr) => {
                                             const dom = tr.getAttribute('data-domain') || tr.querySelector('.domain')?.textContent || '';
                                             const match = q === '' ? true : re.test(dom);
                                             tr.style.display = match ? '' : 'none';
                                             if (match) shown++;
                                           });
                                        
                                           $visCount.text(shown);
                                         }
                                        
                                         // Entprellen der Eingabe 
                                         let fto;
                                         $filter.on('input', function() {
                                           const v = this.value;
                                           clearTimeout(fto);
                                           const table = $(this.closest("table")).data("table");
                                           fto = setTimeout(() => {
                                             localStorage.setItem(filterKey, v);
                                             applyAllFilter(v,table);
                                           }, 120);
                                         });
                                        
                                         // Beim Umschalten auf den Tab „Alle“ Filter erneut anwenden (falls DOM neu geändert wurde)
                                         $('.tabbtn[aria-controls="tab-all"]').on('click', () => applyAllFilter($filter.val()));
                                        
                                         // Persistierten Filter laden & anwenden
                                         const initialFilter = localStorage.getItem(filterKey) || "";
                                         $filter.val(initialFilter);
                                         applyAllFilter(initialFilter);
                                         
                                        })();
                                        </script>
                                        
                                        

                                        Widget2

                                        Dieses Widget zeigt alle geblockten requests an. Auch hier können ein paar Konfigurationen vorgenommen werden.
                                        Aufgrund dieser Lösung wurde noch ein kleiner glitch im jsontemplate entdeckt. Daher muss hier die Version 4.1.3 verwendet werden, ansonsten werden im 2.widget die Liste nicht korrekt dargestellt.

                                        d6c55515-a712-475f-80b8-2f417be28632-image.png
                                        Das Template muss im entsprechenden Feld eingetragen werden. Zusätzlich muss noch ein Datenpunkt vom typ String angelegt werden und wie hier verknüpft werden.
                                        Darin werden die bekannten domänen gespeichert.

                                        <%
                                        // config area
                                        // adapter instance
                                        const pihole_adapter_instance = 0;  //Adapter Instanz
                                        const blocked = true;  //Wie oben, ob geblockte oder nicht geblockte requests abgerufen werden soll
                                        const request_count=500;  // Anzahl der letzten requests, also ab dem jetzigen Zeitpunkt die letzten 500 requests.
                                        %>
                                        

                                        943fa6bf-e513-494e-a836-249b47749fb1-image.png

                                        Template

                                        <%
                                        // config area
                                        // adapter instance
                                        const pihole_adapter_instance = 0;
                                        const blocked = true;
                                        const request_count=500;
                                        %>
                                        <%
                                        const knownDP = Object.keys(dp)[0] || "";
                                        const knownValue = dp[knownDP] || "[]";
                                        %>
                                        
                                        <style>
                                        .pihole.requests {
                                           font-size: 0.8em;
                                        }
                                        .pihole.requests .col {
                                           text-align: left;
                                        }
                                        .pihole.requests .col.time {
                                           width: 15%;
                                        }
                                        .pihole.requests .col.status {
                                           width: 5%;
                                        }
                                        .pihole.requests .col.type {
                                           width: 5%;
                                        }
                                        .pihole.requests .col.domain {
                                           width: 20%;
                                        }
                                        .pihole.requests .col.client_name {
                                           width: 20%;
                                        }
                                        .pihole.requests .col.client_ip {
                                           width: 10%;
                                        }
                                        
                                        </style>
                                        <div class="pihole requests">
                                           <div>
                                               <select class="clientsb" name="clients">
                                                     <option value="">no Clients</option>
                                               </select>
                                           </div>
                                           <table data-table="all">
                                           	<thead>
                                           		<tr>
                                           			<th class="col time">Time</th>
                                           			<th class="col status">Status</th>
                                           			<th class="col type">Type</th>
                                           			<th class="col domain">Domain</th>
                                           			<th class="col client_name">Client Name</th>
                                           			<th class="col client_ip">Client IP</th>
                                           		</tr>
                                           	</thead>
                                           	<tbody>
                                               </tbody>
                                           </table>
                                        </div>
                                        <script>
                                        //Javascript code der im browser läuft
                                        (async () => {
                                           const pihole_adapter_instance = 0;
                                           const adapterinstance = "pi-hole2."+pihole_adapter_instance;
                                           const blocked = <%- blocked %>;
                                           const request_count=<%- request_count %>;
                                        
                                           const knownDP   = "<%- knownDP %>";
                                           const knownValue = atob("<%= btoa(knownValue) %>");
                                           const knownValueSet = new Set(JSON.parse(knownValue));
                                        
                                           let fto;    
                                           let $table=$(".pihole.requests tbody");
                                        
                                           await fillClients();
                                        
                                           function fillTable() {
                                               let table=$(".pihole.requests tbody"); 
                                           }
                                           async function fillClients() {
                                        
                                             const key = "<%= widgetID %>selectedclient";
                                             const selectedClient = localStorage.getItem(key)||"";
                                           
                                               let clients = await getClients();
                                               let $clientselect = $(".pihole.requests .clientsb");
                                        
                                               const clientlist = Object.entries(clients.clients)
                                                 .map(([ip, v]) => ({
                                                   ip, ...v
                                                 }))
                                                 .sort((a, b) => b.total - a.total);
                                               $clientselect.empty();
                                               $clientselect.append($('<option value="" '+isSelected(selectedClient,"")+'>nothing selected</option>'));
                                               clientlist.map(el=>$clientselect.append($('<option value="'+el.ip+'" '+isSelected(selectedClient,el.ip)+'>'+el.name+'/'+el.ip+'</option>')));
                                               let that=this;
                                               $clientselect.on('change', function() {
                                                 const v = this.value;
                                                 clearTimeout(fto);
                                                 fto = setTimeout(() => {
                                                   localStorage.setItem(key, v);
                                                   applySelect(v);
                                                 }, 120);
                                               });
                                        
                                               if (selectedClient) {
                                                   applySelect(selectedClient);
                                               }
                                               async function applySelect(client) {
                                                   let requests =  await getFilteredRequests(client /*"192.168.1.232"*/,request_count);
                                                   $table.empty();
                                                   requests.queries
                                                     .filter(req=>!knownValueSet.has(req.domain))
                                                     .map(req=>$table.append(makeRow(req)));
                                               }
                                           }
                                           function findIPv4(adresses) {
                                               let ips = adresses||[];
                                           
                                               return (adresses||"").split(",").filter(ip=>ip.split(".").length-1)[0]||"";
                                           }
                                           function isSelected(v1,v2) {
                                               return (v1==v2) ? "selected":"";
                                           }
                                           function makeRow(item) {
                                               return $(`
                                                   <tr>
                                                       <td class="col time">`+         formatDate(item.time)+`</th>
                                                       <td class="col status">`+       item.status+`</th>
                                                       <td class="col type">`+         item.type+`</th>
                                                       <td class="col domain">`+       item.domain+`</th>
                                                       <td class="col client_name">`+  item.client.name+`</th>
                                                       <td class="col client_ip">`+    item.client.ip+`</th>
                                                   </tr>
                                               `);
                                           }
                                           async function getData(client) {
                                               if (!client) {
                                                   client = clients[0];
                                               }
                                               return await getFilteredRequests(client /*"192.168.1.232"*/,request_count);
                                           }
                                           async function sendToAsync(instance, command, sendData) {
                                               return new Promise((resolve, reject) => {
                                                   try {
                                                       vis.conn.sendTo(instance, command, sendData, function (receiveData) {
                                                       resolve(receiveData);
                                                   });
                                                   } catch (error) {
                                                       reject(error);
                                                   }
                                               });
                                           }
                                           async function getClients() {
                                               return await sendToAsync(adapterinstance,"piholeapi", {
                                                   method: 'GET',
                                                   endpoint: "/history/clients?N=200",
                                               });
                                           };
                                           async function getFilteredRequests(client_ip,count) {
                                               return await sendToAsync(adapterinstance,"piholeapi", {
                                                   method: 'GET',
                                                   endpoint: "/queries?client_ip="+client_ip+"&upstream=blocklist&order%5B0%5D%5Bdir%5D=desc&start=0&length="+count,
                                               });
                                           };
                                           function formatDate(ts) {
                                               const date = new Date(ts * 1000);
                                               return date.toISOString();
                                           }
                                        
                                        })();
                                        </script>
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        

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

                                        Support us

                                        ioBroker
                                        Community Adapters
                                        Donate

                                        487
                                        Online

                                        32.4k
                                        Users

                                        81.3k
                                        Topics

                                        1.3m
                                        Posts

                                        7
                                        36
                                        2785
                                        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