[gelöst] Regex Zeichen ersetzen und userreading daraus machen

Begonnen von matze1999, 20 Dezember 2023, 17:15:13

Vorheriges Thema - Nächstes Thema

matze1999

Hallo,

ich habe folgendes Reading aus diesem Device:

define myDeparture HTTPMOD none 0
attr myDeparture devStateStyle style="text-align:left;;font-weight:bold;;"
attr myDeparture get01Name Niederwaldplatz
attr myDeparture get01Regex (\[\[.*\]\]).*
attr myDeparture get01URL https://transport.stefan-biermann.de/publictransportapi/rest/departure/FHEM?from=33000902&provider=Vvo
attr myDeparture stateFormat Niederwaldplatz
#   DEF        none 0
#   FUUID      64eb6437-f33f-214e-c553-454c20252644940b
#   Interval   0
#   MainURL   
#   ModuleVersion 4.1.16 - 4.4.2023
#   NAME       myDeparture
#   NOTIFYDEV  global
#   NR         621
#   NTFY_ORDER 50-myDeparture
#   STATE      [["65","Blasewitz","6"],["65","Luga","10"],["85","Löbtau Süd","16"],["65","Blasewitz","16"],["65","Heidenau","20"],["65","Blasewitz","26"],["65","Luga","30"],["65","Blasewitz","36"],["85","Löbtau Süd","36"],["65","Heidenau","40"]]
#   TYPE       HTTPMOD
#   CompiledRegexes:
#   READINGS:
#     2023-11-21 14:29:05   Niederwaldplatz [["65","Blasewitz","6"],["65","Luga","10"],["85","Löbtau Süd","16"],["65","Blasewitz","16"],["65","Heidenau","20"],["65","Blasewitz","26"],["65","Luga","30"],["65","Blasewitz","36"],["85","Löbtau Süd","36"],["65","Heidenau","40"]]
#
setstate myDeparture [["65","Blasewitz","6"],["65","Luga","10"],["85","Löbtau Süd","16"],["65","Blasewitz","16"],["65","Heidenau","20"],["65","Blasewitz","26"],["65","Luga","30"],["65","Blasewitz","36"],["85","Löbtau Süd","36"],["65","Heidenau","40"]]
setstate myDeparture 2023-11-21 14:29:05 Niederwaldplatz [["65","Blasewitz","6"],["65","Luga","10"],["85","Löbtau Süd","16"],["65","Blasewitz","16"],["65","Heidenau","20"],["65","Blasewitz","26"],["65","Luga","30"],["65","Blasewitz","36"],["85","Löbtau Süd","36"],["65","Heidenau","40"]]


aus diesem Reading:

Niederwaldplatz [["65","Blasewitz","6"],["65","Luga","10"],["85","Löbtau Süd","16"],["65","Blasewitz","16"],["65","Heidenau","20"],["65","Blasewitz","26"],["65","Luga","30"],["65","Blasewitz","36"],["85","Löbtau Süd","36"],["65","Heidenau","40"]]

und würde gern folgende userreadings machen (wirklich die ersten 3 "Werte" - und aus "ö" soll "ö" und aus "ü" soll ü werden):

65 Blasewitz 6 65 Luga 10 85 Löbtau Süd 16
Mit Regexp kann ich nach den Zeichen " und ] und , suchen, aber wie ersetze ich diese durch und trenne die einzelnen Zeichenfolgen ab "," ?

matze1999

betateilchen

Das ist doch schon gedanklich der falsche Ansatz.

Die Umlaute hängen an der Zeichensatzcodierung,
Die 9 Werte, die Dich interessieren, bekommst Du durch split() an den Kommas in ein array geliefert, aus dem Du dann mit map die Anführungszeichen und die eckigen Klammern entfernst.
Danach baust Du aus den 9 Werten die drei gewünschten readings zusammen.

In einer Funktion in der 99_myUtils.pm dürfte das Ganze grob geschätzt weniger als 10 Zeilen Code brauchen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Felix_86

#2
Hallo,

schonmal versucht, das Encoding auf UTF-8 zu setzen?

Zitatattr myDeparture reading01Encode UTF-8
attr myDeparture get01Encode UTF-8

Zitat von: betateilchen am 20 Dezember 2023, 17:23:52In einer Funktion in der 99_myUtils.pm dürfte das Ganze grob geschätzt weniger als 10 Zeilen Code brauchen.

Nur wenn man der Perl-Programmierung mächtig ist. Ich löse solche Dinge auch eher in FHEM (oder Bash-Scripten), da ich von Perl keinen Plan habe.
Grüße von Felix

Pi3, Raspbian 11, FHEM 6.4, ca 315 Device
SIGNALduino (TCM, TX, IT, SD_GT), CUL (EM, FS20, HMS), JeeLink (PCA301), mailcheck, echodevice, alexa, TelegramBot, Weather (OWM), DWD_OpenData, FRITZBOX, TabletUI, Calendar, Abfall, Vitoconnect, LGTV_WebOS, Nina, MQTT2

betateilchen

#3
Zitat von: Felix_86 am 20 Dezember 2023, 17:25:50Nur wenn man der Perl-Programmierung mächtig ist. Ich löse solche Dinge auch eher in FHEM (oder Bash-Scripten), da ich von Perl keinen Plan habe.

bla bla bla...
wenn Du "solche Dinge in FHEM löst", löst Du sie vermutlich auch in perl, weil FHEM komplett in perl programmiert ist...

Für die Aufgabe würde ich nichtmal ein HTTPMOD device bemühen, wenn ich eh schone eine Funktion für die Auswertung schreibe. Dann baue ich den Aufruf der URL dort auch gleich mit ein.

Übrigens: ja, man könnte da ganze auch komplett in einem Bash-Skript lösen - aber auch das muss man können.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#4
define departures dummy
sub departure3 {
  my $url = "https://transport.stefan-biermann.de/publictransportapi/rest/departure/FHEM?from=33000902&provider=Vvo";
  my $result = GetFileFromURL($url);
  my @val = split(/,/,$result);
  map {$_ =~ s/[\[\]"]//g; } @val;
  for (my $i=0;$i<3;$i++) {
    my $l = "$val[$i*3] $val[($i*3)+1] $val[($i*3)+2]";
    fhem("setreading departures departure$i $l",1);
  }
}

{departure3()}
in die FHEM Befehlszeile eingegeben, liefert im device "departures" die drei readings:

setstate departures 2023-12-20 18:02:15 departure0 85 Löbtau Süd 3
setstate departures 2023-12-20 18:02:15 departure1 65 Blasewitz 4
setstate departures 2023-12-20 18:02:15 departure2 65 Heidenau 7

Den Aufruf von departure3() kann man natürlich auch beispielsweise in ein at packen, um die Werte regelmäßig zu aktualisieren.
Die Umlaute werden bei mir übrigens korrekt in die readings geschrieben, deshalb habe ich keine Konvertierung eingebaut.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

matze1999

Hallo,

@betateilchen, Danke, das nimmt mir Arbeit ab, aber eigentlich wollte ich das irgendwie selbst machen  :( , mit ein paar Denkanstößen.
Aber jetzt zerlege ich das mal und versuche es an anderer Stelle zu nutzen.

Schöne Weihnachten!

matze1999

betateilchen

Da sind lediglich die "Denkanstöße" umgesetzt, die ich in meiner ersten Antwort aufgeführt hatte.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

matze1999

Hallo,

noch ein kleines Problem: das Tasmota Display stellt die Umlaute (öüä) nicht dar, diese müssen als EPDFont übertragen werden

~ef -> ö
~f5 -> ü

kann man in den readings auch z.B. alle ö gegen ~ef austauschen?

matze1999

matze1999

ja, kann man:

in der o.g. sub

$z=~s/ö/\~ef/;
$z=~s/ü/\~f5/;

einfügen.

matze1999

matze1999

Hallo,

noch ein Versuch, als userreading, klappt aber nicht:

displayZiel {my $Temp = ("departures","Ziel0",""); $Temp=~s/ö/\~ef/; return $Temp}
matze1999

betateilchen

#10
Zitat von: matze1999 am 20 Dezember 2023, 21:17:43ja, kann man:
in der o.g. sub
$z=~s/ö/\~ef/;
$z=~s/ü/\~f5/;
einfügen.

ja, kann man so machen, wenn es nur um zwei Werte geht, die man ersetzen möchte.
Da es insgesamt im Deutschen aber 7 Umlaute gibt, würde man einen anderen Weg wählen, wenn man alle Umlaute ersetzen müsste.

Warum bist Du eigentlich so obergeil auf userReadings?
Masochistisch veranlagt?

my $Temp = ("departures","Ziel0","")
Da fehlt vermutlich ein ReadingsVal vor der Klammer, ansonsten macht das Konstrukt so keinen Sinn.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Wenn es unbedingt im HTTPMOD sein muss, dann kann man auch zwei Ansätze kombinieren.

defmod myDeparture HTTPMOD none 0
attr myDeparture get01Name Niederwaldplatz
attr myDeparture get01OExpr {departure3($val);;return $val}
attr myDeparture get01Regex (\[\[.*\]\]).*
attr myDeparture get01URL https://transport.stefan-biermann.de/publictransportapi/rest/departure/FHEM?from=33000902&provider=Vvo

sub departure3 {
  my $result = shift;
  my @val = split(/,/,$result);
  map {$_ =~ s/[\[\]"]//g; } @val;
  for (my $i=0;$i<3;$i++) {
    my $l = "$val[$i*3] $val[($i*3)+1] $val[($i*3)+2]";
    fhem("sleep 0.1; setreading myDeparture departure$i $l",1);
  }
}

In die Funktion kann man natürlich auch noch weitere Ersetzungen einbauen.

Aber userReadings braucht man auch so nicht.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

matze1999

#12
Hallo,

HTTPMOD habe ich verworfen, ich nehme die Lösung von @betateilchen mit einem minütlichen at.

Da ich für Fhem und für das Tasmota Display unterschiedliche Varianten benötige, versuche ich das Austauschen der Umlaute über userreadings.

Dabei habe ich aber Probleme:

wie kann ich mehrere Umlaute auf einmal tauschen, das funktioniert (das userReading zweimal manipulieren) nicht:

displayZiel0 {my $Temp = ReadingsVal("departures","Ziel0",""); $Temp=~s/ö/\~ef/|s/ü/\~f5/; return $Temp}

weiterhin würde ich die "0" bei Minuten gern durch "" ersetzen, das gelingt mir irgendwie nicht.

das bringt nur "li" auf dem Display:

displayMin0 {my $Temp = ReadingsVal("departures","Min0","");; $Temp=~s/0//;; return $Temp}
obwohl im Device das steht:

setstate departures 2023-12-21 10:30:03 displayMin0
setstate departures 2023-12-21 10:30:03 displayMin1 9
setstate departures 2023-12-21 09:17:02 displayMin2 9

evtl. muss ich dass durch ein Leerzeichen ersetzen?

Dann kommt noch das Problem, dass jede "0" ersetzt wird, auch die in "10", ich muss also das Ersetzen auf einstellige Zahlen beschränken.

matze1999




 

matze1999

ein Problem gelöst, das Tasmota Display kann ich mit einem Leerzeichen "~20" anstelle der "0" beschreiben:

displayMin0 {my $Temp = ReadingsVal("departures","Min0",""); $Temp=~s/0/\~20/; return $Temp}
allerdings bleibt das Problem, dass auch eine "0" in zweistelligen Zahlen ersetzt wird (10 -> 1).

matze1999


betateilchen

s/^0$/~20/
Aber ich halte den Ansatz mit den userReadings immer noch für wenig zielführend.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!