Posts: 41
Threads: 13
Joined: Dec 2016
Reputation:
0
Hi everyone,
I've been looking for a way to introduce pie charts and bar graphs to our visualizations. I stumbled on the Google chart API and this example for other platform that uses lua script.
What I'd like to do is to get data from group addresses, send it to the API and present the chart in a frame.
I lack JS and HTML knowledge to understand all this, so any help is welcome.
BR,
A Neves
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
You don't need any Lua scripting here, it can be done purely with Custom JavaScript.
Here's a Gauge example:
Code: $(function(){
// load chart JS
$.getScript('https://www.gstatic.com/charts/loader.js', function() {
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(function() {
// create empty element and add it to plan with ID=4
var el = $('<div></div>').css({
position: 'absolute',
width: 200,
height: 200,
top: 200,
left: 200
}).appendTo('#plan-4');
// (re)draw gauge on each object update
grp.listen('32/1/1', function(object) {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Level', object.value]
]);
// gauge options
var options = {
width: 200,
height: 200,
redFrom: 90,
yellowFrom: 75,
yellowTo: 90,
redTo: 100,
minorTicks: 5
};
var chart = new google.visualization.Gauge(el.get(0));
chart.draw(data, options);
});
});
});
});
Posts: 41
Threads: 13
Joined: Dec 2016
Reputation:
0
Thank you admin. This works just like I needed to.
How can I pass an array from a script to the custom JS? I'm thinking in combine Google charts with this example:
http://www.openrb.com/docs/trends-new.htm
Or simply creating a table like this and call it in JS:
Code: kwh_lights = grp.getvalue('1/1/33')
kwh_sockets = grp.getvalue('1/1/53')
kwh_AC = grp.getvalue('1/1/73')
kwh_garden = grp.getvalue('1/1/93')
energy_pie={{'Label', 'Value'},
{'Lights', kwh_lights},
{'Sockets', kwh_sockets},
{'AC', kwh_AC },
{'Garden', kwh_garden }
}
log(energy_pie)
BR,
A Neves
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
For smaller arrays you can use a virtual object with 250-byte string data type and put data converted via json.encode. For larger arrays you will need to create a sepearate .lp file that will output resulting data array.
Posts: 41
Threads: 13
Joined: Dec 2016
Reputation:
0
Unfortunately I don't know how to work with .lp files. Can you provide me an example, please?
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
Docs on how to upload .lp files:
https://forum.logicmachine.net/showthread.php?tid=85
.lp file is a Lua script which is accessible from HTTP. Here's a minimal example that outputs data in JSON format:
Code: <?
data = { 1, 2, 3 }
print(json.encode(data))
Then, in Custom JavaScript you can load data from .lp like this (in callback function passed to google.charts.setOnLoadCallback). Once data is loaded you can create new chart and draw it.
Code: $.getJSON('/user/data.lp', function(data) {
console.log(data);
// draw chart here
});
Posts: 264
Threads: 39
Joined: Feb 2016
Reputation:
1
-----------
FRANCE SMARTHOME & SMARTBUILDING INTEGRATION
SE ECO EXPERT
Posts: 106
Threads: 40
Joined: Sep 2017
Reputation:
0
(17.05.2018, 12:28)admin Wrote: You don't need any Lua scripting here, it can be done purely with Custom JavaScript.
Here's a Gauge example:
Code: $(function(){
// load chart JS
$.getScript('https://www.gstatic.com/charts/loader.js', function() {
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(function() {
// create empty element and add it to plan with ID=4
var el = $('<div></div>').css({
position: 'absolute',
width: 200,
height: 200,
top: 200,
left: 200
}).appendTo('#plan-4');
// (re)draw gauge on each object update
grp.listen('32/1/1', function(object) {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Level', object.value]
]);
// gauge options
var options = {
width: 200,
height: 200,
redFrom: 90,
yellowFrom: 75,
yellowTo: 90,
redTo: 100,
minorTicks: 5
};
var chart = new google.visualization.Gauge(el.get(0));
chart.draw(data, options);
});
});
});
});
Hi,
I'm trying this function...but I have a doubt. What is the empty element that I must put in PLAN ? And where Can I found the plan ID ?
Regards,
Alberto
KNX Advanced Partner + Tutor
Posts: 4643
Threads: 24
Joined: Aug 2017
Reputation:
207
Plan ID can be found by selecting your plan and then click quick view
Then in the new opened window you will see plan ID after the # in the url
You should see something like that in final visu
Your LM must have internet connection for this to work.
------------------------------
Ctrl+F5
Posts: 106
Threads: 40
Joined: Sep 2017
Reputation:
0
31.03.2020, 13:00
(This post was last modified: 31.03.2020, 13:02 by toujour.)
Great !! thanks Daniel !!
My doubt was for an "empty element". Now I understand that it was only to see the page (create a botton with empty image).
BR,
Alberto
KNX Advanced Partner + Tutor
Posts: 23
Threads: 3
Joined: Sep 2019
Reputation:
2
Hello, I am trying to implement the use of surplus photovoltaic energy taking into account the weather and radiation forecast. Now I am trying to tune the algorithm, plotting with google charts some info. I am able to plot different values, but I am not able to solve two issues
- With several plots, tooltip is only visible in the first #plan. Exchanging from one #plan to the other, the one that wasn't working now works, and vice versa.
- there is differenci if I access to the plan from home page or directly from specific url, i.e. http://192.168.0.10/scada-vis/#21. now the information lixe axes title and legend
I attach a snapshot of plan21, whose has the first chart, the tooltip works properly but not the info like legend. I draw the cursor by hand
The #plan24 has not work the tooltip
Changing the plot form #plan24 to #plan21 tooltips work well. And if I load 192.168.0.10/scada-vis/#21 the information like legend, it is showed
The javascript used:
Code: $(function(){
// load chart JS
$.getScript('https://www.gstatic.com/charts/loader.js', function() {
google.charts.load('current', {'packages':['gauge', 'corechart'],language: 'es'});
google.charts.setOnLoadCallback(drawSolcast);
google.charts.setOnLoadCallback(drawGraphBC);
//------------------------------------------------------------------------------------------------
//-- plan21, graph consumo BC
//---
function drawGraphBC() {
// create empty element and add it to plan with ID=21
var graphEl = $('<div></div>').css({
position: 'absolute',
width: 1000, height: 350,
top: 20, left: 20
}).appendTo('#plan-21');
$.getJSON('/user/energia.lp', function(jsonData) {
console.log(jsonData);
var data4 = new google.visualization.arrayToDataTable(jsonData);
var opt4 = { title: 'Calefacción / ACS' ,
width: 1000, height: 350,
// Gives each series an axis that matches the vAxes number below.
focusTarget: 'category',
seriesType: 'bars',
series: {
0: {targetAxisIndex: 0, areaOpacity: 1, lineWidth: 1},
1: {targetAxisIndex: 0, areaOpacity: 1, lineWidth: 1},
2: {targetAxisIndex: 1, areaOpacity: 0, visibleInLegend: false, type: 'line'}
} ,
vAxes: {
// Adds titles to each axis.
0: {title: 'Potencia [kW]', viewWindow: {min: 0, max:2500} },
1: { title: 'COP', gridlines: { interval: [ 1, 2, 3, 4, 5, 6 ] },
viewWindow: {min: 1, max: 6}, gridlines: { count: 0} }
}
};
var chart4 = new google.visualization.ComboChart(graphEl.get(0));
chart4.draw(data4, opt4);
}); //getJSON
}; //drawWCons
//------------------------------------------------------------------------------------------------
//-- plan24, grafica weather
//---
function drawSolcast() {
// create empty element and add it to plan with ID=24
var graphSol = $('<div></div>').css({
position: 'absolute',
width: 1000, height: 350,
top: 400, left: 20,
border: 'solid'
}).appendTo('#plan-21');
$.getJSON('/user/sol2graph.lp', function(jsonObj) {
console.log(jsonObj);
var data5 = new google.visualization.DataTable();
data5.addColumn('date', 'fecha');
data5.addColumn('number', "pv_estimate");
data5.addColumn('number', "kWh/dia");
// a formato tiempo
for (var i = 0; i < jsonObj.length; i++) {
jsonObj[i][0] = new Date( jsonObj[i][0] * 1000);
}
data5.addRows(jsonObj);
var tickMarks = [];
var hoy = new Date()
for (var i = 0; i < 7; i++) {
tickMarks.push(new Date(hoy.getTime() + i*24*60*60*1000));
}
var opt5 = { title: 'Pv kWh' ,
width: 1000, height: 350,
chartArea: {width: '90%', height: '80%'},
focusTarget: 'category',
seriesType: 'lines',
hAxis: {
format: 'EE, d MMM',
gridlines: { count: 7},
ticks: tickMarks
},
series: {
0: {targetAxisIndex: 0, areaOpacity: 1, lineWidth: 1},
1: {targetAxisIndex: 1, areaOpacity: 0.2, lineWidth: 1, type: 'area', color: '#f1ca3a' }
},
vAxes: {
// Adds titles to each axis.
0: {title: '[kW]', viewWindow: {min: 0, max:3.5}, gridlines: {interval: [ 0.5, 1, 1.5, 2, 2.5, 3 ] }},
1: { viewWindow: {min: 0, max: 70}, gridlines: { count: 0}, ticks: [ ] }
}
};
var date_formatter = new google.visualization.DateFormat({ pattern: 'dd MMM, HH:mm' });
date_formatter.format(data5, 0);
var chart5 = new google.visualization.ComboChart(graphSol.get(0));
chart5.draw(data5, opt5);
}); //getJSON
}; //drawSolcast
}); // getscript
});
Any help is welcome, thanks
Jose
--
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
The problem is that chart does not render properly when it's drawn in a hidden element (plan).
You can listen to the "showplan" event and draw charts only when the containing plan becomes visible like this:
Code: google.charts.load('current', {'packages':['gauge', 'corechart'],language: 'es'});
$('body').on('showplan', function(event, id) {
if (id == 21) {
google.charts.setOnLoadCallback(drawGraphBC);
}
else if (id == 24) {
google.charts.setOnLoadCallback(drawSolcast);
}
}).trigger('showplan', [ currentPlanId ]);
//------------------------------------------------------------------------------------------------
Posts: 23
Threads: 3
Joined: Sep 2019
Reputation:
2
23.02.2021, 10:05
(This post was last modified: 23.02.2021, 10:05 by jose_dli.)
Thanks Admin for the quick answer, I have added the listener, now the complete information is displayed, like legends. But the tooltip is only available for the first plan, it works in plan#21 but not in plan#24, Do you have any idea what is the origin for this issue? for me tooltips are important to keep the grahps human readable and clean. Thanks again for your support
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
It's possible that chart instance can be created multiple times. Use this to create chart only once. I've removed some parts of the code to make it more readable.
Code: $(function(){
// load chart JS
$.getScript('https://www.gstatic.com/charts/loader.js', function() {
var chart4, chart5;
google.charts.load('current', {'packages':['gauge', 'corechart'],language: 'es'});
$('body').on('showplan', function(event, id) {
if (id == 21) {
google.charts.setOnLoadCallback(drawGraphBC);
}
else if (id == 24) {
google.charts.setOnLoadCallback(drawSolcast);
}
}).trigger('showplan', [ currentPlanId ]);
//------------------------------------------------------------------------------------------------
//-- plan21, graph consumo BC
//---
function drawGraphBC() {
if (!chart4) {
// create empty element and add it to plan with ID=21
var graphEl = $('<div></div>').css({
position: 'absolute',
width: 1000, height: 350,
top: 20, left: 20
}).appendTo('#plan-21');
chart4 = new google.visualization.ComboChart(graphEl.get(0));
}
$.getJSON('/user/data.lp', function(jsonData) {
var data4 = new google.visualization.arrayToDataTable(jsonData);
var opt4 = { ... };
chart4.draw(data4, opt4);
}); //getJSON
}; //drawWCons
//------------------------------------------------------------------------------------------------
//-- plan24, grafica weather
//---
function drawSolcast() {
if (!chart5) {
// create empty element and add it to plan with ID=24
var graphSol = $('<div></div>').css({
position: 'absolute',
width: 1000, height: 350,
top: 400, left: 20,
border: 'solid'
}).appendTo('#plan-24');
chart5 = new google.visualization.ComboChart(graphSol.get(0));
}
$.getJSON('/user/data2.lp', function(jsonObj) {
var data5 = new google.visualization.DataTable();
var opt5 = { ... };
var date_formatter = new google.visualization.DateFormat({ pattern: 'dd MMM, HH:mm' });
date_formatter.format(data5, 0);
chart5.draw(data5, opt5);
}); //getJSON
}; //drawSolcast
}); // getscript
});
Posts: 23
Threads: 3
Joined: Sep 2019
Reputation:
2
23.02.2021, 11:29
(This post was last modified: 23.02.2021, 11:31 by jose_dli.)
Thanks for the help, but it continues without showing the tooltip for the last #plan. It seems that for the other charts, it doesn't know where is the cursor .
I can use other chart library (highcharts ???). I'm a noob, any recommendation is welcome. Is it possible include de libraries in SL "harddisk"?, for not use it in CDN format and avoid script failures by abandoning backward compatibility.
Posts: 23
Threads: 3
Joined: Sep 2019
Reputation:
2
Hello again, I have found a solution, it is not ideal but it works, for both charts, Google and Highcharts.
Now it works because layout is removed from plan in Vis. structure > Levels/Plans. I said that tooltip works only with the first plan, but it seems that the problem was not the order, if not layout definition
If any one want the code for use Highcharts I can upload
Posts: 38
Threads: 10
Joined: Dec 2017
Reputation:
0
Hi, I know this thread is quite old, but since it's related, I think it's the right place.
I have an script with a json format array saved in a group direction: [["Time","Price"],["0",207.56],["1",202.29],["2",193.04],["3",190.45],["4",193.28],["5",184.3],["6",186.88],["7",222.27],["8",217.72],["9",262.96],["10",265.24],["11",262.25],["12",256.23],["13",209.29],["14",212.33],["15",215.99],["16",219.46],["17",266.98],["18",284.13],["19",293.19],["20",274.91],["21",221.46],["22",214.04]]
I also have the javascript code to make the google's example line graph, but due to my lack of knowledge in JS, I don't know how to pass the array to the line graphic. Could you help me please?
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
This thread has several examples that you can use: https://forum.logicmachine.net/showthread.php?tid=4202
You can put your data into storage and retrieve it by using a .lp server-side script.
|