🌈 Bild herunterladen, direkt aus Reading darstellen,keine Datei, parseFunction1

Begonnen von Torxgewinde, 04 September 2023, 21:29:31

Vorheriges Thema - Nächstes Thema

Torxgewinde

Hallo,
Ich wollte eine Bilddatei als Reading haben, ohne den Umweg über das Dateisystem nehmen zu müssen. HTTPMOD kann generell was herunterladen und blockiert FHEM auch nicht, allerdings kann man an den BODY der HTTP-response mit Hausmitteln als Internal heran. Ich hätte es aber gerne als Reading, und das auch direkt als BASE64 encodiert.

Damit das gelingt bemüht man eine nicht gut dokumentierte Funktion "parseFunction1" oder "parseFunktion2". Minimal implementieren kann man eine Funktion in z.B. der 99_myUtils.pm:

  ###############################################################################
  #
  #  for HTTPMOD, keep the raw body of the HTTP response as reading ".body"
  #
  ###############################################################################
  sub myParseFunction_rawResponseAsReadingDotBody {
    use LWP::UserAgent;
    use HTTP::Response;
    use MIME::Base64;

    my ($hash, $buffer) = @_;

    # Entferne die HTTP-Header, wir wollen nur den "Body", auch wenn es Binärdaten sind
    my $http_response_obj = HTTP::Response->parse($buffer);

    # Da ein Bild Binärdaten sind, konvertiere ich es nach BASE64. FHEM kam aber auch damit klar,
    # wenn man es binär belässt, ich brauche es aber eh später als BASE64
    my $body = encode_base64($http_response_obj->content);

    # Speichere den Wert als Reading ".body".
    # Der Punkt sorgt dafür, dass das Reading bei den üblichen Settings nicht angezeigt wird.
    readingsSingleUpdate($hash, ".body", $body, 1);
  }

Jetzt zum eigentlichen Download mit HTTPMOD. Wir laden hier einfach mal alle 12h die Wettervorhersage für morgen herunter:
defmod WeatherForecast HTTPMOD https://www.dwd.de/DWD/wetter/wv_allg/deutschland/film/vhs_deutschland.jpg 43200
attr WeatherForecast parseFunction1 main::myParseFunction_rawResponseAsReadingDotBody
attr WeatherForecast stateFormat {\
my $img_base64 = ReadingsVal($name, ".body", undef);;\
return "keine Antwort" if !defined($img_base64);;\
$img_base64 =~ s/\n//g;;\
return "<html><img src=\"data:image/jpg;;base64, $img_base64\"></img></html>";;\
}
attr WeatherForecast timeout 20
attr WeatherForecast webCmd reread

  • Will man ein HTML Tag als Reading parsen lassen, darf kein Zeilenumbruch im Reading sein. Dafür ist der RegEx der "\n", also Zeilenumbrüche sucht und mit nichts ersetzt, das "g" sorgt dafür, dass es mehrfach/global gemacht wird falls nötig.
  • Die Parse Funktion ist im Namensraum "main" wenn man es in myUtils gespeichert hat, deswegen "main::" vor dem Funktionsnamen.
  • Data-URIs sind eine Möglichkeit direkt aus dem Quelltext heraus Dateien einzubinden. Diese müssen dann aber BASE64 codiert sein, was die Dateigröße extrem vergrößert.

So sieht es dann aus:
Du darfst diesen Dateianhang nicht ansehen.

Warum das ganze? Ich wollte eigentlich das Wetterradar-GIF in FHEM cachen und nicht immer wieder vom DWD aus einem <iframe> herunterladen. Da FHEMWEB aber beim Ausliefern von großen Seiten (mit BASE64 aufgeblasen auf >=15MB) blockiert, habe ich von diesem Plan Abstand genommen. Ich denke die Verwendung von "parseFunction1" bedarf aber eines Codeschnipsels, falls jemand mal eine andere Idee verwirklichen möchte.

Viel Spaß!