Skip to content

Reference Network

Frank Edwards edited this page Nov 12, 2017 · 1 revision

Home > Reference Network

This section provides the step-by-step configuration for a reference IoT network using LoRa devices, Floranet, and a Azure IoT Hub cloud service.

Network Design

The network design diagram is shown below.

Reference Network

This simple network design consists of the components shown in the table below.

Network Element Specifications Comments
LoRa Devices Multitech mDot Developer Kit Class A devices
LoRa Gateway Multitech Conduit Gateway Equipped with LoRa 915MHz mCard
Network Server FloraNet Installed on Ubuntu Linux 16.04
Application Server Microsoft Azure IoT Hub

The solution is designed such that devices will transmit simple temperature values as LoRaWAN payload, processed by Floranet and forwarded to the Azure IoT Hub using the HTTPS protocol. The solution will utilise a Floranet application property that allows devices to send simple 4 byte float values, with the network server translating these values to JSON objects for telemetry consumption by Azure IoT Hub. To demonstrate both methods of authentication, one device will be configured using ABP, and the other using OTAA.

The network and application parameters are defined in the table below.

Parameter Setting Comments
Frequency Band AU915 Australian 915-928 MHz
Network ID 0x3 Local: Experimental nodes
OTAA Address Range 0600.0001 - 060f.ffff Default
Application EUI 0a0b.0c0d.0a0b.0c0d
AppKey 0937.c721.8c66.0b42
FPort 15

Devices

The two devices are configured as per the following table.

Device Name Device EUI App Name Activation DevAddr
ota_device 0f0e.0e0d.0001.0203 azure_device01 OTAA -
abp_device 0f0e.0e0d.0000.0001 azure_device02 ABP 0610.0000

Each device is programmed using the Mbed OS repository LoraWAN-demo-72. Refer to this page for information for detailed configuration of the device and application parameters within the source code. For our reference network, the following code snippets are used.

ota_device

Commissioning.h

/*!
 * When set to 1 the application uses the Over-the-Air activation procedure
 * When set to 0 the application uses the Personalisation activation procedure
 */
#define OVER_THE_AIR_ACTIVATION                     1

/*!
 * Indicates if the end-device is to be connected to a private or public network
 */
#define LORAWAN_PUBLIC_NETWORK                      true

#if( OVER_THE_AIR_ACTIVATION != 0 )

/*!
 * Mote device IEEE EUI (big endian)
 */
#define LORAWAN_DEVICE_EUI                          { 0x0F, 0x0E, 0x0E, 0x0D, 0x00, 0x01, 0x02, 0x03 }

/*!
 * Application IEEE EUI (big endian)
 */
#define LORAWAN_APPLICATION_EUI                     { 0x0A, 0x0B, 0x0C, 0x0D, 0x0A, 0x0B, 0x0C, 0x0D }

/*!
 * AES encryption/decryption cipher application key
 */
#define LORAWAN_APPLICATION_KEY                     { 0x01, 0x7E, 0x15, 0x16, 0x38, 0xAE, 0xC2, 0xA6, 0xAB, 0xF7, 0x25, 0x88, 0x09, 0xCF, 0x4F, 0x3C }

#else

abp_device

Commissioning.h

/*!
 * When set to 1 the application uses the Over-the-Air activation procedure
 * When set to 0 the application uses the Personalization activation procedure
 */
#define OVER_THE_AIR_ACTIVATION                     0
#else

/*!
 * Current network ID
 */
#define LORAWAN_NETWORK_ID                          ( uint32_t )0x03

/*!
 * Device address on the network (big endian)
 */
#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0x06100000

/*!
 * AES encryption/decryption cipher network session key
 */
#define LORAWAN_NWKSKEY                             { 0xAE, 0xB4, 0x8D, 0x4C, 0x6E, 0x9E, 0xA5, 0xC4, 0x8C, 0x37, 0xE4, 0xF1, 0x32, 0xAA, 0x85, 0x16 }
/*!
 * AES encryption/decryption cipher application session key
 */
#define LORAWAN_APPSKEY                             { 0x79, 0x87, 0xA9, 0x6F, 0x26, 0x7F, 0x0A, 0x86, 0xB7, 0x39, 0xEE, 0xD4, 0x80, 0xFC, 0x2B, 0x3C }

#endif

Message Payload

For both devices, we include the following code in main.cpp to generate a float value to be sent as the application's temperature payload. We will periodically send a confirmed message with the temperature with a random value between 42 and 50, using fport 15.

/*!
 * Join requests trials duty cycle.
 */
#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us

/*!
 * Defines the application data transmission duty cycle. 30s, value in [us].
 */
#define APP_TX_DUTYCYCLE                            30000000

/*!
 * Defines a random delay for application data transmission duty cycle. 10s,
 * value in [us].
 */
#define APP_TX_DUTYCYCLE_RND                        10000000

/*!
 * Default mote datarate
 */
#define LORAWAN_DEFAULT_DATARATE                    DR_4

/*!
 * LoRaWAN confirmed messages
 */
#define LORAWAN_CONFIRMED_MSG_ON                    true

/*!
 * LoRaWAN Adaptive Data Rate
 *
 * \remark Please note that when ADR is enabled the end-device should be static
 */
#define LORAWAN_ADR_ON                              1
/*!
 * LoRaWAN application port
 */
#define LORAWAN_APP_PORT                            15

/*!
 * \brief   Prepares the payload of the frame
 */
static void PrepareTxFrame( uint8_t port )
{
	float temp, v;

    switch( port )
    {
    case 15:
        {
        	// Generate a random number 0 < a < 8.0 and add to 42
        	v = ((float)rand()/(float)(RAND_MAX)) * 8.0;
        	temp = 42.0 + v;

        	AppDataSize = sizeof(temp);
        	std::memcpy(AppData, &temp, AppDataSize);
        }
        break;

Once compiled, the project binary is installed to each MDot device's flash storage.

Gateway

A single Multitech Conduit gateway is connected to a wired Ethernet port on the same LAN as Floranet server. To configure an IP address on the interface, login to the gateway's web interface and perform the following steps:

  • Choose the Setup item from the menu then Network Interfaces
  • Edit the eth0 interface by clicking the icon under Options
  • In the popup window configure the appropriate address information. See below.

For the Multitech Conduit, it is necessary to change the system to operate as a Basic Packet Forwarder. Instructions for doing this:

As per the guides above, the global.json file used for the reference network is included below. Note that the Australian 915-928 MHz band is being used, and the FloraNet server is listening on the IP address 192.168.1.100, UDP port 1700.

{
	"SX1301_conf": {
		"lorawan_public": true,
		"clksrc": 1,
		"clksrc_desc": "radio_1 provides clock to concentrator",
		"radio_0": {
			"enable": true,
			"type": "SX1257",
			"freq": 915500000,
			"rssi_offset": -166.0,
			"tx_enable": true
		},
		"radio_1": {
			"enable": true,
			"type": "SX1257",
			"freq": 916300000,
			"rssi_offset": -166.0,
			"tx_enable": false
		},
		"chan_multiSF_0": {
			"desc": "Lora MAC, 125kHz, all SF, 916.8 MHz",
			"enable": true,
			"radio": 0,
			"if": -300000
		},
		"chan_multiSF_1": {
			"desc": "Lora MAC, 125kHz, all SF, 917.0 MHz",
			"enable": true,
			"radio": 0,
			"if": -100000
		},
		"chan_multiSF_2": {
			"desc": "Lora MAC, 125kHz, all SF, 917.2 MHz",
			"enable": true,
			"radio": 0,
			"if": 100000
		},
		"chan_multiSF_3": {
			"desc": "Lora MAC, 125kHz, all SF, 917.4 MHz",
			"enable": true,
			"radio": 0,
			"if": 300000
		},
		"chan_multiSF_4": {
			"desc": "Lora MAC, 125kHz, all SF, 917.6 MHz",
			"enable": true,
			"radio": 1,
			"if": -300000
		},
		"chan_multiSF_5": {
			"desc": "Lora MAC, 125kHz, all SF, 917.8 MHz",
			"enable": true,
			"radio": 1,
			"if": -100000
		},
		"chan_multiSF_6": {
			"desc": "Lora MAC, 125kHz, all SF, 918.0 MHz",
			"enable": true,
			"radio": 1,
			"if": 100000
		},
		"chan_multiSF_7": {
			"desc": "Lora MAC, 125kHz, all SF, 918.2 MHz",
			"enable": true,
			"radio": 1,
			"if": 300000
		},
		"chan_Lora_std": {
			"desc": "Lora MAC, 500kHz, SF8, 917.5 MHz",
			"enable": true,
			"radio": 0,
			"if": 400000,
			"bandwidth": 500000,
			"spread_factor": 8
		},
		"chan_FSK": {
			"desc": "FSK disabled",
			"enable": false
		},
		"tx_lut_0": {
			"desc": "TX gain table, index 0",
			"pa_gain": 0,
			"mix_gain": 8,
			"rf_power": -6,
			"dig_gain": 0
		},
		"tx_lut_1": {
			"desc": "TX gain table, index 1",
			"pa_gain": 0,
			"mix_gain": 10,
			"rf_power": -3,
			"dig_gain": 0
		},
		"tx_lut_2": {
			"desc": "TX gain table, index 2",
			"pa_gain": 0,
			"mix_gain": 12,
			"rf_power": 0,
			"dig_gain": 0
		},
		"tx_lut_3": {
			"desc": "TX gain table, index 3",
			"pa_gain": 1,
			"mix_gain": 8,
			"rf_power": 3,
			"dig_gain": 0
		},
		"tx_lut_4": {
			"desc": "TX gain table, index 4",
			"pa_gain": 1,
			"mix_gain": 10,
			"rf_power": 6,
			"dig_gain": 0
		},
		"tx_lut_5": {
			"desc": "TX gain table, index 5",
			"pa_gain": 1,
			"mix_gain": 12,
			"rf_power": 10,
			"dig_gain": 0
		},
		"tx_lut_6": {
			"desc": "TX gain table, index 6",
			"pa_gain": 1,
			"mix_gain": 13,
			"rf_power": 11,
			"dig_gain": 0
		},
		"tx_lut_7": {
			"desc": "TX gain table, index 7",
			"pa_gain": 2,
			"mix_gain": 9,
			"rf_power": 12,
			"dig_gain": 0
		},
		"tx_lut_8": {
			"desc": "TX gain table, index 8",
			"pa_gain": 1,
			"mix_gain": 15,
			"rf_power": 13,
			"dig_gain": 0
		},
		"tx_lut_9": {
			"desc": "TX gain table, index 9",
			"pa_gain": 2,
			"mix_gain": 10,
			"rf_power": 14,
			"dig_gain": 0
		},
		"tx_lut_10": {
			"desc": "TX gain table, index 10",
			"pa_gain": 2,
			"mix_gain": 11,
			"rf_power": 16,
			"dig_gain": 0
		},
		"tx_lut_11": {
			"desc": "TX gain table, index 11",
			"pa_gain": 3,
			"mix_gain": 9,
			"rf_power": 20,
			"dig_gain": 0
		},
		"tx_lut_12": {
			"desc": "TX gain table, index 12",
			"pa_gain": 3,
			"mix_gain": 10,
			"rf_power": 23,
			"dig_gain": 0
		},
		"tx_lut_13": {
			"desc": "TX gain table, index 13",
			"pa_gain": 3,
			"mix_gain": 11,
			"rf_power": 25,
			"dig_gain": 0
		},
		"tx_lut_14": {
			"desc": "TX gain table, index 14",
			"pa_gain": 3,
			"mix_gain": 12,
			"rf_power": 26,
			"dig_gain": 0
		},
		"tx_lut_15": {
			"desc": "TX gain table, index 15",
			"pa_gain": 3,
			"mix_gain": 14,
			"rf_power": 27,
			"dig_gain": 0
		}
	},
	"gateway_conf": {
        "gateway_ID" : "00:08:00:4A:03:B0",
		"server_address": "192.168.1.100",
		"serv_port_up": 1700,
		"serv_port_down": 1700,
                "forward_crc_error": false,
		"servers": [ {
			"server_address": "192.168.1.100",
			"serv_port_up": 1700, 
			"serv_port_down": 1700, 
			"serv_enabled": true
		} ]
	}

}

Azure IoT Hub

Azure IoT Hub is a component of Microsoft's cloud-hosted IoT solution. As shown in the architecture diagram below, Azure IoT Hub provides reliable bidirectional communications between IoT devices and a solution back end. Note additional Azure IoT services are required to build a complete IoT solution; in this reference implementation we will only deal with the IoT Hub component to verify device-to-cloud messaging.

Azure IoT Architecture

As outlined in the Setup Guide, Floranet only supports the Azure HTTPS protocol to send time-series telemetry from devices, and to receive Azure IoT cloud-to-device messages. As per the architecture diagram, Floranet acts as a IP-capable device that proxies for the connected LoRa wireless devices.

Create the Test IoT Hub

To create an Azure IoT hub, follow the steps in the Azure guide Create an IoT hub using the Azure portal. Once completed, we will use three parameters defined in the IoT Hub configuration.

Setting Parameter Typical Value
Overview hostname iothubname.azure-devices.net
Shared Access Policies Policy name iothubowner
Shared Access Policies iothubowner Primary key alphanumeric string

Create the IoT Hub Devices

In the Azure portal, choose Device Explorer in the IoT Hub, and click Add. Create the following devices:

  • azuredevice01
  • azuredevice02

FloraNet

Based on the application requirements outlined above, we will configure Floranet's system parameters as shown below.

Parameter Value Comment
name floranet-test
listen 0.0.0.0 Default
port 1700 Default
webport 8000 Default
apitoken Use factory default
freqband AU915
netid 010203 Default
duplicateperiod 10 Default
fcrelaxed yes Default
otaastart 0600.0001 Default
otaaend 060f.ffff Default
macqueueing yes Default
macqueuelimit 120 Default

FLoraNet is installed on the target system as per the Setup Guide.

In the following steps, we will assume a fresh installation, with factory defaults loaded when the server is first started.

$ floranet -c database.cfg -d -f
2017-11-08T10:42:25+1000 [Floranet#info] Starting up
2017-11-08T10:42:25+1000 [Floranet#info] Reading database configuration from database.cfg
2017-11-08T10:42:25+1000 [Floranet#info] No system configuration found. Loading factory defaults
2017-11-08T10:42:25+1000 [Floranet#info] Initialising the server
2017-11-08T10:42:25+1000 [Floranet#info] Starting the server
2017-11-08T10:42:25+1000 [Floranet#info] Starting the web server
2017-11-08T10:42:25+1000 [-] Site starting on 8000
2017-11-08T10:42:25+1000 [twisted.web.server.Site#info] Starting factory <twisted.web.server.Site instance at 0x104cec170>
2017-11-08T10:42:25+1000 [Floranet#info] Starting the LoRaWAN interface
2017-11-08T10:42:25+1000 [-] LoraWAN starting on 1700
2017-11-08T10:42:25+1000 [-] Starting protocol <floranet.lora.wan.LoraWAN instance at 0x104cf3248>

System Configuration

Set the required system parameters using floracmd as shown.

$ export FLORANET_TOKEN='IMxHj@wfNkym@*+V85Rs^G<QXMD~p[eaX3S=_D8f7{z0q{GN'
$ floracmd
Using floranet server localhost:8000
floranet> system set name=floranet-test freqband=AU915
floranet> system show
System: floranet-test at localhost:8000
          Network interface: 0.0.0.0
          LoraWAN port: 1700
          Web server port: 8000
          Frequency band: AU915
          Network ID: 0x01.02.03
          OTAA Address Range: 0x0600.0001 - 0x060f.ffff
          ADR enabled: Yes
          ADR margin: 0.0 dB
          ADR cycle time: 9000 s
          ADR message time: 10 s
          Relaxed frame count: Yes
          MAC queueing: Yes
          MAC queue limit: 120 s
floranet> 

Application Configuration

Create a new application that defines the security context for our devices. Ensure the parameters (AppEUI and Appkey) match those defined above.

floranet> app add 0a0b.0c0d.0a0b.0c0d name='Azure IoT Test App' appkey=0173.1516.38ae.c2a6.abf7.2588.09cf.4f3c appnonce=04fe92 fport=15
floranet> app show 0a0b.0c0d.0a0b.0c0d
Application EUI: 0a0b.0c0d.0a0b.0c0d
          name: Azure IoT Test App
          domain: -
          fport: 15
          interface: -

Application Interface

Create a new Application Interface for the Azure IoT Hub instance, and add this to our Azure IoT Test App application created above.

floranet> interface add azure protocol=https name='Test Iot Hub Interface' iothost=testhub00123.azure-devices.net keyname=iothubowner keyvalue='oVk97f4/CgaCQ1nZMk3QYDU8vYx5wgipKfX0Av2STc8=' pollinterval=30
floranet> interface show all
ID  Name                    Type           
  1 Test Iot Hub Interface  Azure HTTPS   
floranet> interface show 1
          name: Test Iot Hub Interface
          protocol: HTTPS
          key name: iothubowner
          key value: oVk97f4/CgaCQ1nZMk3QYDU8vYx5wgipKfX0Av2STc8=
          Polling interval: 30 minutes
          status: Started
floranet> app set 0a0b.0c0d.0a0b.0c0d appinterface_id=1
floranet> app show 0a0b.0c0d.0a0b.0c0d
Application EUI: 0a0b.0c0d.0a0b.0c0d
          name: Azure IoT Test App
          domain: -
          fport: 15
          interface: 1
          Properties:

Application Property

The final step of the application configuration involves mapping application data received from devices as a float value, to be sent to the IoT hub as a JSON object with a 'Temperature' key.

We create this application property as follows, and display the final application configuration.

floranet> property add 0a0b.0c0d.0a0b.0c0d name=Temperature type=float port=15
floranet> app show 0a0b.0c0d.0a0b.0c0d
Application EUI: 0a0b.0c0d.0a0b.0c0d
          name: Azure IoT Test App
          domain: -
          fport: 22
          interface: 1
          Properties:
            15  Temperature:float

Gateway Configuration

Add our single gateway as shown below. The gateway address is 192.168.1.125. Note the EUI is derived form the gateway_id key in the Multitech Conduit's global.json configuration file.

floranet> gateway add 192.168.1.125 eui=0080.0000.b1af.0000 power=26 enabled=yes name="test"
floranet> gateway show all
Gateway        IP-Address       EUI                     Enabled  Power-dBm   
test           192.168.1.125    0080.0000.b1af.0000     Yes      26

Device Configuration

Finally we will add our devices as per the requirements provided above, associating both with our defined application via the appeui parameter. We use the appname parameter to identify each device to the upstream Azure IoT Hub service.

floranet> device add 0f0e.0e0d.0001.0203 name=ota_device appeui=0a0b.0c0d.0a0b.0c0d otaa=yes enabled=yes appname=azure_device01
floranet> device add 0f0e.0e0d.0000.0001 name=abp_device appeui=0a0b.0c0d.0a0b.0c0d otaa=no devaddr=0610.0000 nwkskey=aeb4.8d4c.6e9e.a5c4.8c37.e4f1.32aa.8516 appskey=7987.a96f.267f.0a86.b739.eed4.80fc.2b3c appname=azure_device02 enabled=yes 
floranet> device show all
Device         DeviceEUI               DevAddr     Enabled  Act  Average-SNR 
abp_device     0f0e.0e0d.0000.0001     0610.0000   Yes      ABP  N/A         
ota_device     0f0e.0e0d.0001.0203     0000.0000   Yes      OTA  N/A

Testing and Verification

Gateway Connectivity

Once started, the gateway will start exchanging GWMP messages to Floranet. The log indicates the gateway is connected via the following messages.

2017-11-11T16:57:12+1000 [Floranet#debug] Received '\x01\xf8\r\x02\x00\x80\x00\x00\x00\x00\xa3\xf9' from 192.168.1.125:57102
2017-11-11T16:57:12+1000 [Floranet#debug] Received PULL_DATA from 192.168.1.125:57102
2017-11-11T16:57:12+1000 [Floranet#debug] Sending PULL_ACK message to 192.168.1.125:57102
2017-11-11T16:57:12+1000 [Floranet#debug] Sending '\x01\xf8\r\x04\x00\x80\x00\x00\x00\x00\xa3\xf9' to 192.168.1.125:57102

Device Connectivity

When the OTA device is powered up, it will send a Join Request message to Floranet, which will respond with the Join Accept. The following log messages demonstrate this sequence.

2017-11-11T17:13:11+1000 [Floranet#debug] Received '\x01x\xb0\x00\x00\x80\x00\x00\x00\x00\xa3\xf9{"rxpk":[{"tmst":1946593944,"time":"2017-11-11T07:12:24.993659Z","chan":8,"rfch":0,"freq":915.900000,"stat":1,"modu":"LORA","datr":"SF8BW500","codr":"4/5","lsnr":10.0,"rssi":-34,"size":23,"data":"AA0MCwoNDAsKAwIBAA0ODg/QRfgdsU4="}]}' from 192.168.1.125:56246
2017-11-11T17:13:11+1000 [Floranet#info] Successful Join request from DevEUI 0f0e.0e0d.0001.0203 for AppEUI 0a0b.0c0d.0a0b.0c0d | Assigned address 0600.0001
2017-11-11T17:13:11+1000 [Floranet#info] Sending join response for devaddr 0600.0001
2017-11-11T17:13:11+1000 [Floranet#debug] Sending PULL_RESP message to 192.168.1.125:57102
2017-11-11T17:13:11+1000 [Floranet#debug] Sending '\x01\x00\x00\x03{"txpk":{"tmst":1947593944,"freq":923.3,"rfch":0,"powe":26,"modu":"LORA","datr":"SF9BW500","codr":"4/5","ipol":true,"size":17,"data":"IIdVh5MbEm9pEenIp4eLg4E","ncrc":false}}' to 192.168.1.125:57102
2017-11-11T17:13:11+1000 [Floranet#debug] Sending PULL_RESP message to 192.168.1.125:57102
2017-11-11T17:13:11+1000 [Floranet#debug] Sending '\x01\x00\x00\x03{"txpk":{"tmst":1948593944,"freq":923.3,"rfch":0,"powe":26,"modu":"LORA","datr":"SF12BW500","codr":"4/5","ipol":true,"size":17,"data":"IIdVh5MbEm9pEenIp4eLg4E","ncrc":false}}' to 192.168.1.125:57102

Once connected and sufficient messages are received, we can check the device's connectivity via floracmd:

floranet> device show all
Device         DeviceEUI               DevAddr     Enabled  Act  Average-SNR 
ota_device     0f0e.0e0d.0001.0203     0600.0001   Yes      OTA  11.00 dBm   
abp_device     0f0e.0e0d.0000.0001     0610.0000   Yes      ABP  N/A      

Note that you can also connect a VT100 terminal to the device via it's USB interface, and verify it is authenticated and is sending messages.

The ABP device does not require the Join procedure, and simply uses its pre-defined paramaters to start sending application messages.

Azure Device-to-Cloud Messaging

As LoRaWAN messages are received from each device, Floranet uses the application property to send Azure device-to-cloud messages to the configured IoT Hub instance.

In order to verify the transfer of device application data to the IoT Hub test instance, we will use the Device Explorer application.

Once installed, under the Configuration tab, enter the IoT Hub connection string, which can be obtained from the Azure IoT Hub portal via Shared access policies and iothubowner. Click on the Copy button to copy the Connection string - primary key string, past it into the Configuration tab, and click Update.

You can then click on the Data tab, choose a device from the dropdown list, and click on Monitor to view the messages being sent.