start.sh on boot, run inverter.php in infinite loop

This commit is contained in:
2012-11-27 09:26:25 +01:00
commit 9c9fce8383
7 changed files with 2185 additions and 0 deletions

20
etc/init.d/inverter Normal file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: inverter
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 5
# Description:
### END INIT INFO
case "$1" in
'start')
/opt/inverter/start.sh
;;
'stop')
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
exit 0

362
opt/inverter/config.ini Normal file
View File

@@ -0,0 +1,362 @@
#-----------------------------------------
# CONFIGURATION FILE FOR INVERTER MONITOR
#-----------------------------------------
# Should work with PHOENIXTEC manufactured inverters: CMS / Sun Ezy / Orion / Eaton et al.
#
# Should at least work with:
# * CMS2000 (CMS 2000)
# * CMS10000 (CMS 10000) - requires more testing though
# * SE2800 (SunEzy 2800)
# * SE4600 (SunEzy 600E)
# * ETN2000 (Eaton 2000)
#
# NOTE: http://pvoutput.org capable of accepting 60 data updates per hour,
# but will only keep 1 every 5-10mins depending on your setting.
#-------
# flags
#-------
[flags]
debug = 0 # 0 = NO, 1 = YES
use_pvoutput = 1 # 0 = NO, 1 = YES to export data to http://pvoutput.org
use_rrdtool = 1 # 0 = NO, 1 = YES to export data to rrdtool for graphing
#-------------------
# number of seconds
#-------------------
[secs]
datapoll_freq = 5
pvoutput_freq = 300 # every 5-10mins per your setting in http://pvoutput.org
timeout = 2
reinit = 10 # -1 = infinite num of times (ie dont die)
#------------------
# file path to use
#------------------
[paths]
windows = "C:/solar" # windows
other = "/opt/inverter/data" # unix/linux
#-------------------------
# script and binary files
#-------------------------
[scripts]
pvoutput = "perl pvoutput.pl" # to export data to http://pvoutput.org
create_rrd = "perl create_rrd.pl" # to export data to rrdtool for graphing
rrdtool_exe_win = "rrdtool" # windows
rrdtool_exe_oth = "/usr/bin/rrdtool" # unix/linux
#----------------------
# serial port settings
#----------------------
[serial]
baud = 9600
port_win = "COM5" # windows, COM port
#port_oth = "/dev/ttyS0" # unix/linux, serial port
port_oth = "/dev/ttyUSB0" # unix/linux, USB port
#port_oth = "/dev/rfcomm0" # unix/linux, bluetooth port
parity = "none"
databits = 8
stopbits = 1
handshake = "none"
datatype = 'raw'
#------------------------------------------------
# hex start indeces and lengths for certain data
#------------------------------------------------
[hex]
data_to_follow_index = 8
capacity_index = 20
capacity_length = 12
firmware_index = 32
firmware_length = 14
model_index = 46
model_length = 28
manuf_index = 74
manuf_length = 32
serial_index = 106
serial_length = 20
other_index = 138
other_length = 8
confserial_index = 18
#-----------------------------------------------
# hex packet codes - SEND (request to inverter)
#-----------------------------------------------
[sendhex]
initialise = "aaaa010000000004000159"
serial = "aaaa010000000000000155"
conf_serial1 = "aaaa0100000000010b"
conf_serial2 = "01"
version = "aaaa01000001010300015a"
paramfmt = "aaaa010000010101000158"
param = "aaaa01000001010400015b"
datafmt = "aaaa010000010100000157"
data = "aaaa010000010102000159"
#------------------------------------------------
# hex packet codes - RECV (response to inverter)
#------------------------------------------------
[recvhex]
serial = "aaaa0000010000800a"
conf_serial = "aaaa000101000081"
version = "aaaa000101000183"
paramfmt = "aaaa000101000181"
param = "aaaa000101000184"
datafmt = "aaaa000101000180"
data = "aaaa000101000182"
#---------------------
# inverter parameters
#---------------------
[param_vpvstart]
hexcode = "40"
multiply = 0.1
measure = "V"
index = -1
descr = "PV Start-up voltage"
[param_tstart]
hexcode = "41"
multiply = 1
measure = "Sec"
index = -1
descr = "Time to connect grid"
[param_vacmin]
hexcode = "44"
multiply = 0.1
measure = "V"
index = -1
descr = "Minimum operational grid voltage"
[param_vacmax]
hexcode = "45"
multiply = 0.1
measure = "V"
index = -1
descr = "Maximum operational grid voltage"
[param_facmin]
hexcode = "46"
multiply = 0.01
measure = "Hz"
index = -1
descr = "Minimum operational frequency"
[param_facmax]
hexcode = "47"
multiply = 0.01
measure = "Hz"
index = -1
descr = "Maximum operational frequency"
[param_zacmax]
hexcode = "48"
multiply = 1
measure = "mOhm"
index = -1
descr = "Maximum operational grid impendance"
[param_dzac]
hexcode = "49"
multiply = 1
measure = "mOhm"
index = -1
descr = "Allowable Delta Zac of operation"
#---------------
# inverter data
#---------------
[data_temp]
hexcode = "00"
multiply = 0.1
measure = "deg C"
index = -1
descr = "Internal Temperature"
[data_vpv1]
hexcode = "01"
multiply = 0.1
measure = "V"
index = -1
descr = "Panel 1 Voltage"
[data_vpv2]
hexcode = "02"
multiply = 0.1
measure = "V"
index = -1
descr = "Panel 2 Voltage"
[data_vpv3]
hexcode = "03"
multiply = 0.1
measure = "V"
index = -1
descr = "Panel 3 Voltage"
[data_ipv1]
hexcode = "04"
multiply = 0.1
measure = "A"
index = -1
descr = "Panel 1 DC Current"
[data_ipv2]
hexcode = "05"
multiply = 0.1
measure = "A"
index = -1
descr = "Panel 2 DC Current"
[data_ipv3]
hexcode = "06"
multiply = 0.1
measure = "A"
index = -1
descr = "Panel 3 DC Current"
[data_etoday]
hexcode = "0d"
multiply = 0.01
measure = "kWh"
index = -1
descr = "Accumulated Energy Today"
[data_vpv]
hexcode = "40"
multiply = 0.1
measure = "V"
index = -1
descr = "Panel Voltage"
[data_iac]
hexcode = "41"
multiply = 0.1
measure = "A"
index = -1
descr = "Grid Current"
[data_vac]
hexcode = "42"
multiply = 0.1
measure = "V"
index = -1
descr = "Grid Voltage"
[data_fac]
hexcode = "43"
multiply = 0.01
measure = "Hz"
index = -1
descr = "Grid Frequency"
[data_pac]
hexcode = "44" # "0b" for 3phase
multiply = 1
measure = "W"
index = -1
descr = "Output Power"
[data_zac]
hexcode = "45"
multiply = 1
measure = "mOhm"
index = -1
descr = "Grid Impedance"
[data_etotalh]
hexcode = "47" # "07" for 3phase
multiply = 256
measure = "kWh"
index = -1
descr = "Accumulated Energy (high bit)"
[data_etotall]
hexcode = "48" # "08" for 3phase
multiply = 0.1
measure = "kWh"
index = -1
descr = "Accumulated Energy (low bit)"
[data_htotalh]
hexcode = "49" # "09" for 3phase
multiply = 256
measure = "hrs"
index = -1
descr = "Working Hours (high bit)"
[data_htotall]
hexcode = "4a" # "0a" for 3phase
multiply = 1
measure = "hrs"
index = -1
descr = "Working Hours (low bit)"
[data_mode]
hexcode = "4c" # "0c" for 3phase
multiply = 1
measure = " "
index = -1
descr = "Operating Mode"
[data_errgv]
hexcode = "78"
multiply = 1
measure = " "
index = -1
descr = "Error message: GV fault value"
[data_errgf]
hexcode = "79"
multiply = 1
measure = " "
index = -1
descr = "Error message: GF fault value"
[data_errgz]
hexcode = "7a"
multiply = 1
measure = " "
index = -1
descr = "Error message: GZ fault value"
[data_errtemp]
hexcode = "7b"
multiply = 1
measure = " "
index = -1
descr = "Error message: Tmp fault value"
[data_errpv1]
hexcode = "7c"
multiply = 1
measure = " "
index = -1
descr = "Error message: PV1 fault value"
[data_errgfc1]
hexcode = "7d"
multiply = 1
measure = " "
index = -1
descr = "Error message: GFC1 fault value"
[data_errmode]
hexcode = "7e"
multiply = 1
measure = " "
index = -1
descr = "Error mode"

View File

@@ -0,0 +1,54 @@
#!/usr/bin/perl -w
#
# AS AT 27Mar2011
#
# This creates the rrd file using rrdtool (Round Robin Database Tool)
# Download & install rrdtool for your platform (unix/linux/windows)
# - http://oss.oetiker.ch/rrdtool/download.en.html
# - http://www.mywebhostingblog.net/window-hosting/install-rrdtool-on-windows-server/]
#
# CREATED BY: slampt with help from JinbaIttai
#
# + editions by shell_l_d:
# + converted to perl script
#
# Usage examples:
# perl create_rrd.pl "c:/solar/inverter.rrd" "c:/rrdtool/rrdtool"
# perl create_rrd.pl "/tmp/inverter.rrd" "/usr/bin/rrdtool"
#
# Arguments:
# $ARGV[0] = path & name for the new rrd file
# $ARGV[1] = path to rrdtool
#
#######################################################################
my $rrdfile = $ARGV[0];
my $rrdexe = $ARGV[1];
#
# Info: http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html
# --step = base interval in secs with which data will be fed into the RRD.
# --start = time in secs since EPOCH when first value should be added to the RRD
# DS = Data Source
# DS:ds-name:GAUGE|COUNTER|DERIVE|ABSOLUTE:heartbeat:min:max
# RRA = Round Robin Archive
# RRA:AVERAGE|MIN|MAX|LAST:xff:steps:rows
#
my $rrdCreateLine = "--step 60 " .
# "--start 1300774440 " .
"DS:TEMP:GAUGE:120:U:U " .
"DS:VPV:GAUGE:120:U:U " .
"DS:IAC:GAUGE:120:U:U " .
"DS:VAC:GAUGE:120:U:U " .
"DS:FAC:GAUGE:120:U:U " .
"DS:PAC:GAUGE:120:0:U " .
"DS:ETOTAL:GAUGE:120:0:U " .
"DS:HTOTAL:GAUGE:120:0:U " .
"DS:MODE:GAUGE:120:0:U " .
"DS:ETODAY:GAUGE:120:0:U " .
"RRA:AVERAGE:0.5:1:576 " . # 1*60secs= 1min , 576* 1min = 9.6hrs = 0.4days
"RRA:AVERAGE:0.5:6:672 " . # 6*60secs= 6mins, 672* 6mins = 67.2hrs = 2.8days
"RRA:AVERAGE:0.5:24:732 " . # 24*60secs= 24mins, 732* 24mins = 292.8hrs = 12.2days
"RRA:AVERAGE:0.5:144:1460"; #144*60secs=144mins, 1460*144mins = 3504.0hrs = 146.0days
system( "$rrdexe create $rrdfile $rrdCreateLine" );

44
opt/inverter/inverter.php Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/php
<?php
$sWake = '7:30';
$sSleep = '17:30';
$sTask = '/opt/inverter/inverter.pl > /dev/null';
printf("Be awake between %s and %s\n", $sWake, $sSleep);
$fWake = getHour($sWake);
$fSleep = getHour($sSleep);
chdir('/opt/inverter/');
while (true) {
// Check for current need to be awake
$fNow = getHour();
if (!($bAwake = $fNow >= $fWake)) {
printf("[%s] Too early to wake!\n", date('r'));
} else if ($bSleep = $fNow >= $fSleep) {
printf("[%s] Time to sleep!\n", date('r'));
}
if ($bAwake && !$bSleep) {
// Need to be awake now
printf("[%s] Running task\n", date('r'));
system($sTask);
printf("[%s] Task ended\n", date('r'));
} else {
// Don't need to be awake now
if (!$bAwake) {
// Sleep untill wake time
$iTime = strtotime($sWake);
} else {
// Sleep untill next day wake time
$iTime = strtotime(sprintf('%s + 1 day', $sWake));
}
printf("[%s] Sleeping untill: %s\n", date('r'), date('r', $iTime));
time_sleep_until($iTime);
}
}
echo "\n";
function getHour($sTime = null) {
$iTime = $sTime === null ? time() : strtotime($sTime);
return date('H', $iTime) + date('i', $iTime) / 60;
}

1582
opt/inverter/inverter.pl Normal file

File diff suppressed because it is too large Load Diff

121
opt/inverter/pvoutput.pl Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/perl -w
#
# AS AT 04May2011
#
# Submit solar production data to pvoutput.org per http://pvoutput.org/help.html#api
#
# Setup your pvoutput settings per http://pvoutput.org/help.html#api
# Set all values in @PVOUTPUT in this script to match those in your pvoutput settings
# - API_KEY & SYSTEM_ID to your settings from pvoutput.org
# - SERIAL_NUM to your inverter's serial number
# - add another record (in curly braces) if you have more than 1 inverter
#
# V1: Initial release
#
# Copyright Eric Sandeen <sandeen@sandeen.net> 2010
# released under GNU GPL v3 or later
#
# + editions by mmcdon23:
# + removed enphase envoy lines
# + added 4 arguments
#
# + editions by shell_l_d:
# + added serial_num argument so works for multiple inverters
# + replaced variables with @PVOUTPUT array of hashes
# + removed die if $current_watts = 0
#
# Usage examples:
# perl pvoutput.pl 5500 1813 20110307 12:15 1234567890
#
# Arguments:
# $ARGV[0] = (ETODAY) watt hrs exported so far today
# $ARGV[1] = (PAC) current watts
# $ARGV[2] = (VAC) current voltage
# $ARGV[3] = date (YYYYMMDD)
# $ARGV[4] = time (HH:MM)
# $ARGV[5] = inverter serial number - in case of multiple inverters
#
#######################################################################
use HTTP::Request::Common qw(POST GET);
use LWP::UserAgent; # Web User Agent
use strict;
my $daily_watthrs = $ARGV[0];
my $current_watts = $ARGV[1];
my $current_volts = $ARGV[2];
my $log_date = $ARGV[3];
my $log_time = $ARGV[4];
my $serial_num = $ARGV[5];
use constant {
DEBUG_SCRIPT => 0, # 0 = NO, 1 = YES
LIVE_DATA_URL => "http://pvoutput.org/service/r1/addstatus.jsp",
};
#
# Array of Hashes of pvoutput information for each inverter - add more as required (in curly braces)
#
my @PVOUTPUT = (
{
SERIAL_NUM => "1204DQ0116",
API_KEY => "16e7a916d69656e354d00461a4da1d2e40cfa4f1",
SYSTEM_ID => "12419",
},
);
#######################################################################
#
# Display arguments if $debug turned on
#
if ( DEBUG_SCRIPT ) {
print "Serial: $serial_num as at: $log_date $log_time\n";
print "Now: $current_watts W\n";
print "Today: $current_volts Wh\n";
print "Today: $daily_watthrs Wh\n";
}
#
# Prepare the web request
#
my $ua = LWP::UserAgent->new;
#
# Loop through the PVOUTPUT Array of Hashes to find the matching inverter serial number
#
my $i;
for $i ( 0 .. $#PVOUTPUT ) {
if ( $PVOUTPUT[$i]{SERIAL_NUM} eq $serial_num ) {
if ( DEBUG_SCRIPT ) {
print $PVOUTPUT[$i]{SERIAL_NUM} . " serial match found at index $i\n";
}
$ua->default_header(
"X-Pvoutput-Apikey" => $PVOUTPUT[$i]{API_KEY},
"X-Pvoutput-SystemId" => $PVOUTPUT[$i]{SYSTEM_ID},
"Content-Type" => "application/x-www-form-urlencoded"
);
}
}
#
# Prepare request string
#
print "Sending to PVOUTPUT [ d => $log_date, t => $log_time, v1 => $daily_watthrs, v2 => $current_watts, v6 => $current_volts ]\n";
my $request = POST LIVE_DATA_URL, [ d => $log_date, t => $log_time, v1 => $daily_watthrs, v2 => $current_watts, v6 => $current_volts ];
#
# Send request to pvoutput to add/update live output status
#
my $res = $ua->request($request);
#
# Display any errors
#
if (! $res->is_success) {
die "Couldn't submit data to pvoutput.org:" . $res->status_line . "\n";
}
exit;

2
opt/inverter/start.sh Normal file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
/opt/inverter/inverter.php >> /opt/inverter/log 2>&1 &