自分の行動時の温湿度を可視化しよう~環境センサ(2JCIE-BL01)のデータをMonacaで拾ってkintoneに投げるまで


目的~温湿度データを人に紐づける

「センサーからデータを拾ってクラウドに上げてIoT!」的な記事はたくさんあるのですが、ちょっと目的が異なっていまして、今回の目的は 自分の動線の温湿度データを取る です。
いわゆる据置型センサーとして一番使いやすいのはNetatmoだと思います。設置が簡単でAPIもそろっているので最小限の手間で可視化までもっていけます。ただしそこではデータの主体は 「場所」 になる、つまり「この部屋はどういう温度だ」というようにデータが場所に紐づきます。このデータを人に紐づけるには(1) 「人」 がどこの場所にいた→(2)その 「場所」 はどういう温度だった→(3)「人」 がいた場所はこういう温度だった、的な紐づけロジックが必要になりまあまあ面倒になります。これを解決するために 「人」 側で直接データを取って記録するのがこの記事の目的です。

実験では1台のみビーコンを使用し持ち歩いていますが、これを複数台用意しても複数人使用していても利用できるのがこの記事のポイントとなります。

実装の全体像

  • 温湿度をビーコン(OMRON環境センサ 2JCIE-BL01)からアドバタイズさせます。初期設定の状態からセンサをbroadcasterへの変更が必要です。ここは別記事化してありますのでこちらをご覧ください。コンシューマー向けの正規ルートがあるのかどうかよくわからないのですが、WxBeacon2を買うのが一番手っ取り早いです。一個5000円。
  • アドバタイズデータをMonaca(Cordova)アプリで拾います
  • 拾ったデータをkintoneに投げ、可視化します

アドバタイズデータをMonaca(Cordova)アプリで拾う

温湿度ビーコンを選別し、アドバタイズパケットのByteArrayを解釈する、という手順になります。今回はBLEのプラグインとしてcordova-plugin-ble-centralを使用しました。注意点は以下です。

  • 機器のフィルタは機器名にする。プライマリサービスとかでやろうと試したのですが、名前でフィルタが確実でした、、
  • iOSとAndroid で機器名の表示とアドバタイズパケット内の返してくるバイト範囲が異なる。 左記の制限から母機のArchitectureを確認し分岐させます。まあここらへんはこういうものだと諦めてください、、。
  • パケットの中身は通信仕様マニュアルの3章を参考にしてください。
index.html_script内
    function blescan(){
        console.log('start stan');
        ble.scan([], 15, function(device) {
            //in case iOS
            if ( monaca.isIOS ) {
                if(device.name == "EP-BL01"){
                    var adData = new Uint8Array(device.advertising.kCBAdvDataManufacturerData);
                    var temp = (adData[4] * 256 + adData[3]) / 100 ;
                    var humid = (adData[6] * 256 + adData[5]) / 100;
                    var light = (adData[8] * 256 + adData[7]);
                    var uv = (adData[10] * 256 + adData[9]) / 100;
                    var press = (adData[12] * 256 + adData[11]) / 10;
                    var noise = (adData[14] * 256 + adData[13]) / 100;
                    document.getElementById("msg").innerHTML = 
                        'Temp:' + temp + '/Humid:' + humid + '/Light:' + light + '/UV:' + uv +
                        '/Press:' + press + '/Sound:' + noise + ' ' + JSON.stringify(device);
                    push2Kintone(temp, humid, light, uv, press, noise);
                }
            }
            //in case Android
            else if ( monaca.isAndroid ) {
                if(device.name == "EP"){
                    var adData = new Uint8Array(device.advertising);
                    var temp = (adData[9] * 256 + adData[8]) / 100 ;
                    var humid = (adData[11] * 256 + adData[10]) / 100;
                    var light = (adData[13] * 256 + adData[12]);
                    var uv = (adData[15] * 256 + adData[14]) / 100;
                    var press = (adData[17] * 256 + adData[16]) / 10;
                    var noise = (adData[19] * 256 + adData[18]) / 100;
                    document.getElementById("msg").innerHTML = 
                        'Temp:' + temp + '/Humid:' + humid + '/Light:' + light + '/UV:' + uv +
                        '/Press:' + press + '/Sound:' + noise + ' ' + JSON.stringify(device);
                    push2Kintone(temp, humid, light, uv, press, noise);
                } 
            }
        }, function(){})    
    }

拾ったデータをkintoneに投げ、可視化する

REST APIに投げるのめんどくさいなーて思っていたらMonacaとkintoneで忘年会出欠アプリを作るの投稿でユーティリティライブラリがあるのを知りました。これはラクチン。

index.html
<script src="js/kintoneUtility.min.js"></script> 
index.html_script内
    var kintoneapp = {
      id: 'YOUR_ID',
      domain: 'YOUR_DOMEIN'
    };

    var timer;

    document.addEventListener('deviceready', function() {
        // ドメイン情報の設定
        kintoneUtility.rest.setDomain(kintoneapp.domain);
        // トークンの設定
        kintoneUtility.rest.setApiTokenAuth('YOUR_TOKEN');
        // ゲストスペースの場合
        kintoneUtility.rest.setGuestSpaceId('YOUR_SPACE_ID');
    });

    function timerStart(){
        timer = setInterval(function(){
            console.log("intvl called");
            blescan();
        }, 180000); //3分毎に更新
    }

    function push2Kintone(temp, humid, light, uv, press, noise){
        var record = {
          temp: {
            value: temp
          },
          humid: {
            value: humid
          },
          light: {
            value: light
          },
          uv: {
            value: uv
          },
          press: {
            value: press
          },
          noise: {
            value: noise
          },
        };
        kintoneUtility.rest.postRecord({
          app: kintoneapp.id,
          record: record,
          isGuest: true
        }).then(function(response) {
          console.log(response);
        }).catch(function(error) {
          console.log(error);
        });
    }

index.htm_HTML部分
<body>
    <div>
        <h2>温湿度ビーコン連携</h2>
    </div>
    <div id="msg"></div>
  <ons-button onClick = "blescan();">Manual Scan</ons-button>
  <ons-button onClick = "timerStart();">Start periodical</ons-button>
</body>

注意点

バックグラウンドで動かそうとするにはバッファリングとか必要かもしれません。

余談

弊社kintoneのヘビーユーザーでクライアント証明書まで導入しているんですが、すっかりそのこと忘れていて謎のエラーが返ってくるデバッグで半日使ってしまいました、、。ゲストスペースを使用しているのはその理由です、、。

利用例

こんな感じで3分毎にデータを上げさせたものをkintoneで可視化してみました。

mBaaSの中で上げたデータで簡単にグラフを書いてくれるものがなかったので、こういう用途でkintoneは便利かと思います。mBaaSが必要な理由に関してはまた来年中旬ぐらいに公表予定です。

ちなみにわたくし猛烈にカゼを引きやすいので、カバンにつけておいてモニタしてます。おかげで部屋の温度が2度低いだけでブーブー言う面倒くさい人間になりました(笑)