Display Plant Sensor Data in webpage

Looking for a way to remotely monitor and analyze your plant's health?

This PHP code allows you to easily display the sensor data from your plants.

The data is then easily accessible and ready for analysis.

Say hello to efficient plant monitoring with this simple and effective solution.

Try it out today!

In the article Send Plant Sensor Data to Remote Database using ESP8266 I have shown how to send data we collect with different sensors to a database and how to store it.

To obtain useful information we need to display the data in a way that can be understood with ease.

1. Create a php file called database_connection.php and add the following code:

<?php
	require_once 'dbconfig.php';
	$connect = new PDO($dsn, $username, $password);
?>

2. Create a php file and name it fetch.php, open for edit and add below content.

This file will be called by sensors.html (we will make it in next step) every time we want to display data by pressing Show Charts button.

<?php
	include('database_connection.php');
	//"2020-10-14 00:28:38" used as example
	//Replace '2020-10-14 00:28:38' with NOW() in the query's below
	$d = "'2020-10-14 00:28:38'";
	$myWhere = "";
	if ( isset( $_POST['intervalselection'] ) ) {
		$timeInterval = $_POST['intervalselection'];
		switch ($timeInterval) {
			case "1":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 6 HOUR)";
				break;
			case "2":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 DAY)";
				break;
			case "3":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 WEEK)";
				break;
			case "4":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 MONTH)";
				break;
			case "5":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 QUARTER)";
				break;
			case "6":
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 YEAR)";
				break;
			default:
				$myWhere = " WHERE TimeStamp >= DATE_SUB(".$d.", INTERVAL 1 HOUR)";
		}
	}
	
 	if ( isset( $_POST['roomselection'] ) ) {
		$selectedRoom = $_POST['roomselection'];
		$myWhere .= " AND Room=".$selectedRoom;
	}
	
	$query = "SELECT Hub, TimeStamp, BatteryLevel, Pressure, Temperature, AirHumidity, SoilHumidity, Red, Green, Blue, Clear, UV FROM sensorsvalues".$myWhere;
	$statement = $connect->prepare($query);
	$statement->execute();
	$result = $statement->fetchAll();
	foreach($result as $row) {
		$output[] = array(
		'HB'   => $row["Hub"],
		'TS'   => $row["TimeStamp"],
		'BL'  => $row["BatteryLevel"],
		'P'  => $row["Pressure"],
		'T'  => $row["Temperature"],
		'AH'  => $row["AirHumidity"],
		'SH'  => $row["SoilHumidity"],
		'R'  => $row["Red"],
		'G'  => $row["Green"],
		'B'  => $row["Blue"],
		'C'  => $row["Clear"],
		'UV'  => $row["UV"]
		);
	}
	echo json_encode($output);
?>

3. Create a html file and name it sensors.html, open for edit and add below content.

<!DOCTYPE html>
<html>
	<head>
		<link rel="stylesheet" type="text/css" href="/floorplansel.css">
		<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
		<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
		<script type="text/javascript">
			// Load Charts and the corechart package.
			google.charts.load('current', {'packages':['corechart']});
			// Draw the line chart for battery level when Charts is loaded.
			google.setOnLoadCallback();
			function getData(){
				// Get the selected score (assuming one was selected)
				var interval = document.querySelector('input[name="intervalselection"]:checked').value;
				var room = document.querySelector('input[name="roomselection"]:checked').value;
				var dataTosend = 'intervalselection='+interval+'&roomselection='+room;
				$.ajax({
					url: "fetch.php",
					method: "POST",
					data: { intervalselection: interval, roomselection: room },
					async: true,
					success: function (data) {
						var phpResult = $.parseJSON(data);
						drawBattery(phpResult);
						drawPressure(phpResult);
						drawTemperature(phpResult);
						drawHumidity(phpResult);
						drawLight(phpResult);
						drawUV(phpResult);
					},
					error: function(){
						alert('Error in getting data!');
					}
				});
			}
					
			// Callback that draws the line chart for battery level.
			function drawBattery(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'Battery Level');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iLevel = parseFloat($.trim(bData[c].BL));
					batteryData.addRows([[iDate , iLevel]]);
				}
				// Set options for battery chart.
				var options = {title: 'Battery level [%]' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, vAxis: {gridlines : {color: 'red', count : 10}}, trendlines: { 0: {color: 'purple', type: 'polynomial', degree: 5, visibleInLegend: false}}};
				// Instantiate and draw the chart for battery.
				var chart = new google.visualization.LineChart(document.getElementById("battery"));
				chart.draw(batteryData, options);		
			}
			// Callback that draws the line chart for pressure level.
			function drawPressure(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'Pressure Level');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iLevel = parseFloat($.trim(bData[c].P));
					batteryData.addRows([[iDate, iLevel]]);
				}
				// Set options for pressure chart.
				var options = {title: 'Pressure level [hPa]' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, vAxis: {gridlines : {color: 'red', count : 10}}, trendlines: { 0: {color: 'purple', type: 'polynomial', degree: 5, visibleInLegend: false}}};
				// Instantiate and draw the chart for pressure.
				var chart = new google.visualization.LineChart(document.getElementById("pressure"));
				chart.draw(batteryData, options);		
			}
			// Callback that draws the line chart for temperature level.
			function drawTemperature(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'Temperature Level');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iLevel = parseFloat($.trim(bData[c].T));
					batteryData.addRows([[iDate, iLevel]]);
				}
				// Set options for temperature chart.
				var options = {title: 'Temperature [°C]' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, vAxis: {gridlines : {color: 'red', count : 10}}, trendlines: { 0: {color: 'purple', type: 'polynomial', degree: 5, visibleInLegend: false}}};
				// Instantiate and draw the chart for temperature.
				var chart = new google.visualization.LineChart(document.getElementById("temperature"));
				chart.draw(batteryData, options);		
			}
			// Callback that draws the line chart for humidity level.
			function drawHumidity(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'Air Humidity');
				batteryData.addColumn('number', 'Soil Humidity');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iAir = parseFloat($.trim(bData[c].AH));
					var iSoil = parseFloat($.trim(bData[c].SH));
					batteryData.addRows([[iDate, iAir, iSoil]]);
				}
				// Set options for humidity chart.
				var options = {title: 'Air and Soil humidity [%]' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, colors: ['blue', 'green'], vAxis: {gridlines : {color: 'red', count : 10}}};
				// Instantiate and draw the chart for humidity.
				var chart = new google.visualization.LineChart(document.getElementById("humidity"));
				chart.draw(batteryData, options);		
			}
			// Callback that draws the line chart for light level.
			function drawLight(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'Red');
				batteryData.addColumn('number', 'Green');
				batteryData.addColumn('number', 'Blue');
				batteryData.addColumn('number', 'Clear');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iR = parseFloat($.trim(bData[c].R));
					var iG = parseFloat($.trim(bData[c].G));
					var iB = parseFloat($.trim(bData[c].B));
					var iC = parseFloat($.trim(bData[c].C));
					batteryData.addRows([[iDate, iR, iG, iB, iC]]);
				}
				// Set options for light chart.
				var options = {title: 'Light levels' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, colors: ['red', 'green', 'blue', 'yellow'], vAxis: {gridlines : {color: 'red', count : 10}}};
				// Instantiate and draw the chart for light.
				var chart = new google.visualization.LineChart(document.getElementById("light"));
				chart.draw(batteryData, options);		
			}
			// Callback that draws the line chart for UV level.
			function drawUV(chart_data) {
				var bData = chart_data;
				var batteryData = new google.visualization.DataTable();
				batteryData.addColumn('datetime', 'myDate');
				batteryData.addColumn('number', 'UV Level');
				for(var c = 0; c < bData.length; c++) {
					var iDate = new Date(bData[c].TS);
					var iLevel = parseFloat($.trim(bData[c].UV));
					batteryData.addRows([[iDate, iLevel]]);
				}
				// Set options for UV chart.
				var options = {title: 'UV Level' , animation: {duration: 1000, easing: 'out', startup: true}, legend: { position: 'bottom' }, vAxis: {gridlines : {color: 'red', count : 10}}, trendlines: { 0: {color: 'purple', type: 'polynomial', degree: 5, visibleInLegend: false}}};
				// Instantiate and draw the chart for UV.
				var chart = new google.visualization.LineChart(document.getElementById("uv"));
				chart.draw(batteryData, options);		
			}
		</script>
		<title>GVI Sensor Page Example</title>
	</head>
	<body onload="getData();">
		<h1 style="text-align:center">Welcome to My IoT sensors Page!</h1>
		<div class="center">
			<img src="/FloorPlan.png" alt="Floor plan" style="width:974px;height:873px;">
			<a id="area_BedRoom" alt="BedRoom" title="BedRoom" class="area" href="#"></a>
			<a id="area_HallWay" alt="HallWay" title="HallWay" class="area" href="#"></a>
			<a id="area_BathRoom" alt="BathRoom" title="BathRoom" class="area" href="#"></a>
			<a id="area_LivingRoom" alt="LivingRoom" title="LivingRoom" class="area" href="#"></a>
			<a id="area_Kitchen" alt="Kitchen" title="Kitchen" class="area" href="#"></a>
			<a id="area_WashRoom" alt="WashRoom" title="WashRoom" class="area" href="#"></a>
			<a id="area_StorageRoom" alt="StorageRoom" title="StorageRoom" class="area" href="#"></a>			
		</div>
		<br>
		</br>
		<table align="center">
			<thead>
				<tr>
					<th colspan="7">Select time interval and room</th>
				</tr>
				<tr>
					<td colspan="7">&nbsp;</td>
				</tr>
			</thead>
			<tbody>
				<form>
					<tr>
						<td>
							<input type="radio" id="hour1" name="intervalselection" value="0" checked>
							<label for="1 Hour">1 Hour</label>
						</td>
						<td>
							<input type="radio" id="hour6" name="intervalselection" value="1">
							<label for="6 Hours">6 Hours</label>
						</td>
						<td>
							<input type="radio" id="day" name="intervalselection" value="2">
							<label for="Day">Day</label>
						</td>
						<td>
							<input type="radio" id="week" name="intervalselection" value="3">
							<label for="Week">Week</label>
						</td>
						<td>
							<input type="radio" id="month" name="intervalselection" value="4">
							<label for="Month">Month</label>
						</td>
						<td>
							<input type="radio" id="quarter" name="intervalselection" value="5">
							<label for="Quarter">Quarter</label>
						</td>
						<td>
							<input type="radio" id="year" name="intervalselection" value="6">
							<label for="Year">Year</label>
						</td>					
					</tr>
					<tr>
						<td>
							<input type="radio" id="BedRoom" name="roomselection" value="0">
							<label for="BedRoom">Bedroom</label>
						</td>
						<td>
							<input type="radio" id="HallWay" name="roomselection" value="1">
							<label for="HallWay">Hallway</label>
						</td>
						<td>
							<input type="radio" id="BathRoom" name="roomselection" value="2">
							<label for="BathRoom">Bathroom</label>
						</td>
						<td>
							<input type="radio" id="LivingRoom" name="roomselection" value="3" checked>
							<label for="LivingRoom">Living room</label>
						</td>	
						<td>
							<input type="radio" id="Kitchen" name="roomselection" value="4">
							<label for="Kitchen">Kitchen</label>
						</td>
						<td>
							<input type="radio" id="WashRoom" name="roomselection" value="5">
							<label for="WashRoom">Wash room</label>
						</td>
						<td>
							<input type="radio" id="StorageRoom" name="roomselection" value="6">
							<label for="StorageRoom">Storage room</label>
						</td>					
					</tr>
					<tr>
						<td colspan="7">&nbsp;</td>
					</tr>
					<tr>
						<td colspan="7" align="center">
							<input type="button" onclick="getData()" value="Show charts">
						<td>
					<tr>
				</form>
			</tbody>
		</table>
		<!--Table and divs that hold the pie charts-->
		<table width="100%" align="center">
			<colgroup>
				<col span="1" style="width: 50%;">
				<col span="1" style="width: 50%;">
			</colgroup>
			<thead>
				<tr>
					<th colspan="2">Sensors data</th>
				</tr>
				<tr>
					<td colspan="2">&nbsp;</td>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>
						<div id = "battery"></div>
					</td>
					<td>
						<div id = "pressure"></div>
					</td>
				</tr>
				<tr>
					<td>
						<div id = "temperature"></div>
					</td>
					<td>
						<div id = "humidity"></div>
					</td>
				</tr>
				<tr>
					<td>
						<div id = "light"></div>
					</td>
					<td>
						<div id = "uv"></div>
					</td>
				</tr>
			</tbody>
		</table>
	</body>
</html>

The css file used in the project is floorplansel.css

.center {
  position: relative;
  margin: auto;
  width: 974px;
  border: 3px solid green;
  padding: 0px;
}

.area {
    background:#fff;
	border: 2px solid blue;
    display:block;
    opacity:0;
    position:absolute;
}

	#area_BedRoom {
		top: 120px; left: 22px; width: 369px; height: 312px;
	}
	#area_HallWay {
		top: 119px; left: 400px; width: 161px; height: 313px;
	}	
	#area_BathRoom {
		top: 119px; left: 569px; width: 193px; height: 313px;
	}
	#area_LivingRoom {
		top: 442px; left: 23px; width: 628px; height: 409px;
	}
	#area_Kitchen {
		top: 441px; left: 661px; width: 290px; height: 409px;
	}
	#area_WashRoom {
		top: 303px; left: 772px; width: 179px; height: 129px;
	}	
	#area_StorageRoom {
		top: 120px; left: 772px; width: 180px; height: 173px;
	}
	#area_BedRoom:hover, #area_HallWay:hover, #area_BathRoom:hover, #area_LivingRoom:hover, #area_Kitchen:hover, #area_WashRoom:hover , #area_StorageRoom:hover{
		opacity:0.5;
	}
	
.container {
    width:98%; 
    margin:1%;
  }

The working example can be tested on the live demo https://sensors.grozeaion.com/sensors.html

Be aware that the bigger the time interval you select the bigger the loading time of the page will be.

Comments powered by CComment

Who’s online

We have 134 guests and no members online