src.dualinventive.com/mtinfo/dist/webroot/rc-4.05/include/plot-temp.php

521 lines
20 KiB
PHP

<?php
/** \file include/plot_temp.php
* \brief DI webinterface plot temperature script.
* \author Rob Schalken, Core|Vision
* \version $Revision: 26247 $
* \date $Date: 2016-02-29 10:40:22 +0100 (Mon, 29 Feb 2016) $
*
* This file contains the temperature plot script
*/
/*
************************************************************************
**
** 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
** 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.
**
************************************************************************
*/
require_once("graphics.php");
// Create temp plot and write to file
function plot_temp_graph($zkl, $start, $end, $log_files, $log_rt, $file, $transparent=1, $width=800, $height=600) {
GLOBAL $_PAGE_INFO;
// Download header
download_document_header("image/png", $file, "write_file", "plot_temp");
// temperature range
$T_max = 70;
$T_min = -25;
$T_range = $T_max - $T_min;
// create the image
$im = imagecreatetruecolor($width+5,$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, $transparent ? 127 : 0);
$bgcolor_transp = imagecolorallocatealpha($im, 255, 255, 255, 96);
$gridcolor = $black; // main grid and markers
$sgridcolor = $lgrey; // guides in the grid
$nextdaycolor = $grey; // next day line
$linecolor = array( 'on-board' => $blue, 'ntc' => $purple );
$zero_color = $lred; // 0 degrees line
$info_color = $red; // additional info
//
// 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;
}
// Minimum time defined?
if (!strlen($start)) {
$tmin = $log_files[0]['tmin'];
}
else {
$tmin = strtotime($start);
}
// Maximum time defined?
if (!strlen($end)) {
$tmax = time();
}
else {
$tmax = strtotime($end);
}
// Get zkl info
$zkl_info = db_fetch_lance($zkl, "", 1);
// Determine for which sensors to plot the data (in logical order)
$supported_sensors = array();
if(
db_check_system_device_capabilities($zkl_info['device'],"temperatuursensor on-board")
) $supported_sensors['on-board'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'on-board');
if(
db_check_system_device_capabilities($zkl_info['device'], "temperatuursensor extern")
) $supported_sensors['ntc'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'extern');
// External sensor #2 are stored in the fields for the on-board sensor (MTinfo supports a maximum of two sensors in total)
if(
!db_check_system_device_capabilities($zkl_info['device'],"temperatuursensor on-board") &&
db_check_system_device_capabilities($zkl_info['device'], "temperatuursensor extern") &&
db_system_device_nr_tempsensors($zkl_info['device']) > 1
) $supported_sensors['on-board'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'on-board');
$tz_offset = $tmin - intval(gmstrftime("%s", $tmin));
$tz_info = localtime($tmin, true);
if( $tz_info['tm_isdst'] ) $tz_offset += 3600;
$duration = $tmax - $tmin;
//
// Draw the grid
//
// draw background
imagefill($im, 0, 0, $bgcolor);
// offsets with the drawing grid
// largest value label: 3 characters ("-10")
// x: left to right
// y: bottom to top
global $x_off, $x_ext, $y_off, $y_ext;
$x_off = 3 * 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)) - 1; // date/time
$y_ext = $y_off;
$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 5.0 C
for( $T = $T_min; $T <= $T_max; $T += 5 ) {
$y = ($y_ext * ($T - $T_min) / $T_range);
imageline($im, $x_off, $y_off - $y, $x_off + $x_ext, $y_off - $y, $T == 0 ? $zero_color : $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("%d", $T),
$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;
}
unset($x_save);
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 ((!isset($x_save) || (($x_off + $x) >= ($x_save + (imagefontheight($labelfont) << 1))))) {
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("%F", $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, strftime("%F", $x_time), $gridcolor, ALV_TOP | ALH_CENTER);
$x_save = $x_off + $x;
}
}
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("%F", $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("%F", $tmin), $grey, ALV_BOTTOM | ALH_LEFT);
//
// Draw the legend
//
$y_legend_off = $y_off;
// determine size of the legend; the lines are 3 characters long separated by a space;
// the labels are separated by four spaces
$y_legend_ext = 4; // (&deg;C)
foreach( $supported_sensors as $sensor => $sensor_info ) {
$str = $sensor_info['display'];
$y_legend_ext += strlen($str) + 4 + 4;
}
$y_legend_ext *= imagefontwidth($labelfont);
if( $y_legend_ext < $y_ext ) $y_legend_off -= ($y_ext - $y_legend_ext) >> 1;
foreach( $supported_sensors as $sensor => $sensor_info ) {
$str = $sensor_info['display'];
$y_legend_off -= strlen($str) * imagefontwidth($labelfont);
imagestringupalign($im, $labelfont, 0, $y_legend_off, $str, $gridcolor, ALV_TOP | ALH_LEFT);
$y_legend_off -= imagefontwidth($labelfont);
imageline($im,
imagefontheight($labelfont) >> 1, $y_legend_off , /* space */
imagefontheight($labelfont) >> 1, $y_legend_off - 3 * imagefontwidth($labelfont), /* line length */
$linecolor[$sensor]
);
$y_legend_off -= (7 * imagefontwidth($labelfont));
}
imagestringupalign($im, $labelfont, 0, $y_legend_off - 4 * imagefontwidth($labelfont), "(\xB0C)", $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
//
// Initial values
$skip_first = FALSE;
$log_count = 0;
// Valid data?
if ((is_array($log_files)) && (is_array($log_rt))) {
if ($log_files[0]['tmin'] > $log_rt[0]['t']) {
// End of log_realtime is start of "first" log file
$rt['end'] = $log_files[0]['tmin'];
// Add dummy log_file entry to log_files array => and skip log files check
$log_files = array_merge(array("Dummy"), $log_files);
// Set skip flag
$skip_first = TRUE;
}
}
do {
// Initial values
$valid_entry = FALSE;
//
// LOG_ZKL
//
if (is_array($log_files)) {
if (!$skip_first) {
// get tmin,tmax for this logfile
$log_tmin = $log_files[$log_count]['tmin'];
$log_tmax = $log_files[$log_count]['tmax'];
if ($log_tmin < $tmin && $log_tmax < $tmin) continue;
if( $log_tmin < $tmin ) $log_tmin = $tmin;
if( $log_tmax > $tmax ) $log_tmax = $tmax;
// define logfile info
$sdcard = $log_files[$log_count]['sdcard'];
$rpgmcount = $log_files[$log_count]['rpgmcount'];
$startup = $log_files[$log_count]['startup'];
// get the data
$query = "SELECT log_zkl.id,log_zkl.t,log_temp.sensor,log_temp.temp ";
$query .= "FROM log_zkl,log_temp ";
$query .= "WHERE ";
$query .= " log_zkl.id=log_temp.id AND ";
$query .= " log_zkl.zkl=" . $zkl . " AND ";
$query .= " log_zkl.sdcard=" . $sdcard . " AND ";
$query .= " log_zkl.rpgmcount=" . $rpgmcount . " AND ";
$query .= " log_zkl.startup=" . $startup . " ";
// select sensor
foreach( $supported_sensors as $sensor => $sensor_info ) {
$query .= " AND log_temp.sensor='" . $sensor . "' ";
}
$query .= "ORDER BY log_zkl.id";
$result = db_fetch_data($query, "log", null, 0);
foreach($supported_sensors as $sensor => $sensor_info) {
unset($t_begin[$sensor]);
unset($stored_value[$sensor]);
}
$counter = 0;
while($row = mysql_fetch_assoc($result['result'])) {
// Get sensor info
$sensor = $row['sensor'];
// Increment counter
$counter++;
// Valid sensor
if ($supported_sensors[$sensor]) {
// First sensor data
if(!isset($t_begin[$sensor])) {
// Valid log data
if ($row['t'] > $log_tmin) {
$t_begin[$sensor] = $row['t'];
}
// Store last value
$stored_value[$sensor] = $row;
}
else {
// Changed or last log value
if (($row['temp'] != $stored_value[$sensor]['temp']) || ($result['nr_rows'] == $counter)) {
// Get start and end time
$t_start = $t_begin[$sensor];
$t_end = $row['t'];
if ($t_end >= $log_tmin && $t_start <= $log_tmax) {
// Check boundaries
if($t_start < $log_tmin) {
$t_start = $log_tmin;
}
else if($t_end > $log_tmax) {
$t_end = $log_tmax;
}
// Invalid timestamp => next sample
if ($t_end < $t_start) continue;
// Data too old (1 hour limit)? => Restart
if (($t_begin[$sensor] < $t_end) && (($t_end - $t_begin[$sensor]) > 3600)) {
$t_begin[$sensor] = $t_end;
}
// Average
$row['temp'] = (($stored_value[$sensor]['temp'] + $row['temp'])/2);
// Set flag
$valid_entry = TRUE;
// Draw line
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($row['temp'] - $T_min) / $T_range),
$linecolor[$sensor]);
// Update variables
$t_begin[$sensor] = $t_end;
$stored_value[$sensor] = $row;
}
}
}
}
}
// Last log entry
foreach($supported_sensors as $sensor => $sensor_info) {
if ((isset($t_begin[$sensor])) && (isset($stored_value[$sensor]))) {
if ($log_tmax > $t_begin[$sensor]) {
// Define start/end
$t_start = $t_begin[$sensor];
$t_end = $log_tmax;
// Set flag
$valid_entry = TRUE;
// Draw line
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
$linecolor[$sensor]);
}
}
}
}
}
// Reset flag
$skip_first = FALSE;
if (is_array($log_files)) {
// Valid entries found? Or searching for the end?
if ($valid_entry) {
// End of this log file is begin of log realtime
$rt['begin'] = $tmax;
}
else {
// No valid entries found => Retry with the log realtime, could be a "bug"
$rt['begin'] = $tmin;
}
// Last log file => end of period, else begin of next log file
$rt['end'] = (($log_count + 1) == sizeof($log_files)) ? $tmax : $log_files[$log_count + 1]['tmin'];
// Check if end is not before begin
if ((strlen($rt['begin'])) && (strlen($rt['end']))) {
$rt['end'] = ($rt['end'] > $rt['begin']) ? $rt['end'] : $rt['begin'];
}
}
else {
$rt['begin'] = $tmin;
$rt['end'] = $tmax;
}
//
// LOG_REALTIME
//
if (is_array($log_rt)) {
// Initial values
$counter = 0;
for ($i = 0; (($i < sizeof($log_rt)) && !((strlen($rt['end'])) && ($log_rt[$i]['t'] > $rt['end']))); $i++) {
// Valid timeframe?
if ((($log_rt[$i]['t'] >= $rt['begin']) || (!$rt['begin'])) && (($log_rt[$i]['t'] <= $rt['end']) || (!$rt['end']))) {
// Increment counter
$counter++;
// Handle all temperature sensors
foreach( $supported_sensors as $sensor => $sensor_info ) {
// Valid data?
if (!is_null($log_rt[$i]["temp_" . str_replace("-", "", $sensor)])) {
// First sensor data
if (!isset($t_begin[$sensor])) {
// Valid log data
$t_begin[$sensor] = $log_rt[$i]['t'];
// Store last value
$stored_value[$sensor] = $log_rt[$i]["temp_" . str_replace("-", "", $sensor)];
}
else {
if ($i) {
//// Data too old (1 hour limit)? => Restart
//if (($log_rt[$i - 1]['t'] < $log_rt[$i]['t']) && (($log_rt[$i]['t'] - $log_rt[$i - 1]['t']) > 3600)) {
// $t_begin[$sensor] = $log_rt[$i]['t'];
//
// // Store last value
// $stored_value[$sensor] = $log_rt[$i]["temp_" . str_replace("-", "", $sensor)];
//}
}
// Changed or last log value
if ((($log_rt[$i]["temp_" . str_replace("-", "", $sensor)] != $stored_value[$sensor]) || (sizeof($log_rt) == $counter))) {
// Get start and end time
$t_start = $t_begin[$sensor];
$t_end = $log_rt[$i]['t'];
// Average
$temp = (($stored_value[$sensor] + $log_rt[$i]["temp_" . str_replace("-", "", $sensor)])/2);
// Draw line
imageline($im,
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor] - $T_min) / $T_range),
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($temp - $T_min) / $T_range),
$linecolor[$sensor]);
// Update variables
$t_begin[$sensor] = $t_end;
$stored_value[$sensor] = $temp;
}
}
}
}
}
}
}
} while ((is_array($log_files)) && (++$log_count < sizeof($log_files)));
//
// Catch & destroy the final image
//
ob_start();
imagepng($im);
download_document_data(ob_get_contents(), "write_file", "plot_temp");
ob_end_clean();
imagedestroy($im);
}
?>