Category Archives: python

Pachube dashboard brewery, with pygame and stomp

I send a bunch of data from my sensor network _to_ pachube, but this post is about using pachube as a data _source_ They have this app called a dashboard, which basically gives you some knobs and switches, that are hooked up as live inputs to a pachube data stream.

So, that got me thinking, here was a process control GUI pretty much done for me. The permissions are a bit wonky, so I’ll only include a picture here, but basically I get a knob for a set temperature, and a button to turn an alarm on or off. (I can add lots more, but this is all I’ve got set up so far)
Pachube Dashboard control panel

Neat, but now what? Well, the pachube api is pretty easy, so I just hooked up yet another consumer to my local network, (sensor data is dumped into a stomp/activemq message bus here, so that I can have infinite consumers of the data, without ever having to touch the code on my sensor nodes) that pulls data not just from the local network, but also from this pachube dashboard’s feed.

Add a little bit of pygame hackery so I can play sounds, and now I have a heating/cooling warning system for the kettle in the kitchen.

Example output

2011-01-22 11:05:08,649 INFO main - Current temp on probe is 31
2011-01-22 11:05:08,650 DEBUG main - threshold is 74, mode: heating
2011-01-22 11:05:08,650 INFO main - Turning music off.... we're below the threshold
2011-01-22 11:05:13,364 INFO main - Current temp on probe is 32
2011-01-22 11:05:13,365 DEBUG main - threshold is 74, mode: heating
2011-01-22 11:05:13,365 INFO main - Turning music off.... we're below the threshold
2011-01-22 11:07:01,408 INFO main - Current temp on probe is 33
2011-01-22 11:07:01,409 DEBUG main - threshold is 74, mode: heating
2011-01-22 11:07:01,409 INFO main - Turning music off.... we're below the threshold
2011-01-22 11:07:01,409 INFO main - Fetching current dashboard values from pachube, incase they've changed

This is far from any sort of automatic brewery, and was more an experiment in what was possible, and how easily. And it’s still a lot better than having me walk over to the kitchen every 5 minutes to check the current temperature. Now I can just turn the stove on, and get back to serious time wasting on the internet!

Source is over at github, https://github.com/karlp/karlnet/blob/master/consumers/pachube/consumer.pachube.dashboard.py

Things I found:

  • Pachube dashboard only updates if you drag the knobs. Using direct entry doesn’t update the datastream
  • Playing sounds from python is easy, but only when you find the right library, and only when you guess at the documentation a lot. I’ve no idea if this works on windows or osx. I tried a lot of other ways first, all of which failed miserably.

Pachube exporting now in place

Pachube is an interesting looking site. They don’t really seem to have all that many users, but hey, if they’re going to graph all my data for me, cool. It’s not exactly top secret information. I still don’t have things like the (new!) humidity sensor calibrated, but hey, it’s uploading, and it’s graphing.
TinyTemp has the initial atTiny85 based temperature sensor, and FreqyTemp has the new mega328 based temperature and relative humidity sensor. (more on that still to come)

The max/min values are off from some errors I was getting while I was setting this up, but hey, the more data exports the better right?
Github has the code

stomp: more with less. Publishing for the masses, rather than doing everything yourself

The early prototype head end software for karlnet did all the decoding of the wireless frames, and also handled doing something with the data, in that case, sticking it all into RRD databases so that tools like Cacti could make me some pretty graphs of the temperature. Now, that sort of architecture doesn’t scale very well, and it was about to become quite a pig when I started adding more nodes.

I already had more things I wanted doing, I wanted webpages, I wanted to try out some different RRD graphing engines (cacti is a bit of a pig to configure, but it does make nice graphs)

What I really wanted was to put all the hard work of reliably slurping data off the xbee network into one place, and put all the user applications that use that data somewhere else. (Reliably reading off the xbees is the topic of another post)

I’d been very happy with python for the serial decoding so far, but I certainly didn’t want to restrict myself to just python. I also wanted to make sure that anyone who wanted to could write an application using the data, not just me. A message bus was exactly what I wanted, and although it’s a little bit of a “big enterprise buzzword” it really doesn’t have to be. Or at least, you don’t have to be scared by it.

Stomp is one of the simpler, lighter weight message bus protocols. With a suitable “broker” (the name of the magic blob of software that handles all the messages) you can quite easily publish a message, like, “node:1, sensorA: 19 degrees Celsius” and then _anyone_ else who had registered that they were interested in receiving temperature readings would be delivered a copy of the message. Whether there was one listener, or one hundred.

With the 5 second pub/sub overview out of the way, how did I do it?

ActiveMQ is a well established solid player in the message bus world, and although traditionally associated with JMS messaging, it also has built in stomp support. Surprisingly, there was no package for activemq for ubuntu 9.10, but the installation is straightforward (some new skills learnt will go in another post) and then the instructions for enabling stomp are very clear.

Now, trying it out! I use stompy for python support. I also tried stomp.py, but it did nasty things like swallowing keyboard interrupts, so you couldn’t kill your scripts with ^C. I don’t recommend it. I simply tried it first :(

Stompy was easy!

import random, time
from stompy.simple import Client
stomp = Client("hostname of activemq/stomp")
stomp.connect()
while True:
     stomp.put("fake sensor1: %d" % random.randint(0,50), destination="/topic/karlnet")
     time.sleep(5)

Tada! And likewise for any receiver…

....
stomp = Client("hostname")
stomp.connect()
stomp.subscribe("/topic/karlnet")
while True:
     message = stomp.get()
     print "hohoho, we got some sensor readings: " + message.body

Now that’s cool, but we’re only sending fixed strings there, we want real objects! We need to be careful not to use anything python specific here, because we can’t control (and don’t want to control) who’s listening at the other end. XML or JSON are probably the simplest choices here, though you could come up with your own custom scheme here, even just manual string parsing, if you were you were really masochistic.

I chose JSON, mostly because my day job has enough XML, and JSON seems like a perfectly reasonable alternative. The python standard library json might be enough for you, but my message format is an object, not a dictionary of key/values, so I had to use jsonpickle

So, the final shiny fake sender / receivers are in svn, and in the same consumers/producers directories, you can see the two real apps, the main producer, reading data from the base station Xbee, and a simple script that updates RRD databases. That code is beautifully simple now that it’s been extracted out of the nitty gritty of the sensor network code.

Finally, for an example of what can be done now that we live in the future, have a read of Stomp on WebSockets and perhaps even a look at consumers/simple_web in svn.