This time, I'll explain a simple Python app that receives a string from a Xbee, decodes its header and then tweets the payload to a twitter account. I'm a complete Python newb so if you have suggestions on a better implementation, I'm all ears.
Here's basically what I've done. Heavily borrowed from mightyOhm and ladyada, this project receives data from Xbees in "the field". Using a unique header, the client app determines the payload destination which can be a tweet or a web service.
Mr mightyOhm has written a great series on hacking the Asus wl-520gu wireless router to build an open source wireless streaming internet radio receiver. If you haven't read thru Jeff's work, stop right now and read it. Now.
Ladyada's award winning tweet-a-watt takes data from a kill-a-watt, sends it to Xbee embedded in a hacked wl-520gu and then tweets it for the world to see how green you are. I've copied the Xbee connection from her and the idea of using Python. She didn't post her Python source, so I've had to stumble thru this. I just read tonite, that the tweet-a-watt project will be a project in Make Magazine, volume 18. [update] ladyada did post her source, I just missed it. Check out her good stuff here.
My tweet-a-w/e's spin is that any data generating thing (a "whatever") can be hooked to an Xbee in the field. Either directly to the Xbee or via an Arduino. The Xbee transmits to a receiving Xbee that has been wired into the serial port of a hacked Asus wl-520gu. The Python app running on the router reads the data and based on a unique header code, the payload is either tweeted or sent to a web service.
So I ended last time by showing a small snippet of Python that read the incoming data and printed it. Now let's modify that snip so it reads the first few characters and makes a decision of what to do. This first revision is pretty hackish and we'll improve on it as "whatevers" are added in the field. My opinion is get it working, then optimize.
Last time we installed Python but I didn't tell about the python-twitter wrapper from DeWitt Clinton. Here's what I did:
- Install simple JSON dependency
- wget http://pypi.python.org/packages/source/s/simplejson/simplejson-2.0.9.tar.gz
- gunzip simplejson-2.0.9.tar.gz
- tar xvf simplejson-2.0.9.tar
- python setup.py install
Mr Google has no clue about this error. Plenty of problems, but I couldn't find anything. I mucked with my LD_LIBRARY_PATH and considered rebuilding Python. Finally, I actually started looking at the source referenced in the trace. Here's what I found. Install OpenSSL and problems are solved. I wrote about my fun here.
# opkg updateAnd finally install python-twitter:
# opkg install openssl-util
- wget http://python-twitter.googlecode.com/files/python-twitter-0.5.tar.gz
- gunzip python-twitter-0.5.tar.gz
- tar xvf python-twitter-0.5.tar
- python setup.py install
I'm currently planning 4 whatevers that will be talking to the router:
- Xbee connected to my laptop via a SparkFun Xbee Explorer USB
- Maxim DS18B20 1-wire temperature sensor connected to an Arduino and an Xbee
- Nike+ receiver in a Serial Adapter connected to an Arduino and an Xbee
- Xbee in ADC (Analog-to-digital conversion) and digital I/O line passing.
I created an array to hold the whatever name, the unique header, the action to perform, and username/password:
# tweet-a-w/e stuff array # "whatever", header string, action, user, password # WE_ARRAY = [ ['WE_TEST', '', _tweet_it, 'username', 'password'], ['WE_TEMPERATURE', '', _web_it, 'username2', 'password'], ['WE_NIKEPLUS', '', _stalk_it, 'username3', 'password'], ['WE_XBEE', '0x7e', _tweet_it, 'username4', 'password'] ]The action array elements are functions to perform the tweet or web action. Here's what I defined:
# # define functions to do something with received data # # tweet data # def _tweet_it(data, twuser, twpass): # login to twitter print 'tweet w/' + twuser api = twitter.Api(username=twuser, password=twpass) api.PostUpdate(data) # web service data # def _web_it(data, twuser, twpass): # tbd print 'wrote to web service w/' + twuser # stalk the data # def _stalk_it(data, twuser, twpass): # tbd print 'watch it w/' + twuserOk, now let's read the data and determine what we got:
# open up the serial port on router # print 'opening serial port ' + SERIALPORT ser = serial.Serial(SERIALPORT, BAUDRATE, timeout=TIMEOUT) ser.open() # read data # try: print 'entering read loop' # loop forever while 1: # read it from serial port data = ser.read(NUMCHARS) if len(data) > 0: print 'Read: ' + data # loop thru our whatever array and see if we recognize the header for i in range(0, len(WE_ARRAY)-1): if data.startswith(WE_ARRAY[i]): print WE_ARRAY[i] + " action " + WE_ARRAY[i].__name__ WE_ARRAY[i](data, WE_ARRAY[i], WE_ARRAY[i]) break finally: print 'closing serial port' ser.closeThe only tricky thing in that code is the action call. Once we have a header match, the 2nd array element is one of the action functions that we defined. Simply call it and pass the data, username/password as arguments.
My Python client file is here.
Get your file on the router and start it:
root@OpenWrt:/opt/project# python XbeeReader.pyAnd send it something. For me, a quick test is to use another Xbee in the SparkFun Xbee Explorer. When I plug this in to my laptop, it shows up as /dev/ttyUSB0 so to write a quick string is as simple as:
d@hopper:~/projects/wl-520gu$ echo " Testing " + `date` > /dev/ttyUSB0And on the router telnet window, I see:
opening serial port /dev/tts/0I'm using a test twitter account and viola, the string " Testing" shows up like magic.
entering read loop
Read:  Testing + Thu Mar 26 23:30:47 EDT 2009
WE_TEST action _tweet_it
How are the Xbees configured? Real easy. I put ZNET 2.5 Router / End Device AT firmware version 1244 on both. I use Linux so using X-CTU was a little tricky until I figured out how to use it with Wine. I wrote about it here.
The Xbee in the router is named PINK. Last year, I built the NKC Xbee Shield Kit and goofed something up. When I installed the Xbee, it got really hot and the white Xbee label turned pink. It still works but is discolored. Here's the X-CTU file for PINK.
The Xbee connected to my laptop via the Xbee Explorer is named WHITE. Because it's not discolored. The config is EXACTLY same as PINK except for the name and destination. After loading the ZNET 2.5 Router / End Device AT firmware, I went to the X-CTU Terminal tab and typed:
+++Here's the X-CTU file for WHITE.
Plans for next time. Clean up the client so only the data is written to twitter and not the unique header. Then hook up the DS18B20 temperature sensor and start tweeting real data.
What do you think? Leave a comment.