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. Tester
  4. Neuer Adapter pi-hole2 für pihole>=V6

NEWS

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    9
    1
    120

  • 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

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

Geplant Angeheftet Gesperrt Verschoben Tester
52 Beiträge 9 Kommentatoren 3.2k Aufrufe 13 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.
  • OliverIOO Offline
    OliverIOO Offline
    OliverIO
    schrieb am zuletzt editiert von OliverIO
    #35

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

    Meine Adapter und Widgets
    TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
    Links im Profil

    1 Antwort Letzte Antwort
    1
    • OliverIOO Offline
      OliverIOO Offline
      OliverIO
      schrieb am zuletzt editiert von OliverIO
      #36

      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>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      

      Meine Adapter und Widgets
      TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
      Links im Profil

      1 Antwort Letzte Antwort
      0
      • MartinPM Online
        MartinPM Online
        MartinP
        schrieb am zuletzt editiert von
        #37

        Mein Sohn beschwert sich, dass er bei der Google Suche die Werbe-Links oben NICHT klicken kann.
        Wenn er nach Auto-Teilen sucht, ist die Werbung doch manchmal nützlich.

        Ansonsten findet er das Blocken durchaus nützlich.
        Gäbe es die Möglichkeit für feinere Abstufungen des Abschaltens des Blockings?

        • Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
        • Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

        Dann könnte ich ihm z. B. einen Vis2 View basteln, wo er das mit einem Fingertipp aktivieren kann ...

        Intel(R) Celeron(R) CPU N3000 @ 1.04GHz 8G RAM 480G SSD
        Virtualization : unprivileged lxc container (debian 12 on Proxmox 8.4.14)
        Linux pve 6.8.12-16-pve
        6 GByte RAM für den Container
        Fritzbox 6591 FW 8.03 (Vodafone Leih-Box)
        Remote-Access über Wireguard der Fritzbox

        OliverIOO BananaJoeB 2 Antworten Letzte Antwort
        0
        • mcm1957M Online
          mcm1957M Online
          mcm1957
          schrieb am zuletzt editiert von mcm1957
          #38

          Die Filterung wird durch pi-hole bestimmt - und nicht durch den Adapter.
          Schau dir mal die pi-hole Dokumentation an um zu sehen was du da wie einstellen kannst.

          Oder ziehlt die Frage darauf ab dass das Widget weitere Funktionen von pi-hole unterstützen soll?

          Entwicklung u Betreuung: envertech-pv, hoymiles-ms, ns-client, pid, snmp Adapter;
          Support Repositoryverwaltung.

          Wer Danke sagen will, kann nen Kaffee spendieren: https://paypal.me/mcm1957atiobroker

          LESEN - gute Forenbeitrage

          1 Antwort Letzte Antwort
          0
          • MartinPM MartinP

            Mein Sohn beschwert sich, dass er bei der Google Suche die Werbe-Links oben NICHT klicken kann.
            Wenn er nach Auto-Teilen sucht, ist die Werbung doch manchmal nützlich.

            Ansonsten findet er das Blocken durchaus nützlich.
            Gäbe es die Möglichkeit für feinere Abstufungen des Abschaltens des Blockings?

            • Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
            • Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

            Dann könnte ich ihm z. B. einen Vis2 View basteln, wo er das mit einem Fingertipp aktivieren kann ...

            OliverIOO Offline
            OliverIOO Offline
            OliverIO
            schrieb am zuletzt editiert von
            #39

            @MartinP

            Wenn du mir sagst wie man das über die pi hole gui macht könnte ich schauen wie man das über die api abbilden könnte.
            So detailliert kenne ich pihole nicht.
            Hier reichen uns die einheitlichen Möglichkeiten.

            Meine Adapter und Widgets
            TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
            Links im Profil

            1 Antwort Letzte Antwort
            1
            • MartinPM Online
              MartinPM Online
              MartinP
              schrieb am zuletzt editiert von
              #40

              Muss ich mir anschauen, die API habe ich noch nicht genutzt, habe die Basteleien bisher in der Web-Oberfläche von Pi-Hole gebaut ...

              Möglicherweise muss ich da auch noch einmal von vorne anfangen, und PiHole komplett neu aufsetzen..

              Läuft derzeit in einer sehr indirekten Installation Proxmox -> LXC-Container -> Docker ->PiHole

              Solle MACVLAN benutzen, sonst könne man gar keine Randscharfe Zuordnung zu Clients gewährleisten.

              Intel(R) Celeron(R) CPU N3000 @ 1.04GHz 8G RAM 480G SSD
              Virtualization : unprivileged lxc container (debian 12 on Proxmox 8.4.14)
              Linux pve 6.8.12-16-pve
              6 GByte RAM für den Container
              Fritzbox 6591 FW 8.03 (Vodafone Leih-Box)
              Remote-Access über Wireguard der Fritzbox

              OliverIOO 1 Antwort Letzte Antwort
              0
              • MartinPM MartinP

                Muss ich mir anschauen, die API habe ich noch nicht genutzt, habe die Basteleien bisher in der Web-Oberfläche von Pi-Hole gebaut ...

                Möglicherweise muss ich da auch noch einmal von vorne anfangen, und PiHole komplett neu aufsetzen..

                Läuft derzeit in einer sehr indirekten Installation Proxmox -> LXC-Container -> Docker ->PiHole

                Solle MACVLAN benutzen, sonst könne man gar keine Randscharfe Zuordnung zu Clients gewährleisten.

                OliverIOO Offline
                OliverIOO Offline
                OliverIO
                schrieb am zuletzt editiert von OliverIO
                #41

                @MartinP

                nicht du sollst dich mit der api beschäftigen.
                du sollst nur schauen wie du dein ziel mit der web oberfläche (=gui, graphical user interface) umsetzen kannst.

                wenn du das beschreiben kannst, kann man schauen was man damit im adapter machen kann.

                für macvlan musst du eigentlich nicht nneu installieren.
                das ist reine docker konfiguration.
                wie das mit Proxmox/LXC aussieht weiß ich allerdings nicht, da dann der Netzwerkverkehr nochmal durch eine weitere schicht durchgeführt wird.

                ich gehe mal davon aus, das man in pihole irgendwas mit client zu gruppen zuordnung machen muss und dann clients dynamisch zu gruppen zuordnet oder wieder rausnimmt um dann blocking ein/auszuschalten

                Meine Adapter und Widgets
                TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                Links im Profil

                1 Antwort Letzte Antwort
                0
                • MartinPM MartinP

                  Mein Sohn beschwert sich, dass er bei der Google Suche die Werbe-Links oben NICHT klicken kann.
                  Wenn er nach Auto-Teilen sucht, ist die Werbung doch manchmal nützlich.

                  Ansonsten findet er das Blocken durchaus nützlich.
                  Gäbe es die Möglichkeit für feinere Abstufungen des Abschaltens des Blockings?

                  • Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
                  • Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

                  Dann könnte ich ihm z. B. einen Vis2 View basteln, wo er das mit einem Fingertipp aktivieren kann ...

                  BananaJoeB Offline
                  BananaJoeB Offline
                  BananaJoe
                  Most Active
                  schrieb am zuletzt editiert von
                  #42

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

                  Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
                  Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

                  Naja, Die Möglichkeit temporär Pi-Hole zu deaktivieren (für x Minuten oder Stunden) ist in der GUI eingebaut. Ob das über die API geht ... vermutlich.

                  Hier hat einer ein Bash-Skript gebaut welches Gruppen per API aktiviert oder deaktiviert:
                  https://gist.github.com/Data-Monkey/d88199a51feb715f7d67a47900c846bb
                  Ein Client kann ja in mehreren Gruppen sein, wenn der also zusätzlich in einer Gruppe ist bei der nicht gefiltert ist, könnte man das über diesen Weg ein- und ausschalten (vermutlich)

                  ioBroker@Ubuntu 24.04 LTS (VMware) für: >260 Geräte, 5 Switche, 7 AP, 9 IP-Cam, 1 NAS 42TB, 1 ESXi 15TB, 4 Proxmox 1TB, 1 Hyper-V 48TB, 14 x Echo, 5x FireTV, 5 x Tablett/Handy VIS || >=160 Tasmota/Shelly || >=95 ZigBee || PV 8.1kW / Akku 14kWh || 2x USV 750W kaskadiert || Creality CR-10 SE 3D-Drucker

                  OliverIOO 2 Antworten Letzte Antwort
                  0
                  • BananaJoeB BananaJoe

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

                    Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
                    Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

                    Naja, Die Möglichkeit temporär Pi-Hole zu deaktivieren (für x Minuten oder Stunden) ist in der GUI eingebaut. Ob das über die API geht ... vermutlich.

                    Hier hat einer ein Bash-Skript gebaut welches Gruppen per API aktiviert oder deaktiviert:
                    https://gist.github.com/Data-Monkey/d88199a51feb715f7d67a47900c846bb
                    Ein Client kann ja in mehreren Gruppen sein, wenn der also zusätzlich in einer Gruppe ist bei der nicht gefiltert ist, könnte man das über diesen Weg ein- und ausschalten (vermutlich)

                    OliverIOO Offline
                    OliverIOO Offline
                    OliverIO
                    schrieb am zuletzt editiert von
                    #43

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

                    Naja, Die Möglichkeit temporär Pi-Hole zu deaktivieren (für x Minuten oder Stunden) ist in der GUI eingebaut. Ob das über die API geht ... vermutlich.

                    ja das geht und ist im aktuellen pihole adapter per datenpunkt eingebaut.

                    Meine Adapter und Widgets
                    TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                    Links im Profil

                    1 Antwort Letzte Antwort
                    1
                    • BananaJoeB BananaJoe

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

                      Blocking nur für ein/mehrere Client-Device (sein Notebook, sein Gaming-PC, sein Smartphone) temporär generell aufheben
                      Temporär ein Profil aktivieren, was die Google-Adlinks generell durchlässt

                      Naja, Die Möglichkeit temporär Pi-Hole zu deaktivieren (für x Minuten oder Stunden) ist in der GUI eingebaut. Ob das über die API geht ... vermutlich.

                      Hier hat einer ein Bash-Skript gebaut welches Gruppen per API aktiviert oder deaktiviert:
                      https://gist.github.com/Data-Monkey/d88199a51feb715f7d67a47900c846bb
                      Ein Client kann ja in mehreren Gruppen sein, wenn der also zusätzlich in einer Gruppe ist bei der nicht gefiltert ist, könnte man das über diesen Weg ein- und ausschalten (vermutlich)

                      OliverIOO Offline
                      OliverIOO Offline
                      OliverIO
                      schrieb am zuletzt editiert von
                      #44

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

                      Hier hat einer ein Bash-Skript gebaut welches Gruppen per API aktiviert oder deaktiviert:
                      https://gist.github.com/Data-Monkey/d88199a51feb715f7d67a47900c846bb
                      Ein Client kann ja in mehreren Gruppen sein, wenn der also zusätzlich in einer Gruppe ist bei der nicht gefiltert ist, könnte man das über diesen Weg ein- und ausschalten (vermutlich)

                      woher weiß die gruppe dann was geblockt werden soll?
                      oder geht da nur alles blocken oder nix?

                      Meine Adapter und Widgets
                      TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                      Links im Profil

                      BananaJoeB 1 Antwort Letzte Antwort
                      0
                      • OliverIOO OliverIO

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

                        Hier hat einer ein Bash-Skript gebaut welches Gruppen per API aktiviert oder deaktiviert:
                        https://gist.github.com/Data-Monkey/d88199a51feb715f7d67a47900c846bb
                        Ein Client kann ja in mehreren Gruppen sein, wenn der also zusätzlich in einer Gruppe ist bei der nicht gefiltert ist, könnte man das über diesen Weg ein- und ausschalten (vermutlich)

                        woher weiß die gruppe dann was geblockt werden soll?
                        oder geht da nur alles blocken oder nix?

                        BananaJoeB Offline
                        BananaJoeB Offline
                        BananaJoe
                        Most Active
                        schrieb am zuletzt editiert von
                        #45

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

                        woher weiß die gruppe dann was geblockt werden soll?
                        oder geht da nur alles blocken oder nix?

                        Naja, du setzt den Client in 2 Gruppen.
                        In die Normale wo alles gefiltert wird,
                        und die eine wo nichts gefiltert wird.

                        Und die Gruppe bei der nichts gefiltert wird schaltet man an oder aus nach Bedarf.
                        In der Hoffnung das das "Rechtemanagement" von pi-hole addierend arbeitet,
                        Testen müsste man das.
                        Da es aber auch bei Blockieren funktioniert, könnte auch der umgekehrte Weg möglich sein

                        ioBroker@Ubuntu 24.04 LTS (VMware) für: >260 Geräte, 5 Switche, 7 AP, 9 IP-Cam, 1 NAS 42TB, 1 ESXi 15TB, 4 Proxmox 1TB, 1 Hyper-V 48TB, 14 x Echo, 5x FireTV, 5 x Tablett/Handy VIS || >=160 Tasmota/Shelly || >=95 ZigBee || PV 8.1kW / Akku 14kWh || 2x USV 750W kaskadiert || Creality CR-10 SE 3D-Drucker

                        OliverIOO 1 Antwort Letzte Antwort
                        0
                        • BananaJoeB BananaJoe

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

                          woher weiß die gruppe dann was geblockt werden soll?
                          oder geht da nur alles blocken oder nix?

                          Naja, du setzt den Client in 2 Gruppen.
                          In die Normale wo alles gefiltert wird,
                          und die eine wo nichts gefiltert wird.

                          Und die Gruppe bei der nichts gefiltert wird schaltet man an oder aus nach Bedarf.
                          In der Hoffnung das das "Rechtemanagement" von pi-hole addierend arbeitet,
                          Testen müsste man das.
                          Da es aber auch bei Blockieren funktioniert, könnte auch der umgekehrte Weg möglich sein

                          OliverIOO Offline
                          OliverIOO Offline
                          OliverIO
                          schrieb am zuletzt editiert von
                          #46

                          @BananaJoe

                          ok, das kann @MartinP dann testen und Rückmeldung geben.

                          Dann könnte man für jede Gruppe einen Bool Datenpunkt anlegen um die zu aktivieren/deaktivieren.
                          Falls die Zugehörigkeit zu einer Gruppe darüber bestimmt ob geblockt wird oder nicht könnte man ein sendTo Befehl machen, bei dem ein client dann (ggfs auch zeitbasiert) zwischen Gruppen hin und hergeschoben wird.

                          Meine Adapter und Widgets
                          TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                          Links im Profil

                          BananaJoeB 1 Antwort Letzte Antwort
                          0
                          • OliverIOO OliverIO

                            @BananaJoe

                            ok, das kann @MartinP dann testen und Rückmeldung geben.

                            Dann könnte man für jede Gruppe einen Bool Datenpunkt anlegen um die zu aktivieren/deaktivieren.
                            Falls die Zugehörigkeit zu einer Gruppe darüber bestimmt ob geblockt wird oder nicht könnte man ein sendTo Befehl machen, bei dem ein client dann (ggfs auch zeitbasiert) zwischen Gruppen hin und hergeschoben wird.

                            BananaJoeB Offline
                            BananaJoeB Offline
                            BananaJoe
                            Most Active
                            schrieb am zuletzt editiert von
                            #47

                            @OliverIO Ein Client kann ja auch in mehreren Gruppen sein.
                            Theoretisch auch in einer "Keine Filterung" und "Blockiert".
                            Was gewinnt weis ich ohne Tests nicht, bei einer Firewall würde blockieren gewinnen oder die Reihenfolge entscheiden.
                            Dann bräuchte es das hin und herswitchen zwischen gruppen nicht

                            ioBroker@Ubuntu 24.04 LTS (VMware) für: >260 Geräte, 5 Switche, 7 AP, 9 IP-Cam, 1 NAS 42TB, 1 ESXi 15TB, 4 Proxmox 1TB, 1 Hyper-V 48TB, 14 x Echo, 5x FireTV, 5 x Tablett/Handy VIS || >=160 Tasmota/Shelly || >=95 ZigBee || PV 8.1kW / Akku 14kWh || 2x USV 750W kaskadiert || Creality CR-10 SE 3D-Drucker

                            OliverIOO 1 Antwort Letzte Antwort
                            0
                            • BananaJoeB BananaJoe

                              @OliverIO Ein Client kann ja auch in mehreren Gruppen sein.
                              Theoretisch auch in einer "Keine Filterung" und "Blockiert".
                              Was gewinnt weis ich ohne Tests nicht, bei einer Firewall würde blockieren gewinnen oder die Reihenfolge entscheiden.
                              Dann bräuchte es das hin und herswitchen zwischen gruppen nicht

                              OliverIOO Offline
                              OliverIOO Offline
                              OliverIO
                              schrieb am zuletzt editiert von OliverIO
                              #48

                              @BananaJoe

                              Aber ist alles Vermutung basierend auf Vermutung.
                              Wie gesagt:
                              Ausprobieren wie das über die über das Userinterface zu bedienen ist, dann kann man schauen wie man das über die API bewerkstelligt, so das es alle über die üblichen iobroker Methoden einfachst zu bedienen ist und auf Knöpfe/Schalter/etc. zu legen ist.

                              Meine Adapter und Widgets
                              TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                              Links im Profil

                              1 Antwort Letzte Antwort
                              1
                              • BananaJoeB Offline
                                BananaJoeB Offline
                                BananaJoe
                                Most Active
                                schrieb am zuletzt editiert von BananaJoe
                                #49

                                So, mal eben remote zu Hause drauf und extra getestet,
                                Wenn ein Client sowohl in der Default-Gruppe ist (bei der Standardmäßig gefiltert wird) und in einer Gruppe bei der nicht gefiltert wird,
                                dann wird trotzdem gefiltert.
                                Erst wenn ich ihn aus Default herausnehme geht es.

                                Wie üblich gewinnt verbieten vor erlauben

                                ioBroker@Ubuntu 24.04 LTS (VMware) für: >260 Geräte, 5 Switche, 7 AP, 9 IP-Cam, 1 NAS 42TB, 1 ESXi 15TB, 4 Proxmox 1TB, 1 Hyper-V 48TB, 14 x Echo, 5x FireTV, 5 x Tablett/Handy VIS || >=160 Tasmota/Shelly || >=95 ZigBee || PV 8.1kW / Akku 14kWh || 2x USV 750W kaskadiert || Creality CR-10 SE 3D-Drucker

                                1 Antwort Letzte Antwort
                                0
                                • BananaJoeB Offline
                                  BananaJoeB Offline
                                  BananaJoe
                                  Most Active
                                  schrieb am zuletzt editiert von
                                  #50

                                  Da hatte ich auch einen Denkfehler. Die Blocklisten sind Gruppen zugeordnet, ist man Mitglied der Gruppe, wird diese auch angewandt.
                                  Der Trick mit einer Gegenregel / Ausnahme die nur für die Gruppe gilt, funktioniert nicht

                                  ioBroker@Ubuntu 24.04 LTS (VMware) für: >260 Geräte, 5 Switche, 7 AP, 9 IP-Cam, 1 NAS 42TB, 1 ESXi 15TB, 4 Proxmox 1TB, 1 Hyper-V 48TB, 14 x Echo, 5x FireTV, 5 x Tablett/Handy VIS || >=160 Tasmota/Shelly || >=95 ZigBee || PV 8.1kW / Akku 14kWh || 2x USV 750W kaskadiert || Creality CR-10 SE 3D-Drucker

                                  OliverIOO 1 Antwort Letzte Antwort
                                  0
                                  • BananaJoeB BananaJoe

                                    Da hatte ich auch einen Denkfehler. Die Blocklisten sind Gruppen zugeordnet, ist man Mitglied der Gruppe, wird diese auch angewandt.
                                    Der Trick mit einer Gegenregel / Ausnahme die nur für die Gruppe gilt, funktioniert nicht

                                    OliverIOO Offline
                                    OliverIOO Offline
                                    OliverIO
                                    schrieb am zuletzt editiert von OliverIO
                                    #51

                                    @BananaJoe

                                    also wird eine funktion benötigt, die einen user von einer gruppe zu einer anderen schiebt. ggfs kann ein user auch in mehreren gruppen aktiv sein um evtl teilweise sperren aufrecht zu erhalten

                                    default: alles wird gesperrt
                                    gruppe 1: liste A (windows nach Hause telefonieren)
                                    gruppe 2: liste B (listen mit google adsense etc. werbung)
                                    gruppe 3: keine Liste, also keine Sperrung

                                    Szenario1
                                    user ist zu beginn in gruppe 1 und 2 um alles ungewünschte zu sperren
                                    temporär soll user überhaupt keine sperre haben, also wird user von 1 nach 3 gesetzt und 2 gelöscht

                                    Szenario2
                                    oder einfach nur von 2 nach 3, 1 bleibt erhalten um nur ein teilweises blocken zu erlauben.
                                    bspw windows telefoniert nach hause soll immer unterdrückt werden, aber google shopping manchmal deaktiviert werden um auf die gesponsorten links oder produktvorschläge zu klicken

                                    default ist dann nur der fallback für die clients für die keine bersondere behandlung erfolgen soll.

                                    @MartinP kannst du das verifizieren ob das für dich passen würde?

                                    Meine Adapter und Widgets
                                    TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                                    Links im Profil

                                    1 Antwort Letzte Antwort
                                    1
                                    • Meister MopperM Online
                                      Meister MopperM Online
                                      Meister Mopper
                                      schrieb zuletzt editiert von
                                      #52

                                      Da die API von Pi-hole v6 nicht den Abruf der insgesamt geblockten unique domains vorsieht, habe ich mich mal mit einer KI auf die Suche gemacht und eine Lösung vermittels Abfrage der sqlite3-Datenbank des Pi-hole gefunden.

                                      Diese wird mit einem exec-Befehl vermittels Skript initiiert. Das funktioniert natürlich nur, wenn der Systemuser iobroker auch einen passwortfreien ssh-Zugriff vermittels Schlüssel auf den Pi-hole Server hat und im Javascript-Adapter exec aktiviert wurde.

                                      736a0952-52af-46cd-ad76-d278c2bf5f91-image.png

                                      Zur Erläuterung:
                                      Ich habe zwei Pi-hole Server laufen, deshalb werden hier täglich zwei Datenpunkte befüllt (das muss dann nach eigenen Bedürfnissen angepasst werden).

                                      Hier das Skript:

                                      // Konfiguration der Pi-hole Server und Datenpunkte
                                      const piholeServers = [
                                         // Struktur: 0_userdata.0.Pihole.piholeX.UniqueGravityDomains
                                         { host: 'pihole', datapoint: '0_userdata.0.Pihole.pihole0.UniqueGravityDomains' },
                                         { host: 'rpifr24', datapoint: '0_userdata.0.Pihole.pihole1.UniqueGravityDomains' }
                                      ];
                                      
                                      // Funktion zum Erstellen der Datenpunkte, falls diese noch nicht existieren
                                      function createDataPoints() {
                                         piholeServers.forEach(server => {
                                             createState(server.datapoint, 0, {
                                                 name: `Anzahl der einzigartigen Domains auf ${server.host}`,
                                                 type: 'number',
                                                 role: 'value',
                                                 unit: 'Domains'
                                             });
                                         });
                                         console.log("Struktur der Pi-hole Datenpunkte erstellt oder geprüft.");
                                      }
                                      
                                      // Hauptfunktion zum Abrufen und Aktualisieren der Daten
                                      function updatePiHoleData() {
                                         console.log("Starte tägliche Pi-hole Datenaktualisierung...");
                                      
                                         // SQL-Befehl: Jetzt werden die inneren doppelten Anführungszeichen escaped,
                                         // während die einfachen Anführungszeichen ('gravity_count') direkt stehen bleiben können,
                                         // da sie vom äußeren Doppel-Anführungszeichen-Kontext geschützt werden.
                                         const sqlQuery = "SELECT value FROM info WHERE property = 'gravity_count';"; 
                                      
                                         piholeServers.forEach(server => {
                                             // ENDGÜLTIGE LÖSUNG: Äußeres JS-Kommando in Backticks.
                                             // Das SSH-Kommando wird von doppelten Anführungszeichen (`"`) umschlossen.
                                             // Die innere Anführungszeichenstruktur muss von der Datenbank die einfachen Anführungszeichen erhalten.
                                             const command = `ssh thomas@${server.host} "sudo pihole-FTL sqlite3 /etc/pihole/gravity.db \\"${sqlQuery}\\""`;
                                             // HINWEIS: Dies ist die robusteste Form der Verschachtelung, die die innere einfache Anführungszeichenkette
                                             // an die SQLite-Engine weitergibt, indem die äußeren Doppel-Anführungszeichen escaped werden.
                                      
                                             require('child_process').exec(command, function(error, stdout, stderr) {
                                                 if (error) {
                                                     console.error(`Fehler bei SSH-Verbindung zu ${server.host}: ${error.message}`);
                                                     console.error(`[${server.host}] Fehlerdetails: ${stderr}`);
                                                     return;
                                                 }
                                                 if (stderr) {
                                                     console.error(`Stderr von ${server.host}: ${stderr}`);
                                                 }
                                                 
                                                 const domainCount = parseInt(stdout.trim(), 10);
                                                 
                                                 if (!isNaN(domainCount)) {
                                                     setState(server.datapoint, domainCount, true);
                                                     console.log(`[${server.host}] Domainanzahl erfolgreich aktualisiert: ${domainCount}`);
                                                 } else {
                                                     console.error(`[${server.host}] Konvertierung der Domainanzahl fehlgeschlagen: ${stdout}`);
                                                 }
                                             });
                                         });
                                      }
                                      
                                      // 1. Datenpunkte beim Skriptstart erstellen/prüfen
                                      createDataPoints();
                                      
                                      // 2. Skript beim Start einmalig ausführen
                                      updatePiHoleData();
                                      
                                      // 3. Täglich um 01:25 Uhr morgens aktualisieren
                                      // Die Cron-Syntax ist: 'Minuten Stunden * * *'
                                      schedule('25 1 * * *', updatePiHoleData);
                                      

                                      Vielleicht hilft es ja anderen Nerds (Huch, die Emojis können noch nicht eingefügt werden ggg).

                                      Proxmox und HA

                                      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

                                      854

                                      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