start.sh on boot, run inverter.php in infinite loop
This commit is contained in:
20
etc/init.d/inverter
Normal file
20
etc/init.d/inverter
Normal 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
362
opt/inverter/config.ini
Normal 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"
|
||||
54
opt/inverter/create_rrd.pl
Normal file
54
opt/inverter/create_rrd.pl
Normal 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
44
opt/inverter/inverter.php
Normal 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
1582
opt/inverter/inverter.pl
Normal file
File diff suppressed because it is too large
Load Diff
121
opt/inverter/pvoutput.pl
Normal file
121
opt/inverter/pvoutput.pl
Normal 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
2
opt/inverter/start.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
/opt/inverter/inverter.php >> /opt/inverter/log 2>&1 &
|
||||
Reference in New Issue
Block a user