Single Page Responsive Web Apps using JavaScript , jQuery and Bootstrap

The ThingSpeak Web Page does not allow you to pull historical data from your channel, plus simple things like converting Absolute Pressure to Mean Sea Level Pressure require running Matlab Scripts.

I decided to create a single page web app that had the features I required. I ended up with the following features:

  • Cross platform/browser
  • Responsive (usable on my 24″ monitor, tablet and phone)
  • Customizable graphs (color, type etc)
  • Ability to select multiple days/weeks
  • Ability to select last minute/hour/day
  • Sea Level Pressure Conversion Built in
  • Auto summation for rain graphs by interval
  • Auto update graphs to get latest data

The web app needs to request data from api.thingspeak.com which is a different domain to the domain where the web app is hosted. To do this I created a route in Ktor which accepts a JSON request and responds with the contents of the request.

post("/getJSON") {
            val thisReq = call.receive()
            val req = khttp.get(thisReq.url)
            println(thisReq.url)
            if (req.statusCode == 200) {
                call.respond(req.jsonObject)
            } else {
                call.respond(json { "success" to "false" })
            }
        }

I understand this could be potentially abused as this is a effectively an anonymous router, but I am not worried just yet.

To access this in JavaScript:

var thingSpeakQuery = `https://api.thingspeak.com/channels/${feedID}/feeds/last.json`;
var getJSONThingSpeak = {
	"url": thingSpeakQuery
};
$.ajax({
	type: "POST",
	url: "/getJSON",
	data: JSON.stringify(getJSONThingSpeak),
	contentType: "application/json; charset=utf-8",
	dataType: "json",
	success: function (element) {
		// code here to handle data
	},
	failure: function (errMsg) {
		alert(errMsg);
	},
	// catch internal server error, this happens when the server can't pass the JSON data,
        // or the ThingSpeak ID is invalid
	statusCode: {
		500: function () {
			console.log("Query returned no data.");
		}
	}
});

Here I am using an AJAX function to get the latest data from the specified ThingSpeakID.

The rest of the web is pretty much standard JavaScript and relies heavily on jQuery to update the web page. The JSON data structures get pretty complicated. In order to debug/test the code while I was writing it I made the returned JSON data a global variable and used Chromium’s Dev Tools to write the code.

For example here where are looping through all the Charts and adding the ThingSpeak data:

thisData.map.feeds.myArrayList.forEach(function (element) {
                // loop over each data field in ThingSpeak data
                for (var k = 0; k < chartList.length; k++) {
                    // store as a tmp string, as not to change with 'k'
                    var tmp = k + 1;
                    weatherCharts[k].data.datasets[0].data.push({
                        x: moment(element.map.created_at),
                        y: parseFloat(element.map["field" + tmp.toString()])
                    });
// snipped

The above would be very difficult to write by hand, or get working by trial and error. Being able to run the code in the browser and make things instantly change was actually a lot of fun.

JavaScript is fast becoming my favorite language, not due to it’s technical merits but due to the fact it allows we to be vendor agnostic. I can run my code on my FreeBSD/Linux/Android/Windows/Mac/iPhone hardware.

The coolest feature, is the auto update feature. It allows me to leave the browser window open on my computer and have a live stream graph of my weather station without having to continuously hit the refresh button!

It’s pretty simple, it just uses a JavaScript interval function:

setInterval(function () {
    // This will be executed every 60 seconds
    getLatestWeatherForWeatherCharts();
    }, 60000);

You can use the web app here.

opens3.net_weatherstats.html

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s