Über das Systemkommando `(echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337`
kann ich mir von meinem Wechselrichter folgenden Status anzeigen lassen.
Command-line interface to the iec61850 data model
Usage:
<empty> - shows all logical nodes
<node> - shows given logical / data node
detail <node> - detailed view of logical / data node
<node>=<val> - assign a value to the given data node
loop <node> <n> <d>- show value of the node <n> times, waiting <d>msec
r - repeat last command
exit - close connection
help - show this message
[Read] SwDER/CPOL1
- SwDER/CPOL1.Mod.[ stVal = 1 (on), ctlVal = 1 (on) ]
- SwDER/CPOL1.Health.stVal = 1 (Ok)
- SwDER/CPOL1.Beh.stVal = 1 (on)
- SwDER/CPOL1.Wmax.setMag.f = 0.0
- SwDER/CPOL1.Wmin.setMag.f = 0.0
- SwDER/CPOL1.Wchrg.setMag.f = 0.0
- SwDER/CPOL1.SRLPosW.setMag.f = 0.0
- SwDER/CPOL1.SRLNegW.setMag.f = 0.0
- SwDER/CPOL1.Whome.setMag.f = 0.0
- SwDER/CPOL1.WPV.setMag.f = 0.0
- SwDER/CPOL1.Wtol.setMag.f = 0.0
- SwDER/CPOL1.PhsAlm.[ stVal = 0, ctlVal = 0 ]
- SwDER/CPOL1.ConnAlm.[ stVal = 0, ctlVal = 0 ]
- SwDER/CPOL1.PRLposDuration.setVal = 0
- SwDER/CPOL1.PRLnegDuration.setVal = 0
- SwDER/CPOL1.PRLposStart.setVal = 0
- SwDER/CPOL1.PRLnegStart.setVal = 0
- SwDER/CPOL1.PRLposAddW.setMag.f = 0.0
- SwDER/CPOL1.PRLnegAddW.setMag.f = 0.0
- SwDER/CPOL1.OffsetDuration.setVal = 1422692866
- SwDER/CPOL1.OffsetStart.setVal = 0
- SwDER/CPOL1.SRLDur.setVal = 0
- SwDER/CPOL1.SRLStrt.setVal = 0
- SwDER/CPOL1.ClrPosMinHz.setMag.f = 0.0
- SwDER/CPOL1.ClrPosMaxHz.setMag.f = 0.0
- SwDER/CPOL1.ClrPosStart.setVal = 0
- SwDER/CPOL1.ClrNegMinHz.setMag.f = 0.0
- SwDER/CPOL1.ClrNegMaxHz.setMag.f = 0.0
- SwDER/CPOL1.ClrNegStart.setVal = 0
- SwDER/CPOL1.ErrCode.stVal = 0
- SwDER/CPOL1.WarnCode.stVal = 0
Disconnected by client request
Ich suche nun nach einem Weg diese Statusinformationen in FHEM zu verarbeiten.
Also z.B. die Statusinformation aus dem Register SwDER/CPOL1.WarnCode.stVal
Habt ihr soetwas bei euch bereits gelöst oder eine Idee dazu?
Gruß Manuel
Hallo Manuel,
so als Idee, auf System Ebene:
dat=($(echo "- SwDER/CPOL1.WarnCode.stVal = 0"|grep "WarnCode"))
echo ${dat[-1]}
Also Dein Code:
dat=($((echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337|grep "WarnCode"))
echo ${dat[-1]}
Willst Du nur den einen Wert?
Ich hätte Bedenken, das die Abfrage blockiert. Man könnte ein Script auf System laufen lassen und die Werte über HTTP nach FHEM schreiben.
Gruß Otto
Hallo Otto,
freut mich dass du hier Rückmeldung gibst - ich habe bereits einige einer Blog Einträge abgespeichert.
Ich möchte mehrere Werte auslesen... ~10-20 aus verschiedenen dieser Abfragen. Wie könnte ein Http-Skript aufgebaut werden?
Gruß Manuel
Auf die Schnelle noch die Idee:
Du definierst einen Dummy in FHEM.
Hier (https://github.com/heinz-otto/fhemcl)gibt es ein Script mit dem man in diesen Dummy mit setreading Werte schreiben kann.
Anstatt echo ${dat[-1]} schreibst Du dann
bash fhemcl.sh 8083 "setreading MyDummy WarnCode ${dat[-1]}
Jetzt musst Du die Sache mit grep verfeinern (z.B. auf SwDER greppen) den ${dat[-2]} nochmal splitten z.B. am Punkt und dann ein Element daraus als Readingname nehmen und in einer Schleife nach FHEM schaffen.
Gruß Otto
Hallo Otto,
wenn ich das richtig verstanden habe geht dein zweiter Ansatz geht davon aus, dass auf dem entfernten Rechner fhem läuft - oder?
Das ist nicht der fall und auch wenn es möglich wäre, sollte die Grundkonfiguration nicht verändert werden.
Gruß Manuel
Moin Manuel,
bisher hast Du nichts von einem entfernten Rechner gesagt. Ich nahm an Deine Abfragezeile hattest Du sogar aus FHEM heraus gemacht?
In meinem Ansatz wird nichts verändert, es ist einfach ein Script was läuft. So wie es dargestellt ist auf der gleichen Maschine wo FHEM läuft. Du kannst als Parameter auch die komplette url des FHEM Servers angeben.
Deine Abfrage geht doch remote an einen anderen Rechner (netcat) an dem Gedanken habe ich nichts geändert.
Mir ist nicht klar ob Du mehrere unterschiedliche Abfragen machen willst oder bloß den ganzen Rattenschwanz - SwDER/CPOL1. ... als Readings haben willst.
Mir ist nicht klar
- wie oft Du das abfragen willst.
- wie lange die Abfrage dauert
- in welcher Programmiersprache Du Dich wohler fühlst
Deswegen nur Ideen. :)
Gruß Otto
Ich habe irgendwann mal gelernt das große Problem nicht lange zu betrachten sondern in kleine Teile aufzuteilen und diese für sich zu lösen.
Was haben wir bisher:
dat=($((echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337|grep "WarnCode"))
echo "WarnCode ${dat[-1]}"
Gibt doch bei der aktuellen Abfrage den aktuellen WarnCode aus - oder?
So holst Du Dir mein Script (auf der Maschine wo FHEM läuft)
wget -O fhemcl.sh https://raw.githubusercontent.com/heinz-otto/fhemcl/master/fhemcl.sh
So kannst Du einen Dummy erzeugen
bash fhemcl.sh 8083 "define MyDummy dummy
So setzt Du deinen WarnCode als Reading
dat=($((echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337|grep "WarnCode"))
bash fhemcl.sh 8083 "setreading MyDummy WarnCode ${dat[-1]}
Kannst Du das nachvollziehen? Passt das fürs Erste?
Was brauchen wir noch?
Die Filterung der richtigen Zeilen für die zukünftigen Readings.
Die Extraktion des Readingsnamens aus der Zeile (den Zeilen) SwDER/CPOL1.PRLposDuration.setVal
Eine Schleife über über alle Readings um die Werte nach FHEM zu schreiben.
Einen Trigger und entsprechenden Aufruf dieses Scripts.
Hallo Otto,
das hat mich schon einen großen Schritt weiter gebracht.
Ich habe nun den Befehl in die 99_myUtils.pm gepackt welche ich später zyklisch aufrufen will.
sub
CMD_CPOL1()
{
my @response = `(echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337 | grep "WarnCode"`;
Log(3,"WarnCode: @response");
fhem("setreading SwDER_CPOL1 WarnCode $response[-1]");
}
dann habe ich ein dummy "SwDER_CPOL1" mit einem userReading "WarnCode" definiert
Internals:
CFGFN
FUUID 5e9c6140-f33f-295f-2ab2-806265940aa47e12
NAME SwDER_CPOL1
NR 389
STATE ???
TYPE dummy
READINGS:
2020-04-19 16:43:49 WarnCode - SwDER/CPOL1.WarnCode.stVal = 0
Attributes:
room 6_CMD
userReadings WarnCode
Da ich das ganze letztlich auf mehrere Readings aufsplitten möchte ist was wahrscheinlich nötig erst den gesamten Inhalt zu speichern und diesen dann irgendwie nachträglich zu zerlegen. Auch ist es noch nicht ganz rund da ich eigentlich nur den Wert 0 ablegen will.
Das Array enthält wie gewünscht die ganze Zeile - der Zugriff auf das Element [-1] gibt aber auch die gesamte Zeile aus.
Dein Vorschlag auf Kommandozeilen level bringt genau das gesuchte Ergebnis.
dat=($((echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337|grep "WarnCode"))
echo "WarnCode ${dat[-1]}"
WarnCode 0
So bekommst Du eventuell nur die 0 (noch nicht getestet)
sub
CMD_CPOL1()
{
my @response = split (" ",`(echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337 | grep "WarnCode"`);
Log(3,"WarnCode: @response");
fhem("setreading SwDER_CPOL1 WarnCode $response[-1]");
}
Hallo Otto,
korrekt - das klappt so wird der String aufgeteilt und ich bekomme die "0" als Reading.
Auch wenn das nun grudsätzlich funktioniert möchte ich nicht immer x-mal die kompl.
Daten lesen um ein Register zu lesen.
Ich will dich nicht überstrapazieren - vielleicht kannst du aber noch grob skizzieren wie man das nun umbauen muss um die Daten zunächst komplett zu lesen und dann zeilenweise die Register Inhalte auslesen kann.
Danke
Manuel
Geduld Manuel, ich bin dabei :)
Mal sehen ob das tut ???
Das ist jetzt entsprechenden deinem ersten Post, die andere Ausgabe (PM) sah anders aus. Du musst den String ev. anpassen:
grep {/SwDER\/CPOL1\./}
Das ist der Teil der Ausgabe der halbwegs ordentliche "readings" enthält. Der / und der . muss escaped werden!
sub
CMD_CPOL1()
{
my @response = `(echo "SwDER/CPOL1";echo "exit";) | netcat 192.168.0.222 1337 "`;
@response= grep {/SwDER\/CPOL1\./} @response;
foreach ( @response ) {
my @line = split(" ",$_);
my @reading = split(/\./,$line[1]);
Log(3," $reading[1] $line[-1]");
fhem("setreading SwDER_CPOL1 $reading[1] $line[-1]");
}
}
Mein Test lief mit dieser Datei (ich habe ja Deine Ausgabe nicht) auf Systemebene: perl test.pl
test.pl
#!/usr/bin/perl -w
use strict;
my $string = <<"EOT";
[Read] SwDER/CPOL1
- SwDER/CPOL1.Mod.[ stVal = 1 (on), ctlVal = 1 (on) ]
- SwDER/CPOL1.Health.stVal = 1 (Ok)
- SwDER/CPOL1.Beh.stVal = 1 (on)
- SwDER/CPOL1.Wmax.setMag.f = 0.0
- SwDER/CPOL1.Wmin.setMag.f = 0.0
- SwDER/CPOL1.Wchrg.setMag.f = 0.0
- SwDER/CPOL1.SRLPosW.setMag.f = 0.0
- SwDER/CPOL1.SRLNegW.setMag.f = 0.0
- SwDER/CPOL1.Whome.setMag.f = 0.0
- SwDER/CPOL1.WPV.setMag.f = 0.0
- SwDER/CPOL1.Wtol.setMag.f = 0.0
- SwDER/CPOL1.PhsAlm.[ stVal = 0, ctlVal = 0 ]
- SwDER/CPOL1.ConnAlm.[ stVal = 0, ctlVal = 0 ]
- SwDER/CPOL1.PRLposDuration.setVal = 0
- SwDER/CPOL1.PRLnegDuration.setVal = 0
- SwDER/CPOL1.PRLposStart.setVal = 0
- SwDER/CPOL1.PRLnegStart.setVal = 0
- SwDER/CPOL1.PRLposAddW.setMag.f = 0.0
- SwDER/CPOL1.PRLnegAddW.setMag.f = 0.0
- SwDER/CPOL1.OffsetDuration.setVal = 1422692866
- SwDER/CPOL1.OffsetStart.setVal = 0
- SwDER/CPOL1.SRLDur.setVal = 0
- SwDER/CPOL1.SRLStrt.setVal = 0
- SwDER/CPOL1.ClrPosMinHz.setMag.f = 0.0
- SwDER/CPOL1.ClrPosMaxHz.setMag.f = 0.0
- SwDER/CPOL1.ClrPosStart.setVal = 0
- SwDER/CPOL1.ClrNegMinHz.setMag.f = 0.0
- SwDER/CPOL1.ClrNegMaxHz.setMag.f = 0.0
- SwDER/CPOL1.ClrNegStart.setVal = 0
- SwDER/CPOL1.ErrCode.stVal = 0
- SwDER/CPOL1.WarnCode.stVal = 0
Disconnected by client request
EOT
my @array = split("\n", $string);
#print $array[-3];
@array = grep {/SwDER\/CPOL1\./} @array;
foreach ( @array ) {
#print $_."\n";
my @line = split(" ",$_);
#print $line[1]."\n";
my @reading = split(/\./,$line[1]);
print $reading[1]." ".$line[-1]."\n";
}
Gruß Otto
Hallo Otto,
danke das passt fast perfekt - das fine-tuning bekomme ich bestimmt hin.
1000 Dank für deine Zeit !!
Schönen Abend
Moin,
das freut mich! Du hast da eben ein paar Zeilen, die passen nicht in das einfache Schema. Entweder die sind nicht wichtig, dann ist auch gut, oder Du musst dafür ein paar Sonderlocken einführen. Ist sicher mit ein paar speziellen Abfragen analog zum jetzigen zu machen. Da wird die sub eben etwas länger. Du musst unter Umständen aufpassen, dass es Dir FHEM nicht blockiert.
Da wäre aus meiner Sicht die Abfrage mit netcat kritisch. Die läuft zwar offenbar schnell, aber dort kann es mal im Netzwerk klemmen. Da sollte man vielleicht nochmal nachdenken, das man das von FHEM nur triggert und die Daten dann von "außen" kommen und FHEM nicht die ganze Zeit wartet. Da wäre dann vielleicht wieder die Datenübergabe mit meinem Script fhemcl wieder eine Möglichkeit.
Also: FHEM startet non blocking (wartet nicht) ein Script, in dem Script werden die Daten geholt und an FHEM übergeben.
Erstmal nur so als Idee.
Gruß Otto