Get started with RUI3 API

This article aims to show you the basics to start creating your custom firmware with RUI3 API. We have already the API documentation available in our Documentation Center and example code can be found in the RUI3 BSP and in our Github repo.

In addition to that, here is an overview of the requirements to connect your RUI3 WisDuo or WisBlock Core to LoRaWAN.

1) LoRaWAN Credentials

Depending on the Join Mode your RUI3 node needs different credentials, DevEUI, AppEUI, AppKey for OTAA or AppSkey, NwSkey and Device Address for ABP. All of these can be set with simple function calls in RUI3:

To manage the credentials for OTAA Join mode the function calls are

  • api.lorawan.appeui
  • api.lorawan.appkey
  • api.lorawan.deui

To manage the credentials for ABP Join mode the functions calls are

  • api.lorawan.daddr
  • api.lorawan.appskey
  • api.lorawan.nwkskey

These functions have both SET and GET calls, so you can not only set the values, but you can also read back the values.

Example for OTAA:

  uint8_t node_device_eui[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x88};
  // OTAA Application EUI MSB
  uint8_t node_app_eui[8] = {0x0E, 0x0D, 0x0D, 0x01, 0x0E, 0x01, 0x02, 0x0E};
  // OTAA Application Key MSB
  uint8_t node_app_key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E};
  
  // Set App EUI
  if(!(ret = api.lorawan.appeui.set(node_app_eui, 8)))
  {
       Serial.printf("RUI3 - set device EUI failed! \r\n");
       return;
  }
  // Set App Key
  if(!(ret = api.lorawan.appkey.set(node_app_key, 16)))
  {
       Serial.printf("RUI3 - set application EUI failed! \r\n");
       return;
  }
  // Set Device EUI
  if(!(ret = api.lorawan.deui.set(node_device_eui, 8)))
  {
       Serial.printf("RUI3 - set application key failed! \r\n");
       return;
  }

Example for ABP:

  uint8_t node_dev_addr[4] = {0x05, 0x05, 0x06, 0x06};
  // ABP Application Session Key
  uint8_t node_app_skey[16] = {0xB4, 0x91, 0xCC, 0x10, 0x17, 0x0E, 0x89, 0x04, 0x33, 0xCA, 0x5B, 0x13, 0x1E, 0x74, 0x20, 0x07};
  // ABP Network Session Key
  uint8_t node_nwk_skey[16] = {0xBF, 0x9B, 0x75, 0xBC, 0xD6, 0x08, 0x06, 0xDD, 0x80, 0xED, 0xB8, 0xE6, 0x83, 0x29, 0x9D, 0x22};

  // Set Device Address
  if (!api.lorawan.daddr.set(node_dev_addr, 4)) {
    Serial.printf("RUI3 - set device addr failed! \r\n");
    return;
  }
  // Set Application Session Key
  if (!api.lorawan.appskey.set(node_app_skey, 16)) {
    Serial.printf
    ("RUI3 - set application session key failed! \r\n");
    return;
  }
  // Set Network Session Key
  if (!api.lorawan.nwkskey.set(node_nwk_skey, 16)) {
    Serial.printf
    ("RUI3 - set network session key failed! \r\n");
    return;
  }

2) Network parameter

In addition to the credentials, several network parameters must be defined, such as Region, Node Class, Join Mode and for some regions and specific LoRaWAN servers, the Channel Mask.

All of these settings can be setup with the following API functions:

  • api.lorawan.band
  • api.lorawan.deviceClass
  • api.lorawan.njm
  • api.lorawan.mask

These functions have both SET and GET calls, so you can not only set the values, but you can also read back the values.

api.lorawan.band

This call is used to set (or check) the Region (equal frequency settings) the device is using. Valid settings are:

RAK_REGION_EU433RAK_REGION_IN865RAK_REGION_AU915
RAK_REGION_CN470RAK_REGION_EU868RAK_REGION_KR920
RAK_REGION_RU864RAK_REGION_US915RAK_REGION_AS923

Example:

  if(!(ret = api.lorawan.band.set(RAK_REGION_EU868)))
  {
       Serial.printf("RUI3 - set band failed! \r\n");
       return;
  }

api.lorawan.deviceClass

LoRaWAN node devices can be set to three different classes.

Class A devices are for lowest power consumption, the device can only receive downlink messages from a LNS (LoRaWAN Network Server) after it has send a data packet

Class B devices open scheduled receive windows for downlink messages and therefore have a higher power consumption

Class C devices can receive downlink messages at any time. As the LoRa transceiver has to be in receive mode all the time, this class has the highest power consumption.

Valid settings are:

RAK_LORA_CLASS_ARAK_LORA_CLASS_BRAK_LORA_CLASS_C

Example:

  if(!(ret = api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)))
  {
       Serial.printf("RUI3 - set device class failed! \r\n");
       return;
  }

api.lorawan.njm

As mentioned before, LoRaWAN has two methods for a device to join the network, OTAA and ABP.

In OTAA mode, the device has a DevEUI, an AppEUI and an AppKey that are known by both the LNS and the device. During the join process, the device sends these credentials to the LNS. If the LNS recognizes the credentials, it creates new random application session key and network session key and sends these back to the device. These keys are then used in future communication to encrypt the data messages.

In ABP mode, the device and the LNS know both already the application session key and the network session key. The Join procedure is therefore just on the device itself to inform the LoRaWAN MAC stack about these keys.

Valid network join modes:

RAK_LORA_OTAARAK_LORA_ABP

Example:

  // Set network join mode
  if(!(ret = api.lorawan.njm.set(RAK_LORA_OTAA))) 
  {
       Serial.printf("RUI3 - set network join mode failed! \r\n");
       return;
  }

api.lorawan.mask

Some of the regions channel plans defined in the LoRaWAN regional parameters have a large number of channels (frequencies), that can be used to communicate between the device, gateway and LNS. In these cases, the device needs to know which channels it is allowed to use to send packets. These are usually eight TX channels and one RX channel.

As an example, the region US915 has defined 72 channels, but as most gateways support only eight channels, these eight channels that can be used have to be masked out of the 72. The Things Network uses channels 8 to 15, as default, so the device has to be set up to use only these eight channels. The channel masks are defined in groups of 8 channels as shown below:

Mask number (for API call)Channel MaskEnabled Channels
ALL0x0000All enabled
10x00010 - 7
20x00028 – 15
30x000416 - 23
40x000824 - 31
50x001032 - 39
60x002040 – 47
100x020072 – 79
110x040080 – 87
120x080088 - 95

Example:

// Set the channel mask (only required for US915, AU915 and CN470)
  uint16_t maskBuff = 0x0002;
  if(!(ret = api.lorawan.njm.set(&maskBuff))) 
  {
       Serial.printf("RUI3 - set channel mask failed! \r\n");
       return;
  }

3) Join the network

After all, the above credentials and settings are done, the device is ready to join the network. Besides the join function call, another function can be used to check the status of the join process.

  • api.lorawan.join
  • api.lorawan.njs

The api.lorawan.join call returns only the success or failure of the join start. The join can e.g. fail if the device has already joined the network.

The status of the join sequence can be checked with the api.lorawan.njs call. If the device has successfully joined, it will return TRUE, otherwise FALSE.

Example:

// Start to join the network
  if(!(ret = api.lorawan.join()))                   
  {
       Serial.printf("RUI3 - join fail! \r\n");
       return;
  }
  /**Wait for Join success */
  while (!api.lorawan.njs.get())
  {
    Serial.print("Waiting for Lorawan join...");
    api.lorawan.join();
    delay(10000);
  }

4) Summary

These few commands setup the device to successfully join the LoRaWAN network. Complete simple example for RUI3 network join sequence:

void setup()
{
    // OTAA Device EUI MSB
    uint8_t node_device_eui[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x88};
    // OTAA Application EUI MSB
    uint8_t node_app_eui[8] = {0x0E, 0x0D, 0x0D, 0x01, 0x0E, 0x01, 0x02, 0x0E};
    // OTAA Application Key MSB
    uint8_t node_app_key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E};

    // Set App EUI
    if (!(ret = api.lorawan.appeui.set(node_app_eui, 8)))
    {
        Serial.printf("RUI3 - set device EUI failed! \r\n");
        return;
    }
    // Set App Key
    if (!(ret = api.lorawan.appkey.set(node_app_key, 16)))
    {
        Serial.printf("RUI3 - set application EUI failed! \r\n");
        return;
    }
    // Set Device EUI
    if (!(ret = api.lorawan.deui.set(node_device_eui, 8)))
    {
            Serial.printf("RUI3 - set application key failed! \r\n");
        return;
    }
    // Set LoRaWAN Region
    if (!(ret = api.lorawan.band.set(RAK_REGION_EU868)))
    {
        Serial.printf("RUI3 - set band failed! \r\n");
        return;
    }
    // Set device class
    if (!(ret = api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)))
    {
        Serial.printf("RUI3 - set device class failed! \r\n");
        return;
    }
    // Set network join mode
    if (!(ret = api.lorawan.njm.set(RAK_LORA_OTAA)))
    {
        Serial.printf("RUI3 - set network join mode failed! \r\n");
        return;
    }
    // Start to join the network
    if(!(ret = api.lorawan.join()))                   
    {
        Serial.printf("RUI3 - join fail! \r\n");
        return;
    }
}

bool has_joined = false;

void loop()
{
    if (!has_joined)
    {
        if (api.lorawan.njs.get())
        {
            Serial.println("RUI3 - joined network");
            has_joined = true;
        }
    }
    else
    {
        // Read sensors, send the data
        // ...
        // We talk about this in the next post
    }
}