$max ) return $max; else return $val; } function get_tmin_tmax_from_file($fname, &$tmin, &$tmax) { $fp = fopen($fname, "r"); while( ($str = fgets($fp)) !== FALSE ) { if( preg_match("/timestamp ([0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]{1,2}:[0-9]{2}:[0-9]{2})/", $str, $matches) > 0 ) { $t = strtotime($matches[1]); if( $t >= strtotime("2007-01-01 00:00:00") ) { if( $tmin == 0 ) { $tmin = $tmax = $t; } else { if( $t < $tmin ) $tmin = $t; if( $t > $tmax ) $tmax = $t; } } } } fclose($fp); } function file_fetch_line($fp, &$date) { while( 1 ) { $str = fgets($fp); if( $str === FALSE ) return FALSE; if( strpos($str, "timestamp") !== FALSE ) { if( substr($str, 0, 8) == "00:00:00" ) $date += 24 * 60 * 60; } else if( strpos($str, "measurement details") !== FALSE ) { if( preg_match("/rms=([0-9A-F]{4}), b\/a=([0-9A-F]{4})/", $str, $matches) > 0 ) { return array( 't' => strtotime(date("Y-m-d", $date) . " " . substr($str, 0, 8)), 'b_a' => intval($matches[2], 16) / 65536.0, 'rms' => intval($matches[1], 16) ); } } } } // which table? $use_log_realtime = isset($_GET['log_realtime']); $use_file = isset($_GET['file']); // TO DO: include the right file with definitions for the database if( !$use_file ) { // 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( $use_file ) { // get tmin,tmax from the log file if( is_array($_GET['file']) ) { } else { $tmin = $tmax = 0; get_tmin_tmax_from_file($_GET['file'], $tmin, $tmax); array_push($logfiles, array('file' => $_GET['file'], 'tmin' => $tmin, 'tmax' => $tmax)); } } 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( $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( $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 = 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, 218, 255, 218); $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 - 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 } if( !isset($_GET['hide_info']) ) $y_ext -= imagefontheight($infofont) * 2; // 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,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) $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 // $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 // 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; //error_log("logfile(" . $logfile['sdcard'] . "," . $logfile['rpgmcount'] . "," . $logfile['startup'] . ") " . date("Y-m-d H:i:s", $log_tmin) . "->" . date("Y-m-d H:i:s", $log_tmax)); // $sdcard = $logfile['sdcard']; $rpgmcount = $logfile['rpgmcount']; $startup = $logfile['startup']; // measurement start/end $m_begin = array(); $m_end = array(); $p = 0; $t_cal_start = array(); if( $logfile['file'] ) { // data already collected $fp = fopen($logfile['file'], "r"); $date = strtotime(date("Y-m-d", $logfile['tmin'])); while( ($str = fgets($fp)) !== FALSE ) { if( strpos($str, "timestamp") !== FALSE ) { if( substr($str, 0, 8) == "00:00:00" ) $date += 24 * 60 * 60; } else if( strpos($str, "measurement start") !== FALSE ) { $m_begin[$p] = strtotime(date("Y-m-d", $date) . " " . substr($str, 0, 8)); } else if( strpos($str, "measurement end") !== FALSE ) { $m_end[$p++] = strtotime(date("Y-m-d", $date) . " " . substr($str, 0, 8)); } else if( strpos($str, "measurement details") !== FALSE ) { if( preg_match("/default b\/a threshold=([01]\.[0-9]{3})/", $str, $matches) > 0 ) { $b_a_threshold = $matches[1]; } else if( preg_match("/PWM updated, period=[0-9]+ \(([0-9.]+)kHz\)/", $str, $matches) > 0 ) { array_push($t_cal_start, array( 'tijd' => strtotime(date("Y-m-d", $date) . " " . substr($str, 0, 8)), 'minor' => 0x18, 'b_a' => $b_a_threshold, 'freq' => $matches[1] * 1000 )); } } } fclose($fp); } else if( $use_log_realtime ) { // cache minimum and maximum id; this is a lot faster for some reason $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; $result = mysql_run($query, $db_data_handle); if( $result ) { $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]; } $meting = 0; $query = "SELECT t,changes,mcu_state,b_a_autocal,freq "; $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 & 0x0081) != 0"; $query .= " )"; $query .= " ) "; $query .= "ORDER BY id"; $result = mysql_run($query, $db_data_handle); while( $row = mysql_fetch_assoc($result) ) { if( ($row['mcu_state'] & 0x0001) != $meting ) { if( ($meting = ($row['mcu_state'] & 0x0001)) ) { // measurement start $m_begin[$p] = $row['t']; $m_end[$p] = -1; // measurement start (or start of data) or auto-calibration array_push( $t_cal_start, array( 't' => $row['t'], 'minor' => (($row['changes'] & 0x0080) ? 0x24 : 0x18), // auto-calibration? if not, measurement start 'b_a' => $row['b_a_autocal'], 'freq' => $row['freq'] ) ); $p++; } else { // measurement end $m_end[$p - 1] = $row['t']; } } else if( ($row['changes'] & 0x0080) && $row['b_a_autocal'] ) { array_push( $t_cal_start, array( 't' => $row['t'], 'minor' => 0x24, // auto-calibration (or start of log) 'b_a' => $row['b_a_autocal'], 'freq' => $row['freq'] ) ); } } } else { // normal log data $query = "SELECT t,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 ) { $m_begin[$p] = $row['t']; $m_end[$p] = -1; if( $p > 0 && $m_end[$p - 1] == -1 ) { $m_end[$p - 1] = $row['t']; } $p++; } else if( $p > 0 ) { $m_end[$p - 1] = $row['t']; } } } if( $p > 0 && $m_end[$p - 1] == -1 ) $m_end[$p - 1] = $tmax; // valid measurements? if not, bail out here if( $p == 0 && !$_GET['all'] ) continue; $n = $p; // // Draw b/a limit line // if( $logfile['file'] ) { } else if( $use_log_realtime ) { // data already collected } else { $query = "SELECT log_zkl.t,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); while( $row = mysql_fetch_assoc($result) ) { array_push($t_cal_start, $row); } } $p = 0; $p_cal = 0; while( $p < $n && $m_end[$p] < $tmin ) $p++; while( $p_cal < count($t_cal_start) && $p < $n ) { $b_a = $t_cal_start[$p_cal]['b_a']; $t_begin = $t_cal_start[$p_cal]['t']; $t_end = ($p_cal + 1 == count($t_cal_start)) ? $log_tmax : $t_cal_start[$p_cal + 1]['t']; if( $t_begin > $log_tmax ) { $p_cal++; continue; } if( $t_end < $log_tmin ) { $p_cal++; continue; } if( $t_begin < $m_begin[$p] ) $t_begin = $m_begin[$p]; if( $t_begin < $log_tmin ) $t_begin = $log_tmin; if( $t_end > $m_end[$p] ) $t_end = $m_end[$p]; if( $t_end > $log_tmax ) $t_end = $log_tmax; if( $t_end < $m_begin[$p] ) { $p_cal++; continue; } 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 ); $p_cal++; if( $t_end >= $m_end[$p] ) $p++; } // // Plot the data // // get the data if( $logfile['file'] ) { $fp = fopen($logfile['file'], "r"); $date = strtotime(date("Y-m-d", $logfile['tmin'])); } else if( $use_log_realtime ) { $query = "SELECT t,b_a,rms "; $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 & 0x0030) != 0 AND "; $query .= " (mcu_state & 0x0001) != 0 "; $query .= " )"; $query .= " ) "; $query .= "ORDER BY id"; $result = mysql_run($query, $db_data_handle); } else { // normal log data $query = "SELECT log_zkl.t,log_meting.b_a,log_meting.rms"; if( $zkl_info['wcpu_versie']['datecode'] >= 0x20091006 ) $query .= ",log_meting.d_b_a,log_meting.d_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 = 0; while( $logfile['file'] ? $row = file_fetch_line($fp, $date) : $row = mysql_fetch_assoc($result) ) { if( !isset($t_start) ) { $t_start = $row['t']; $b_a = $row['b_a']; $rms = $row['rms']; $d_b_a = $row['d_b_a']; $d_rms = $row['d_rms']; } else { $t_this = $t_end = $row['t']; if( ( $_GET['all'] && $t_end >= $log_tmin && $t_start <= $log_tmax ) || ( $p < $n && $t_end >= $m_begin[$p] && $t_end >= $log_tmin && ($p == $n || $t_start < $m_end[$p]) && $t_start <= $log_tmax ) ) { // adjust start and end of the line if( $t_start < $log_tmin ) $t_start = $log_tmin; if( $t_end > $log_tmax ) $t_end = $log_tmax; if( !$_GET['all'] ) { if( $t_start < $m_begin[$p] ) { $t_start = $m_begin[$p]; // new measurement $b_a = $row['b_a']; $rms = $row['rms']; } if( $p < $n && $t_end >= $m_end[$p] ) { $t_end = $m_end[$p]; $p++; } } // 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['wcpu_versie']['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 ); if( $t_end == $t_this ) { // draw connecting line for the next segment 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( $zkl_info['wcpu_versie']['datecode'] >= 0x20091006 && $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 ); if( $t_end == $t_this ) { // draw connecting line for the next segment 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 * $row['b_a']), $b_a_color ); } } else if( $p < $n && $t_end >= $m_end[$p] ) { $p++; } $t_start = $t_this; $b_a = $row['b_a']; $rms = $row['rms']; $d_b_a = $row['d_b_a']; $d_rms = $row['d_rms']; } } // draw last segment $t_end = $log_tmax; if( $p < $n && $t_end >= $m_begin[$p] && $t_end >= $log_tmin && ($p == $n || $t_start < $m_end[$p]) && $t_start <= $log_tmax ) { // adjust start and end of the line if( $t_start < $m_begin[$p] ) $t_start = $m_begin[$p]; if( $p < $n && $t_end >= $m_end[$p] ) { $t_end = $m_end[$p]; } 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( $zkl_info['wcpu_versie']['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), $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( $zkl_info['wcpu_versie']['datecode'] >= 0x20091006 && $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]['t'] - $t_cal_start[$i]['t']) < $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,t,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]['t'] >= $row['t'] && !$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 $p = 0; $p_cal = 0; while( $p < $n && $m_end[$p] < $tmin ) $p++; while( $p_cal < count($t_cal_start) && $p < $n ) { $b_a = $t_cal_start[$p_cal]['b_a']; $f = $t_cal_start[$p_cal]['freq']; $t_begin = $t_cal_start[$p_cal]['t']; $t_end = ($p_cal + 1 == count($t_cal_start)) ? $log_tmax : $t_cal_start[$p_cal + 1]['t']; if( $t_begin > $log_tmax ) { $p_cal++; continue; } if( $t_end < $log_tmin ) { $p_cal++; continue; } if( $t_begin < $m_begin[$p] ) $t_begin = $m_begin[$p]; if( $t_begin < $log_tmin ) $t_begin = $log_tmin; if( $t_end > $m_end[$p] ) $t_end = $m_end[$p]; if( $t_end > $log_tmax ) $t_end = $log_tmax; if( $t_end < $m_begin[$p] ) { $p_cal++; continue; } $x = $x_off + ((($t_begin - $tmin) * $x_ext) / $duration); $y = $y_off - ($y_ext * $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", $b_a) . "\n" . sprintf("f =%5.0f", $f), $cal_info_color, $bgcolor_transp, $align); $p_cal++; if( $t_end >= $m_end[$p] ) $p++; } // get switch events (relay events are no longer plotted as the relay // is no longer used to switch the short circuit between the rails if( $logfile['file'] ) { } else if( $use_log_realtime ) { } else { $query = "SELECT t,major,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 .= " ("; $query .= " major=0xA AND "; $query .= " (minor=0x68 OR minor=0x69)"; $query .= " ) "; $query .= "ORDER BY id"; $result = mysql_run($query, $db_data_handle); while( $row = mysql_fetch_assoc($result) ) { $t_cal = $row['t']; //if( $t_cal < $log_tmin ) $t_cal = $log_tmin; //if( $t_cal > $log_tmax ) $t_cal = $log_tmax; if( $t_cal >= $log_tmin && $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), ($row['major'] == 0xD ? _("relais") : _("switch")) . " " . (($row['minor'] & 0x01) == 0 ? _("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); if( $use_log_realtime ) imagestringborderalign($im, $labelfont, $width >> 1, imagefontheight($labelfont), _("(real-time data log)"), $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); ?>