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
mit dem Perl Modul XML::Parser
Schau Dir mal 98_openweathermap.pm an, da habe ich sowas eingebaut. In 55_GDS glaub auch.
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
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.
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
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)
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
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 ;)
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 (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. :)
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.
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
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.
Hallo Betateilchen,
danke auch noch für die Optimierungsanregungen,hab ich so eingebaut.
Viele Grüße
Klaus
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.
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.