MilkcocoaにつながるCocoaBitでリクエスト数を減らすArduinoコードの地味な配慮について

この記事は、Milkcocoa Advent Calendar 2016の8日目の記事です。前日は @joeartsea さんの <a href="http://qiita.com/joeartsea/items/f5e3056639123036c6e7" title="Milkcocoaとenebularの関係 - Qiita" target="_blank">Milkcocoaとenebularの関係</a> でした。

今回はMilkcocoaにつながるCocoaBitでリクエスト数を減らすArduinoコードの地味な配慮について書かせていただきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/56170/359093f6-7b9f-9035-f09f-d8c73b9fc607.png)

CocoaBitベースでお伝えしますが、<a href="http://nefry.studio/" title="Nefry - フリスクサイズのIoTデバイス" target="_blank">Nefry</a>や他のESPerの実装でも活かせるものです。

# CocoaBit

CocoaBitについての詳細はこちら。

<a href="https://dotstud.io/blog/cocoabit-littlebits-milkcocoa-nefry/" title="電子回路を簡単に学べるlittleBitsをインターネットに繋げよう！「CocoaBit」を開発中 | dotstudio" target="_blank">電子回路を簡単に学べるlittleBitsをインターネットに繋げよう！「CocoaBit」を開発中 | dotstudio</a>

# 経緯について

![image](https://qiita-image-store.s3.amazonaws.com/0/56170/c5ffe714-c879-da3e-6727-dbf742f5a425.png)

最近イベントごとで手軽にMilkcocoaにつながるCocoaBitを使っています。


ですが、CocoaBitをたくさんセンシング記録させようとすると、あっというまにMilkcocoaの無料プランの制限に達してしまいます。

![image](https://qiita-image-store.s3.amazonaws.com/0/56170/3fa6eb9e-66c9-5909-d83d-650ec0aea38a.png)

まずいですね。無料プランの制限を見てみるとより伝わるかと思います。

<a href="https://mlkcca.com/price.html" title="Pricing | Milkcocoa" target="_blank">Pricing | Milkcocoa</a>

このあたりを解決したくリクエスト数を減らすArduinoコードの地味な配慮をします。

# 最初書いていたコード

最初書いていたコードはさきほどの記事を参考にして、10秒ごとにセンシングするコードを書いていました。

```c:simple_output.ino
#include <Nefry.h>
#include <Nefry_Milkcocoa.h>
 
Nefry_Milkcocoa *milkcocoa;
 
char *datastore;
int sensorValue;
 
void setup() {
  milkcocoa->print();//Setup ModuleページにAPPIDの表示をする
  milkcocoa = Nefry_Milkcocoa::begin();//milkcocoaと接続に必要になる処理をします。
  datastore = Nefry.getConfStr(3);//Setup Moduleページに入力されたデータストア名を保存します。
}
 
void loop() {
  sensorValue = analogRead(A0);//アナログの入力を読みます。
  Nefry.print("input sensor = " );
  Nefry.println(sensorValue);//センサーデータを表示します。
  Nefry.println( milkcocoa->loop(10000) ? "Milkcocoa Connect OK" : "Milkcocoa Connect NG" ); //10秒以内にMilkcocoaに接続できればokと表示されます。
  Nefry.ndelay(10000);//10秒待つ
}
```

これですと値の変化を細かく取得するぶんには良いのですが、値が変化しない場合も丁寧に値を送ってしまうので、リクエスト数が大量になってしまいます。

**実際、CocoaBitを5台ほど同時に動かして1時間ほど試していたら、かなりのリクエスト数になってしまい慌ててOFFにした経験があります。**

# 修正したコード

ということで、通信を減らすために変化が大きい時だけ送信するように修正したコードがこちらです。

```c:connection_on_change.ino
#include <Nefry.h>
#include <Nefry_Milkcocoa.h>
 
Nefry_Milkcocoa *milkcocoa;
 
char *datastore;
int sensorValue;
int sensorValueHistory;
int spanValue;
 
void setup() {
  milkcocoa->print();//Setup ModuleページにAPPIDの表示をする
  milkcocoa = Nefry_Milkcocoa::begin();//milkcocoaと接続に必要になる処理をします。
  datastore = Nefry.getConfStr(3);//Setup Moduleページに入力されたデータストア名を保存します。
  sensorValueHistory = 0;
  spanValue = 0;
}
 
void loop() {
  sensorValue = analogRead(A0);//アナログの入力を読みます。
  Nefry.println(sensorValue);//センサーデータを表示します。
  // 通信を減らすために変化が大きい時だけ送信
  int spanValue = abs(sensorValueHistory - sensorValue);
  if( spanValue > 100 ){
    Nefry.println( milkcocoa->loop(10000) ? "Milkcocoa Connect OK" : "Milkcocoa Connect NG" ); //10秒以内にMilkcocoaに接続できればokと表示されます。
    DataElement elem = DataElement();
    elem.setValue("v", sensorValue);//センサーの状態を送信できる形に変換
    milkcocoa->push(datastore, &elem);//Milkcocoaに送信
  } else {
    Nefry.println("--");
  }
  sensorValueHistory = sensorValue;
  //
  Nefry.ndelay(1000);//1秒待つ
}
```

以上です。

大事な点は、数値の絶対値を返すabs関数を使用して値の変化の正方向の変化でも負方向の変化でも丸め込んで変化を捉えているところと、

```c
int spanValue = abs(sensorValueHistory - sensorValue);
```

ある程度、アナログ値のブレがあるので、明らかに値が変わったときに検出するようにしています。

```c
if( spanValue > 100 ){
```

アナログ値は0～1024で返ってくるので、10刻みくらいで今回は良いだろうということで100判定にしています。

この値を小さくすれば、より細かな反応に対応できるものとなります。また、littleBitsのボタンモジュールのようにON/OFFだけとらえるならば、ざっくり512（1024の中間値）で捉えてしまってもよいでしょう。

# 結果

大変地味な実装ですが、このコードによってボタンを押されたらというインタラクティブなものに関しては、アクションが起きたときだけ捉えられるようなり、リクエスト量をグッと抑えることができました。より多くのデバイスでセンシングできますね！

もちろん、センシングするものの中には温度センサーのように微妙な変化を伝えるものもあり、その場合は別の対策が必要かと思いますが、分かりやすくボタンをおすようなインタラクティブなものを作る際の一助となればうれしいです。

# さて、次回のアドベントカレンダーは…

[Milkcocoa Advent Calendar 2016](http://qiita.com/advent-calendar/2016/milkcocoa)も明日で9日目。

私 @tseigo が「複数人へAPIな仕組みを展開する時にMilkcocoaで手軽に行えた話」を書かせていただきます。

※顔アイコンは<a href="http://icooon-mono.com/" title="アイコン素材ダウンロードサイト「icooon-mono」 | 商用利用可能なアイコン素材が無料(フリー)ダウンロードできるサイト | 6000個以上のアイコン素材を無料でダウンロードできるサイト ICOOON MONO" target="_blank">アイコン素材ダウンロードサイト「icooon-mono」</a>さんからお借りしました。