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