Can I make a graph between two xhttp variables? - javascript

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>

Related

Highcharts with JSON data coming from microcontroler

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

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>

Display 100 Points in 1 second : Highcharts

So I have a project where I am trying to update chart. in which 100 points to be displayed in each second.
For that I am trying this example from the Highcharts.
But the chart stops responding to such event.
The code:
jsfiddle
Highcharts.chart('container', {
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, true);
}, 10);
}
}
},
time: {
useUTC: false
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
headerFormat: '<b>{series.name}</b><br/>',
pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
}())
}]
});
You can set redraw parameter in addPoint method to false and call chart.redraw() at longer intervals:
chart: {
...,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0],
chart = this;
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], false, true);
}, 10);
setInterval(function() {
chart.redraw();
}, 500);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/s3gh6q5j/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
https://api.highcharts.com/class-reference/Highcharts.Chart#redraw

Spline Graph with diagonally fixed values with 0,0 and ploting remaing same

We are using Spline Graph for our game in which we are facing issue with x and y axis value which we need to put 0,0 and save the values from initially till end as we need to all plotting from start till end of the value.
Check Live Demo Here
JavaScript Code
<script>
var a = 1;
var b = 1;
var factor = 1.2;
$(document).ready(function () {
Highcharts.chart('container', {
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
b = b*1.2;
console.log(b);
var x = a; // current time
var y = b;
a++;
series.addPoint([x, y], true, true);
}, 700);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'number',
min: 0,
tickInterval: 2
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>X: ' + this.x+', Y:'+this.y;
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],i;
for (i = 1; i <= 19; i++) {
b = b*factor;
data.push({
x: a,
y: b
});
a++;
}
return data;
}())
}]
});
});
The following code draws a curve line from the origin (0,0) to the end point which gets updated on the interval. You needed to make the shift variable false in the addPoint call. Higchart docs
$(document).ready(function () {
var a = 1;
var b = 1;
var factor = 1.2;
Highcharts.chart('container', {
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
b = b*1.2;
var x = a; // current time
var y = b;
a++;
// Add new end point
series.addPoint([x, y], true, false);
}, 700);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'number',
min: 0,
tickInterval: 2
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>X: ' + this.x+', Y:'+this.y;
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
// Add point at origin and last point of series
var data = [{x:0,y:0}],i;
for (i = 1; i <= 19; i++) {
b = b*factor;
a++
data.push({
x: a,
y: b
});
}
return data;
}())
}]
});
});
Updated JsFiddle

Highcharts bar chart wont animate

Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart,
function initializeData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push({
name: setName($scope.jsondata[x].name),
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 5000);
}
function updateData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
console.debug("here");
for (x = 0; x < 5; x++) {
$scope.chart.series[0].data[x].update({
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'category',
labels: {
style: {
fontSize: '11px'
}
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Total Score',
align: 'high'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total Score <b>{point.y:.3f}</b>'
},
series: [{
name: 'Active Users',
data: [],
dataLabels: {
enabled: true,
rotation: 30,
style: {
fontSize: '10px',
fontFamily: 'Verdana, sans-serif'
},
format: '{point.y:.3f}', // one decimal
}
}]
});
And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference.
Some edits:
So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically).
function initializeData() {
$interval.cancel(mainInterval);
$scope.previousPackets = '';
$http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) {
var newdata = [];
var x = (new Date()).getTime();
for (var step = 9; step >= 0; step--) {
newdata.push([x - 1000 * step, 0]);
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 2000);
}
function updateData() {
$http.get(url + acronym + '/latest').success(function(returnedData) {
var x = (new Date()).getTime();
if ($scope.previousPackets != returnedData[0].numPackets) {
$scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true);
$scope.previousPackets = returnedData[0].numPackets;
} else {
$scope.chart.series[0].addPoint([x, 0], true, true);
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'areaspline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Packets'
},
plotLines: [{
value: 0,
width: 1,
color: '#d9534f'
}]
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Packets',
data: []
}]
});
I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little
function initializeChart(initialData, onload) {
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: onload
}
....
series: [{
name: 'Active Users',
data: initialData,
dataLabels: {
enabled: true,
format: '{point.y:.3f}', // one decimal
}
}]
});
}
function getData(callback) {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push([setName(ret[x].name), ret[x].data]);
}
callback(newdata);
});
}
As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart.
function readDataFirst() {
getData(function(newdata) {
initializeChart(newdata);
});
}
function initializeChartFirst() {
initializeChart([], function() {
getData(function(newdata) {
$scope.chart.series[0].setData(newdata);
})
});
}
The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible.
However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update
function forceAnimationByDoubleInitialization() {
getData(function(newdata) {
initializeChart([]);
var zerodata = newdata.map(function(item) {
return [item[0], 0]
});
$scope.chart.series[0].setData(zerodata);
$scope.chart.series[0].setData(newdata);
});
All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc

Categories

Resources