Location: PHPKode > projects > WaveWatcher > wavewatcher3/html/graph/uptime.php
<?
// Input Variables
$node_id = empty($node_id) ? 0 : $node_id;						// ID on the node we should draw data for

$nSizeX = empty($xsize) ? 450 : $xsize;							// Total width of the picture
$nSizeY = empty($ysize) ? 80 : $ysize;							// Total height of the picture
$font = empty($font) ? 2 : $font;								// Font to all the text in the diagram
$dateStartTime = empty($starttime) ? null : $starttime;			// The start of the time interval to draw
$dateStopTime = empty($stoptime) ? null : $stoptime;			// The stop of the time interval to draw
$nDrawMode = empty($drawmode) ? 2 : $drawmode;					// How the data should be drawn
$nHorPos = empty($xpos) ? 24 : $xpos;							// Number of steps on the x-scale 
$nDownTimeLevel = isset($downtime) ? $downtime : 5;				// Help to decide the time that must go before a client is estimated as down
$nMode = empty($mode) ? 1 : $mode;								// Text that explain what time (or %) it is between two delimitationlines on the x-scale

// Internal Variables
$strError = "";		// Error message
$bError = FALSE;	// Tells if an error has occured or not

// Check if valid values. If not, set to default or set an error
$nMode = $nMode != 1 &&  $nMode != 2 && $nMode != 3 ? 1 : $nMode;
$nSizeX = $nSizeX < 1 ? 450 : $nSizeX;							
$nSizeY = $nSizeY < 1 ? 80 : $nSizeY;							
$font = $font < 1 || $font > 5 ? 2 : $font;	
$nDrawMode = $nDrawMode < 1 || $nDrawMode > 2 ? 2 : $nDrawMode;					
$nDownTimeLevel = $nDownTimeLevel < 0 ? 5 : $nDownTimeLevel;			
$nHorPos = $nHorPos < 1 ? 24 : $nHorPos;							

// is it a valid ID or not?
if ($node_id <= 0)
{
	$strError .= "Not a valid node_id. ";
	$bError = TRUE;
}	

if(!empty($dateStopTime) && !empty($dateStartTime))
{
	// If $dateStartTime and $dateStopTime have been sent as parameters to the program
	// we calculate a valid $nStartTime && $nStopTime and finally we find a suitable $nHorPos also!

	$nStopTime = mktime(substr($dateStopTime,6,2), 0, 0, substr($dateStopTime,2,2), substr($dateStopTime,4,2), substr($dateStopTime,0,2));
	$nStartTime = mktime(substr($dateStartTime,6,2), 0, 0, substr($dateStartTime,2,2), substr($dateStartTime,4,2), substr($dateStartTime,0,2));

	$nHorPos = ($nStopTime - $nStartTime) / 3600;								// Presentation type: Hours
	$nHorPos = $nMode == 2 ? ($nStopTime - $nStartTime) / 3600 / 24 : $nHorPos;	// Presentation type: Days
	$nHorPos = $nMode == 3 ? ($nStopTime - $nStartTime) / 3600 / 24 : $nHorPos;	// Presentation type: Weeks

	if ($nStartTime >= $nStopTime)
	{
		$bError = TRUE;
		$strError .= "Not a valid time interval. ";
	}
}
else
{
	// If not $dateStartTime and $dateStopTime have been sent as parameters to the program
	// we set $nStopTime to the time just now and calculate a valid $nStartTime with help of 
	// $nHorPos that was sent as a parameter.

	$nStopTime = time();
	//$nStopTime = 1015580663; // last value in the test database

	switch($nMode)
	{
		case 1:		$nStartTime = $nStopTime - $nHorPos * 3600; // 3600 = 60 * 60
					break;

		case 2:		$nStartTime = $nStopTime - $nHorPos * 86400; // 86400 = 60 * 60 * 24
					break;

		case 3:		$nStartTime = $nStopTime - $nHorPos * 86400;
					break;

		default:	$nStartTime = $nStopTime - $nHorPos * 3600;
					break;
	}
}

// Internal Variables
$nFontHeight = ImageFontHeight($font);				// Selected fonts height
$nFontWidth = ImageFontWidth($font);				// Selected fonts width
$nLeft = 4;											// the space to the left of drawn data
$nRight = 4;										// the space to the right of drawn data
$nTop = 2 + $nFontHeight + 2;						// the space over the drawn data
$nBottom = 4 + $nFontHeight + 2 + $nFontHeight + 5;	// the space bellow the drawn data
$nHeight = $nSizeY - $nTop - $nBottom;				// Height to use when drawing the data
$nWidth = $nSizeX - $nLeft - $nRight;				// Width to use when drawing the data
$dStepX = ($nWidth / $nHorPos);						// Size of each step on the x-scale

// Define header type
Header("Content-type: image/png");

// Create image
$im = ImageCreate($nSizeX, $nSizeY);

// Define colors
$clrWhite = ImageColorAllocate($im, 255, 255, 255);	// Background color
$clrBlack = ImageColorAllocate($im, 0, 0, 0);
$clrUp = ImageColorAllocate($im, 0, 0, 224);
$clrDown = ImageColorAllocate($im, 224, 0, 0);
$clrTitle = ImageColorAllocate($im, 0, 0, 0); 
$clrRed = ImageColorAllocate($im, 224, 0, 0);

// Draw outer border
ImageRectangle($im, 0, 0, $nSizeX-1, $nSizeY-1, $clrBlack);

ImageString($im, $font, $nSizeX-$nFontWidth*15-6, 2, "uptime", $clrUp);
ImageString($im, $font, $nSizeX-$nFontWidth*9-6, 2, "/", $clrTitle);
ImageString($im, $font, $nSizeX-$nFontWidth*8-6, 2, "downtime", $clrDown);

// Set style to the separator line
$arrSeparator=array($clrRed,$clrRed,$clrWhite,$clrWhite);
ImageSetStyle($im, $arrSeparator);

if (!$bError)
{
	require_once("../../classes/dbconnection.php");

	// Database access
	$dbcn = new DBConnection();
	$dbcn->Connect();
	$query = "SELECT node_name FROM nodes WHERE node_id = '$node_id'"; 
	$resultNodeName = $dbcn->Query($query); // Get the nodes name
	$query = "SELECT utime FROM ping_times_log WHERE node_id = '$node_id' AND utime >= '$nStartTime' AND utime <= '$nStopTime' ORDER BY utime DESC LIMIT 30"; 
	$result = $dbcn->Query($query); // Get data to check the minimum time between pings

	if ($result)
	{
		$nCount = 0;
		$nDataInterval = $nStopTime - $nStartTime;

		while (List($utime) = $dbcn->FetchRow($result))
			$time[$nCount++] = $utime;

		// Check the minimum time between pings
		for ($i = 1; $i < $nCount; $i++)
		{
			if (($time[$i - 1] - $time[$i]) < $nDataInterval)
				$nDataInterval = $time[$i - 1] - $time[$i];
		}

		// Calculate the time that must go before a node is estimated as down
		$nTimeBeforeDown = $nDataInterval * $nDownTimeLevel;

		// Get all the values for the selected time
		$query = "SELECT utime, ping_time FROM ping_times_log WHERE node_id = '$node_id' AND utime >= '$nStartTime' AND utime <= '$nStopTime' ORDER BY utime";
		$result = $dbcn->Query($query);
	}
	$dbcn->Disconnect();

	// Write title
	if ($resultNodeName)
	{
		List($name) = $dbcn->FetchRow($resultNodeName);
		ImageString($im, $font, 4, 2, "$name", $clrTitle);
	}
	else
	{
		ImageString($im, $font, 4, 2, "Unknown node", $clrTitle);
	}

	// Evaluate result
	if ($result)
	{
		$nCount = 0;
		$nLastTimeUp = $nCount; // index for the last time the node was up

		while (List($utime, $ping_time) = $dbcn->FetchRow($result))
		{
			$time[$nCount] = $utime - $nStartTime;
			
			if ($ping_time > 0)
			{
				$ping[$nCount] = 1;
				$holder[$nCount] = 1;
				$nLastUp = $nCount;
			} 
			else
			{
				$holder[$nCount] = 0;
				$bDown = TRUE;

				// Filter out errors
				// Wait for $nTimeBeforeDown seconds before ploting down
				if (($time[$nCount] - $time[$nLastUp]) > $nTimeBeforeDown)
				{
					if ($ping[$nCount - 1] == 0)
						$ping[$nCount] = 0;
					else
					{
						for ($j = $nCount; $j > $nLastUp; $j--)
							$ping[$j] = 0;
					}
				}
				else
				{
					$ping[$nCount] = 1;
				}
			}
			
			$nCount++;
		}

		if ($nCount > 0)
		{
			$nMinutes = strftime("%M", $nStopTime);
			$nHours = strftime("%H", $nStopTime);

			switch($nMode)
			{
				// $dPosTime		Where to draw delimitation line on the x-scale 
				// $strMode			Text that explain what time it is between two delimitationlines on the x-scale
				// $nExtraPos		Is to loop some extra times in the next for-loop when $nMode = 3. Otherwise the text to the left on the x-scale is missing

				// hour
				case 1:		$nMinutesOffset = $dStepX / 60 * $nMinutes;
							$dPosTime = $nLeft + ($nHorPos * $dStepX) - $nMinutesOffset;
							$strMode = "hour";
							$nExtraPos = 0;		
							break;
				
				// day
				case 2:		$nHoursOffset = $dStepX / 24 * $nHours;
							$nMinutesOffset = $dStepX / 1440 * $nMinutes; // (1440 = 24 * 60)
							$dPosTime = $nLeft + ($nHorPos * $dStepX) - $nHoursOffset - $nMinutesOffset;
							$strMode = "day";
							$nExtraPos = 0;
							break;

				// week
				case 3:		$nHoursOffset = $dStepX / 24 * $nHours;
							$nMinutesOffset = $dStepX / 1440 * $nMinutes; // (1440 = 24 * 60)
							$dPosTime = $nLeft + ($nHorPos * $dStepX) - $nHoursOffset - $nMinutesOffset;
							$strMode = "week";
							$nExtraPos = 7;		// Make sure all the text for the x-scale is printed
							break;

				default:	break;
			}

			$bSeperator = FALSE;
			$bDelimitationLine = TRUE;
			$nStop = $nHorPos + $nExtraPos;	

			// Draw horizontal numbers or text
			for($pos = 0; $pos <= $nStop; $pos++)
			{
				switch($nMode)
				{
					// $strTextX		Text or number for x-scale
					// $nTextOffset		Dislocate $strTextX to the right place in relation to $nMode and the delimitationlines

					// Hour
					case 1:		$strTextX = strftime("%H", $nStopTime - (3600 * $pos)); // 3600 = 60 * 60
								$nTextOffset = $nFontWidth;

								// Only print every other hour
								if ((($strTextX % 2) == 0) && (($dPosTime + $nTextOffset) <= ($nLeft + $nWidth)) && (($dPosTime - $nTextOffset) >= $nLeft))
								{
									ImageString($im, $font, $dPosTime - $nTextOffset, $nTop + $nHeight + 4, $strTextX, $clrBlack);
								}

								// Should we draw separator line?
								$bSeperator = $strTextX == "0" ? true : false;
								break;

					// Day
					case 2:		// Check if both name and number of the day fits between delimitationlines
								if ($dStepX < (7 * $nFontWidth)) // Only number
								{
									$strTextX = strftime("%d", $nStopTime - (86400 * $pos)); // 86400 = 24 * 60 * 60
									$nTextOffset = $nFontWidth;
								}
								else // Both name and number
								{
									$strTextX = strftime("%a %d", $nStopTime - (86400 * $pos)); 
									$nTextOffset =  3 * $nFontWidth;
								}
								
								$nTextCenter = $dStepX / 2;

								if ((($dPosTime + $nTextCenter + $nTextOffset) <= ($nLeft + $nWidth)) && (($dPosTime + $nTextCenter - $nTextOffset) >= $nLeft))
								{
									ImageString($im, $font, $dPosTime + $nTextCenter - $nTextOffset, $nTop + $nHeight + 4, $strTextX, $clrBlack);
								}

								// Should we draw separator line?
								$bSeperator = strftime("%w", $nStopTime - 3600 * 24 * $pos) == "1" ? true : false;
								break;

					// Week
					case 3:		$strTextX = strftime("%V", $nStopTime - (86400 * $pos)); // 86400 = 24 * 60 *60
								$nTextCenter = $dStepX * 7 / 2;
								$nTextOffset = $nFontWidth;

								if ($strTextX != strftime("%V", $nStopTime - 86400 * ($pos + 1)))
								{
									if (($dStepX * 7) >= (5 * $nFontWidth))
									{
										$strTextX = "w $strTextX";
										$nTextOffset = 2 * $nFontWidth;
									}

									if ((($dPosTime + $nTextCenter + $nTextOffset) <= ($nLeft + $nWidth)) && (($dPosTime + $nTextCenter - $nTextOffset) >= $nLeft))
									{
										ImageString($im, $font, $dPosTime + $nTextCenter - $nTextOffset, $nTop + $nHeight + 4, $strTextX, $clrBlack);
									}
									
									$bDelimitationLine = true;
								}
								else
								{
									$bDelimitationLine = false;
								}

								// Should we draw separator line?
								$bSeperator = strftime("%d", $nStopTime - 3600 * 24 * $pos) == "01" ? true : false;
								break;

					default:	break;
				}
			
				if ($dPosTime >= $nLeft)
				{
					// draw separator line?
					if ($bSeperator)
						ImageLine($im, $dPosTime, $nTop, $dPosTime, $nTop + $nHeight, IMG_COLOR_STYLED);	
					
					// draw delimitation line?
					if ($bDelimitationLine)
						ImageLine($im, $dPosTime, $nSizeY - $nBottom - 3, $dPosTime, $nSizeY - $nBottom + 3, $clrBlack);		
				}
				
				$dPosTime -= $dStepX;	
			}

			// initiate the variables to use when drawing the data 
			$dPixelPerSec = $nWidth / ($nStopTime - $nStartTime);
			$nLastChange = 0;
			$bOldUp = $ping[0] > 0 ? TRUE : FALSE;
			$nOldTime = $time[0];
			$nOldStatus = $ping[0];
			$nUpTime = 0;
			$nDownTime = 0;

			for ($i = 1; $i < $nCount; $i++)
			{
				$bUp = $ping[$i] > 0;

				// Draw data
				if ($bUp != $bOldUp || $i == ($nCount - 1))
				{
					$nOldX = ceil($time[$nLastChange] * $dPixelPerSec) + $nLeft;
					$nX = ceil($time[$i] * $dPixelPerSec) + $nLeft;

					$nExtraPixel = $nOldX == $nX ? 1 : 0; // maybe extra pixel so the width of the rectangle not is 0

					if ($bOldUp) // Draw up
					{
						if ($nDrawMode == 1)
							ImageFilledRectangle($im, $nOldX, $nTop, $nX - 1 + $nExtraPixel, $nTop + ($nHeight / 2) - 1, $clrUp);
						else
							ImageFilledRectangle($im, $nOldX, $nTop, $nX - 1 + $nExtraPixel, $nTop + $nHeight -1, $clrUp);
					}
					else // Draw down
					{
						if ($nDrawMode == 1)
							ImageFilledRectangle($im, $nOldX, $nTop + ($nHeight / 2), $nX - 1 + $nExtraPixel, $nTop + $nHeight - 1, $clrDown);
						else
							ImageFilledRectangle($im, $nOldX, $nTop, $nX - 1 + $nExtraPixel, $nTop + $nHeight - 1, $clrDown);
					}

					$nLastChange = $i;
					$bOldUp = $bUp;
				}

				// Count uptime and downtime
				if ($nOldStatus != $ping[$i] || $i == ($nCount - 1))
				{
					if ($nOldStatus == 0)
						$nDownTime += $time[$i] - $nOldTime;
					else
						$nUpTime += $time[$i] - $nOldTime;

					$nOldTime = $time[$i];
					$nOldStatus = $ping[$i];
				}
			}

			// Calculate uptime in %
			$nTotalTime = $time[$nCount - 1] - $time[0];
			$dUpTime = round($nUpTime / $nTotalTime * 100, 1);

			// Write uptime
			ImageString($im, $font, ($nSizeX / 2) - (($nFontWidth * 9) / 2), 2, "Up: $dUpTime%" , $clrBlack);
		}
		else
		{
			$bError = TRUE;
			$strError .= "There are no data in the database for the reqested time. ";
		}
	}
	else
	{
		$bError = TRUE;
		$strError .= "Not a valid query to the database. Check node_id. ";
	}
}

// Write error message if an error has occurred
if ($bError)
	ImageString($im, $font, $nLeft + 5, $nTop + ($nHeight / 2) - $nFontHeight, $strError, $clrTitle);

// Write time period
$strPeriodStart = strftime("%y-%m-%d %R", $nStartTime);
$strPeriodStop = strftime("%y-%m-%d %R", $nStopTime);
$str = "$strPeriodStart - $strPeriodStop [$strMode]";
ImageString($im, $font, ($nSizeX / 2) - (($nFontWidth * strlen($str)) / 2), $nSizeY - $nFontHeight - 2, $str , $clrTitle);

// Draw horizontal and vertical line
ImageLine($im, $nLeft, $nTop + $nHeight, $nLeft + $nWidth, $nTop + $nHeight, $clrBlack);
ImageLine($im, $nLeft, $nTop, $nLeft, $nTop + $nHeight, $clrBlack);

// Output Image
ImagePng($im);
ImageDestroy($im);
?>
Return current item: WaveWatcher