Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:solar_inverters:sma

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Nächste Überarbeitung
Vorhergehende Überarbeitung
Nächste ÜberarbeitungBeide Seiten der Revision
hardware:channels:solar_inverters:sma [2018/01/25 13:32] – angelegt jauhardware:channels:solar_inverters:sma [2018/06/18 10:43] – Hinweis auf SBFspot jau
Zeile 1: Zeile 1:
-#redirect /howto/wechselrichter_sma+===== SMA Wechselrichter ===== 
 +Der Hersteller SMA bietet Solarwechselrichter [[http://www.sma.de/produkte/solarwechselrichter.html]] an, 
 +deren Daten über verschiedenen Schnittstellen ausgelesen werden können. SMA bietet zum Auslesen die 
 +Software "Sunny Explorer" an, die unter Windows läuft. 
 +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 Seite sind einige Beispiele gezeigt. 
 + 
 +==== SMAspot ==== 
 +Die Software SMAspot ist bei [[https://smaspot.codeplex.com/]] zu finden. 
 +<note important>SMASpot wurde eingestellt, das Projekt wird unter dem Namen SBFspot weitergeführt. [[https://github.com/SBFspot/SBFspot/]]</note> 
 +=== 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. /usr/local/src 
 +  - Anlegen eines Verzeichnisses z.b. "smaspot" 
 +  - 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/Release/SMASpot /usr/local/bin  
 + 
 +=== Anpassen der Konfiguration für Bluetooth === 
 +== Bluetooth Adapter prüfen == 
 +Beispiel: Cambridge Silicon Radio Bluetooth Adapter 
 +<code> 
 +lsusb | grep -i blue 
 +Bus 002 Device 003: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) 
 +</code> 
 +== SMA Geräte mit Bluetooth suchen == 
 +XXXX verdeckt die Angaben des konkreten Beispiels 
 +<code> 
 +hcitool scan | grep -i SMA 
 + 00:80:25:24:XX:XX SMA002d SN: 200221XXXX SN200221XXXX 
 + 00:80:25:29:XX:XX SMA002d SN: 213010XXXX SN213010XXXX 
 +</code> 
 + 
 +== Ergebnisse in SMASpot.cfg eintragen == 
 +Wenn mehrere Inverter vorliegen einfach mehrere cfg Dateien erstellen z.B. 4000Watt.cfg, 1300Watt.cfg  
 + 
 +== SMASpot testen == 
 +<code> 
 +SMASpot -v  
 +</code> 
 +oder  
 +<code> 
 +SMASpot -v -cfg4000Watt.cfg 
 +</code> 
 + 
 +==== Beispiel STP 9000 TL-20 mit SMASpot per Ethernet / Perl->Middleware ==== 
 + 
 + 
 +Ich besitze den Wechselrichter STP 9000TL-20 [[http://www.sma.de/produkte/solar-wechselrichter-ohne-transformator/sunny-tripower-5000tl-6000tl-7000tl-8000tl-9000tl.html]]. Dieser hat direkt einen Ethernetanschluss, der mit dem Tool SMAspot angesprochen werden kann. Das Tool ist zu kompilieren. Sobald es läuft, findet es den Wechselrichter und gibt ein paar Infos aus: 
 +SMAspot -sp0 -v 
 + 
 +Ich möchte den Gesamtertrag, sowie den Ertrag je String in den Volkszaehler übernehmen: 
 +Hierzu habe ich für den Gesamtertrag einen Kanal  
 +El. Energie (Zählerstände)  
 +und für den Ertrag je String  je einen Kanal  
 +El. Energie (Leistungswerte) 
 +angelegt. Die UUID sind später im Script einzutragen. 
 +Anbei das Script: 
 + 
 +<code perl sma.pl> 
 +#!/usr/bin/perl 
 +use LWP::UserAgent; 
 +open STATUS, "/home/markus/hack/sma/smaspot/bin/Release/SMAspot -sp0 -v |" 
 +or die "can't fork: $!"; 
 +while (<STATUS>) { 
 + if (/ETotal:[ ]*(.*)kWh/){ 
 + &submitt("e63106b0-dd25-11e3-9cd5-27aa144849cd",  $1); 
 +  
 +    } 
 +    if (/String 1 Pdc:[ ]*(.*)kW/){ 
 +    $value = $1; 
 +    $value =~ s/\.//g; 
 +    &submitt("103ec300-dd27-11e3-84b2-a98f0b16e92d",  $value); 
 +     
 +     
 +    } 
 +    if (/String 2 Pdc:[ ]*(.*)kW/){ 
 +    $value = $1; 
 +    $value =~ s/\.//g; 
 +    &submitt("2d130060-dd27-11e3-b78b-738251a19608",  $value); 
 +    } 
 +}  
 +close STATUS or die "bad netstat: $! $?"; 
 + 
 +#------ 
 +sub submitt 
 +
 +     $uuid =  $_[0] ; 
 +    $val =  $_[1] ; 
 +    print $uuid . " : " . $val . "\n"; 
 + 
 + 
 +    my $server_endpoint = "http://localhost/volkszaehler.org/htdocs/middleware.php/data/${uuid}.json?value=" . $val; 
 +#    get("http://localhost/volkszaehler.org/htdocs/middleware.php/data/2d130060-dd27-11e3-b78b-738251a19608.json?value=" . $1)."\n"; 
 +    #print "serverget = " .  $server_endpoint . "\n"; 
 + 
 +    # set custom HTTP request header fields 
 +    my $req = HTTP::Request->new(POST => $server_endpoint); 
 +    $req->header('content-type' => 'application/json'); 
 +    $req->header('x-auth-token' => 'kfksj48sdfj4jd9d'); 
 + 
 +    # add POST data to HTTP request body 
 +    $req->content(" "); 
 + 
 +    my $ua = LWP::UserAgent->new; 
 +    my $resp = $ua->request($req); 
 +    if ($resp->is_success) { 
 +      my $message = $resp->decoded_content; 
 +      print "Received reply: $message\n"; 
 +    } else { 
 +      print "HTTP GET error code: ", $resp->code, "\n"; 
 +      print "HTTP GET error message: ", $resp->message, "\n"; 
 +    } 
 + 
 +
 +</code> 
 + 
 +Das Script wird dabei einmal pro Minute mit cron aufgerufen. 
 +<code> 
 +*  * * * *    /usr/bin/perl /home/markus/hack/Volksz/sma.pl 
 +</code> 
 + 
 +Um den Eigenverbrauch zu bestimmen bilde ich die Differenz zwischen der Einspeisung, gemessen am Stromzähler. ( mit vzlogger) und der erzeugten Strommenge des SMA. Da der SMA immer etwas verzögert die Werte anzeigt, lege ich nur einen Messpunkt alle 15 Minuten ab: Die Kanäle sind zuvor in der Weboberfläche anzulegen, und mit mysql die channel_id zu selektieren.  
 +Änderung 04.06.2014: Die Berechnung des Gesamtverbrauchs ist aktualisiert.  
 + 
 +== Originalscript von Markus == 
 +<code bash eigenverbrauch.sh> 
 +#!/bin/bash 
 +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`, `timestamp`, `value`) select 7,  timestamp_2,   data_4.value - data_2.value /1000    from ( 
 +SELECT  
 +max(case when `channel_id`  = 2 then timestamp else 0 end) timestamp_2, 
 +max(case when `channel_id`  = 4 then timestamp else 0 end) timestamp_4 
 +  FROM `data` where channel_id in (2,4)  
 +and timestamp > (select max(timestamp) from data where `channel_id` = 7) 
 +group by floor(`timestamp`/60/1000/15) ) a inner join data data_2 on  timestamp_2  = data_2.timestamp and data_2.channel_id = 2 
 +inner join data data_4 on  timestamp_4  = data_4.timestamp and data_4.channel_id = 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`, `timestamp`, `value`) select 8,  timestamp_1,   (select data.value from data where channel_id = 7 and  data.timestamp <= data_1.timestamp order by timestamp desc limit 1) + data_1.value/1000     from  
 +
 +SELECT  
 +max(case when `channel_id`  = 1 then timestamp else 0 end) timestamp_1, 
 +max(case when `channel_id`  = 7 then timestamp else 0 end) timestamp_7 
 +  FROM `data` where channel_id in (1,7)  
 +group by floor(`timestamp`/60/1000/15)  
 +) a inner join data data_1 on  timestamp_1  = data_1.timestamp and data_1.channel_id = 1 
 +' | mysql --user=vz --password=dsdsdsdsds volkszaehler 
 + 
 +</code> 
 +auch diese Script wird mit cron gestartet, aber nur ein mal die Stunde. 
 +<code> 
 +1  * * * *    bash /home/markus/hack/Volksz/eigenverbrauch.sh 
 +</code> 
 + 
 +== Modifiziertes Script (Versuch von Wolfgang) == 
 +<code bash eigenverbrauch.sh> 
 +#!/bin/bash 
 +# calculate own PV usage  
 +# Author: Markus 2014-05-20 
 +# latest version: 
 +# $Header: /home/wf/smaspot/RCS/eigenverbrauch.bash,v 1.5 2014/05/29 10:17:11 wf Exp wf $ 
 + 
 +
 +# get the delete query for the given channel 
 +
 +deletequery() { 
 +  local l_channel=$1 
 +cat << EOF 
 +  DELETE  
 +   FROM `data`  
 +   WHERE `timestamp` =  
 +     (SELECT MAX(timestamp) FROM data WHERE channel_id = $l_channel)   
 +   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`, `timestamp`, `value`)  
 +    SELECT $l_chanel,  timestamp_2,   data_3.value - data_2.value /1000     
 +    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,$l_c3)  
 +          AND timestamp > ( 
 +            SELECT MAX(timestamp) FROM data WHERE `channel_id` = $l_channel  
 +          ) 
 +        GROUP by floor(`timestamp`/60/1000/15) ) a  
 +        INNER JOIN data data_2  
 +          ON  timestamp_2  = data_2.timestamp  
 +          AND data_2.channel_id = $l_c2  
 +        INNER JOIN data data_3  
 +          ON  timestamp_3  = data_3.timestamp  
 +          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 "^#" | mysql --user=$user --password=$password $db $debug 
 +insertquery 7 2 4 | egrep -v "^#" | mysql --user=$user --password=$password $db $debug 
 + 
 +# channel 8 is calculated from as channel 7 - channel 1 / 1000  
 +echo "DELETE FROM `data` WHERE channel_id = 8" |  mysql --user=$user --password=$password $db $debug 
 +insertquery 8 1 7 | egrep -v "^#" | mysql --user=$user --password=$password $db $debug 
 + 
 +</code> 
 +Und so sieht es aus: 
 + 
 +{{:howto:screenshotsma.jpg?800|}} 
 + 
 +==== 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 
 +   usage: ./sma2vz --vzurl=vzurl --cuuid_pwr=x --cuuid_kwh=y  
 +     [ --daytimeonly --lat=lattitude --lon=longitude] 
 +     [--loop --delay=delay]  
 +    | [--help]  
 +    | [--configure]  
 +     
 +     --vzurl=<url>  
 +        volkszaehler middleware url   
 +     
 +     --cuuid_pwr=<uuid>  
 +        channel uuid for power (watt) PV output  
 +     
 +     --cuuid_kwh=<uuid>   
 +       channel uuid for energy (kwH) PV total  
 +  
 +     --daytimeonly 
 +       do not post data at night (e.g. if your device does not supply data) 
 + 
 +     --lon=<longitude> 
 +       plant longitude geo coordinate 
 + 
 +     --lat=<lattitude> 
 +       plant lattitude geo coordinate 
 +     
 +     --loop   
 +       poll SMA inverters in a loop   
 +     
 +     --delay=<secs>   
 +       how many secs to wait between each reading (default: 15 secs) 
 +     
 +     --configure  
 +       create SMAsport configuration file(s)  
 +         modify ./sma2vz inverters shell function  
 +         here document to fit your plant's data 
 +</code> 
 + 
 +<code bash configure example> 
 +./sma2vz --lat 51.244 --lon 6.52 --configure 
 +</code>         
 + 
 +<code bash loop example> 
 +./sma2vz \ 
 +  --vzurl "http://capri/vz/middleware.php/data"
 +  --cuuid_pwr "7744bbf0-e74d-11e3-9ec7-xxxx"
 +  --cuuid_kwh "460feba0-e74f-11e3-8a0d-xxxx"
 +  --daytimeonly --lat 51.244 --lon 6.52 \ 
 +  --loop --delay 15 
 +</code> 
 + 
 +<code bash cron example> 
 +cd /home/wf/smaspot 
 +/home/wf/smaspot/sma2vz \ 
 +  --vzurl "http://capri/vz/middleware.php/data"
 +  --cuuid_pwr "7744bbf0-e74d-11e3-9ec7-xxxx"
 +  --cuuid_kwh "460feba0-e74f-11e3-8a0d-xxxx"
 +  --daytimeonly --lat 51.244 --lon 6.52 >> /var/log/energymeter.log 
 +</code> 
 + 
 +<code | logoutput example> 
 +2014-06-01 12:52:08 PV:  1409 Watt   6699.801 kwH sun rise:05:21 set:21:42 
 +2014-06-01 12:53:07 PV:  2176 Watt   6699.826 kwH sun rise:05:21 set:21:42 
 +2014-06-01 12:54:07 PV:  1699 Watt   6699.855 kwH sun rise:05:21 set:21:42 
 +2014-06-01 12:55:07 PV:  3375 Watt   6699.898 kwH sun rise:05:21 set:21:42 
 +2014-06-01 12:56:07 PV:  3578 Watt   6699.957 kwH sun rise:05:21 set:21:42 
 +</code> 
 + 
 +Any feedback please to wf (at) bitplan.com - enjoy! 
 + 
 + 
 +<code bash sma2vz> 
 +#/bin/bash 
 +# SMAspot with Volkszaehler 
 +# WF 2014-05-29 
 +# $Header: /home/wf/smaspot/RCS/sma2vz,v 1.8 2014/06/01 10:49:38 wf Exp wf $ 
 + 
 +
 +# get a configuration 
 +#  param 1: bluetooth address 
 +#  param 2: name of configuration/plant 
 +#  param 3: "USER" password for SMA device 
 +#  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, SBF 
 +
 +#  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's Bluetooth address 
 +# Windows: smaspot -scan 
 +# Linux  : hcitool scan 
 +# IMPORTANT FOR SPEEDWIRE USERS: COMMENT OUT BTADDRESS (PUT # IN FRONT) 
 +BTAddress=$l_btaddr 
 + 
 +# SMA Inverter's Speedwire IP address 
 +# 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 
 +#IP_Address=0.0.0.0 
 + 
 +# User password (default 0000) 
 +Password=$l_password 
 + 
 +# MIS_Enabled (Multi Inverter Support: Default=0 Disabled) 
 +# +------------+-------+-------------+ 
 +# | #Inverters | NetID | MIS_Enabled | 
 +# +------------+-------+-------------+ 
 +# |      1         | Don't Care  | 
 +# +------------+-------+-------------+ 
 +# |      1       > |      0      | 
 +# +------------+-------+-------------+ 
 +# |      >1    |   > |      1      | 
 +# +------------+-------+-------------+ 
 +MIS_Enabled=0 
 + 
 +# Plantname 
 +Plantname=$l_name 
 + 
 +# OutputPath (Place to store CSV files) 
 +#  
 +# Windows: C:\TEMP\SMA\%Y 
 +# Linux  : /home/sbf/Documents/sma/%Y 
 +# %Y %m and %d will be expanded to Year Month and Day 
 +OutputPath=$l_path/%Y 
 + 
 +# OutputPathEvents (Place to store CSV files for events) 
 +# If omitted, OutputPath is used 
 +OutputPathEvents=$l_path/Events 
 + 
 +# Position of pv-plant http://itouchmap.com/latlong.html 
 +# 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://www.cplusplus.com/reference/clibrary/ctime/strftime/ 
 +DateTimeFormat=%Y-%m-%d %H:%M:%S 
 + 
 +# DateFormat (default %d/%m/%Y) 
 +DateFormat=%-%m-%d 
 + 
 +# DecimalPoint (comma/point default comma) 
 +DecimalPoint=point 
 + 
 +# TimeFormat (default %H:%M:%S) 
 +TimeFormat=%H:%M:%S 
 + 
 +# 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;en-US;fr-FR;nl-NL;es-ES;it-IT 
 +# Default en-US 
 +Locale=de-DE 
 + 
 +# Timezone 
 +# Select the right timezone in date_time_zonespec.csv 
 +# e.g. Timezone=Europe/Brussels 
 +Timezone=Europe/Berlin 
 + 
 +########################### 
 +### 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/LF|Delimiter semicolon|Decimalpoint comma|Precision 3 
 +# 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:mm:ss;kWh;kW 
 +# 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/semicolon default semicolon) 
 +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];DcMs.Watt[B]...) 
 +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 
 + 
 +#PVoutput_SID 
 +#Sets PVoutput System ID 
 +PVoutput_SID= 
 + 
 +#PVoutput_Key 
 +#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's temperature 
 +InverterTemp=0 
 + 
 +# InverterTempMapTo (default v5 = Use standard PVoutput Temperature Graph) 
 +# In Donation Mode only, map inverter's temperature to extended data field (v7..v12) 
 +# For more info, see http://pvoutput.org/help.html#donations  
 +InverterTempMapTo=v5 
 + 
 +# CumulativeEnergy (default 0 = Today's Energy) 
 +# Set the cumulative flag = 1 when you wish to pass lifetime energy or 0 for today's energy 
 +# 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  
 +#   hcitool scan | grep SMA 
 +#  
 +# 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 "USER" that the SMA Device expects 
 +# fourth column is the latitude 
 +# fifth  column is the longitude 
 +cat << EOF 
 +00:80:25:24:xx:xy 1300Watt password /home/wf/smaspot 
 +00:80:25:29:xx:xy 4000Watt password /home/wf/smaspot 
 +EOF 
 +
 + 
 +
 +# create configuration files 
 +
 +configure() { 
 +  checklonlat "configure" 
 +inverters | while read btaddr name password path; do 
 +  echo "creating ${name}.cfg for bluetooth addr $btaddr" 1>&
 +  smaspot_config $btaddr $name $password $lon $lat $path > ${name}.cfg 
 +done 
 +
 + 
 +
 +# get the sma meter reading 
 +
 +getsmameter() { 
 +  # temp filename base for SMAspor result 
 +  tmp=/tmp/smaspot$$ 
 +  # 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 "running smaspot with ${name}.cfg for bluetooth addr $btaddr" 
 +    ./SMAspot -v -nocsv -cfg${name}.cfg > ${tmp}_${name} 
 +    # the lines we need look like: 
 +    #  EToday: 3.358kWh 
 +   #  ETotal: 5151.294kWh 
 +    #  Total Pac   :   0.442kW 
 + 
 +    # let's filter the result with awk 
 +    cat ${tmp}_${name} | awk ' 
 +# set the field separator fitting the x: y format 
 +BEGIN        { FS=":";doublequote="\x22"
 +# check the input lines for the three patterns and remove 
 +# the unit at the end - assign to the three variables 
 +# etoday, etotal and totalpac 
 +/EToday:/    { etoday  =$2;gsub("kWh","",etoday)   } 
 +/ETotal:/    { etotal  =$2;gsub("kWh","",etotal)   } 
 +/Total Pac/  { totalpac=$2;gsub("kW" ,"",totalpac) } 
 +# at the end of all lines print out a single json formatted result line 
 +END          {  
 +                printf("{%s,%s,%s}\n",  
 +                  json("etoday",etoday), 
 +                  json("etotal",etotal), 
 +                  json("totalpac",totalpac))  
 +             } 
 +# helper function to create json name values 
 +function json(name,value,result) { 
 +  # trim value 
 +  gsub(" ","",value); 
 +  result=quote(name)":"quote(value); 
 +  return result  
 +
 + 
 +# helper function to quote a string 
 +function quote(s,result) { 
 +  result=doublequote s doublequote; 
 +  return result  
 +}'  
 +  rm ${tmp}_${name} 
 +done 
 +
 + 
 +
 +# show usage 
 +
 +usage() {  
 +cat << EOF 
 +   usage: $0 --vzurl=vzurl --cuuid_pwr=x --cuuid_kwh=y  
 +     [ --daytimeonly --lat=lattitude --lon=longitude] 
 +     [--loop --delay=delay]  
 +    | [--help]  
 +    | [--configure]  
 +     
 +     --vzurl=<url>  
 +        volkszaehler middleware url   
 +     
 +     --cuuid_pwr=<uuid>  
 +        channel uuid for power (watt) PV output  
 +     
 +     --cuuid_kwh=<uuid>   
 +       channel uuid for energy (kwH) PV total  
 +  
 +     --daytimeonly 
 +       do not post data at night (e.g. if your device does not supply data) 
 + 
 +     --lon=<longitude> 
 +       plant longitude geo coordinate 
 + 
 +     --lat=<lattitude> 
 +       plant lattitude geo coordinate 
 +     
 +     --loop   
 +       poll SMA inverters in a loop   
 +     
 +     --delay=<secs>   
 +       how many secs to wait between each reading (default: 15 secs) 
 +     
 +     --configure  
 +       create SMAsport configuration file(s)  
 +         modify $0 inverters shell function  
 +         here document to fit your plant's data 
 +EOF 
 +  exit 1 
 +
 + 
 +#  
 +# show error and exit 
 +
 +error() { 
 +  local l_msg=$1 
 +  local l_hint=$2 
 +  echo "error $0: $l_msg" 1>&
 +  echo "  you might want to $l_hint !" 1>&
 +  exit 1 
 +
 + 
 +
 +# check that longitude and lattitude are supplied 
 +
 +checklonlat() { 
 +  local l_title="$1" 
 +  if [ "$lon" == ""
 +  then 
 +    error "option --lon" "supply lon longitude setting for $l_title to work" 
 +  fi 
 +  if [ "$lat" == ""
 +  then 
 +    error "option --lat" "supply lat lattitude setting for $l_title to work" 
 +  fi 
 +
 + 
 +# defaults 
 +delay=15 
 +maxloops=1 
 +daytimeonly=0 
 + 
 +# check command line arguments 
 +while [ $# -gt 0 ] 
 +do 
 +  arg="$1" 
 +  #echo "$arg" 
 +  case "$arg" in  
 +     --help) 
 +       usage 
 +       ;; 
 + 
 +     --vzurl)  
 +       vzurl="$2" 
 +       shift 
 +       ;; 
 + 
 +     --cuuid_pwr)  
 +       cuuid_pwr="$2" 
 +       shift 
 +       ;; 
 + 
 +     --cuuid_kwh)  
 +       cuuid_kwh="$2" 
 +       #echo $cuuid_kwh 
 +       shift 
 +       ;; 
 + 
 +     --daytimeonly) 
 +       daytimeonly=1; 
 +       ;; 
 + 
 +     --lat)  
 +       lat="$2" 
 +       shift 
 +       ;; 
 + 
 +     --lon)  
 +       lon="$2" 
 +       shift 
 +       ;; 
 + 
 +     --delay)  
 +       delay=$2      
 +       shift 
 +       ;; 
 + 
 +     --loop) 
 +       maxloops=10000000; 
 +       ;; 
 + 
 +     --configure) 
 + 
 +       echo "creating configuration files" 
 +       configure 
 +       exit 
 +       ;; 
 +     *) 
 +       echo >&2 "Invalid argument: $1" 
 +       exit 1 
 +     ;; 
 +   esac 
 +   shift 
 +done 
 + 
 +# check that options are set 
 +if [ "$vzurl" == ""
 +then 
 +  error "option --vzurl is missing" "check and use volkszaehler middleware url" 
 +fi 
 +if [ "${cuuid_pwr}" == ""
 +then 
 +  error "option --cuuid_pwr is missing" "check the uuid for the PV power (Watt) channel" 
 +fi 
 +if [ "$cuuid_kwh" == ""
 +then 
 +  error "option --cuuid_kwh" "check the uuid for the PV energy (kwH) channel" 
 +fi 
 +if [ "$daytimeonly" -eq 1 ] 
 +then 
 +  checklonlat "daytimeonly" 
 +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> 
 +<code php sma2vz.php> 
 +<?php 
 +  /** 
 +   * read meter data from SMA device 
 +   * and post it to volkszaehler 
 +   * $Header: /home/wf/smaspot/RCS/sma2vz.php,v 1.6 2014/06/01 10:40:27 wf Exp wf $ 
 +   */ 
 + 
 +// common code for reading and posting 
 +require __DIR__.'/vzapihelper.php'; 
 + 
 +  /** 
 +   * check the daytime values 
 +   */ 
 +  function daytime($latitude,$longitude) { 
 +    $result=array(); 
 +    // 08:53 CEST 
 +    // $time_format = 'H:i T'; 
 +    // 08:53 
 +    $time_format = 'H:i'; 
 + 
 +    // find time offset in hours 
 +    $tzoffset = date("Z")/60 / 60; 
 + 
 +    $zenith = 90+(50/60); // True sunrise/sunset 
 + 
 +    // determine sunrise time 
 +    $sunrise = date_sunrise(time(), SUNFUNCS_RET_STRING, $latitude, $longitude, $zenith, $tzoffset); 
 +    $sunrise_time = date($time_format, strtotime(date("Y-m-d") . ' '. $sunrise)); 
 +    // determine sunset time 
 +    $sunset = date_sunset(time(), SUNFUNCS_RET_STRING, $latitude, $longitude, $zenith, $tzoffset); 
 +    $sunset_time = date($time_format, strtotime(date("Y-m-d") . ' '. $sunset)); 
 + 
 +    // check whether it's daytime 
 +    $sunrise_epoch = date_sunrise(time(), SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tzoffset); 
 +    $sunset_epoch  = date_sunset(time(), SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tzoffset); 
 +    $time_epoch = time(); // time now 
 + 
 +    $result["daytime"]=($time_epoch < $sunset_epoch and $time_epoch > $sunrise_epoch); 
 + 
 +    $result["rise"] = $sunrise_time; 
 +    $result["set"] = $sunset_time; 
 +    $result["time"] = date("Y-m-d H:i:s",time()); 
 +    return $result; 
 +  }  
 + 
 +  $loop=0; 
 +  // possible command line options 
 +  // --vzurl= --cuuid_pwr= --cuuid_kwh= --daytimeonly 
 +  $longopts=array("vzurl:","cuuid_pwr:","cuuid_kwh:","lat:","lon:","daytimeonly:"); 
 +  $shortopts=""; 
 +  $options=getopt($shortopts,$longopts); 
 +  // the volkszaehler middleware url 
 +  $vzurl=checkoption("vzurl",$options); 
 +  // channel uuids 
 +  // power (watts) 
 +  $cuuid_pwr=checkoption("cuuid_pwr",$options); 
 +  // energy (kWh) 
 +  $cuuid_kwh=checkoption("cuuid_kwh",$options); 
 +  // daytimeonly?  
 +  $daytimeonly=checkoption("daytimeonly",$options); 
 +  if ($daytimeonly) { 
 +    $latitude=checkoption("lat",$options); 
 +    $longitude=checkoption("lon",$options); 
 +  } 
 +   
 +  $jsonlines=file("php://stdin"); 
 +  $tmeter=array(); 
 +  foreach ($jsonlines as $line_nume => $json) { 
 +    // get the meter reading 
 +    $meter=json_decode($json, true); 
 +    #var_dump($meter); 
 +    foreach ($meter as $name => $value) { 
 +      if (!array_key_exists($name,$tmeter))  
 +        $tmeter[$name]=0; 
 +      $tmeter[$name]+=$value; 
 +    } 
 +  } 
 +  #var_dump($tmeter); 
 +  //array(3) { ["etoday"]=> float(2.52) 
 +  // ["etotal"]=> float(6632.462) 
 +  //["totalpac"]=> float(2.478) } 
 +  $etotal=$tmeter["etotal"]; 
 +  $totalpac=$tmeter["totalpac"]*1000; 
 +  if ($daytimeonly) { 
 +    $daytime=daytime($latitude,$longitude); 
 +    if (!$daytime["daytime"]) { 
 +      printf("%s after sunset: %s wait for sunrise: %s\n",$daytime["time"],$daytime["set"],$daytime["rise"]); 
 +      exit(2);  
 +    } 
 +  } 
 +  # total wattage of all inverters 
 +  post2vz($vzurl,$cuuid_pwr,$totalpac); 
 +  # total kwh of all inverters  
 +  post2vz($vzurl,$cuuid_kwh,$etotal); 
 +  if ($daytimeonly) { 
 +    printf("%s PV: % 5d Watt % 10.3f kwH sun rise:%s set:%s\n",$daytime["time"],$totalpac,$etotal,$daytime["rise"],$daytime["set"]);  
 +  } else { 
 +    printf("PV Current/Total: %4.0f Watt %.3f kwH\n",$totalpac,$etotal);  
 +  } 
 +  exit(0); 
 +?> 
 + 
 +</code> 
 + 
 +<code php vzapihelper.php> 
 +<?php 
 +  /** 
 +   * vzapi helper functions 
 +   * $Header: /home/wf/youless/RCS/vzapihelper.php,v 1.3 2014/05/30 06:57:23 wf Exp $ 
 +   */ 
 + 
 +  /** 
 +   * get a curl channel 
 +   */ 
 +  function curl($url) { 
 +    //  Initiate curl 
 +    $ch = curl_init(); 
 +    // Disable SSL verification 
 +    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
 +    // Will return the response, if false it print the response 
 +    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
 +    // Set the url 
 +    curl_setopt($ch, CURLOPT_URL,$url); 
 + 
 +    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,$fields) { 
 +     $ch=curl($url); 
 +     $fields_string=""; 
 +     //url-ify the data for the POST 
 +    foreach($fields as $key=>$value) {  
 +      $fields_string .= $key.'='.$value.'&';  
 +    } 
 +    rtrim($fields_string, '&'); 
 +    curl_setopt($ch,CURLOPT_POST, count($fields)); 
 +    curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);   
 +    $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 
 +    */ 
 +   function post2vz($vzurl,$cuuid,$value,$debug=false) { 
 +     // post data to middleware according to:  
 +     // http://wiki.volkszaehler.org/development/api/reference 
 + 
 +     // adapt timestamp to volkszaehler conventions 
 + $timestamp=time()*1000; 
 + 
 +     # first  
 +     $posturl=$vzurl."/".$cuuid.".json"; 
 +     $fields=array("ts"=>$timestamp,"value" => $value ); 
 +     $presult=postUrl($posturl,$fields); 
 +     if ($debug) { 
 +       echo $presult; 
 +     } 
 +   } 
 + 
 +  /** 
 +   * check that option $opt is available in $options 
 +   * return the value if available 
 +   */ 
 +  function checkoption($opt,$options) { 
 +    if (array_key_exists($opt,$options)) 
 +      return $options[$opt]; 
 +    else 
 +      die("option $opt missing!\n"); 
 +  } 
 + 
 +?> 
 + 
 +</code>
hardware/channels/solar_inverters/sma.txt · Zuletzt geändert: 2020/12/18 13:30 von wasserma