CoAP -03
TinyOS CoAP
Contents
This page describes how to setup the TinyOS CoAP implementation based on libcoap, which implements the Constrained Application Protocol (CoAP) [[1]].
This adaptation uses the TinyOS blip stack for UDP communication.
Installation instructions
Get the code
The code for the TinyOS adaptation of libcoap is in a git repository. That repository is a clone of the tinyos-main svn repository. libcoap as an external project is included using git submodule.
In order to get yourself a copy:
git clone -b blip-coap-server-client-unification http://www.comnets.uni-bremen.de/~mab/git/tinyos-main.git/ cd tinyos-main git submodule init git submodule update
Then set the TOSROOT and TOSDIR environment variables appropriately.
Compile libcoap and examples
cd $TOSROOT/apps/CoapBlip/libcoap autoconf ./configure make
Compile and install CoapBlip application
cd $TOSROOT/apps/CoapBlip make telosb blip coap install,3
Run it
blip IPBaseStation
blip ip-driver
./coap-server ./coap-client
Important parts of TinyOS CoAP
$TOSROOT/apps/CoapBlip/* | Sample application | |||
$TOSROOT/support/make/coap.extra | Makefile extension for CoAP | |||
$TOSROOT/tos/lib/app/coap/* | Core libcoap TinyOS adaptation | |||
|
CoAP interfaces |
Wiring your resource to the application
To read values of the sensors, the parameterized ReadResource interface has been introduced to provide multiple independent instances of the same interface for all available sensors. This design scheme saves code space, eliminates fan-outs and allows portability to different motes by simply changing the wiring.
ReadResource
The ReadResource interface currently provides three functions:
interface ReadResource { command error_t get(coap_tid_t id); event void getDone(error_t result, coap_tid_t id, uint8_t asyn_message, uint8_t* val, uint8_t buflen); event void getPreAck(coap_tid_t id); }
The getDone() event is signaled if the sensor reading has finished within a predefined time (PREACK_TIMEOUT) to create a immediate response. In case of a deferred message response, i.e. sensor data retrieval takes longer as defined in PREACK_TIMEOUT, getPreAck() is signaled to establish a asynchronous message exchange.
Example code to wire temperature and humidity sensor on TelosB motes:
configuration CoapBlipC { } implementation { CoapBlipP.CoAPServer -> CoapUdpServerC; components new SensirionSht11C() as HumTempSensor; components new CoapReadResourceC(uint16_t, KEY_TEMP) as CoapReadTempResource; CoapReadTempResource.Read -> HumTempSensor.Temperature; CoapUdpServerC.ReadResource[KEY_TEMP] -> CoapReadTempResource.ReadResource; components new CoapReadResourceC(uint16_t, KEY_HUM) as CoapReadHumResource; CoapReadHumResource.Read -> HumTempSensor.Humidity; CoapUdpServerC.ReadResource[KEY_HUM] -> CoapReadHumResource.ReadResource; }
The mapping of the parameterized ReadResource to its corresponding sensor is done by its key value which is mapped at compile-time to a constant integer by a predefined mapping function (get_key()) in tinyos_coap_ressources.h. Here the key "KEY_TEMP" corresponds to a 0 whereas the key "KEY_HUM" is mapped to 1.
Requesting data from a sensor, the following command needs to be called:
call ReadResource.get[get_key(uri->path.s, uri->path.length)](*id);
In case of an inappropriate call of get() in the application, e.g. for a non existing URI, the default function below must be implemented in the application to handle this exception:
default command error_t ReadResource.get[uint16_t uri_key](coap_tid_t id) { //get not available for this resource, handle this case return FAIL; }
After the sensor is read, getDone() is signaled and returns the sensor data. The following function handles this event:
event void ReadResource.getDone[uint16_t uri_key](error_t result, coap_tid_t id, uint8_t asyn_message, uint8_t* val_buf, uint8_t buflen) { //send response with sensor value }
The same implementation holds for the getPreAck() event.
WriteResource
Since the LED resource, for example, provides both, Read- and Write-Resource interfaces, another component (CoapLedResource) is used to provide full access to the LedsC module. While ReadResource provides the get() command, the WriteResource provides the put() command to modify or change the state of a resource.
The interface looks as follows:
interface WriteResource { command error_t put(uint8_t* val, uint8_t buflen); event void putDone(error_t result); }
For accessing the LED resource, the wiring looks like this:
configuration CoapBlipC { } implementation { CoapBlipP.CoAPServer -> CoapUdpServerC; CoapBlipP.Leds -> LedsC; components new CoapLedResourceC(KEY_LED) as CoapLedResource; CoapLedResource.Leds -> LedsC; CoapUdpServerC.ReadResource[KEY_LED] -> CoapLedResource.ReadResource; CoapUdpServerC.WriteResource[KEY_LED] -> CoapLedResource.WriteResource; }
Accessing the WriteResource out of the application, the put() function as well as its default command has to be implemented.
call WriteResource.put[get_key(uri->path.s, uri->path.length)](buf, *buflen) default command error_t WriteResource.put[uint16_t uri_key](uint8_t* val, uint8_t buflen) { //put not available for this resource, handle this case return FAIL; }