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

919 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-runavg.php
** Author: Jack Weeland
** Date: July 6, 2009
** File version: $Release$
** $Date: 2013/10/30 17:22:36 $
**
************************************************************************
*/
/*
************************************************************************
**
** TEST SCRIPT FOR THE RUNNING AVERAGE COMPRESSION
** ===============================================
**
** Display a measurement 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
** show_rms - also plot the RMS values
** hide_title - do not device id-code and date
** hide_info - do not show additional info
**
** 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);
function clip($val, $min, $max)
{
if( $val < $min )
return $min;
else if( $val > $max )
return $max;
else
return $val;
}
function avg($array, $count, &$h_delta)
{
if( $count == 0 ) {
$h_delta = 0;
return 0;
}
// sum and average
$sum = 0;
for( $i = 0; $i < $count; $i++ ) $sum += $array[$i];
$avg = $sum / $count;
// delta
$h_delta = 0;
for( $i = 0; $i < $count; $i++ ) {
$delta = abs($array[$i] - $avg);
if( $delta > $h_delta ) $h_delta = $delta;
}
return $avg;
}
// 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;
}
}
// determine width and height
$width = $_GET['w'];
$height = $_GET['h'];
if( !$width ) $width = 640;
if( !$height ) $height = 480;
// get information about the device
if( isset($_GET['logfile']) ) {
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(UNIX_TIMESTAMP(tijd)) AS tmin,MAX(UNIX_TIMESTAMP(tijd)) 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);
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(UNIX_TIMESTAMP(tijd)) AS tmin,MAX(UNIX_TIMESTAMP(tijd)) 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);
array_push($logfiles, array('sdcard' => $sdcard, 'rpgmcount' => $rpgmcount, 'startup' => $startup, 'tmin' => $row['tmin'], 'tmax' => $row['tmax']));
}
}
else {
// retrieve logfiles from the database
$query = "SELECT sdcard,rpgmcount,startup,MIN(UNIX_TIMESTAMP(tijd)) AS tmin,MAX(UNIX_TIMESTAMP(tijd)) AS tmax ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " tijd BETWEEN FROM_UNIXTIME(" . $tmin . ") AND FROM_UNIXTIME(". $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['logfile']) ) {
error_log($PHP_SELF . ": no log file or time range defined");
exit(1);
}
list($sdcard,$rpgmcount,$startup) = explode(',', $_GET['logfile']);
$query = "SELECT MIN(UNIX_TIMESTAMP(tijd)) AS tmin,MAX(UNIX_TIMESTAMP(tijd)) 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);
list($tmin,$tmax) = mysql_fetch_array($result);
array_push($logfiles, array('sdcard' => $sdcard, 'rpgmcount' => $rpgmcount, 'startup' => $startup, 'tmin' => $tmin, 'tmax' => $tmax));
}
if( $tmin >= $tmax ) {
error_log($PHP_SELF . ": empty time range: " . strftime("%D %T", $tmin) . "-" . strftime("%D %T", $tmax));
exit(1);
}
$tz_offset = date("Z");
$duration = $tmax - $tmin;
//
// Draw the graph
//
header("Content-type: image/png");
header('Pragma: no-cache');
// create the image
$im = imagecreatetruecolor($width,$height);
if( function_exists("imageantialias") )
imageantialias($im, true);
$black = imagecolorstring($im, "black");
$white = imagecolorstring($im, "white");
$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);
$tdgreen = imagecolorallocatealpha($im, 0, 160, 0, 96);
$red = imagecolorstring($im, "red");
$lred = imagecolorstring($im, "#FFC0C0");
$dred = imagecolorallocate($im, 160, 0, 0);
$blue = imagecolorallocate($im, 0, 0, 224);
$tblue = imagecolorallocatealpha($im, 0, 0, 224, 96);
$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
$cal_b_a_color = $lred; // b/a limit line
$cal_info_color = $red; // info with the above
$cal_rms_color = $llgreen; // very light green
$cal_rms_bcolor = $lgreen; // border for legend, a bit darker light green
$b_a_color = $blue; // line of the b/a graph
$b_a_tcolor = $tblue; // line of the b/a graph
$rms_color = $dgreen; // line of the rms graph
$rms_tcolor = $tdgreen; // line of the rms graph
//
// 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;
}
//
// 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 = 5 * 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 - 10 * imagefontwidth($labelfont); // date/time
$y_ext = $y_off;
if( !isset($_GET['hide_title']) )
$y_ext -= imagefontheight($labelfont); // title
else
$y_ext -= imagefontheight($labelfont) >> 1; // extent of the top value label
if( !isset($_GET['hide_info']) )
$y_ext -= imagefontheight($infofont) << 1; // info + arrow
// draw valid/okay RMS indicator below anything else
if( isset($_GET['show_rms']) ) {
imagefilledrectangle($im,
$x_off, $y_off - ($y_ext * (sqrt(5735) / 100.0)),
$x_off + $x_ext, $y_off - ($y_ext * (sqrt( 800) / 100.0)),
$cal_rms_color
);
}
// The grid is drawn _under_ the lines and ornaments like the title etc
// Y tick marks every 0.100
for( $y_tick = 0; $y_tick <= 1.0; $y_tick += 0.1 ) {
$y = $y_tick * $y_ext;
imageline($im, $x_off, $y_off - $y, $x_off + $x_ext, $y_off - $y, $lgrey);
imageline($im, $x_off - 2, $y_off - $y, $x_off, $y_off - $y, $black);
imagestringalign($im, $labelfont, $x_off - 2, $y_off - $y, sprintf("%.2f", $y / $y_ext), $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,2*60*60,4*60*60,6*60*60,8*60*60,12*60*60,24*60*60,7*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;
}
for( $x = ($x_ext * $x_tick_val) / $duration; $x <= $x_ext; $x += $x_tick_step ) {
$x_time = $tmin + $x_tick_val;
if( $x_tick_off >= (24*60*60) ) {
if( strftime("%d", $x_time) == "01" ) {
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", $x_time), $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", $x_time), $gridcolor, ALV_TOP | ALH_CENTER);
}
else {
if( strftime("%H%M%S", $x_time) == "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", $x_time), $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", $x_time), $gridcolor, ALV_TOP | ALH_CENTER);
}
$x_tick_val += $x_tick_off;
}
if( $x_tick_off != (24*60*60) )
imagestringupalign($im, $labelfont, $x_off, $y_off - 2, strftime("%x", $tmin), $grey, ALV_BOTTOM | ALH_LEFT);
//
// Draw the legend
//
$y_legend_off = $y_off;
if( isset($_GET['show_rms']) ) {
$y_legend_off -= ($y_ext - (8+4+11+4+8+4+14) * imagefontwidth($labelfont)) >> 1;
imagestringupalign($im, $labelfont, 0, $y_legend_off - 4 * imagefontwidth($labelfont), "rms", $gridcolor, ALV_TOP | ALH_LEFT);
imageline($im,
imagefontheight($labelfont) >> 1, $y_legend_off - 5.5 * imagefontwidth($labelfont), /* space */
imagefontheight($labelfont) >> 1, $y_legend_off - 8 * imagefontwidth($labelfont), /* line length */
$rms_color
);
$y_legend_off -= (8+4) * imagefontwidth($labelfont);
imagestringupalign($im, $labelfont, 0, $y_legend_off - 7 * imagefontwidth($labelfont), "rms ok", $gridcolor, ALV_TOP | ALH_LEFT);
imagefilledrectangle($im,
0, $y_legend_off - 11 * imagefontwidth($labelfont),
imagefontheight($labelfont), $y_legend_off - 8 * imagefontwidth($labelfont),
$cal_rms_color
);
imagerectangle($im,
0, $y_legend_off - 11 * imagefontwidth($labelfont),
imagefontheight($labelfont), $y_legend_off - 8 * imagefontwidth($labelfont),
$cal_rms_bcolor
);
$y_legend_off -= (11+4) * imagefontwidth($labelfont);
}
else {
$y_legend_off -= ($y_ext - (8+4+14) * imagefontwidth($labelfont)) >> 1;
};
imagestringupalign($im, $labelfont, 0, $y_legend_off - 4 * imagefontwidth($labelfont), "b/a", $gridcolor, ALV_TOP | ALH_LEFT);
imageline($im,
imagefontheight($labelfont) >> 1, $y_legend_off - 5 * imagefontwidth($labelfont), /* space */
imagefontheight($labelfont) >> 1, $y_legend_off - 8 * imagefontwidth($labelfont), /* line length */
$b_a_color
);
$y_legend_off -= (8+4) * imagefontwidth($labelfont);
imagestringupalign($im, $labelfont, 0, $y_legend_off - 10 * imagefontwidth($labelfont), "b/a limit", $gridcolor, ALV_TOP | ALH_LEFT);
imageline($im,
imagefontheight($labelfont) >> 1, $y_legend_off - 11 * imagefontwidth($labelfont), /* space */
imagefontheight($labelfont) >> 1, $y_legend_off - 14 * imagefontwidth($labelfont), /* line length */
$cal_b_a_color
);
//
// 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
//
$h_size = 64;
$h_b_a = array();
$h_rms = array();
for( $i = 0; $i < $h_size; $i++ ) {
$h_b_a[$i] = 1.0;
$h_rms[$i] = 0;
}
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'];
// measurement start/end
$m_begin = array();
$m_end = array();
$query = "SELECT UNIX_TIMESTAMP(tijd) AS tijd,major ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup . " AND ";
$query .= " (major=1 OR major=2) ";
$query .= "ORDER BY id";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
if( $row['major'] == 1 )
array_push($m_begin, $row['tijd']);
else
array_push($m_end, $row['tijd']);
}
$n_begin = count($m_begin);
$n_end = count($m_end);
// valid measurements? if not, bail out here
if( $n_begin == 0 ) continue;
//
// Draw b/a limit line
//
$query = "SELECT UNIX_TIMESTAMP(log_zkl.tijd) AS tijd,log_zkl.minor,log_calibratie.b_a,log_calibratie.freq ";
$query .= "FROM log_zkl,log_calibratie ";
$query .= "WHERE ";
$query .= " log_zkl.id=log_calibratie.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_calibratie.b_a <> 0 "; // failed auto-calibration
$query .= "ORDER BY log_zkl.id";
$result = mysql_run($query, $db_data_handle);
$p_begin = 0;
$p_end = 0;
$t_cal_start = array();
while( $row = mysql_fetch_assoc($result) ) array_push($t_cal_start, $row);
$cal = 0;
while( $cal < count($t_cal_start) ) {
$b_a = $t_cal_start[$cal]['b_a'];
$t_begin = $t_cal_start[$cal]['tijd'];
$t_end = ($cal + 1 < count($t_cal_start)) ? $t_cal_start[$cal + 1]['tijd'] : $log_tmax;
if( $t_end <= $m_begin[$p_begin] ) {
$cal++;
continue;
}
if( $p_begin < $n_begin ) {
if( $t_begin <= $m_begin[$p_begin] ) {
$t_begin = $m_begin[$p_begin];
}
}
while( 1 ) {
if( $p_end < $n_end && $t_end >= $m_end[$p_end] ) {
$t_end = $m_end[$p_end];
$p_begin++;
$p_end++;
}
else {
// last piece of the line will be drawn
$cal++;
break;
}
}
if( $t_begin < $log_tmin ) $t_begin = $log_tmin;
if( $t_end < $log_tmin ) continue;
else if( $t_end > $log_tmax ) $t_end = $log_tmax;
imageline($im,
$x_off + ((($t_begin - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$lred
);
}
//
// Plot the data
//
$h_ptr = 0;
$h_count = 0;
$h_delta = 0;
$prev_time = 0;
$ref_avg = 0;
$ref_b_a = 0;
$ref_delta = 1;
// get the data
$query = "SELECT UNIX_TIMESTAMP(log_zkl.tijd) AS tijd,log_meting.b_a,log_meting.rms";
$query .= " ";
$query .= "FROM log_zkl,log_meting ";
$query .= "WHERE ";
$query .= " log_zkl.id=log_meting.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 . " ";
$query .= "ORDER BY log_zkl.id";
$result = mysql_run($query, $db_data_handle);
unset($t_start);
$p_begin = 0;
$p_end = 0;
while( $row = mysql_fetch_assoc($result) ) {
if( !isset($t_start) ) {
$t_start = $row['tijd'];
$b_a = $row['b_a'];
$rms = $row['rms'];
$d_b_a = 0;
//$d_rms = $row['d_rms'];
}
else {
$time = strtotime($row['tijd']);
if( $prev_time > 0 ) {
while( ++$prev_time < $time ) {
// should be done twice, but it's only to give an idea
// of how good the algorithm works
$h_b_a[$h_ptr] = $prev_b_a;
$h_rms[$h_ptr] = $prev_rms;
$h_ptr = ($h_ptr + 1) & ($h_size - 1);
if( $h_count < $h_size ) $h_count++;
}
// probably this:
$ref_b_a = $prev_b_a;
//$ref_avg = avg($h_b_a, $h_count, $h_delta);
}
$prev_time = $time;
$t_this = $t_end = $row['tijd'];
if(
$p_begin < $n_begin &&
$t_end >= $m_begin[$p_begin] &&
$t_end >= $log_tmin &&
($p_end == $n_end || $t_start < $m_end[$p_end]) &&
$t_start <= $log_tmax
) {
// adjust start and end of the line
if( $t_start < $m_begin[$p_begin] ) {
$t_start = $m_begin[$p_begin];
// new measurement
$b_a = $row['b_a'];
$rms = $row['rms'];
}
if( $p_end < $n_end && $t_end >= $m_end[$p_end] ) {
$t_end = $m_end[$p_end];
$p_begin++;
$p_end++;
}
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;
$avg = avg($h_b_a, $h_count, $h_delta);
$delta = abs($row['b_a'] - $avg);
$log = false;
if( $delta > .25 ) {
$log = true;
$h_ptr = 0;
$h_count = 0;
$ref_avg = $avg = $row['b_a'];
$ref_delta = 0;
}
else if( $delta > ($h_delta + (16/1024)) ) {
// delta of this measurement is higher than the historical data
// (plus a little margin)
$log = true;
$ref_avg = $avg;
$ref_delta = $delta;
}
else if( abs($h_delta - $ref_delta) > (8/1024) ) {
// change in historical delta
$log = true;
$ref_avg = $avg;
$ref_delta = $h_delta;
}
else if( abs($avg - $ref_avg) > (8/1024) ) {
// change in running average
$log = true;
$ref_avg = $avg;
$ref_delta = $h_delta;
}
if( $log ) {
// b/a is more important than the rms-value
if( isset($_GET['show_rms']) ) {
$prev_rms = sqrt($rms) / 100.0;
$new_rms = sqrt($row['rms']) / 100.0;
if(
$zkl_info['firmware']['wcpu']['datecode'] >= 0x20091006 &&
$d_rms &&
($d_rms * $y_ext) > 1
) {
// draw a (lighter) rectangle to show the delta
$min_rms = sqrt($rms + $d_rms) / 100.0;
$max_rms = sqrt($rms - $d_rms) / 100.0;
imagefilledrectangle($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext) , $y_off - ($y_ext * clip($min_rms, 0.0, 1.0)),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext) - 1, $y_off - ($y_ext * clip($max_rms, 0.0, 1.0)),
$rms_tcolor
);
}
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_rms),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_rms),
$rms_color
);
imageline($im,
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_rms),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $new_rms),
$rms_color
);
}
if(
$d_b_a &&
($d_b_a * $y_ext) > 1
) {
// draw a (lighter) rectangle to show the delta
imagefilledrectangle($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext) , $y_off - ($y_ext * clip($b_a + $d_b_a, 0.0, 1.0)),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext) - 1, $y_off - ($y_ext * clip($b_a - $d_b_a, 0.0, 1.0)),
$b_a_tcolor
);
}
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$b_a_color
);
imageline($im,
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $avg),
$b_a_color
);
}
}
else if( $p_end < $n_end && $t_end >= $m_end[$p_end] ) {
$p_begin++;
$p_end++;
}
if( $log ) {
$t_start = $t_this;
$b_a = $avg;//$row['b_a'];
$rms = $row['rms'];
$d_b_a = $h_delta;
//$d_rms = $row['d_rms'];
}
}
$h_b_a[$h_ptr] = $row['b_a'];
$h_rms[$h_ptr] = $row['rms'];
$h_ptr = ($h_ptr + 1) & ($h_size - 1);
if( $h_count < $h_size ) $h_count++;
// save
$prev_b_a = $row['b_a'];
$prev_rms = $row['rms'];
}
// draw last segment
$t_end = $log_tmax;
if(
$p_begin < $n_begin &&
$t_end >= $m_begin[$p_begin] &&
$t_end >= $log_tmin &&
($p_end == $n_end || $t_start < $m_end[$p_end]) &&
$t_start <= $log_tmax
) {
// adjust start and end of the line
if( $t_start < $m_begin[$p_begin] ) $t_start = $m_begin[$p_begin];
if( $p_end < $n_end && $t_end >= $m_end[$p_end] ) {
$t_end = $m_end[$p_end];
}
if( $t_start < $log_tmin ) $t_start = $log_tmin;
if( $t_end > $log_tmin ) {
if( $t_end > $log_tmax ) $t_end = $log_tmax;
if( isset($_GET['show_rms']) ) {
$prev_rms = sqrt($rms) / 100.0;
if(
$d_rms &&
($d_rms * $y_ext) > 1
) {
// draw a (lighter) rectangle to show the delta
$min_rms = sqrt($rms + $d_rms) / 100.0;
$max_rms = sqrt($rms - $d_rms) / 100.0;
imagefilledrectangle($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * clip($min_rms, 0.0, 1.0)),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * clip($max_rms, 0.0, 1.0)),
$rms_tcolor
);
}
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_rms),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $prev_rms),
$rms_color
);
}
if(
$d_b_a &&
($d_b_a * $y_ext) > 1
) {
// draw a (lighter) rectangle to show the delta
imagefilledrectangle($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * clip($b_a + $d_b_a, 0.0, 1.0)),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * clip($b_a - $d_b_a, 0.0, 1.0)),
$b_a_tcolor
);
}
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * $b_a),
$b_a_color
);
}
}
//
// Print additional info
//
if( !isset($_GET['hide_info']) ) {
// discard "doubles" in the $t_cal_start array
$dt = (9 * imagefontwidth($infofont) * $duration) / $x_ext;
$db_a = (4 * imagefontheight($infofont)) / $y_ext;
for( $i = 1; $i < count($t_cal_start); $i++ ) {
$j = $i;
while( --$j >= 0 ) {
if(
abs($t_cal_start[$j]['tijd'] - $t_cal_start[$i]['tijd']) < $dt &&
abs($t_cal_start[$j]['b_a'] - $t_cal_start[$i]['b_a']) < $db_a
) $t_cal_start[$j]['hide'] = TRUE;
}
}
// get "events"
$query = "SELECT id,UNIX_TIMESTAMP(tijd) AS tijd,minor ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup . " AND ";
$query .= " major=5 AND ";
$query .= " (minor=0x11 OR minor=0x23) ";
$query .= "ORDER BY id";
$result = mysql_run($query, $db_data_handle);
// try to match the events with an entry in the array of calibration data
while( $row = mysql_fetch_assoc($result) ) {
for( $i = 0; $i < count($t_cal_start); $i++ ) {
if( $t_cal_start[$i]['tijd'] >= $row['tijd'] && !$t_cal_start[$i]['hide'] ) {
switch( $row['minor'] ) {
case 0x23:
$autocal_query = "SELECT aan_uit,status FROM log_calibratiestart WHERE id=" . $row['id'];
$autocal_result = mysql_run($autocal_query, $db_data_handle);
$autocal_row = mysql_fetch_assoc($autocal_result);
if( $autocal_row['aan_uit'] == 'uit' && $autocal_row['status'] == 'ok' )
$t_cal_start[$i]['event'] = 'auto-cal';
break;
case 0x11:
$t_cal_start[$i]['event'] = 'sweep';
break;
}
break;
}
}
}
// plot them in the graph
foreach( $t_cal_start as $cal_info ) if( !$cal_info['hide'] ) {
$t_cal = $cal_info['tijd'];
if( $t_cal < $log_tmin ) $t_cal = $log_tmin;
if( $t_cal > $log_tmax ) $t_cal = $log_tmax;
$x = $x_off + ((($t_cal - $tmin) * $x_ext) / $duration);
$y = $y_off - ($y_ext * $cal_info['b_a']);
if( $x < $x_off + 9 * imagefontwidth($infofont) ) {
imageline($im, $x, $y, $x , $y - imagefontwidth($infofont), $cal_info_color);
imageline($im, $x, $y, $x + imagefontwidth($infofont), $y, $cal_info_color);
imageline($im, $x, $y, $x + imagefontheight($infofont) * .7, $y - imagefontheight($infofont) * .7, $cal_info_color);
$x += imagefontheight($infofont);
$align = ALH_LEFT | ALV_BOTTOM;
}
else {
imageline($im, $x, $y - 1, $x - (imagefontwidth($infofont) >> 1), $y - 1 -(imagefontwidth($infofont) >> 1), $cal_info_color);
imageline($im, $x, $y - 1, $x + (imagefontwidth($infofont) >> 1), $y - 1 - (imagefontwidth($infofont) >> 1), $cal_info_color);
imageline($im, $x, $y, $x, $y - imagefontheight($infofont), $cal_info_color);
$align = ALH_CENTER | ALV_BOTTOM;
}
imagestringborderalign($im, $infofont, $x, $y - imagefontheight($infofont), $cal_info['event'] . "\n" . sprintf("b/a=%.3f", $cal_info['b_a']) . "\n" . sprintf("f =%5.0f", $cal_info['freq']), $cal_info_color, $bgcolor_transp, $align);
}
// get relais events
$query = "SELECT UNIX_TIMESTAMP(tijd) AS tijd,minor ";
$query .= "FROM log_zkl ";
$query .= "WHERE ";
$query .= " zkl=" . $_GET['zkl'] . " AND ";
$query .= " sdcard=" . $sdcard . " AND ";
$query .= " rpgmcount=" . $rpgmcount . " AND ";
$query .= " startup=" . $startup . " AND ";
$query .= " major=0xD AND ";
$query .= " (minor=0x18 OR minor=0x19) ";
$query .= "ORDER BY id";
$result = mysql_run($query, $db_data_handle);
while( $row = mysql_fetch_assoc($result) ) {
$t_cal = $row['tijd'];
if( $t_cal < $log_tmin ) $t_cal = $log_tmin;
if( $t_cal > $log_tmax ) $t_cal = $log_tmax;
$x = $x_off + ((($t_cal - $tmin) * $x_ext) / $duration);
$y = $y_off - $y_ext; // always at the b/a=1.000 line
imageline($im, $x, $y - 1, $x - (imagefontwidth($infofont) >> 1), $y - 1 -(imagefontwidth($infofont) >> 1), $cal_info_color);
imageline($im, $x, $y - 1, $x + (imagefontwidth($infofont) >> 1), $y - 1 - (imagefontwidth($infofont) >> 1), $cal_info_color);
imageline($im, $x, $y, $x, $y - imagefontheight($infofont), $cal_info_color);
$align = ALH_CENTER | ALV_BOTTOM;
imagestringborderalign($im, $infofont, $x, $y - imagefontheight($infofont), _("relais") . "\n" . ($row['minor'] == 0x18 ? _("uit") : _("aan")), $cal_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 - Meting - %s tot %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);
?>