Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:solar_inverters:sma

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Nächste ÜberarbeitungBeide Seiten der Revision
hardware:channels:solar_inverters:sma [2018/01/25 13:32] – angelegt jauhardware:channels:solar_inverters:sma [2018/04/01 15:54] – veschoben von /howto/wechselrichter_sma 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 inzwischen bei [[https://smaspot.codeplex.com/]] zu finden. Die downloads 
 +befinden sich unter [[https://smaspot.codeplex.com/releases]]  
 +=== 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 [[https://smaspot.codeplex.com/]] angesprochen werden kann. Das Tool smaspot 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