[patch] $EVTPART issue

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

Vorheriges Thema - Nächstes Thema

frankef

Zitat von: betateilchen am 13 Dezember 2022, 22:50:00
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?

Hier ist mit noch aufgefallen, dass dei toJSON-Funktion die Werte neu sortiert. Kann man das vermeiden?

betateilchen

#16
Zitat von: frankef am 14 Dezember 2022, 21:45:20
Hier ist mit noch aufgefallen, dass dei toJSON-Funktion die Werte neu sortiert.

Falsch.
Das macht nicht die toJSON Funktion, sondern das ist ein Verhalten des perl Datentyps "hash". Die Elementreihenfolge in einem hash ist mehr oder weniger willkürlich. Deshalb greift man ja in einem hash über den key auf einen bestimmten Wert zu und nicht über seine Position (das wäre in einem array so)

Zitat von: frankef am 14 Dezember 2022, 21:37:20
Hast du vielleicht noch einen Hinweis, wie man das mit Perl-Mitteln machen würde?

Natürlich... simpelstes perl...


use JSON;
use Scalar::Util qw/looks_like_number/;

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";
     $text =~ s/://g;
  my @a = split (/ /,$text);
  map {$_ += 0 if looks_like_number($_)} @a;
  my %a = @a;
  return encode_json \%a;
}


Ergebnis:

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

Es ist übrigens dieser Funktion schnurzpiepegal, wieviele Werte in Deinem Quellstring stecken und wie lang sie sind...


--
-----------------------
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:54:04

Natürlich... simpelstes perl...


use JSON;
use Scalar::Util qw/looks_like_number/;

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";
     $text =~ s/://g;
  my @a = split (/ /,$text);
  map {$_ += 0 if looks_like_number($_)} @a;
  my %a = @a;
  return encode_json \%a;
}


--

Super, vielen vielen Dank.
Damit habe ich mir jetzt eine generische Funktion "ReadingtoJSON" gebaut, die meine Werte wieder wie vorher als JSON einpackt.

Ich rufe sie innerhalb des Notify auf (hier für das Reading sGlobal), welches die MQTT Nachricht auf dem richtigen Topic versendet:


define notify_publish_LWZ303i_sGlobal_TEST notify Mythz:sGlobal.* set mqtt2Mosquitto publish -r LWZ303i/Readings/sGlobal_TEST {(ReadingtoJSON("Mythz","sGlobal"))}


Die Funtion sieht so aus:

use JSON;
use Scalar::Util qw/looks_like_number/;

sub ReadingtoJSON($$) {
  my ($device, $reading) = @_;
  my $text = ReadingsVal("$device","$reading","");
     $text =~ s/://g;
  my @a = split (/ /,$text);
  map {$_ += 0 if looks_like_number($_)} @a;
  my %a = @a;
  my $text1 = encode_json \%a;
  return "{"."\"".$reading."\":".$text1."}";
}


Das ist sicher nicht perfekt, aber es funktioniert erstmal für mich - soweit ich das gerade überblicke.
Nochmal vielen Dank!

PS: Ich habe ne Menge an Perl noch nicht verstanden und kratze an der Oberfläche. Ich vermute Perl und ich werden leider keine Freunde ;-)

frankef

Doch noch eine Frage:

Dass die Reihenfolge der Werte im Hash (und dann auch in der MQTT Nachricht) zufällig ist, erschwert das debugging später.
Kann man die noch sortieren, damit sie wenigstens immer in der gleich Reihenfolge kommen (auch wenn die unterschiedlich zur Reihenfolge im Reading sein mag)?

betateilchen

-----------------------
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: frankef am 14 Dezember 2022, 23:13:48


use JSON;
use Scalar::Util qw/looks_like_number/;

sub ReadingtoJSON($$) {
  my ($device, $reading) = @_;
  my $text = ReadingsVal("$device","$reading","");
     $text =~ s/://g;
  my @a = split (/ /,$text);
  map {$_ += 0 if looks_like_number($_)} @a;
  my %a = @a;
  my $text1 = encode_json \%a;
  return "{"."\"".$reading."\":".$text1."}";
}


Das ist sicher nicht perfekt, aber es funktioniert erstmal für mich - soweit ich das gerade überblicke.
Nochmal vielen Dank!

PS: Ich habe ne Menge an Perl noch nicht verstanden und kratze an der Oberfläche. Ich vermute Perl und ich werden leider keine Freunde ;-)

Die Funktion klappt bei den meisten Readings. Allerdings nicht bei sFan. Das liegt vermutlich daran, dass dieses Reading eine führende null hat.

Ich spreche mal immi an, ich vermute das ist ein Versehen.


Beta-User

#21
Hier noch was aus der RHASSPY-Küche, Rhasspy ist auch etwas wählerisch, was das JSON-Format angeht:

sub _toCleanJSON {
    my $data = shift // return;
   
    return $data if ref $data ne 'HASH';
    my $json = toJSON($data);
   
    $json =~ s{(":"(true|false|null)")}{": $2}gxms;
    $json =~ s{":"}{": "}gxms;
    $json =~ s{("enable": (?:false|true)),("intentId": "[^"]+")}{$2,$1}gms;
    return $json;
}


Übergeben wird ein HASH-Type-Datenelement, die Rückgabe müßte sortiert sein, soweit ich mich entsinne, und wenn man die letzte spezielle rauswirft, müßte das auch den Anforderungen genügen... (toJSON handhabt Ziffern korrekt).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors