98_DSBMobile - Modul zur Abfrage des Vertretungsplans

Begonnen von KernSani, 06 Januar 2020, 20:22:44

Vorheriges Thema - Nächstes Thema

KernSani

Pünktlich zum Schulbeginn (zumindest für diejenigen bei denen heute noch Feiertag war  8) ) habe ich noch schnell ein Modul geschnitzt, dass den Vertretungsplan der DSBMobile-App - die an der Schule meines Sohnes verwendet wird (und wohl auch an einigen anderen Schulen zumindest in BaWü) -auszulesen.
Das Modul verwendet einige Module, die möglicherweise nicht auf eurem System vorhanden sind, die müssen ggf. über cpan installiert werden:


use IO::Compress::Gzip;   
use IO::Uncompress::Gunzip;
use MIME::Base64;
use HTML::TableExtract;



Define
define dsb DSBMobile

dann unbedingt die Attribute pflegen:
dsb_user und dsb_password sind die Logindaten der DSBMobile App
In dsb_class können die Klassen eingeschränkt werden, für die die Vertretungen abgerufen werden sollen. Ich würde das stark empfehlen, sonst werden es schnell ziemlich viele Readings. Hier kann eine Regex mitgegeben werden, zum einen um mehrere Klassen anzugeben (also sowas wie 5a|7b) aber auch, weil z.B. bei meiner Schule gerne Vertretungen (in Sport oder so) für die Klassen 5abc eingetragen werden. Das Modul würde das nicht finden, wenn als Klasse 5b gepflegt ist. Eine passende Regex könnte 5.*b lauten.

Der einzige Get-Befehl holt dann den Vertretungsplan ab. Dies ist bewusst nicht timer gesteuert, sondern sollte über ein at gemacht werden. Bei uns kommen die Updates meistens morgens um ca. 07:40 und dann nochmal nachmittags. Ich hole also einmal um 07:45 und einmal abends aktuelle Daten ab.
Über dsb_interval kann eingestellt werden, wie häufig neue Daten abgerufen werden sollen.

Das Teil legt eine Menge readings an, die nicht wirklich gut lesbar sind, daher gibt es noch eine (im ersten Schritt wirklich sehr einfach gehaltene) Funktion um einen Weblink anzulegen

define dsb_web weblink htmlCode {DSBMobile_simpleHTML("dsb")}



Ergebnis sieht dann irgendwie so aus:
Zitat2019-12-20
08c, 5 - 6. Stunde(n) --- (---) statt WELZ (D) Entfall ---
2020-01-07
08c, 1. Stunde(n) ROLK (D) statt WELZ (D) --- ---
08c, 2. Stunde(n) HUMM (D) statt WELZ (D) --- ---

Kann man natürlich schöner machen ;-) Ich könnte mir auch vorstellen ein Mapping mit einzubauen, dass die Lehrerkürzel auf echte Namen und/oder Fächerkürzel auf Fächer mappt etc... Die App enthält auch noch andere Infos (wie z.B. News, oder auch "Info des Tages" im Vertretungsplan), die derzeit noch nicht ausgelesen werden.
Lasst mich wissen, falls ihr Interesse habt, dass das Dings aufgebohrt wird.

Update 25.01.: Mittlerweile werden auch die "Infos des Tages" abgerufen (diese können im Weblink mit einem optionalem zweitem Parameter eingeblendet werden, siehe Commandref). Ausserdem werden auch die "Aushänge" abgerufen und können mittels eines zweiten Weblinks (DSBMobile_infoHTML($name)) angezeigt werden.

Update 11.02.: In Bayern ticken die Vertretungspläne anders (und möglicherweise nicht nur da). Die Readings werden nun dynamisch aufgrund der im Vertretungsplan vorhandenen Spalten abgefragt. Das macht die Ausgabe etwas schwieriger, weil das Modul ja jetzt nicht weiß, welche Readings kommen. Daher gibt es jetzt ein Attribut "dsb_outputFormat", indem die Readings als Platzhalter eingebaut werden können. In meinem Fall sieht das so aus:
%Klasse_n_% %Stunde%. Stunde %Vertreter% (%Fach%, %Raum%) statt %_Lehrer_% (%_Fach_%, %_Raum_%) %Vertr._von% %_Le.__nach% %Vertretungs-Text%
Zusätzlich gibt es auch noch das Attribut "dsb_classReading". Dieses muss gesetzt werden, falls die Spalte mit der Klassenangabe nicht "Klasse(n)" heißt (das ist aber auch in Bayern so).
Ausserdem habe ich noch ein paar kleinere Verbesserungen und Optimierungen vorgenommen:
* die "Info des Tages" jetzt auch angezeigt, wenn für den fraglichen Tag keine Vertretungen vorhanden sind
* wenn über den Get-Befehl die Daten abgeholt werden, wird nichtmehr geprüft ob neue Daten vorhanden sind, sondern es wird auf jeden Fall neu geladen, ebenso werden die Daten auf jeden Fall neu geladen (beim nächsten Timer oder manuellem Get) wenn das "dsb_class" oder "dsb_classReading" geändert wurden.
* ein/zwei Bugs ausgebaut ;-)
Update 12.02.: Kleinen Bug gefixt (Perl-Warnung im Log, wenn keine Vertretungs-Daten gefunden werden)
Update 14.02.: Noch eine Perl-Warnung gefixt, Commandref auf deutsch ergänzt und das Ganze ins SVN eingecheckt, d.h. DSBMobile steht ab morgen mit dem regulären FHEM-Update zur Verfügung.
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

mvatfhem

Hallo,

ich bin an dem Modul sehr interessiert. Leider bekomme ich es nicht zum Laufen. Die Perl Module müssten per Debian Buster repo eigentlich alle installiert sein.

Beim define des Moduls bekomme ich folgende Fehlermeldung:


2020.01.09 22:42:25 1: PERL WARNING: Backslash found where operator expected at ./FHEM/98_DSBMobile.pm line 157, near "gzip \"
2020.01.09 22:42:25 1: PERL WARNING: (Do you need to predeclare gzip?)
2020.01.09 22:42:25 1: PERL WARNING: Backslash found where operator expected at ./FHEM/98_DSBMobile.pm line 192, near "gunzip \"
2020.01.09 22:42:25 1: PERL WARNING: (Do you need to predeclare gunzip?)
2020.01.09 22:42:25 1: reload: Error:Modul 98_DSBMobile deactivated:
syntax error at ./FHEM/98_DSBMobile.pm line 157, near "gzip \"
syntax error at ./FHEM/98_DSBMobile.pm line 192, near "gunzip \"

2020.01.09 22:42:25 0: syntax error at ./FHEM/98_DSBMobile.pm line 157, near "gzip \"
syntax error at ./FHEM/98_DSBMobile.pm line 192, near "gunzip \"


Viellleicht hast Du einen Tip für mich.

Gruß Markus

amenomade

Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

mvatfhem

Danke für Deinen Tip, aber gzip ist installiert und libio-compress-perl, libperlio-gzip-perl ebenso.

KernSani

RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

amenomade

#5
Nw ist IO::Compress::Gzip Teil von libio-compress-perl, und das hat er installiert.
https://packages.debian.org/de/sid/libio-compress-perl

Das Problem scheint aber eher von den Backslashes zu kommen
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

KernSani

#6
Möglicherweise war es auch ein ganz anderes Problem... Kannst du mal die am ersten Post angehängte Datei probieren?
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

KernSani

Ich habe nochmal etwas nachgeforscht, was das "Do you need to predeclare..." verursachen könnte und predeclare gzip und gunzip jetzt. Mir ist ein Rätsel, warum das bei mir funktioniert und bei dir nicht, kann aber mit perl-Version, lib-Version und/oder Betriebssystem zusammenhängen. Auf jeden Fall wäre ich dankbar, @mvatfhem wenn du mit der Version im ersten Post nochmal testen könntest.
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

mvatfhem

Schönen guten Abend,

ich habe die andere Version von KernSani probiert. Das Problem bleibt das Gleiche, ebenso die Fehlermeldung. Die benötigten Perl Module habe ich alle per apt installiert, also nicht über cpan. OS ist Debian Buster. Wenn ich die Backslashes entferne dann wird das Module geladen. Danach habe ich dsb_user und dsb_password  eingegeben. Ein get dsb timetable lässt fhem dann aber gnadenlos abstürzen.

Gruß Markus

KernSani

Hi Markus,

wenn du die backslashes entfernst, versucht gzip ein file zu öffnen, das es nicht gibt. gzip verlangt in diesem Fall zwingend eine Referenz (also mit \). Daher ist der Absturz ohne \ vorhersehbar... Hast du die Version, die im ersten Post angehängt ist probiert, oder die, die ich gestern (bzw. heute) um 00:37:08 in einem separaten Post angehängt hatte?
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

mvatfhem

ich habe beide ausprobiert. Die Fehlermeldung von der Datei mit 11.405 Bytes.


2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Initialize redefined at ./FHEM/98_DSBMobile.pm line 48.
2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Define redefined at ./FHEM/98_DSBMobile.pm line 63.
2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Undefine redefined at ./FHEM/98_DSBMobile.pm line 85.
2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Notify redefined at ./FHEM/98_DSBMobile.pm line 91.
2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Set redefined at ./FHEM/98_DSBMobile.pm line 104.
2020.01.11 00:20:40 1: PERL WARNING: Subroutine DSBMobile_Get redefined at ./FHEM/98_DSBMobile.pm line 110.
2020.01.11 00:20:40 1: reload: Error:Modul 98_DSBMobile deactivated:
syntax error at ./FHEM/98_DSBMobile.pm line 160, near "gzip \"
syntax error at ./FHEM/98_DSBMobile.pm line 195, near "gunzip \"

2020.01.11 00:20:40 0: syntax error at ./FHEM/98_DSBMobile.pm line 160, near "gzip \"
syntax error at ./FHEM/98_DSBMobile.pm line 195, near "gunzip \"

amenomade

#11
Ich habe ein bisschen experimentiert. Es scheint, dass Perl (5.24 bei mir) ein anderes gzip nutzt (das vom system?). Warum... weiss ich (noch?) nicht.
Dieses einfache Programm bringt den gleichen Fehler:
use IO::Compress::Gzip;
use IO::Uncompress::Gunzip;
my $input = "this is my text";
my $output;
gzip \$input => \$output;
print "$output\n";

pi@pivirtual:~ $perl test.pl
Backslash found where operator expected at test.pl line 5, near "gzip \"
           (Do you need to predeclare gzip?)
Syntax error at test.pl line 5, near "gzip \"
Execution of test.pl aborted due to compilation errors.


Aber wenn man "gzip" durch "IO::Compress::Gzip::gzip" ersetzt, geht es.
Dieses Programm funktioniert:
use IO::Compress::Gzip;
use IO::Uncompress::Gunzip;
my $input = "this is my text";
my $output;
IO::Compress::Gzip::gzip \$input => \$output;
print "$output\n";


Also im Modul überall wo gzip und gunzip benutzt werden, mit entspr. Modulname explizit ergänzen, z.B.:
    gzip \$json => \$zip;
eher
    IO::Compress::Gzip::gzip \$json => \$zip;
Sollte als Workaround funktionieren

Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

KernSani

Cool. Danke. Passe ich irgendwann am Wochenende an:D


Kurz, weil mobil
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

amenomade

Komischerweise geht es auch bei mir mit:
use IO::Compress::Gzip qw(gzip);
use IO::Uncompress::Gunzip qw(gunzip);
my $input = "this is my text";
my $output;
gzip \$input => \$output;
print "$output\n";
gunzip \$output => \$input;
print "$input\n";
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

KernSani

Ich habe amenomades workaround eingebaut und ein paar kleiner Optimierungen vorgenommen.
Der HTML-Output ignoriert jetzt Tage in der Vergangenheit.
Aktuelle Version hängt am ersten Post.

RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...