Custom Web Chart

Related to the Portal
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

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.
Roberto.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

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?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

Data is collected through JSONP for each filter:
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.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

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?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

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?
Roberto.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

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 :)
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

Do you have specific names for them?
Roberto.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

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...
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

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
Roberto.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

That would be intutitive :)
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

rimai wrote: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.
I've had a bash at doing this in javascript. I haven't tried it with highcharts yet, but it works with a my modified version of your webcharts using d3.

See http://arch1.github.io/RA_CustomCharts/

and

https://github.com/arch1/RA_CustomCharts


The RFW plot is a good example of plotting data gaps.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

Very nice. The only thing you're missing is the mouse-overs to see the details.
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

Yes - I'll put on that on the todo list (along with plotting individual relays - maths was easier than I thought it would be).

I've made the charts scrollable in this version (still needs a bit of tidying up - but tooltips shouldn't be too hard):

http://bl.ocks.org/arch1/5c63a184ca638b291df7

(best viewed in new window)
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

That is really cool. Can we overlap multiple filters? Thanks for showing the HTML in that. I was able to copy that over to my server and switch it to my ID. FYI Celsius to Fahrenheit was a pain but not too bad.
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

I'm planning to add multiple filters - but it will take me a while - this is already a major stretch of my javascript/d3 capabilities.

While there are plenty of examples around ( http://bl.ocks.org/mbostock/3884955, http://www.d3noob.org/2014/07/d3js-mult ... matic.html) adding extra features without breaking existing ones is proving a challenge...
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

lnevo wrote: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?
Here's my first crack at plotting individual relay data from the decimal representation:

http://bl.ocks.org/arch1/9178a77aea3d5775897a

the plotting code isn't very elegant yet (it's hard-coded to main relay and expansion relay box only) - but seems to work OK (with data gaps dealt with too).
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

Awesome
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

AlanM wrote:Right. Is it because you use highstock.js instead of highchart.js? I wouldn't think so, though. Weird.
I can't work out how highcharts deal with irregular data either. Others have lobbied so far ? unsuccessfully for changes re data gaps:
http://forum.highcharts.com/highstock-u ... age15.html
User avatar
arch
Posts: 20
Joined: Sun Mar 10, 2013 12:22 am

Re: Custom Web Chart

Post by arch »

lnevo wrote:Very nice. The only thing you're missing is the mouse-overs to see the details.
Tooltips added in this version (I'm sure this code could be written in a fraction of the number of lines).

http://bl.ocks.org/arch1/d220e06fc3dcc4ea6d82
saf1
Posts: 111
Joined: Thu Jun 28, 2012 1:46 pm

Re: Custom Web Chart

Post by saf1 »

Not sure I understand how the portal charts are supposed to work. I wanted to see how the wave maker was working with regards to my tide code and both PWMA and PWMD are both showing activity - or something with regards to plots in the chart.

Yet on the tank I can clearly see only one RW spinning up and the PWM D at 65% while the PWM A is at 0. What is the web chart actually plotting or do I need to enable something else. I was trying to see if it actually slowed down at night and if the left and right side alternated and at what time. Now I'm totally lost :)

Thanks.
-scott

http://forum.reefangel.com/status/chart ... ilter=PWMA
http://forum.reefangel.com/status/chart ... ilter=PWMD
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

The portal plots data every 5 minutes.
For fast wavemaking, you won't be able to see it in the chart.
Roberto.
saf1
Posts: 111
Joined: Thu Jun 28, 2012 1:46 pm

Re: Custom Web Chart

Post by saf1 »

rimai wrote:The portal plots data every 5 minutes.
For fast wavemaking, you won't be able to see it in the chart.
Ok. That makes sense. However, what I am seeing is both PWM A and D showing data and/or a pattern when the ReefAngel Client and physical RW in question is off. I'm not sure what data it is actually plotting then.

The tide code I have running now is:
if (tide.isIncoming()) {
ReefAngel.DCPump.DaylightChannel = None;
ReefAngel.DCPump.ActinicChannel = AntiSync;
}
else {
ReefAngel.DCPump.DaylightChannel = AntiSync;
ReefAngel.DCPump.ActinicChannel = None;
}

Then under the ///// Place your custom code below here I have:
ReefAngel.DCPump.SetMode( ReefCrest,45,10 );
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

It's plotting the reefcrest wave form.
It is a random waveform, just like what you see in the chart.
Every 5 minutes, the controller sends data. Whatever happens in between those 5 minutes won't be shown in the chart.
Roberto.
saf1
Posts: 111
Joined: Thu Jun 28, 2012 1:46 pm

Re: Custom Web Chart

Post by saf1 »

rimai wrote:It's plotting the reefcrest wave form.
It is a random waveform, just like what you see in the chart.
Every 5 minutes, the controller sends data. Whatever happens in between those 5 minutes won't be shown in the chart.
Ok, I understand that. I guess the error is on my part somewhere then because what I was trying to figure out is why the graphs for PWM A and D are both showing data when only one is actually running. In this case PWM D.

I was assuming that tide.isIncoming with the if/else would power PWM D and have A set to off (that is actually what is running now). Then when the tide is outgoing it would swap D to off and A to on. So when I saw the graphs showing data for both it didn't make any sense to me. I've also only seen the PWM D running using this function so clearly I have something wrong.

Back to the drawing board :)
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

Ahh. Now I understand what you were asking.
The reason I think you are not getting a true representation of what is happening is because the graph won't lot zeros.
If you look at the chart for PWMA, the last plot was Thursday 1:45pm and then, it jumps to Friday 3:05pm. It doesn't show the zeros for that time frame in between.
Roberto.
saf1
Posts: 111
Joined: Thu Jun 28, 2012 1:46 pm

Re: Custom Web Chart

Post by saf1 »

rimai wrote:Ahh. Now I understand what you were asking.
The reason I think you are not getting a true representation of what is happening is because the graph won't lot zeros.
If you look at the chart for PWMA, the last plot was Thursday 1:45pm and then, it jumps to Friday 3:05pm. It doesn't show the zeros for that time frame in between.
Ok, that makes sense(the light bulb light :) ). And sorry that I wasn't clear in asking the question.
saf1
Posts: 111
Joined: Thu Jun 28, 2012 1:46 pm

Re: Custom Web Chart

Post by saf1 »

Actually, I think I have another error looking back at my code. If I set the ReefAngel.DCPump.DaylightChannel = None, that is applying no PWM signal, or 0(?)? Reading various threads today it appears the general thought is to leave them at 25 or so percent power?

If I truly wanted high and low tide or only one side performing the actual pattern then I'd probably need to disable/enable the relay box port with power. Or go back and use AntiSync/Sync unless the tidalSwell power it back up from 0.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Custom Web Chart

Post by lnevo »

Is there a URL I can use to get the Relay Data chart? Right now I'm using the filter R1 but would like to embed the Relay Data one that's on the portal instead.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

Not yet.
Let me see if I can get that done.
Roberto.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Custom Web Chart

Post by rimai »

See if it works now.
I added the ability to get single relays.
Use filter relayxy, where x is the relay box and the y is the port.
Examples:
relay2 - Main Box relay 2
relay15 - Exp Box 1 relay 5
Roberto.
Post Reply