src.dualinventive.com/mtinfo/dist/webroot/support/plot-batterij.php

869 lines
33 KiB
PHP

<?php
/*
************************************************************************
**
** Copyright (c) 2009..2013 by
** Core|Vision B.V.
** Hambakenwetering 1
** 5231 DD 's-Hertogenbosch
** The Netherlands
**
** All Rights Reserved
**
************************************************************************
*/
/*
************************************************************************
**
** Project name: Dual Inventive: MTinfo Support Scripts
** Filename: plot-batterij.php
** Author: Jack Weeland
** Date: July 9, 2009
** File version: $Revision: 1.19 $
** $Date: 2013/12/19 14:49:58 $
**
************************************************************************
*/
/*
************************************************************************
**
** Display battery levels in a graph.
**
** Mandatory parameters, via "GET", all of which are retrieved from
** the database
** zkl - database ID of the ZKL to query
** logfile - sdcard,rpgmcount,startup of the logfile to plot
** and/or
** tmin,tmax - date/time of the time frame (the current time will
** be used if tmax is ommitted)
** Optional output options:
** w - width of the output image
** h - height of the output image
** n - number of batteries, default 2
** V - maximum voltage, default 15.0
** hide_title - do not device id-code and date
** hide_info - do not show additional info
** log_realtime - use 'log_realtime' instead of 'log_batterij'
** (with 'tmin', 'tmax' and 'batterij'; _not_ 'logfile')
** only _one_ battery can be shown!
** batterij - battery to show ("2" for battery #2, battery #1 is
** the default; _only_ for 'log_realtime'
**
** Notes:
** - If both 'logfile' and a 'tmin'/'tmax' are specified, then the data
** from the logfile will be scaled to the specified time frame.
** - If _no_ 'logfile' is specified, all logfiles with data in the time
** frame will be shown.
** - Logfiles with an invalid date (i.e. 1970-1-1) are _never_ plotted.
**
************************************************************************
*/
//
// Check inputs for SQL statement injection and such.
// Items not tested below are not vulnerable for SQL statement injection, e.g.
// a time is always converted using 'strtotime()' and other items are only
// used in the PHP but never in the composition of an SQL statement
// [security audit 2013-10-23]
//
if(
(isset($_GET['zkl']) && !is_numeric($_GET['zkl'])) ||
(isset($_GET['logfile']) && !preg_match('/^[0-9]+,[0-9]+,[0-9]+$/', $_GET['logfile']) && !in_array($_GET['logfile'], array('log_tcp','log_versienummer','log_realtime','log_secure_zkl'))) ||
(isset($_GET['db']) && dirname($_GET['db']) != ".")
) {
// don't do anything fancy or interruptive as fiddling with the GET parameters
// is intended by the author
die("Parameter error");
}
require_once("../include/graphics.php");
require_once("../include/i18n.php");
require_once("../include/cp3000-tcpclient.php");
require_once("support.inc.php");
set_time_limit(0);
// which table?
$use_log_realtime = isset($_GET['log_realtime']);
// read the database information
if( isset($_GET['db']) ) $db_info = read_database(DBCONFIG_DIR, $_GET['db']);
else $db_info = array();
if( !isset($db_info['host']) ) $db_info['host'] = "localhost";
if( !isset($db_info['user']) ) $db_info['user'] = "root";
if( !isset($db_info['passwd']) ) $db_info['passwd'] = "";
if( !isset($db_info['db']) ) $db_info['db'] = "di_zkl";
// open the database
$db_data_handle = mysql_connect($db_info['host'], $db_info['user'], $db_info['passwd']);
if( $db_data_handle === FALSE ) {
echo mysql_error();
exit(1);
}
mysql_select_db($db_info['database'], $db_data_handle);
if( $db_info['main'] ) {
$db_main_info = read_database(DBCONFIG_DIR, $db_info['main']);
$db_main_handle = mysql_connect($db_main_info['host'], $db_main_info['user'], $db_main_info['passwd'], true);
if( $db_main_handle === FALSE ) {
echo mysql_error();
exit(1);
}
mysql_select_db($db_main_info['database'], $db_main_handle);
}
else {
$db_main_handle = $db_data_handle;
$db_main_info = $db_info;
}
// number of batteries and max V
if( isset($_GET['n']) ) $n_batterij = $_GET['n'];
else $n_batterij = 2;
if( isset($_GET['V']) ) $V = $_GET['V'];
else $V = 15.0;
// batteries to show
$show_batterij = array();
if( isset($_GET['batterij']) ) {
if( is_array($_GET['batterij']) ) {
for( $i = 0; $i < count($_GET['batterij']); $i++ )
$show_batterij[] = $_GET['batterij'][$i] - 1;
}
else $show_batterij[] = $_GET['batterij'] - 1;
}
else for( $i = 0; $i < $n_batterij; $i++ ) {
$show_batterij[] = $i;
}
// determine width and height
$width = $_GET['w'];
$height = $_GET['h'];
if( !$width ) $width = 640;
if( !$height ) $height = 480;
// get information about the device
list($sdcard,$rpgmcount,$startup) = explode(',', $_GET['logfile']);
$query = "SELECT serienr,idcode,tcp_server,mcu_versie,wcpu_versie,IFNULL(gebruiker,eigenaar) AS gebruiker FROM zkl WHERE id=" . $_GET['zkl'];
$result = mysql_run($query, $db_main_handle);
$zkl_info = mysql_fetch_assoc($result);
if( $zkl_info['gebruiker'] ) {
$query = "SELECT tz,i18n FROM klant WHERE id=" . $zkl_info['gebruiker'];
$result = mysql_run($query, $db_main_handle);
$tz_info = mysql_fetch_assoc($result);
}
else {
$tz_info = array( 'tz' => date("e"), 'i18n' => "nl" );
}
if( $_GET['tz'] ) $tz_info['tz'] = $_GET['tz'];
if( $_GET['lc'] ) $tz_info['i18n'] = $_GET['lc'];
$zkl_info['tz'] = $tz_info['tz'];
$zkl_info['i18n'] = $tz_info['i18n'];
$zkl_info['mcu_versie'] = zkl_get_fw_version($zkl_info['mcu_versie']);
$zkl_info['wcpu_versie'] = zkl_get_fw_version($zkl_info['wcpu_versie']);
putenv("TZ=" . $zkl_info['tz']);
i18n_settext_language($zkl_info['i18n']);
setlocale(LC_ALL, $zkl_info['i18n']);
// get timeframe and log files
$logfiles = array();
if( isset($_GET['tmin']) ) {
$tmin = strtotime($_GET['tmin']);
if( isset($_GET['tmax']) && $_GET['tmax'] ) $tmax = strtotime($_GET['tmax']);
else $tmax = time();
if( isset($_GET['logfile']) ) {
if( is_array($_GET['logfile']) ) foreach( $_GET['logfile'] as $logfile ) {
list($sdcard,$rpgmcount,$startup) = explode(',', $logfile);
$query = "SELECT MIN(t) AS tmin,MAX(t) AS tmax ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup;
$result = mysql_run($query, $db_data_handle);
$row = mysql_fetch_assoc($result);
if( !$_GET['ignore_errors'] ) {
if( $row['tmax'] > time() ) {
error_log($_SERVER['PHP_SELF'] . ": logfile " . $_GET['zkl'] . "-" . $sdcard . "," . $rpgmcount . "," . $startup . " has bogus 'max(t)'; using 'now'");
$row['tmax'] = time();
}
}
array_push($logfiles, array('sdcard' => $sdcard, 'rpgmcount' => $rpgmcount, 'startup' => $startup, 'tmin' => $row['tmin'], 'tmax' => $row['tmax']));
}
else {
list($sdcard,$rpgmcount,$startup) = explode(',', $_GET['logfile']);
$query = "SELECT MIN(t) AS tmin,MAX(t) AS tmax ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup;
$result = mysql_run($query, $db_data_handle);
$row = mysql_fetch_assoc($result);
if( !$_GET['ignore_errors'] ) {
if( $row['tmax'] > time() ) {
error_log($_SERVER['PHP_SELF'] . ": logfile " . $_GET['zkl'] . "-" . $sdcard . "," . $rpgmcount . "," . $startup . " has bogus 'max(t)'; using 'now'");
$row['tmax'] = time();
}
}
array_push($logfiles, array('sdcard' => $sdcard, 'rpgmcount' => $rpgmcount, 'startup' => $startup, 'tmin' => $row['tmin'], 'tmax' => $row['tmax']));
}
}
else if( $use_log_realtime ) {
// fake a log file for the drawing loop below
array_push($logfiles,
array(
'sdcard' => 0,
'rpgmcount' => 0,
'startup' => 0,
'tmin' => $tmin,
'tmax' => $tmax
)
);
}
else if( !isset($_GET['file']) ) {
// retrieve logfiles from the database
$query = "SELECT sdcard,rpgmcount,startup,MIN(t) AS tmin,MAX(t) AS tmax ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " t BETWEEN " . $tmin . " AND ". $tmax . " ";
$query .= "GROUP BY sdcard,rpgmcount,startup";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
array_push($logfiles, $row);
}
}
}
else if( !isset($_GET['file']) ) {
if( !isset($_GET['logfile']) ) {
error_log($_SERVER['PHP_SELF'] . ": no log file or time range defined");
exit(1);
}
list($sdcard,$rpgmcount,$startup) = explode(',', $_GET['logfile']);
$query = "SELECT MIN(t) AS tmin,MAX(t) AS tmax ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup;
$result = mysql_run($query, $db_data_handle);
$row = mysql_fetch_assoc($result);
if( $row['tmin'] < strtotime("2000-1-1") ) {
error_log($_SERVER['PHP_SELF'] . ": logfile " . $_GET['zkl'] . "-" . $sdcard . "," . $rpgmcount . "," . $startup . " has bogus 'min(t)'; using only data from 2000");
$result = mysql_run($query . " AND t >= " . strtotime('2000-1-1'), $db_data_handle);
$row = mysql_fetch_assoc($result);
}
$tmin = $row['tmin'];
if( isset($_GET['tmax']) ) $tmax = strtotime($_GET['tmax']);
else {
if( $row['tmax'] > time() ) {
error_log($_SERVER['PHP_SELF'] . ": logfile " . $_GET['zkl'] . "-" . $sdcard . "," . $rpgmcount . "," . $startup . " has bogus 'max(t)'; using 'now'");
$tmax = time();
}
else $tmax = $row['tmax'];
}
array_push($logfiles, array('sdcard' => $sdcard, 'rpgmcount' => $rpgmcount, 'startup' => $startup, 'tmin' => $tmin, 'tmax' => $tmax));
}
if( $tmin >= $tmax ) {
error_log($_SERVER['PHP_SELF'] . ": empty time range: " . strftime("%D %T", $tmin) . "-" . strftime("%D %T", $tmax));
exit(1);
}
$tz_offset = date("Z", $tmin);
$duration = $tmax - $tmin;
//
// Draw the graph
//
header("Content-type: image/png");
header('Pragma: no-cache');
header('Expires: ' . date("r"));
// create the image
$im = imagecreatetruecolor($width,$height);
if( function_exists("imageantialias") )
imageantialias($im, true);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 192, 192, 192);
$lgrey = imagecolorallocate($im, 240, 240, 240);
$dgrey = imagecolorallocate($im, 128, 128, 128);
$green = imagecolorallocate($im, 0, 192, 0);
$lgreen = imagecolorallocate($im, 192, 255, 192);
$llgreen = imagecolorallocate($im, 248, 255, 248);
$dgreen = imagecolorallocate($im, 0, 160, 0);
$red = imagecolorallocate($im, 255, 0, 0);
$lred = imagecolorallocate($im, 255, 192, 192);
$dred = imagecolorallocate($im, 160, 0, 0);
$blue = imagecolorallocate($im, 0, 0, 224);
$dblue = imagecolorallocate($im, 0, 0, 160);
$purple = imagecolorallocate($im, 224, 0, 224);
$dpurple = imagecolorallocate($im, 160, 0, 160);
$font = 2; // 6x13
$bfont = 3; // 7x13 medium bold
$tfont = 1; // 5x8
//
// Colors and font to use
//
$bgcolor = imagecolorallocatealpha($im, 255, 255, 255, $_GET['transparent'] ? 127 : 0);
$bgcolor_transp = imagecolorallocatealpha($im, 255, 255, 255, 96);
$gridcolor = $black; // main grid and markers
$sgridcolor = $lgrey; // guides in the gred
$nextdaycolor = $grey; // next day line
$linecolor = array( $blue, $purple, $dred, $dgreen );
$info_color = $red; // additional info: status changes
//
// Font selection (dependent on image size)
//
// labels and legenda
if( $width <= 320 || $height <= 240 ) {
$labelfont = 1;
$infofont = 1;
}
else if( $width >= 2048 && $height >= 1536 ) {
$labelfont = 5;
$infofont = 3;
}
else if( $width >= 1280 && $height >= 1024 ) {
$labelfont = 3;
$infofont = 2;
}
else {
$labelfont = 2;
$infofont = 1;
}
//
// Constants
//
$battery_state = array();
$battery_state[0] = 'ok';
$battery_state[1] = 'alarm';
$battery_state[3] = 'leeg';
$battery_state[7] = 'verwijderd';
//
// Draw the grid
//
// draw background
imagefill($im, 0, 0, $bgcolor);
// offsets with the drawing grid
// largest value label: 1.000
// x: left to right
// y: bottom to top
global $x_off, $x_ext, $y_off, $y_ext;
$x_off = 4 * imagefontwidth($labelfont) // value labels +
+ imagefontheight($labelfont) // legend +
+ (imagefontheight($labelfont) >> 1); // extra spacing
$x_ext = $width - $x_off - (imagefontheight($labelfont) >> 1); // + extent of the last date label
$y_off = $height - 3 - strlen(strftime("%X")) * imagefontwidth($labelfont); // date/time
$y_ext = $y_off;
if( !isset($_GET['hide_title']) ) {
$y_ext -= imagefontheight($labelfont); // title
if( $use_log_realtime ) $y_ext -= imagefontheight($labelfont);
}
else {
$y_ext -= imagefontheight($labelfont) >> 1; // extent of the top value label
}
// The grid is drawn _under_ the lines and ornaments like the title etc
// Y tick marks every 1.0
for( $niveau = 0; $niveau <= $V; $niveau += 1.0 ) {
$y = $y_off - ($y_ext * $niveau / $V);
imageline($im, $x_off, $y, $x_off + $x_ext, $y, $lgrey);
imageline($im, $x_off - 2, $y, $x_off, $y, $black);
imagestringalign($im, $labelfont, $x_off - 2, $y, sprintf("%.1f", $niveau), $gridcolor, ALV_MIDDLE | ALH_RIGHT);
}
// X tick marks
// find a correct stepping for the date labels first
$x_tick_sec = array(5,15,1*60,5*60,15*60,30*60,60*60,4*60*60,6*60*60,8*60*60,12*60*60,24*60*60,7*24*60*60,30*24*60*60,365*24*60*60);
for(
$step = 0, $x_tick_step = 0;
$x_tick_step < (imagefontheight($labelfont) << 1) && $step < count($x_tick_sec);
$step++
) {
$x_tick_off = $x_tick_sec[$step];
$x_tick_step = ($x_ext * $x_tick_off) / $duration;
$x_tick_val = $x_tick_off - (($tmin + $tz_offset) % $x_tick_off);
if( $x_tick_val == $x_tick_off ) $x_tick_val = 0;
}
if( $x_tick_off >= (24*60*60) ) {
if( strtotime("first day of next year", time()) !== FALSE ) {
// big steps; use days/weeks/months/years for DST and leap years
if( $x_tick_off == (365*24*60*60) ) {
$t = strtotime("this year January 01 midnight", $tmin);
$t_step = "first day of next year";
}
else if( $x_tick_off == (30*24*60*60) ) {
$t = strtotime("first day of this month midnight", $tmin);
$t_step = "first day of next month";
}
else if( $x_tick_off == (7*24*60*60) ) {
$t = strtotime("this week Monday midnight", $tmin);
$t_step = "+1 weeks";
}
else {
$t = strtotime("midnight", $tmin);
$t_step = "tomorrow";
}
}
else {
// "nice" arithmatic is not supported
if( $x_tick_off == (365*24*60*60) ) {
$t = strtotime("this year January 01 midnight", $tmin);
$t_step = "+1 year";
}
else if( $x_tick_off == (30*24*60*60) ) {
$t = strtotime("first day of this month midnight", $tmin);
$t_step = "+1 month";
}
else if( $x_tick_off == (7*24*60*60) ) {
$t = strtotime("this week Monday midnight", $tmin);
$t_step = "+1 weeks";
}
else {
$t = strtotime("midnight", $tmin);
$t_step = "tomorrow";
}
}
}
else {
if( $x_tick_off >= 60*60 ) {
$t_step = "+" . ($x_tick_off / (60*60)) . " hours";
}
else if( $x_tick_off >= 60 ) {
$t_step = "+" . ($x_tick_off / 60) . " minutes";
}
else {
$t_step = "+" . $x_tick_off . " seconds";
}
$t = $tmin;
if( $x_tick_val > 0 ) $t = strtotime("+" . $x_tick_val . " seconds", $t);
}
while( $t <= $tmax ) {
if( $t >= $tmin ) {
$x = ((($t - $tmin) / $duration) * $x_ext);
if( $x_tick_off >= (24*60*60) ) {
if( $x_tick_off == (30*24*60*60) ) {
// month name
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $nextdaycolor);
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
imagestringupalign($im, $labelfont, $x_off + $x, $y_off - 2, strftime("%B", $t), $nextdaycolor, ALV_BOTTOM | ALH_LEFT);
}
else if( $x_tick_off == (7*24*60*60) ) {
// month name
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $nextdaycolor);
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
imagestringupalign($im, $labelfont, $x_off + $x, $y_off - 2, strftime("%V", $t), $nextdaycolor, ALV_BOTTOM | ALH_LEFT);
}
else {
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $sgridcolor);
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
}
imagestringupalign($im, $labelfont, $x_off + $x, $y_off + 2, strftime("%x", $t), $gridcolor, ALV_TOP | ALH_CENTER);
}
else {
if( strftime("%H%M%S", $t) == "000000" ) {
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $nextdaycolor);
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
imagestringupalign($im, $labelfont, $x_off + $x, $y_off - 2, strftime("%x", $t), $nextdaycolor, ALV_BOTTOM | ALH_LEFT);
}
else {
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $sgridcolor);
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
}
imagestringupalign($im, $labelfont, $x_off + $x, $y_off + 2, strftime("%X", $t), $gridcolor, ALV_TOP | ALH_CENTER);
}
}
// increment $t (yup, that's what the line below does)
//error_log(serialize($t) . " + " . $t_step);
$t = strtotime($t_step, $t);
if( $t === FALSE ) {
trigger_error("Date/time error when adding \"" . $t_step . "\"", E_USER_ERROR);
}
}
if( $x_tick_off < (24*60*60) && (($x_tick_val / $duration) * $x_ext) > imagefontheight($labelfont) ) {
// show start day only on detailed plots (it is already in the titles)
imagestringupalign($im, $labelfont, $x_off, $y_off - 2, strftime("%x", $tmin), $grey, ALV_BOTTOM | ALH_LEFT);
}
//
// Draw the legend
//
if (!isset($_GET['hide_legend'])) {
$y_legend_off = $y_off;
$y_legend_off -= ($y_ext - (count($show_batterij) * (10+4) - 4 + 3) * imagefontwidth($labelfont)) >> 1;
for( $batterij = 0; $batterij < $n_batterij; $batterij++ ) if( in_array($batterij, $show_batterij) ) {
imagestringupalign($im, $labelfont, 0, $y_legend_off - 6 * imagefontwidth($labelfont), sprintf("batt %d", $batterij + 1), $gridcolor, ALV_TOP | ALH_LEFT);
imageline($im,
imagefontheight($labelfont) >> 1, $y_legend_off - 7 * imagefontwidth($labelfont), /* space */
imagefontheight($labelfont) >> 1, $y_legend_off - 10 * imagefontwidth($labelfont), /* line length */
$linecolor[$batterij]
);
$y_legend_off -= (10+4) * imagefontwidth($labelfont);
}
imagestringupalign($im, $labelfont, 0, $y_legend_off - 3 * imagefontwidth($labelfont), "(V)", $gridcolor, ALV_TOP | ALH_LEFT);
}
//
// Draw the border to the left and bottom of the canvas
//
imageline($im, $x_off, $y_off, $x_off, $y_off - $y_ext + 1, $gridcolor);
imageline($im, $x_off, $y_off, $x_off + $x_ext, $y_off, $gridcolor);
//
// Plot the data
//
foreach( $logfiles as $logfile ) {
// get tmin,tmax for this logfile
$log_tmin = $logfile['tmin'];
$log_tmax = $logfile['tmax'];
if( $log_tmin < $tmin ) $log_tmin = $tmin;
if( $log_tmax > $tmax ) $log_tmax = $tmax;
//
$sdcard = $logfile['sdcard'];
$rpgmcount = $logfile['rpgmcount'];
$startup = $logfile['startup'];
// cache minimum and maximum id; this is a lot faster for some reason
if( $use_log_realtime ) {
$query = "SELECT MIN(id),MAX(ID) FROM log_realtime WHERE zkl=" . $_GET['zkl'] . " AND t BETWEEN " . $log_tmin . " AND " . $log_tmax;
if( ($result = mysql_run($query, $db_data_handle)) ) {
$row = mysql_fetch_array($result);
$id_min = $row[0];
$id_max = $row[1];
}
else exit(im_print_error($im, "No data"));
$query = "SELECT MAX(id) FROM log_realtime WHERE zkl=" . $_GET['zkl'] . " AND t <= " . $log_tmin;
if( ($result = mysql_run($query, $db_data_handle)) ) {
$row = mysql_fetch_array($result);
$id_tmin = $row[0];
}
else {
// no suitable minimum
$query = "SELECT MIN(id) FROM log_realtime WHERE zkl=" . $_GET['zkl'];
$result = mysql_run($query, $db_data_handle);
$row = mysql_fetch_array($result);
$id_tmin = $row[0];
}
}
// get the status changes
if( !isset($_GET['hide_info']) ) {
$batt_event = array();
for( $batterij = 0; $batterij < $n_batterij; $batterij++ )
$batt_event[$batterij] = array();
if( $logfile['file'] ) {
// not implemented
}
else if( $use_log_realtime ) {
// two batteries, initially both absent
$status[0] = -1;
$status[1] = -1;
$sel = -1;
$charger = 0;
$query = "SELECT id,t,changes,mcu_state,rc_state,batt_sel,batt1_niveau,batt2_niveau ";
$query .= "FROM log_realtime ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " (";
if( $id_tmin ) $query .= " id=" . $id_tmin . " OR ";
$query .= " (";
$query .= " id BETWEEN " . $id_min . " AND " . $id_max . " AND ";
$query .= " (changes & 0x0805) != 0";
$query .= " )";
$query .= " ) ";
$query .= "ORDER BY id";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
if( ($t = $row['t']) < $tmin ) $t = $tmin;
if( (($row['mcu_state'] >> 8) & 0x000F) != $status[0] ) {
$status[0] = (($row['mcu_state'] >> 8) & 0x000F);
array_push($batt_event[0], array(
'id' => $row['id'],
't' => $t,
'batterij' => 0,
'niveau' => $row['batt1_niveau'],
'status' => $battery_state[$status[0]],
'leeftijd' => 0
)
);
}
if( (($row['mcu_state'] >> 12) & 0x000F) != $status[1] ) {
$status[1] = (($row['mcu_state'] >> 12) & 0x000F);
array_push($batt_event[1], array(
'id' => $row['id'],
't' => $t,
'batterij' => 1,
'niveau' => $row['batt2_niveau'],
'status' => $battery_state[$status[1]],
'leeftijd' => 0
)
);
}
if( $row['batt_sel'] != $sel ) {
$sel = $row['batt_sel'];
array_push($batt_event[0], array(
'id' => $row['id'],
't' => $t,
'batterij' => $sel,
'niveau' => $sel ? $row['batt2_niveau'] : $row['batt1_niveau'],
'status' => 'selectie',
'leeftijd' => 0
)
);
}
if( isset($_GET['show_charger']) && (($row['rc_state'] >> 10) & 0x0001) != $charger ) {
if( ($charger = (($row['rc_state'] >> 10) & 0x0001)) ) $event = 'charger on';
else $event = 'charger off';
array_push($batt_event[0], array(
'id' => $row['id'],
't' => $t,
'batterij' => 0,
'status' => $event,
'niveau' => $row['batt1_niveau'],
'leeftijd' => 0
)
);
}
}
}
else {
$query = "SELECT log_zkl.id,log_zkl.t,log_batterijstatus.batterij,log_batterijstatus.status,log_batterijstatus.leeftijd ";
$query .= "FROM log_zkl,log_batterijstatus ";
$query .= "WHERE ";
$query .= " log_zkl.id=log_batterijstatus.id AND ";
$query .= " log_zkl.zkl=" . $_GET['zkl'] . " AND ";
$query .= " log_zkl.sdcard=" . $sdcard . " AND ";
$query .= " log_zkl.rpgmcount=" . $rpgmcount . " AND ";
$query .= " log_zkl.startup=" . $startup . " AND ";
$query .= " log_zkl.major=6 AND log_zkl.minor=16 AND ";
$query .= " log_batterijstatus.batterij IN (" . implode(",", $show_batterij) . ") ";
$query .= "ORDER BY log_zkl.id";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
@array_push($batt_event[$row['batterij']], $row);
}
if( isset($_GET['show_charger']) ) {
$query = "SELECT log_zkl.id,log_zkl.t,log_zkl.minor ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " log_zkl.zkl=" . $_GET['zkl'] . " AND ";
$query .= " log_zkl.sdcard=" . $sdcard . " AND ";
$query .= " log_zkl.rpgmcount=" . $rpgmcount . " AND ";
$query .= " log_zkl.startup=" . $startup . " AND ";
$query .= " log_zkl.major=10 AND ";
$query .= " (log_zkl.minor=0x7C OR log_zkl.minor=0x7D) ";
$query .= "ORDER BY log_zkl.id";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
if( $row['minor'] == 0x7C ) $row['status'] = "charger off";
else $row['status'] = "charger on";
$row['batterij'] = 0;
@array_push($batt_event[0], $row);
}
}
}
}
// get the data
if( $logfile['file'] ) {
}
else if( $use_log_realtime ) {
$query = "SELECT id,t,batt1_niveau,batt2_niveau ";
$query .= "FROM log_realtime ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " (";
if( $id_tmin ) $query .= " id=" . $id_tmin . " OR ";
$query .= " (";
$query .= " id BETWEEN " . $id_min . " AND " . $id_max . " AND ";
$query .= " (changes & 0x0F00) != 0";
$query .= " )";
$query .= " ) ";
$query .= "ORDER BY id";
$result = mysql_run($query, $db_data_handle);
// log_realtime, only two batteries
$b_start = 0;
$b_end = 1;
}
else {
$query = "SELECT log_zkl.id,t,log_batterij.batterij,log_batterij.niveau ";
$query .= "FROM log_zkl,log_batterij ";
$query .= "WHERE ";
$query .= " log_zkl.id=log_batterij.id AND ";
$query .= " log_zkl.zkl=" . $_GET['zkl'] . " AND ";
$query .= " log_zkl.sdcard=" . $sdcard . " AND ";
$query .= " log_zkl.rpgmcount=" . $rpgmcount . " AND ";
$query .= " log_zkl.startup=" . $startup . " AND ";
$query .= " log_batterij.batterij IN (" . implode(",", $show_batterij) . ") ";
$query .= "ORDER BY log_zkl.id";
$result = mysql_run($query, $db_data_handle);
}
for( $batterij = 0; $batterij < $n_batterij; $batterij++ ) {
$p_event[$batterij] = 0;
unset($t_begin[$batterij]);
}
while( $row = mysql_fetch_assoc($result) ) {
if( !$use_log_realtime ) $b_start = $b_end = $row['batterij'];
for( $batterij = $b_start; $batterij <= $b_end; $batterij++ ) if( in_array($batterij, $show_batterij) ) {
if( !$use_log_realtime ) $niveau = $row['niveau'];
else $niveau = $row[sprintf('batt%d_niveau', $batterij + 1)];
if( !isset($t_begin[$batterij]) ) {
$t_begin[$batterij] = $row['t'];
$level[$batterij] = $niveau;
}
else {
$t_start = $t_begin[$batterij];
$t_this = $t_end = $row['t'];
if(
$t_end >= $log_tmin &&
$t_start <= $log_tmax
) {
if( $t_start < $log_tmin ) $t_start = $log_tmin;
if( $t_end < $log_tmin ) break;
else if( $t_end > $log_tmax ) $t_end = $log_tmax;
$prev_level = $level[$batterij];
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_level / $V),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_level / $V),
$linecolor[$batterij]
);
imageline($im,
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_level / $V),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $niveau / $V),
$linecolor[$batterij]
);
// status change?
if( !isset($_GET['hide_info']) )
while(
$p_event[$batterij] < count($batt_event[$batterij]) &&
$batt_event[$batterij][$p_event[$batterij]]['id'] < $row['id']
) {
if(
$t_end - $batt_event[$batterij][$p_event[$batterij]]['t'] > 1
) {
// due to datacompression (nr of log entries stored in the database),
// the level may have been stored in the past instead of immediately
// after the status change.
$batt_event[$batterij][$p_event[$batterij]]['niveau'] = $prev_level;
$p_event[$batterij]++;
}
else {
$batt_event[$batterij][$p_event[$batterij]]['niveau'] = $niveau;
$p_event[$batterij]++;
}
}
}
$t_begin[$batterij] = $t_this;
$level[$batterij] = $niveau;
}
}
}
// draw last segment
for( $batterij = 0; $batterij < $n_batterij; $batterij++ ) if( in_array($batterij, $show_batterij) ) {
$t_start = $t_begin[$batterij];
$t_end = $log_tmax;
if(
$t_end >= $log_tmin &&
$t_start <= $log_tmax
) {
if( $t_start < $log_tmin ) $t_start = $log_tmin;
if( $t_end > $log_tmin ) {
if( $t_end > $log_tmax ) $t_end = $log_tmax;
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $level[$batterij] / $V),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $level[$batterij] / $V),
$linecolor[$batterij]
);
}
}
}
//
// Print additional status
//
if( !isset($_GET['hide_info']) ) for( $batterij = 0; $batterij < $n_batterij; $batterij++ ) {
foreach( $batt_event[$batterij] as $event ) {
$x = $x_off + ((($event['t'] - $tmin) * $x_ext) / $duration);
$y = $y_off - ($y_ext * $event['niveau'] / $V);
$right = ($x <= $x_off + (1 + strlen($batt_event[$batterij][$t_end])) * imagefontwidth($infofont));
if( $event['status'] == 'ok' || $event['status'] == 'verwijderd' ) {
$y_label = $y - (imagefontheight($infofont) >> 1);
if( $right ) {
imageline($im, $x, $y, $x , $y - imagefontwidth($infofont), $info_color);
imageline($im, $x, $y, $x + imagefontwidth($infofont), $y, $info_color);
imageline($im, $x, $y, $x + imagefontheight($infofont) * .7, $y - imagefontheight($infofont) * .7, $info_color);
$x_label = $x + imagefontheight($infofont);
$align = ALH_LEFT | ALV_BOTTOM;
}
else {
imageline($im, $x, $y, $x , $y - imagefontwidth($infofont), $info_color);
imageline($im, $x, $y, $x - imagefontwidth($infofont), $y, $info_color);
imageline($im, $x, $y, $x - imagefontheight($infofont) * .7, $y - imagefontheight($infofont) * .7, $info_color);
$x_label = $x - imagefontheight($infofont);
$align = ALH_RIGHT | ALV_BOTTOM;
}
}
else {
$y_label = $y + (imagefontheight($infofont) >> 1);
if( $right ) {
imageline($im, $x, $y, $x , $y + imagefontwidth($infofont), $info_color);
imageline($im, $x, $y, $x + imagefontwidth($infofont), $y, $info_color);
imageline($im, $x, $y, $x + imagefontheight($infofont) * .7, $y + imagefontheight($infofont) * .7, $info_color);
$x_label = $x + imagefontheight($infofont);
$align = ALH_LEFT | ALV_TOP;
}
else {
imageline($im, $x, $y, $x , $y + imagefontwidth($infofont), $info_color);
imageline($im, $x, $y, $x - imagefontwidth($infofont), $y, $info_color);
imageline($im, $x, $y, $x - imagefontheight($infofont) * .7, $y + imagefontheight($infofont) * .7, $info_color);
$x_label = $x - imagefontheight($infofont);
$align = ALH_RIGHT | ALV_TOP;
}
}
imagestringborderalign($im, $infofont, $x_label, $y_label, _($event['status']), $info_color, $bgcolor_transp, $align);
if( $zkl_info['wcpu_versie']['datecode'] >= 0x20090628 ) {
if( $align & ALV_TOP )
$y_label += imagefontheight($infofont);
else
$y_label -= imagefontheight($infofont);
$val = $event['leeftijd'];
imagestringborderalign($im, $infofont, $x_label, $y_label, sprintf("%u:%02u:%02u", $val / 3600, ($val / 60) % 60, $val % 60), $info_color, $bgcolor_transp, $align);
}
}
}
}
//
// Draw the title, on top of everything else
//
if( !isset($_GET['hide_title']) ) {
imagestringborderalign($im, $labelfont, $width >> 1, 0, sprintf(_("%s - Battery - %s to %s"), $zkl_info['idcode'], strftime("%c", $tmin), strftime("%c", $tmax)), $gridcolor, $bgcolor_transp, ALV_TOP | ALH_CENTER);
}
//
// Output the final image
//
imagepng($im);
imagedestroy($im);
// clean-up
if( $db_main_info['file'] != $db_info['file'] ) mysql_close($db_main_handle);
mysql_close($db_data_handle);
?>