FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: matze1999 am 20 Dezember 2023, 17:15:13

Titel: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 20 Dezember 2023, 17:15:13
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
Titel: Aw: Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 17:23:52
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.
Titel: Aw: Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: Felix_86 am 20 Dezember 2023, 17:25:50
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.
Titel: Aw: Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 17:36:05
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.
Titel: Aw: Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 18:05:26
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.
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 20 Dezember 2023, 18:44:20
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
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 18:49:57
Da sind lediglich die "Denkanstöße" umgesetzt, die ich in meiner ersten Antwort aufgeführt hatte.
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 20 Dezember 2023, 20:44:34
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
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 20 Dezember 2023, 21:17:43
ja, kann man:

in der o.g. sub

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

einfügen.

matze1999
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 20 Dezember 2023, 21:28:49
Hallo,

noch ein Versuch, als userreading, klappt aber nicht:

displayZiel {my $Temp = ("departures","Ziel0",""); $Temp=~s/ö/\~ef/; return $Temp}
matze1999
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 21:38:44
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.
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 20 Dezember 2023, 22:17:04
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.
Titel: Aw: [gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 21 Dezember 2023, 10:33:24
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




 
Titel: Aw: [noch nicht ganz gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 21 Dezember 2023, 11:13:02
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

Titel: Aw: [noch nicht ganz gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: betateilchen am 21 Dezember 2023, 17:13:57
s/^0$/~20/
Aber ich halte den Ansatz mit den userReadings immer noch für wenig zielführend.
Titel: Aw: [noch nicht ganz gelöst] Regex Zeichen ersetzen und userreading daraus machen
Beitrag von: matze1999 am 21 Dezember 2023, 19:24:53
Hallo,

Danke für die Tipps, ich bin mit den userReadings ganz zufrieden.

Ich nutze das jetzt so, ich trenne die einzelnen Datensätze auch noch in Linie, Ziel und Minuten, damit ich die Daten auf der Anzeige besser anordnen kann:

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]";
    my $z = "$val[($i*3)+1]";
    my $dz = "$val[($i*3)+1]";
    my $m = "$val[($i*3)+2]";
    $dz=~s/ö/\~ef/;
    $dz=~s/ü/\~f5/;
    fhem("setreading departures Linie$i $l",1);
    fhem("setreading departures Ziel$i $z",1);
    fhem("setreading departures displayZiel$i $dz",1);
    fhem("setreading departures Min$i $m",1);
  }
}

Dann werden noch zwei Sätze der anzuzeigenden Daten gebildet: eines für die Darstellung in und mit fhem und ein Satz für die Darstellung auf dem Tasmota Display.

attr departures userReadings displayMin0 {my $Temp = ReadingsVal("departures","Min0","");; $Temp=~s/^0$/~20/;; return $Temp},\
displayMin1 {my $Temp = ReadingsVal("departures","Min1","");; $Temp=~s/^0$/~20/;; return $Temp},\
displayMin2 {my $Temp = ReadingsVal("departures","Min2","");; $Temp=~s/^0$/~20/;; return $Temp},\
rssMin0 {my $Temp = ReadingsVal("departures","Min0","");; $Temp=~s/^0$//;; return $Temp},\
rssMin1 {my $Temp = ReadingsVal("departures","Min1","");; $Temp=~s/^0$//;; return $Temp},\
rssMin2 {my $Temp = ReadingsVal("departures","Min2","");; $Temp=~s/^0$//;; return $Temp}

setstate departures 65\
Luga\
0
setstate departures 2023-12-21 18:40:01 Linie0 65
setstate departures 2023-12-21 18:40:01 Linie1 65
setstate departures 2023-12-21 18:40:01 Linie2 85
setstate departures 2023-12-21 18:40:01 Min0 0
setstate departures 2023-12-21 18:40:01 Min1 11
setstate departures 2023-12-21 18:40:01 Min2 10
setstate departures 2023-12-21 18:40:01 Ziel0 Luga
setstate departures 2023-12-21 18:40:01 Ziel1 Blasewitz
setstate departures 2023-12-21 18:40:01 Ziel2 Löbtau Süd
setstate departures 2023-12-21 18:40:01 displayMin0 ~20
setstate departures 2023-12-21 18:40:01 displayMin1 11
setstate departures 2023-12-21 18:40:01 displayMin2 10
setstate departures 2023-12-21 18:40:01 displayZiel0 Luga
setstate departures 2023-12-21 18:40:01 displayZiel1 Blasewitz
setstate departures 2023-12-21 18:40:01 displayZiel2 L~efbtau S~f5d
setstate departures 2023-12-21 18:40:01 rssMin0
setstate departures 2023-12-21 18:40:01 rssMin1 11
setstate departures 2023-12-21 18:40:01 rssMin2 19

Dann werden alle Minute die Daten erneuert:

defmod departure.at at +*00:01:00 {departure3()}
attr departure.at alignTime 00:00

Und danach per doif auf das Display geschrieben, als trigger der letzte Durchgang der Schleife ("Min2") in der sub:

([MQTT2_DVES_AAC355:LWT] eq "Online" and [departures:Min2]) (
set MQTT2_DVES_AAC355 clear,
set MQTT2_DVES_AAC355 line01 Li,
set MQTT2_DVES_AAC355 line02 Ziel,
set MQTT2_DVES_AAC355 line03 Min,
set MQTT2_DVES_AAC355 line11 [departures:Linie0],
set MQTT2_DVES_AAC355 line12 [departures:displayZiel0],
set MQTT2_DVES_AAC355 line132 [departures:displayMin0],
set MQTT2_DVES_AAC355 line21 [departures:Linie1],
set MQTT2_DVES_AAC355 line22 [departures:displayZiel1],
set MQTT2_DVES_AAC355 line232 [departures:displayMin1],
set MQTT2_DVES_AAC355 line31 [departures:Linie2],
set MQTT2_DVES_AAC355 line32 [departures:displayZiel2],
set MQTT2_DVES_AAC355 line332 [departures:Min2]
)

und in ein RSS:

myrss3.png

# Schriftart festlegen
font /usr/share/fonts/truetype/msttcorefonts/arial.ttf

thalign "left"
pt 20
rgb "FFFFFF"
text 10 30 "Linie"
text 100 30 "Ziel"
thalign "right"
text 450 30 "Min"

line 10 35 450 35

rgb "FFFF00"
thalign "left"
text 10 60 ReadingsVal("departures","Linie0","")
text 100 60 ReadingsVal("departures","Ziel0","")
text 10 90 ReadingsVal("departures","Linie1","")
text 100 90 ReadingsVal("departures","Ziel1","")
text 10 120 ReadingsVal("departures","Linie2","")
text 100 120 ReadingsVal("departures","Ziel2","")


thalign "right"
text 450 60 ReadingsVal("departures","rssMin0","")
text 450 90 ReadingsVal("departures","rssMin1","")
text 450 120 ReadingsVal("departures","rssMin2","")

Das einzige, was ich gern noch machen würde ist, die Textposition der Minuten auf dem Tasmota Display in Abhängigkeit von der Stellenanzahl festzulegen, damit ich dort auch rechtsbündig anzeigen lassen kann. Da weiss ich noch nicht wie ich das genau mache.

matze1999