* fetch temperature from wunderground
* fix errors in pvoutput value correction
This commit is contained in:
@@ -1,24 +1,34 @@
|
|||||||
#!/usr/bin/php
|
#!/usr/bin/php
|
||||||
<?php
|
<?php
|
||||||
require_once 'functions.php';
|
require_once 'functions.php';
|
||||||
|
require_once 'wunderground.php';
|
||||||
|
|
||||||
|
define('STATION', 'INOORDHO4');
|
||||||
define('RRD_FILE', 'data/inverter_%s_today.rrd');
|
define('RRD_FILE', 'data/inverter_%s_today.rrd');
|
||||||
define('RRD_FETCH', 'rrdtool fetch %s AVERAGE -r %d -s %d -e %d');
|
define('RRD_FETCH', 'rrdtool fetch %s AVERAGE -r %d -s %d -e %d');
|
||||||
define('PVOUTPUT_URL', 'http://pvoutput.org/service/r1/addstatus.jsp');
|
define('PVOUTPUT_URL', 'http://pvoutput.org/service/r1/addstatus.jsp');
|
||||||
define('TODAY_FILE', 'data/today_%s.csv');
|
define('TODAY_FILE', 'data/today_%s.csv');
|
||||||
define('FIELD', 'PAC');
|
define('FIELD', 'PAC');
|
||||||
define('RESOLUTION', 5);
|
define('RESOLUTION', 5);
|
||||||
define('MARGIN', 0.1);
|
define('MARGIN_ENERGY', 0.1);
|
||||||
|
define('MARGIN_TEMPERATURE', 0.2);
|
||||||
$aSystems = array(
|
$aSystems = array(
|
||||||
'1204DQ0116' => array('16e7a916d69656e354d00461a4da1d2e40cfa4f1', '12419')
|
'1204DQ0116' => array('16e7a916d69656e354d00461a4da1d2e40cfa4f1', '12419')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Fake command line for debugging */
|
||||||
|
//$argv = array(null, 1.5, 1234, 230, '1204DQ0116');
|
||||||
|
|
||||||
/* Fetch command line arguments */
|
/* Fetch command line arguments */
|
||||||
$fToday = floatval($argv[1]);
|
$fToday = floatval($argv[1]);
|
||||||
$fPower = floatval($argv[2]);
|
$fPower = floatval($argv[2]);
|
||||||
$fVoltage = floatval($argv[3]);
|
$fVoltage = floatval($argv[3]);
|
||||||
$sSerial = $argv[4];
|
$sSerial = $argv[4];
|
||||||
|
|
||||||
|
/* Fetch temperature */
|
||||||
|
$aData = wunderground('conditions', sprintf('pws:%s', STATION));
|
||||||
|
$fTemperature = isset($aData['current_observation']['temp_c']) ? $aData['current_observation']['temp_c'] : null;
|
||||||
|
|
||||||
/* Fetch twilight data */
|
/* Fetch twilight data */
|
||||||
$iDay = date('z');
|
$iDay = date('z');
|
||||||
$aTwilight = getTwilight(date('Y'), $iDay);
|
$aTwilight = getTwilight(date('Y'), $iDay);
|
||||||
@@ -27,10 +37,10 @@ $aTwilight = getTwilight(date('Y'), $iDay);
|
|||||||
$sTodayFile = sprintf(TODAY_FILE, $sSerial);
|
$sTodayFile = sprintf(TODAY_FILE, $sSerial);
|
||||||
$aToday = array();
|
$aToday = array();
|
||||||
if (file_exists($sTodayFile)) {
|
if (file_exists($sTodayFile)) {
|
||||||
$aToday = explode(',', file_get_contents($sTodayFile));
|
$aToday = explode(',', file_get_contents($sTodayFile));
|
||||||
}
|
}
|
||||||
if (count($aToday) != 3 || $aToday[0] != $iDay) {
|
if (count($aToday) != 3 || $aToday[0] != $iDay) {
|
||||||
$aToday = array($iDay, 0, strtotime($aTwilight[1]));
|
$aToday = array($iDay, 0, strtotime($aTwilight[1]), null);
|
||||||
}
|
}
|
||||||
$iLast = $aToday[2];
|
$iLast = $aToday[2];
|
||||||
|
|
||||||
@@ -52,7 +62,7 @@ if (isset($aFields[FIELD])) {
|
|||||||
$aRow = explode(' ', $sRow);
|
$aRow = explode(' ', $sRow);
|
||||||
$iDate = substr($aRow[0], 0, -1);
|
$iDate = substr($aRow[0], 0, -1);
|
||||||
$iInterval = $bFirst ? (($bFirst = false) || RESOLUTION) : $iDate - $iLast;
|
$iInterval = $bFirst ? (($bFirst = false) || RESOLUTION) : $iDate - $iLast;
|
||||||
if (($fValue = floatval($aRow[$iField])) > 0) {
|
if (($fValue = floatval($aRow[$iField])) > 0) {
|
||||||
$fEnergy += $iInterval * $fValue;
|
$fEnergy += $iInterval * $fValue;
|
||||||
}
|
}
|
||||||
$iLast = $iDate;
|
$iLast = $iDate;
|
||||||
@@ -62,10 +72,30 @@ if (isset($aFields[FIELD])) {
|
|||||||
/* Store today data */
|
/* Store today data */
|
||||||
$aToday[1] += $fEnergy / 1000 / 3600;
|
$aToday[1] += $fEnergy / 1000 / 3600;
|
||||||
$aToday[2] = $iTime;
|
$aToday[2] = $iTime;
|
||||||
|
$aToday[3] = $fTemperature;
|
||||||
file_put_contents($sTodayFile, implode(',', $aToday));
|
file_put_contents($sTodayFile, implode(',', $aToday));
|
||||||
|
|
||||||
/* Correct today data */
|
/* Correct today data */
|
||||||
$fToday = $aToday[1] > ((1 + MARGIN) * $fEnergy) ? $fEnergy : $aToday[1];
|
$fToday = $fToday > ((1 + MARGIN_ENERGY) * $aToday[1]) ? $aToday[1] : $fToday;
|
||||||
|
|
||||||
|
/* Construct PVOutput data */
|
||||||
|
$aData = array(
|
||||||
|
'd' => date('Ymd', $iTime),
|
||||||
|
't' => date('H:i', $iTime),
|
||||||
|
'v1' => 1000 * $fToday, // Wh
|
||||||
|
'v2' => $fPower,
|
||||||
|
'v6' => $fVoltage);
|
||||||
|
|
||||||
|
/* Add (corrected) temperature when available */
|
||||||
|
if (isset($fTemperature)) {
|
||||||
|
if (isset($aToday[3])) {
|
||||||
|
$fTemperature = abs($aToday[3] - $fTemperature) > (MARGIN_TEMPERATURE * $aToday[3]) ? $aToday[3] : $fTemperature;
|
||||||
|
}
|
||||||
|
$aData['v5'] = $fTemperature; // ignore potential flaws in first temperature of the day
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store debug data */
|
||||||
|
file_put_contents('pvoutput.debug', array(json_encode($argv), json_encode($aData)) . "\n", FILE_APPEND);
|
||||||
|
|
||||||
/* Send data to PVOutput */
|
/* Send data to PVOutput */
|
||||||
if (isset($aSystems[$sSerial])) {
|
if (isset($aSystems[$sSerial])) {
|
||||||
@@ -75,12 +105,7 @@ if (isset($aSystems[$sSerial])) {
|
|||||||
CURLOPT_HTTPHEADER => array(
|
CURLOPT_HTTPHEADER => array(
|
||||||
sprintf('X-Pvoutput-Apikey: %s', $aSystems[$sSerial][0]),
|
sprintf('X-Pvoutput-Apikey: %s', $aSystems[$sSerial][0]),
|
||||||
sprintf('X-Pvoutput-SystemId: %s', $aSystems[$sSerial][1])),
|
sprintf('X-Pvoutput-SystemId: %s', $aSystems[$sSerial][1])),
|
||||||
CURLOPT_POSTFIELDS => http_build_query(array(
|
CURLOPT_POSTFIELDS => http_build_query($aData),
|
||||||
'd' => date('Ymd', $iTime),
|
|
||||||
't' => date('H:i', $iTime),
|
|
||||||
'v1' => 1000 * $fToday, // Wh
|
|
||||||
'v2' => $fPower,
|
|
||||||
'v6' => $fVoltage)),
|
|
||||||
CURLOPT_RETURNTRANSFER => true));
|
CURLOPT_RETURNTRANSFER => true));
|
||||||
$sResult = curl_exec($rCurl);
|
$sResult = curl_exec($rCurl);
|
||||||
}
|
}
|
||||||
7
opt/inverter/weather.php
Normal file
7
opt/inverter/weather.php
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
require_once 'wunderground.php';
|
||||||
|
|
||||||
|
define('STATION', 'INOORDHO4');
|
||||||
|
$aData = wunderground('conditions', sprintf('pws:%s', STATION));
|
||||||
|
echo $fTemperature = isset($aData['current_observation']['temp_c']) ? $aData['current_observation']['temp_c'] : null;
|
||||||
67
opt/inverter/wunderground.php
Normal file
67
opt/inverter/wunderground.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
define('KEY', '2556854ea765c351');
|
||||||
|
define('LIMIT_MINUTE', 10);
|
||||||
|
define('LIMIT_DAY', 500);
|
||||||
|
define('LIMIT_FILE', 'wunderground.json');
|
||||||
|
|
||||||
|
function wunderground($sService, $sQuery, $bDebug = false) {
|
||||||
|
/* Get current date values */
|
||||||
|
$iMinute = date('i');
|
||||||
|
$iDay = date('z');
|
||||||
|
|
||||||
|
if (file_exists(LIMIT_FILE)) {
|
||||||
|
/* Read number of calls used */
|
||||||
|
$sJSON = file_get_contents(LIMIT_FILE);
|
||||||
|
$aJSON = json_decode($sJSON, true);
|
||||||
|
$aCount = array(
|
||||||
|
'minute' => $iMinute != $aJSON['minute'][0] ? 0 : $aJSON['minute'][1],
|
||||||
|
'day' => $iDay != $aJSON['day'][0] ? 0 : $aJSON['day'][1]);
|
||||||
|
} else {
|
||||||
|
/* Initialise to zero */
|
||||||
|
$aCount = array(
|
||||||
|
'minute' => 0,
|
||||||
|
'day' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check call limits */
|
||||||
|
$iWait = 0;
|
||||||
|
if ($aCount['minute'] >= LIMIT_MINUTE) {
|
||||||
|
$iWait = 60 - date('s');
|
||||||
|
if ($bDebug === true) {
|
||||||
|
printf("Minute limit (%d) reached, wait %d seconds\n", LIMIT_MINUTE, $iWait);
|
||||||
|
}
|
||||||
|
$aCount['minute'] = 0;
|
||||||
|
} else if ($aCount['day'] >= LIMIT_DAY) {
|
||||||
|
$iWait = strtotime('00:00 + 1 day') - time();
|
||||||
|
if ($bDebug === true) {
|
||||||
|
printf("Daily limit (%d) reached, wait %d seconds\n", LIMIT_DAY, $iWait);
|
||||||
|
}
|
||||||
|
$aCount['day'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent from exceeding call limits */
|
||||||
|
if ($iWait > 0) {
|
||||||
|
//die("Try again later!\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update call counts */
|
||||||
|
++$aCount['minute'];
|
||||||
|
++$aCount['day'];
|
||||||
|
|
||||||
|
/* Report number of calls used */
|
||||||
|
if ($bDebug === true) {
|
||||||
|
printf("Used %d/%d minutely and %d/%d daily calls\n", $aCount['minute'], LIMIT_MINUTE, $aCount['day'], LIMIT_DAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write number of calls used to file */
|
||||||
|
$aJSON = array(
|
||||||
|
'minute' => array($iMinute, $aCount['minute']),
|
||||||
|
'day' => array($iDay, $aCount['day']));
|
||||||
|
file_put_contents(LIMIT_FILE, json_encode($aJSON));
|
||||||
|
|
||||||
|
/* Perform actual call */
|
||||||
|
$sUrl = sprintf('http://api.wunderground.com/api/%s/%s/q/%s.json', KEY, $sService, $sQuery);
|
||||||
|
$sJSON = file_get_contents($sUrl);
|
||||||
|
return json_decode($sJSON, true);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user