[Gelöst]:XML-Datei nach FHEM Readings

Begonnen von Klaus Rubik, 19 März 2014, 18:01:57

Vorheriges Thema - Nächstes Thema

Klaus Rubik

Hallo,

kennt jemand eine Möglichkeit wie man mit einfachen Mitteln (ohne Programmierkenntisse  :)) eine von einem Webserver bereitgestellte XML-Datei parsen kann und die Werte FHEM als Readings in einem Device bereitstellt?

Beispiel der XML-Datei:
<?xml version="1.0" encoding="UTF-8" ?>
<GetValues>
<Version>1.2.51</Version>
<Uptime>0d 00:08:37</Uptime>
<Copyright>Nico Treffkorn,Magdeburg</Copyright>
<CurrentDateTime>19.03.2014 17:41:06</CurrentDateTime>
<LastEDLReceive>19.03.2014 17:41:06</LastEDLReceive>
<LastUDPReceive>00.00.0000 00:00:00</LastUDPReceive>
<LastWallboxControl>00.00.0000 00:00:00</LastWallboxControl>
<LastSQLStatement>00.00.0000 00:00:00</LastSQLStatement>
<LastKNXBroadcast>00.00.0000 00:00:00</LastKNXBroadcast>
<LastStorageReceive>00.00.0000 00:00:00</LastStorageReceive>
<SmartMeter>
<Using>1</Using>
<Type>SMA</Type>
<Serial>1900204007</Serial>
<TimeStamp>525987</TimeStamp>
<ActualPower>861</ActualPower>
<RealPower>
<L1>213</L1>
<L2>371</L2>
<L3>277</L3>
</RealPower>
<PowerFactor>
<total>0.916</total>
<L1>0.845</L1>
<L2>0.728</L2>
<L3>0.934</L3>
</PowerFactor>
<Voltage>
<L1>227</L1>
<L2>227</L2>
<L3>227</L3>
</Voltage>
<mAmpere>
<L1>1111</L1>
<L2>2245</L2>
<L3>1307</L3>
</mAmpere>
<MeterReadings>
<Consumption>180.0</Consumption>
<Surplus>160.6</Surplus>
</MeterReadings>
</SmartMeter>
<Infrastructure>
<MainFuses>
<Current>35000</Current>
<SafetyDistance>2000</SafetyDistance>
</MainFuses>
</Infrastructure>
<KNX>
<Using>0</Using>
</KNX>
<MySQL>
<Using>0</Using>
</MySQL>
<EV>
<Using>0</Using>
</EV>
<StorageSystem>
<Using>0</Using>
</StorageSystem>
</GetValues>


Ich habe schon mit HTTPMOD gespielt, habe aber keinen Plan, wie ich die einzelnen REGEXPs definieren soll.

Vielen Dank für jegliche Unterstützung

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

mit dem Perl Modul XML::Parser

Schau Dir mal 98_openweathermap.pm an, da habe ich sowas eingebaut. In 55_GDS glaub auch.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Klaus Rubik

Zitat von: betateilchen am 19 März 2014, 18:09:45
Schau Dir mal 98_openweathermap.pm an, da habe ich sowas eingebaut. In 55_GDS glaub auch.

Hallo Betateilchen,

danke für den raschen Tipp, aber wie gesagt ohne Programmierkenntnisse wird das schwierig  :'(

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

so schwer ist das nicht.

1. Einen Dummy namens xmldummy anlegen

define xmldummy dummy

2. Folgenden Code in Deine 99_myUtils.pm kopieren



sub xmlTest {

use XML::Simple qw(:strict);

my $xmltext = '<?xml version="1.0" encoding="UTF-8" ?>
<GetValues>
<Version>1.2.51</Version>
<Uptime>0d 00:08:37</Uptime>
<Copyright>Nico Treffkorn,Magdeburg</Copyright>
<CurrentDateTime>19.03.2014 17:41:06</CurrentDateTime>
<LastEDLReceive>19.03.2014 17:41:06</LastEDLReceive>
<LastUDPReceive>00.00.0000 00:00:00</LastUDPReceive>
<LastWallboxControl>00.00.0000 00:00:00</LastWallboxControl>
<LastSQLStatement>00.00.0000 00:00:00</LastSQLStatement>
<LastKNXBroadcast>00.00.0000 00:00:00</LastKNXBroadcast>
<LastStorageReceive>00.00.0000 00:00:00</LastStorageReceive>
<SmartMeter>
<Using>1</Using>
<Type>SMA</Type>
<Serial>1900204007</Serial>
<TimeStamp>525987</TimeStamp>
<ActualPower>861</ActualPower>
<RealPower>
<L1>213</L1>
<L2>371</L2>
<L3>277</L3>
</RealPower>
<PowerFactor>
<total>0.916</total>
<L1>0.845</L1>
<L2>0.728</L2>
<L3>0.934</L3>
</PowerFactor>
<Voltage>
<L1>227</L1>
<L2>227</L2>
<L3>227</L3>
</Voltage>
<mAmpere>
<L1>1111</L1>
<L2>2245</L2>
<L3>1307</L3>
</mAmpere>
<MeterReadings>
<Consumption>180.0</Consumption>
<Surplus>160.6</Surplus>
</MeterReadings>
</SmartMeter>
<Infrastructure>
<MainFuses>
<Current>35000</Current>
<SafetyDistance>2000</SafetyDistance>
</MainFuses>
</Infrastructure>
<KNX>
<Using>0</Using>
</KNX>
<MySQL>
<Using>0</Using>
</MySQL>
<EV>
<Using>0</Using>
</EV>
<StorageSystem>
<Using>0</Using>
</StorageSystem>
</GetValues>
';

my $ref = XMLin($xmltext, KeyAttr => { }, ForceArray => [ ]);


setreading ('xmldummy', 'CurrentDateTime', $ref->{CurrentDateTime});

return;
}



3. Die Funktion mit {xmlTest} in der Befehlszeile ausführen

Danach sollte der in 1.) definierte Dummy ein neues Reading "CurrentDateTime" haben, das den Wert aus dem vorgegebenen XML-Inhalt besitzt.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Klaus Rubik

Hallo Betateilchen,

schon mal Danke für die Informationen, kannst Du mir bitte auch noch die Codezeile sagen, welche ich im Perl-Script einbauen muss, damit die Daten beim Aufruf der Funktion geladen werden? Die Webseite ist

http://x.x.x.x:18001/xml

Vielen Dank, den Rest müsste ich dann hinbekommen :)

Viele Grüße

klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

Moin,

den setreading Befehl in meinem letzten Beispiel musst Du wahrscheinlich noch in ein fhem() packen, also fhem("setreading(...)")

Zu Deiner anderen Frage:

my $xmltext = GetFileFromUrl("http://...:18001/xml");

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

Klaus Rubik

Hallo Betateilchen,

vielen Dank für deine Geduld!! Aktuell sieht mein Code in der 99_myUtils.pm wie folgt aus:

######## Auslesen SMA Energy Meter #################


sub EnergyMeter {

use XML::Simple qw(:strict);


my $xmltext = GetFileFromURL("http://192.168.0.25:18001/xml");

my $ref = XMLin($xmltext, KeyAttr => { }, ForceArray => [ ]);


fhem("setreading ('EnergyMeter', 'CurrentDateTime', $ref->{CurrentDateTime})");

return;
}


Ich habe als Dummydevice "EnegyMeter" angelegt.  Jedoch kommt jetzt nach dem Aufruf in der FHEM Komandozeile folgende Fehlermeldung im Logfile:

2014.03.20 10:30:06 1: devspec2array ('EnergyMeter',: Unmatched ( in regex; marked by <-- HERE in m/^( <-- HERE ('EnergyMeter')$/ at ./fhem.pl line 967.

Und schon steh ich wieder voll auf dem Schlauch  :'(

Viele Grüße

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

sorry, mein Fehler. Die runden Klammern musst Du bei setreading weglassen.

fhem("setreading 'EnergyMeter', 'CurrentDateTime', $ref->{CurrentDateTime}");

Aber mal ehrlich: Syntax von solchen Befehlen rauszubekommen, könntest Du wahrscheinlich auch selbst schaffen ;)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Klaus Rubik

Hallo Betateilchen,

vielen Dank für deine Unterstützung. Hier ist nun der Code für die my_Utils.pm:

######## Auslesen SMA Energy Meter und zuweisen an Solar-Readings #################


sub UpdateEnergyMeter {

use XML::Simple qw(:strict);


my $xmltext = GetFileFromURL("http://192.168.0.25:18001/xml");

my $ref = XMLin($xmltext, KeyAttr => { }, ForceArray => [ ]);

Log 3, "EnergyMeter: update readings";

fhem("setreading Solar total_pac_usage $ref->{SmartMeter}->{ActualPower}");
fhem("setreading Solar phase_1_usage $ref->{SmartMeter}->{RealPower}->{L1}");
fhem("setreading Solar phase_2_usage $ref->{SmartMeter}->{RealPower}->{L2}");
fhem("setreading Solar phase_3_usage $ref->{SmartMeter}->{RealPower}->{L3}");

return;
}


Die Bereitstellung der XML-Daten erfolgt über die frei erhältliche Smart Charging Software (http://www.eb-systeme.de/?page_id=1382).

Über ein entsprechendes notify wird die Routine bei mir nach jedem auslesen der Wechselrichterdaten getriggert:

define UpdateVerbrauch notify Solar:device_status.* {UpdateEnergyMeter}

Warum das Ganze?
Damit kann ich nun abhängig vom aktuellen Verbrauch und den Erzeugerdaten des Solar-Wechselrichters den Eigenverbrauch optimieren.

Viele Grüße

Klaus

PS: wie gesagt, meine Programmierkenntnisse gehen gegen 0, Optimierungen des Codes jederzeit erwünscht.  :)
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

siehste, war doch gar nicht so schwierig :)

Zwei Sachen würde ich ändern:


  • use XML::Simple kannst Du ganz nach oben in die 99_myUtils packen, am besten noch vor die Initialize-Funktion.
  • das Auslesen der Werte aus dem geparsten XML sollte auch ohne die vielen -> funktionieren, dann wird das Lesen etwas übersichtlicher.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Klaus Rubik

Zitat von: betateilchen am 20 März 2014, 14:30:59
das Auslesen der Werte aus dem geparsten XML sollte auch ohne die vielen -> funktionieren, dann wird das Lesen etwas übersichtlicher.

wie meinst du das? so:

$ref{SmartMeter}{RealPower}{L1} statt $ref->{SmartMeter}->{RealPower}->{L1}

Viele Grüße

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

betateilchen

genau so meine ich das :)

wobei ich mir angewöhnt habe: $ref->{..}{..}{..} zu verwenden, also nur einmal -> damit man auf Anhieb erkennt, dass es geschweifte Klammern sind. Je nach Display und Beleuchtung am Arbeitsplatz ist das manchmal schwer von runden Klammern zu unterscheiden, aber runde Klammern können nach -> nicht vorkommen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Klaus Rubik

Hallo Betateilchen,

danke auch noch für die Optimierungsanregungen,hab ich so eingebaut.

Viele Grüße

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

rizo

Muss dieses alte Thema nochmal rausholen, da ich etwas ähnliches vorhabe wie der TE.

Möchte von einer Website ( VU ) IP/web/timerliste die Timer auslesen. Wenn ich die Webadresse im Browser eingebe, steht ganz oben: This XML file does not appear to have any style information associated with it. The document tree is shown below. Ist das ein Problem?

So ist es ca. aufgelistet auf der Seite:

<e2servicereference>1:0:19:EF11:421:1:C00000:0:0:0:</e2servicereference>
<e2servicename>VOX HD</e2servicename>
<e2eit>33375</e2eit>
<e2name>Ab in die Ruine! - S07E02 - Folge 2</e2name>
<e2description>S07E02 - Folge 2</e2description>

<e2servicereference>1:0:19:EF11:421:1:C00000:0:0:0:</e2servicereference>
<e2servicename>VOX HD</e2servicename>
<e2eit>33376</e2eit>
<e2name>
Hot oder Schrott Die Allestester - S05E01 - Folge 1
</e2name>
<e2description>S05E01 - Folge 1</e2description>

Ich möchte gerne den Sender, Sendungsname, und die e2description als jeweils eigene Readings auslesen.

Leider ist es wie beim TE, ich hab auch vom Programmieren 0 Ahnung.

Danke für eure Hilfe.

rizo

Habe bisher einen Dummy:

define Timerdummy dummy

angelegt.

Und die myUtils so bearbeitet:

sub xmltest {

use XML::Simple qw(:strict);


my $xmltext = GetFileFromURL("http://192.168.0.30/web/timerlist");

my $ref = XMLin($xmltext, KeyAttr => { }, ForceArray => [ ]);

fhem("setreading Timerdummy e2servicename {e2servicename}");

return;
}


das Reading e2servicename wird beim Timerdummy angelegt aber mit dem Wert {e2servicename}. Also es wird nix aus der Website ausgelesen wenn ich es richtig sehe.