Highcharts with JSON data coming from microcontroler - javascript

I would like to modify the following HTML/JS code in order to fulfil the following requirements:
Select only "temp" data in my JSON file
xAxis should be "point" and not datetime
I don't want a refresh every X seconds but only when the page is refreshed.
<script>
var chartT = new Highcharts.Chart({
chart:{ renderTo : 'chart-temperature' },
title: { text: 'BME280 Temperature' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: '#059e8a' }
},
xAxis: { type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Temperature (Celsius)' }
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000 ) ;
and my JSON looks like this:
[
{"point":184,"temp":20.5,"humidity":49.5,"weight1":0,"weight2":0},
{"point":185,"temp":20.6,"humidity":49.7,"weight1":0,"weight2":0},
{"point":186,"temp":20.6,"humidity":49.6,"weight1":0,"weight2":0}
]
right now, the command
xhttp.open("GET", "/temperature", true);
xhttp.send();
will return my whole JSON file in a string
But in the chart I only want to display the "temp" information.

You need to parse your JSON to JS object and use series.setData method. For example:
function getData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const data = JSON.parse(this.responseText);
const processedData = data.map(dataEl => [dataEl.point, dataEl.temp]);
chartT.series[0].setData(processedData);
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}
getData();
Also, please check this thread about new ways of sending requests: Parsing JSON from XmlHttpRequest.responseJSON
Live demo: http://jsfiddle.net/BlackLabel/p9gaxmju/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#setData

Related

Can I make a graph between two xhttp variables?

I tried to make a graph between two variables instead of graphinh time but I couldn't. So I want to know I this is available by the way?
var chartT = new Highcharts.Chart({
chart: { renderTo: "chart-temperature" },
title: { text: "DHT22 Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
series: { color: "#059e8a" },
},
xAxis: { type: "datetime", dateTimeLabelFormats: { second: "%H:%M:%S" } },
yAxis: {
title: { text: "Temperature (Celsius)" },
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false },
});
setInterval(function () {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if (chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000);
var chartH = new Highcharts.Chart({
chart: { renderTo: "chart-humidity" },
title: { text: "DHT22 Humidity" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: { second: "%H:%M:%S" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
setInterval(function () {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if (chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 30000);
I wanted to make a graph between humidity on y axis and temperature on x axis. I tried changing the x variable ,of the humidity chart, to be like the y variable ,of the temperature chart, but the chart of the humidity didn't work.
You have to synchronize the received data from the two API requests. Here's a solution that records partial data (either temperature or humidity) - pending array and identifies corresponding requests by registering the time of the requested - tRequest.
This may be a starting point for your more elaborate solution. Please let me know if this is not exactly what you wanted.
The data is simulated (random points) as I don't have access to your API, but there are real XMLHttpRequests (to highcharts on cdn).
The same in this fiddle
var chartT = new Highcharts.Chart({
chart: { renderTo: "chart-temperature" },
title: { text: "DHT22 Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
series: { color: "#059e8a" },
},
xAxis: { type: "datetime", dateTimeLabelFormats: { second: "%H:%M:%S" } },
yAxis: {
title: { text: "Temperature (Celsius)" },
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false },
});
var chartH = new Highcharts.Chart({
chart: { renderTo: "chart-humidity" },
title: { text: "DHT22 Humidity" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: { second: "%H:%M:%S" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
var chartTH = new Highcharts.Chart({
chart: { renderTo: "chart-temperature-humidity", type: "scatter" },
title: { text: "DHT22 Humidity vs Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
//line: { animation: false, dataLabels: { enabled: true } },
scatter: {marker: {fillColor: '#ce4a05'}}
},
xAxis: {
title: { text: "Temperature (Celsius)" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
function requestTemperature(whenReceived) { // whenReceived is a handler to be called when a data point was received
var tRequest = new Date().getTime();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = Math.floor(Math.random()*100)/4;//parseFloat(this.responseText);
whenReceived(x, y, tRequest);
}
};
xhttp.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js", true);
xhttp.send();
}
function requestHumidity(whenReceived) {
var tRequest = new Date().getTime();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = Math.floor(100+Math.random()*250)/4;//parseFloat(this.responseText);
whenReceived(x, y, tRequest);
}
};
xhttp.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js", true);
xhttp.send();
}
function addToChart(chart, [x, y]){
if (chart.series[0].data.length > 40) {
chart.series[0].addPoint([x, y], true, true, true);
} else {
chart.series[0].addPoint([x, y], true, false, true);
}
}
var pending = []; // pending array will contain values received for only one of the variables
function afterTemperatureReceived(x, y, tRequest){
addToChart(chartT, [x, y]);
var humidityReceived = pending.findIndex(o => Math.abs(o.tRequest - tRequest) < 100);
if(humidityReceived >= 0){ // a humidity value was received with a call time very close to this
var H = pending.splice(humidityReceived, 1)[0].H; // delete from pending and retain H value
addToChart(chartTH, [y, H]); // current y is temp, the first (x) coordinate of chartTH
}
else{ // humidity not yet received
// add temperature to pending, waiting for its humidity to be received
pending.push({T: y, tRequest});
}
}
function afterHumidityReceived(x, y, tRequest){
addToChart(chartH, [x, y]);
var temperatureReceived = pending.findIndex(o => Math.abs(o.tRequest - tRequest) < 100);
if(temperatureReceived >= 0){ // a temperature value was received with a call time very close to this
var T = pending.splice(temperatureReceived, 1)[0].T; // delete from pending and retain T value
addToChart(chartTH, [T, y]); // current y is humidity, the second (y) coordinate of chartTH
}
else{ // temperature not yet received
// add humidity to pending, waiting for its humidity to be received
pending.push({H: y, tRequest});
}
}
function mainTick(){
requestTemperature(afterTemperatureReceived);
requestHumidity(afterHumidityReceived);
}
mainTick();
setInterval(mainTick, 5000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="chart-temperature" style="height:20vh;min-height:350px"></div>
<div id="chart-humidity" style="height:20vh;min-height:350px"></div>
<div id="chart-temperature-humidity" style="height:20vh;min-height:350px"></div>

Highcharts series setData from ajax php procedure

I am using Highcharts on my website. Then an Ajax PHP procedure to load data dynamically from database, by clicking on a legend item. Now I want to set the result into the series data but with no success as I am unable to use 'this' as 'this' is not the legend item anymore. You'll be able to understand it from the code below. I tried something like chart.series.setData[] but it did not work. Thanks for any solutions of how can I proceed.
<script>
Highcharts.chart('myChart', {
series: [<?echo $allnames;?>],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top'
},
plotOptions: {
series: {
events: {
legendItemClick: function() {
var jmeno=this.name;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myData= this.responseText;
//I am unable to use 'this' as it is not the legend item
this.setData([myData]);
}
};
xmlhttp.open("GET","/data.php?q="+jmeno,true);
xmlhttp.send();
}
}
}
},
});
</script>
Resolved.
<script>
Highcharts.chart('graf', {
title: {text: 'Hello darkness my old friend'},
series: [<?echo $allnames;?>],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top'
},
plotOptions: {
series: {
events: {
legendItemClick: function() {
var jmeno=this.name;
var that=this;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myData = this.responseText;
var splitData = myData.split(",");
var newData = [];
for(var i = 0;i<splitData.length;i++){
var num = splitData[i];
if(num != ""){
num = parseFloat(num);
newData.push(num);
}
}
that.setData(newData);
}
};
xmlhttp.open("GET","/data.php?q="+jmeno,true);
xmlhttp.send();
}
}
}
},
});
</script>

Change Highcharts Graph based on two Select inputs

I have an array of data of the following format:
[["sno","day","status","data1","data2","data3","data4"],
["1","01-12-2020","success","23","66","53","34"],
["2","02-12-2020","success","12","9","8","6"],
["3","03-12-2020","success","10","11","16","13"],
["4","04-12-2020","success","34","43","54","34"],
["5","01-12-2020","fail","45","26","36","44"],
["6","02-12-2020","fail","12","15","11","13"],
["7","03-12-2020","fail","34","43","33","29"],
["8","04-12-2020","fail","23","34","31","23"]
]
to display the particular text in Highcharts I used the Following code:
var weekData = [["sno","day","status","data1","data2","data3","data4"],["1","01-12-2020","success","23","66","53","34"],["2","02-12-2020","success","12","9","8","6"],["3","03-12-2020","success","10","11","16","13"],["4","04-12-2020","success","34","43","54","34"],["5","01-12-2020","fail","45","26","36","44"],["6","02-12-2020","fail","12","15","11","13"],["7","03-12-2020","fail","34","43","33","29"],["8","04-12-2020","fail","23","34","31","23"]] ;
//console.log(weekData);
function change()
{
var valStatus = document.getElementById("statusSelect");
status = valStatus.value;
//console.log(status);
if(status == 'success')
{
const successValues = weekData.filter((x)=>x[2] === "success"); //New Cases
console.log(successValues);
return successValues;
}
else if(status == 'fail')
{
const failValues = weekData.filter((x)=>x[2] === "fail"); //New Cases
console.log(failValues)
return failValues;
}
}
function getCol(matrix, col){
var column = [];
for(var i=0; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
function chartCreate()
{
change();
const toNumbers = arr => arr.map(Number);
var getstat= change();
var day = getCol(getstat,1);
console.log(day);
var sdata1 = toNumbers(getCol(getstat,3));
console.log("data 1" ,sdata1);
var sdata2 = toNumbers(getCol(getstat,4));
console.log(sdata2);
var sdata3 = toNumbers(getCol(getstat,5));
console.log(sdata3);
var sdata4 = toNumbers(getCol(getstat,6));
console.log(sdata4);
For the full program You can check my fiddle : https://jsfiddle.net/abnitchauhan/L27n0wfs/
the problem is that when I am status select box, The Chart is not updating.
Also I feel that this code is quite lengthy when the datasets will increase overtime. is there any efficient approach to display this data on Highchart's based on the same select options.
I made an update to JS code. See if this is what you want:
var weekData = [["sno","day","status","data1","data2","data3","data4"],["1","01-12-2020","success","23","66","53","34"],["2","02-12-2020","success","12","9","8","6"],["3","03-12-2020","success","10","11","16","13"],["4","04-12-2020","success","34","43","54","34"],["5","01-12-2020","fail","45","26","36","44"],["6","02-12-2020","fail","12","15","11","13"],["7","03-12-2020","fail","34","43","33","29"],["8","04-12-2020","fail","23","34","31","23"]] ;
//console.log(weekData);
function change()
{
var valStatus = document.getElementById("statusSelect");
status = valStatus.value;
//console.log(status);
if(status == 'success')
{
const successValues = weekData.filter((x)=>x[2] === "success"); //New Cases
console.log(successValues);
return chartCreate(successValues);
}
else if(status == 'fail')
{
const failValues = weekData.filter((x)=>x[2] === "fail"); //New Cases
console.log(failValues)
return chartCreate(failValues);
}
}
function getCol(matrix, col){
var column = [];
for(var i=0; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
function chartCreate(stat)
{
const toNumbers = arr => arr.map(Number);
var getstat= stat;
var day = getCol(getstat,1);
console.log(day);
var sdata1 = toNumbers(getCol(getstat,3));
console.log("data 1" ,sdata1);
var sdata2 = toNumbers(getCol(getstat,4));
console.log(sdata2);
var sdata3 = toNumbers(getCol(getstat,5));
console.log(sdata3);
var sdata4 = toNumbers(getCol(getstat,6));
console.log(sdata4);
var options = {
chart:{
renderTo: 'chart',
defaultSeriesType: 'line'
},
title: {
text: 'dummy'
},
subtitle: {
text: ' '
},
yAxis: {
title: {
text: ' ',
//tickPointInterval: 250
},
minorTickInterval: 'auto',
// tickInterval: 4,
},
xAxis: {
labels :{
minorTickInterval: 'auto',
formatter: function(){
return day[this.value];
}
},
tickInterval: 10
},
credits: {
enabled: false
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
// pointStart: 0
}
},
tooltip: {
// split: true,
formatter: function() {
var points = this.points,
tooltipArray = ['day: <b>' + day[this.x] + '</b><br/> Value : <b>'+ this.y +'</b>']
return tooltipArray;
}
},
series: [
{
name: 'Check',
data: sdata1
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
};
var chart = new Highcharts.Chart(options);
$("#dataSelect").on('change', function(){
//alert('f')
var selVal = $("#dataSelect").val();
if(selVal == 'data1' || selVal == '')
{
options.series = [{name: 'Data', data: sdata1}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
else if(selVal == 'data2')
{
options.series = [{name: 'Data', data: sdata2}]
}
else if(selVal == 'data3')
{
options.series = [{name: 'Data', data: sdata3}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
else if(selVal == 'data4')
{
options.series = [{name: 'Data', data: sdata4}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
var chart = new Highcharts.Chart(options);
});
}
change();
Your code looks very complex and does not fully work. In this case, I will suggest using the series setData method mixed with the change event listener. My example is a bit simplified, but I think it might be the right way.
document.getElementById('dataSelect').addEventListener('change', () => {
const selectorValue = document.getElementById('dataSelect').value
chart.series[0].setData(data[selectorValue])
});
API: https://api.highcharts.com/class-reference/Highcharts.Series#setData
Demo: https://jsfiddle.net/BlackLabel/nfz0a9bm/

not able ot show date in x axis in highcharts

i want to show date in x asis but not able to show. showing values like this 00.00.00.100 in the graph.unable to convert 1577844000000 to proper date,month,year in javascript to show in the x axis using dateTimeLabelFormats in highcharts.how to use ticks and how to show it in graphs.
ticks values are printing in the console like this.
sample tick data
1577844000000
1577843100000
1577842200000
1577841300000
15778404000
sample data from the response
DeviceTimeStamp: "2020-01-10T00:30:00"
code
getalldata();
function getalldata() {
var xhttp_roomlogs = new XMLHttpRequest();
xhttp_roomlogs.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(xhttp_roomlogs.responseText);
var Ch1Temp = [];
var Ch2Temp = [];
$(response).each(function (i, item) {
var date = UtcToIst(item.DeviceTimeStamp);
var ticks = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
Ch1Temp.push([ticks, item.Ch1Temp])
Ch2Temp.push([ticks, item.Ch2Temp])//
});
$('#container').empty();
var labels = response.map(function (e) {
var roomtempdata = e.Ch1Temp;
return parseFloat(roomtempdata);
})
var ch2temp = response.map(function (e) {
var roomtempdata = e.Ch2Temp;
return parseFloat(roomtempdata);
})
Highcharts.chart('container', {
credits: {
enabled: false
},
title: {
text: 'Chamber 1 & 2 Temp'
},
subtitle: {
text: 'in Degree Celcius'
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Temperature'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
//y co-ordinates
series: [{
name: 'Chamber 1 Temp',
data: labels
},
{
name: 'Chamber 2 Temp',
data: ch2temp
}
],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
//highcharts end
}
};
xhttp_roomlogs.open("GET", "/api/data", true);
xhttp_roomlogs.send();
}
function UtcToIst(data) {
var dt = new Date(data);
return dt;
}
You can convert the json date using:
var jsonDate = "\/Date(1577844000000)\/".substr(6);
var dateObject = new Date(parseInt(jsonDate ));
var stringDate = (dateObject.getMonth() + 1) + "/" + dateObject.getDate() + "/" + dateObject.getFullYear();
console.log("Dat Object:" + dateObject);
console.log("String Date:" + stringDate);
sample hightchart code:
Highcharts.chart('container', {
chart: {
type: 'column'
},
xAxis: {
categories: ['1/1/2020', '1/2/2020', '1/3/2020', '1/4/2020', '1/5/2020']
},
plotOptions: {
column: {
stacking: 'normal'
}
},
legend: {
labelFormatter: function () {
if(this.data.length > 0) {
return this.data[0].category;
} else {
return this.name;
}
}
},
series: [{
data: [{x:0,y:1}],
name: '1/1/2020'
},{
data: [{x:1,y:1}],
name: '1/2/2020'
},{
data: [{x:2,y:1}],
name: '1/3/2020'
},{
data: [{x:3,y:1}],
name: '1/4/2020'
},{
data: [{x:4,y:1}],
name: '1/5/2020'
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<figure class="highcharts-figure">
<div id="container"></div>
</figure>

Chartjs X axis labels will not display

The documentation for time in ChartJs is extremely vague and gives little working examples so I'm struggling to get a time series working for temperature data recorded at a particular time. I can get the correct time format to appear in the tooltip, but it will not appear on the X axis.
Graph code:
<script>
var ctx = document.getElementById('myChart');
var data = {
labels: [],
datasets: [{
label: "Temperature Graph",
fill: false,
borderColor: '#3cba9f',
data: []
}]
}
const options = {
type: 'line',
data: data,
options: {
fill: false,
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day',
stepSize: 1,
displayFormats: {
day: 'MMM D'
}
},
display: true,
scaleLabel: {
display: true,
labelString: "Date",
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
},
display: true,
scaleLabel: {
display: true,
labelString: "Temperature",
}
}]
}
}
}
var chart = new Chart(ctx, options)
</script>
Data collection code:
window.onload = function load() {
getData();
}
var prevData = [];
var prevLabels = [];
function getData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI('http://localhostlocalhost/getTemp'));
xhr.onload = function() {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
console.log(data);
var label = data.timestamp * 1000;
prevData.push(data.temperature);
prevLabels.push(label);
chart.data.datasets[0].data = prevData;
chart.data.labels = prevLabels;
chart.update();
}
else {
alert(xhr.status);
}
};
xhr.send();
setTimeout(getData, 10000);
}
Example xhr response:
{temperature: 17, humidity: 38, location: "location", timestamp: 1542824305}
The data is plotted to the graph and all works as expected, the time just does not appear on the X axis

Categories

Resources