howto:wechselrichter_sma
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
howto:wechselrichter_sma [2018/01/25 16:04] – code jau | howto:wechselrichter_sma [2018/04/01 15:56] (aktuell) – Titel jau | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ===== SMA Wechselrichter ===== | + | ===(verschobene |
- | Der Hersteller SMA bietet Solarwechselrichter [[http:// | + | #redirect hardware:channels:solar_inverters:sma |
- | deren Daten über verschiedenen Schnittstellen ausgelesen werden können. SMA bietet zum Auslesen die | + | |
- | Software "Sunny Explorer" | + | |
- | Für die Nutzung mit der Volkszähler Lösung ist die Quelloffene Software SMASpot besser geeignet, die platttformübergreifend genutzt werden kann, und sich in die Volkszaehler Infrastruktur auf unterschiedliche Weise | + | |
- | einbinden lässt. Auf dieser | + | |
- | + | ||
- | ==== SMAspot ==== | + | |
- | Die Software SMASpot ist inzwischen bei [[https:// | + | |
- | befinden sich unter [[https:// | + | |
- | === Kompilieren von SMAspot unter Linux === | + | |
- | Die folgenden Punkte wurden unter Ubuntu 12.04 LTS getestet sollten aber auch in anderen Debian-kompatiblen | + | |
- | Distributionen funktionieren: | + | |
- | + | ||
- | - Herunterladen des Sourcecodes z.B. als SMAspot_SRC_244_Linux_Win32.tar.gz z.B. / | + | |
- | - Anlegen eines Verzeichnisses z.b. " | + | |
- | - Wechseln in dieses Verzeichnis | + | |
- | - Auspacken mit ../tar xvfz SMAspot_SRC_244_Linux_Win32.tar.gz | + | |
- | - Installieren der nötigen Libraries sudo apt-get install libbluetooth-dev libcurl4-openssl-dev libboost-all-dev | + | |
- | - Übersetzen mit sudo make | + | |
- | - Kopieren des Ergebnisses sudo cp bin/ | + | |
- | + | ||
- | === Anpassen der Konfiguration für Bluetooth === | + | |
- | == Bluetooth Adapter prüfen == | + | |
- | Beispiel: Cambridge Silicon Radio Bluetooth Adapter | + | |
- | < | + | |
- | lsusb | grep -i blue | + | |
- | Bus 002 Device 003: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) | + | |
- | </ | + | |
- | == SMA Geräte mit Bluetooth suchen | + | |
- | XXXX verdeckt die Angaben des konkreten Beispiels | + | |
- | < | + | |
- | hcitool scan | grep -i SMA | + | |
- | 00: | + | |
- | 00: | + | |
- | </ | + | |
- | + | ||
- | == Ergebnisse in SMASpot.cfg eintragen == | + | |
- | Wenn mehrere Inverter vorliegen einfach mehrere cfg Dateien erstellen z.B. 4000Watt.cfg, | + | |
- | + | ||
- | == SMASpot testen == | + | |
- | < | + | |
- | SMASpot -v | + | |
- | </ | + | |
- | oder | + | |
- | < | + | |
- | SMASpot -v -cfg4000Watt.cfg | + | |
- | </ | + | |
- | + | ||
- | ==== Beispiel STP 9000 TL-20 mit SMASpot per Ethernet / Perl-> | + | |
- | + | ||
- | + | ||
- | Ich besitze den Wechselrichter STP 9000TL-20 [[http:// | + | |
- | SMAspot -sp0 -v | + | |
- | + | ||
- | Ich möchte den Gesamtertrag, | + | |
- | Hierzu habe ich für den Gesamtertrag einen Kanal | + | |
- | El. Energie (Zählerstände) | + | |
- | und für den Ertrag je String | + | |
- | El. Energie (Leistungswerte) | + | |
- | angelegt. Die UUID sind später im Script einzutragen. | + | |
- | Anbei das Script: | + | |
- | + | ||
- | <code perl sma.pl> | + | |
- | #!/ | + | |
- | use LWP:: | + | |
- | open STATUS, "/ | + | |
- | or die " | + | |
- | while (< | + | |
- | if (/ETotal:[ ]*(.*)kWh/ | + | |
- | & | + | |
- | + | ||
- | } | + | |
- | if (/String 1 Pdc:[ ]*(.*)kW/ | + | |
- | $value = $1; | + | |
- | $value =~ s/\.//g; | + | |
- | & | + | |
- | + | ||
- | + | ||
- | } | + | |
- | if (/String 2 Pdc:[ ]*(.*)kW/ | + | |
- | $value = $1; | + | |
- | $value =~ s/\.//g; | + | |
- | & | + | |
- | } | + | |
- | } | + | |
- | close STATUS or die "bad netstat: $! $?"; | + | |
- | + | ||
- | #------ | + | |
- | sub submitt | + | |
- | { | + | |
- | $uuid = $_[0] ; | + | |
- | $val = $_[1] ; | + | |
- | print $uuid . " : " . $val . " | + | |
- | + | ||
- | + | ||
- | my $server_endpoint = " | + | |
- | # get(" | + | |
- | #print " | + | |
- | + | ||
- | # set custom HTTP request header fields | + | |
- | my $req = HTTP:: | + | |
- | $req-> | + | |
- | $req-> | + | |
- | + | ||
- | # add POST data to HTTP request body | + | |
- | $req-> | + | |
- | + | ||
- | my $ua = LWP:: | + | |
- | my $resp = $ua-> | + | |
- | if ($resp-> | + | |
- | my $message = $resp-> | + | |
- | print " | + | |
- | } else { | + | |
- | print "HTTP GET error code: ", $resp-> | + | |
- | print "HTTP GET error message: ", $resp-> | + | |
- | } | + | |
- | + | ||
- | } | + | |
- | </ | + | |
- | + | ||
- | Das Script wird dabei einmal pro Minute mit cron aufgerufen. | + | |
- | < | + | |
- | * * * * * / | + | |
- | </ | + | |
- | + | ||
- | Um den Eigenverbrauch zu bestimmen bilde ich die Differenz zwischen der Einspeisung, | + | |
- | Änderung 04.06.2014: Die Berechnung des Gesamtverbrauchs ist aktualisiert. | + | |
- | + | ||
- | == Originalscript von Markus == | + | |
- | <code bash eigenverbrauch.sh> | + | |
- | # | + | |
- | echo ' | + | |
- | delete from `data` where `timestamp` = (select * from (select max(timestamp) from data where channel_id = 7) x) and channel_id = 7 | + | |
- | ' | mysql --user=vz --password=fdfdfdfdf volkszaehler -T | + | |
- | echo ' | + | |
- | INSERT INTO `data`( `channel_id`, | + | |
- | SELECT | + | |
- | max(case when `channel_id` | + | |
- | max(case when `channel_id` | + | |
- | FROM `data` where channel_id in (2,4) | + | |
- | and timestamp > (select max(timestamp) from data where `channel_id` = 7) | + | |
- | group by floor(`timestamp`/ | + | |
- | inner join data data_4 on timestamp_4 | + | |
- | ' | mysql --user=vz --password=fdfdfdfdf volkszaehler | + | |
- | + | ||
- | echo ' | + | |
- | delete from `data` where channel_id = 8 | + | |
- | ' | mysql --user=vz --password=fdfdfdfdf volkszaehler -T | + | |
- | #and timestamp > (select max(timestamp) from data where `channel_id` = 8) | + | |
- | + | ||
- | echo ' | + | |
- | INSERT INTO `data`( `channel_id`, | + | |
- | ( | + | |
- | SELECT | + | |
- | max(case when `channel_id` | + | |
- | max(case when `channel_id` | + | |
- | FROM `data` where channel_id in (1,7) | + | |
- | group by floor(`timestamp`/ | + | |
- | ) a inner join data data_1 on timestamp_1 | + | |
- | ' | mysql --user=vz --password=dsdsdsdsds volkszaehler | + | |
- | + | ||
- | </ | + | |
- | auch diese Script wird mit cron gestartet, aber nur ein mal die Stunde. | + | |
- | < | + | |
- | 1 * * * * bash / | + | |
- | </ | + | |
- | + | ||
- | == Modifiziertes Script (Versuch von Wolfgang) == | + | |
- | <code bash eigenverbrauch.sh> | + | |
- | # | + | |
- | # calculate own PV usage | + | |
- | # Author: Markus 2014-05-20 | + | |
- | # latest version: | + | |
- | # $Header: / | + | |
- | + | ||
- | # | + | |
- | # get the delete query for the given channel | + | |
- | # | + | |
- | deletequery() { | + | |
- | local l_channel=$1 | + | |
- | cat << EOF | + | |
- | DELETE | + | |
- | FROM `data` | + | |
- | WHERE `timestamp` = | + | |
- | | + | |
- | AND channel_id = $l_channel; | + | |
- | EOF | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # get the insert query for the given channels | + | |
- | # l_chanel the channel to insert into | + | |
- | # l_c2 - the channel to substract | + | |
- | # l_c3 - the channel to substract the value from | + | |
- | # | + | |
- | insertquery() { | + | |
- | local l_channel=$1 | + | |
- | local l_c2=$2 | + | |
- | local l_c3=$3 | + | |
- | cat << EOF | + | |
- | INSERT INTO `data`( `channel_id`, | + | |
- | SELECT $l_chanel, | + | |
- | FROM ( | + | |
- | SELECT | + | |
- | MAX(CASE WHEN `channel_id` = $l_c2 then timestamp else 0 end) timestamp_2, | + | |
- | MAX(CASE WHEN `channel_id` = $l_c3 then timestamp else 0 end) timestamp_3 | + | |
- | FROM `data` | + | |
- | WHERE channel_id in ($l_c2, | + | |
- | AND timestamp > ( | + | |
- | SELECT MAX(timestamp) FROM data WHERE `channel_id` = $l_channel | + | |
- | ) | + | |
- | GROUP by floor(`timestamp`/ | + | |
- | INNER JOIN data data_2 | + | |
- | ON timestamp_2 | + | |
- | AND data_2.channel_id = $l_c2 | + | |
- | INNER JOIN data data_3 | + | |
- | ON timestamp_3 | + | |
- | AND data_3.channel_id = $l_c3 | + | |
- | EOF | + | |
- | } | + | |
- | + | ||
- | # modify according to your volkszaehler mysql database settings | + | |
- | user=vz | + | |
- | password=fdfdfdfdf | + | |
- | db=volkszaehler | + | |
- | + | ||
- | # debug setting | + | |
- | debug= | + | |
- | # uncomment to debug sql | + | |
- | #debug=-T | + | |
- | + | ||
- | # modify to suite your channel settings | + | |
- | + | ||
- | # channel 7 is calculated from as channel 4 - channel 2 / 1000 | + | |
- | deletequery 7 | egrep -v " | + | |
- | insertquery 7 2 4 | egrep -v " | + | |
- | + | ||
- | # channel 8 is calculated from as channel 7 - channel 1 / 1000 | + | |
- | echo " | + | |
- | insertquery 8 1 7 | egrep -v " | + | |
- | + | ||
- | </ | + | |
- | Und so sieht es aus: | + | |
- | + | ||
- | {{:howto: | + | |
- | + | ||
- | ==== Beispiel SB 4000 TL-21 + SB 1300TL-10 mit SMASpot und PHP ==== | + | |
- | The solution consists of three parts: | + | |
- | - the bash script sma2vz | + | |
- | - the php script sma2vz.php | + | |
- | - the php helper script vzapihelper.php (same as in the youless page) | + | |
- | + | ||
- | the bash script sma2vz has a function configure - this needs to run once you might want | + | |
- | to configure the here-document part in the function inverters of this script | + | |
- | + | ||
- | there is a help screen available: | + | |
- | <code bash sma2vz> | + | |
- | ./sma2vz --help | + | |
- | | + | |
- | [ --daytimeonly --lat=lattitude --lon=longitude] | + | |
- | | + | |
- | | [--help] | + | |
- | | [--configure] | + | |
- | + | ||
- | | + | |
- | volkszaehler middleware url | + | |
- | + | ||
- | | + | |
- | channel uuid for power (watt) PV output | + | |
- | + | ||
- | | + | |
- | | + | |
- | + | ||
- | | + | |
- | do not post data at night (e.g. if your device does not supply data) | + | |
- | + | ||
- | | + | |
- | plant longitude geo coordinate | + | |
- | + | ||
- | | + | |
- | plant lattitude geo coordinate | + | |
- | + | ||
- | | + | |
- | poll SMA inverters in a loop | + | |
- | + | ||
- | | + | |
- | how many secs to wait between each reading (default: 15 secs) | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | here document to fit your plant' | + | |
- | </ | + | |
- | + | ||
- | <code bash configure example> | + | |
- | ./sma2vz --lat 51.244 --lon 6.52 --configure | + | |
- | </ | + | |
- | + | ||
- | <code bash loop example> | + | |
- | ./sma2vz \ | + | |
- | --vzurl " | + | |
- | --cuuid_pwr " | + | |
- | --cuuid_kwh " | + | |
- | --daytimeonly --lat 51.244 --lon 6.52 \ | + | |
- | --loop --delay 15 | + | |
- | </ | + | |
- | + | ||
- | <code bash cron example> | + | |
- | cd / | + | |
- | / | + | |
- | --vzurl " | + | |
- | --cuuid_pwr " | + | |
- | --cuuid_kwh " | + | |
- | --daytimeonly --lat 51.244 --lon 6.52 >> / | + | |
- | </ | + | |
- | + | ||
- | <code | logoutput example> | + | |
- | 2014-06-01 12:52:08 PV: 1409 Watt | + | |
- | 2014-06-01 12:53:07 PV: 2176 Watt | + | |
- | 2014-06-01 12:54:07 PV: 1699 Watt | + | |
- | 2014-06-01 12:55:07 PV: 3375 Watt | + | |
- | 2014-06-01 12:56:07 PV: 3578 Watt | + | |
- | </ | + | |
- | + | ||
- | Any feedback please to wf (at) bitplan.com - enjoy! | + | |
- | + | ||
- | + | ||
- | <code bash sma2vz> | + | |
- | #/ | + | |
- | # SMAspot with Volkszaehler | + | |
- | # WF 2014-05-29 | + | |
- | # $Header: / | + | |
- | + | ||
- | # | + | |
- | # get a configuration | + | |
- | # param 1: bluetooth address | + | |
- | # param 2: name of configuration/ | + | |
- | # param 3: " | + | |
- | # param 4: latitude of plant | + | |
- | # param 5: longitude of plant | + | |
- | # param 6: path to output files of SMAspot | + | |
- | # | + | |
- | smaspot_config() { | + | |
- | local l_btaddr=$1 | + | |
- | local l_name=$2 | + | |
- | local l_password=$3 | + | |
- | local l_lon=$4 | + | |
- | local l_lat=$5 | + | |
- | local l_path=$6 | + | |
- | cat << EOF | + | |
- | ################################################################################ | + | |
- | # ____ __ __ _ _ | + | |
- | # / ___|| \/ | / \ ___ _ __ ___ | |_ | + | |
- | # \___ \| |\/| | / _ \ / __| '_ \ / _ \| __| | + | |
- | # ___) | | | |/ ___ \\__ \ |_) | (_) | |_ | + | |
- | # | + | |
- | # |_| | + | |
- | # | + | |
- | # SMAspot.cfg - Configuration file for SMAspot.exe | + | |
- | # SMAspot - Yet another tool to read power production of SMA solar inverters | + | |
- | # (c)2012-2014, | + | |
- | # | + | |
- | # DISCLAIMER: | + | |
- | # A user of SMAspot software acknowledges that he or she is receiving this | + | |
- | # software on an "as is" basis and the user is not relying on the accuracy | + | |
- | # or functionality of the software for any purpose. The user further | + | |
- | # acknowledges that any use of this software will be at his own risk | + | |
- | # and the copyright owner accepts no responsibility whatsoever arising from | + | |
- | # the use or application of the software. | + | |
- | # | + | |
- | ################################################################################ | + | |
- | + | ||
- | # SMA Inverter' | + | |
- | # Windows: smaspot -scan | + | |
- | # Linux : hcitool scan | + | |
- | # IMPORTANT FOR SPEEDWIRE USERS: COMMENT OUT BTADDRESS (PUT # IN FRONT) | + | |
- | BTAddress=$l_btaddr | + | |
- | + | ||
- | # SMA Inverter' | + | |
- | # If IP_Address is not set or is 0.0.0.0 SMAspot will try to detect the speedwire inverter by broadcast | + | |
- | # If IP_Address is set to a valid IP, SMAspot will try to connect directly to that IP without broadcast detection | + | |
- | # | + | |
- | + | ||
- | # User password (default 0000) | + | |
- | Password=$l_password | + | |
- | + | ||
- | # MIS_Enabled (Multi Inverter Support: Default=0 Disabled) | + | |
- | # +------------+-------+-------------+ | + | |
- | # | #Inverters | NetID | MIS_Enabled | | + | |
- | # +------------+-------+-------------+ | + | |
- | # | 1 | + | |
- | # +------------+-------+-------------+ | + | |
- | # | 1 | + | |
- | # +------------+-------+-------------+ | + | |
- | # | >1 | > | + | |
- | # +------------+-------+-------------+ | + | |
- | MIS_Enabled=0 | + | |
- | + | ||
- | # Plantname | + | |
- | Plantname=$l_name | + | |
- | + | ||
- | # OutputPath (Place to store CSV files) | + | |
- | # | + | |
- | # Windows: C: | + | |
- | # Linux : / | + | |
- | # %Y %m and %d will be expanded to Year Month and Day | + | |
- | OutputPath=$l_path/ | + | |
- | + | ||
- | # OutputPathEvents (Place to store CSV files for events) | + | |
- | # If omitted, OutputPath is used | + | |
- | OutputPathEvents=$l_path/ | + | |
- | + | ||
- | # Position of pv-plant http:// | + | |
- | # Example for Ukkel, Belgium | + | |
- | Latitude=$l_lat | + | |
- | Longitude=$l_lon | + | |
- | + | ||
- | # Calculate Missing SpotValues | + | |
- | # If set to 1, values not provided by inverter will be calculated | + | |
- | # eg: Pdc1 = Idc1 * Udc1 | + | |
- | CalculateMissingSpotValues=1 | + | |
- | + | ||
- | # DateTimeFormat (default %d/%m/%Y %H:%M:%S) | + | |
- | # For details see strftime() function | + | |
- | # http:// | + | |
- | DateTimeFormat=%Y-%m-%d %H:%M:%S | + | |
- | + | ||
- | # DateFormat (default %d/%m/%Y) | + | |
- | DateFormat=%-%m-%d | + | |
- | + | ||
- | # DecimalPoint (comma/ | + | |
- | DecimalPoint=point | + | |
- | + | ||
- | # TimeFormat (default %H:%M:%S) | + | |
- | TimeFormat=%H: | + | |
- | + | ||
- | # SynchTime (default 1 = On) | + | |
- | # If set to 1 the Inverter time is synchronised with pc time | + | |
- | # Some inverters don't have a real-time clock | + | |
- | SynchTime=1 | + | |
- | + | ||
- | # SunRSOffset | + | |
- | # Offset to start before sunrise and end after sunset (0-3600 - default 900 seconds) | + | |
- | SunRSOffset=900 | + | |
- | + | ||
- | # Locale | + | |
- | # Translate Entries in CSV files | + | |
- | # Surpported locales: de-DE; | + | |
- | # Default en-US | + | |
- | Locale=de-DE | + | |
- | + | ||
- | # Timezone | + | |
- | # Select the right timezone in date_time_zonespec.csv | + | |
- | # e.g. Timezone=Europe/ | + | |
- | Timezone=Europe/ | + | |
- | + | ||
- | ########################### | + | |
- | ### CSV Export Settings ### | + | |
- | ########################### | + | |
- | # With CSV_* settings you can define the CSV file format | + | |
- | + | ||
- | # CSV_Export (default 1 = Enabled) | + | |
- | # Enables or disables the CSV Export functionality | + | |
- | CSV_Export=1 | + | |
- | + | ||
- | # CSV_ExtendedHeader (default 1 = On) | + | |
- | # Enables or disables the SMA extended header info (8 lines) | + | |
- | # isep=; | + | |
- | # Version CSV1|Tool SMAspot|Linebreaks CR/ | + | |
- | # etc... | + | |
- | # This is usefull for manual data upload to pvoutput.org | + | |
- | CSV_ExtendedHeader=1 | + | |
- | + | ||
- | # CSV_Header (default 1 = On) | + | |
- | # Enables or disables the CSV data header info (1 line) | + | |
- | # dd/MM/yyyy HH: | + | |
- | # This is usefull for manual data upload to pvoutput.org | + | |
- | # If CSV_ExtendedHeader is enabled, CSV_Header is also enabled | + | |
- | CSV_Header=1 | + | |
- | + | ||
- | # CSV_SaveZeroPower (default 1 = On) | + | |
- | # When enabled, daily csv files contain all data from 00:00 to 23:55 | + | |
- | # This is usefull for manual data upload to pvoutput.org | + | |
- | CSV_SaveZeroPower=1 | + | |
- | + | ||
- | # CSV_Delimiter (comma/ | + | |
- | CSV_Delimiter=semicolon | + | |
- | + | ||
- | # CSV_Spot_TimeSource (Inverter|Computer default Inverter) | + | |
- | CSV_Spot_TimeSource=Inverter | + | |
- | + | ||
- | # CSV_Spot_WebboxHeader (Default 0 = Off) | + | |
- | # When enabled, use Webbox style header (DcMs.Watt[A]; | + | |
- | CSV_Spot_WebboxHeader=0 | + | |
- | + | ||
- | ################################# | + | |
- | ### Online Monitoring Systems ### | + | |
- | ################################# | + | |
- | # | + | |
- | # In the future, multiple online monitoring systems can be defined | + | |
- | # Here we can activate the ones we like | + | |
- | # | + | |
- | ################################ | + | |
- | ### PVoutput Upload Settings ### | + | |
- | ################################ | + | |
- | # PVoutput (default 0 = Disabled) | + | |
- | # Enables or disables the upload functionality to pvoutput.org | + | |
- | # When enabled, be sure to use -u switch on the command line | + | |
- | PVoutput=0 | + | |
- | + | ||
- | # | + | |
- | #Sets PVoutput System ID | + | |
- | PVoutput_SID= | + | |
- | + | ||
- | # | + | |
- | #Sets PVoutput API Key | + | |
- | PVoutput_Key= | + | |
- | + | ||
- | # VoltageLogging sets AC or DC logging. | + | |
- | # Possible values are: | + | |
- | # NONE (disabled) | + | |
- | # MAX(AC) (default) | + | |
- | # AC(PH1) or AC(PH2) or AC(PH3) | + | |
- | # MAX(DC) or DC(ST1) or DC(ST2) | + | |
- | VoltLogging=MAX(AC) | + | |
- | + | ||
- | # InverterTemp (default 0 = disabled) | + | |
- | # Enables or disables the upload of the inverter' | + | |
- | InverterTemp=0 | + | |
- | + | ||
- | # InverterTempMapTo (default v5 = Use standard PVoutput Temperature Graph) | + | |
- | # In Donation Mode only, map inverter' | + | |
- | # For more info, see http:// | + | |
- | InverterTempMapTo=v5 | + | |
- | + | ||
- | # CumulativeEnergy (default 0 = Today' | + | |
- | # Set the cumulative flag = 1 when you wish to pass lifetime energy or 0 for today' | + | |
- | # WARNING!!! DO NOT CHANGE THIS FLAG DURING DAYLIGHT AS THIS WILL MESS UP YOUR PVOUTPUT GRAPHS | + | |
- | CumulativeEnergy=0 | + | |
- | EOF | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # | + | |
- | # | + | |
- | inverters() { | + | |
- | # insert your data from | + | |
- | # | + | |
- | # | + | |
- | # first column is bluetooth address | + | |
- | # second column is the name of the device (here just the wattage is used) | + | |
- | # third column is the password for " | + | |
- | # fourth column is the latitude | + | |
- | # fifth column is the longitude | + | |
- | cat << EOF | + | |
- | 00: | + | |
- | 00: | + | |
- | EOF | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # create configuration files | + | |
- | # | + | |
- | configure() { | + | |
- | checklonlat " | + | |
- | inverters | while read btaddr name password path; do | + | |
- | echo " | + | |
- | smaspot_config $btaddr $name $password $lon $lat $path > ${name}.cfg | + | |
- | done | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # get the sma meter reading | + | |
- | # | + | |
- | getsmameter() { | + | |
- | # temp filename base for SMAspor result | + | |
- | tmp=/ | + | |
- | # read data from all inverters | + | |
- | inverters | while read btaddr name password path; do | + | |
- | # single shot run of SMAspot with no CVS export | + | |
- | # uncomment to debug | + | |
- | #echo " | + | |
- | ./SMAspot -v -nocsv -cfg${name}.cfg > ${tmp}_${name} | + | |
- | # the lines we need look like: | + | |
- | # EToday: 3.358kWh | + | |
- | # ETotal: 5151.294kWh | + | |
- | # Total Pac : | + | |
- | + | ||
- | # let's filter the result with awk | + | |
- | cat ${tmp}_${name} | awk ' | + | |
- | # set the field separator fitting the x: y format | + | |
- | BEGIN { FS=":"; | + | |
- | # check the input lines for the three patterns and remove | + | |
- | # the unit at the end - assign to the three variables | + | |
- | # etoday, etotal and totalpac | + | |
- | / | + | |
- | / | + | |
- | /Total Pac/ { totalpac=$2; | + | |
- | # at the end of all lines print out a single json formatted result line | + | |
- | END { | + | |
- | printf(" | + | |
- | json(" | + | |
- | json(" | + | |
- | json(" | + | |
- | } | + | |
- | # helper function to create json name values | + | |
- | function json(name, | + | |
- | # trim value | + | |
- | gsub(" ","", | + | |
- | result=quote(name)":" | + | |
- | return result | + | |
- | } | + | |
- | + | ||
- | # helper function to quote a string | + | |
- | function quote(s, | + | |
- | result=doublequote s doublequote; | + | |
- | return result | + | |
- | }' | + | |
- | rm ${tmp}_${name} | + | |
- | done | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # show usage | + | |
- | # | + | |
- | usage() { | + | |
- | cat << EOF | + | |
- | | + | |
- | [ --daytimeonly --lat=lattitude --lon=longitude] | + | |
- | | + | |
- | | [--help] | + | |
- | | [--configure] | + | |
- | + | ||
- | | + | |
- | volkszaehler middleware url | + | |
- | + | ||
- | | + | |
- | channel uuid for power (watt) PV output | + | |
- | + | ||
- | | + | |
- | | + | |
- | + | ||
- | | + | |
- | do not post data at night (e.g. if your device does not supply data) | + | |
- | + | ||
- | | + | |
- | plant longitude geo coordinate | + | |
- | + | ||
- | | + | |
- | plant lattitude geo coordinate | + | |
- | + | ||
- | | + | |
- | poll SMA inverters in a loop | + | |
- | + | ||
- | | + | |
- | how many secs to wait between each reading (default: 15 secs) | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | here document to fit your plant' | + | |
- | EOF | + | |
- | exit 1 | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # show error and exit | + | |
- | # | + | |
- | error() { | + | |
- | local l_msg=$1 | + | |
- | local l_hint=$2 | + | |
- | echo "error $0: $l_msg" | + | |
- | echo " | + | |
- | exit 1 | + | |
- | } | + | |
- | + | ||
- | # | + | |
- | # check that longitude and lattitude are supplied | + | |
- | # | + | |
- | checklonlat() { | + | |
- | local l_title=" | + | |
- | if [ " | + | |
- | then | + | |
- | error " | + | |
- | fi | + | |
- | if [ " | + | |
- | then | + | |
- | error " | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | # defaults | + | |
- | delay=15 | + | |
- | maxloops=1 | + | |
- | daytimeonly=0 | + | |
- | + | ||
- | # check command line arguments | + | |
- | while [ $# -gt 0 ] | + | |
- | do | + | |
- | arg=" | + | |
- | #echo " | + | |
- | case " | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | #echo $cuuid_kwh | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | | + | |
- | ;; | + | |
- | + | ||
- | | + | |
- | + | ||
- | echo " | + | |
- | | + | |
- | | + | |
- | ;; | + | |
- | *) | + | |
- | echo >&2 " | + | |
- | exit 1 | + | |
- | ;; | + | |
- | | + | |
- | | + | |
- | done | + | |
- | + | ||
- | # check that options are set | + | |
- | if [ " | + | |
- | then | + | |
- | error " | + | |
- | fi | + | |
- | if [ " | + | |
- | then | + | |
- | error " | + | |
- | fi | + | |
- | if [ " | + | |
- | then | + | |
- | error " | + | |
- | fi | + | |
- | if [ " | + | |
- | then | + | |
- | checklonlat " | + | |
- | fi | + | |
- | + | ||
- | loop=0 | + | |
- | while [ $loop -lt $maxloops ] | + | |
- | do | + | |
- | # get the SMA meter readings | + | |
- | getsmameter | php sma2vz.php --vzurl=$vzurl --cuuid_pwr=$cuuid_pwr --cuuid_kwh=$cuuid_kwh --daytimeonly=$daytimeonly --lat=$lat --lon=$lon | + | |
- | # sleep a while | + | |
- | if [ $maxloops -gt 1 ] | + | |
- | then | + | |
- | sleep $delay | + | |
- | fi | + | |
- | loop=`expr $loop + 1 ` | + | |
- | done | + | |
- | + | ||
- | </ | + | |
- | <code php sma2vz.php> | + | |
- | <?php | + | |
- | /** | + | |
- | * read meter data from SMA device | + | |
- | * and post it to volkszaehler | + | |
- | * $Header: / | + | |
- | */ | + | |
- | + | ||
- | // common code for reading and posting | + | |
- | require __DIR__.'/ | + | |
- | + | ||
- | /** | + | |
- | * check the daytime values | + | |
- | */ | + | |
- | function daytime($latitude, | + | |
- | $result=array(); | + | |
- | // 08:53 CEST | + | |
- | // $time_format = 'H:i T'; | + | |
- | // 08:53 | + | |
- | $time_format = ' | + | |
- | + | ||
- | // find time offset in hours | + | |
- | $tzoffset = date(" | + | |
- | + | ||
- | $zenith = 90+(50/60); // True sunrise/ | + | |
- | + | ||
- | // determine sunrise time | + | |
- | $sunrise = date_sunrise(time(), | + | |
- | $sunrise_time = date($time_format, | + | |
- | // determine sunset time | + | |
- | $sunset = date_sunset(time(), | + | |
- | $sunset_time = date($time_format, | + | |
- | + | ||
- | // check whether it's daytime | + | |
- | $sunrise_epoch = date_sunrise(time(), | + | |
- | $sunset_epoch | + | |
- | $time_epoch = time(); // time now | + | |
- | + | ||
- | $result[" | + | |
- | + | ||
- | $result[" | + | |
- | $result[" | + | |
- | $result[" | + | |
- | return $result; | + | |
- | } | + | |
- | + | ||
- | $loop=0; | + | |
- | // possible command line options | + | |
- | // --vzurl= --cuuid_pwr= --cuuid_kwh= --daytimeonly | + | |
- | $longopts=array(" | + | |
- | $shortopts=""; | + | |
- | $options=getopt($shortopts, | + | |
- | // the volkszaehler middleware url | + | |
- | $vzurl=checkoption(" | + | |
- | // channel uuids | + | |
- | // power (watts) | + | |
- | $cuuid_pwr=checkoption(" | + | |
- | // energy (kWh) | + | |
- | $cuuid_kwh=checkoption(" | + | |
- | // daytimeonly? | + | |
- | $daytimeonly=checkoption(" | + | |
- | if ($daytimeonly) { | + | |
- | $latitude=checkoption(" | + | |
- | $longitude=checkoption(" | + | |
- | } | + | |
- | + | ||
- | $jsonlines=file(" | + | |
- | $tmeter=array(); | + | |
- | foreach ($jsonlines as $line_nume => $json) { | + | |
- | // get the meter reading | + | |
- | $meter=json_decode($json, | + | |
- | # | + | |
- | foreach ($meter as $name => $value) { | + | |
- | if (!array_key_exists($name, | + | |
- | $tmeter[$name]=0; | + | |
- | $tmeter[$name]+=$value; | + | |
- | } | + | |
- | } | + | |
- | # | + | |
- | //array(3) { [" | + | |
- | // [" | + | |
- | // | + | |
- | $etotal=$tmeter[" | + | |
- | $totalpac=$tmeter[" | + | |
- | if ($daytimeonly) { | + | |
- | $daytime=daytime($latitude, | + | |
- | if (!$daytime[" | + | |
- | printf(" | + | |
- | exit(2); | + | |
- | } | + | |
- | } | + | |
- | # total wattage of all inverters | + | |
- | post2vz($vzurl, | + | |
- | # total kwh of all inverters | + | |
- | post2vz($vzurl, | + | |
- | if ($daytimeonly) { | + | |
- | printf(" | + | |
- | } else { | + | |
- | printf(" | + | |
- | } | + | |
- | exit(0); | + | |
- | ?> | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | <code php vzapihelper.php> | + | |
- | <?php | + | |
- | /** | + | |
- | * vzapi helper functions | + | |
- | * $Header: / | + | |
- | */ | + | |
- | + | ||
- | /** | + | |
- | * get a curl channel | + | |
- | */ | + | |
- | function curl($url) { | + | |
- | // Initiate curl | + | |
- | $ch = curl_init(); | + | |
- | // Disable SSL verification | + | |
- | curl_setopt($ch, | + | |
- | // Will return the response, if false it print the response | + | |
- | curl_setopt($ch, | + | |
- | // Set the url | + | |
- | curl_setopt($ch, | + | |
- | + | ||
- | return $ch; | + | |
- | } | + | |
- | + | ||
- | /** | + | |
- | * read the given url | + | |
- | * @param $url:the url to read from | + | |
- | */ | + | |
- | function readUrl($url) | + | |
- | $ch=curl($url); | + | |
- | + | ||
- | // Execute | + | |
- | $result=curl_exec($ch); | + | |
- | return $result; | + | |
- | } | + | |
- | + | ||
- | /** | + | |
- | * post to the given url | + | |
- | */ | + | |
- | function postUrl($url, | + | |
- | | + | |
- | | + | |
- | // | + | |
- | foreach($fields as $key=> | + | |
- | $fields_string .= $key.' | + | |
- | } | + | |
- | rtrim($fields_string, | + | |
- | curl_setopt($ch, | + | |
- | curl_setopt($ch, | + | |
- | $result=curl_exec($ch); | + | |
- | return $result; | + | |
- | } | + | |
- | + | ||
- | /** | + | |
- | * post data to vz middleware | + | |
- | * param 1: vzurl - middleware url of volkszaehler | + | |
- | * param 2: channel uuid | + | |
- | * param 3: value to post | + | |
- | */ | + | |
- | | + | |
- | // post data to middleware according to: | + | |
- | // http:// | + | |
- | + | ||
- | // adapt timestamp to volkszaehler conventions | + | |
- | $timestamp=time()*1000; | + | |
- | + | ||
- | # first | + | |
- | | + | |
- | | + | |
- | | + | |
- | if ($debug) { | + | |
- | echo $presult; | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | /** | + | |
- | * check that option $opt is available in $options | + | |
- | * return the value if available | + | |
- | */ | + | |
- | function checkoption($opt, | + | |
- | if (array_key_exists($opt, | + | |
- | return $options[$opt]; | + | |
- | else | + | |
- | die(" | + | |
- | } | + | |
- | + | ||
- | ?> | + | |
- | + | ||
- | </ | + |
howto/wechselrichter_sma.1516892664.txt.gz · Zuletzt geändert: 2018/01/25 16:04 von jau