Big & Breaking Update to our Arduino Library

Fokke Zandbergen

The Things Network User

Posted on 05-12-2016

Arduino Board

We've just release a big and breaking update to our Arduino Library. Thanks to the hard work of our team, including Johan Stokking, Nicolas DeJean and myself the library now has a smaller footprint and more simple API. This does come at the cost of some breaking changes, which I'll lay out for you in this post.

Constructor instead of init()

You used to initialize the class instance via an init method:

#include "TheThingsNetwork.h"

#define loraSerial Serial1
#define debugSerial Serial

TheThingsNetwork ttn;

void setup() {
  debugSerial.begin(9600);
  loraSerial.begin(57600);

  ttn.init(loraSerial, debugSerial);

In the new version this has been replaced by a constructor, which now also requires a frequency plan:

#include "TheThingsNetwork.h"

#define loraSerial Serial1
#define debugSerial Serial
const ttn_fp_t freqPlan = TTN_FP_EU868; // or TTN_FP_US915

TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan);

void setup() {
  loraSerial.begin(57600);
  debugSerial.begin(9600);

No more reset()

We've dropped the public reset() method. This is now handled internally.

Keys has hex string instead of byte array

This is a real click-saver. No longer do you need to toggle your keys to the MSB format and paste them like this:

const byte appEui[8] = {0x70, 0xB3, 0xD5, 0x7E, 0xE0, 0xE0, 0x01, 0x4A1};
const byte appKey[16] = {0x73, 0x6D, 0x24, 0xD2, 0x69, 0xBE, 0xE3, 0xAE, 0x0E, 0xCE, 0xF0, 0xBB, 0x6C, 0xA4, 0xBA, 0xFE};

With the new version you can copy the default hex string:

const char *appEui = "0000000000000000";
const char *appKey = "00000000000000000000000000000000";

Receive messages via callback

Receiving downlink messages in response to an uplink messages used to be an adventure:

void loop() {
  byte send[1] = { 0x01 };
  int downlinkBytes = ttn.sendBytes(send, sizeof(send));

  if (downlinkBytes > 0) {
    debugSerial.print("Received " + String(downlinkBytes) + " bytes via " + String(ttn.downlinkPort) + ": ")

    for (int i = 0; i < downlinkBytes; i++) {
      debugSerial.print(String(ttn.downlink[i]) + " ");
    }

    debugSerial.println();
  }

  delay(10000);
}

We have made this a lot friendlier with the new onMessage() method to register a callback:

void setup() {
  // ..

  ttn.onMessage(message)
}

void message(const byte* payload, int length, int port) {
  debugSerial.print("Received " + String(length) + " bytes on port " + String(port) + ":");

  for (int i = 0; i < length; i++) {
    debugSerial.print(" " + String(payload[i]));
  }

  debugSerial.println();
}

Poll for messages

If you don't have anything to send, you can now also use the handy poll() method to check for scheduled downlink messages by sending a single byte:

void loop() {
  ttn.poll();
}

See the updated documentation and release notes for more details and let us know if you run into any issues or have ideas for further improvements.

PS: You may also notice a new TheThingsMessage class. We'll explain how you can use this to encode and decode messages using protocol buffers in another post.