[patch] $EVTPART issue

Begonnen von Phill, 16 Februar 2018, 11:53:46

Vorheriges Thema - Nächstes Thema

Phill

Hi, ich mal wieder.

Bezüglich dieser beiden Beitrage,
https://forum.fhem.de/index.php/topic,81942.msg740059.html#msg740059
https://forum.fhem.de/index.php/topic,84370.0.html

habe ich mir das Problem mal genauer angeschaut und folgendes festgestellt. Die Aussage $EVTPART geht nur bis 9 ist nicht ganz falsch.
Und zwar funktioniert es innerhalb Perl Codes und wahrscheinlich auch Shellcommands bei größeren Zahlen wie 10. Innerhalb von FHEM Befehlen gibt es ein Problem. Das fatale, nicht immer. Das liegt an der grundsätzlichen Unsortiertheit der HASHes. Hier $evalSpecials.
Das bedeutet, wird zuerst $EVTPART1 verarbeitet werden alle $EVTPART1* ersetzt, wird aber zuerst $EVTPART10 ausgewertet dementsprechend dann alle $EVTPART10*.
Lässt sich aber leicht durch ein sort beheben.

Gruß
Index: fhem.pl
===================================================================
--- fhem.pl (Revision 16184)
+++ fhem.pl (Arbeitskopie)
@@ -1116,7 +1116,7 @@
   $cmd =~ s/^[ \t]*//;
   if($evalSpecials) {
     map { my $n = substr($_,1); my $v = $evalSpecials->{$_};
-          $cmd =~ s/\$$n/$v/g; } keys %{$evalSpecials};
+          $cmd =~ s/\$$n/$v/g; } sort { $b cmp $a } keys %{$evalSpecials};
     $evalSpecials = undef if(!$calledFromChain || $calledFromChain ne "ACC");
   }
   my ($fn, $param) = split("[ \t][ \t]*", $cmd, 2);


[EDIT]
Lässt sich übrigens folgendermaßen veranschaulichen:

define d dummy
defmod n notify n set d $EVTPART12
trigger n a b c d e f g h i j k l m
 
Bringt manchmal m und manchmal b2.
Wohingegen
defmod n notify n {Log 1, $EVTPART12}
immer funktioniert.

Hier ist mir auch noch aufgefallen, wenn man weniger als 12 Evtparts hat, wird auch bei meinem Patch b2 im Dummy stehen. Auch etwas suboptimal.

Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

betateilchen

Da events mit mehr als 10 Teilen ziemlich selten vorkommen und auch Dein patch das Problem nicht wirklich behebt, sollte man einfach alles so lassen wie es ist.

Wer tatsächlich einen event mit so vielen Einzelteilen verarbeiten will, kann das jederzeit in seiner 99_myUtils.pm machen und dort den split einfach selbst vornehmen. Das läßt sich sowieso einfacher verarbeiten.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Phill

#2
Das ist nicht wirklich dein Ernst. Du willst mich einen Zustand bestehen lassen der einem falsche und unzuverlässige Werte zurück gibt.

Ich bin schockiert.

Natürlich behebt der Patch DAS Problem, es gibt einfach noch ein zusätzliches Problem, welches eventuell noch gar nicht aufgetreten ist. Siehe mein letzter Satz. Und ich mache mir tatsächlich Gedanken darüber ob ich das Problem nicht etwas zu ausführlich beschrieben habe.  ;D

Aber anstatt dauernd im gestern zu leben vielleicht einfach Mal selbst Gedanken zu einer Problemlösung machen. Vielleicht so.Index: fhem.pl
===================================================================
--- fhem.pl (Revision 16184)
+++ fhem.pl (Arbeitskopie)
@@ -1116,7 +1116,7 @@
   $cmd =~ s/^[ \t]*//;
   if($evalSpecials) {
     map { my $n = substr($_,1); my $v = $evalSpecials->{$_};
-          $cmd =~ s/\$$n/$v/g; } keys %{$evalSpecials};
+          $cmd =~ s/\$$n(?!\d+)/$v/g; } keys %{$evalSpecials};
     $evalSpecials = undef if(!$calledFromChain || $calledFromChain ne "ACC");
   }
   my ($fn, $param) = split("[ \t][ \t]*", $cmd, 2);

Damit dürften beide Probleme behoben sein. Noch nicht getestet, hab gerade ein schlafendes Kind auf mir und schreibe mit dem Handy.
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

rudolfkoenig

Da die zweite Variante auch nicht perfekt ist (wenn $EVENT12 stehenbleibt, hilft auch keinem) habe ich die einfacher zu verstehende erste Version kurz getestet und eingecheckt. Und wer damit immer noch Probleme hat, der moege sich via shell oder perl weiterhelfen.

betateilchen

Den Teufel mit dem Beelzebub austreiben... welch ein Quatsch.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

CoolTux

Hallo Rudi,

Warum so einen halbgarren Patch für eine Anforderung einpflegen welche einmal in hundert Jahren vor kommt. Sowas kann man nun wirklich mit split und ner myUtils machen. Niemand wird mehr wie 10 Teile eines Events einfach so im Notify verarbeiten. Sowas ist einfach Blödsinn.

Bitte überlege es Dir noch mal. Gibt genug andere Baustellen.



Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

rudolfkoenig

Weil der Patch klein und verstaendlich ist, keine Nebenwirkungen hat, und im Normalfall hilft.

frankef

#7
Hallo zusammen, auch wenn dieser Thread alt ist, beschreibt er mein Problem ganz gut.
Ich nutze das THZ Modul https://wiki.fhem.de/wiki/Tecalor_THZ_W%C3%A4rmepumpe

Dort gibt es Readings, die regelmäßig aktualisiert werden, die ich gerne als sauber formatiertes JSON über MQTT verschicke.
Ich habe das über ein notify in 86 EVTPARTs zerlegt.
Vor x Jahren hatte ich mich mühsam durch den PEARL Code gefriemelt ;-)
Mit einer alten FHEM Version lief der Code jetzt auch jahrelang zuverlässig:

define notify_publish_LWZ303i_sGlobal notify Mythz:sGlobal.* set mqtt2Mosquitto publish -r LWZ303i/Readings/{((split(":","$EVTPART0"))[0])} {"{((split(":","$EVTPART0"))[0])}":{"{((split(":","$EVTPART1"))[0])}":$EVTPART2,"{((split(":","$EVTPART3"))[0])}":$EVTPART4,"{((split(":","$EVTPART5"))[0])}":$EVTPART6,"{((split(":","$EVTPART7"))[0])}":$EVTPART8,"{((split(":","$EVTPART9"))[0])}":$EVTPART10,"{((split(":","$EVTPART11"))[0])}":$EVTPART12,"{((split(":","$EVTPART13"))[0])}":$EVTPART14,"{((split(":","$EVTPART15"))[0])}":$EVTPART16,"{((split(":","$EVTPART17"))[0])}":$EVTPART18,"{((split(":","$EVTPART19"))[0])}":$EVTPART20,"{((split(":","$EVTPART21"))[0])}":$EVTPART22,"{((split(":","$EVTPART23"))[0])}":$EVTPART24,"{((split(":","$EVTPART25"))[0])}":$EVTPART26,"{((split(":","$EVTPART27"))[0])}":$EVTPART28,"{((split(":","$EVTPART29"))[0])}":$EVTPART30,"{((split(":","$EVTPART31"))[0])}":$EVTPART32,"{((split(":","$EVTPART33"))[0])}":$EVTPART34,"{((split(":","$EVTPART35"))[0])}":$EVTPART36,"{((split(":","$EVTPART37"))[0])}":$EVTPART38,"{((split(":","$EVTPART39"))[0])}":$EVTPART40,"{((split(":","$EVTPART41"))[0])}":$EVTPART42,"{((split(":","$EVTPART43"))[0])}":$EVTPART44,"{((split(":","$EVTPART45"))[0])}":$EVTPART46,"{((split(":","$EVTPART47"))[0])}":$EVTPART48,"{((split(":","$EVTPART49"))[0])}":$EVTPART50,"{((split(":","$EVTPART51"))[0])}":$EVTPART52,"{((split(":","$EVTPART53"))[0])}":$EVTPART54,"{((split(":","$EVTPART55"))[0])}":$EVTPART56,"{((split(":","$EVTPART57"))[0])}":$EVTPART58,"{((split(":","$EVTPART59"))[0])}":$EVTPART60,"{((split(":","$EVTPART61"))[0])}":$EVTPART62,"{((split(":","$EVTPART63"))[0])}":$EVTPART64,"{((split(":","$EVTPART65"))[0])}":$EVTPART66,"{((split(":","$EVTPART67"))[0])}":$EVTPART68,"{((split(":","$EVTPART69"))[0])}":$EVTPART70,"{((split(":","$EVTPART71"))[0])}":$EVTPART72,"{((split(":","$EVTPART73"))[0])}":$EVTPART74,"{((split(":","$EVTPART75"))[0])}":$EVTPART76,"{((split(":","$EVTPART77"))[0])}":$EVTPART78,"{((split(":","$EVTPART79"))[0])}":$EVTPART80,"{((split(":","$EVTPART81"))[0])}":$EVTPART82,"{((split(":","$EVTPART83"))[0])}":$EVTPART84,"{((split(":","$EVTPART85"))[0])}":$EVTPART86}}

Nachdem ich das FHEM jetzt neu aufsetzen musste, funktioniert der PEARL Code leider nicht mehr.
Bis $EVTPART20 funktioniert es. Ab $EVTPART21 kommt Unsinn raus.

Ist 20 jetzt die neue Grenze für $EVTPARTx?

Wie kann ich alternativ die Nachricht so verarbeiten, dass hinten ein sauberes JSON rauskommt?

betateilchen

Zitat von: frankef am 13 Dezember 2022, 21:15:29
Wie kann ich alternativ die Nachricht so verarbeiten, dass hinten ein sauberes JSON rauskommt?

Mehrere Möglichkeiten...


  • FHEM hat eine interne Funktion toJSON(), die Dir vielleicht weiterhilft
  • Du kannst $EVENT in einer eigenen Funktion in beliebig viele Teile splitten


Und es heisst perl, nicht pearl.

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

frankef

Oh toJSON() kling schonmal gut.

Ich finde irgendwie kein passendes Beispiel für mich, oder kannst mir kurz mit der Syntax auf die Sprünge helfen?

Ich nehme mal ein kürzeres Beispiel aus meinem alten Code:
Das Reading ist "sHC2"
Der Inhalt ist z.B: "outsideTemp: -9.5 returnTemp: 30.2 vorlaufTemp: 32.7 heatSetTemp: 32.7 heatTemp: 32.7 stellgroesse: -0.7 seasonMode: winter hcOpMode: setback"

Das war mein altes Notify:
define notify_publish_LWZ303i_sHC2 notify Mythz:sHC2.* set mqtt2Mosquitto publish -r LWZ303i/Readings/{((split(":","$EVTPART0"))[0])} {"{((split(":","$EVTPART0"))[0])}":{"{((split(":","$EVTPART1"))[0])}":$EVTPART2,"{((split(":","$EVTPART3"))[0])}":$EVTPART4,"{((split(":","$EVTPART5"))[0])}":$EVTPART6,"{((split(":","$EVTPART7"))[0])}":$EVTPART8,"{((split(":","$EVTPART9"))[0])}":$EVTPART10,"{((split(":","$EVTPART11"))[0])}":$EVTPART12,"{((split(":","$EVTPART13"))[0])}":"$EVTPART14","{((split(":","$EVTPART15"))[0])}":"$EVTPART16"}}

Und dieses Notiy hatte bei einem Update des Readings eine solche JSON Message über MQTT versendet (auf dem Topic "LWZ303i/Readings/sHC2"):
{"sHC2":{"outsideTemp":-9.5,"returnTemp":30.2,"vorlaufTemp":32.7,"heatSetTemp":32.7,"heatTemp":32.7,"stellgroesse":-0.7,"seasonMode":"winter","hcOpMode":"setback"}}

Wie könnte ich das jetzt mit der toJSON() Funktion machen?

betateilchen

Verwende bitte code Tags in Deinen Beiträgen! Danke.

In der 99_myUtils.pm habe ich folgendes eingetragen:


sub test {
  my $text = "outsideTemp: -9.5 returnTemp: 30.2 vorlaufTemp: 32.7 heatSetTemp: 32.7 heatTemp: 32.7 stellgroesse: -0.7 seasonMode: winter hcOpMode: setback";
  my %a = split(/ /,$text);
  return toJSON \%a;
}


Dann habe ich in der FHEM Befehlszeile eingegeben:

{test}

und erhalte folgendes Ergebnis:

{"hcOpMode:":"setback","heatSetTemp:":"32.7","heatTemp:":"32.7","outsideTemp:":"-9.5","returnTemp:":"30.2","seasonMode:":"winter","stellgroesse:":"-0.7","vorlaufTemp:":"32.7"}


Was will man mehr?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

TomLee

Zitat von: betateilchen am 13 Dezember 2022, 22:50:00
Was will man mehr?

Die numerischen Werte ohne Quotes, für einen korrekten JSON.

frankef

#12
Hallo zusammen, ja genau.
Für die Weiterverarbeitung beim Empfänger der MQTT-Nachricht ist es wichtig, dass das ein korrektes JSON ist, wo numerische Werte nicht als Strings drin stehen.

Ich versuche das jetzt jeweils in einer eigenen Funktion für jedes Reading (mit unterschiedlichen Längen und Positionen der Werte).
Eine generische Funktion, die
- selbst erkennt, was ein nummerischer Wert ist
- funktioniert, egal ob im Event 5 oder 50 Werte drin stehen
- das Ergebnis als JSON wieder ins notify zurückliefert um dort weiterverarbeitet zu werden
wäre toll, aber da habe ich zu wenig Verständnis von Perl.


betateilchen

#13
Mein Codeschnipsel war doch nur die Prinzipbeschreibung.
Es ist doch gar kein Problem, sowohl die überflüssigen Doppelpunkte in den keys zu entfernen als auch die Anführungszeichen um numerische Werte.

Mein Ziel war lediglich, eine mögliche Vorgehensweise darzustellen, nicht eine fertige copy&paste Lösung zu präsentieren.

Zitat von: frankef am 14 Dezember 2022, 19:59:35
Ich versuche das jetzt jeweils in einer eigenen Funktion für jedes Reading

Das ist doch totaler bullshit. Den Namen von device und reading kann man doch einfach als Parameter an die Funktion übergeben und dann in einem Aufruf von ReadingsVal() verwenden, um den Quellwert zu lesen, den man dann verarbeiten will.

Das, was Du als Anforderung an eine "generische Funktion" forderst, bringt FHEM alles mit.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

frankef

Zitat von: betateilchen am 14 Dezember 2022, 21:03:31
Das ist doch totaler bullshit. Den Namen von device und reading kann man doch einfach als Parameter an die Funktion übergeben und dann in einem Aufruf von ReadingsVal() verwenden, um den Quellwert zu lesen, den man dann verarbeiten will.

Das, was Du als Anforderung an eine "generische Funktion" forderst, bringt FHEM alles mit.

Die Eigene Funktion für jedes Reading brauche ich nicht, weil ich device und reading drinnen brauche (das Reading steckt ja auch im $Event mit drin.), sondern weil der Inhalt der jeweiligen Readings unterschiedlich lang ist und weil manchmal auch strings statt nummerische Werte drin vorkommen und zwar an uneinheitlichen Stellen.
Um dafür etwas generisches zu bauen müsste man die Anzahl der mit Leerzeichen getrennten Einträge ermitteln (-> ok das würde ich bestimmt hinbekommen) und dann für jeden Wert (Eintrag im Array) rausbekommen ob es ein nummerischer Wert ist (-> dann nicht als String "-6.5" sondern als Wert -6.5 in das JSON packen).

Hast du vielleicht noch einen Hinweis, wie man das mit Perl-Mitteln machen würde?