Ring-of-Things
Purpose
The purpose of the Ring-Of-Things is to use the openwsn firmware stack and the CoAP library to implement a simple demo where a 'ringmaster' (in this case a local python client), instructs motes via CoAP packet communication to do simple actions like blink or buzz.
Powerpoint of initial design: https://docs.google.com/presentation/d/1atlBdYjgV6HwVyvTbz42K-ek7jkmLHYt7oatlnUHvk0
Design
A CoAP app must be added to the firmware, called 'rrt', to allow for the ringmaster to send and receive CoAP packets to the resource. A tutorial for adding a CoAP app is described here: Adding a CoAP app
This app needs to have several functionalities:
- notify the ringmaster of a mote's availability (when it goes 'online')
- ability for a mote to wait for an incoming packet from the ringmaster
- checking for a message type upon reception, and knowing whether to 'blink', 'buzz', perform another simple action, or forward an action to another mote (identified via ipv6)
- ability to send a CoAP packet from itself to another mote (with some data)
The ringmaster needs to:
- send packets to motes via the coap library
- wait on incoming packets
- keep track of all motes that are in its ring (in this case with a simple queue) and send instructions in a rotation
- handle error handling - motes dropping off unexpectedly, packet loss, receiving unexpected packets
Code - firmware
The firmware code is the main addition (openwsn-fw), which runs on the motes.
Here is the firmware pull request: https://github.com/openwsn-berkeley/openwsn-fw/pull/128/
File Changed | Description |
---|---|
bsp/boards/python/openwsnmodule_obj.h | add rrt_vars_t struct to python OpenMote struct |
inc/opendefs.h | add ringmaster port constant on which to listen to and send ring master packets |
openapps/SConscript | add rrt as part of the default apps to be built with SCons |
openapps/openapps.c | add rrt_init(), the initialization function for rrt resource |
openapps/rrt/rrt.c | add rrt resource to openapps, with the code for handling all mote actions. A GET action sends confirmation to the ringmaster, a POST action accepts payloads and determines what to do next (forward, perform action, or nothing), and a DELETE (which unregisters a mote). rrt.c also defines a function sendCoAPMsg, which sends a char to either an address or a hardcoded ringmaster address |
openapps/rrt/rrt.h | define function signatures to be used outside of rrt.c, as well as the rrt_vars_t struct |
openapps/rrt/rrt.py | simple python program for testing python coap library functionality - no purpose other than coap library experimentation |
openstack/04-TRAN/opencoap.h | hardcoded ringmaster address added here |
openstack/04-TRAN/openudp.c | add switch blocks for the ringmaster port in openudp_receive and openudp_sendDone |
openstack/SConscript | add proper path for rrt folder |
projects/python/SConscript.env | add proper constants to get the proper objectification |
Code - ringmaster.py
Here is the repo: https://github.com/openwsn-berkeley/ringmaster
To run the client, simply execute
python ringmaster.py
This will open up communication with OpenWSN motes on default port 15000.
This script maintains a stack (array) of registered motes that have sent a discovery packet to it. It maintains a pointer which rotates through the stack.
Analysis
Here is a screenshot of wireshark whilst the ringmaster and simulator is running at some point in time
Notice some interesting packets:
packet #13 - A CoAP packet is captured from the localhost to mote bbbb::1415:92cc:0:2 (mote 2 in simulation). This is the packet that is sent when sending a GET request to the 'rt' resource of mote 2 through Firefox Copper (CoAP Interaction#CoAPdiscovery). In the context of ringmaster, this triggers the mote to be online
packet #17 - a UDP packet headed for localhost from mote 2. This packet has the simple message 'D' in its payload, representing Discovery. Notice the Source port is 5683, the default port for COAP communication, while the destination is 15000, the hardcoded port I chose for the ringmaster to listen on.
packet #22 - A CoAP PUT packet telling the mote that it has been confirmed as registered by the ringmaster
packet #28 - ringmaster tells packet 2 to perform action 'B' - in this case, blink
Here is a simple ringmaster output, as of this writing:
The output here is fairly arbitrarily, used just for demonstration purposes. First, the ringmaster is started, where it waits for incoming messages. At some point, it received a discovery message from mote 2, after which it sends a confirmation message via CoAP PUT. Then, it sends an action B to the same mote, as it now has a mote queue to work with. When the mote blinks, it notifies the ringmaster. Seeing as there is only one mote in the queue at the time, the ringmaster tells mote 2 to forward an action to another ipv6, which in this case is the same one. Only after mote 3 gets registered can we start seeing oscillation between the two motes performing actions.