Sakura IoT PlartformでIncoming Webhookを試す

# はじめに

さくらインターネットが提供する「[さくらのIoT Platform](https://iot.sakura.ad.jp/)」は、データを送受信するための通信環境とデータの保存や処理に必要なシステムを一体で提供するIoTプラットフォームです。2017年2月頭の時点ではβ版として提供されており、通信モジュールやArduino用シールドを購入すればすぐに試すことができます。ここでは、通信モジュールに対するウェブリクエストを試してみました。

# 材料

- [さくらの通信モジュール（LTE）-β版](http://iot-store.sakura.ad.jp/items/4326125)：1個
- [Arduinoシールドボード-β版](http://iot-store.sakura.ad.jp/items/4350904)：1個
- Arduino Uno：1個

# 準備

1. [β版ドキュメント](https://iot.sakura.ad.jp/developer/)の指示に従ってプロジェクトの作成とモジュールの登録をおこなう
2. [SAKURA Internet IoT Communication Module Library for Arduino](https://github.com/sakura-internet/SakuraIOArduino)の説明に従ってライブラリ「SakuraIO」をArduino IDEに追加する

# 実装

まず、ダッシュボードを開き、モジュールのIDをどこかにコピー＆ペーストします。次に、「連携サービス」で「Incoming Webhook」を追加し、この時に生成される「token」をどこかにコピー＆ペーストしておきます。

続けて、APIドキュメントの「[Incoming Webhook](https://api.sakura.io/incoming/v1/docs/)」ページを開きます。このページからは実際にウェブリクエストを送信できますので、次のようにしてtokenとmoduleを入力し、valueに適当な値を入力します。

![Sakura IoT Plartform Incoming Webhookの画面例](https://qiita-image-store.s3.amazonaws.com/0/92577/6398a2f9-0fc9-00d6-cba8-084fd38cf27a.png)

ここで、typeは以下のような意味になります。

|Type|意味|Arduino|
|:--|:--|:--|
|`i`|32ビット整数型|`int32_t`|
|`I`|32ビット符号なし整数型|`uint32_t`|
|`l`|64ビット整数型|`int64_t`|
|`L`|64ビット符号なし整数型|`uint64_t`|
|`f`|浮動小数点型|`float`|
|`d`|倍精度浮動小数点型|`double`|
|`b`[^1]|バイナリ|`uint8_t[8]`|

[^1]: 2017年2月2日の時点で試してみた範囲では、APIドキュメントのページから送信しようとすると`value`に入力した文字列が`null`として扱われ、エラーになってしまいます。送信後に表示される`curl`コマンドの内容を参考にコマンドラインなどから送信すればエラーなく受信されます。

これにより、以下のようなボディのウェブリクエストを`https://api.sakura.io/incoming/v1/{token}`に対して送信する準備が整いました。

```json
{
    "type":"channels",
    "module":"************",
    "payload":{
        "channels":[
            {
                "channel":0,
                "type":"i",
                "value":123
            }
        ]
    }
}
```

最後に、以下のスケッチをArduinoボードにアップロードします。

```cpp
#include <SakuraIO.h>

// Sakura IO
SakuraIO_I2C sakuraio;

void setup() {
  // シリアル通信を開始
  Serial.begin(9600);

  // オンラインになるまで待つ
  while ((sakuraio.getConnectionStatus() & 0x80) != 0x80) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("");
  Serial.println("Online");
}

void loop() {
  // 受信キューの状態を取得
  uint8_t rxAvailable;
  uint8_t rxQueued;
  sakuraio.getRxQueueLength(&rxAvailable, &rxQueued);

  // 受信キューにたまっているメッセージの数だけ繰り返す
  for (uint8_t i = 0; i < rxQueued; i++) {
    uint8_t channel;
    uint8_t type;
    uint8_t values[8];
    int64_t offset;

    // キューからのメッセージを取り出しに成功したら以下を実行
    uint8_t ret = sakuraio.dequeueRx(&channel, &type, values,
                                     &offset);
    if (ret == CMD_ERROR_NONE) {
      Serial.print("channel: ");
      Serial.println(channel);
      Serial.print("type: ");
      Serial.println((char)type);
      Serial.print("value: ");

      // タイプに応じて受信したバイト列から変換して値をプリント
      if (type == 'i') {
        // 32ビット整数型の場合
        int32_t value = 0;
        memcpy(&value, &values, sizeof(int32_t));
        Serial.println(value);
      } else if (type == 'f') {
        // 浮動小数点型の場合
        float value = 0;
        memcpy(&value, &values, sizeof(float));
        Serial.println(value, 5);
      } else if (type == 'b') {
        // バイナリの場合
        for (int i = 0; i < 8; i++) {
          Serial.print(values[i], HEX);
        }
        Serial.println();
      }
    } else {
      Serial.println("ERROR");
    }
  }

  delay(5000);
}
```

アップロードが終了したら［ツール］メニューから［シリアルモニタ］を開き、ウェブブラウザからウェブリクエストを送信すると以下のように受信されるはずです。

![シリアルモニタの画面例](https://qiita-image-store.s3.amazonaws.com/0/92577/30b59615-80f8-0586-2509-fd6a8df18c4f.png)

特定のURLにウェブリクエストを送信するだけですので、様々なウェブサービスから通信モジュールに対してメッセージを送信することができます。例えば、次のように設定することでIoTウェブサービス「IFTTT」からも送信できます。

![IFTTT](https://qiita-image-store.s3.amazonaws.com/0/92577/53ef50ce-997d-2c87-edff-10a014747bea.png)

ただし、この時Incoming Webhookに関するAPIドキュメントページが生成した以下のJSONだと、RFC 4627、RFC7159、ECMA-404のいずれにも適合しているはずなのに、IFTTTでアプレットを作成する段階でエラーが発生してしまいます。

```json
{"type":"channels","module":"************","payload":{"channels":[{"channel":0,"type":"i","value":123}]}}
```

以下のように順序を変更すると、問題なく設定することができました。

```json
{"payload":{"channels":[{"channel":0,"type":"i","value":123}]},"type":"channels","module":"************"}
```

# おわりに

2017年2月頭の時点では連携サービスとしてWebSocketやMQTT、AWS IoTなどが用意されており、様々なウェブサービスと簡単に組み合わせることができるようになっているようです。β版ということもあり配布されているドキュメントが古く多少混乱するところがないわけではないですが、正式リリース時には解消されるでしょうから、目的にマッチすれば使いやすいサービスだと思います。