├── docs ├── assets │ ├── lora1.png │ ├── lora10.png │ ├── lora11.png │ ├── lora12.png │ ├── lora13.png │ ├── lora14.png │ ├── lora15.png │ ├── lora16.png │ ├── lora17.png │ ├── lora18.jpg │ ├── lora19.png │ ├── lora2.png │ ├── lora3.png │ ├── lora4.png │ ├── lora5.jpg │ ├── lora6.jpg │ ├── lora7.png │ ├── lora8.png │ ├── lora9.png │ ├── stream1.png │ ├── stream10.png │ ├── stream11.png │ ├── stream12.png │ ├── stream13.png │ ├── stream14.png │ ├── stream2.png │ ├── stream3.png │ ├── stream4.png │ ├── stream5.png │ ├── stream6.png │ ├── stream7.png │ ├── stream8.png │ ├── stream9.png │ ├── ttn1.png │ ├── ttn10.png │ ├── ttn11.png │ ├── ttn12.png │ ├── ttn13.png │ ├── ttn14.png │ ├── ttn15.png │ ├── ttn16.png │ ├── ttn17.png │ ├── ttn18.png │ ├── ttn19.png │ ├── ttn2.png │ ├── ttn3.png │ ├── ttn4.png │ ├── ttn5.png │ ├── ttn6.png │ ├── ttn7.png │ ├── ttn8.png │ └── ttn9.png ├── index.md └── intro-to-lora.md ├── mkdocs.yml └── ttn-node-app ├── .gitignore ├── package.json ├── public ├── ARMmbedLogo.svg ├── helper.js └── style.css ├── server.js └── views └── index.html /docs/assets/lora1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora1.png -------------------------------------------------------------------------------- /docs/assets/lora10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora10.png -------------------------------------------------------------------------------- /docs/assets/lora11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora11.png -------------------------------------------------------------------------------- /docs/assets/lora12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora12.png -------------------------------------------------------------------------------- /docs/assets/lora13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora13.png -------------------------------------------------------------------------------- /docs/assets/lora14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora14.png -------------------------------------------------------------------------------- /docs/assets/lora15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora15.png -------------------------------------------------------------------------------- /docs/assets/lora16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora16.png -------------------------------------------------------------------------------- /docs/assets/lora17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora17.png -------------------------------------------------------------------------------- /docs/assets/lora18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora18.jpg -------------------------------------------------------------------------------- /docs/assets/lora19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora19.png -------------------------------------------------------------------------------- /docs/assets/lora2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora2.png -------------------------------------------------------------------------------- /docs/assets/lora3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora3.png -------------------------------------------------------------------------------- /docs/assets/lora4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora4.png -------------------------------------------------------------------------------- /docs/assets/lora5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora5.jpg -------------------------------------------------------------------------------- /docs/assets/lora6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora6.jpg -------------------------------------------------------------------------------- /docs/assets/lora7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora7.png -------------------------------------------------------------------------------- /docs/assets/lora8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora8.png -------------------------------------------------------------------------------- /docs/assets/lora9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/lora9.png -------------------------------------------------------------------------------- /docs/assets/stream1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream1.png -------------------------------------------------------------------------------- /docs/assets/stream10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream10.png -------------------------------------------------------------------------------- /docs/assets/stream11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream11.png -------------------------------------------------------------------------------- /docs/assets/stream12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream12.png -------------------------------------------------------------------------------- /docs/assets/stream13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream13.png -------------------------------------------------------------------------------- /docs/assets/stream14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream14.png -------------------------------------------------------------------------------- /docs/assets/stream2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream2.png -------------------------------------------------------------------------------- /docs/assets/stream3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream3.png -------------------------------------------------------------------------------- /docs/assets/stream4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream4.png -------------------------------------------------------------------------------- /docs/assets/stream5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream5.png -------------------------------------------------------------------------------- /docs/assets/stream6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream6.png -------------------------------------------------------------------------------- /docs/assets/stream7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream7.png -------------------------------------------------------------------------------- /docs/assets/stream8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream8.png -------------------------------------------------------------------------------- /docs/assets/stream9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/stream9.png -------------------------------------------------------------------------------- /docs/assets/ttn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn1.png -------------------------------------------------------------------------------- /docs/assets/ttn10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn10.png -------------------------------------------------------------------------------- /docs/assets/ttn11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn11.png -------------------------------------------------------------------------------- /docs/assets/ttn12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn12.png -------------------------------------------------------------------------------- /docs/assets/ttn13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn13.png -------------------------------------------------------------------------------- /docs/assets/ttn14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn14.png -------------------------------------------------------------------------------- /docs/assets/ttn15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn15.png -------------------------------------------------------------------------------- /docs/assets/ttn16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn16.png -------------------------------------------------------------------------------- /docs/assets/ttn17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn17.png -------------------------------------------------------------------------------- /docs/assets/ttn18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn18.png -------------------------------------------------------------------------------- /docs/assets/ttn19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn19.png -------------------------------------------------------------------------------- /docs/assets/ttn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn2.png -------------------------------------------------------------------------------- /docs/assets/ttn3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn3.png -------------------------------------------------------------------------------- /docs/assets/ttn4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn4.png -------------------------------------------------------------------------------- /docs/assets/ttn5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn5.png -------------------------------------------------------------------------------- /docs/assets/ttn6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn6.png -------------------------------------------------------------------------------- /docs/assets/ttn7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn7.png -------------------------------------------------------------------------------- /docs/assets/ttn8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn8.png -------------------------------------------------------------------------------- /docs/assets/ttn9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/lora-docs/7452c6ce6f695468b4568f8c318e0b108985e157/docs/assets/ttn9.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # LoRa on Arm Mbed OS 2 | 3 | [LoRaWAN](http://lora-alliance.org) is a long range wide-area network technology that combines long range with low power consumption. This space contains documents on how to start building LoRa networks and LoRa appliances using Arm Mbed. 4 | -------------------------------------------------------------------------------- /docs/intro-to-lora.md: -------------------------------------------------------------------------------- 1 | ## Building your own private LoRa network 2 | 3 | There is a lot of interest in [LoRa](https://www.lora-alliance.org), a wide-area network solution that promises kilometers of range with low power consumption, a perfect fit for the Internet of Things. Telecom operators are rolling out LoRa networks, but because LoRa operates in the [open spectrum](https://en.wikipedia.org/wiki/ISM_band), you can also set up your own network. This article discusses what you need to build a private LoRa network and how to use the network to send data from an Arm Mbed end node to the cloud. 4 | 5 | **Note on LoRa vs. LoRaWAN:** Technically, this article explains how to build a LoRaWAN network. LoRa is the modulation technique used (PHY), and LoRaWAN is the network protocol on top of the physical layer (MAC). 6 | 7 | ### 1. What you need 8 | 9 | A typical LoRa network consists of four parts: devices, gateways, a network service and an application: 10 | 11 | ![Topology of a LoRa network](assets/lora1.png)Topology of a LoRa network 12 | 13 | For hardware, you need devices and gateways, similar to how you would set up a Wi-Fi network. Gateways are simple: they scan the spectrum and capture LoRa packets. There is no gateway pinning here. Devices are not associated with a single gateway; thus, all gateways within range of a device receive the signal. The gateways then forward their data to a network service that handles the packet. 14 | 15 | The network service deduplicates packets when multiple gateways receive the same packet, decrypts the message (everything is end-to-end encrypted) and handles LoRa features, such as adaptive data rating. It then forwards the decrypted data to your application. Often, network service providers allow you to run parts of the network - such as the application server, which decrypts the messages - yourself. 16 | 17 | You need hardware: 18 | 19 | - Gateways. 20 | - Devices. 21 | 22 | And software: 23 | 24 | - Device firmware. 25 | - A network service. 26 | - An app. 27 | 28 | This guide shows you: 29 | 30 | - Which hardware you can buy. 31 | - How to configure a gateway. 32 | - How to write device firmware. 33 | - How to set up a web application to show your LoRa traffic. 34 | 35 | **Note:** The frequency that LoRa uses differs among regions. Make sure your gateways and devices are legal in your jurisdiction. For example, use 915 MHz radios in the United States and 868 MHz radios in Europe. You can find more information in the [LoRaWAN regional parameters](http://net868.ru/assets/pdf/LoRaWAN-Regional-Parameters-v1.1rA.PDF) specification. 36 | 37 | #### 1.1 - Choosing a gateway 38 | 39 | You have [many choices in the gateways](https://www.loriot.io/lora-gateways.html) you can use, but we've had good experience with these three: 40 | 41 | - [Kerlink Wirnet station](https://www.kerlink.com/product/wirnet-station/). Expensive (around 1,200 euros) but great build quality and range. 42 | - [MultiTech conduit](http://www.multitech.com/brands/multiconnect-conduit). About 1/3 of the price of the Kerlink (about 450 euros) and good for smaller setups. MultiTech also has a [rugged outdoor](http://www.multitech.com/brands/multiconnect-conduit-ip67) version. Make sure you also order the LoRa mCard. 43 | - Building your own with a Raspberry Pi and an [IMST iC880A](http://shop.imst.de/wireless-modules/lora-products/8/ic880a-spi-lorawan-concentrator-868-mhz) concentrator. At about 150 euros, this is a cost-efficient option. 44 | 45 | ![Self-built gateway using a Raspberry Pi and an IMST iC880A](assets/lora5.jpg)Self-built LoRa gateway based on Raspberry Pi 2 and IMST iC880A. Total cost is about 150 euros. 46 | 47 | For development purposes, one gateway is enough, but in a production deployment, you need at least two because there will always be dark spots in your network. 48 | 49 | ![Kerlink Wirnet station mounted in Oslo](assets/lora18.jpg)Kerlink Wirnet station overlooking the Oslo fjord. 50 | 51 | #### 1.2 - Choosing a device 52 | 53 | You also need to build devices. If you use Mbed OS (and you should), you can either use: 54 | 55 | - A development board with a LoRa transceiver: 56 | - [L-Tek FF1705](https://os.mbed.com/platforms/L-TEK-FF1705/). 57 | - [MultiTech xDot](https://os.mbed.com/platforms/MTS-xDot-L151CC/). 58 | - [MultiTech mDot](https://os.mbed.com/platforms/MTS-mDot-F411/) and the [UDK2 board](http://www.digikey.com/product-detail/en/multi-tech-systems-inc/MTUDK2-ST-MDOT/591-1278-ND/5247463). 59 | - [MultiTech mDot EVB](https://os.mbed.com/platforms/mdotevb/). 60 | - [B-L072Z-LRWAN1 LoRa®Discovery kit](https://os.mbed.com/platforms/ST-Discovery-LRWAN1/). 61 | - An Mbed OS 5 Enabled development board together with a LoRa shield: 62 | - [SX1272MB2xAS](https://os.mbed.com/components/SX1272MB2xAS/) - shield based on the SX1272 transceiver. 63 | - [SX1276MB1xAS](https://os.mbed.com/components/SX1276MB1xAS/) - shield based on the SX1276 transceiver. 64 | 65 | This tutorial applies to all combinations listed above. 66 | 67 | **Note:** When ordering hardware, always make sure you get the variant that works in your region (for example 868 MHz in Europe and 915 MHz in the US). 68 | 69 | #### 1.3 - Network server 70 | 71 | For software, you need a server that understands the LoRa protocol and can interpret the data the device sends. It's possible to use your own (Semtech can give you its reference implementation if you sign an NDA), but there are also companies building LoRa network servers as a service, handling everything on your behalf. This article uses [The Things Network](https://www.thethingsnetwork.org), an open source, globally distributed network service that also has a free hosted community edition. 72 | 73 | Because a network server only processes your data and doesn't store it, you need a somewhere to store your messages, as well. The Things Network allows you to hook into its service through an MQTT client and forward your data to the cloud service of your choice (or straight to your application). 74 | 75 | ### 2. Setting up the gateway 76 | 77 | You now need to configure the gateway by installing software to scan the spectrum and forward all LoRa packets to the network server. Below are setup instructions for the three gateways suggested earlier. 78 | 79 | #### 2.1 - Prerequisites 80 | 81 | ##### Kerlink Wirnet stations 82 | 83 | Follow the instructions in [this document](https://www.thethingsnetwork.org/docs/gateways/kerlink/config.html). 84 | 85 | ##### MultiTech Conduit 86 | 87 | The conduit is configured with DHCP disabled, so you need to enable this first. There are two options to do this: either through Ethernet or through micro-USB. 88 | 89 | **Using Ethernet** 90 | 91 | 1. Connect to the conduit over Ethernet (from the conduit to your computer). 92 | 1. Set a static IP address of 192.168.2.2 for your computer. 93 | 1. Set a static IP address of 192.168.2.1 as your router. 94 | 1. Log in through SSH to 192.168.2.1 with the username `root` and password `root`. 95 | 96 | **Over micro-USB** 97 | 98 | 1. Connect to the conduit using a micro-USB cable. 99 | 1. The gateway appears as a serial device. 100 | 1. You can use a program such as [GNU Screen](https://www.gnu.org/software/screen/) or [PuTTY](http://putty.org) to log into the gateway with the username `root` and password `root`. 101 | 102 | **Note if logging in fails:** If logging in as `root` fails but you can log in with the username `admin` and the password `admin`, you are running the AEP firmware. To proceed, update your gateway firmware to mLinux. Use [these instructions](http://www.multitech.net/developer/software/mlinux/using-mlinux/flashing-mlinux-firmware-for-conduit/). 103 | 104 | Now that you are connected, you can set up the gateway: 105 | 106 | 1. Enable DHCP by following Step 4 in [this document](http://www.multitech.net/developer/software/mlinux/getting-started-with-conduit-mlinux/). 107 | 1. Connect the gateway over Ethernet to your router. 108 | 1. Verify that the gateway is connected to the internet (for example, by running `ping 8.8.4.4`). 109 | 110 | ##### Raspberry Pi 111 | 112 | Follow the instructions in [this document](https://github.com/ttn-zh/ic880a-gateway/wiki). 113 | 114 | #### 2.2 - Registering the gateway 115 | 116 | 1. [Sign up](https://console.thethingsnetwork.org) for an account at The Things Network. 117 | 1. You're redirected to the dashboard page. 118 | 1. Click **Gateways**. 119 | 120 | ![Gateways](assets/ttn1.png) 121 | 122 | 1. Click **Register gateway**. 123 | 124 | ![Add a new gateway](assets/ttn2.png) 125 | 126 | 1. Fill in the details of your gateway. 127 | 128 | ![Gateway details](assets/ttn3.png)Gateway details: The Things Network uses the gateway location to create coverage maps, so make sure the location is set correctly. 129 | 130 | 1. If you use the Kerlink Wirnet station: 131 | - Tick **I'm using the legacy packet forwarder**. 132 | - Under **Gateway EUI**, enter the EUI of the gateway (printed on the box). 133 | 134 | 1. If you use the Raspberry Pi: 135 | - Tick **I'm using the legacy packet forwarder**. 136 | - Under **Gateway EUI**, enter the EUI that printed when you called `install.sh` in step 2.1. 137 | 138 | 1. Click **Register gateway**. 139 | 1. You have created the gateway. 140 | 141 | If you use the MultiTech conduit, you need the 'Gateway key' to authenticate the gateway to the network. Copy it. 142 | 143 | ![Gateway key is required for authentication to the network](assets/ttn4.png) 144 | 145 | #### 2.3 - Installing the packet forwarder 146 | 147 | ##### Kerlink Wirnet station or Raspberry Pi 148 | 149 | No further action required. The gateway shows as 'Connected' in the TTN console. 150 | 151 | ![Connected!](assets/ttn7.png)Connected! 152 | 153 | ##### MultiTech conduit 154 | 155 | 1. On the gateway, run: 156 | 157 | ``` 158 | $ wget https://github.com/kersing/multitech-installer/raw/master/installer.sh 159 | $ sh installer.sh 160 | ``` 161 | 162 | 1. A wizard starts. Answer the questions. 163 | 164 | ![Configuring the MultiTech Conduit gateway for The Things Network](assets/ttn5.png)Wizard for configuring the MultiTech Conduit. 165 | 166 | 1. After the gateway reboots, log back in. 167 | 1. Then run (again): 168 | 169 | ``` 170 | $ sh installer.sh 171 | ``` 172 | 173 | 1. Fill in the remaining questions. 174 | 175 | ![Configuring the MultiTech Conduit gateway for The Things Network (step 2)](assets/ttn6.png)Wizard (2) for configuring the MultiTech Conduit. 176 | 177 | 1. After this, the gateway shows as **Connected** in the TTN console. 178 | 179 | ![Connected!](assets/ttn7.png)Connected! 180 | 181 | ### 3. Building a device 182 | 183 | This section explains how to build a device that can send sensor data over the LoRa network. For example, you can create a motion sensor using a [PIR sensor](https://www.adafruit.com/products/189) (less than 10 euros). Of course, you can use any other sensor. 184 | 185 | ![nRF51-DK, LoRa shield and a PIR sensor](assets/lora6.jpg)PIR sensor hooked up to a Nordic Semiconductor nRF51-DK with a SX1276 LoRa shield 186 | 187 | #### 3.1 - Some notes on writing firmware 188 | 189 | ##### Restrictions on sending data 190 | 191 | You cannot send data constantly because of spectrum regulations. Although the spectrum that LoRa uses is unlicensed, it is regulated. For example, in Europe, there are duty cycle limitations of 1% - meaning you can only send 1% of the time. In the US, there's dwell time, which requires you to wait at least 400 ms between transmissions. If you violate these regulations, your data transmission fails. How fast you are allowed to send data depends on the spread factor you use. With a higher spread factor, it takes longer to send a message - though the chance that a gateway receives it increases. However, you need to wait longer before you can send data again. During development, you can set the spread factor to SF7 (the lowest), so you can send every 6-7 seconds. 192 | 193 | LoRaWAN has a feature called Adaptive Data Rating (ADR), through which the network can control the spread factor. You probably want this enabled. 194 | 195 | ##### Blocked pins 196 | 197 | A disadvantage of the SX1272 and SX1276 LoRa shields is that they block a lot of pins. You can solder new headers on the back of the shield to add new peripherals, or use a microcontroller such as the nRF51-DK or a NUCLEO board that has more pins available than just the Arduino headers. 198 | 199 | #### 3.2 - Registering the device on The Things Network 200 | 201 | LoRaWAN uses an end-to-end encryption scheme that uses two session keys. The network server holds one key, and the application server holds the other. (In this tutorial, TTN fulfils both roles). These session keys are created when the device joins the network. For the initial authentication with the network, the application needs its device EUI, the EUI of the application it wants to join (referred to as the application EUI) and a preshared key (the application key). 202 | 203 | The device EUI and application EUI are globally unique identifiers. You can buy a block of EUIs from the [IEEE](http://standards.ieee.org/develop/regauth/tut/eui.pdf). Modules often already come with an EUI, which is printed on the device. If you're using a radio shield you can use an EUI from The Things Network's block. 204 | 205 | **Note:** In LoRaWAN 1.1, the join key replaces the application key, and the join server handles the initial authentication. However, at the time of writing, this is not implemented on The Things Network. 206 | 207 | Register the device in The Things Network, and generate some keys: 208 | 209 | 1. Go to [The Things Network console](https://console.thethingsnetwork.org). 210 | 1. Click **Applications**. 211 | 1. Click **Add application**. 212 | 213 | ![Add application in TTN](assets/ttn8.png) 214 | 215 | 1. Fill in the details of your application, and click **Add application**. 216 | 217 | ![Application details](assets/ttn9.png)Filling in the application details in The Things Network. 218 | 219 | 1. You're redirected to the application page. Under **Devices**, click **Register device**. 220 | 221 | ![Register device](assets/ttn10.png) 222 | 223 | 1. If your device has an EUI printed on it, enter this in **Device EUI**. 224 | 225 | ![Device EUI on a LoRa module](assets/ttn11.png)The device EUI is often printed on the module or on the box. 226 | 227 | 1. If your device does not have an EUI printed on it, press the **generate** button to allocate an EUI from a block owned by The Things Network. Do **not** make an EUI up; it must be globally unique. 228 | 229 | ![Generating Device EUI](assets/ttn12.png) 230 | 231 | 1. Fill in the rest of the details, and click **Register**. 232 | 233 | ![Registering a new device in TTN](assets/ttn13.png) 234 | 235 | 1. The device page opens. It contains the keys that your device uses when authenticating with the network. Click the `<>` button to get the keys as a byte array. This makes it easy to copy the keys into code. 236 | 237 | ![Showing device keys in TTN](assets/ttn14.png) 238 | 239 | Now that the device is registered in The Things Network, you can start writing code! 240 | 241 | #### 3.3 - Importing the demo application 242 | 243 | Mbed comes with the Arm Mbed Online Compiler, which you can use to build applications without needing to install anything on your computer. (Mbed also has [offline tools](https://os.mbed.com/docs/latest/tools/index.html)). 244 | 245 | 1. [Sign up](https://os.mbed.com/account/signup/?next=%2F) for an account on Arm Mbed, which hosts the Online Compiler. 246 | 1. Find your development board on [the platforms page](https://os.mbed.com/platforms/). 247 | 1. Click **Add to your Mbed Compiler**. 248 | 1. Go to [mbed-os-example-lorawan](https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-lorawan/). 249 | 1. Click **Import this program**. 250 | 1. You're redirected to the Online Compiler, where you can give the program a name. 251 | 252 | ![Importing a program to get started](assets/lora7.png)Importing a program to get started 253 | 254 | **Note:** Make sure you select the correct board in the top right corner of the compiler. 255 | 256 | ![Selecting the right board](assets/lora8.png)Selecting the correct board 257 | 258 | #### 3.4 - Setting keys 259 | 260 | In the Online Compiler: 261 | 262 | 1. Open `mbed_app.json`. This file contains the configuration for the application and holds the authentication keys. 263 | 1. If you have a SX1272 or SX1276 **shield** (not if you have a module), set your radio type under `lora-radio`. 264 | 1. Under `lora.device-eui`, enter the device EUI from the TTN console. 265 | 1. Under `lora.application-eui`, enter the application EUI from the TTN console. 266 | 1. Under `lora.application-key`, enter the application key from the TTN console. 267 | 268 | ![Putting the LoRaWAN authentication keys in mbed_app.json](assets/ttn15.png)Correct keys set in `mbed_app.json` 269 | 270 | 1. Under `lora.phy` specify the channel plan for your region. A list of possible values is listed under '[Selecting a PHY'](https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-lorawan#selecting-a-phy) in the docs. 271 | 272 | ##### Sending the value of the PIR sensor 273 | 274 | To send the current value of the PIR sensor (whether it sees movement), in the Online Compiler: 275 | 276 | 1. Open `main.cpp`. 277 | 1. Replace the function `send_message()` with: 278 | 279 | ```cpp 280 | static void send_message() { 281 | static InterruptIn pir(D5); // If you hooked the sensor up to a different pin, change it here 282 | 283 | // create a one-byte payload which contains whether the PIR sensor is *high* or *low* 284 | uint8_t buffer[] = { pir.read() }; 285 | int16_t retcode = lorawan.send(LORAWAN_APP_PORT, buffer, sizeof(buffer), MSG_CONFIRMED_FLAG); 286 | 287 | if (retcode == 0) { 288 | printf("Sent message over LoRaWAN successfully!\n"); 289 | } 290 | else { 291 | printf("Failed to send message (duty-cycle violation?) (%d)\n", retcode); 292 | } 293 | } 294 | ``` 295 | 296 | #### 3.5 - Verifying the setup 297 | 298 | Now you can verify whether the setup works by flashing this application to your board. 299 | 300 | 1. In the Online Compiler, click the **Compile** button. 301 | 302 | ![Compile button](assets/lora10.png)Compile button 303 | 304 | 1. When compilation succeeds, the compiler sends a file to your computer. 305 | 1. Plug your development board into the computer (over micro-USB) to mount it as a USB mass storage device. In most cases, you do not need a driver, but you can find drivers [here](https://os.mbed.com/docs/latest/tutorials/windows-serial-driver.html). 306 | 1. Once the device mounts, drag the compiled file onto the board. This causes the device to boot. You can then see the device joining and then sending messages in the The Things Network console, under the **Data** tab: 307 | 308 | ![Data](assets/ttn19.png)We've got data! 309 | 310 | **Note 1:** You can hook a [serial monitor](https://os.mbed.com/docs/latest/tutorials/serial-comm.html) up to the development board (baud rate 115,200) to see debugging messages. 311 | 312 | **Note 2:** No data in the **Data** tab? Verify that the gateway can receive messages. In the TTN console, go to your gateway, and see if any data comes through under the **Traffic** tab. If you see your device there but not under the device page, the keys are probably wrong. 313 | 314 | ##### Sending manually 315 | 316 | By default, the application sends data automatically. If you want to change this, remove this line from `main.cpp`: 317 | 318 | ```cpp 319 | ev_queue.call_every(TX_TIMER, send_message); 320 | ``` 321 | 322 | Call `send_message` whenever you want (for example after the state of the sensor changes). Note that you still need to adhere to the duty cycle, so you may not be able to send data immediately. 323 | 324 | #### 3.6 - Relaying data back to the device 325 | 326 | You can also send data back to the device. Because LoRaWAN (in Class-A mode, which you're using here) is not continuously connected to the network, you need to wait for a receive (RX) window to occur to receive data. An RX window opens after a transmission. So you need to *send* to the network before you can receive a message. If you send a message from The Things Network to your device, the network automatically queues the message and delivers it in the next RX window. 327 | 328 | You can toggle the LED on your development board over LoRa. In the Online Compiler: 329 | 330 | 1. Open `main.cpp`. 331 | 1. Replace the `receive_message` function with: 332 | 333 | ```cpp 334 | static void receive_message() { 335 | static DigitalOut led(LED1, 0); // the LED under control, default value of 0 336 | 337 | int16_t retcode = lorawan.receive(LORAWAN_APP_PORT, rx_buffer, 338 | LORAMAC_PHY_MAXPAYLOAD, 339 | MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG); 340 | 341 | // ignore errors while retrieving 342 | if (retcode < 0) return; 343 | 344 | led = rx_buffer[0]; // set the value of the LED depending on the first byte in the message 345 | 346 | printf("Received %d bytes: ", retcode); 347 | for (uint8_t i = 0; i < retcode; i++) { 348 | printf("%x", rx_buffer[i]); 349 | } 350 | printf("\n"); 351 | } 352 | ``` 353 | 354 | **Note:** On some development boards, writing `0` to the LED turns them on. On others, writing `1` does this. It depends on the wiring of the board. 355 | 356 | 1. Compile, and flash the application. 357 | 1. When the device is back online, use the The Things Network console to queue a message. Go to your device page, and under **Downlink**, select port **21** and data `01`. Then press **Send**. 358 | 359 | ![Queuing a downlink message using the TTN console](assets/ttn16.png)Queuing a downlink message over port 21 360 | 361 | 1. After the next transmission, the LED toggles, and a message appears on the serial console. Try the same thing now by sending `0`. 362 | 363 | ### 4. Getting your data out of the The Things Network 364 | 365 | The system works and sends data in two directions, but the data is not stored anywhere. You can change that. The Things Network offers a data API to get the data out of the network. You can then store it on your own servers or forward it to a cloud service. 366 | 367 | For this tutorial, we built a small web application that listens for events from the movement sensors and shows an overview of all sensors. To use this application, you need a recent version of [Node.js](https://nodejs.org) installed on your computer. 368 | 369 | ![Application that shows movement information, built using Mbed OS and The Things Network](assets/lora19.png)Demo application 370 | 371 | To build this application, first grab an access key from The Things Network: 372 | 373 | 1. Go to your application in the TTN console. 374 | 1. Locate your **Application ID**, and make note of it. 375 | 376 | ![TTN Application ID](assets/ttn17.png) 377 | 378 | 1. Locate your **Access Key**, click the **show** button and make note of it, as well. 379 | 380 | ![TTN Access Key](assets/ttn18.png) 381 | 382 | Now clone, the demo application, and run it. 383 | 384 | 1. [Download the demo application](https://github.com/ARMmbed/lora-docs/archive/master.zip), and extract it. 385 | 1. In the unzipped application, locate `ttn-node-app/server.js`, and paste your Application ID and Access Key on lines 1 and 2. 386 | 1. Open a terminal - or command prompt - and navigate to the folder where you unzipped the application. 387 | 1. Run: 388 | 389 | ``` 390 | $ cd ttn-node-app 391 | $ npm install 392 | $ node server.js 393 | ``` 394 | 395 | This shows: 396 | 397 | ``` 398 | Connecting to the The Things Network data channel... 399 | Connected to The Things Network data channel 400 | Retrieving devices... 401 | Retrieved devices (2) 402 | Web server listening on port 5270! 403 | ``` 404 | 405 | 1. Now, open a web browser, and navigate to http://localhost:5270 to see the application running. 406 | 407 | ### 5. Recap 408 | 409 | LoRa/LoRaWAN is a technology with which anyone can set up a network and start building long-range IoT devices with a relatively small investment. We hope this guide helped you get started, and we would love to see what you build with LoRa and Mbed. 410 | 411 | #### More material 412 | 413 | - [Webinar: getting started with LoRa using Arm Mbed and The Things Network](https://pages.arm.com/2017-10-29-webinar-registration.html). 414 | - [Mbed OS LoRaWAN stack documentation](https://os.mbed.com/docs/latest/reference/lorawan.html). 415 | - [Firmware updates over LoRaWAN](https://os.mbed.com/blog/entry/firmware-updates-over-lpwan-lora/). 416 | - [Presentations from The Things Conference](https://www.youtube.com/playlist?list=PLM8eOeiKY7JUhIyxWWU2-qziejDbBg-pf). 417 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Getting started with LoRa on mbed 2 | 3 | docs_dir: docs 4 | 5 | pages: 6 | - ['index.md','LoRa on mbed'] 7 | - ['intro-to-lora.md','Building your own private LoRa network'] 8 | -------------------------------------------------------------------------------- /ttn-node-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | -------------------------------------------------------------------------------- /ttn-node-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mbed-ttn-node-app", 3 | "version": "1.0.0", 4 | "description": "Simple web application showing data from The Things Network", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/armmbed/lora-docs.git" 12 | }, 13 | "keywords": [ 14 | "lora", 15 | "ttn", 16 | "the things network", 17 | "mbed", 18 | "lorawan" 19 | ], 20 | "author": "Jan Jongboom ", 21 | "license": "Apache-2.0", 22 | "bugs": { 23 | "url": "https://github.com/armmbed/lora-docs/issues" 24 | }, 25 | "homepage": "https://github.com/armmbed/lora-docs#readme", 26 | "dependencies": { 27 | "express": "^4.16.2", 28 | "hbs": "^4.0.1", 29 | "socket.io": "^2.0.4", 30 | "ttn": "^2.3.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ttn-node-app/public/ARMmbedLogo.svg: -------------------------------------------------------------------------------- 1 | arm_mbed_lockup_horizontal -------------------------------------------------------------------------------- /ttn-node-app/public/helper.js: -------------------------------------------------------------------------------- 1 | var notificationTo; 2 | function showNotification(msg) { 3 | clearTimeout(notificationTo); 4 | 5 | var el = document.querySelector('#notification'); 6 | el.textContent = msg; 7 | el.style.opacity = 1; 8 | el.style.visibility = 'visible'; 9 | 10 | notificationTo = setTimeout(function() { 11 | el.style.opacity = 0; 12 | el.style.visibility = 'hidden'; 13 | }, 6000); 14 | 15 | el.onclick = function() { 16 | clearTimeout(notificationTo); 17 | el.style.opacity = 0; 18 | el.style.visibility = 'hidden'; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /ttn-node-app/public/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Lato'); 2 | 3 | #header { margin-top: 20px; } 4 | #logo { width: 167px; } 5 | body { 6 | font-family: "Lato", sans-serif; 7 | margin: 0; 8 | padding: 0 20px; 9 | font-weight: 300; 10 | color: rgb(80, 79, 77); 11 | font-size: 16px; 12 | } 13 | h1 { 14 | background: linear-gradient(45deg, #0091BD, #002B49); 15 | color: white; 16 | font-weight: 400; 17 | font-size: 48px; 18 | margin: 20px -20px; 19 | padding: 30px 20px; 20 | } 21 | a { 22 | color: #0091BD; 23 | text-decoration: none; 24 | } 25 | a:hover { color: #333E48; } 26 | p, li { 27 | line-height: 23px; 28 | } 29 | h2 { 30 | font-weight: 300; 31 | } 32 | #sensors { padding: 0; margin-top: -20px; } 33 | #sensors li { 34 | display: flex; 35 | flex-direction: column; 36 | margin: 0; 37 | padding: 20px 0; 38 | border-bottom: solid 1px lightgray; 39 | } 40 | #sensors li p { 41 | margin: 0; 42 | } 43 | #sensors li label { 44 | display: inline-block; 45 | width: 100px; 46 | font-weight: bold; 47 | } 48 | 49 | #notification { 50 | position: fixed; 51 | bottom: 20px; 52 | background: rgba(0,0,0,0.6); 53 | color: white; 54 | border-radius: 10px; 55 | display: inline-block; 56 | padding: 10px 20px; 57 | cursor: pointer; 58 | transition: all 0.6s ease-out; 59 | left: 50%; 60 | transform: translateX(-50%); 61 | } 62 | -------------------------------------------------------------------------------- /ttn-node-app/server.js: -------------------------------------------------------------------------------- 1 | let TTN_APP_ID = 'YOUR_APP_ID'; 2 | let TTN_ACCESS_KEY = 'YOUR_ACCESS_KEY'; 3 | 4 | const express = require('express'); 5 | const app = express(); 6 | const server = require('http').Server(app); 7 | const io = require('socket.io')(server); 8 | const hbs = require('hbs'); 9 | const ttn = require('ttn'); 10 | 11 | // Some options for express (node.js web app library) 12 | hbs.registerPartials(__dirname + '/views/partials'); 13 | app.use(express.static(__dirname + '/public')); 14 | app.set('view engine', 'html'); 15 | app.set('views', __dirname + '/views'); 16 | app.engine('html', hbs.__express); 17 | 18 | TTN_APP_ID = process.env['TTN_APP_ID'] || TTN_APP_ID; 19 | TTN_ACCESS_KEY = process.env['TTN_ACCESS_KEY'] || TTN_APP_ID; 20 | 21 | // Store some state about all devices, you probably want to store this in a database 22 | let devices = {}; 23 | 24 | // And handle requests 25 | app.get('/', function (req, res, next) { 26 | let d = Object.keys(devices).map(k => { 27 | let o = { 28 | devId: k, 29 | last_seen: new Date(devices[k].last_seen).toLocaleString(), 30 | state: devices[k].state 31 | }; 32 | return o; 33 | }) 34 | // Render index view, with the devices based on mapToView function 35 | res.render('index', { devices: d }); 36 | }); 37 | 38 | // Connect to TTN 39 | console.log('Connecting to the The Things Network data channel...'); 40 | 41 | ttn.data(TTN_APP_ID, TTN_ACCESS_KEY).then(client => { 42 | client.on('uplink', (devId, payload) => { 43 | console.log('retrieved uplink', devId, payload); 44 | 45 | let device = devices[devId] = devices[devId] || {}; 46 | 47 | if (payload.port === 21) { // PIR sensor data 48 | device.state = payload.payload_raw[0]; // check first byte 49 | device.last_seen = Date.now(); 50 | 51 | // send to all connected browsers, so they can update their state 52 | io.emit('movement-change', devId, device.state); 53 | } 54 | }); 55 | 56 | console.log('Connected to The Things Network data channel'); 57 | console.log('Retrieving devices...'); 58 | }).then(() => { 59 | return ttn.application(TTN_APP_ID, TTN_ACCESS_KEY); 60 | }).then(app => { 61 | return app.devices(); 62 | }).then(ttn_devices => { 63 | console.log('Retrieved devices (' + ttn_devices.length + ')'); 64 | 65 | for (let t of ttn_devices) { 66 | if (devices[t.devId]) continue; 67 | 68 | devices[t.devId] = { 69 | state: -1, 70 | last_seen: 0 71 | }; 72 | } 73 | 74 | // Now we can start the web server 75 | server.listen(process.env.PORT || 5270, process.env.HOST || '0.0.0.0', function () { 76 | console.log('Web server listening on port %s!', process.env.PORT || 5270); 77 | }); 78 | }).catch(err => { 79 | console.error('Could not authenticate with TTN...', err); 80 | }); 81 | 82 | -------------------------------------------------------------------------------- /ttn-node-app/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LoRaWAN intruder detection 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 |

Movement sensors

16 | 17 | 26 | 27 | 28 | 29 | 30 | 31 | 50 | 51 | 52 | 53 | --------------------------------------------------------------------------------