WiFiが使えない場所でもIoT!3G通信モジュール「3GPI」を使って、Raspberry Piの温度データをMilkcocoaに送信してみた

Posted: / Tags: Raspberry_Pi



こんにちは!部谷です。メカトラックス株式会社さんに3GPIをお借りしたので、使ってみました!

3GPIはその名の通り、Raspberry Pi用の3Gモジュールです。最近ソラコムさんのSIMで3GPIを使うブログをよく見かけます。

本製品は、Raspberry Piにスタック可能な 3G 通信モジュール搭載基板です。

設定済みOSをインストールしたmicroSDカードが付属しているため、対応SIMを使用すれば即座にインターネットに接続可能です。

通信不調時の自動リセット機能や再接続機能も備えており、C言語以外にスクリプト言語も利用できるため、組み込み開発に不慣れな方でも簡単に M2M 機器等の開発が可能となります。

3GPI(Raspberry Pi 向け3G通信モジュール)| 電子/通信機器/組込機器の開発-メカトラックス株式会社

今回はその先の、どういう風にアプリケーションを作るのかというところをやりたいと思います。

まずはセットアップ

セットアップは、以下の3つの手順になります。

  1. Raspberry Piと3GPIを接続する
  2. Node.jsをインストールする
  3. SPI(シリアル通信)を使えるようにする

Raspberry Piと3GPIを接続する

以下の手順で接続します。

  • 3GPIモジュールにSIMを装着します。(SIMは別途用意する必要があります)
  • 3GPIモジュールをRaspberry Piに取り付けます。
  • USBケーブルで3GPIとRaspberry Piをつなぎます。
  • 3Gアンテナをつけます。

今回はDTIのSIM(ドコモのmvno)をお借りして使用しました。3GPIをRaspberry Piに取り付ける作業は、説明書を見ながらやればとても簡単でしたので割愛します。SDカードは同封されているものを使いました。それに温度センサーをつけて、仕上がりは以下の画像みたいな感じです。

この辺は知り合いのロケット飛ばしている高校生に手伝っていただきました。今回の温度センサーはADT7310で、以下のブログ記事と同じセンサーです。

さっそく3GでIPを取得できているかifconfigで確認。ppp0ってところですね。

pi@raspberrypi:~/$ ifconfig
eth0      Link encap:Ethernet  HWaddr b8:27:eb:c5:88:xx
          inet addr:192.168.0.9  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::ba27:ebff:fec5:8807/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14203 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12425 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7194480 (6.8 MiB)  TX bytes:1661214 (1.5 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1104 (1.0 KiB)  TX bytes:1104 (1.0 KiB)

ppp0      Link encap:Point-to-Point Protocol
          inet addr:100.71.159.xxx  P-t-P:10.64.64.64  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:7 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:130 (130.0 B)  TX bytes:321 (321.0 B)

Node.jsをインストールする

Raspberry Piで取得したセンサーデータをリアルタイムに可視化する(導入編)でも紹介しましたが、以下のコマンドでNode.jsをインストールします。

pi@raspberrypi:~/$ wget http://nodejs.org/dist/v0.10.24/node-v0.10.24-linux-arm-pi.tar.gz
pi@raspberrypi:~/$ tar -zxvf node-v0.10.24-linux-arm-pi.tar.gz
pi@raspberrypi:~/$ sudo mv node-v0.10.24-linux-arm-pi /usr/local/node

SPI(シリアル通信)を使えるようにする

Raspberry Piで取得したセンサーデータをリアルタイムに可視化する(センサー編)と同様に、SPIを有効にする作業を行います。

pi@raspberrypi:~/$ sudo vi /etc/modprobe.d/raspi-blacklist.conf
/etc/modprobe.d/raspi-blacklist.conf
#blacklist spi-bcm2708
blacklist i2c-bcm2708

また、今回はSPIを有効にする作業で、追加で行うことがあります。

まず、/boot/config.txtdtparam=spi=onを追加します。

pi@raspberrypi:~/$ sudo vi /boot/config.txt
dtparam=spi=on

sudo rebootでリブートします。

pi@raspberrypi:~/$ sudo reboot

再起動が終わったら、spiがonになっているか確認します。spi_bcm2708が出てくればOKです。

pi@raspberrypi:~/$ lsmod | grep spi
spi_bcm2708             5183  0

最後に、nodeをコマンドを使えるようにしましょう。

pi@raspberrypi:~/$ sudo ln -s  /usr/local/node/bin/node /usr/bin/node
pi@raspberrypi:~/$ sudo ln -s  /usr/local/node/bin/npm /usr/bin/npm
pi@raspberrypi:~/$ node -v
v0.10.24

これでセットアップ終了です。

さっそくMilkcocoaを使ってみる

セットアップが終わったのでMilkcocoaを使っていきます。登録がまだの方はMilkcocoaのサイトで登録を済ませ、アプリを作成しておいて下さい。

動くプログラムを作成

まず必要なモジュールをインストールします。今回は/home/pi/work/で作業することにします。

Raspberry Piのコマンド
$ mkdir work
$ cd ~/work
$ npm install milkcocoa
$ npm install pi-spi
$ sudo npm install forever -g

/worktemp.jsというJavaScriptファイルを作ります。シリアル通信で書き込む値等(主にBufferクラス使用部分)はこちらの記事を参考にしています。

/home/pi/work/temp.js
var MilkCocoa = require('milkcocoa');
var SPI = require('pi-spi');
var Interval = 5 * 60 * 1000;

//起動して20秒後に開始
setTimeout(start, 20 * 1000);

function start() {
  var milkcocoa = new MilkCocoa('your-app-id.mlkcca.com');
  var ds = milkcocoa.dataStore('3gpi-test');

  var spi = SPI.initialize("/dev/spidev0.1"),
  INIT1 = Buffer([0x08,0x80]),
  INIT2 = Buffer([0x54]),
  Stop = Buffer([0x50]),
  Op = Buffer([0xff,0xff]);

  spi.clockSpeed(100000);

  loop();

  function loop() {
    spi.write(INIT1, function() {
      setTimeout(function() {
        spi.write(INIT2, function() {
          setTimeout(getTemp, 1000)
        })
      }, 500);
    });
    function getTemp() {
      spi.transfer(Op, Op.length, function (err, d) {
        if(err) {
          console.error(err);
          return;
        }
        var v = ((d[0]<<8) + d[1]) / 128;
        console.log(v);
        ds.push({val : v});
        spi.write(Stop, function() {
          setTimeout(loop, Interval);
        })
      });
    }
  }
}

your-app-idのところは自分のMilkcocoa App IDに書き換えてください。

node temp.jsで動作確認できます。20秒たつと、温度がコンソールに表示されます。 Milkcocoaの管理画面でも確認できます。

デーモン化してみる

自動起動するようデーモン化してみましょう。

etc/init.dの中のtemptemp.jsを起動するスクリプトを書きます。

pi@raspberrypi:~/$ sudo vi /etc/init.d/temp
/etc/init.d/temp
#! /bin/sh
# /etc/init.d/temp
### BEGIN INIT INFO
# Provides:              GSpreadEdit
# Required-Start:    $remote_fs $named $syslog
# Required-Stop:     $remote_fs $named $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: &lt;Short Description&gt;
# Description:       &lt;Longer Description&gt;
### END INIT INFO

USER=pi
HOME=/home/pi

export USER HOME
export NODE_PATH=$NODE_PATH:/home/pi/work/node_modules
export PATH=$PATH:/usr/bin

case "$1" in
    start)
        echo "Starting... Temp"
    su $USER -c 'forever start /home/pi/work/temp.js'
        ;;

    stop)
        echo "Stopping..."
        su $USER -c 'forever stop /home/pi/work/temp.js'
        ;;

    *)
        echo "Usage: /etc/init.d/temp {start|stop}"
        exit 1
        ;;
esac

exit 0

tempを保存したら、パーミッションを変更した後、自動起動の設定をします。

pi@raspberrypi:~/$ sudo chmod 777 /etc/init.d/temp
pi@raspberrypi:~/$ sudo update-rc.d temp defaults

これでRaspberry Piを起動すると自動的に、temp.jsのプログラムが実行されます。LANケーブルをとって、Raspberry Piを再起動してみましょう。

定期的に温度が取得できてます。ここまで3時間ほどでできました。

おまけ(Web側の監視用画面を作ってみる)

ちなみに現在の温度と、平均と最大と最小を表示するWeb側の処理を書いてみました。ブラウザをリロードしなくても、5分ごとにデータが更新されます。

ソースコードはこれだけです。

index.html
<html>
<head>
    <style>
        .wrapper {
            width: 760px;
            margin: 0 auto;
        }
        .panel {
            width: 80%;
            color: #333;
            background-color: #eef;
            margin: 20px auto;
        }
        .panel-title {
            background-color: #cce;
            font-size: 20px;
            padding: 2px 6px;
        }
        .panel-body {
            padding: 12px 24px;
            font-size: 24px;
        }
    </style>
</head>
<body>
    <div class="wrapper">
        <div class="panel">
            <div class="panel-title">Current</div>
            <div id="current" class="panel-body">29.8</div>
        </div>
        <div class="panel">
            <div class="panel-title">Average</div>
            <div id="average" class="panel-body">27.5</div>
        </div>
        <div class="panel">
            <div class="panel-title">Max</div>
            <div id="max" class="panel-body">30.1</div>
        </div>
        <div class="panel">
            <div class="panel-title">Min</div>
            <div id="min" class="panel-body">24.6</div>
        </div>
    </div>

<script src='https://cdn.mlkcca.com/v0.6.0/milkcocoa.js'></script>
<script>
window.addEventListener('load', function() {
    var currentElem = document.getElementById('current');
    var avgElem = document.getElementById('average');
    var maxElem = document.getElementById('max');
    var minElem = document.getElementById('min');

    var milkcocoa = new MilkCocoa("hoticvaynqn.mlkcca.com");
    var ds = milkcocoa.dataStore('3gpi-test');
    var currentDataArr = [];
    ds.on('push', function(pushed) {
        currentDataArr,push(pushed);
        update(currentDataArr);
    });
    ds.stream().next(function(err, data) {
        currentDataArr = data.reverse();
        update(currentDataArr);
    });
    function update(data) {
        var current = 0, avg = 0, max = 0,min = 100;

        current = data[0].value.val;

        data.forEach(function(d) {
            avg += d.value.val;
            if(max < d.value.val) max = d.value.val;
            if(min > d.value.val) min = d.value.val;
        })
        avg /= data.length;

        currentElem.textContent = current;
        avgElem.textContent = avg;
        maxElem.textContent = max;
        minElem.textContent = min;
    }
});
</script>
</body>
</html>

おまけ2(認証とアクセス制御)

状況に応じて、「認証」か「手軽なアクセス制御」をやっておきましょう。

  • それなりの規模だったり、ビジネスとしてやるなら「認証」
  • 開発時や個人的にやるなら「手軽なアクセス制御」

認証

今回は以下を参考に、Auth0を用いて認証までしてみました。

Auth0に関する設定は リアルタイムなToDoアプリをMilkcocoaとJavaScriptで作る(認証編)も参考になります。今回はFacebook認証ではなく、User/Pass認証を行っています。Auth0側でConnectionというものを作らなければいけません。このあたりは次回に詳しく説明しようと思います。

こちらのnode.jsでauth0を使うための汎用モジュールworkディレクトリにコピー(/work/以下にauth0wrapper.jsを作成)して、temp.jsを以下のように修正します。

/home/pi/work/temp.js
var MilkCocoa = require('milkcocoa');
var Interval = 5 * 60 * 1000;
var SPI = require('pi-spi');

// auth0wrapper.jsを読み込む
var auth0 = require("./auth0wrapper");

auth0.setHost("auth0アカウントのドメイン.auth0.com");
auth0.setClientId("auth0のClient ID");
auth0.setConnection("Auth0のConnections名");

setTimeout(auth, 1000);

function auth() {
    var milkcocoa = new MilkCocoa('hoticvaynqn.mlkcca.com');
    milkcocoa.user(function(err, user) {
        console.log(err, user);
        if(user) {
            start(milkcocoa);
        }else{
            auth0.loginWithEmailAndPassword("syuhei176@gmail.com", "universe", function(err, data) {
                milkcocoa.authWithToken(data.id_token, function(err, user){
                    if(err) return console.error(err);
                    start(milkcocoa);
                });
            });
        }
    });
}

function start(milkcocoa) {

var ds = milkcocoa.dataStore('3gpi-test');
/*省略*/
}

Web側のプログラムでも同じように認証すれば、以下のようなセキュリティルールでアクセス制御できます。 auth0|useridxxxxxxxxxxxがユーザIDです。Auth0の管理画面で確認することができます。

セキュリティルール
3gpi-test {
    permit : all;
    rule : account.sub == "auth0|useridxxxxxxxxxxx";
}

手軽なアクセス制御

手軽にアクセス制御するのであれば、以下のようにUUIDを生成して、MilkCocoaの第2引数にclientIdとして入れる方法を使います。

/home/pi/work/temp.js
var MilkCocoa = require('milkcocoa');
var Interval = 5 * 60 * 1000;
var SPI = require('pi-spi');
var clientId = "324f84d9-bc3f-41d1-b0f9-f5912ee990a4";

setTimeout(auth, 1000);

function start() {
    var milkcocoa = new MilkCocoa('your-app-id.mlkcca.com', {clientId:clientId});

/*省略*/
}
セキュリティルール
3gpi-test {
    permit : on(push), query;
    rule : true;
}

3gpi-test {
    permit : push;
    rule : client.id == "324f84d9-bc3f-41d1-b0f9-f5912ee990a4";
}

終わりに

3GPIを使ってMilkcocoaにデータを保存する例を紹介しました。

3G通信を使うことで、車でも、物置でも、WiFiのないおばあちゃんの家でも、電源があればどこでも持っていけます。便利ですね。

皆さんも一度、祖父母の家に設置してモニタリングしてみる等やってみてはいかがでしょうか。


記事内で次の画像を加工・使用しています: "Raspberry Pi Vector Illustration" by Jonathan Rutheiser - Own work. Licensed under CC BY-SA 3.0 via Wikimedia Commons.