LoRaWANでIoTプラットフォーム（The Things Network）にデータを上げる方法

# イントロダクション
[前回の投稿](http://qiita.com/openwave-co-jp/items/fc4695f6de36fc9cd398)で、LoRaでのIoT（「モノ」と「インターネット」をどう繋ぐのか？）について紹介しました。
今回の記事では一歩進んで、LoRaWANでのIoTについてまとめたいと思います。

使用する機器は前回同様、弊社（[株式会社オープンウェーブ](http://www.openwave.co.jp/)）の[LoRa IoT スターターキット](http://www.openwave.co.jp/lorawan/)ですが、接続するIoTプラットフォームにはThe Things Network（以降TTN）を使用します。

# LoRaとLoRaWAN
この二つは、似て非なるものです。

## LoRa
無線の通信規格（物理層の規格）。

## LoRaWAN
ノードからIoTプラットフォームまでのプロトコル。

![全体像.PNG](https://www.researchgate.net/profile/Jonathan_De_Carvalho_Silva/publication/318866065/figure/fig1/AS:523019924590592@1501709075391/Illustration-LoRaWAN-network-layers.png)

<details><summary>2019/2/1</summary>
TTNから画像が削除され、他で分かりやすく説明されている画像と差し替えました。
作者:https://www.researchgate.net/profile/Jonathan_De_Carvalho_Silva
</details>

上図は、LoRaWANのプロトコルを説明する図です。
LoRaWANの場合、3つの登場人物がいます。

1. センサー：センサーを設置する機器（ノード、エンドデバイスと表現したりもする。）
2. ゲートウェイ：デバイスから受け取ったパケットを、ネットワークサーバに上げる機器
3. ネットワークサーバ：IoTプラットフォーム（ここにデータが集まる。）

LoRaが利用されている部分は、センサーとゲートウェイの間です。（PHY Layer→物理レイヤのLoRa）

LoRaWANは、センサー、ゲートウェイ、ネットワークサーバの一連のプロトコル全体です。
ゲートウェイはカプセル化して転送（Packet Forward）するだけです。
ネットワークサーバがTTNです。
私はセンサーとネットワークサーバを直接結ぶ赤い矢印この層をLoRaWANだととらえています。

アプリケーションから見れば、センサーとネットワークサーバが繋がっているように見えるという状態です。（ゲートウェイは単なる中継者）

## LoRaWANの良いところ
[LoRaを使ってIoTをするとき](http://qiita.com/openwave-co-jp/items/fc4695f6de36fc9cd398)と比べると、登場人物は同じで、役割も変わりません。
ではLoRaWANのメリットは、何でしょうか？次の二つが大きいと思います。

### 通信の暗号化
LoRaWANでは、デバイスとバックエンドの通信が暗号化されています。デバイスからの電波が傍受されても、傍受者はデータは読み取れません。

### デバイス（ノード）毎にデータを管理
Thing Speakではチャネル毎にデータを管理していました。（複数のデバイスから一つのチャネル宛にデータを投げると、見分けがつきません）
LoRaWANでは、デバイスごとにEUIと呼ばれるIDを管理し、デバイス単位のより細かいデータの管理が可能です。

# The Things Network（TTN）とは
EUでLoRaWANの草分け的存在で、LoRaWANのことを調べるとだいたいここにたどり着きます。
TTNではバックエンドを誰でも使えるように公開しています。

> 世界初のクラウドソーシング型IoTネットワーク
> オランダの首都アムステルダムでは、2015年8月、世界で初めて、クラウドソーシングによるIoT向けネットワークの構築に取り組む『The Things Network』を創設。
> 
> 有志の市民や地元企業らが、IoT向け無線通信規格LoRaWANに準拠するゲートウェイを合わせて10台購入し、それぞれの住宅やオフィスに設置。
> 
> わずか6週間で、アムステルダム市内にIoTネットワークを張り巡らせることに成功した。

引用：http://news.mynavi.jp/news/2015/11/14/244/

# 全体像
![全体像lorawan.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/47f5b6ff-9888-1d91-daf6-782a06692aff.png)
デバイス：LoRa Mini
ゲートウェイ：LG01-JP
デバイスの固定文字列「Hello, world!」を、LoRaWANプロトコルでTTNへ送信します。

## 使用ハードウェア
- Dragino社のLoRa IoT スターターキット
    - Dragino LG01-JP：LoRaゲートウェイ
    - Dragino LoRa mini：LoRaノード

## 使用ソフト
- Arduino IDE(1.6.13)
- Python 2.7(LG01-JPにインストールされている)
- TeraTerm等ターミナルのソフト
- WinSCP等SCPの使えるソフト
- Arduino用LMiCのライブラリ(下記をダウンロードして、Arduino IDEのライブラリにインクルードしておく)
https://github.com/matthijskooijman/arduino-lmic

## 使用プログラム
https://github.com/openwave-co-jp/LoRaWANExample

- LoRaWANExample/lora-arduino/lora-arduino.ino　　→デバイス（LoRa mini）
- LoRaWANExample/liteLoraGW/liteLoraGW.ino　　　→ゲートウェイLoRa受信(LG01-JP)
- LoRaWANExample/pythonScript　　　　　　　　　→ゲートウェイTTN送信(LG01-JP)

# 手順

## TTNの設定
https://www.thethingsnetwork.org/

### アプリケーションとデバイスの登録
TTNにアカウントを作成し、アプリケーションの登録と、そのアプリケーションにデバイスを登録します。
アプリケーションは作成後、ABPに変更します。（デフォルトはOTAA）
デバイスを作成した時に得られた、Network Session Key、App Session Key、Device Addressを控えます。
![TTN.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/8fa36086-caaa-b665-cca1-773d6bde69d5.png)
)


### ゲートウェイの登録

次の点に注意し、TTNでゲートウェイを作成します。

- 予めLG01-JPにTeraTerm等でログインし、MACアドレス※1を控えておきます
- TTNでゲートウェイの登録を行います
    - 「I'm using the legacy packet forwarder」を選択した上で作成します
    - Gateway IDはLG01-JPのMACアドレスを上3桁、FF、FF、下三桁で登録します
        - 例：MACアドレス「AA BB CC 11 22 33」の場合「AA BB CC FF FF 11 22 33」となる
    - 他は適宜設定します※2

※1：MACアドレスについて、LG01-JPには複数あります。（WiFiと有線の口ですね）
WiFiと有線のどちらのMACアドレスを使うのか？という疑問が出てくるかと思いますが、実はどちらでも構いません。
[Pythonのプログラム](http://qiita.com/openwave-co-jp/items/7edb3661ab5703e38e7c#python%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)の項でもGateway IDを使うのですが、ハードから直接MACアドレスを取得したりはしません。
多数のゲートウェイを設置する場合には、この辺を自動で設定する必要があります。

※2：ゲートウェイの接続先ルータの設定について。
ゲートウェイのプログラミングでは、現在router.au.thethings.network（オーストラリア）のサーバへ接続しています。
そのため、下記の設定では、アジアのルータを設定してください。
![TTN_GW設定.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/8cf4245d-bc64-1058-648f-26c2ae6401ae.png)


## ゲートウェイのプログラミング
ゲートウェイでは、LoRaでデバイスからデータを受信するArduinoのプログラムと、TTNにデータを転送するPythonのプログラムがあります。

### Pythonのプログラム
「使用プログラム」のpythonScript内のgwstat.pyを開き、Gateway IDの個所を、[TTNに登録したGateway ID](http://qiita.com/openwave-co-jp/items/7edb3661ab5703e38e7c#%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4%E3%81%AE%E7%99%BB%E9%8C%B2)で書き換えます。

```py:gwstat.py
# change your gateway ID(from 0xA8 to 0xD4)
head = chr(1) \
+ chr(random.randint(0,255)) \
+ chr(random.randint(0,255)) \
+ chr(0) \
+ chr(0xA8) \
+ chr(0xAA) \
+ chr(0xAA) \
+ chr(0xFF) \
+ chr(0xFF) \
+ chr(0xAA) \
+ chr(0xAA) \
+ chr(0xD4)
```

書き換えたgwstat.py含み、pythonScript内のファイルとフォルダを、LG01-JPの下記のディレクトリに配置します。（WinSCP等で可能です。dataディレクトリは作成してください。）

```text
/mnt/mtdblock3
        ├─data
        ├─base64.py
        └─gwstat.py
```

### Arduinoのプログラム
「使用プログラム」のliteLoraGW.inoを、Arduino IDEで開きます。
→LG01-JPに書き込み
![LG01-JP.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/2ca560bf-c767-106d-5078-1b8a3fe6e99e.png)

## デバイスのプログラミング
デバイス側では、LMiCライブラリの修正とデバイス情報の設定が必要になります。

### LMiCライブラリの修正
LMiCとは、IBMが作成した暗号化を含めたLoRaのMACプロトコル→LoRaMACのライブラリです。（LoraMac in Cの略）
LoRaWANではLoRaMACを使用しているため、デバイスはLoRaMACに準拠してコーディングする必要があります。下記サイトがLMiCのサイトですが、LoRa WAN in Cとなっています。LoRaMAC＝LoRaWANのような流れがあるように思われますね。ファイル名は今のところlmicのままです。
https://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html

これをArduinoで使えるようにしたものが「使用ソフト」に挙げたArduino用LMiCのライブラリです。
2017/3現在のLMiCライブラリ（v1.5ベース）は、EUとUS基準の無線周波数の設定が用意されています。そのまま日本では使えないので、とりあえず簡単に日本で使っても良い設定に変更します。

Arduino IDEを通常通りインストールすると、インクルードしたライブラリは\Documents\Arduino\librariesに配置されます。
\Documents\Arduino\libraries\arduino-lmic-master\src\lmic\lorabase.hを開き、EUの設定を書き換えます。

```c:lorabase.h修正前
// Default frequency plan for EU 868MHz ISM band
// Bands:
//  g1 :   1%  14dBm
//  g2 : 0.1%  14dBm
//  g3 :  10%  27dBm
//                 freq             band     datarates
enum { EU868_F1 = 868100000,      // g1   SF7-12
       EU868_F2 = 868300000,      // g1   SF7-12 FSK SF7/250
       EU868_F3 = 868500000,      // g1   SF7-12
       EU868_F4 = 868850000,      // g2   SF7-12
       EU868_F5 = 869050000,      // g2   SF7-12
       EU868_F6 = 869525000,      // g3   SF7-12
       EU868_J4 = 864100000,      // g2   SF7-12  used during join
       EU868_J5 = 864300000,      // g2   SF7-12   ditto
       EU868_J6 = 864500000,      // g2   SF7-12   ditto
};
enum { EU868_FREQ_MIN = 863000000,
       EU868_FREQ_MAX = 870000000 };
```

```c:lorabase.h修正後
// Default frequency plan for EU 868MHz ISM band
// Bands:
//  g1 :   1%  14dBm
//  g2 : 0.1%  14dBm
//  g3 :  10%  27dBm
//                 freq             band     datarates
enum { EU868_F1 = 923200000,      // g1   SF7-12
       EU868_F2 = 923400000,      // g1   SF7-12 FSK SF7/250
       EU868_F3 = 923600000,      // g1   SF7-12
       EU868_F4 = 923800000,      // g2   SF7-12
       EU868_F5 = 924000000,      // g2   SF7-12
       EU868_F6 = 924200000,      // g3   SF7-12
       EU868_J4 = 924600000,      // g2   SF7-12  used during join
       EU868_J5 = 924800000,      // g2   SF7-12   ditto
       EU868_J6 = 925000000,      // g2   SF7-12   ditto
};
enum { EU868_FREQ_MIN = 920600000,
       EU868_FREQ_MAX = 928000000 };
```

※上記は、複数チャンネルのある環境（923.2MHz～925MHzの9チャネル）を想定した設定です。送信する際、チャネルを切り替えながら送信します。LG01-P-JPのプログラムは923.2MHzの1チャネルのみでコーディングしています。（F2～J6のチャネルで送信しているデータは受信できません）



### デバイスのプログラミング

「使用プログラム」のlora-arduino.inoを、Arduino IDEで開きます。
「[アプリケーションとデバイスの登録](http://qiita.com/openwave-co-jp/items/7edb3661ab5703e38e7c#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AE%E7%99%BB%E9%8C%B2)」で控えたNetwork Session Key、App Session Key、Device Addressで下記を書き換えます。

```cpp:lora-arduino.ino
//ttn
static const PROGMEM u1_t NWKSKEY[16] = { 0x19, 0x7C, 0x79, 0x8E, 0x6D, 0xDE, 0xEB, 0xA6, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0FF, 0xFF };
// LoRaWAN AppSKey, application session key
// This is the default Semtech key, which is used by the prototype TTN
// network initially.
//ttn
static const u1_t PROGMEM APPSKEY[16] = { 0x07, 0x8C, 0xB1, 0x4F, 0x1E, 0xAD, 0x39, 0x4A, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0FF, 0xFF };
// LoRaWAN end-device address (DevAddr)
// See http://thethingsnetwork.org/wiki/AddressSpace
//ttn
static const u4_t DEVADDR = 0x2600FFFF;
```
このソース内でmydataという変数が、送信するデータです。
→LoRa miniに書き込み
![LoRamini.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/53f97613-ca3c-f671-4a4e-aabf1e779f87.png)

## 接続確認
TTNにログインし、コンソールでデバイスの画面を開きます。
![wan01.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/457f4baa-a34e-57c1-73b3-e0c829727f68.png)

データを受信すると、リストに表示されます。
![wan02.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/0f48d739-e7f0-71ae-3a87-5b5a9902cb69.png)

行を展開すると、受信したデータの詳細を見ることができます。
![wan03.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/e7f49d6d-064f-3bcc-4a95-f9b8f7b788d6.png)

Payloadの「48656C6C6F2C20776F726C6421」が、デバイスのmydataになります。
この数字をASCII文字で表現すると、「Hello, world!」になります。

# 最後に
今回使用したLMiCにはまだ日本のLoRaWANの基準が実装されていないこともあり、「とりあえず日本で飛ばしてよい周波数」で動かしました。
本来であれば、どのチャンネルをどう使うかなどLoRa AllianceのLoRaWANの仕様とARIBのSTD-T108が定める仕様に則って実装する必要があると思います。


# 注意

プログラミングにはArduino IDEを使用しますが、事前にArduino IDEに次の設定が必要です。

- Dragino向けの設定をしておく必要があります。
http://www.ibeacondo.com/download/LG01_LoRa_Gateway_Manual_JP.pdf
- 次のライブラリを検索してインクルードしておく必要があります。
    - 「LoRa」(LoRaライブラリ)

この記事で使用するソースは、使用するハードに依存している部分が大きいため、他のハードとの組み合わせでどうなるかは分かりません。

また、今回使用したプログラムは、LoRaWANの仕様を完全に満たしているわけではありません。（最も簡単なLoRaWANによるデータのアップロードをしているだけです。パケットのカウントや、SN比の算出など、ゲートウェイやデバイスの状態を表す値の取得の実装もダミーで実装しています。）

[株式会社オープンウェーブ](http://www.openwave.co.jp/)