ArduinoとLoRaWANモジュールでデータを送信する

#はじめに
これは、センスウェイ社の提供しているLoRaWANサービスを利用して、ひとまずセンサーは使わず、ダミーデータを送信してみる記事です。

Node-REDを導入済み
・作業するPCに、Arduino IDEをインストール済み
・Arduino UNO（または互換機）を持っている
・センスウェイ社のLoRaWAN通信モジュールArduinoシールドを持っている
・センスウェイ社が提供するゲートウェイを持っている、もしくは基地局のエリア内にいる

これらの条件を満たしている方向けの記事となります。


#LoRaWAN通信モジュールを登録する
SenseWay Mission Connectにアカウントを作成し、モジュールを登録、アカウントに紐づけます。

手順は、公式のマニュアルを参考にして下さい。

https://service.senseway.net/manual/how-to-register-senseway-mission-connect/
#ArduinoとLoRaWAN通信モジュールを接続する
ArduinoとLoRaWAN通信モジュールを、重ね合わせるようにして接続します。

ピンの足は細いので折れないよう注意しながら、Arduino側にしっかりと差し込みます。押し込みすぎると壊れてしまいますので、自然に止まったら無理に押し込まないようにします。
#テスト動作用のArduinoスケッチを作成する
ではいよいよ、Arduinoにテスト動作用のスケッチを書き込みます。
##Kashiwa Geeksライブラリを導入する
LoRaWANをArduinoで簡単に扱うためのライブラリ「Kashiwa Geeks」を使用します。まずはArduino IDEにライブラリを追加します。

https://github.com/ty4tw/KashiwaGeeks

画像赤枠の「Clone or download」→「Download ZIP」で、ダウンロードします。
![4-1--1-kashiwa-geeks-1.png](https://qiita-image-store.s3.amazonaws.com/0/252280/0a5f7396-79e5-018c-8797-049e176a63fb.png)

次に、Arduino IDEを起動し、「スケッチ」→「ライブラリをインクルード」→「.zip形式のライブラリをインストール」で、先ほどダウンロードしたzipファイルを選択し、インストールします。
![4-1--2-kashiwa-geeks-2.png](https://qiita-image-store.s3.amazonaws.com/0/252280/5284409f-32f4-e8e1-d564-f915732d6e98.png)


「スケッチ」→「ライブラリをインクルード」の中の下の方に「KashiwaGeeks-master」があれば、インストールは成功です。
![4-1--3-kashiwa-geeks-3.png](https://qiita-image-store.s3.amazonaws.com/0/252280/338938e3-a1b3-110c-b0f5-0bc9b58c72f7.png)


※この記事では扱いませんが、「ファイル」→「スケッチ例」→「KashiwaGeeks-master」の中に、スケッチ例がいくつかありますので、参考にして下さい。
![4-1--4-kashiwa-geeks-4.png](https://qiita-image-store.s3.amazonaws.com/0/252280/eb8e36ae-c810-65ef-a5de-de81c45c765e.png)


##スケッチの紹介
```c++:sample_lorawan
#include <KashiwaGeeks.h>

#define ECHO true

ADB922S LoRa;

uint8_t port = 13;

void start()
{
    ConsoleBegin(57600);
    ConsolePrint(F("\nLoRaWAN Sample\n"));

    if ( LoRa.begin(9600, DR2) == false )
    {
        while(true)
        {
            LedOn();
            delay(300);
            LedOff();
            delay(300);
        }
    }

    LoRa.join();
}


//========================================
// Functions to be executed periodically
//========================================
void taskSample(void)
{
    sendSample();
}

//========================================
//            Execution interval
//    TASK( function, initial offset, interval by minute )
//========================================
TASK_LIST = {
        TASK(taskSample, 0, 1),
        END_OF_TASK_LIST
};

//================================
//          Power save functions
//================================
void sleep(void)
{
    LoRa.sleep();
    DebugPrint(F("Sleep.\n"));
}
void wakeup(void)
{
    LoRa.wakeup();
    DebugPrint(F("Wakeup.\n"));
}

//================================
//      Send sample data function
//================================
void sendSample(void)
{
  float dummy_data = 24.68;
  int16_t sample_data = dummy_data * 100;
  LoRa.sendData(port, ECHO, F("%04x"), sample_data);
}

/*   End of Program  */
```
こちらがスケッチの全体像です。コピペで利用できます。

このスケッチは、次のように大きく4つに分けて考えることができます。
01～26行目の初期設定と起動処理
29～44行目のタスク設定
46～58行目のスリープと復帰に関する処理
60～68行目の送信処理

細かい説明は割愛します。
65行目に記述がありますが、温度を取得したようなイメージで、「24.68」というダミーのデータを設定しています。

※このスケッチ例では、送信したデータに対するACKを要求してません。何かのエラーで通信に失敗したとしても、失敗を察知して再送信したりしない設定になっているという事です！
ACKを要求して通信成功するまで再送するモードもありますが、LoRaWANを含む「LPWA」に使用されている電波帯域はとてもルールが厳しく、「同じ空間内で、複数台が同じタイミング・周波数チャンネルで電波を使用できない」ことになっています。そう考えると、空間内で使用可能な電波は「限りある資源」であると言え、「可能な限り、電波を使用する時間を短くする」のが基本です。
ACKを要求すると、ACKが返ってくる分、要求しない時の倍の時間電波を使用することになるので、可能な限りACK要求しないのが推奨されています。

##Arduinoにスケッチを書き込む
ArduinoとPCをUSBケーブルで接続し、スケッチを書き込みます。
書き込み手順は、通常のArduinoスケッチの書き込み手順と同じです。

書き込みが完了したら、一旦Arduinoの電源をOFFにします。
#Node-REDでデバッグの準備をする
データを受け取るアプリケーションとして、Node-REDのデバッグ機能を使用します。

Node-REDの画面を開き、次の画像のようにノードを配置、接続します。
MQTT INノードは左側「入力」の中に、デバッグノードは「出力」の中にあります。
![5--1-node-red-1.png](https://qiita-image-store.s3.amazonaws.com/0/252280/1c1affcf-d127-881f-d412-f18e8c08bd43.png)

次に、MQTT INノードをダブルクリックし、設定を開き、新規MQTTブローカーを追加します。
![5--2-node-red-2.png](https://qiita-image-store.s3.amazonaws.com/0/252280/567570e6-7dee-5d5b-ed4d-30c2670cc102.png)

サーバに「mqtt.senseway.net」、ポートに「1883」を入力し、「セキュリティ」タブを開きます。
![5--3-node-red-3.png](https://qiita-image-store.s3.amazonaws.com/0/252280/857c7a13-6b49-00f5-4237-88e240f95f30.png)

SenseWay Mission Connectのアカウント情報を入力し、「追加」をクリックします。
![5--4-node-red-4.png](https://qiita-image-store.s3.amazonaws.com/0/252280/230a4b74-2439-44d8-438e-f9d6809059fa.png)

「サーバ」が設定したものになっているのを確認し、「トピック」と「QoS」を指定します。
「トピック」は「lora/〇〇〇〇/+/rx」（〇〇〇〇は、SenseWay Mission Connectのアカウント名）、QoSは「0」にし、「完了」をクリックします。
![5--5-node-red-5.png](https://qiita-image-store.s3.amazonaws.com/0/252280/c40d7f4d-d0d5-bb43-4776-5b5e6d5bdcc0.png)

※もしLoRaWANモジュールを複数所持していてデータが混ざってしまいそうな場合、トピックの+の部分にdevEUIを入力してください。


右上「デプロイ」をクリックし、これらの変更を適用します。デプロイしたら、画像赤枠のテントウムシのようなマークをクリックし、デバッグ画面を開きます。
![5--6-node-red-6.png](https://qiita-image-store.s3.amazonaws.com/0/252280/a4917b91-1f8e-1e45-00c5-ece7939410cd.png)

以上で、デバッグの準備は完了です！
#ゲートウェイの接続を確認する（エリア内の方はスキップでOK）
ゲートウェイをご自宅のルーターにLAN接続し、電源を入れます。設定は特に必要なく、ゲートウェイ前面のLEDがすべて緑色になれば準備完了です。
#動作テスト！
Arduinoの電源を入れます。

この時Arduino IDEのコンソール画面を開いておけば、次のような内容が表示されます（通信に手間取ったりすると、norespなどのメッセージが表示されることもあります）。
![7--1-console.png](https://qiita-image-store.s3.amazonaws.com/0/252280/a01b6563-e741-27e1-3944-4fe4ff1d4670.png)


問題なければNode-REDのデバッグ画面にメッセージが表示されるはずです。メッセージはJSON形式になっていて、色々な情報が入っています。
##MQTTメッセージをコピペし、JSONを整形
デバッグメッセージのJSONをコピーします！メッセージにカーソルを合わせると、コピーボタンが表示されますので画像赤枠のコピーボタンをクリックしましょう。
![7-1--1-node-red-1.png](https://qiita-image-store.s3.amazonaws.com/0/252280/b7f9647d-4972-ba48-34df-c13c0ecbc249.png)

次に、JSONを見やすく整えます。「JSON　整形」とGoogleなどで検索すると、JSONの整形ツールがいくつも出てきますので、好きなものを選び、コピーしたJSONを張り付けて整形します。
##JSONの中身を見てみる
JSONの中身は、次のようになっています。

```
{
  gw:[  //ゲートウェイに関する情報。電波を受信したゲートウェイが複数台ある場合、配列で複数の情報が入る
    0:{ //配列の0番目。一つしかなくても配列になる
      date:2019-01-19T10:24:13.297302Z  //日付、時刻の情報
      rssi:-45                          //信号強度
      snr:11.8                          //信号のノイズ比
      gwid:****************             //信号を受信したゲートウェイのID
    }
  ]
  mod:{  //受信したデータに関する情報
    fq:927.4                 //使用周波数
    cnt:1                    //センスウェイサーバー側のカウント数
    data:09a4                //ポート番号
    mt:ucnf                  //ACKを要求するかどうか。要求は「cnf」、非要求は「ucnf」
    devEUI:****************  //デバイスのID（devEUI）
    dr:2                     //データレート
    port:13                  //ポート番号
  }
}
```

送信したデータそのものは、「mod」の中の「data」に入っています。ダミーのデータは24.68でしたが、JSONを見てみると09a4になっています。これは、送信しやすい形にエンコードしているからです。このあとアプリケーション側でデコードすれば、元の24.68という値に戻ります。

※エンコードは、Arduinoスケッチ上で「100倍にしてから10進数→16進数に変換」しています。
※デコードは、例えばNode-REDなどで、エンコードとは逆の手順で「16進数→10進数に変換してから100で割る」というふうにします。

センサーの種類でポート番号を分けて処理を振り分けたり、同じ種類のセンサーが10個あるような状況ならdevEUIの値を見て「どこに設置したセンサーなのか」を特定したりできます！