howto:wechselrichter_sma
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende ÜberarbeitungNächste ÜberarbeitungBeide Seiten der Revision | ||
howto:wechselrichter_sma [2014/05/29 10:36] – wf_bitplan.com | howto:wechselrichter_sma [2018/01/25 16:04] – code jau | ||
---|---|---|---|
Zeile 48: | Zeile 48: | ||
</ | </ | ||
- | === Beispiele === | + | ==== Beispiel STP 9000 TL-20 mit SMASpot per Ethernet / Perl-> |
- | == Beispiel STP 9000 TL-20 mit SMASpot per Ethernet / Perl-> | + | |
Zeile 63: | Zeile 62: | ||
Anbei das Script: | Anbei das Script: | ||
- | < | + | < |
# | # | ||
use LWP:: | use LWP:: | ||
Zeile 126: | Zeile 125: | ||
</ | </ | ||
- | Um den Eigenverbrauch zu bestimmen bilde ich die Differenz zwischen der Einspeisung, | + | 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 == |
+ | < | ||
#!/bin/bash | #!/bin/bash | ||
echo ' | echo ' | ||
Zeile 150: | Zeile 151: | ||
echo ' | echo ' | ||
- | INSERT INTO `data`( `channel_id`, | + | INSERT INTO `data`( `channel_id`, |
+ | ( | ||
SELECT | SELECT | ||
max(case when `channel_id` | max(case when `channel_id` | ||
max(case when `channel_id` | max(case when `channel_id` | ||
FROM `data` where channel_id in (1,7) | FROM `data` where channel_id in (1,7) | ||
- | group by floor(`timestamp`/ | + | group by floor(`timestamp`/ |
- | inner join data data_1 on timestamp_1 | + | ) a inner join data data_1 on timestamp_1 |
- | ' | mysql --user=vz --password=fdfdfdfdf | + | ' | mysql --user=vz --password=dsdsdsdsds |
</ | </ | ||
auch diese Script wird mit cron gestartet, aber nur ein mal die Stunde. | auch diese Script wird mit cron gestartet, aber nur ein mal die Stunde. | ||
< | < | ||
- | 1 * * * * bash / | + | 1 * * * * bash / |
</ | </ | ||
+ | == Modifiziertes Script (Versuch von Wolfgang) == | ||
+ | <code bash eigenverbrauch.sh> | ||
+ | #!/bin/bash | ||
+ | # 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: | Und so sieht es aus: | ||
{{: | {{: | ||
+ | ==== 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> | ||
+ | #/bin/bash | ||
+ | # 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 | ||
+ | # | ||
+ | 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 " | ||
+ | | ||
+ | usage | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | #echo $cuuid_kwh | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | shift | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | | ||
+ | ;; | ||
+ | |||
+ | | ||
+ | |||
+ | echo " | ||
+ | | ||
+ | exit | ||
+ | ;; | ||
+ | *) | ||
+ | echo >&2 " | ||
+ | exit 1 | ||
+ | ;; | ||
+ | esac | ||
+ | shift | ||
+ | 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.txt · Zuletzt geändert: 2018/04/01 15:56 von jau