I have a json with the name of each server and 3 values: memory, load and cpu.
[
{
"server": "Server1",
"Load": "0.04",
"Mem": "64.46",
"Idle": "97.00"
},
{
"server": "Server2",
"Load": "0.01",
"Mem": "64.79",
"Idle": "97.49"
}
]
I'm having some issues trying to create Google Chart dynamically. Looks like Javascript can't create variables using the loop variable 'i'. See my code below:
var obj = JSON.parse(jsonData);
for (i in obj)
{
var data_table[i] = new google.visualization.DataTable();
data_table[i].addColumn('string', 'Label');
data_table[i].addColumn('number', 'Value');
var server = obj[i].server;
var Load = parseFloat(obj[i].Load);
var Mem = parseFloat(obj[i].Mem);
var Idle = parseFloat(obj[i].Idle);
data_table[i].addRow([server, Load]);
data_table[i].addRow([server, Mem]);
data_table[i].addRow([server, Idle]);
var options = {width: 1500, height: 1000, redFrom: 90, redTo: 100, yellowFrom:75, yellowTo: 90, minorTicks: 5};
var chart[i] = new google.visualization.Gauge(document.getElementById('chart_div'+ i +));
chart[i].draw(data_table+i+, options); ' );
$('body').append('<div id="div'+ i +'" />')
}
I want to create the Chart dynamically to control these chart's later in the javascript/html and also and most important because my json is a little big so I want to avoid to have to create each chart one by one, or have to separate the json for each server.
Any help will be really appreciated. ;-)
Try it like this...
// load json
var obj = JSON.parse(jsonData);
// define arrays to store data and charts
var data_tables = [];
var google_charts = [];
// this is the div that will store all of the charts
var chart_area;
chart_area = document.getElementById('chart_div');
// set the chart options
var chart_options;
chart_options = {
width: 1500,
height: 1000,
redFrom: 90,
redTo: 100,
yellowFrom: 75,
yellowTo: 90,
minorTicks: 5
};
// process json array -- fyi: use 'in' keyword for object keys
for (var i = 0; i < obj.length; i++) {
var chart_container; // chart container for this json instance
var data_table; // data table for this json instance
var google_chart; // google chart for this json instance
// load data table
data_table = new google.visualization.DataTable();
data_table.addColumn('string', 'Label');
data_table.addColumn('number', 'Value');
data_table.addRow([obj[i].server, parseFloat(obj[i].Load)]);
data_table.addRow([obj[i].server, parseFloat(obj[i].Mem)]);
data_table.addRow([obj[i].server, parseFloat(obj[i].Idle)]);
// save it to the array
data_tables.push(data_table);
// create the container for this chart
chart_container = document.createElement('DIV');
chart_area.appendChild(chart_container);
// create -- save -- draw the chart
google_chart = new google.visualization.Gauge(chart_container);
google_charts.push(google_chart);
google_chart.draw(data_table, chart_options);
}
// access the charts / data later using arrays --> data_tables and google_charts
Related
I am not a javascript developer not even expert in ajax, just a no vice desktop developer , I would really appreciate if you can show me how can I connect MCU returning json data to a web page that uses google gauge running on client on local network at home.
So I have implemented a simple Arduino based web sever that returns data in below format:
{“arduino”:
[
{“location”:”outdoor”,”temperature”:”15.55″},
{“location”:”outdoor”,”humidity”:”15″}
]
}
I want to be able to show live temperature without having to refresh the whole page: I came across with google gauge example.
I have modified the example in the link below to display temperature and humidity separate gauge:
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawGauge);
var gaugeOptions = {min: 0, max: 280, yellowFrom: 200, yellowTo: 250,
redFrom: 250, redTo: 280, minorTicks: 5};
var gauge;
function drawGauge() {
gaugeData = new google.visualization.DataTable();
gaugeData.addColumn('number', 'Temperature');
gaugeData.addColumn('number', 'Humidity');
gaugeData.addRows(2);
gaugeData.setCell(0, 0, 120);
gaugeData.setCell(0, 1, 80);
gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
gauge.draw(gaugeData, gaugeOptions);
}
function changeTemp(dir) {
gaugeData.setValue(0, 0, gaugeData.getValue(0, 0) + dir * 25);
gauge.draw(gaugeData, gaugeOptions);
}
function changeHumid(dir) {
gaugeData.setValue(0, 1, gaugeData.getValue(0, 1) + dir * 20);
gauge.draw(gaugeData, gaugeOptions);
}
</script>
</head>
<body>
<div id="gauge_div" style="width:280px; height: 140px;"></div>
<small>Change</small>
<input type="button" value="Temperature" onclick="changeTemp(1)" />
<input type="button" value="Humidity" onclick="changeHumid(1)" />
</body>
</html>
Now I want the change temperate and change Humidity functions should execute after 5 sec displaying latest data from the json returned by executing the MCU bee server URL ? How can I implement that ?
Well, I figured it out, after lots of digging, I finally have something working before I finish my vacation.
below code works and displays the latest value in my google gauge and it refreshes after every 15 seconds, same principle I can apply on json data I have put as sample in the Opening post.
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type='text/javascript'>
// set your channel id here
var channel_id = 166617;
// set your channel's read api key here if necessary
var api_key = 'ZCUB611J8M8ELM9M';
// maximum value for the gauge
var max_gauge_value = 70;
// name of the gauge
var gauge_name = 'Temperature';
// global variables
var chart, charts, data;
var public_key = 'dZ4EVmE8yGCRGx5XRX1W';
// load the google gauge visualization
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(initChart);
// display the data
function displayData(point) {
data.setValue(0, 0, gauge_name);
data.setValue(0, 1, point);
chart.draw(data, options);
}
// load the data
function loadData() {
// variable for the data point
var p;
// JSONP request
var jsonData = $.ajax({
url: 'https://data.sparkfun.com/output/' + public_key + '.json',
data: {page: 1},
dataType: 'jsonp',
}).done(function (results){
// get the data last value
p = results[results.length - 1].tempf;
// if there is a data point display it
if (p) {
displayData(p);
}
});
}
// initialize the chart
function initChart() {
data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(1);
chart = new google.visualization.Gauge(document.getElementById('gauge_div'));
options = {width: 120, height: 120, greenFrom: 10, greenTo: 29, redFrom: 41, redTo: 70, yellowFrom:30, yellowTo: 40, minorTicks: 5};
loadData();
// load new data every 15 seconds
setInterval('loadData()', 15000);
}
</script>
In order to retreive temperature and humidity, you can do (using jquery):
function repeat() {
$.get( "YOUR_WEB_SERVER_JSON_URL", function( data ) {
gaugeData.setValue(0, 0, data.arduino[0].temperature);
gaugeData.setValue(0, 1, data.arduino[1].humidity);
gauge.draw(gaugeData, gaugeOptions);
setTimeout(repeat, 5000);
});
I've set up a simple example for you, check it out here.
I created a sample fiddle for you:
google.charts.load('current', {
'packages': ['gauge']
});
google.charts.setOnLoadCallback(drawGauge);
var gaugeOptions = {
min: 0,
max: 280,
yellowFrom: 200,
yellowTo: 250,
redFrom: 250,
redTo: 280,
minorTicks: 5
};
var gauge;
var gaugeData;
function drawGauge() {
gaugeData = new google.visualization.DataTable();
gaugeData.addColumn('number', 'Temperature');
gaugeData.addColumn('number', 'Humidity');
gaugeData.addRows(2);
gaugeData.setCell(0, 0, 120);
gaugeData.setCell(0, 1, 80);
gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
gauge.draw(gaugeData, gaugeOptions);
repeat();
}
function repeat() {
var dir = Math.floor((Math.random() * 10) + 1);
gaugeData.setValue(0, 0, dir * 25);
gaugeData.setValue(0, 1, dir * 20);
gauge.draw(gaugeData, gaugeOptions);
setTimeout(repeat, 5000);
}
Repeat function is going to be executed every 5 seconds. In a sample fiddle it gets some random number from 1 to 10 and updates charts with this value multiplied by 25 and 20. In your scenario, you should make a call to your web server, parse the response, get values for temperature and humidity and update the charts. Please let me know if you need help on this too.
I have created a Google Pie Chart using the following code:
var data = google.visualization.arrayToDataTable(array);
var options = {
title: 'Meta Share',
is3D: true,
sliceVisibilityThreshold: .04,
slices: { 6 : {offset: 0.2},
},
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I want to select a slice of the pie chart dynamically depending on what my user is doing.
I now have the following code:
var slice = 8;
I would now like to use this variable in the above code, however; replacing the '6' with the variable 'slice' does not work.
Any suggestions? :)
You can't use variables as keys in object literals, you'd have to first create the object, then use brackets to use the variable as a key
var slice = 8;
var slices = {};
slices[slice] = {offset: 0.2};
var data = google.visualization.arrayToDataTable(array);
var options = {
title : 'Meta Share',
is3D : true,
sliceVisibilityThreshold : .04,
slices : slices
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
Sorry for the noob question but I'm having trouble working with arrays in javascript. I'm reading BLE data from an arduino in 2 byte packets and storing the assembled data in an array. Basically the arduino sends the current temp reading over BLE and it's stored in an array.
// Start reading notifications.
evothings.ble.enableNotification(
deviceHandle,
app.characteristicRead,
function(data)
{
app.displayStatus('Active');
app.drawLines([new DataView(data).getUint16(0, true)]);
},
function(errorCode)
{
app.displayStatus('enableNotification error: ' + errorCode);
});
the data is then displayed in a 2d line graph
drawLines: function(dataArray)
{
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var dataPoints = app.dataPoints;
dataPoints.push(dataArray);
if (dataPoints.length > canvas.width)
{
dataPoints.splice(0, (dataPoints.length - canvas.width));
}
var magnitude = 1200;
function calcY(i)
{
return (i * canvas.height) / magnitude;
}
function drawLine(offset, color)
{
context.strokeStyle = color;
context.beginPath();
context.moveTo(0, calcY(dataPoints[dataPoints.length-1][offset]));
var x = 1;
for (var i = dataPoints.length - 2; i >= 0; i--)
{
var y = calcY(dataPoints[i][offset]);
context.lineTo(x, y);
x++;
}
context.stroke();
}
context.clearRect(0, 0, canvas.width, canvas.height);
drawLine(0, '#f00');
},
This all works fine but I'd like to adapt this code to display the current temp (last entry in the data array) as a google chart (gauge).
// Start reading notifications.
evothings.ble.enableNotification(
deviceHandle,
app.characteristicRead,
function(data)
{
app.drawChart([new DataView(data).getUint16(0, true)]);
},
function(errorCode)
{
console.log('enableNotification error: ' + errorCode);
});
and
drawChart: function(dataArray) {
var chartdata = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Temp', 0]
]);
var options = {
width: 800, height: 240,
redFrom: 900, redTo: 1200,
yellowFrom:750, yellowTo: 900,
greenFrom:550, greenTo: 750,
minorTicks: 5,
max: 1200,
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(chartdata, options);
setInterval(function() {
var temp = dataArray.slice(-1)[0];
chartdata.setValue(0, 1, temp);
chart.draw(chartdata, options);
}, 1000);
},
This adapted code works but in a weird way. Initially the chart stays at zero, if I restart the arduino the temp updates but only once and stays at the value even though the arduino is sending new values. I think I wrote the adapted code wrong but not really sure what I'm doing. I barely know C++ and tried to figure out how to adapt this js for my project.
I'm using this function to take the last entry from the array, not sure if this is correct:
dataArray.slice(-1)[0]
I know it's a js issue, when I run the initial code with 2d line graph everything works fine and the data is continuously updated. Both charts pull from the same BLE data array so the problem should be in my js code.
Thanks for any advice
I am having some issues dynamically creating code for Google Gauge visualization. My main problem is that I am trying to build the javascript based on what is returned in some JSON to build multiple gauge panels for a temp monitoring dashboard. Here is my current code:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
//Get php data about sensor into json array for javasript processing
var gauges = <?php echo json_encode($sensor_data);?>;
google.load("visualization", "1", {packages:["gauge"]});
google.setOnLoadCallback(drawChart);
for (var i = 0, len = gauges.length; i < len; ++i) {
var gauge = gauges[i];
var currentTemp = gauge.value;
var chartID = "chart_div_" + gauge.sensor_id;
var gMin = gauge.config_min_temp;
var gMax = gauge.config_max_temp;
var lLimit = gauge.limits_low;
var hLimit = gauge.limits_high;
//calculate major tick increments
var increment = (parseFloat(gMax) - parseFloat(gMin))/4;
var tick0 = gMin;
var tick1 = parseFloat(gMin) + parseFloat(increment);
var tick2 = parseFloat(tick1) + parseFloat(increment);
var tick3 = parseFloat(tick2) + parseFloat(increment);
var tick4 = gMax;
var Ticks = [tick0, tick1, tick2, tick3, tick4];
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Temp', 0]
]);
var options = {
width: 220, height: 220,
redFrom: hLimit, redTo: gMax,
yellowFrom: gMin, yellowTo: lLimit,
greenFrom: gMin, greenTo: gMax,
minorTicks: 5,
majorTicks: Ticks,
min: gMin,
max: gMax,
redColor: '#ff0000',
yellowColor: '#ff0000',
greenColor: '#00cc00'
};
var chart = new google.visualization.Gauge(document.getElementById(chartID));
data.setValue(0, 1, currentTemp);
chart.draw(data, options);
}
}
</script>
My issue is that I cannot create an array of the data object. I need to reference that object inside the for loop. I have googled this issue until I am at my wits end and cannot come up with a good way to do this. I am wide open for suggestions. Thanks in advance.
Your code as-is will create a single drawChart function and then overwrite it, which I am fairly certain is not your intention. This code will loop over your gauges array and draw a Gauge for each element in the array:
function drawChart() {
for (var i = 0, len = gauges.length; i < len; ++i) {
var gauge = gauges[i];
var currentTemp = gauge.value;
var chartID = "chart_div_" + gauge.sensor_id;
var gMin = gauge.config_min_temp;
var gMax = gauge.config_max_temp;
var lLimit = gauge.limits_low;
var hLimit = gauge.limits_high;
//calculate major tick increments
var increment = (parseFloat(gMax) - parseFloat(gMin))/4;
var tick0 = gMin;
var tick1 = parseFloat(gMin) + parseFloat(increment);
var tick2 = parseFloat(tick1) + parseFloat(increment);
var tick3 = parseFloat(tick2) + parseFloat(increment);
var tick4 = gMax;
var Ticks = [tick0, tick1, tick2, tick3, tick4];
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Temp', currentTemp]
]);
var options = {
width: 220, height: 220,
redFrom: hLimit, redTo: gMax,
yellowFrom: gMin, yellowTo: lLimit,
greenFrom: gMin, greenTo: gMax,
minorTicks: 5,
majorTicks: Ticks,
min: gMin,
max: gMax,
redColor: '#ff0000',
yellowColor: '#ff0000',
greenColor: '#00cc00'
};
var chart = new google.visualization.Gauge(document.getElementById(chartID));
data.setValue(0, 1, currentTemp);
chart.draw(data, options);
}
}
Is that what you are looking to accomplish?
Background - I have a spreadsheet with some data in it, I want to prepare and present some "dynamic charts" from this data, what I have thought is create some charts in script editor - HTML and then in the .gs code call this HTML file with a doGet function (after publishing - will be used by Internal members only)
A similar example of chart can be viewed here but when I add the HTML code to the HTML page and Javascript code as with script tags in the HTML page, nothing is displayed in the browser.
How can I implment this chart (or other with similar type) within google doGet function.
Code
<script src="http://www.amcharts.com/lib/amcharts.js" type="text/javascript"></script>
<div id="chartdiv" style="width: 100%; height: 362px;"></div>
var lineChartData = [{
date: new Date(2009, 10, 2),
value: 5},
{
date: new Date(2009, 10, 3),
value: 15},
{
date: new Date(2009, 10, 4),
value: 13},
{
date: new Date(2009, 10, 5),
value: 17},
{
date: new Date(2009, 11, 4),
value: 26}];
AmCharts.ready(function() {
var chart = new AmCharts.AmSerialChart();
chart.dataProvider = lineChartData;
chart.pathToImages = "http://www.amcharts.com/lib/images/";
chart.categoryField = "date";
// sometimes we need to set margins manually
// autoMargins should be set to false in order chart to use custom margin values
chart.autoMargins = false;
chart.marginRight = 0;
chart.marginLeft = 0;
chart.marginBottom = 22;
chart.marginTop = 0;
// AXES
// category
var categoryAxis = chart.categoryAxis;
categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
categoryAxis.minPeriod = "DD"; // our data is daily, so we set minPeriod to DD
categoryAxis.gridAlpha = 0;
categoryAxis.tickLength = 0;
categoryAxis.axisAlpha = 0;
// value
var valueAxis = new AmCharts.ValueAxis();
valueAxis.dashLength = 4;
valueAxis.axisAlpha = 0;
chart.addValueAxis(valueAxis);
// GRAPH
var graph = new AmCharts.AmGraph();
graph.type = "line";
graph.valueField = "value";
graph.lineColor = "#D8E63C";
graph.customBullet = "http://www.amcharts.com/lib/images/star.gif"; // bullet for all data points
graph.bulletSize = 14; // bullet image should be a rectangle (width = height)
graph.customBulletField = "customBullet"; // this will make the graph to display custom bullet (red star)
chart.addGraph(graph);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chart.addChartCursor(chartCursor);
// WRITE
chart.write("chartdiv");
});
Apologies, if I am not able to explain it properly. I am still a newbie in this...
(Note:- have deleted some part of actual code to make it short)
If I understood your question right, you need to use the HTML Service to display that code. Basically, your Apps Script project will have two files, one Code.gs and an html file. Then, use the following in Code.gs, assuming the file with the HTML is called "index.html".
function doGet() {
return HtmlService.createHtmlOutputFromFile('index').setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
Good luck using AmCharts, though - I've never tried that one. However, every other charts library I've tried has failed in HTML Service except for Piety. The Caja sanitizer prevents a lot of stuff from running.