Sending RF12 packets over UDP

As I mentioned in a recent post, the collectd approach fits right in with how wireless RF12 broadcast packets work.

Sounds like a good use for an EtherCard + JeeNode pair (or any other ENC28J60 + RFM12B combo out there):

The idea is to pass all incoming RF12 packets to Ethernet using UDP broadcasts. By using the collectd protocol, many different tools could be used to further process this information.

What I did was take the etherNode sketch in the new EtherCard library, and add a call to forwardToUDP() whenever a valid RF12 comes in. The main trick is to convert this into a UDP packet format which matches collectd’s binary protocol:

The sendUdp() code has been extended to recognize “multicast” destinations, which is the whole point of this: with multicast (a controlled form of broadcasting), you can send out packets without knowing the destination.

The remaining code can be found in the new JeeUdp.ino sketch (note that I’m now using Arduino IDE 1.0beta2 and GitHub for all this).

It took some work to get the protocol right. So before messing up my current collectd setup on the LAN here at JeeLabs, I used port 25827 instead of 25826 for testing. With JeeMon, it’s easy to create a small UDP listener:

And sure enough, eventually it all started to work, with RF12 packets getting re-routed to this listener:

Now the big test. Let’s switch the sketch to port 25826 and see what WireShark thinks of these packets:

Yeay – it’s workin’ !

The tricky part is the actual data. Since these are raw RF12 packets, with a varying number of bytes, there’s no interpretation of the data at this level. What I ended up doing, is sending the data bytes in as many collectd 64-bit unsigned int “counter values” as needed. In the above example, two such values were needed to represent the data bytes. It will be up to the receiver to get those values and convert them to meaningful readings. This decoding will depend on what the nodes are sending, and can be different for each sending JeeNode.

I’ve left the original web browser in as well. Here is the “JeeUdp” box, as seen through a web browser:

(please ignore the old name in the title bar, the name is now “JeeUdp”)

It’s not as automatic out of the box as I’d really like. For one, you have to figure out which IP address this unit gets from DHCP – one way to do so is to connect it to USB and open the serial console. The other bit is that you need to configure the unit to set its name, the UDP port, and the RF12 settings to use. There’s a “Configure” link of the web page to do this – a some point, I’d like to make JeeMon aware of this, so it can do the setup itself (via http). And the last missing piece of the puzzle is to hook this into the different drivers and decoders to interpret the data from these UDP packets in the same way as with a JeeLink on USB.

Re which IP address it has, can’t you tell that from the UDP packet it sends? I know UDP is stateless, but surely it has a sender field in the header? Tie that up with the JeeNode ID which in the RF12 header you forward and Robert is your father’s brother.

Yup – that’s the idea. It’s basically ZeroConf / Bonjour / Rendezvous via collectd-style UDP, and it solves the issue of figuring out the IP address issued by DHCP. Until you plug in two boxes at the same time… then you won’t know which is which.

If we could somehow have a unique serial number for each jeenode (maybe stored in eeprom) so that identification is via the serial, not ip. that way the ip is just for the network transport, the serial is the end to end identification, irrespective of the transport medium be it udp, tcp or rf12.

Good thinking. The IP address may not always remain the same. I think ID’s need not be pre-assigned though. One idea would be to use the MAC address (this just moves the issue). Another idea would be to allow storing a more descriptive name when the box is seen for the first time (it would come with a fixed name initially). Even the MAC address could come as a fixed one, requiring a change before further use (store in EEPROM and reboot the unit).

Ah, wait… I misread your comment. End to end to all the JeeNodes. Yes, that would be very convenient. Same issue, different level. Both will be needed: being able to talk to a specific JeeUdp box, and being able to identify each JeeNode. Here too, I’d like to avoid pre-arranged unique ID’s – it’s less work if all the nodes can start out identically. Sounds doable, since RF12 supports broadcasts – we just need some conventions for the initial conversation.

As Wayne points out, the problem of putting two RFM12 devices on the network at the same time and telling them apart is not a new one.

I wonder if there is a reliable way we could get devices to auto-assign themselves a unique ID when they first join “the RF mesh”? Or maybe an RF12 version of DHCP (although that gets a little tricky without a unique MAC to route a reply to)… Hmmm… The more I think about it, the more like fun it sounds!

I’ve been building a network of RF nodes in a similarish fashion to the JeeNodes, but principally at the moment for temperature logging. So each node has a DS18B20 OneWire temp sensor.

OneWire devices all have a globally unique 48bit id – thus its a no-brainer to include that id in all packets.

Incidentally my nodes use the RFM02 (TX only) and I simply send each packet’s data again at the end of the next few packets (each packet is large enough for 3 or 4 copies of the data and a sequence counter), so if a few get lost occasionally the data gets through – perhaps a trick that you could use with UDP too?

Is that similar to xAP? A jeenode with ethernet plug to act asa xAP master controller, that will be fantastic. Will allow interconnection with loads of other home automation devices/software and possibility to both report and control the jeenodes as there are different types (clasess) of messages. There is even a library for xAP (i m on movile at the moment and unable to provide a link).

A xAp controller can send xAp commands to any targeted xAp enabled device on the network. In this case JeeMon can act as a master controller and send commands to both jeenodes or other xAp enabled devices. If will be to compare, I would say that is similar to Modbus. There are few good application to startwith: xAp Hub, xAp Floorplan (this is how a Jeerev control tab could look like). The xAp message has a source a target and a class plus a unique ID for each node ( by node I reffer here to each input or output of a Jeenode ). Not sure I was very coherent as I have not slept in 30 hours, but what I try to say is that xAp can easely address the indentification part in the network plus the advantage to integrate multiple platforms/devices in a single system – Jeerev can be the brain of the automated house and have sensors connected via rf12 and lan/ internet.

Ok, somehow awake, maybe will make more sense:
– if a box is connected to lan in a remote location and receives data(rf12) from multiple jeenodes active at that location(i.e. building level), then the box can send the incoming rf data via UDP as a xAp message like this:
xap-header
{
v=12
hop=1
uid=FF123400
class=xap-temp.notification
source=jeenode.ethernet.boxnumber.jeenodenumber.jeenodedatatype
}
jeenodedatatype.current
{
jeenodedatatype=25
units=C
}
in this case the jeenodedatatype will be temperature reading.
On the JeeRev/JeeMon part the incoming data will be decoded and device value/status will be updated.
The box will only translate the incoming data into xAp and send it over UDP, all the magic will be done by the JeeMon.
Ofcourse more can be addedd as xAp works both ways: a relay on a certain Jeenode can be targetet and the ethernet box will translate the incoming xAp message in rf12 and send it to the node.
Few good sources of info:
http://www.xapautomation.org/index.php?title=Protocol_definition
and:
http://code.google.com/p/livebox-hah/source/browse/trunk/userapps/?r=211#userapps%2Farduino%2Flibraries
xAp library and few examples.