Especially for Andy Piper who put out a plea for help,
Save the following to ~/bin/httprc
#!/bin/sh links http://en.wikipedia.org/wiki/HTTP_code#$1
Run as follows:
$ httprc 200
This will jump straight to the http return status explanation
Especially for Andy Piper who put out a plea for help,
Save the following to ~/bin/httprc
#!/bin/sh links http://en.wikipedia.org/wiki/HTTP_code#$1
Run as follows:
$ httprc 200
This will jump straight to the http return status explanation
This week I had a day out of the office to go to Zurich to talk at this years IBM developerWorks Days. I had 2 sessions back to back in the mobile stream, the first an introduction to Android Development and the second on MQTT.
The slots were only 35mins long (well 45mins, but we had to leave 5 mins on each end to let people move round) so there was a limit to how much detail I could go into. With this in mind I decided the best way to give people a introduction to Android Development in that amount of time was to quickly walk through writing reasonably simple application. The application had to be at least somewhat practical, but also very simple so after a little bit of thinking about I settled on an app to download the latest image from the web comic XKCD. There are a number apps on Google Play that already do this (and a lot better) but it does show a little Activity GUI design. I got through about 95% of the app live on stage and only had to copy & paste the details for the onPostExecute method to clear the progress dialog and update the image in the last minute to get it to the point I could run it in the emulator.
Here are the slides for this session
And here is the Eclipse project for the Application I created live on stage:
http://www.hardill.me.uk/XKCD-demo-android-app.zip
The MQTT pitch was a little easier to set up, there is loads of great content on MQTT.org to use as a source and of course I remembered to include the section on the MQTT enabled mouse traps and twittering ferries from Andy Stanford-Clark.
Here are the slides for the MQTT session:
For the Demo I used the Javascript d3 topic tree viewer I blogged about last week and my Raspberry Pi running a Mosquitto broker and a little script to publish the core temperature, load and uptime values. The broker was also bridged to my home broker to show the feed from my weather centre and some other sensors.
As part of writing my talks for the developerWorks Days Zurich conference next week I’ve been working on some code for the demo in the MQTT session. I was looking for a nice way to display a MQTT topic structure and the most recent value posted to topic.
In the past I have used a plugin to the freemind mindmap tool that plots the topics as and their values. This worked well but it does require a machine with Java and a very old version of freemind to make it work so it was time to see if there was another approach.
Nick O’Leary had created a neat little python MQTT to Websockets* bridge that we have been using round the office for a while and there are some really great javascript visualisation libraries out there now, so I thought I would see how hard it would be to run up a browser based version.
Starting with the d3 Collapsible Tree Layout example seamed like a good idea and it didn’t take too long to tweak it a little to make it dynamically add new topic branches when a message was received.
function addNode(topic, body) { var parts = topic.split("/"); if (root.children[0]===undefined){ var newnode = {"name": parts.shift(), "children":[]}; root.children = [newnode]; walk(parts,newnode,body); } else { walk(parts,root,body); } update(root); } function walk(parts, node, body) { if (parts.length != 0) { var current = parts.shift() if (node.children && node.children.length != 0) { var z=0; for(z=0; z < node.children.length; z++) { if (node.children[z].name == current) { walk(parts,node.children[z], body); break; } } if (z == node.children.length) { var newnode = {"name": current, "children":[]}; node.children.push(newnode); walk(parts,node.children[z],body); } } else { var newnode = {"name": current, "children":[]}; node.children = [newnode]; walk(parts,node.children[0],body); } } }
I also swapped out the where the data was loaded to use a static root rather than loading it from a json file on the server.
var root = {"name": "/","children": []}; root.x0 = h / 2; root.y0 = 0; update(root);
This worked pretty well so next I set about looking to see if I could add the payload of the message. To do this I added a data field to the json object for each node when populating the tree.
function walk(parts, node, body) { if (parts.length != 0) { var current = parts.shift() if (node.children && node.children.length != 0) { var z=0; for(z=0; z < node.children.length; z++) { if (node.children[z].name == current) { walk(parts,node.children[z], body); break; } } if (z == node.children.length) { var newnode = {"name": current, "children":[]}; node.children.push(newnode); walk(parts,node.children[z],body); } } else { var newnode = {"name": current, "children":[]}; node.children = [newnode]; walk(parts,node.children[0],body); } } else { console.log("body"); node.data = body; } }
Then updated where the SVG is inserted to add a text element in the right place.
... nodeEnter.append("svg:text") .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) .attr("dy", ".35em") .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .text(function(d) { return d.name; }) .style("fill-opacity", 1e-6); // Add message payload nodeEnter.append("svg:text") .attr("class","data") .attr("x", 10) .attr("y", 10) .attr("dy", ".35em") .text(function(d) { return d.data || ""; }) .style("fill-opacity", 1); // Transition nodes to their new position. var nodeUpdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); ...
Again this worked very well, except that it would not update the payload value after adding the first version. I tried a number of things to get this to work, but didn’t get very far, until James Thomas pointed me at this page about how some of the internals of d3 work. It talks about entry, update and exit methods to work on new, existing and removed elements in the data. There are examples of entry and exit functions in the example so I tried adding an update method but kept getting errors that it wasn’t found. I went back and had another look at the examples in the page James had linked to and noticed that update code doesn’t actually use a functions.
... // Add message payload nodeEnter.append("svg:text") .attr("class","data") .attr("x", 10) .attr("y", 10) .attr("dy", ".35em") .text(function(d) { return d.data || ""; }) .style("fill-opacity", 1); // Update payload if changed var nodeChange = node.selectAll("text.data") .text(function(d) {return d.data || "";}); // Transition nodes to their new position. var nodeUpdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); ...
An that was basically it. I’ve added a bit more code to update values when the tree branches are collapsed and to trim payloads to no more than 20 chars so the display is not too cluttered. I’m planning on improving the style sheet a little soon and possibly adding an effect so you see which payloads have been updated recently and maybe add hover text with the full payload for the shortened ones.
You can see the whole thing running here
* There is also some work being done to support Websockets with the Mosquitto MQTT broker, you can see the testing page here