Pachube provides an API-exposed store of sensor data from pretty much anything, but with a focus on sensor data. Â It’s free to use and has what seems to be a pretty complete, reasonably designed, and easy to use API with a nicely flexible authorization model.
I’ve been working on some code to scrape data out of the Netbotz web UI (which does not have an easy to use API) and, as I got to working on the data storage backend for the scraper, remembered Pachube and decided to give it a try rather than reinventing what was effectively the same wheel.
I have generally positive impressions of Pachube after a couple of days messing around with it. Â It was pretty easy to get going, and after stumbling into one quickly-fixed bug was up and sending data in from my prototype scraper pretty quickly.
I’m using the following python class to simplify the interaction. Â It’s trivial, but I didn’t see anything similar already done, so am throwing it here for future google results:
#!/usr/bin/python # This code is released into the public domain (though I'd be interested in seeing # improvements or extensions, if you're willing to share back). import mechanize import json import time class PachubeFeedUpdate: _url_base = "http://api.pachube.com/v2/feeds/" _feed_id = None _version = None ## the substance of our update - list of dictionaries with keys 'id' and 'current_value' _data = None ## the actual object we'll JSONify and send to the API endpoint _payload = None _opener = None def __init__(self, feed_id, apikey): self._version = "1.0.0" self._feed_id = feed_id self._opener = mechanize.build_opener() self._opener.addheaders = [('X-PachubeApiKey',apikey)] self._data = [] self._payload = {} def addDatapoint(self,dp_id,dp_value): self._data.append({'id':dp_id, 'current_value':dp_value}) def buildUpdate(self): self._payload['version'] = self._version self._payload['id'] = self._feed_id self._payload['datastreams'] = self._data def sendUpdate(self): url = self._url_base + self._feed_id + "?_method=put" try: self._opener.open(url,json.dumps(self._payload)) except mechanize.HTTPError as e: print "An HTTP error occurred: %s " % e
Usage is pretty straightforward. Â For example, assuming you have defined key (with a valid API key from Pachube) and feed (a few clicks in the browser once you’ve registered) it’s basically like:
pfu = PachubeFeedUpdate(feed,key) # do some stuff; gather data, repeating as necessary for any number of datastreams pfu.addDatapoint(<datastream_id>,<data_value>)) # finish up and submit the data pfu.buildUpdate() pfu.sendUpdate()
The resulting datapoints basically end up looking like they were logged at the time the sendUpdate() call is made. Â In my situation, I want to send readings from a couple of dozen sensors each into their own Pachube datastream in one shot, so this works fine. Â If, instead, for some reason you need to accumulate updates over time without posting them, you’d need to take a different approach.
recent comments