Skip to content

mpeder/iotcttnhack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 

Repository files navigation

IoT Central Lorawan TTN Hackaton

The goal of this workshop is to setup a working end-to-end IoT solution based on Azure IoT Central, The Things Network and Lorawan.

The overall flow for the IoT telemetry:

flow image

The device we will be using:

node image

The gateway used:

laird image

During this hackaton you will complete the following tasks:

  • Setup an Arduino Development Environment
  • Configure and program a device
  • Configure and setup a LoraWAN gateway
  • Setup conncectivity from the gateway to The Things Network
  • Decode data using custom code in The Things Network
  • Send data from The Things Network to IoT Central via and device bridge running in an Azure Function
  • Create and configure IoT Central

Prerequisites

Contents

  • The Pro Micro boards are not developed by Arduino. As a result the boards are not available in a newly installed IDE
  • Add the boards in the IDE:
  • Go to the 'Tools' menu, item 'Board: "Arduino/Genuino Uno"', this will open a sub menu, select 'Board Manager'
    • In the boards manager, type 'sparkfun' in the dialog to show all SparkFun provided board packages
    • Click on 'SparkFun AVR Boards' to select the package and click 'Install' to install the board definitions on your system
  • Open the 'Tools' menu and go to the 'Board: "Arduino/Genuino Uno"' again. Now select 'SparkFun Pro Micro' from the list
  • IMPORTANT: Open the 'Tools' menu again, in 'Processor' select 'ATmega32u4 (3.3V, 8MHz)'
  • The TTN Node has some specific packages you can install to get started quickly. They are not in the IDE by default so you have to install them.
  • Add the packages in the IDE:
    • Open the 'Sketch' menu
    • Click 'Include Library' then 'Manage Libraries'
    • In the Library Manager search for 'thethingsnode' and click 'Install'
    • In the Library Manager search for 'thethingsnetwork' and click 'Install'
    • Click 'Close'
  • You can now find 'TheThingsNetwork' and 'TheThingsNode' under 'Contributed Libraries'
    • The easiest way to get started is the 'Basic' sketch, but you will be guided later on the specific code to use
  • Use the IDE to upload the following code to the device
    • Remember to insert in your own 'appEui' and 'appKey'
#include <TheThingsNode.h>

// Set your AppEUI and AppKey
const char *appEui = "INSERT YOU OWN";
const char *appKey = "INSERT YOU OWN";

#define loraSerial Serial1
#define debugSerial Serial

// Replace REPLACE_ME with TTN_FP_EU868 or TTN_FP_US915
#define freqPlan TTN_FP_EU868

TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan);
TheThingsNode *node;

#define PORT_SETUP 1
#define PORT_INTERVAL 2
#define PORT_MOTION 3
#define PORT_BUTTON 4

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

  // Wait a maximum of 10s for Serial Monitor
  while (!debugSerial && millis() < 10000)
    ;

  // Config Node
  node = TheThingsNode::setup();
  node->configLight(true);
  node->configInterval(true, 60000);
  node->configTemperature(true);
  node->onWake(wake);
  node->onInterval(interval);
  node->onSleep(sleep);
  node->onMotionStart(onMotionStart);
  node->onButtonRelease(onButtonRelease);

  // Test sensors and set LED to GREEN if it works
  node->showStatus();
  node->setColor(TTN_GREEN);

  debugSerial.println("-- TTN: STATUS");
  ttn.showStatus();

  debugSerial.println("-- TTN: JOIN");
  ttn.join(appEui, appKey);

  debugSerial.println("-- SEND: SETUP");
  sendData(PORT_SETUP);
}

void loop()
{
  node->loop();
}

void interval()
{
  node->setColor(TTN_BLUE);

  debugSerial.println("-- SEND: INTERVAL");
  sendData(PORT_INTERVAL);
}

void wake()
{
  node->setColor(TTN_GREEN);
}

void sleep()
{
  node->setColor(TTN_BLACK);
}

void onMotionStart()
{
  node->setColor(TTN_BLUE);

  debugSerial.print("-- SEND: MOTION");
  sendData(PORT_MOTION);
}

void onButtonRelease(unsigned long duration)
{
  node->setColor(TTN_BLUE);

  debugSerial.print("-- SEND: BUTTON");
  debugSerial.println(duration);

  sendData(PORT_BUTTON);
}

void sendData(uint8_t port)
{
  // Wake RN2483
  ttn.wake();

  ttn.showStatus();
  node->showStatus();

  byte *bytes;
  byte payload[6];

  //Battery
  uint16_t battery = node->getBattery();
  bytes = (byte *)&battery;
  payload[0] = bytes[1];
  payload[1] = bytes[0];

  //Light
  uint16_t light = node->getLight();
  bytes = (byte *)&light;
  payload[2] = bytes[1];
  payload[3] = bytes[0];

  // Temperature
  int16_t temperature = round(node->getTemperatureAsFloat() * 100);
  bytes = (byte *)&temperature;
  payload[4] = bytes[1];
  payload[5] = bytes[0];

  ttn.sendBytes(payload, sizeof(payload), port);

  // Set RN2483 to sleep mode
  ttn.sleep(60000);

  // This one is not optionnal, remove it
  // and say bye bye to RN2983 sleep mode
  delay(50);
}
  • Make sure you have connected the device using USB
  • Make sure you have selected the correct COM port in the IDE
  • Upload the code to the device
  • View the Serial Monitor to validate that the device connects to gw and sends data

Validate Data From TTN Node Device to TTN

  • On the TTN website go and view the data packages from the device on the TTN Application
  • Unless you are really good a decoding a byte array you will probably need a Decoder to understand the data...
  • The same goes for IoT Central as it will expect a JSON payload not a byte array

Create a Device Template

  • In the newly create IoT Central create a device template
  • Telemetry:
    • Battery Voltage Field: battery
    • Light Field: light
    • Temperature Field: temperature
  • State:
    • Device state
      • Field: event
      • Values: button, setup, interval, motion
module.exports = async function (context, req) {
    try {
        context.log('req: ', req);
        context.log('measurements: ', req.body.measurements);
        context.log('hw serial: ', req.body.hardware_serial.toLowerCase());
        req.body = {
            device: {
                deviceId: req.body.hardware_serial.toLowerCase()
            },
            measurements: req.body.payload_fields
        };

        await handleMessage({ ...parameters, log: context.log, getSecret: getKeyVaultSecret }, req.body.device, req.body.measurements, req.body.timestamp);
    } catch (e) {
        context.log('[ERROR]', e.message);

        context.res = {
            status: e.statusCode ? e.statusCode : 500,
            body: e.message
        };
    }
}
  • On the application in TTN add a decoder using the code below
    • Application > Payload Formats > Decoder
function Decoder(bytes, port) {
  var decoded = {};
  var events = {
    1: 'setup',
    2: 'interval',
    3: 'motion',
    4: 'button'
  };
  decoded.event = events[port];
  decoded.battery = (bytes[0] << 8) + bytes[1];
  decoded.light = (bytes[2] << 8) + bytes[3];
  if (bytes[4] & 0x80)
    decoded.temperature = ((0xffff << 16) + (bytes[4] << 8) + bytes[5]) / 100;
  else {
    decoded.temperature = ((bytes[4] << 8) + bytes[5]) / 100;
  }
  
    return {
        "temperature": JSON.stringify(decoded.temperature),
        "light" : JSON.stringify(decoded.light),
        "battery" : JSON.stringify(decoded.battery),
        "event" : decoded.event
    };
}
  • On the application in TTN add an integration to the Azure Function

In this part you only get hints. By now you are ready to start modifying the code yourself!

These are just hint complete the code yourself :-)

if(INSERT YOUR OWN LOGIC) {
    payload[6] = (byte *)true; 
}
else {
    payload[6] = (byte *)false;
}

These are just hint complete the code yourself :-)

if(INSERT YOUR OWN LOGIC) {
    decoded.buttonpressed = true;
}
else {
    decoded.buttonpressed = false;
}
if(decoded.buttonpressed)
{
    return {
        "temperature": JSON.stringify(decoded.temperature),
        "light" : JSON.stringify(decoded.light),
        "battery" : JSON.stringify(decoded.battery),
        "event" : decoded.event,
        "buttonpressed" : INSERT YOUR OWN CODE
    };
}
else {
    return {
        INSERT YOUR OWN CODE
    };
}
  • Add an Event type on the Device Template called 'Button Pressed' using the telemetry field from the device
    • Field: buttonpressed
  • Build a nice looking dashboard on the Device Template showing important information

About

IoT Central Lorawan TTN Hackaton

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published