documentation

Stage 3: Connect to a Network Server

In the first stage, you built the LoRa® moisture-sensing broadcasting device and configured it to send a moisture reading every 30 seconds. In this section, you learn how to reconfigure the device to allow it to connect to a network server using the Semtech Network Server. Connecting a device to a network server allows the data within the messages to be forwarded to other services, for example, you can then display the data in a web-based application or IoT platform.

Configure the Semtech Network Server

Register with the Semtech Network Server and Configure your Gateway

Set up your gateway and configure the Semtech Network Server following these steps:

  1. Find your Gateway ID by following the instructions in the Find the Gateway ID section of the Semtech Network Server User Guide.
  2. Create an account with the Semtech Network Server following the instructions in the Create an Account with the Semtech Network Server section of the Semtech Network User Guide.
  3. Register your gateway and connect it to the Semtech Network Server following the instructions in the Register and Connect Your Gateway to the Semtech Network Server section of the Semtech Network User Guide.

Create an Application

An application in this sense represents a collection of devices on the network server. These devices may either be all of the same type or a mixture of device types. In this tutorial your application will only contain the moisture-sensing device.

  1. Log into the Semtech Network Server if you haven’t already done so.
  2. Click Applications in the menu on the left.

    Semtech Network Server Applications Item

    Semtech Network Server Applications Item

  3. Click + CREATE.

    Applications +CREATE Button

    Applications +CREATE Button

  4. Complete the form:
    • Application name: enter a name with only letters, numbers, and dashes, e.g., moisture-application
    • Application description: Give the application a description e.g., Moisture sensing application (spaces are allowed)
    • Service-profile: select the service profile that matches your region, as listed on the Semtech Network Server website.
  5. Click CREATE APPLICATION. The application appears in the list of Applications.

You have now created an application.

Create Your Device in the Semtech Network Server

Create a Device Profile

The device profile must exist before you can add your device to the Semtech Network Server. Follow these steps to create one:

  1. Log in to the Semtech Network Server.
  2. Click Device-profiles in the menu on the left.
  3. Click + CREATE.
  4. Complete the form as follows:
    • Device-profile name: Enter a profile name, e.g., moisture sensor. Spaces are allowed.
    • LoRaWAN® MAC Version: Select version 1.0.3.
    • LoRaWAN Regional Parameters revision: Select A.
    • ADR algorithm: Select Default ADR algorithm.
    • Max EIRP: Leave this set to the default of 0.
    • Uplink interval (seconds): Set this to 30.  The Semtech Network Server uses this setting to decide whether a device is active or inactive on the dashboard. The device will still work if this setting does not match the actual uplink interval.

    /uploads/loramac_node/create-device-profile-03.png

    Completed Device Profile form

  5. Open the JOIN (OTAA/ABP) tab.
  6. Check the box next to Device supports OTAA.
  7. Click CREATE DEVICE-PROFILE. The device profile appears in the Device-profiles list.

You have now created a device profile.

Add Your Device

  1. Click Applications in the menu on the left.
  2. Click the link to the application you created earlier.
  3. Click + CREATE.
  4. Complete the form as follows:
    • Device name: enter a name using only letters, numbers, and dashes, e.g., moisture-sensor.
    • Device description: enter a description, e.g., Moisture Sensor.
    • Device EUI:
      1. Click the Generate random ID button () to generate a random device EUI.
      2. Click the MSB button to change the display order of the device EUI to LSB (Least Significant Bit).
      3. Copy the Device EUI somewhere safe. You will need to paste this into your Arduino code later. This value is referred to later as DEV_EUI.
    • Device-profile: select the profile you created earlier, e.g., moisture-sensor.
    • Leave the remaining fields set to their default values.
  5. Click CREATE DEVICE.
  6. The KEYS (OTAA) screen displays. Complete the form as follows:
    • Application key:
      1. Click the Generate random ID button () to generate a random Application Key.
      2. Click the Click to copy button (), then select the option Hex Array to copy the Application Key in the format required by the Arduino code.
      3. Copy this Application Key somewhere safe. You will need to paste this into your Arduino code later. This value is referred to later as APP_KEY.
  7. Click SET DEVICE-KEYS to save the keys.
  8. The Device page opens in a new tab.

Set up the Arduino IDE for LoRaWAN

In this section we show you how to; install the open-source library MCCI LoRaWAN LMIC (LoRaWAN-MAC-in-C) that will allow you to send and receive data using LoRa, edit a config file (unless you are based in the U.S.), and select your board.

  1. Open the Arduino IDE.
  2. At the Arduino IDE menu bar, select Sketch > Include Library > Manage Libraries. to open the Library Manager.
  3. Search for MCCI LoRaWAN LMIC and locate the MCCI LoRaWAN LMIC library by Terry Moore. At the time of this writing, the latest version is 4.1.1. Click Install.

    Arduino IDE Library Manager showing the library to install [TODO: Update image with red box around name of correct library to install]

    Warning

    Take care to avoid installing the library named MCCI Arduino LoRaWAN Library, this is a different library and will not work with this tutorial.

  4. Click Close to exit the Library Manager.
  5. At the Arduino IDE menu bar, select Tools > Board > Arduino Uno (or whichever board you are using for this tutorial) to ensure that the correct board is selected.
  6. The LMIC library contains a flag to toggle between region frequencies. You next need to make sure the correct frequency is selected for your region. If your region is US915, you do not need to perform these remaining steps, since that is the default region.
    1. At the Arduino IDE menu bar on Windows and Linux select File > Preferences, on macOS select Arduino > Preferences. The Preferences window opens at the Settings tab.

    2. Locate the Sketchbook location field; we refer to this below as SKETCHBOOK_LOCATION.

      Arduino IDE settings screen showing Sketchbook location

    3. Open your favourite code editor, or install and open Visual Studio Code.

    4. Open the file at SKETCHBOOK_LOCATION/libraries/MCCI_LoRaWAN_LMIC_library/project_config/lmic_project_config.h on macOS and Linux, or SKETCHBOOK_LOCATION\libraries\MCCI_LoRaWAN_LMIC_library\project_config\lmic_project_config.h on Windows. This file contains the settings for the LMIC library.

    5. Edit lmic_project_config.h to comment the #define CFG_us915 1 line, and uncomment the frequency for your country/region.

      For example, to use the EU868 frequency, comment-out the line #define CFG_us915 1 and uncomment the line #define CFG_eu868 1 as follows:

      // project-specific definitions

      #define CFG_eu868 1

      //#define CFG_us915 1

      //#define CFG_au915 1

      //#define CFG_as923 1

      // #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */

      //#define CFG_kr920 1

      //#define CFG_in866 1

  7. Save the lmic_project_config.h file and then close it.

Configure Your LoRa Device

In this section we show you how to update the LoRa device you created in Stage 1 to use the LoRaWAN standard to broadcast the soil moisture readings over the network.

  1. At the Arduino IDE menu, select File > New.
  2. Delete all the boilerplate code that appears in the sketch.
  3. Copy the code below into the sketch. This code, and the code that follows, references the TTN-OTAA sample provided with the LMIC library, which is found here.

    #include lmic.h

    #include hal/hal.h

    #include SPI.h

    #define SensorPin A0

    int sensorValue = -1;

    // Pin mapping: set your pin numbers here. These are for the Dragino shield.

    const lmic_pinmap lmic_pins = {

        .nss = 10,

        .rxtx = LMIC_UNUSED_PIN,

        .rst = 9,

        .dio = {2, 6, 7},

    };

    Note

    The LMIC and SPI library headers #include lmic.h and #include spi.h import the libraries.

    The SensorPin and sensorValue declarations at the top of the sketch define which analog pin the sensor is connected to and set an initial value of -1.

    lmic_pinmap is used to inform the LMIC library of the Arduino pins your shield uses (referred to as a pin mapping). The pin mapping in the code above is for the Dragino shield, but if you are using a different shield, you need to update this struct. Refer to your hardware documentation for the correct pin mappings. The settings are:

    • .nss - for the ‘slave select’ connection
    • .rxtx - for controlling the antenna switch, not used by this software so set to LMIC_UNUSED_PIN
    • .rst - reset pin, used to reset the transceiver
    • .dio - digital I/O pins to get status information from the shield, for example when a transmission starts or is complete

    Learn more about pin mapping at the Pin mapping section of the Ardunio-LMIC library README.

  4. Add the bolded lines below to the bottom of the sketch to set the variables for Over-the-Air Activation (OTAA):

        .dio = {2, 6, 7},

    };

     

    // Insert Device EUI here

    static const u1_t PROGMEM DEVEUI[8] = {

      DEV_EUI

    };

     

    // Insert App Key here

    static const u1_t PROGMEM APPKEY[16] = {

      APP_KEY

    };

     

    void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

    void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}

     

    static const u1_t PROGMEM APPEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00 };

    void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

    Note

    The lines you have just added set the keys used for OTAA.

    DEVEUI[8] defines the Device EUI (DevEUI). A DevEUI is a globally-unique identifier that uniquely identifies your device across any network. DEV_EUI is a placeholder for the real DevEUI. You generated a DevEUI earlier using the Semtech Network Server and will set this in the next step.

    APPKEY[16] defines the Application Key (AppKey). The AppKey is an AES-128 root key specific to the device. The AppKey is used in the join procedure to derive the session keys. APP_KEY is a placeholder for the real AppKey. You generated an AppKey earlier using the Semtech Network Server and will set this in the next step.

    APPEUI[8] defines the Application EUI (AppEUI), renamed Join EUI (JoinEUI) in LoRaWAN Link Layer Specification v1.0.4 and v1.1. The AppEUI/JoinEUI is used to identify a Join Server that sits apart from the Network Server, responsible for handling the Join Procedure. The Semtech Network Server does not require an AppEUI/JoinEUI and can handle the Join Procedure itself, so this is set to the dummy value { 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00 }.

  5. Edit the code to replace the DEV_EUI and APP_KEY placeholders with the values listed below.
    1. DEV_EUI:

      Use the DEV_EUI you saved in the section Add Your Device. Transform this to the Hex Array format. A DevEUI of 6d 10 df 93 af 3b 03 36 becomes 0x6d, 0x10, 0xdf, 0x93, 0xaf, 0x3b, 0x03, 0x36 when transformed into the Hex Array format. Replace DEV_EUI in the code with the Hex Array you created.

    2. APP_KEY:

      Use the APP_KEY you saved in the section Add Your Device. This is already in the Hex Array format. Replace APP_KEY in the code with the APP_KEY value.

    Check that the code is formatted as below, using the keys you generated in place of the examples below.

    // Insert Device EUI here

    static const u1_t PROGMEM DEVEUI[8] = {

      0x6d, 0x10, 0xdf, 0x93, 0xaf, 0x3b, 0x03, 0x36

    };

     

    // Insert App Key here

    static const u1_t PROGMEM APPKEY[16] = {

      0x77, 0x21, 0x7A, 0x25, 0x43, 0x2A, 0x46, 0x2D, 0x4A, 0x61, 0x4E, 0x64, 0x52, 0x67, 0x55, 0x6A

    };

  6. Add the bolded lines below to the bottom of the sketch, setting the frequency of broadcast to once every 30 seconds.

    void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

    // Schedule uplink to send every TX_INTERVAL seconds

    const unsigned TX_INTERVAL = 30;

    Note

    The duty cycle, which is the amount of time a device is allowed to broadcast in the LoRaWAN spectrum, is regulated by government. A duty cycle limit of 1% means that for any given time period the device may only broadcast for 1% of that time, e.g. 864 seconds within a 24-hour period. In addition, TTN has a fair usage policy limiting the uplink time per device to 30 seconds per day.

    There are calculators, such as this third-party one on GitHub, that allow you to estimate your airtime for an uplink message.

  7. Add the following bolded lines to the bottom of the sketch file to to send an uplink containing the reading:

    const unsigned TX_INTERVAL = 30;

    void do_send(osjob_t* j) {

        // Check if there is not a current TX/RX job running

        if (LMIC.opmode & OP_TXRXPEND) {

            Serial.println(F(OP_TXRXPEND, not sending));

        } else {

     

            // Prepare upstream data transmission at the next possible time.

            sensorValue = analogRead(SensorPin);

            Serial.println(Reading is: );

            Serial.println(sensorValue);

     

            // int -> byte array

            byte payload[2];

            payload[0] = lowByte(sensorValue);

            payload[1] = highByte(sensorValue);

     

            // transmit packet at the next available slot. The parameters are:

            // - 1, FPort: the port used to send the packet, port 1

            // - payload: the payload to send

            // - sizeof(payload): the size of the payload

            // - 0: if we want an acknowledgement response (ack), 0 means we do not want an ack

            LMIC_setTxData2(1, payload, sizeof(payload), 0);

            Serial.println(F(Payload queued));

        }

    }

     

    Note

    analogRead(SensorPin) reads the measurement from the sensor.

    lowByte and highByte convert the integer value into a small two-byte array payload.

    LMIC_setTxData2 sets the payload ready for the next transmission by the LMIC library.

  8. Add the following bolded lines to the bottom of the sketch file to handle events from the LMIC library:

            Serial.println(F(Payload queued));

        }

    }

    static osjob_t sendjob;

    void onEvent (ev_t ev) {

        switch(ev) {

            case EV_JOINING:

                Serial.println(EV_JOINING);

                break;

            case EV_JOINED:

                Serial.println(EV_JOINED);

                // We will disable link check mode, this is used to periodically verify network connectivity, which we do not need in this tutorial

                LMIC_setLinkCheckMode(0);

                break;

            case EV_JOIN_FAILED:

                Serial.println(EV_JOIN_FAILED);

                break;

            case EV_REJOIN_FAILED:

                Serial.println(EV_REJOIN_FAILED);

                break;

            case EV_TXCOMPLETE:

                Serial.println(EV_TXCOMPLETE);

                // Schedule next transmission

                os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);

                break;

             default:

                break;

        }

    }

     

    Note

    When the LMIC library completes an event, it calls the onEvent function, passing the name of the event (ev).

    Examples of events include when joining is complete (EV_JOINED) and when transmission is complete (EX_TXCOMPLETE).

    Join and transmission events are logged to the Arduino Serial Monitor using Serial.println().

    When the EX_TXCOMPLETE event is received indicating that the transmission is complete, the next uplink message is scheduled by instructing the os_setTimedCallback function to call the do_send in TX_INTERVAL seconds, which you set to 30 earlier.

  9. Add the following bolded lines to the bottom of the sketch file to run the methods you just created:

                break;

        }

    }

    void setup() {

        Serial.begin(9600);

        Serial.println(F(Starting));

     

        // Initalizes the LIMIC library,

        os_init();

     

        // Resets the MAC state - this removes sessions, meaning the device must repeat the join process each time it is started.

        LMIC_reset();

     

        // Let LMIC compensate for an inaccurate clock

        LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

     

        // Disable link check validation - this is used to periodically verify network connectivity. Not needed in this tutorial.

        LMIC_setLinkCheckMode(0);

     

        // Set data rate to Spreading Factor 7 and transmit power to 14 dBi for uplinks

        LMIC_setDrTxpow(DR_SF7, 14);

     

        // Start job

        do_send(&sendjob);

    }

     

    void loop() {

        os_runloop_once();

    }

    Note

    The Ardunio setup function is called automatically when a sketch starts. It runs all the setup functions. These functions are detailed in the comments in the sketch above.

    The dosend() method starts the OTAA Join Procedure.

    The loop() function is called on a consecutive loop by Ardunio, and is used to call the LMIC method os_runloop_once(). At that point it hands control over to LMIC. LMIC then sends queued transmissions and runs other radio events. When an event is complete, the onEvent method is called.

Join to the Network and View Device Data

  1. Make sure that your gateway is plugged-in and powered-on.
  2. Log into the Semtech Network Server.
  3. In the menu on the left, click Gateways.
  4. Verify that your gateway is listed as Last Seen a few seconds ago.
  5. Gateways page showing gateway as online.

    Note

    If you do not see your gateway listed, or if it is offline, verify that it is turned on and recheck the steps you followed in the Register and Connect Your Gateway to the Semtech Network Server section of the Semtech Network User Guide.

  6. In the menu on the left, click Applications.
  7. Click on the application you created earlier.
  8. The devices associated with your application appear. Click on the device you created earlier.
  9. Click on to the DEVICE DATA tab.

    Location of the DEVICE DATA tab.

  10. A spinning wheel displays. Leave this tab open throughout the rest of this section so you can view the messages.
  11. Connect the Arduino board to your computer via the USB-B cable. You should see power LEDs illuminate on the Arduino and on the shield.
  12. Connect the broadcasting device to the computer’s USB port using the USB-B cable. You should see a power LED illuminate on the Arduino and on the shield.
  13. At the Arduino IDE menu, select Tools > Port. We need to select the serial port that the Arduino is connected to. Select the port labeled with the model of your Arduino board. If none of the ports are labeled, disconnect the Arduino board and reopen the menu; the entry that disappears should be your board. Reconnect the board, then select the entry that had disappeared.
  14. At the Arduino IDE menu, open the Serial Monitor by selecting Tools > Serial Monitor. Verify that 9600 baud is selected.
  15. Verify and upload the sketch using the buttons in the Sketch Window menu bar.
  16. The logs showing the EV_JOINING and EV_JOINED messages display in the Serial Monitor. The device has now completed the OTAA process, using the Device EUI and Application Key.

    Serial Monitor showing the join process

    Warning

    If you only see the EV_JOINING message, check the DEVICE DATA tab. If you see no data, double-check that the DevEUI is correct, revisiting the section Configure the LoRa Device. If you see an error event in the DEVICE DATA tab, make sure that the AppKey is correct, revisiting the section Configure the LoRa Device.

  17. On the DEVICE DATA tab of the Semtech Network Server dashboard, the messages sent from the device appear as events. The join event displays following the first uplink from the device. Once that occurs, the network server knows that the device is activated, and the join event appears in the list of events. When the device sends uplinks, the up event appears. When the device sends a status message, the status event appears. All of these events should appear.

    DEVICE DATA tab showing join and up events.

You have now successfully updated your device’s DevEUI and AppKey, and joined to the network.

Decode the Payload

  1. Log into the Semtech Network Server.
  2. Click Device-profiles in the menu on the left./uploads/loramac_node/create-device-profile-01.png
  3. Click on the moisture sensor profile you created earlier.
  4. Click on the CODEC tab.
  5. Choose Custom JavaScript codec functions from the Payload codec options.
  6. Paste the following code into the first field which appears, replacing all the boilerplate code:

    function Decode(fPort, bytes, variables) {

      var decoded = {};

      // Check this is a message with a payload (fPort is not 0, which is used for status messages)

      if (fPort !== 0) {

        // Calculate the original moisture value from the two-byte payload

        decoded.Moisture = bytes[0] + bytes[1] * 256;

      }

      return decoded;

    }

    Completed codec form

  7. Click UPDATE DEVICE-PROFILE to save the codec to your profile.
  8. Click Applications in the menu on the left.
  9. Click on the application you created earlier.
  10. Click on the device you created earlier.
  11. Click on the DEVICE DATA tab.
  12. Wait for an up message to appear.
  13. Expand the up message and scroll down to the objectJSON key shown in the image below. The Moisture value appears, which is the value decoded using the codec you just created.

    Decoded Moisture value.