I have a mysql database containing multiple columns of power values captured over time, with time captured in the first column. I would like to plot the power values and display the time of day on the x-axis of a Highcharts chart. I am currently able to display the multiple Power values on the y-axis but I am unable to get the time of day to display on the chart. Here is the PHP code that partially works:
<?php
// Connect to database
$con = mysqli_connect("localhost","userid","passwd","power_readings");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
// Set the variable $rows to the columns Energy_Date and Total_watts
$query = mysqli_query($con,"SELECT Energy_Date,Total_watts FROM combined_readings");
$rows = array();
$rows['name'] = 'Total_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows['data'][] = $tmp['Total_watts'];
}
// Set the variable $rows1 to the columns Energy_Date and Power_watts
$query = mysqli_query($con,"SELECT Energy_Date,Power_watts FROM combined_readings");
$rows1 = array();
$rows1['name'] = 'Neurio_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows1['data'][] = $tmp['Power_watts'];
}
// Set the variable $rows2 to the columns Energy_Date and Solar_watts
$query = mysqli_query($con,"SELECT Energy_Date,Solar_watts FROM combined_readings");
$rows2 = array();
$rows2['name'] = 'Solar_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows2['data'][] = $tmp['Solar_watts'];
}
$result = array();
array_push($result,$rows);
array_push($result,$rows1);
array_push($result,$rows2);
print json_encode($result, JSON_NUMERIC_CHECK);
mysqli_close($con);
?>
Can someone tell me how to change the code to pass the values from the time of day column properly?
Here is what the chart currently looks like:
When I made changes to the PHP to add the 'Energy_Date' field to the array passed to Highcharts (shown below) it results in a blank chart.
The array consists of fields that look like this (a time stamp followed by a power reading, separated by period:
"2018-02-21 16:56:00.052","2018-02-21 16:59:00.052","2018-02-21 17:02:00.039","2018-02-21 17:05:00.039","2018-02-21 17:08:00.039"
<?php
// Connect to database
$con = mysqli_connect("localhost","userid","passwd","power_readings");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
// Set the variable $rows to the columns Energy_Date and Total_watts
$query = mysqli_query($con,"SELECT Energy_Date,Total_watts FROM combined_readings");
$rows = array();
$rows['name'] = 'Total_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows['data'][] = $tmp['Energy_Date'].$tmp['Total_watts'];
}
// Set the variable $rows1 to the columns Energy_Date and Power_watts
$query = mysqli_query($con,"SELECT Energy_Date,Power_watts FROM combined_readings");
$rows1 = array();
$rows1['name'] = 'Neurio_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows1['data'][] = $tmp['Energy_Date'].$tmp['Power_watts'];
}
// Set the variable $rows2 to the columns Energy_Date and Solar_watts
$query = mysqli_query($con,"SELECT Energy_Date,Solar_watts FROM combined_readings");
$rows2 = array();
$rows2['name'] = 'Solar_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows2['data'][] = $tmp['Energy_Date'].$tmp['Solar_watts'];
}
$result = array();
array_push($result,$rows);
array_push($result,$rows1);
array_push($result,$rows2);
print json_encode($result, JSON_NUMERIC_CHECK);
mysqli_close($con);
?>
The html receiving this array looks like this:
<!DOCTYPE html>
<html lang="en">
<title>Combined Values Graph</title>
<head>
<meta http-equiv="refresh" content="180">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
var x_values = [];
var chart;
$(document).ready(function() {
Highcharts.setOptions({
colors: ['#4083e9', '#99ccff', '#00ffff', '#e6e6e6', '#DDDF00', '#64E572', '#FF9655', '#FFF263', '#6AF9C4']
});
$.getJSON("values.php", function(json) {
chart = new Highcharts.Chart({
chart: {
renderTo: 'mygraph',
type : 'spline',
borderWidth: 1,
zoomType: 'x',
panning: true,
panKey: 'shift',
plotShadow: false,
marginTop: 100,
height: 500,
plotBackgroundImage: 'gradient.jpg'
},
plotOptions: {
series: {
fillOpacity: 1
}
},
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
title: {
text: 'Combined Power Readings'
},
subtitle: {
text: 'Total = Neurio + Solar Readings in Watts'
},
xAxis : {
title : {
text : 'Time of Day'
}
},
yAxis: {
title: {
text: 'Power (watts)'
},
plotLines: [{
value: 0,
width: 2,
color: '#ff0000',
zIndex:4,
dashStyle: 'ShortDot'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.x +': '+ this.y;
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 120,
borderWidth: 1
},
plotOptions : {
spline : {
marker : {
radius : 0,
lineColor : '#666666',
lineWidth : 0
}
}
},
series: json
});
});
});
});
</script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
</head>
<body>
<div class="container" style="margin-top:20px">
<div class="col-md-10">
<div class="panel panel-primary">
<div class="panel-body">
<div id ="mygraph"></div>
</div>
</div>
</div>
</div>
</body>
</html>
I have added the console statement to the bottom of the js like so:
series: json
});
console.log(json);
});
Here's what is shown in the browser console for PHP version 1 (The version that displays the graphs).
Browser console 1
Here's what is shown in the browser console for PHP version 2 (The version that gives a blank chart).
Browser console 2
Thanks for your helpful suggestions. I have changed the while loops to look like this:
while($tmp = mysqli_fetch_array($query)) {
$rows['data'][] = $tmp['Energy_UTC'];
$rows['data'][] = $tmp['Total_watts'];
}
The output of the PHP now looks like this:
[{"name":"Total_watts","data":[1519315164,93,1519315344,354]},{"name":"Neurio_watts","data":[1519315164,76,1519315344,309]},{"name":"Solar_watts","data":[1519315164,17,1519315344,45]}]
The data being passed to Highcharts (from the console) now looks like this:
Browser console 3
The chart is still wrong: the x-axis is not showing the timestamps and the chart is incorrect. Can anyone suggest how to change the PHP or html to correct this?
OK, I have updated the while loops to look like this:
$query = mysqli_query($con,"SELECT Energy_UTC,Total_watts FROM combined_readings");
$rows = array();
$rows['name'] = 'Total_watts';
while($tmp = mysqli_fetch_array($query)) {
$rows['data'][] = [$tmp['Energy_UTC'],$tmp['Total_watts']];
}
The PHP output now looks like this:
[{"name":"Total_watts","data":[[1519387869,423],[1519388049,423],[1519388229,332],[1519388410,514],[1519388590,514]...
and the chart is now displaying UTC timestamps for each power value.
You are writing a large block of code with many duplicated components. I've taken the time to DRY your method. It is best practice to minimize calls to the database, so I've managed to combine your queries into one simple select.
Theoretically, you will only need to modify $colnames_labels to modify your HighChart. I have written inline comments to help you to understand what my snippet does. I have written some basic error checks to help you to debug if anything fails.
Code: (untested)
$colnames_labels=[
'Total_watts'=>'Total_watts',
'Power_watts'=>'Neurio_watts',
'Solar_watts'=>'Solar_watts'
];
$select_clause_ext=''; // declare as empty string to allow concatenation
foreach($colnames_labels as $colname=>$label){
$data[]=['name'=>$label]; // pre-populate final array with name values
// generates: [0=>['name'=>'Total_watts'],1=>['name'=>'Neurio_watts'],2=>['Solar_watts']]
$select_clause_ext.=",$colname";
// generates: ",Total_watts,Power_watts,Solar_watts"
}
$subarray_indexes=array_flip(array_keys($colnames_label)); // this will route resultset data to the correct subarray
// generates: ['Total_watts'=>0,'Power_watts'=>1,'Solar_watts'=>2]
if(!$result=mysqli_query($con,"SELECT UNIX_TIMESTAMP(Energy_Date) AS Stamp{$select_clause_ext} FROM combined_readings ORDER BY Energy_Date")){
$data=[['name'=>'Syntax Error (query error)','data'=>[0,0]]; // overwrite data with error message & maintain expected format
}elseif(!mysqli_num_rows($result)){
$data=[['name'=>'Logic Error (no rows)','data'=>[0,0]];
}else{
while($row=mysqli_fetch_assoc($result)){
foreach($subarray_indexes as $i=>$col){
$data[$i]['data'][]=[$row['Stamp'],$row[$col]]; // store [stamp,watts] data in appropriate subarrays
}
}
}
echo json_encode($data,JSON_NUMERIC_CHECK); // Convert to json (while encoding numeric strings as numbers) and print to screen
I have been at this some time trying to get highcharts to chart some data returned by php. I have done many searches and nothing works. I can write the php to deliver the data however it needs to be but how do you get it to dynamically chart it?????
I can deliver it as:
[["1372875867","44.8782806"],["1372875885","46.2020226"]]
or
[[1372876686,44.0655823],[1372876693,43.3360596], etc ]
but how do I get the data from the php output into the dyname example they display?????
!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Highstock Example</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
Highcharts.setOptions({
global : {
useUTC : false
}
});
// Create the chart
window.chart = new Highcharts.StockChart({
chart : {
renderTo : 'container',
events : {
load : function() {
// set up the updating of the chart eachsecond
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(),
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0
},
title : {
text : 'Live random data'
},
exporting: {
enabled: false
},
series : [{
name : 'Random data',
data : (function() {
// generate an array of random data
var data = [], time = (new Date()).getTime(), i;
for( i = -999; i <= 0; i++) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
})()
}]
});
});
</script>
</head>
<body>
<script src="../../js/highstock.js"></script>
<script src="../../js/modules/exporting.js"></script>
<div id="container" style="height: 500px; min-width: 500px"></div>
</body>
</html>
my current php is:
<?php
// include("$_SERVER[DOCUMENT_ROOT]/config/config.php");
include("adodb5/adodb.inc.php");
$connection = new COM("ADODB.Connection") or die("Cannot start ADO");
$result_set = $connection->Execute("
SELECT tag, TIME, value
FROM picomp
WHERE TIME >= '*-3m' AND tag = 'xxx:xx_xxx.xxx'
");
$result_count = 0;
// $labels = array();
while (!$result_set->EOF) {
$pidate = date("U", strtotime($result_set->fields[1]) );
if ($result_count <> 0){
print ",";
}else{
print "[";
}
print "[".$pidate.",".$result_set->fields[2]."]";
// array_push("{$result_set->fields[2]}");
$result_count = $result_count +1;
$result_set->MoveNext();
// echo "testing";
}
print "];";
You can use HighchartsPHP which is a wrapper for Highcharts, which basically allows you to write all that JS code in PHP. It's very useful and pretty simple to use.
HighchartsPHP on GitHub
Your timestamp should be multiplied by 1000, and both values should be numbers.
Please familair with soultion, how to prepare JSON, because you only print "as JSON", but it is not.
Take look at http://php.net/manual/en/function.json-encode.php where some examples are introduced.
Hey guys I am having trouble loading my data into the highstock charts.
My json.php calls on a sample MySQL database and looks something like this:
$result = mysql_query("SELECT UNIX_TIMESTAMP(date)*1000 AS timestamp,value from sample") or die('Could not query');
if(mysql_num_rows($result)){
echo 'Test';
$first = true;
$row=mysql_fetch_assoc($result);
while($row=mysql_fetch_row($result)){
if($first) {
$first = false;
} else {
echo ',';
}
$json_str = json_encode($row, JSON_NUMERIC_CHECK);
echo $json_str;
}
if(array_key_exists('callback', $_GET)){
$callback = $_GET['callback'];
echo $callback. '('.$json_str.');';
}
} else {
echo '[]';
}
mysql_close($db);
My index.htm which calls the Json.php is from the sample highstock template I just merely changed the getJson to match with my reference. Here is the code. Any help would be much appreciated, thanks.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Highstock Example</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$.getJSON('json.php', function(data) {
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1
},
title : {
text : 'Test'
},
series : [{
name : 'Test',
data : data,
marker : {
enabled : true,
radius : 3
},
shadow : true,
tooltip : {
valueDecimals : 2
}
}]
});
});
});
</script>
</head>
<body>
<script src="js/highstock.js"></script>
<script src="js/modules/exporting.js"></script>
<div id="container" style="height: 500px; min-width: 500px"></div>
</body>
</html>
Also, my json is parsed in this manner:
Test[1370899026000,10],[1370899026000,4],[1368177426000,11],[1370899026000,12],[1370899026000,13],[1370899026000,11],[1370899026000,13],[1370899026000,11],[1370899026000,13],[1370899026000,9],[1370899026000,14],[1370899026000,12],[1370899026000,10],[1370899026000,15],[1370899026000,12],[1378826226000,7],[1370899026000,9],[1370899026000,11],[1370899026000,7],[1370899026000,3],[1370899026000,6],[1370899026000,0],[1370899026000,11],[1370899026000,5],[1370899026000,9],[1370899026000,7],[1370899026000,8],[1370899026000,8],[1370899026000,9],[1370899026000,13],[1370899026000,11],[1370899026000,10],[1370899026000,13],[1370899026000,12],[1370899026000,12],[1370899026000,11],[1370899026000,13],[1370899026000,10],[1370899026000,8],[1370899026000,15],[1370899026000,13],[1370899026000,12],[1370899026000,14],[1370899026000,9],[1370899026000,9],[1370899026000,12],[1370899026000,13],[1370899026000,4],[1370899026000,4],[1370899026000,4],[1370899026000,13],[1370899026000,5],[1370899026000,10],[1370899026000,4],[1370899026000,10],[1370899026000,22],[1370899026000,9],[1370899026000,5],[1370899026000,9],[1370899026000,10],[1370899026000,5],[1370899026000,7],[1370899026000,10],[1370899026000,5],[1370899026000,7],[1370899026000,9],[1370899026000,9],[1370899026000,10],[1370899026000,6],[1370899026000,6],[1370899026000,6],[1370899026000,12],[1370899026000,7],[1370899026000,12],[1370899026000,8],[1370899026000,13],[1370899026000,12],[1370899026000,9],[1370899026000,7],[1370899026000,7],[1370899026000,9],[1370899026000,12],[1370899026000,13],[1370899026000,9],[1370899026000,10],[1370899026000,4],[1370899026000,11],[1370899026000,12],[1370899026000,13],[1370899026000,11],[1370899026000,13],[1370899026000,11],[1370899026000,13],[1370899026000,9],[1370899026000,14],[1370899026000,12],[1370899026000,10],[1370899026000,15],[1370899026000,12],[1370899026000,7],[1370899026000,9],[1370899026000,11],[1370899026000,7],[1370899026000,3],[1370899026000,6],[1370899026000,0],[1370899026000,11],[1370899026000,5],[1370899026000,9],[1370899026000,7],[1370899026000,8],[1370899026000,8],[1370899026000,9],[1370899026000,13],[1370899026000,11],[1370899026000,10],[1370899026000,13],[1370899026000,12],[1370899026000,12],[1370899026000,11],[1370899026000,13],[1370899026000,10],[1370899026000,8],[1370899026000,15],[1370899026000,13],[1370899026000,12],[1370899026000,14],[1370899026000,9],[1370899026000,9],[1370899026000,12],[1370899026000,13],[1370899026000,4],[1370899026000,4],[1370899026000,4],[1370899026000,13],[1370899026000,5],[1370899026000,10],[1370899026000,4],[1370899026000,10],[1370899026000,22],[1370899026000,9],[1370899026000,5],[1370899026000,9],[1370899026000,10],[1370899026000,5],[1370899026000,7]
Try closing with
[]
Highstock fiddle: http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/areaspline/
Data of that fiddle: http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-c.json&callback=?
Please take look at http://docs.highcharts.com/#preprocessing-data-from-a-database and take look at very simple example with json_encode:
tmp = array();
$tmp[] = array('A',5);
$tmp[] = array('B',6);
$tmp[] = array('C',1);
$tmp[] = array('D',2);
$rows = array();
for($i=0; $i<count($tmp); $i++)
{
$row['name'] = $tmp[$i][0];
$row['data'] = array($tmp[$i][1]);
array_push($rows,$row);
}
print json_encode($rows);
Highcharts:
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
type: 'column'
},
series: [{
name: 'Browser share',
data: []
}]
}
$.getJSON("datavotecolum.php", function(json) {
console.log(json);
options.series = json;
chart = new Highcharts.Chart(options,function(chart){
console.log(chart.series);
});
});
});
I am passing Highstock/Highcharts three separate series of data via PHP and for some reason only one series is displayed when the chart is loaded. Here is an example of what my HTML output looks like now: http://bit.ly/15D3Dhi and here is what my full PHP code looks like:
date_default_timezone_set('America/Los_Angeles');
$stocks = array('MSFT' => 'http://ichart.finance.yahoo.com/table.csv?s=MSFT', 'AAPL' => 'http://ichart.finance.yahoo.com/table.csv?s=AAPL', 'FB' => 'http://ichart.finance.yahoo.com/table.csv?s=FB', 'ZNGA' => 'http://ichart.finance.yahoo.com/table.csv?s=ZNGA');
$stocks_data = array();
foreach ($stocks as $key=>$stock) {
$fh = fopen($stock, 'r');
$header = fgetcsv($fh);
$varname = $key . '_data';
$$varname = array();
while ($line = fgetcsv($fh)) {
${$varname}[count($$varname)] = array_combine($header, $line);
}
fclose($fh);
}
foreach($MSFT_data as $val){
$MSFT[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$MSFT = json_encode($MSFT);
foreach($AAPL_data as $val){
$AAPL[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$AAPL = json_encode($AAPL);
foreach($FB_data as $val){
$FB[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$FB = json_encode($FB);
?>
<html>
<head>
<title>
Highcharts + PHP + Stock Data
</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container'
},
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function() {
return (this.value > 0 ? '+' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: [{
name: 'MSFT',
data: <?php echo $MSFT; ?>
}, {
name: 'AAPL',
data: <?php echo $AAPL; ?>
}, {
name: 'FB',
data: <?php echo $FB; ?>
}]
});
});
</script>
</head>
<body>
<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container" style="height: 500px; min-width: 600px"></div>
</body>
</html>
Can anyone look at my code and see why only one series is showing up? If you look at the source of my HTML output, all data appears to have been passed in the same way, so it's not clear to me why only one series is displayed.
Thanks and let me know if you have any questions or need more information.
Looked at it, and the first thing I noticed is the code is quite clean, but there is a JS error:
Highcharts error #15: www.highcharts.com/errors/15
Title: Highcharts expects data to be sorted
Then I noticed FB is the only one that shows up, but expanding the date range lets you see FB and another series, so the Y axis is to blame.
Out of whim I decided to fix the JS error first, and somehow the Y-axis solved itself. So looks like the JS error is the culprit.
EDITED: Using the much faster array_reverse instead of array_unshift per 585connor's suggestion:
foreach($MSFT_data as $val){
$MSFT[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$MSFT = json_encode(array_reverse($MSFT));
foreach($AAPL_data as $val){
$AAPL[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$AAPL = json_encode(array_reverse($AAPL));
foreach($FB_data as $val){
$FB[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$FB = json_encode(array_reverse($FB));
foreach($ZNGA_data as $val){
$ZNGA[] = array((strtotime($val['Date']) * 1000), ((float)$val['Close']));
}
$ZNGA = json_encode(array_reverse($ZNGA));