Listening to a RFM69 Radio with Python
This post follows on from my last post on how to connect a RFM69 radio module directly to a Raspberry PI (RPI).
So, we have a radio (RFM69HCW) connected to a RPI and we want to listen for incoming messages and then act on them, performing some task. In this post we are going to look at how you can forward messages from an RFM69 network to a RESTful API. HTTP requests can be slow and we need to consider how to manage possible delays. If we block the radio receiver loop while making the necessary HTTP request, then time critical messages will be forced to wait!
We could solve this problem in a number of ways. In this post we are going to use Asyncio. It’s worth mentioning here that although Asyncio is often touted as the wonder child of Python 3, asynchronous processing is not new to Python. More importantly, Asyncio is not a silver bullet and depending on your task may not be the best solution. I am not going to go over old ground talking about the pros and cons of async vs sync or concurrency and parallelism, Abu Ashraf Masnun has a nice article called Async Python: The Different Forms of Concurrency which I think covers this topic well.
Having said this, the task of forwarding messages to an API is a good fit for Asyncio and it is also a good excuse to play with some cool new libraries. We will get on to them later, but first we need to prepare our RPI.
Prepare the Raspberry Pi
The first thing we need to do is make sure SPI and GPIO access is enabled on our RPI. To do this, open a terminal, SSH into the RPI:
ssh pi@raspberrypi.local
and open the configuration tool:
sudo raspi-config
From the menu select “Interface options” and then using the sub-menu enable “SPI” and “Remote GPIO”.
Prepare a sensor node
In order to test the radio we need a companion sensor node to transmit and receive data. I am going to use an Adafruit RFM69 Feather, but the code can easily be adapted to other board types.
You will need to install LowPowerLabs’ RFM69 library. Details of how to do this can be found in their Github repository’s readme file.
Next, grab my example node code and upload it to your Feather. This code will periodically send messages to the node with an ID of 1 and listen out for messages sent to Node 2.
Raspberry Pi RFM69 Test Code
Finally we can test our hardware! SSH into your RPI and if you are using a virtual environment then activate it and install the RFM69Radio library:
pip install rpi-rfm69
This is a library I created and is largely based on the work of Eric Trombly, who created a Python port of the LowPowerLabs RFM69 C library. All I have tried to do is make the API more Pythonic. Here is a small test script for receiving and sending data, upload and tun it on your RPI.
Hopefully at this point you are seeing packets from the sensor node scrolling past.
Building an RFM69 to RESTful API Gateway
As I mentioned, we are using Asyncio (introduced in Python 3.5) to interleave processing tasks with listening to the radio. To do this we need an asynchronous HTTP client. Once again the Talk Python Podcast comes to the rescue - in an interview with Pawel Miech the aiohttp library was brought to my attention. Using this library in combination with RFM69Radio gives us:
The destination url is set to http://httpbin.org/post
. This is a free online service which will echo back the post data sent to the service. It has a whole host (pardon the pun) of other tools for testing HTTP clients.
So let’s get this up and running. First off, we need to install the necessary libraries.
pip install rpi-rfm69 pip install aiohttp pip install cchardet pip install aiodns pip install spidev pip install RPi.GPIO
as a one liner:
pip install rpi-rfm69 aiohttp cchardet aiodns spidev RPi.GPIO
Navigate to where you want to run the code and create a new Python file and copy and paste the code above. Alternatively you can run the following commands to copy it from my snippets.
pip install getgist getgist jkittley rfm69_async_rxtx.py
Finally, run the command below to execute the script.
python rfm69_async_rxtx.py