|
From: <ma...@us...> - 2012-05-11 18:16:13
|
Revision: 808
http://openautomation.svn.sourceforge.net/openautomation/?rev=808&view=rev
Author: makki1
Date: 2012-05-11 18:16:06 +0000 (Fri, 11 May 2012)
Log Message:
-----------
Sunny Webbox/SMA
Modified Paths:
--------------
wiregate/plugin/generic/SunnyWeb.pl
Added Paths:
-----------
wiregate/plugin/generic/Plugin-subscribe-debug.pl
wiregate/plugin/generic/SunnyWeb-CSV.pl
Added: wiregate/plugin/generic/Plugin-subscribe-debug.pl
===================================================================
--- wiregate/plugin/generic/Plugin-subscribe-debug.pl (rev 0)
+++ wiregate/plugin/generic/Plugin-subscribe-debug.pl 2012-05-11 18:16:06 UTC (rev 808)
@@ -0,0 +1,19 @@
+# Einfaches Plugin zum debuggen aller aktiven Plugin-subscriptions
+# just zur Doku
+
+$plugin_info{$plugname.'_cycle'} = 3600;
+my $ret;
+
+for my $k ( sort keys %plugin_subscribe ) {
+ for my $p ( keys %{$plugin_subscribe{ $k }} ) {
+ $ret .= "Plugin $p subscribed to $k\n";
+ }
+}
+
+for my $k ( sort keys %plugin_socket_subscribe ) {
+ $ret .= "Plugin $plugin_socket_subscribe{$k} subscribed to socket $k\n";
+}
+
+#return; # no debug out
+return $ret;
+
Added: wiregate/plugin/generic/SunnyWeb-CSV.pl
===================================================================
--- wiregate/plugin/generic/SunnyWeb-CSV.pl (rev 0)
+++ wiregate/plugin/generic/SunnyWeb-CSV.pl 2012-05-11 18:16:06 UTC (rev 808)
@@ -0,0 +1,109 @@
+# Plugin zur Abfrage einer Sunny Webbox-2 (BT) via FTP/CSV
+# V 1.1 2012-05-03
+# Aufbau moeglichst so, dass man unterhalb der Definitionen nichts aendern muss!
+# Der Abruf des CSV ist recht langsam, daher erledigt das ein Shell-script/Crontab:
+# Das CSV wird nicht analysiert sondern nur fixe Positionen angesprungen,
+# da unterschiedliche WR unterschiedlich viele Werte liefern
+
+##################
+### DEFINITION ###
+##################
+$plugin_info{$plugname.'_cycle'} = 300; # Eigenen Aufruf-Zyklus setzen
+
+my @Werte = (
+{ Name => "G_Metering.TotWhOut", GA => "10/1/1", DPT => "13", Column => 1, Type => "COUNTER"},
+{ Name => "G_Operation.GriSwCnt", GA => "10/1/2", DPT => "13", Column => 2, Type => "COUNTER"},
+{ Name => "G_GridMs.TotW", GA => "10/1/3", DPT => "14", Column => 5, Type => "GAUGE"},
+
+{ Name => "210_Metering.TotWhOut", GA => "10/1/11", DPT => "13", Column => 22, Type => "COUNTER"},
+{ Name => "210_Operation.GriSwCnt", GA => "10/1/12", DPT => "13", Column => 23, Type => "COUNTER"},
+{ Name => "210_Metering.TotOpTms", GA => "10/1/13", DPT => "13", Column => 24, Type => "COUNTER"},
+{ Name => "210_Metering.TotFeedTms",GA => "10/1/14", DPT => "13", Column => 25, Type => "COUNTER"},
+{ Name => "210_GridMs.TotW", GA => "10/1/15", DPT => "14", Column => 26, Type => "GAUGE"},
+{ Name => "210_GridMs.Hz", GA => "10/1/16", DPT => "14", Column => 27, Type => "GAUGE"},
+{ Name => "210_Isolation.FltA", GA => "10/1/17", DPT => "9", Column => 28, Type => "GAUGE"},
+{ Name => "210_Isolation.LeakRis", GA => "10/1/18", DPT => "14", Column => 29, Type => "GAUGE"},
+{ Name => "210_DcMs.Vol_A", GA => "10/1/19", DPT => "14", Column => 30, Type => "GAUGE"},
+{ Name => "210_DcMs.Amp_A", GA => "10/1/21", DPT => "14", Column => 31, Type => "GAUGE"},
+{ Name => "210_GridMs.PhV.phsA", GA => "10/1/23", DPT => "14", Column => 32, Type => "GAUGE"},
+{ Name => "210_GridMs.A.phsA", GA => "10/1/26", DPT => "14", Column => 33, Type => "GAUGE"},
+{ Name => "210_DcMs.Watt_A", GA => "10/1/29", DPT => "13", Column => 34, Type => "GAUGE"},
+
+{ Name => "211_Metering.TotWhOut", GA => "10/1/41", DPT => "13", Column => 39, Type => "COUNTER"},
+{ Name => "211_Operation.GriSwCnt", GA => "10/1/42", DPT => "13", Column => 40, Type => "COUNTER"},
+{ Name => "211_Metering.TotOpTms", GA => "10/1/43", DPT => "13", Column => 41, Type => "COUNTER"},
+{ Name => "211_Metering.TotFeedTms",GA => "10/1/44", DPT => "13", Column => 42, Type => "COUNTER"},
+{ Name => "211_GridMs.TotW", GA => "10/1/45", DPT => "14", Column => 43, Type => "GAUGE"},
+{ Name => "211_GridMs.Hz", GA => "10/1/46", DPT => "14", Column => 44, Type => "GAUGE"},
+{ Name => "211_Isolation.FltA", GA => "10/1/47", DPT => "9", Column => 45, Type => "GAUGE"},
+{ Name => "211_Isolation.LeakRis", GA => "10/1/48", DPT => "14", Column => 46, Type => "GAUGE"},
+{ Name => "211_DcMs.Vol_A", GA => "10/1/49", DPT => "14", Column => 47, Type => "GAUGE"},
+{ Name => "211_DcMs.Vol_B", GA => "10/1/10", DPT => "14", Column => 48, Type => "GAUGE"},
+{ Name => "211_DcMs.Amp_A", GA => "10/1/51", DPT => "14", Column => 49, Type => "GAUGE"},
+{ Name => "211_DcMs.Amp_B", GA => "10/1/52", DPT => "14", Column => 50, Type => "GAUGE"},
+{ Name => "211_GridMs.PhV.phsA", GA => "10/1/53", DPT => "14", Column => 51, Type => "GAUGE"},
+{ Name => "211_GridMs.PhV.phsB", GA => "10/1/54", DPT => "14", Column => 52, Type => "GAUGE"},
+{ Name => "211_GridMs.PhV.phsC", GA => "10/1/55", DPT => "14", Column => 53, Type => "GAUGE"},
+{ Name => "211_GridMs.A.phsA", GA => "10/1/56", DPT => "14", Column => 54, Type => "GAUGE"},
+{ Name => "211_GridMs.A.phsB", GA => "10/1/57", DPT => "14", Column => 55, Type => "GAUGE"},
+{ Name => "211_GridMs.A.phsC", GA => "10/1/58", DPT => "14", Column => 56, Type => "GAUGE"},
+{ Name => "211_DcMs.Watt_A", GA => "10/1/59", DPT => "13", Column => 57, Type => "GAUGE"},
+{ Name => "211_DcMs.Watt_B", GA => "10/1/60", DPT => "13", Column => 58, Type => "GAUGE"}
+);
+
+#Daten von Referenzanlage/CSV:
+#0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62
+#<SN>
+#;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;WebBox-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;SB 3000TL-20;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10;STP 12000TL-10
+#<SN>
+#;Metering.TotWhOut;Operation.GriSwCnt;Metering.TotOpTms;Metering.TotFeedTms;GridMs.TotW;GridMs.Hz;Isolation.FltA;Isolation.LeakRis;DcMs.Vol[A];DcMs.Vol[B];DcMs.Amp[A];DcMs.Amp[B];GridMs.PhV.phsA;GridMs.PhV.phsB;GridMs.PhV.phsC;GridMs.A.phsA;GridMs.A.phsB;GridMs.A.phsC;DcMs.Watt[A];DcMs.Watt[B];Operation.Health;Metering.TotWhOut;Operation.GriSwCnt;Metering.TotOpTms;Metering.TotFeedTms;GridMs.TotW;GridMs.Hz;Isolation.FltA;Isolation.LeakRis;DcMs.Vol[A];DcMs.Amp[A];GridMs.PhV.phsA;GridMs.A.phsA;DcMs.Watt[A];Operation.Health;Operation.Evt.Prio;Operation.Evt.Msg;Operation.Evt.Dsc;Metering.TotWhOut;Operation.GriSwCnt;Metering.TotOpTms;Metering.TotFeedTms;GridMs.TotW;GridMs.Hz;Isolation.FltA;Isolation.LeakRis;DcMs.Vol[A];DcMs.Vol[B];DcMs.Amp[A];DcMs.Amp[B];GridMs.PhV.phsA;GridMs.PhV.phsB;GridMs.PhV.phsC;GridMs.A.phsA;GridMs.A.phsB;GridMs.A.phsC;DcMs.Watt[A];DcMs.Watt[B];Operation.Health;Operation.Evt.Prio;Operation.Evt.Msg;Operation.Evt.Dsc
+#;Counter;Counter;Counter;Counter;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Status;Counter;Counter;Counter;Counter;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Status;Status;Status;Status;Counter;Counter;Counter;Counter;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Analog;Status;Status;Status;Status
+#dd.MM.yyyy HH:mm;kWh;;h;h;W;Hz;mA;kOhm;V;V;A;A;V;V;V;A;A;A;W;W;;kWh;;h;h;W;Hz;mA;kOhm;V;A;V;A;W;;;;;kWh;;h;h;W;Hz;mA;kOhm;V;V;mA;mA;V;V;V;A;A;A;W;W;;;;
+#03.05.2012 14:40;3804,60;407,00;3137,63;2838,07;4594,00;49,96;9,00;3000,00;291,54;527,14;5,54;2,71;232,54;231,42;233,42;4,76;5,11;5,12;3305,00;1434,00;Ok;881,10;221,00;1515,96;1357,44;1038,00;49,96;6,00;3000,00;203,98;5,21;234,31;4,42;1066,00;Ok;NonePrio;None;None;2923,50;186,00;1621,67;1480,63;3556,00;49,96;12,00;3000,00;379,11;527,14;5874,00;2712,00;230,78;231,42;233,42;5,09;5,11;5,12;2239,00;1434,00;Ok;NonePrio;None;None
+#root@wiregateXXX:~# cat /usr/local/bin/sunny-getcsv.sh
+# #!/bin/sh
+#FILE="CSV/$(date +%Y/%m/%Y-%m-%d).csv"
+#USER="Installer"
+#PASS="1234"
+#IP="192.168.0.110"
+#curl "ftp://$USER:$PASS@$IP/$FILE" | tail -n 1 > /tmp/sunny.csv
+#curl "http://$IP/culture/login?Language=LangDE&Userlevels=$USER&password=$PASS" > /tmp/sunny.xml
+
+#chmod a+x /usr/local/bin/sunny-getcsv.sh
+#crontab -l
+# m h dom mon dow command
+#*/6 * * * * /usr/local/bin/sunny-getcsv.sh >/dev/null 2>&1
+
+# 13.010 DPT_ActiveEnergy [-2 147 483 648 ... 2 147 483 647] Wh - 4 byte signed
+# 14.056 DPT_Value_Power W - 4 byte float
+
+#######################
+### ENDE DEFINITION ###
+#######################
+
+# Hauptverarbeitung
+open (CSV, '/tmp/sunny.csv');
+my @line;
+while (<CSV>) {
+ chomp;
+ next unless $_; # protect empty lines
+ @line = split /;/, $_;
+}
+close (CSV);
+
+foreach ( @Werte ) {
+ $line[$_->{Column}] =~ s/\.//g;
+ $line[$_->{Column}] =~ s/,/\./;
+ knx_write($_->{GA}, $line[$_->{Column}], $_->{DPT});
+ $line[$_->{Column}] *= 3600 if ($_->{Type} eq "COUNTER");
+ update_rrd($_->{Name},"",$line[$_->{Column}], $_->{Type});
+}
+
+
+@line=();
+undef @line;
+@Werte=();
+undef @Werte;
+
+return "Updated";
+
Modified: wiregate/plugin/generic/SunnyWeb.pl
===================================================================
--- wiregate/plugin/generic/SunnyWeb.pl 2012-05-10 20:01:11 UTC (rev 807)
+++ wiregate/plugin/generic/SunnyWeb.pl 2012-05-11 18:16:06 UTC (rev 808)
@@ -1,57 +1,120 @@
-# Plugin zur Abfrage einer Sunny Webbox-2 (BT)
-# V 1.0
+# Plugin zur Abfrage einer Sunny Webbox-2 (BT) via HTTP/XML
+# es existiert noch ein zweites, erweiteretes Plugin SunnyWeb-CSV!
+# -> Gesamt-Anlagenstatus/Ertrag sofern mehrere Wechselrichter
+# angeschlossen sind!
+# V 1.1 2012-05-03
# Aufbau moeglichst so, dass man unterhalb der Definitionen nichts aendern muss!
##################
### DEFINITION ###
##################
-my $ip = "192.168.1.110";
+my $ip = "192.168.0.110";
my $user = "Installer";
-my $pass = "1111";
+my $pass = "1234";
my $url = "/culture/login?Language=LangDE&Userlevels=".$user."&password=".$pass;
-# 13.010 DPT_ActiveEnergy [-2 147 483 648 ... 2 147 483 647] Wh
+# 13.010 DPT_ActiveEnergy [-2 147 483 648 ... 2 147 483 647] Wh - 4 byte signed
my $name = "PV-Anlage"; # Name fuer die RRD-Archive
-my $ga_ertrag = "13/3/1"; # GA fuer Gesamtertrag in Wh DPT13
-my $ga_tagesertrag = "13/3/2"; # GA fuer Tagesertrag in Wh DPT13
-my $ga_error = "13/3/0"; # GA erhaelt eine 1 wenn Anlagenzustand nicht Ok
-
+my $ga_ertrag = "10/0/1"; # GA fuer Gesamtertrag in Wh DPT13
+my $ga_tagesertrag = "10/0/2"; # GA fuer Tagesertrag in Wh DPT13
+# 14.056 DPT_Value_Power W - 4 byte float
+my $ga_leistung = "10/0/3"; # GA fuer akt. Leistung in W DPT14
+my $ga_error = "10/0/4"; # GA erhaelt eine 1 wenn Anlagenzustand nicht Ok
$plugin_info{$plugname.'_cycle'} = 300; # Eigenen Aufruf-Zyklus setzen
+my $debug = 0; # Debug-Ausgaben aktivieren?
+
#######################
### ENDE DEFINITION ###
#######################
# Hauptverarbeitung
-use LWP::Simple;
+use LWP::Simple; # comment wenn lokales XML
use XML::Simple;
-my $xml = get("http://".$ip.$url);
+my $xml = get("http://".$ip.$url); # comment wenn lokales XML
return "Fehler beim auslesen!" unless $xml;
+if ($debug) {
+ open (XMLFILE, '>/tmp/sunny1.xml');
+ print XMLFILE $xml;
+ close (XMLFILE);
+}
+
+# Die Webbox ist ziemlich lahm, ca. 2.3s im Schnitt; geschickter waere es, das XML per wget/curl mit der crontab zu holen siehe SunnyWeb-CSV.
my $data = XMLin($xml)->{Content}->{Element}->{Tab}->{'hp.PlantOverview'}->{Element};
+#my $data = XMLin('/tmp/sunny.xml')->{Content}->{Element}->{Tab}->{'hp.PlantOverview'}->{Element};
my $separator = $data->{'decimalSeparator'};
my $dataP = $data->{Element}[0]->{Items}->{XmlItem}->{'Solar-Wechselrichter'}->{Items}->{XmlItem};
my $zustand = $dataP->{Zustand}{'Value'};
+
my $gesErtrag = $dataP->{Gesamtertrag}{'Value'};
-my $tagErtrag = $dataP->{Tagesertrag}{'Value'};
-my $gesFactor = $dataP->{Gesamtertrag}{'factor'};
-$gesErtrag =~ s/$separator/\./;
+my $gesFactor = $dataP->{Gesamtertrag}{'factor'} || 1;
+#my $dseparator = $data->{'decimalSeparator'};
+#my $gseparator = $data->{'groupSeparator'};
+# as lang=DE we assume x.xxx,yy
+# a little haky-cranky as perl writes UTF8 numbers otherwise
+$gesErtrag =~ s/\.//g;
+$gesErtrag =~ s/,/\./;
$gesErtrag *= $gesFactor;
+my $tagErtrag = $dataP->{Tagesertrag}{'Value'};
+my $tagFactor = $dataP->{Tagesertrag}{'factor'} || 1;
+$tagErtrag =~ s/\.//;
+$tagErtrag =~ s/,/\./;
+$tagErtrag *= $tagFactor;
+
+my $aktLeistung = $dataP->{Leistung}->{Items}->{XmlItem}{'Summe'}{'Value'};
+my $leistFactor = $dataP->{Leistung}->{Items}->{XmlItem}{'Summe'}{'factor'} || 1;
+$aktLeistung =~ s/\.//;
+$aktLeistung =~ s/\,/\./;
+$aktLeistung *= $leistFactor;
+
knx_write($ga_ertrag,$gesErtrag,13);
knx_write($ga_tagesertrag,$tagErtrag,13);
+knx_write($ga_leistung,$aktLeistung,14);
if ($zustand !~ /Ok/) {
# Etwas mit dem Problem machen
- knx_write($ga_error,1,1)
+ knx_write($ga_error,1,1);
+} else {
+ knx_write($ga_error,0,1);
}
# Werte loggen
update_rrd($name,"_Leistung",$gesErtrag*3600,"COUNTER");
update_rrd($name,"_Tag",$tagErtrag);
+update_rrd($name,"_aktLeistung",$aktLeistung);
-#DEBUG: return "Zustand $zustand Tag: $tagErtrag Wh Gesamt $gesErtrag Wh";
+#my $dataD = XMLin($xml)->{DeviceTree}->{Devices}->{Device}->{Devices}->{Device}; # only first, a little hacky
+#my $dataD = XMLin('/tmp/sunny.xml')->{DeviceTree}->{Devices}->{Device}->{Devices}->{Device}; # only first, a little hacky
+
+#my @wrs; # Array der einzelnen Wechselrichter
+#for my $key (sort keys %$dataD) {
+# print "$dataD->{$key}->{deviceType} <= $key => $dataD->{$key}->{Value}\n";
+# push (@wrs,$dataD->{$key}->{Value}); # SN in array ablegen
+#}
+
+#foreach (@wrs) {
+ # hier koennte man nun noch die einzelnen WR-Details holen
+#}
+
+# avoid memleaks?
+$xml = (); # comment wenn lokales XML
+$data = ();
+$dataP = ();
+#$dataD = ();
+undef $xml; # comment wenn lokales XML
+undef $data;
+undef $dataP;
+#undef $dataD;
+
+
+# finally wollen wir Tausender im log, wilde RE
+$gesErtrag =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
+$tagErtrag =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
+$aktLeistung =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
+return "Zustand $zustand Leistung: $aktLeistung W Tag: $tagErtrag Wh Gesamt $gesErtrag Wh\n" if $debug;
return;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|