Experience IoT through Node.js

起きたらツイートする目覚まし時計

Node.jsを入れたRasberry Piで目覚ましをつくろう〈Node.jsシリーズ vol.6〉

前回の記事では、Node.jsを入れたRaspberry Piを使ったシンプルなIoT体験の方法について書きました。

今回はさらにレベルアップして、Raspberry Piからハードウェアを制御しながら、同時にネット上にもデータを投げるデモを作ってみたいと思います。

Raspberry Piでスイッチ入力を受け付ける

前回はRaspberry Piに接続したLEDを点灯させるデモをご紹介しましたが、今回はその逆、Raspberry Piに接続したパーツからの入力を受けてみましょう。

まずは簡単なスイッチを接続し、これが押されるとコンソールにメッセージを表示するコードを書きたいと思います。

今回はタクタイルスイッチというシンプルな押しボタン式のスイッチで構成します。
スイッチから流れる電圧の高低でRaspberry Pi側はON/OFFを判定するのですが、このあたりの詳しいメカニズムの話は本題と離れるので割愛します。

構成にあたっては「ラズベリーパイで手作り目覚まし時計!ストップボタン編」という記事を参考にさせていただきました。

まずは、以下のようなコードを書いてRaspberry Pi上のNode.js環境で実行します。

switch_receive.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var fs = require('fs');

// Raspberry Pi GPIOの21番ピンを入力モードに設定する
fs.writeFileSync('/sys/class/gpio/export', 21);
fs.writeFileSync('/sys/class/gpio/gpio21/direction', 'in');

// 無限ループで21番ピンの状態を表示し続ける(ONなら1、OFFなら0)
// ONとなったらループを抜けて終了
var value = 0;
while( 1 ) {
    value = fs.readFileSync('/sys/class/gpio/gpio21/value', 'ascii');
    console.log( value );

    if ( value == 1 ) {
        break;
    }
}

// ループを抜けたら、21番ピンの使用を解除して終了
fs.writeFileSync('/sys/class/gpio/unexport', 21);

$ sudo node switch_receive.jsで起動しましょう。

スイッチを押さない状態ではコンソールに0が表示され続けていますが……

スイッチを押すと、1と表示して終了しました。実験成功です!

アラームをスイッチで止める仕組みを作る

今度はこれを応用し、スイッチを押して止めない限りアラームが鳴り続け、止めると「起きました!」とツイートする仕組みを作ってみましょう。

アラームブザーとして、回路に圧電ブザーを追加します。

今回はGPIOの20番ピンに接続します。

起動したらブザーが鳴り続け、スイッチを押すとツイートして止まるコードを作成してみます。

buzzer.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/** パラメータまわり **/

// アプリ登録時に取得したkeyを入れて初期化
var twitter = require('twitter');
var client = new twitter({
    consumer_key: '【Consumer Keyの内容】',
    consumer_secret: '【Consymer Secretの内容】',
    access_token_key: '【Access Token Keyの内容】',
    access_token_secret: '【Access Token Secretの内容】'
});


/** アラーム判定メイン部分 **/

var fs = require('fs');

// Raspberry Pi GPIOの20番ピンを出力に
fs.writeFileSync('/sys/class/gpio/export', 20);
fs.writeFileSync('/sys/class/gpio/gpio20/direction', 'out');

// Raspberry Pi GPIOの21番ピンを入力受け付け
fs.writeFileSync('/sys/class/gpio/export', 21);
fs.writeFileSync('/sys/class/gpio/gpio21/direction', 'in');

while (1) {
    // 21番ピンの入力をチェック
    var value = fs.readFileSync('/sys/class/gpio/gpio21/value', 'ascii');

    if ( value == 1 ) {
        // ストップスイッチを押したらループを抜ける
        break;
    }
    else {
        // ストップスイッチが押されるまでの処理
        // 20番ピンのブザーを鳴らす
        // (ON/OFFを交互に行い、音を鳴らす)
        fs.writeFileSync('/sys/class/gpio/gpio20/value', 1);
        fs.writeFileSync('/sys/class/gpio/gpio20/value', 0);
    }
};


/** ループを抜けたあとの処理 **/

// ツイートする
client.post( 'statuses/update', { status : "起きました!" }, function() {} );

// ピンを解放
fs.writeFileSync('/sys/class/gpio/unexport', 20);
fs.writeFileSync('/sys/class/gpio/unexport', 21);

$ sudo node buzzer.jsで起動すると、ブザーが鳴り響きます。

ここで、ボタンを押すと、ブザーが止まり、Twitterに

と、ツイートされました。

これで、基本ができました。

Twitterでパラメーター設定ができるようにしよう

さて、これまでの実装の集大成です。

Node.js + Raspberry Piで、Twitterから制御できる目覚ましを作りましょう!

  • 今回目標とする仕様
    • Twitterでアラーム時刻をツイートすると設定される
    • アラーム時刻になると圧電ブザーが鳴る
    • ストップボタンを押すとアラームが停止し、Twitterに「起きました!」とツイートする

コードはこのようなかたちになります。

mezamashi.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/** パラメータまわり **/

// アプリ登録時に取得したkeyを入れて初期化
var twitter = require('twitter');
var client = new twitter({
    consumer_key: '【Consumer Keyの内容】',
    consumer_secret: '【Consymer Secretの内容】',
    access_token_key: '【Access Token Keyの内容】',
    access_token_secret: '【Access Token Secretの内容】'
});


/** 関数定義部分 **/

// アラームセット関数
var alarmEpoch = 0;
function setAlarm( year, month, day, hour, min ) {
    alarmEpoch = ( new Date( year, month - 1, day, hour, min ) ).getTime();
}

// アラーム設定時刻判定関数
function isAlarmTime() {
    var nowEpoch = ( new Date() ).getTime();
    if ( alarmEpoch <= nowEpoch ) {
        return 1;
    }
    else {
        return 0;
    }
}


/** アラーム判定メイン部分 **/

// タイムラインから、指定した文字列でフィルターする
client.stream( 'statuses/filter', { track : '@【自分のアカウント名】 #meza' }, function( stream ) {
    stream.on( 'data', function( data ) {

        // 文字列をパースして設定時刻を取り出し
        var text = data.text;
        var matches = text.match( /\d+/ );
        var matchRaw = matches[0];
        var year  = matchRaw.substr(0,4);
        var month = matchRaw.substr(4,2);
        var day   = matchRaw.substr(6,2);
        var hour  = matchRaw.substr(8,2);
        var min   = matchRaw.substr(10,2);

        // アラーム設定
        setAlarm( year, month, day, hour, min );

        /* Raspberry Pi GPIO設定 */
        var fs = require('fs');

        // Raspberry Pi GPIOの20番ピンを出力に
        fs.writeFileSync('/sys/class/gpio/export', 20);
        fs.writeFileSync('/sys/class/gpio/gpio20/direction', 'out');

        // Raspberry Pi GPIOの21番ピンを入力受け付け
        fs.writeFileSync('/sys/class/gpio/export', 21);
        fs.writeFileSync('/sys/class/gpio/gpio21/direction', 'in');

        /* アラーム待ち受け */
        while (1) {
            if ( !isAlarmTime() ) { continue; }

            // 21番ピンの入力をチェック
            var value = fs.readFileSync('/sys/class/gpio/gpio21/value','ascii');

            if ( value == 1 ) {
                // ストップスイッチを押したらループを抜ける
                break;
            }
            else {
                // ストップスイッチが押されるまでの処理
                // 20番ピンのブザーを鳴らす
                fs.writeFileSync('/sys/class/gpio/gpio20/value', 1 );
                fs.writeFileSync('/sys/class/gpio/gpio20/value', 0 );
            }
        }


        /** ループを抜けたあとの処理 **/

        // ツイートする
        client.post( 'statuses/update', { status : "起きました!" }, function() {} );

        // ピンを解放
        fs.writeFileSync('/sys/class/gpio/unexport', 20);
        fs.writeFileSync('/sys/class/gpio/unexport', 21);
    });
});

Twiter Streaming APIでツイートを待ち受け、「@【自分のアカウント名】 YYYYMMDDHHMM #meza」というツイートが見つかれば、これをアラーム時刻として設定します。

あとは無限ループでアラーム時刻に達するまで待ち続け、時刻に達したらGPIO経由で圧電ブザーを鳴らします。

同じくGPIO経由でボタン入力も待ち構え、入力があり次第、ループを抜けだして「起きました!」とツイートします。

実行する前に、Raspberry Piのタイムゾーン設定がきちんとUTC+9になっているかの確認をお忘れなく。
設定方法はこちらの記事が参考になります。

$ sudo node mezamashi.jsで待ち受け状態になったら、Twitterで「@【自分のアカウント名】 201509010600 #meza」とツイートし、アラーム時刻を設定します。

アラーム設定時刻になると……

ブザーが鳴りました!

ボタンを押すとブザーが止まり、ツイートされます!

このようにNode.jsを使うと、比較的簡単にイベントドリブンなアプリケーションを書くことができ、Raspberry Piを組み合わせることでお手軽にIoTを実感することができます。

最先端の技術を手軽に使えるNode.js、ぜひこの素晴らしき世界にあなたも飛び込んでみてください!

Tech Blog

(編集部)

株式会社リクルートライフスタイルのTech Blog編集部です。いま流行りのTechネタやちょっと使えるTipsなどをお届けしていきます。

NEXT