diff --git a/etc/init.d/inverter b/etc/init.d/inverter index d85007c..5e65610 100644 --- a/etc/init.d/inverter +++ b/etc/init.d/inverter @@ -1,20 +1,156 @@ -#!/bin/sh +#! /bin/sh ### BEGIN INIT INFO -# Provides: inverter -# Required-Start: $network -# Required-Stop: $network -# Default-Start: 2 3 5 -# Description: +# Provides: inverter.php +# Required-Start: $network +# Required-Stop: $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: +# Description: This file should be used to construct scripts to be +# placed in /etc/init.d. ### END INIT INFO +# Author: <> +# + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="" +NAME=inverter.php +DAEMON=/opt/inverter/inverter.php +DAEMON_ARGS="" +PIDFILE=/var/run/inverter/inverter.pid +SCRIPTNAME=/etc/init.d/inverter.php + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/${NAME} ] && . /etc/default/${NAME} + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE + return 0 +} + case "$1" in -'start') - /opt/inverter/start.sh + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac ;; -'stop') + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac ;; -*) - echo "Usage: $0 { start | stop }" + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + status) + status_of_proc $DAEMON $NAME -p $PIDFILE + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 + exit 3 ;; esac -exit 0 + +: diff --git a/etc/logrotate.d/inverter b/etc/logrotate.d/inverter new file mode 100644 index 0000000..ab8e648 --- /dev/null +++ b/etc/logrotate.d/inverter @@ -0,0 +1,11 @@ +/var/log/inverter.log { + rotate 15 + compress + missingok + notifempty + sharedscripts + size 5M + postrotate + /bin/kill -HUP `cat /var/run/inverter/inverter.pid 2>/dev/null` 2> /dev/null || true + endscript +} \ No newline at end of file diff --git a/opt/inverter/inverter.php b/opt/inverter/inverter.php index 53ff8f3..de3ad46 100644 --- a/opt/inverter/inverter.php +++ b/opt/inverter/inverter.php @@ -1,44 +1,86 @@ #!/usr/bin/php /dev/null'; +require_once 'functions.php'; +require_once 'System/Daemon.php'; // pear install -f System_Daemon -printf("Be awake between %s and %s\n", $sWake, $sSleep); -$fWake = getHour($sWake); -$fSleep = getHour($sSleep); -chdir('/opt/inverter/'); +define('NAME', 'inverter'); +define('TASK', '/opt/inverter/inverter.pl > /dev/null'); +define('CWD', '/opt/inverter/'); +define('MODE', 0755); +define('FILE_DAEMON_START', 'daemon_start.sh'); +define('FILE_DAEMON_STOP', 'daemon_stop.sh'); +define('DEFAULT_WAKE', '7:00'); +define('DEFAULT_SLEEP', '19:00'); +chdir(CWD); -while (true) { - // Check for current need to be awake +/* Remove previous at entries */ +foreach (explode("\n", trim(command('atq'))) as $sJob) { + $sId = substr($sJob, 0, strpos($sJob, "\t")); + $sJob = command(sprintf('at -c %s ' . "\n", $sId)); + $aJob = explode("\n", trim(command(sprintf('at -c %s', $sId)))); + if (strpos(array_pop($aJob), NAME) !== false) { + command(sprintf('atrm %s', $sId)); + } +} + +/* Inverter daemon */ +System_Daemon::setOptions(array( + 'appName' => NAME, + 'appDescription' => '', + 'authorName' => '', + 'authorEmail' => '')); + +/* Install service */ +if (isset($argv[1]) && $argv[1] == 'install') { + System_Daemon::writeAutoRun(); // update-rc.d %s defaults + + /* Write scripts for scheduling with at */ + if (!file_exists(FILE_DAEMON_START)) { + file_put_contents(FILE_DAEMON_START, sprintf("#!/bin/bash\nservice %s start", NAME)); + chmod(FILE_DAEMON_START, MODE); + } + if (!file_exists(FILE_DAEMON_STOP)) { + file_put_contents(FILE_DAEMON_STOP, sprintf("#!/bin/bash\nservice %s stop", NAME)); + chmod(FILE_DAEMON_STOP, MODE); + } + exit; +} + +/* Wake at sunrise, sleep at sunset */ +$aTwilight = getTwilight(date('Y'), date('z')); +$fWake = getHour($sWake = isset($aTwilight) ? $aTwilight[1] : DEFAULT_WAKE); +$fSleep = getHour($sSleep = isset($aTwilight) ? $aTwilight[3] : DEFAULT_SLEEP); +System_Daemon::info(sprintf('Be awake between %s and %s', $sWake, $sSleep)); + +/* Start deamon */ +System_Daemon::start(); +$bStop = false; +while (!$bStop && !System_Daemon::isDying()) { + /* Check for current need to be awake */ $fNow = getHour(); if (!($bAwake = $fNow >= $fWake)) { - printf("[%s] Too early to wake!\n", date('r')); + System_Daemon::info('Too early to wake!'); } else if ($bSleep = $fNow >= $fSleep) { - printf("[%s] Time to sleep!\n", date('r')); + System_Daemon::info('Time to sleep!'); } if ($bAwake && !$bSleep) { - // Need to be awake now - printf("[%s] Running task\n", date('r')); - system($sTask); - printf("[%s] Task ended\n", date('r')); + /* Schedule next sleep time */ + $sTime = date('H:i', strtotime($sWake)); + command(sprintf('at -f %s %s 2> /dev/null', FILE_DAEMON_STOP, $sTime)); + + /* Execute task */ + System_Daemon::info('Running task'); + command(TASK); + System_Daemon::info('Task ended'); } 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); + /* Schedule next wake time */ + $sTime = date('H:i', strtotime($sWake)); // ignore slight deviation for next day + command(sprintf('at -f %s %s 2> /dev/null', FILE_DAEMON_START, $sTime)); + System_Daemon::info(sprintf('Waiting untill %s', $sTime)); + $bStop = true; } } -echo "\n"; -function getHour($sTime = null) { - $iTime = $sTime === null ? time() : strtotime($sTime); - return date('H', $iTime) + date('i', $iTime) / 60; -} +/* Stop daemon */ +System_Daemon::stop(); \ No newline at end of file diff --git a/opt/inverter/pvoutput.php b/opt/inverter/pvoutput.php index 21d2029..2c0f0f0 100644 --- a/opt/inverter/pvoutput.php +++ b/opt/inverter/pvoutput.php @@ -87,40 +87,4 @@ if (isset($aSystems[$sSerial])) { CURLOPT_RETURNTRANSFER => true)); $sResult = curl_exec($rCurl); file_put_contents('pvtest', sprintf("[%s] %s\n", date('r'), $sResult), FILE_APPEND); -} - -/* -$a = file_get_contents('test'); -$b = explode("\n", $a); -array_pop($b); -foreach ($b as $c) { - $d = explode(',', $c); - $iTime = $d[2]; - $fToday = $d[4]; - $fEnergy = $d[6]; - $fToday = $fToday > ((1 + MARGIN) * $fEnergy) ? $fEnergy : $fToday; - - $fPower = $d[5]; - $sSerial = $d[3]; - - $e = sprintf("%s,%s,%s\n", date('H:i', $iTime), $fToday * 1000, $fPower); - file_put_contents('do.csv', $e, FILE_APPEND); - - - /* - $rCurl = curl_init(); - curl_setopt_array($rCurl, array( - CURLOPT_URL => PVOUTPUT_URL, - CURLOPT_HTTPHEADER => array( - sprintf('X-Pvoutput-Apikey: %s', $aSystems[$sSerial][0]), - sprintf('X-Pvoutput-SystemId: %s', $aSystems[$sSerial][1])), - CURLOPT_POSTFIELDS => http_build_query(array( - 'd' => date('Ymd', $iTime), - 't' => date('H:i', $iTime), - 'v1' => 1000 * $fToday, // Wh - 'v2' => $fPower)), - CURLOPT_RETURNTRANSFER => true)); - echo $sResult = curl_exec($rCurl); - sleep(61);* -} -exit;*/ \ No newline at end of file +} \ No newline at end of file