Hauptmenü

FHEM und pihole V6

Begonnen von juemuc, 01 Januar 2025, 20:38:12

Vorheriges Thema - Nächstes Thema

juemuc

Hallo zusammen,

hat sich schon jemand mit der neuen pihole-API in der Version pihole V6 beschäftigt? Da dort die API komplett neu und ohne php ist, funktioniert der Aufruf wie unter der Version 5 nicht mehr.

Ich habe aber leider keine Ahnung, wie man nun die neue API (trotz API-Doku) in FHEM einbinden kann. Wer kann helfen?

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

Ralli

ZitatThe Pi-hole API is organized around REST. Our API has predictable resource-oriented URLs, accepts and returns reliable UTF-8 JavaScript Object Notation (JSON)-encoded data for all API responses, and uses standard HTTP response codes and verbs. Most (but not all) endpoints require authentication. API endpoints requiring authentication will fail with code 401 Unauthorized when used outside a valid session.

Quelle: https://ftl.pi-hole.net/development-v6/docs/

Ganz normal HTTP / REST, also mittels HTTPMOD. Was hast du denn bereits probiert?

Für AdGuard habe ich das so anhand des ursprünglichen Beispiels nachgebaut: https://forum.fhem.de/index.php?topic=132511.0 , sollte/dürfte daher für pihole v6 auch nur (d)eine Fleißaufgabe sein.
Gruß,
Ralli

Proxmox 9 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.4 dev, virtualisierte RaspberryMatic (3.83.6.20250705) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.4.1) und HMW-GW, FRITZBOX 7490 (07.59), FBDECT, Siri und Alexa

juemuc

Hallo Ralli,

ich habe bisher die pihole-Daten wie im Thread pihole beschrieben, in FHEM zur Verfügung gestellt. Die Doku von der neuen APi habe ich schon gesehen, nur verstanden habe ich sie nicht  :-\

Ich würde ja gerne klein anfangen und verstehen, wie ich die "SID" erhalte, die wohl für die weiteren Schritte notwendig sind. Ich bitte noch um weitere Unterstützung. Danke

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

Ralli

Du musst hier zweistufig vorgehen. Erst Login, um eine SID zu bekommen, und dann die SID bei jedem weiteren Aufruf mitgeben.

Beispiel: https://forum.fhem.de/index.php?msg=889015
Gruß,
Ralli

Proxmox 9 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.4 dev, virtualisierte RaspberryMatic (3.83.6.20250705) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.4.1) und HMW-GW, FRITZBOX 7490 (07.59), FBDECT, Siri und Alexa

juemuc

Hallo Ralli,

das hilft mir leider nicht weiter, da ich die Info nicht verstehe. In dem Beispiel für die V5 musste ich halt nur die IP-Adresse und den API-Key ersetzen.

Auch die Testabfrage im Browser war mit den damaligen Infos möglich. Mit der http-Programmierung kenne ich mich nicht aus. Trotzdem danke für Deine Hilfe. Ich warte mal weiter ab. Vielleicht nutzt ja noch jemand die V6 und FHEM. 

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

Ralli

#5
Ich habe einmal für dich die Arbeit gemacht:

defmod pihole HTTPMOD none 60
attr pihole alias Pi-hole
attr pihole bodyDecode auto
attr pihole devStateIcon {piholeV6DevStateIcon($name)}
attr pihole enableControlSet 1
attr pihole enableCookies 1
attr pihole enforceGoodReadingNames 1
attr pihole event-on-change-reading .*
attr pihole extractAllJSON 1
attr pihole get01ExtractAllJSON 1
attr pihole get01Header X-FTL-SID: $sid
attr pihole get01Name FTL_summary
attr pihole get01Poll 1
attr pihole get01URL %%base_url%%/stats/summary
attr pihole get02ExtractAllJSON 1
attr pihole get02Header X-FTL-SID: $sid
attr pihole get02Name FTL_version
attr pihole get02Poll 1
attr pihole get02URL %%base_url%%/info/version
attr pihole get03ExtractAllJSON 1
attr pihole get03Header X-FTL-SID: $sid
attr pihole get03Name FTL_info
attr pihole get03Poll 1
attr pihole get03URL %%base_url%%/info/ftl
attr pihole get04Header X-FTL-SID: $sid
attr pihole get04Name FTL_status
attr pihole get04Poll 1
attr pihole get04URL %%base_url%%/dns/blocking
attr pihole get05Header X-FTL-SID: $sid
attr pihole get05Name FTL_messages
attr pihole get05Poll 1
attr pihole get05URL %%base_url%%/info/messages/count
attr pihole handleRedirects 1
attr pihole icon it_raspberry_logo
attr pihole reAuthRegex [Uu]nauthorized
attr pihole replacement01Mode text
attr pihole replacement01Regex %%base_url%%
attr pihole replacement01Value %%protocol%%://%%ip%%/api
attr pihole replacement02Mode text
attr pihole replacement02Regex %%ip%%
attr pihole replacement02Value DEINE_PIHOLE_IP_GGF_MIT_:PORT_WENN_NICHT_STANDARD
attr pihole replacement03Mode key
attr pihole replacement03Regex %%api_password%%
attr pihole replacement03Value api_password
attr pihole replacement04Mode text
attr pihole replacement04Regex %%protocol%%
attr pihole replacement04Value http
attr pihole set01Data {"blocking":false, "timer":$val}
attr pihole set01ExtractAllJSON 1
attr pihole set01Header X-FTL-SID: $sid
attr pihole set01Hint 10,60,180,300,600,900
attr pihole set01Max 900
attr pihole set01Min 10
attr pihole set01Name disable
attr pihole set01ParseResponse 1
attr pihole set01URL %%base_url%%/dns/blocking
attr pihole set02Data {"blocking":true}
attr pihole set02ExtractAllJSON 1
attr pihole set02Header X-FTL-SID: $sid
attr pihole set02Name enable
attr pihole set02NoArg 1
attr pihole set02ParseResponse 1
attr pihole set02URL %%base_url%%/dns/blocking
attr pihole sid1Data {"password": "%%api_password%%"}
attr pihole sid1IdJSON session_sid
attr pihole sidURL %%base_url%%/auth
attr pihole stateFormat blocking
attr pihole userReadings gravity_last_updated_abstime:gravity_last_update.* {strftime('%Y-%m-%d %H:%M:%S', localtime(ReadingsNum($name,'gravity_last_update',0)))}
set pihole storeKeyValue api_password DEIN_PIHOLE_API_PASSWORT

Dazu passend die Routine für die 99_myUtils.pm:

sub piholeV6DevStateIcon
{
my $name = shift;
my $noHeader=shift;

$noHeader=0 if(!defined($noHeader));

#get %%base_url%% replacement from httpmod device (using HTTPMOD method)
# -> this is the url to the web-ui of Pi-Hole
my $baseURL= HTTPMOD::DoReplacement($defs{$name},'get','%%protocol%%')."://".HTTPMOD::DoReplacement($defs{$name},'get','%%ip%%')."/admin/";

#get required readings from pihole httpmod device
my $state =ReadingsVal($name,'blocking','unknown');
my $totalQueries = sprintf("%07d",ReadingsVal($name,'queries_total','0'));
my $blocked = sprintf("%06d",ReadingsVal($name,'queries_blocked','0'));
my $blockedPercentage = sprintf("%04.1f",ReadingsVal($name,'queries_percent_blocked','0'));
my $adListCount =ReadingsVal($name,'gravity_domains_being_blocked','0');
my $messageCount=ReadingsNum($name,'count','0');
   
        my  $ver_info = 'CORE: '.ReadingsVal($name,'version_core_local_version','unknown').' => '.ReadingsVal($name,'version_core_remote_version','unknown');
        $ver_info.= "\nFTL: ".ReadingsVal($name,'version_ftl_local_version','unknown').' => '.ReadingsVal($name,'version_ftl_remote_version','unknown');
        $ver_info.= "\nWEB: ".ReadingsVal($name,'version_web_local_version','unknown').' => '.ReadingsVal($name,'version_web_remote_version','unknown');
        $ver_info.= "\nDocker: ".ReadingsVal($name,'version_docker_local','').' => '.ReadingsVal($name,'version_docker_remote','') if (ReadingsVal($name,'version_docker_local','') ne "");
   
        my $core_upd = 1 if(ReadingsVal($name,'version_core_local_version','unknown') ne ReadingsVal($name,'version_core_remote_version','unknown'));
        my $ftl_upd = 1 if (ReadingsVal($name,'version_ftl_local_version','unknown') ne ReadingsVal($name,'version_ftl_remote_version','unknown'));
        my $web_upd = 1 if (ReadingsVal($name,'version_web_local_version','unknown') ne ReadingsVal($name,'version_web_remote_version','unknown'));
        my $docker_upd = 1 if ((ReadingsVal($name,'version_docker_local','') ne ReadingsVal($name,'version_docker_remote','')) and (ReadingsVal($name,'version_docker_remote','') ne ""));

        my $anyUpd=$ftl_upd+$core_upd+$web_upd+$docker_upd+0;
   

#prepare dedicated css
#hint: html of device overview is by default embedded in a <div> container
#      which has id attribute set to device's NAME
my  $styleClass ='<style>';
        $styleClass.='#'.$name.' svg {height:15px; width:15px; padding-right:1px;} ';
        $styleClass.='#'.$name.' td {padding-left:10px; padding-right:10px} ';
        $styleClass.='</style>';

#prepare images
my $imgQueries=FW_makeImage('it_i-net@cyan');
my $imgBlocked=FW_makeImage('time_manual_mode@red');
my $imgState  =FW_makeImage($state eq 'enabled' ? '15px-green' : '15px-red');
        $imgState = FW_makeImage('15px-orange') if ($state eq 'enabled' and $messageCount > 0);
        my $imgUpdate =FW_makeImage($anyUpd > 0 ? '15px-red' : '15px-green',$ver_info);   

        if ($anyUpd > 0) {
                # fhem("setreading ".$name." available_updates 1")
                readingsSingleUpdate($defs{$name},"available_updates","1",1)
        } else {
                # fhem("setreading ".$name." available_updates 0")
                readingsSingleUpdate($defs{$name},"available_updates","0",0)
        }

#prepare disable/enable command
my $cmd='';
my $callMe='<a href="/fhem?cmd.'.$name.'=set '.$name;
if($state eq 'disabled') {
$callMe .=' enable ';
$cmd =$callMe.'">Enable</a>';
} else {
$callMe .=' disable ';
$cmd  =       $callMe.'60">1</a>';
$cmd .= ' | '.$callMe.'300">5</a>';
$cmd .= ' | '.$callMe.'600">10</a>';
$cmd .= ' | '.$callMe.'900">15</a>';
}

#finally build the html for device overview
my $ret  = $styleClass;
    $ret .= '<table border=0"><tr>';
    #if second argument of this method call is true (=1)
#then do NOT create a table header. Defaults to false (=0)
if(!$noHeader) {    
    $ret .= '<th>State</th>';
    $ret .= '<th>Queries</th>';
    $ret .= '<th>Blocked</th>';
    #$ret .= '<th>Adlist</th>';    
    $ret .= '<th>'.($state eq 'enabled' ? 'Disable [Minutes]':'Disabled').'</th>';
    $ret .= '<th>Upd</th>';           

    $ret .= '</tr><tr>';
}    
        $ret .= '<td><a href="'.$baseURL.'?sid='.urlEncode(InternalVal("$name","sid","")).'" target="_blank">'.$imgState.'</a></td>';
        $ret .= '<td>'.$imgQueries.' '.$totalQueries.'</td>';
        $ret .= '<td>'.$imgBlocked.' '.$blocked.' ('.$blockedPercentage.'%)'.'</td>';
        #$ret .= '<td>'.$imgAdList.' '.$adListCount.'</td>';
        $ret .= '<td>'.$cmd.'</td>';
        $ret .= '<td>'.$imgUpdate.'</td>';
        $ret .= '</tr></table>';

return $ret;
}

Sollte was nicht funktionieren oder ergänzt werden müssen, darfst du das gerne nun übernehmen.
Gruß,
Ralli

Proxmox 9 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.4 dev, virtualisierte RaspberryMatic (3.83.6.20250705) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.4.1) und HMW-GW, FRITZBOX 7490 (07.59), FBDECT, Siri und Alexa

juemuc

Hallo Ralli,

erst einmal vielen vielen Dank. Ich teste und versuche die einzelnen Codezeilen zu verstehen. Gibt es neben dieser Doku:httpmod noch eine Doku zu den verwendeten Befehlen?
Ich finde direkt zu bodyDecode auto keine Erklärung.

Viele Grüße
Jürgen

3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

juemuc

Hallo Ralli,

meine Tests waren erfolgreich. Also noch einmal vielen, vielen Dank. Ich habe noch ein paar Kleinigkeiten angepasst.

  • Da eine "sub" für die Version 5 in der 99_myUtils schon vorhanden war, habe ich Deine in piholeV6DevStateIcon umbenannt.
  • Dort habe ich auch die führenden Nullen für die Darstellung von "Querries" und "Blocked" entfernt.
  • Für die absolute Zeitangabe von "gravity_last_update" habe ich noch eine userReadings mit einer lesbaren Darstellung (YY-MM-DD HH:MM:SS) angelegt.
  • Zusätzlich habe ich das Passwort mit StoreKeyValue "ausgelagert".

Die Änderungen kann ich gerne hier bereitstellen.

Ein paar Fragen habe ich habe dennoch:

  • Unter "error_key" und "error_message" steht jeweils "unauthorized" bzw. "Unauthorized". Die Daten werden aber korrekt ausgelesen.
  • Kann ich die Abfragen in der Browser-Eingabezeile auch direkt testen? in der V5 waren es ja einfach nur https-Aufrufe.

Viele Grüße und Danke für Deine Geduld
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

juemuc

Hallo Ralli,

das Thema "error_key" und "error_message" hat sich erledigt. Die Readings sind nicht mehr aufgetaucht, nachdem ich das ganze einmal gelöscht und wieder hinzugefügt habe. Ich vermute, dass ich einmal das PSW falsch eingegeben hatte und deshalb die Readings erzeugt wurden. Sie werden wohl nicht wieder gelöscht, wenn alles ok ist.

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

Ralli

Zitat von: juemuc am 04 Januar 2025, 21:45:06
  • Da eine "sub" für die Version 5 in der 99_myUtils schon vorhanden war, habe ich Deine in piholeV6DevStateIcon umbenannt.
  • Für die absolute Zeitangabe von "gravity_last_update" habe ich noch eine userReadings mit einer lesbaren Darstellung (YY-MM-DD HH:MM:SS) angelegt.
  • Zusätzlich habe ich das Passwort mit StoreKeyValue "ausgelagert".


Das habe ich ebenfalls noch nachgezogen und ist oben im Beitrag nun auch enthalten.

Zitat
  • Dort habe ich auch die führenden Nullen für die Darstellung von "Querries" und "Blocked" entfernt.

Das wiederum ziehe ich nicht nach, da ich mehrere solche Devices im Web-Frontend untereinander stehen habe und so die Übersichtlichkeit bzw. Anschaulichkeit besser ist.
Gruß,
Ralli

Proxmox 9 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.4 dev, virtualisierte RaspberryMatic (3.83.6.20250705) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.4.1) und HMW-GW, FRITZBOX 7490 (07.59), FBDECT, Siri und Alexa

Hans-Ulrich Tag

Zitat von: juemuc am 04 Januar 2025, 23:00:13Hallo Ralli,

das Thema "error_key" und "error_message" hat sich erledigt. Die Readings sind nicht mehr aufgetaucht, nachdem ich das ganze einmal gelöscht und wieder hinzugefügt habe. Ich vermute, dass ich einmal das PSW falsch eingegeben hatte und deshalb die Readings erzeugt wurden. Sie werden wohl nicht wieder gelöscht, wenn alles ok ist.

Viele Grüße
Jürgen

Hallo Jürgen, diese Fehler erscheinen auch bei mir. Welches Passwort muss ich eintragen? Der Password-Hash unter "Webserver und API" funktioniert nicht.

VG Hans-Ulrich

juemuc

Hallo Hans-Ulrich,

ich habe für die Anmeldung am pihole ein PSW vergeben, welches auch für die API genutzt wird.

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

eisman

hi,

danke für die Arbeit

ich würde das : set pihole storeKeyValue api_password DEIN_PIHOLE_API_PASSWORT

etwas absetzen, weil es nicht zum Code gehört.
hatte es die ganze zeit übersehen....

gruss
1x FHEM Debian, Homematic,ZigBee,FS20 / 1X Raspberry, ConBee / 7x ESP
1x FHEM Debian, Homematic,Z2M             / 1X Raspberry, ConBee / 6x ESP
1x FHEM Debian,MQTT2                             / 1X Raspberry, i2c,onewire,gpio
1x auf Windows 2012 Hyper-V-S

juemuc

#13
Hallo zusammen,

ich habe die sub in der 99_myUtils.pm noch einmal angepasst, da die Updateinformation noch nicht gepasst hat. Es wird nun (korrekt) geprüft ob eine neue Version (inkl. Docker) vorhanden ist.

sub piholeV6DevStateIcon
{
my $name = shift;
my $noHeader=shift;

$noHeader=0 if(!defined($noHeader));

#get %%base_url%% replacement from httpmod device (using HTTPMOD method)
# -> this is the url to the web-ui of Pi-Hole
my $baseURL= "https://".HTTPMOD::DoReplacement($defs{$name},'get','%%ip%%')."/admin/";

#get required readings from pihole httpmod device
my $presence =ReadingsVal($name,'presence','unknown');
        my $state =ReadingsVal($name,'blocking','unknown');
my $totalQueries = ReadingsVal($name,'queries_total','0');
my $blocked = ReadingsVal($name,'queries_blocked','0');
my $blockedPercentage = round(ReadingsVal($name,'queries_percent_blocked','0'),1);
my $adListCount =ReadingsVal($name,'gravity_domains_being_blocked','0');


        my $docker_jn = ReadingsVal($name,'version_docker_local','unknown');
        my $ver_info = 'unknown';
        my $ftl_upd=0;
        my $core_upd=0;
        my $web_upd=0;
        my $docker_upd=0;

        my $core_local_version=ReadingsVal($name,'version_core_local_version','unknown');
        my $core_remote_version=ReadingsVal($name,'version_core_remote_version','unknown');
        my $ftl_local_version=ReadingsVal($name,'version_ftl_local_version','unknown');
        my $ftl_remote_version=ReadingsVal($name,'version_ftl_remote_version','unknown');
        my $web_local_version=ReadingsVal($name,'version_web_local_version','unknown');
        my $web_remote_version=ReadingsVal($name,'version_web_remote_version','unknown');
        my $docker_version_lokal=ReadingsVal($name,'version_docker_local','unknown');
        my $docker_version_remote=ReadingsVal($name,'version_docker_remote','unknown');

        if($docker_jn eq 'unknown' or $docker_jn eq '') {
            $ver_info = 'CORE: '.$core_local_version.' => '.$core_remote_version;
            $ver_info.= "\nFTL: ".$ftl_local_version.' => '.$ftl_remote_version;
            $ver_info.= "\nWEB: ".$web_local_version.' => '.$web_remote_version;
            if($core_local_version ne $core_remote_version) {
                $core_upd=1;
              }
            if($ftl_local_version ne $ftl_remote_version) {
                $ftl_upd=1;
              }
            if($web_local_version ne $web_remote_version) {
                $web_upd=1;
              }
          }else{
            $ver_info = "Docker: ".$docker_version_lokal.' => '.$docker_version_remote;
            if($docker_version_lokal ne $docker_version_remote) {
                $docker_upd=1;
              }
          }

        my $anyUpd=$ftl_upd+$core_upd+$web_upd+$docker_upd+0;
         
#prepare dedicated css
#hint: html of device overview is by default embedded in a <div> container
#      which has id attribute set to device's NAME
my  $styleClass ='<style>';
        $styleClass.='#'.$name.' svg {height:15px; width:15px; padding-right:1px;} ';
        $styleClass.='#'.$name.' td {padding-left:10px; padding-right:10px} ';
        $styleClass.='</style>';

#prepare images
my $imgQueries  =FW_makeImage('it_i-net@cyan');
my $imgBlocked  =FW_makeImage('time_manual_mode@red');
my $imgState    =FW_makeImage($state eq 'enabled' ? '15px-green' : '15px-red');
        my $imgPresence =FW_makeImage($presence eq 'present' ? '15px-green' : '15px-red');
        my $imgUpdate   =FW_makeImage($anyUpd > 0 ? '15px-red' : '15px-green',$ver_info);   

        if ($anyUpd > 0) {
                # fhem("setreading ".$name." available_updates 1")
                readingsSingleUpdate($defs{$name},"available_updates","1",1)
        } else {
                # fhem("setreading ".$name." available_updates 0")
                readingsSingleUpdate($defs{$name},"available_updates","0",0)
        }

#prepare disable/enable command
my $cmd='';
my $callMe='<a href="/fhem?cmd.'.$name.'=set '.$name;
if($state eq 'disabled') {
$callMe .=' enable ';
$cmd =$callMe.'">Enable</a>';
} else {
$callMe .=' disable ';
$cmd  =       $callMe.'60">1</a>';
$cmd .= ' | '.$callMe.'300">5</a>';
$cmd .= ' | '.$callMe.'600">10</a>';
$cmd .= ' | '.$callMe.'900">15</a>';
}

#finally build the html for device overview
my $ret  = $styleClass;
    $ret .= '<table border=0"><tr>';
    #if second argument of this method call is true (=1)
#then do NOT create a table header. Defaults to false (=0)
if(!$noHeader) {    
    $ret .= '<th>Presence</th>';
                        $ret .= '<th>State</th>';
    $ret .= '<th>Queries</th>';
    $ret .= '<th>Blocked</th>';
    #$ret .= '<th>Adlist</th>';
                $ret .= '<th>'.($state eq 'enabled' ? 'Disable [Minutes]':'Disabled').'</th>';
    $ret .= '<th>Upd</th>';           

    $ret .= '</tr><tr>';
}    
        $ret .= '<td><a href="'.$baseURL.'" target="_blank">'.$imgPresence.'</a></td>';
        $ret .= '<td><a href="'.$baseURL.'" target="_blank">'.$imgState.'</a></td>';
        $ret .= '<td>'.$imgQueries.' '.$totalQueries.'</td>';
        $ret .= '<td>'.$imgBlocked.' '.$blocked.' ('.$blockedPercentage.'%)'.'</td>';
        #$ret .= '<td>'.$imgAdList.' '.$adListCount.'</td>';
        $ret .= '<td>'.$cmd.'</td>';
        $ret .= '<td>'.$imgUpdate.'</td>';
        $ret .= '</tr></table>';

return $ret;
}

Viele Grüße
Jürgen
3x Sonos Play 1, 1x Sonos Arc + Sub, 1 Sonos-One, 1x Sonos Playbar
FB6690 + FB7490 mit 4x Dect 200 und 3 Dect-ULE-Thermostate,  raspberry3B+, HM Funkmodul HM-MOD-RPI-PCB, HM Klingelsensor HM-Sen-DB-PCB, HM (IP) Fensterkontakte und  Amazon Echo Dot,  piVCCU, pi OS (bookworm).

bertl

#14
Zitat von: juemuc am 22 Februar 2025, 21:46:50Es wird nun (korrekt) geprüft ob eine neue Version (inkl. Docker) vorhanden ist.

Hast du das auch getestet?

Folgende Fehler sind mir aufgefallen:
1) Du definierst zwar die Variablen (my $ftl_upd=0; my $core_upd=0; my $web_upd=0;), verwendest aber dann nur $core_upd bei den Zuweisungen.
2) Bei der if-Abrage muss auch auf leer abgefragt werden: if($docker_jn eq 'unknown' or $docker_jn eq '')
Kein Fehler aber fraglich:
Wenn du schon die Readings in Variablen schreibst, dann verwende doch anschließend die Variablen und lies diese nicht nochmals ein!
            $ver_info = 'CORE: '.ReadingsVal($name,'version_core_local_version','unknown').' => '.ReadingsVal($name,'version_core_remote_version','unknown');
            $ver_info.= "\nFTL: ".ReadingsVal($name,'version_ftl_local_version','unknown').' => '.ReadingsVal($name,'version_ftl_remote_version','unknown');
            $ver_info.= "\nWEB: ".ReadingsVal($name,'version_web_local_version','unknown').' => '.ReadingsVal($name,'version_web_remote_version','unknown');

$docker_jn und $docker_version_lokal sind ident und somit einmal überflüssig
my $docker_jn = ReadingsVal($name,'version_docker_local','unknown');
my $docker_version_lokal=ReadingsVal($name,'version_docker_local','unknown');

Gruß, Robert