API Usage¶
The following sections describes each of the API modules. The functions are presented in a simplified form here as a quick reference; please see the RIIM SDK API Reference document included in the SDK for details. The RIIM SDK API Reference is distributed with the SDK, and is located at RIIM_SDK/docs/RIIM_API_Reference.html
Multicast¶
Multicast is supported for IPv6 transmissions not requiring responses. This means that you can use multicast for the functions UDP.send6 and CoAP.sendNoAck. In the RIIM wireless network, multicast act as a Broadcast, as the target group is “all nodes.” The following example shows how to send a UDP packet to all nodes in the network.
const IPAddr Addr=UAPI_ADDR_ALL_RIIM_NODES;
UDP.send6(Addr, 12345, payload, payloadSize);
One-hop Multicast¶
RIIM supports multicast just to a node’s immediate neighbors as well. A multicast sent like this won’t be able to hop, and will only be responded to by nodes within reach of the sending node.
const IPAddr Addr=UAPI_ADDR_LINKLOCAL_NODES;
UDP.send6(Addr, 12345, payload, payloadSize);
RIIM_UAPI¶
This is basically an include file that includes everything you need to develop in ICI. It includes all User API definitions and needed standard C header files.
Simply put this include line on top of your source file:
#include "RIIM_UAPI.h"
API Descriptions¶
ADC¶
The ADC module lets you sample and convert the analog input of the module
RC18xx-IPM supports 2 ADC channels, called ADC0 and ADC1.
The following example shows an example usage where the ADC is initialized, read, and the value is converted to millivolts and printed on the console.
static uint32_t milliVolts;
void ADC_DemoFunc()
{
milliVolts=0;
// Set up interface
ADC.init(ADC0, ADC_FIXED_REFERENCE, ADC_SAMPLING_DURATION_10_6_US);
ADC.convertToMicroVolts(ADC0, &milliVolts);
milliVolts /= 1000;
// Print directly to console to show the latest values
Util.printf("ADC sensor read: Voltage(mV): %i\n",milliVolts);
return;
}
The following functions are part of the ADC module.
Function |
Description |
---|---|
init |
Initializes the ADC module input |
convert |
Convert input voltage to its raw ADC value |
convertToMicroVolts |
Convert input voltage to an microvolts |
Clock¶
Note
The Clock API requires TSCH to work.
The Clock module provides ways to synchronize and distribute global time throughout the RIIM network. All the nodes part of a network are synchronized to within a few milliseconds of each other, enabling synchronous actions to take place across the RIIM network.
Note
For the border router, call to the Clock API can only be made > 100 ms after StartBorderRouter command
The Clock module provides two ways of representing time: Time of Day (ToD), and Epoch. ToD provides a 24 hour clock represented by hour, minute, second and millisecond. It can be used to do an action at a specific time during a day, and can be repetitive. Epoch provides an absolute time that’s always increasing. It’s represented in milliseconds, and can be used to measure absolute time or trigger an action at some specific time. It’s not repetitive.
Function |
Description |
---|---|
getToD |
Returns the ToD |
setToD |
Set the ToD |
getEpoch |
Returns the Epoch |
setEpoch |
Set the Epoch |
getAbsoluteTime |
Get absolute time |
registerToDTimedAction |
Register a ToD action |
registerEpochTimedAction |
Register an Epoch action |
stopToDTimedAction |
Stop a planned ToD action |
stopEpochTimedAction |
Stop a planned epoch action |
sendClockToAllNodes |
Send Epoch and ToD to all nodes |
getClockFromBR |
Retrieve the Epoch and ToD from the border router |
getOffsets |
Get the raw offset values for ToD and epoch |
setOffsets |
Set the raw offset values for ToD and epoch |
getLastSynchronizeTimestamp |
Get timestamp when the node last received a clock synchronization |
EpochType epoch; // Set to zero in RIIM_SETUP()
// Epoch callback
void epochCallback(void)
{
EpochType thisEpoch;
Clock.getEpoch(&thisEpoch);
Util.printf("Epoch callback at : %i" , (int32_t)thisEpoch);
// Set next callback to be in 5 seconds
epoch=epoch+5000;
Clock.registerEpochTimedAction(&epoch, epochCallback);
Util.printf(" - New set to : %i\n" , (int32_t)epoch);
return;
}
CoAP¶
The CoAP module lets you start and run a CoAP server and lets you transmit CoAP messages to and from a server. If the server is at the border router or on a mesh router is up to the implementor. The CoAP resources on the server side need to be registered along with a callback function (ResourceHandler). This function is called every time the module receives a CoAP request for the resource. The ResourceHandler have as input a pointer to the response that will be sent upon returning from the callback. This response can be filled in during the callback, if a value is intended returned in the response. The generateResponse() function is a support function to fill the response with boundry checked data.
The client need to connectToServer to allow communication with the server. It also need to register a callback function to handle respones form the server. It can be an empty reponse to a PUT-command or a response with value related to a GET command Then the client can issue CoAP requests when it want and wait for responses.
The CoAP protocol include automatically retries in case of no reponse. The retries are after 20 second and then it times out after slightly over 1 minute.
The following example demonstrates how you initialize the CoAP module, set up a response handler and a resource access handler. When this node receives a PUT, POST, GET or DELETE CoAP message, it will call the CoAP_Handler routine. 5 CoAP resources can be registered, and CoAP.registerResource will return an error if more recsorces are requested.
static const uint8_t Resource_Name[]="data";
static void CoAP_Handler(RequestType type, uint8_t *payload, uint8_t payloadSize, uint8_t *response, uint8_t *responseSize)
{
// In this example we only print the payload directly to the UART
Debug.printPayload(payload, payloadSize);
Util.printf("\n"); // Add a newline for readability in console
return;
}
void ResponseHandler(const uint8_t *payload, uint8_t payload_size)
{
Util.printf("# Got CoAP Response. Doing nothing with it.\n");
return;
}
RIIM_SETUP()
{
Network.startBorderRouter(NULL, NULL, NULL, NULL);
// Setup coap resource
CoAP.init(ResponseHandler);
CoAP.registerResource(Resource_Name,0,CoAP_Handler);
return UAPI_OK;
}
The following functions are part of the CoAP module.
Function |
Description |
---|---|
Init |
Initializes the CoAP module |
connectToServer4 |
Connect to a CoAP server using IPv4. This must be done before accessing it. |
connectToServer6 |
Connect to a CoAP server using IPv6. This must be done before accessing it. |
setKey |
Set DTLS key |
setIdentity |
Set DTLS Identity |
registerResponseHandler |
Register a handler to be executed when a CoAP response arrives |
registerResource |
Register a new resource that will be accessible on the node |
generateResponse |
Generate a response message and send it back to the caller |
send |
Send a GET, PUT, POST or DELETE message to a CoAP server |
sendNoAck |
Send a GET, PUT, POST or DELETE message to a CoAP server, but don’t ask for a CoAP response |
disconnectFromServer |
Disconnect from the CoAP server |
Note: CoAP packets will be retransmitted several times if they’re lost on the way to their destination. Each retransmission with an increased timeout. The total time might be in the order of minutes, and hence the CoAP queue can easily fill up. It’s therefore important to wait for the CoAP response before sending new CoAP packets.
Debug¶
The Debug module contains useful functions for debugging.
The following example shows how you can dump the configuration of the node by calling Debug.printSetup().
RIIM_SETUP()
{
Network.startBorderRouter(NULL, NULL, NULL, NULL);
// Print out the configuration
Debug.printSetup();
return UAPI_OK;
}
The following functions are part of the Debug module.
Function |
Description |
---|---|
printPayload |
Dump the payload to the UART |
printSetup |
Print the current node setup on the UART |
printIPAddr |
Nicely print IPAddr |
radioTest |
Test the radio in CW or MW mode. |
getResetReason |
Return the reset code for last module reset |
Note
For the radioTest function:
This command is locking, meaning that the module needs to be externally reset after its called.
This command can’t be called in RIIM_SETUP(), but must be executed in a callback
Ethernet¶
The Ethernet module is used to interface the Ethernet system. The Ethernet MAC is by default set by using the EUI64 / IEEE address of the module, which is unique to each module.
The following example shows how to read the MAC address
RIIM_SETUP()
{
// Set Ethernet MAC address
uint8_t Mac[6];
Ethernet. getMACAddress(Mac);
return UAPI_OK;
}
Function |
Description |
---|---|
Init |
Initialize the GPIO module |
getMACAddress |
Read the Ethernet MAC address |
GPIO¶
The GPIO module is used to control the GPIOs. By default all GPIOs are tri-state inputs with no pullup or pulldown.
All GPIOs also include PWM controllers capable of working autonomously.
Note
PWM could impact current consumption
The following example shows how to configure GPIO 9 as output and setting it to logical ‘1’.
RIIM_SETUP()
{
// Set up GPIO 9
GPIO.setDirection(GPIO_9, OUTPUT);
GPIO.setValue(GPIO_9, HIGH);
return UAPI_OK;
}
The following functions are part of the GPIO module.
Function |
Description |
---|---|
Init |
Initialize the GPIO module |
setDirection |
Set the GPIO direction to input or output |
setPull |
Set pullup, pulldown or no pull on an input pin |
setHandler |
Register a handler to be called when a specific transition happen on a GPIO |
setValue |
Set the value on an output GPIO to logical 0 or 1 |
toggle |
Invert the output value on an GPIO |
getValue |
Read the value of a GPIO pin |
startPWM |
Start PWM output |
stopPWM |
Stop PWM output |
I2C¶
The I2C module has functions needed for interfacing the I2C bus. It always operates as master, and support clock stretching. It supports two speeds: 100KHz and 400KHz.
The following example demonstrates how the module is initialized and an example transmission towards a Sensirion SHT35 Temperature/Humidity sensor.
static void ReadSensor()
{
static uint8_t wbuf[2];
static uint8_t rbuf[10];
// The command 0x2C0D starts a Medium repeatibility measuring
// with clock stretching enabled. See Sensirion SHT35 datasheet.
wbuf[0]=0x2C;
wbuf[1]=0x0D;
I2C.transfer(0x44,wbuf,2,rbuf, 7);
.......
}
RIIM_SETUP()
{
// Set up interface towards the SHT35-sensor
I2C.init(I2C_400KHZ);
.........
return UAPI_OK;
}
The following functions are part of the I2C module.
Function |
Description |
---|---|
init |
Initializes the I2C driver with the chosen Speed |
transfer |
Transfers data both to and from the slave at bus address SlaveAddress. Data is first written on bus, then read |
read |
Perform only read on the I2C bus |
write |
Perform only write on the I2C bus |
close |
Closes the I2C interface |
Network¶
The Network module has the functions needed for network operations. Before the node can join any network, it must be started by a call to either startBorderRouter, startMeshRouter or startLeaf. Some functions will only have effect depending on the RIIM variant (single channel or TSCH) used.
Note
The UART API can’t be used if SLIP is used, as SLIP uses the UART to transfer data
The following example shows how to start a node as a Router:
RIIM_SETUP()
{
// Simply start as a router node. Nothing more is needed.
Network.startMeshRouter();
return UAPI_OK;
}
The following functions are part of the Network module.
Function |
SC |
TSCH |
Description |
---|---|---|---|
startBorderRouter |
x |
x |
Start the node as a Border Router. |
startMeshRouter |
x |
x |
Start the node as a Mesh Router. |
startLeaf |
x |
x |
Start the node as a Leaf. |
getBorderRouterAddress |
x |
x |
Returns the address of the Border Router |
getParentRSSI |
x |
x |
Get the RSSI value of parent |
getNeighbors |
x |
x |
The a list of all neighbors, including RSSI |
getNetworkState |
x |
x |
Get the state of the network |
radio_On |
x |
Turn radio on |
|
radio_Off |
x |
Turn radio off |
|
join |
x |
x |
(Re)-join a network |
leave |
Deprecated. don’t use. |
||
setFreqBand |
x |
x |
Set the frequency band. |
setPanId |
x |
x |
Set the PAN ID of the node |
getPanId |
x |
x |
Get the PAN ID of the node |
getAddress |
x |
x |
Get the IP (v6) address of the node |
getAddress4 |
x |
X |
Get the IPv4 address of the node |
getNetworkLinks |
x |
x |
Retrieves a list of links between nodes |
setTxPower |
x |
x |
Set the output transmission power |
getNodeType |
x |
x |
Return the type of node we’re configured as |
setChannel |
x |
Set the RF channel to use |
|
isPartOfNetwork |
x |
x |
Check if a gived IP address is part of the network |
setNWKey |
x |
x |
Set the network (LLSEC) key |
setRobustnessFactor |
x |
x |
Set the node’s robustness factor |
setTschMaxBrodcastRate |
x |
Set the maximum network broadcast period |
|
getNodeCount |
x |
x |
Get the number of nodes in the network |
startSlip |
x |
x |
Start the SLIP interface |
setTSCHMode |
Deprecated. |
||
setTSCHParameters |
x |
Deprecated. Use Use Node.SetCurrentConfiguration instead. |
|
reConnect |
x |
x |
Reconnect to (possibly another) network |
autoupdateTSCHParameters |
x |
Enable/disable automatic update of TSCH parameters |
|
stop |
x |
x |
Stops all RF traffic and disjoins any network |
Node¶
The Node module contains functions for reading/writing node information and settings.
static void DemoFunc()
{
NodeInfo info;
Node.getNodeInfo(&info);
Util.printf("HW Revision is %i\n", NodeInfo.Hardware_Rev);
return;
}
RIIM_SETUP()
{
RIIMConfig_t Configuration;
Node.GetCurrentConfiguration(&Configuration);
Configuration.MPLParameters.MPL_Control_Message_IMin=128; // Should be power-of-two
Configuration.MPLParameters.MPL_Control_Message_IMax=2048; // Should be power-of-two
Configuration.MPLParameters.MPL_Control_Message_K=1;
Configuration.MPLParameters.MPL_Data_Message_IMin=128; // Should be power-of-two
Configuration.MPLParameters.MPL_Data_Message_IMax=4096; // Should be power-of-two
Configuration.MPLParameters.MPL_Data_Message_K=3;
Node.SetCurrentConfiguration(&Configuration);
return UAPI_OK;
}
The following functions are part of the Node module:
Function |
Description |
---|---|
getNodeInfo |
Return info about the node: Hardware ID+Revision, Platform ID+Version |
GetDefaultConfiguration |
Get the default configuration (Factory settings) |
GetCurrentConfiguration |
Get the current (in-use) configuration |
SetCurrentConfiguration |
Set the current (in-use) configuration |
SPI¶
The SPI module has all the functions needed for accessing the SPI bus. For chip select control, the user must use a GPIO. For all data transfer and initialization, the SPI module can be used. In the example below, usage of both GPIO and SPI is demonstrated. Only 4-wire SPI is supported
The following example shows how to set up SPI and access the ST LIS3DE accelerometer:
RIIM_SETUP()
{
// Set up GPIO. We must use one GPIO for SPI chip select
GPIO.setDirection(GPIO_3, OUTPUT);
GPIO.setValue(GPIO_3, HIGH);
// Set up interface towards the LIS3DE-sensor
SPI.init(4000000,SPI_POL_0_PHA_0);
// Setup accelerometer to update every second
uint8_t wbuf[2];
wbuf[0]=0x20; // 0 (write), 0(don't increment), 0x20 (register address)
wbuf[1]=0x17; // 1 Hz, enable X,Y and Z axes
GPIO.setValue(GPIO_3, LOW);
SPI.transfer(2, wbuf, NULL);
GPIO.setValue(GPIO_3, HIGH);
return UAPI_OK;
}
The following functions are part of the SPI module:
Function |
Description |
---|---|
init |
Initialize the SPI module |
transfer |
Transfer bytes over the SPI bus |
Timer¶
The Timer module enables the user to create various timers. The timers will call a function when they’re triggered, and can be configured as periodic or one-shot, started and stopped.
The following example creates a periodic timer that calls the function ReadSensor every 10 seconds:
static const uint32_t TimerPeriod=10000;
static uint8_t Sensor_timer_handler;
static void ReadSensor()
{
Util.printf("Reading sensors....\n");
return;
}
RIIM_SETUP()
{
// Create timer that sends the CoAP PUT message
Sensor_timer_handler=Timer.create(PERIODIC, TimerPeriod, ReadSensor);
Timer.start(Sensor_timer_handler);
return UAPI_OK;
}
Function |
Description |
---|---|
create |
Create a new timer |
start |
Start the timer |
stop |
Stop the timer |
isActive |
Check if the timer is active |
config |
(Re)-configure a timer |
UART¶
Note
The UART API can’t be used if SLIP is used, as SLIP uses the UART to transfer data
The UART module controls the UART port. The uart can be configured with respect to baudrate, parity, number of databits and number of stopbits.
static void TxCallback(uint8_t len)
{
Util.printf("Sent %i bytes\n", len);
return;
}
static void DemoFunc()
{
const uint8_t buffer="Test";
UART.init(115200, UART_PARITY_NONE, UART_DATA_8_BITS, UART_STOP_1_BIT);
UART.startTransmit(buffer, sizeof(buffer), TXCallback);
return;
}
Function |
Description |
---|---|
Init |
Initialize the UART module |
startReceive |
Start reception |
cancelReceive |
Stop reception |
startTransmit |
Start transmission of a buffer of bytes |
isTXActive |
Returns true if UART TX is active |
isRXActive |
Returns true if UART RX is active |
enableRXTX |
Enables RXTX functionality on CTS pin. Compatible with RS485 |
startReceive_Adv |
Advanced version of startReceive |
wakeOnUART |
Enable or disable wake-on-uart |
UDP¶
The UDP module controls the sending and reception of UDP packets. It has functions for receiving and sending over IPv6 or IPv4.
void udpCallback(IPAddr src_ipAddr, uint8_t *payload, uint8_t payloadSize)
{
int i;
Util.printf("Msg from ");
for(i=0;i<16;i++){
Util.printf("%.02x" , src_ipAddr.byte[i]);
}
Util.printf(" : %.*s\n" , payloadSize, payload);
UDP.send6(src_ipAddr, 12345, payload, payloadSize);
}
RIIM_SETUP()
{
.....
UDP.setup(udpCallback,12345);
.....
}
Function |
Description |
---|---|
send4 |
Send a UDP packet to an IPv4 address. Typically to the internet |
send6 |
Send a UDP packet to an IPv6 address. Typically inside the RIIM wireless network |
setup |
Setup a handler for reception of UDP packets |
Util¶
The Util module contains useful helper functions. The module provides common C library functions for the ICI user application to use: printf, sprintf, snprinf. It also provides a random generator.
The following example shows how to print something on the console (UART)
static void DemoFunc()
{
Util.printf("Reading sensors....\n");
return;
}
Function |
Description |
---|---|
printf |
Standard C-library printf |
sprintf |
Standard C-library sprintf |
snprintf |
Standard C-library snprintf |
getRand |
Get a random number |
reset |
Reset the module |
getTemperature |
Get module temperature |
strlen |
Return string length |
strcmp |
Standard C-library strcmp |
strncmp |
Standard C-library strncmp |
getVoltage |
Get voltage on the supply pin of the module |