複数のLoRaノードをゲートウェイにアクセスさせるときに気を付けること

# これまでのお話

1. [LoRaでIoTプラットフォーム（ThingSpeak）にデータを上げる方法](http://qiita.com/openwave-co-jp/items/fc4695f6de36fc9cd398)
2. [LoRaWANでIoTプラットフォーム（The Things Network）にデータを上げる方法](http://qiita.com/openwave-co-jp/items/7edb3661ab5703e38e7c)
3. [LoRaにGPSを付けて、会社の周りを歩いてみた（Google Earthで位置情報をプロットする）](http://qiita.com/openwave-co-jp/items/8dae802638cf6ac62650)

# イントロダクション
前回までで、LoRaのノードに温度湿度センサーやGPS受信機を付けて、そのデータをIoTサーバに上げるようなことをしてきました。

しかし、どれもノード1個だけしか使っていません。
実用を考えると、ノードが1個だけということはあり得ませんよね。

今回は、複数のノードを使えるようにするにはどうすればよいのかを考えてみようと思います。
LoRaWANとLoRaについて書きましたが、実践はLoRaのみ行います。

# 考えなければならないこと
大雑把に考えると、だいたい次の点を考える必要がありました。

1. ノードの識別をどうやって行うのか？
2. データを確実に届けるにはどうするのか？

## LoRaWANの場合
LoRaWANについて、弊方ではLMiCによるコーディングしか経験がないのでその範疇で考えます。

### ノードの識別をどうやって行うのか？
LoRaWANの場合、TTNでもLORIOTでもIoTプラットフォーム側で予めノードの情報を登録しておきます。その時、ノードを識別するためのID（Device AddressとかDevice EUIとか）が振られ、ノードのプログラムに持たせてやる必要があります。
実際のLoRaとIDの一致については、「LoRaの場合」と同じことを考える必要があります。

### データを確実に届けるにはどうするのか？
LoRaWANのdownlinkを使える場合、IoTサーバとノード間にセッションを構築するので、その中で通信の開始、送受信の成功／失敗、リトライに失敗などの各ステータスが、イベントとして発生します。（JavaScriptのonClickとかonChangeみたいな感じで、onErrorみたいなものがあります）

なので、失敗のイベントを受け取ったら再度リトライするようなコーディングが、意識的に必要です。
因みに、以前にご紹介したLoRaWANのコードはdownlinkを実装していないので、ノードからデータを送りっぱなしで失敗のイベントなどを発生させられません。
（おそらく、downlinkを実装すればイベントによるリトライ処理ができるようになると思います）


## LoRaの場合
LoRa単体では、個別識別やリトライなどはありません。
自分で考えて実装する必要があります。

### ノードの識別をどうやって行うのか？
個別識別を行うのに必要なのは、次のことです。

1. 「このノードはID：XX」と決めること
2. ノードのIDがいくつか、後から分かること

1.については、プログラマが何かしら（連番、ランダム）の方法で決めればいいですよね。2.については、DBを使うのかExcelを使うのか、何かしらの管理という方法が考えられます。
ただ2.については、コンパイルされた情報からIDを特定するのは困難であるため、プログラムに直接IDを書き込んでしまうと次のような不便な点が発生します。

- ノードを大量に設置する際、ノードを識別するためにIDを書いたラベルを張る作業が発生。
- 大量にノードがあり、プログラムのアップデートが必要になった場合、「プログラム上のノードIDを書き換え→書き込み」という作業になるので、面倒な上、バグのもとにもなる。

ではどうするか？

私は解決のために、EEPROMというものを使いました。
EEPROMは電源を切ってもフラッシュされない記憶装置です。（どの情報を参考にしたか忘れましたが、「HDDみたいなもの」と表現されてる方もいらっしゃいました。）
EEPROMのどこかのアドレスに、IDを書き込む方法により上記の問題が次のように変わります。

- ノードを大量に設置する際、ノードのプログラム書き込みの際にEEPROMにIDの書き込みを行う。
    - EEPROMに書かれているIDを読み取れるので、ラベルで管理しなくて良い。（ラベルを買わずに済む）
    - ラベルを張る手作業よりは、ある程度効率化できそう。（自動採番のプログラム作るとか）
- 大量にノードがあり、プログラムのアップデートが必要になった場合、「書き込み」作業だけでよい。
    - 手順が一つ減る。
    - ID記述ミスなどの余計なバグが発生しない。



### データを確実に届けるにはどうするのか？
できるだけ間違いの少ない伝搬をするために、次のような工夫をします。

- 送信前に受信状態にして、他の端末が通信していないか確認。
    - CSMA/CAではこれを「搬送波感知（Carrier Sense）」という。
    - 総務省／ARIBでルールが決まっていて、アクティブ系小電力無線システム250mW以下のものは、5ms以上行わないといけない。
- ゲートウェイ側も、受信に成功したらレスポンスを返す。
- 送信側はゲートウェイのレスポンスを確認できない場合は、失敗と見なして送り直す。

送り直しは何回行うのか？
重複してデータが送られることは許容するのか？
などは、通信の品質レベルでもっと考える必要はありそうですが、2台のLoRaノードからそれぞれ4秒間隔と7秒間隔で実験したところでは重複はあってもデータの損失はありませんでした。
（この仕組みがない場合は損失だらけになります。）

以降、LoRaによる実践です。

# 全体像
![全体像_マルチノード.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/5a8748d2-47cf-8c35-3580-fd57baefbcde.png)

- 弊社のLoRa IoT スターターキット（Dragino社製）
    - Dragino LG01-JP：LoRaゲートウェイ
    - Dragino LoRa mini Dev：LoRaノード　×２

## 使用ソフト
- Arduino IDE(1.6.13)

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

- LoRaMultiNodes/eeprom_writer/eeprom_writer.ino　　→デバイス（LoRa mini）ID書込み用
- LoRaMultiNodes/node/node.ino　　→デバイス（LoRa mini）本体プログラム
- LoRaMultiNodes/multi_node_GW/multi_node_GW.ino　　　→ゲートウェイLoRa受信(LG01-JP)


# 手順

## LoRa miniへのID書込み
eeprom_writer.inoをArduino IDEで開き、13行目のIDを適宜修正します。（0以外の1バイトに収まる数字が使えるので1～255の数値をセット）
![0001.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/92556dc7-4cf2-ef5d-2c91-78621ff41f37.png)

ノードに書込み後、シリアルモニタを開きます。（シリアルモニタの実行でEEPROMに書き込むようにしています）
![0002.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/428a557d-2952-1106-1d6f-452493e95745.png)

二つ目のノードにも同様にID（別のもの）を指定して書き込みます。
![0003.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/599feb80-66f7-3940-4615-5b29569a1f9f.png)
![0004.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/a38aa6f3-0a85-62b5-211f-0d41a12cba77.png)

## LoRa miniのプログラミング

二つのノードそれぞれに、node.inoを書込み、シリアルモニタを開きます。（シリアルモニタの実行で、プログラムが開始されます）
![0005.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/f146ab17-36a0-7efb-164b-8e21734fd85c.png)

## LoRaゲートウェイのプログラミング
ゲートウェイにmulti_node_GW.inoを書き込み、シリアルモニタを開きます。（シリアルモニタの実行で、プログラムが開始されます）
![0006.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/127b7281-74ad-f16f-f6cb-84bb338df19a.png)


## 動作確認
ノードからは、IDとパケットの回数が送られ来ます。
ID毎に、パケットが抜けなく順番通りに受信できていることを確認してください。
![0007.PNG](https://qiita-image-store.s3.amazonaws.com/0/169302/7cbeba9f-2fd2-f57e-3e1a-a2a54b59de93.png)


# 最後に
そのままだとノードのプログラムが全く同じなので、タイミングが重なりにくく、問題なく送受信できてしまうということもあるかと思います。
その場合は、ノードのプログラムのdelay時間を変更し、タイミングが重なるようにして動作確認することをお勧めします。

データ通信にLoRaを使用する場合、要件に「データの損失は多少許容できること」が必要というサイトを見た覚えがあります。
かと言って全く何もしなかったら使い物にならないので、ある程度通信品質を向上させる努力は必要だなと思いました。


# 注意

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

- Dragino向けの設定をしておく必要があります。
http://www.ibeacondo.com/download/LG01_LoRa_Gateway_Manual_JP.pdf
- RadioHeadライブラリをインターネットから取得して、インクルードしておく必要があります。
http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.63.zip

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

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