Custom Web Chart
Re: Custom Web Chart
If your missing data just fill in the missing timestamps with 0...so if at 6am i had 5 and that was the last data, but I'm getting the chart at 7am, we can fill in 0 at 6:05, 6:10, 6:15... We can just assume no data sent would also be 0..good for if controller goes offline and you look at a chart today you will think your WL is just fine since the chart shows 50%...meanwhile your not sending data for 3 days...for example.
Re: Custom Web Chart
It also hides when sensors eroneously report 0...like my ph does occasionally...however i cam see when without finding a gap in the timeline..
Re: Custom Web Chart
We would need to analyze the results of the query record by record to be able to do this.
Remember that this is a SQL query.
Remember that this is a SQL query.
Roberto.
Re: Custom Web Chart
So how about just biting the bullet then and storing 0 values? You could use NULL value for storing non-sent data.
Re: Custom Web Chart
Your using HighCharts IIRC? I think they have some solutions and its actually opposite of what I said above if I'm interpreting correctly. It asks for you to store the missing data as NULL if you want the x axis to stay consistent.
Re: Custom Web Chart
For missing data on HighCharts, here is an example of making the X axis of the chart nice and even which might be uneven in time (Because of 0 values or missed contact with the controller).
http://www.highcharts.com/demo/spline-irregular-time
I don't see what they're doing different from what the portal does in its JS code, though. Maybe it's a later version of the .js than what the portal points to?
Looks like if the data is a series of x,y values, or I assume an array of 2 element arrays. it should do the right thing with the datetime plot.
http://www.highcharts.com/demo/spline-irregular-time
I don't see what they're doing different from what the portal does in its JS code, though. Maybe it's a later version of the .js than what the portal points to?
Looks like if the data is a series of x,y values, or I assume an array of 2 element arrays. it should do the right thing with the datetime plot.
Re: Custom Web Chart
That seems to be the same way I setup the charts
Code: Select all
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
<meta name="viewport" content="user-scalable=no, initial-scale=.5, maximum-scale=.5, minimum-scale=.5, target-densitydpi=device-dpi" />
<meta name="msapplication-tap-highlight" content="no" />
<link href='http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css' rel='stylesheet'>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src='http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js'></script>
<title>Reef Angel U-App</title>
<script type="text/javascript">
$(function () {
$.mobile.loading( 'show', {
text: 'Connecting to Portal',
textVisible: true,
theme: 'b',
html: ""
});
Highcharts.setOptions({
global: {
useUTC: false
}
});
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
seriesID = 0,
names = [
'PH'
],
colors = Highcharts.getOptions().colors;
$.each(names, function (i, name) {
$.getJSON('http://forum.reefangel.com/status/jsonp.aspx?id=reefangel&filter=' + name.toLowerCase() + '&callback=?', function (data) {
var pcolor;
var tname;
var ydec;
var yunit;
if (name == "PH") {
pcolor = '#669900'
tname = 'pH'
ydec = 2
yunit = 'pH'
}
else if (name == "PHE") {
pcolor = '#447700'
tname = 'pH Expansion'
ydec = 2
yunit = 'pH'
}
else if (name == "SAL") {
pcolor = '#000066'
tname = 'Salinity'
ydec = 1
yunit = 'ppt'
}
else if (name == "ORP") {
pcolor = '#330000'
tname = 'ORP'
ydec = 0
yunit = 'mV'
}
else if (name == "T1") {
pcolor = '#FF0000'
tname = 'Temp 1'
ydec = 1
yunit = '°'
}
else if (name == "T2") {
pcolor = '#FF8800'
tname = 'Temp 2'
ydec = 1
yunit = '°'
}
else if (name == "T3") {
pcolor = '#9900CC'
tname = 'Temp 3'
ydec = 1
yunit = '°'
}
else {
pcolor = '#FF0000'
tname = 'PH'
ydec = 0
yunit = ''
}
if (data.length) {
seriesOptions[seriesID] = {
dataGrouping: {
smoothed: true
},
name: tname,
color: pcolor,
tooltip: {
yDecimals: ydec,
ySuffix: yunit
},
data: data
};
seriesID++;
}
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if(data.length==0)
{
$('#container').html("No data to display");
$.mobile.loading( "hide" );
}
else
if (seriesCounter == names.length) {
createChart();
$.mobile.loading( "hide" );
}
});
});
// create the chart when all data is loaded
function createChart() {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
type: 'spline'
},
title: {
text: 'Reef Angel Controller Web Chart'
},
subtitle: {
text: 'Parameters logged for the past 7 days'
},
credits: {
enabled: false
},
legend: {
enabled: true,
//align: 'right',
//backgroundColor: '#FCFFC5',
borderColor: 'black',
borderWidth: 2,
//layout: 'vertical',
verticalAlign: 'top',
y: 100,
shadow: true
},
rangeSelector: {
buttons: [{
type: 'minute',
count: 60,
text: '1h'
}, {
type: 'minute',
count: 720,
text: '12h'
}, {
type: 'day',
count: 1,
text: '1d'
}, {
type: 'day',
count: 3,
text: '3d'
}, {
type: 'all',
text: '7d'
}],
selected: 2,
inputEnabled: false
},
navigator: {
xAxis: {
type: 'datetime',
maxZoom: 3600000, // 1 hour
dateTimeLabelFormats: { // don't display the dummy year
second: '%I:%M:%S %p',
minute: '%I:%M %p',
hour: '%b/%e',
day: '%b/%e',
week: '%b/%e'
}
}
},
xAxis: {
type: 'datetime',
maxZoom: 3600000, // 1 hour
dateTimeLabelFormats: { // don't display the dummy year
second: '%I:%M:%S %p',
minute: '%I:%M %p',
hour: '%I:%M %p',
day: '%b/%e',
week: '%b/%e'
}
},
yAxis: {
plotLines: [{
value: 0,
width: 1,
color: 'silver'
}]
},
tooltip: {
borderColor: 'silver',
xDateFormat: '%A, %b %e, %l:%M %p',
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>'
},
series: seriesOptions
});
}
});
</script>
</head>
<body>
<script type="text/javascript" src="http://forum.reefangel.com/js/highstock.js"></script>
<div id="container" style="height: 500px; min-width: 600px"></div>
</body>
</html>
Roberto.
Re: Custom Web Chart
Right. Is it because you use highstock.js instead of highchart.js? I wouldn't think so, though. Weird.
Re: Custom Web Chart
When using this with the pwm channels it uses the same color coding for both channels. Is there a way to change that?rimai wrote:I created a page for the new U-App that should work for your purpose:
http://forum.reefangel.com/status/appch ... &filter=t2
You can just append filters.
Thanks
Re: Custom Web Chart
Thanks, that looks better. The only weird thing (minor) is that on the legend it puts both, pwma & pwmd, for each line. It doesn't do this for temperature.rimai wrote:I changed it so it uses a random color.
Try it again.
Re: Custom Web Chart
It's fixed, thanks again. Really like my RA equipment and appreciate all you support Roberto.rimai wrote:It's a bug. Thanks for reporting.
I fixed it. Try again.
Re: Custom Web Chart
Wow, the random colors is awesome. Roberto, the only thing this doesn't do that the other web chart does is the link to download link and print (not so usefull...) Can you add the export option to this one? And at that point, does it makes sense to not just combine them to one?
Re: Custom Web Chart
I'll change the other one with the same capability, but with the export added to it.
Roberto.
Re: Custom Web Chart
Awesome, I hated having to use screengrab to download the graph
Re: Custom Web Chart
Just wanted to say the new charts have been great! And the database fix has been awesome! They load so quick now!!!
Quick question. How do you pull in data for a relay? Like can i map my heater port R6 with T1?
Quick question. How do you pull in data for a relay? Like can i map my heater port R6 with T1?
Re: Custom Web Chart
Whats the issue? You do it for the relay data chart already...
Re: Custom Web Chart
2 different charts and 2 totally different queries.
The problem is that you can pull filter=R, but you can't OR it to get specific ports.
The problem is that you can pull filter=R, but you can't OR it to get specific ports.
Roberto.
Re: Custom Web Chart
Isnt the chart software javascript? Couldn't you massage the result of R and OR it in the js before you process the chart? Another way would be to have a separate js/php/ whatever vb..net i think that would break R up in a usable format.
The problem for me is I dont follow how the graphs get the data
But I'm sure we can get some json/xml/output to do it, or am I missing something?
The problem for me is I dont follow how the graphs get the data
But I'm sure we can get some json/xml/output to do it, or am I missing something?
Re: Custom Web Chart
Data is collected through JSONP for each filter:
For example T1:
http:\\forum.reefangel.com\status\jsonp.aspx?id=reefangel&filter=T1
For example T1:
http:\\forum.reefangel.com\status\jsonp.aspx?id=reefangel&filter=T1
Code: Select all
You can see the JS that occurs in behind the scene:
[code]
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
<meta name="viewport" content="user-scalable=no, initial-scale=.5, maximum-scale=.5, minimum-scale=.5, target-densitydpi=device-dpi" />
<meta name="msapplication-tap-highlight" content="no" />
<link href='http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css' rel='stylesheet'>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src='http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js'></script>
<title>Reef Angel U-App</title>
<script type="text/javascript">
$(function () {
$.mobile.loading( 'show', {
text: 'Connecting to Portal',
textVisible: true,
theme: 'b',
html: ""
});
Highcharts.setOptions({
global: {
useUTC: false
}
});
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
seriesID = 0,
names = [
'T1'
],
colors = Highcharts.getOptions().colors;
$.each(names, function (i, name) {
$.getJSON('http://forum.reefangel.com/status/jsonp.aspx?id=reefangel&filter=' + name.toLowerCase() + '&callback=?', function (data) {
var pcolor;
var tname;
var ydec;
var yunit;
if (name == "PH") {
pcolor = '#669900'
tname = 'pH'
ydec = 2
yunit = 'pH'
}
else if (name == "PHE") {
pcolor = '#447700'
tname = 'pH Expansion'
ydec = 2
yunit = 'pH'
}
else if (name == "SAL") {
pcolor = '#000066'
tname = 'Salinity'
ydec = 1
yunit = 'ppt'
}
else if (name == "ORP") {
pcolor = '#330000'
tname = 'ORP'
ydec = 0
yunit = 'mV'
}
else if (name == "T1") {
pcolor = '#FF0000'
tname = 'Temp 1'
ydec = 1
yunit = '°'
}
else if (name == "T2") {
pcolor = '#FF8800'
tname = 'Temp 2'
ydec = 1
yunit = '°'
}
else if (name == "T3") {
pcolor = '#9900CC'
tname = 'Temp 3'
ydec = 1
yunit = '°'
}
else {
pcolor = getRandomColor()
tname = name.toUpperCase()
ydec = 0
yunit = ''
}
if (data.length) {
seriesOptions[seriesID] = {
dataGrouping: {
smoothed: true
},
name: tname,
color: pcolor,
tooltip: {
yDecimals: ydec,
ySuffix: yunit
},
data: data
};
seriesID++;
}
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if(data.length==0)
{
$('#container').html("No data to display");
$.mobile.loading( "hide" );
}
else
if (seriesCounter == names.length) {
createChart();
$.mobile.loading( "hide" );
}
});
});
// create the chart when all data is loaded
function createChart() {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
type: 'spline'
},
title: {
text: 'Reef Angel Controller Web Chart'
},
subtitle: {
text: 'Parameters logged for the past 7 days'
},
credits: {
enabled: false
},
legend: {
enabled: true,
//align: 'right',
//backgroundColor: '#FCFFC5',
borderColor: 'black',
borderWidth: 2,
//layout: 'vertical',
verticalAlign: 'top',
y: 100,
shadow: true
},
rangeSelector: {
buttons: [{
type: 'minute',
count: 60,
text: '1h'
}, {
type: 'minute',
count: 720,
text: '12h'
}, {
type: 'day',
count: 1,
text: '1d'
}, {
type: 'day',
count: 3,
text: '3d'
}, {
type: 'all',
text: '7d'
}],
selected: 2,
inputEnabled: false
},
navigator: {
xAxis: {
type: 'datetime',
maxZoom: 3600000, // 1 hour
dateTimeLabelFormats: { // don't display the dummy year
second: '%I:%M:%S %p',
minute: '%I:%M %p',
hour: '%b/%e',
day: '%b/%e',
week: '%b/%e'
}
}
},
xAxis: {
type: 'datetime',
maxZoom: 3600000, // 1 hour
dateTimeLabelFormats: { // don't display the dummy year
second: '%I:%M:%S %p',
minute: '%I:%M %p',
hour: '%I:%M %p',
day: '%b/%e',
week: '%b/%e'
}
},
yAxis: {
plotLines: [{
value: 0,
width: 1,
color: 'silver'
}]
},
exporting: {
url: '/export/index.php',
filename: 'Reef Angel Web Chart T1'
},
tooltip: {
borderColor: 'silver',
xDateFormat: '%A, %b %e, %l:%M %p',
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>'
},
series: seriesOptions
});
}
});
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
</script>
</head>
<body>
<script type="text/javascript" src="http://forum.reefangel.com/js/highstock.js"></script>
<script type="text/javascript" src="http://forum.reefangel.com/js/modules/exporting.js"></script>
<div id="container" style="height: 500px; min-width: 600px"></div>
</body>
</html>
Roberto.
Re: Custom Web Chart
So wouldn't you just need jsonp.aspx to have a function to reformat the data if the filter is a relay filter? and then it would just output the R1, R2, R3 etc in the json output?
Re: Custom Web Chart
This is where devs may get confused. Not so much for end users. They never get to see this... But, R1 is actually the variable used for Expansion Box 1 status of all 8 ports and not port 1 of the main box.
I guess you could consider that devs would have a better understanding and not get confused, huh?
I guess you could consider that devs would have a better understanding and not get confused, huh?
Roberto.
Re: Custom Web Chart
Yeah I was just confusing myself in the reply, but I know the variables.
What I do in my php is break that down to separate varaibles for each relay and do the bitwise masks etc to see if they are actually on/off. It's a lot of extra work
What I do in my php is break that down to separate varaibles for each relay and do the bitwise masks etc to see if they are actually on/off. It's a lot of extra work
Re: Custom Web Chart
I use the following:
$R=$xml->'{R}';
$RON=$xml->{'RON'};
$ROFF=$xml->{'ROFF'};
$RBIN=getBin($R);
$RMASK=applyMasks($R,$RON,$ROFF);
then I have:
$relay1val=$RBIN[7];
$relay1status=$RMASK[7];
..
..
Where relay1val is the auto value for the relay and the relay1status is the actual status of the port.
getBin returns the binary string of the number and applyMasks does the same bitwise operations we do to resolve RelayData and RelayMaskOn/RelayMaskOff.
I can send you (or it's linked in my custom portal page) the php I'm using if it would be helpful...
$R=$xml->'{R}';
$RON=$xml->{'RON'};
$ROFF=$xml->{'ROFF'};
$RBIN=getBin($R);
$RMASK=applyMasks($R,$RON,$ROFF);
then I have:
$relay1val=$RBIN[7];
$relay1status=$RMASK[7];
..
..
Where relay1val is the auto value for the relay and the relay1status is the actual status of the port.
getBin returns the binary string of the number and applyMasks does the same bitwise operations we do to resolve RelayData and RelayMaskOn/RelayMaskOff.
I can send you (or it's linked in my custom portal page) the php I'm using if it would be helpful...
Re: Custom Web Chart
I guess we better off calling it just like in our libraries.
Port1-Port8, Box1_Port1-Box1_Port etc
Sent from my Galaxy S5 with Tapatalk
Port1-Port8, Box1_Port1-Box1_Port etc
Sent from my Galaxy S5 with Tapatalk
Roberto.