Bluemix Node-REDでスマホを振ったらTweetするシステムを作る

# 前置き
## Bluemixとは
- IBMが提供するPaaS(Platform as a Service)。
- 迅速かつ簡単にクラウド上でアプリケーションを作成、デプロイ、管理することができる。
- 数多くのアプリやサービスが提供されており、自然言語を解釈するWatsonなどが有名。

# やってみる
## 前提
- BluemixのIBM IDをすでに登録済み（トライアルでも可）であること
    - 登録していない人はhttps://console.ng.bluemix.net/registration から登録
- スマホを持っていること（加速度センサーが対応していれば可能なはず）
- Twitterアカウントを持っていること（持っていなければ作成）
- GitHubのアカウントを持っていること（持っていなければ作成）

## 内容
1. Node-REDアプリの立ち上げ
[BluemixでGitHubの連携やWeb IDE、Delivery Pipelineを利用できるようにする](http://qiita.com/sear-azazel/items/c69a050f9a661cf00c7d)を参考にNode-REDを立ち上げる。

2. モバイルセンサーの組み込み
    - 下記のソースコードをコピーして、Tool ChainsのEclipse orion Web IDEから、publicフォルダへ配置
        - ソースコード

            ```html:sensor.html
            <!DOCTYPE html>
            <html lang="ja">
                <head>
                    <meta charset="utf-8">
                    <meta http-equiv="X-UA-Compatible" content="IE=edge">
                    <meta name="viewport" content="width=device-width, initial-scale=1">
                    <title>加速度センサー</title>
                    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
                    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
                    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
                    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
                </head>
                <body>
                    <div class="container">
                        <div class="table-responsive">
                            <h3 id="deviceid"></h3>
                            <table class="table table-striped table-bordered">
                             <thead>
                                <tr><th>Keys</th><th>Values</th></tr>
                             </thead>
                             <tbody>
                                <tr><td>x</td><td id="acx">&nbsp;</td></tr>
                                <tr><td>y </td><td id="acy">&nbsp;</td></tr>
                                <tr><td>z </td><td id="acz">&nbsp;</td></tr>
                            </table>
                        </div>
                     </div>
                    <script type="text/javascript">
                        var client;
                        var deviceid;
            
                        $(function () {
                            fncGetDeviceId();
                            fncMqttConnect();
                            if (window.DeviceMotionEvent) {
                                window.addEventListener("devicemotion", evtDeviceMotion);
                            }
                        });
            
                        function fncGetDeviceId() {
                            var did = null;
                            cookies = document.cookie.split("; ");
                            for (var i = 0; i < cookies.length; i++) {
                                str = cookies[i].split("=");
                                if (unescape(str[0]) === "deviceid") {
                                    did = unescape(unescape(str[1]));
                                }
                            }
                            deviceid = did !== null ? did : fncGenerateDeviceId();
                            $("#deviceid").html("device id : " + deviceid);
                        }
            
                        function fncGenerateDeviceId() {
                            var did = "";
                            for (var i = 0; i < 12; i++) {
                                did += "0123456789abcdef".charAt(Math.floor(Math.random() * 16));
                            }
                            var str = "deviceid=" + did;
                            document.cookie = str;
            
                            return did;
                        }
            
                        function evtDeviceMotion(event) {
                            event.preventDefault();
                            var ac = event.acceleration;
                            if (ac !== null) {
                                $('#acx').html(ac.x);
                                $('#acy').html(ac.y);
                                $('#acz').html(ac.z);
                            }
                            if (deviceid !== null){
                                var message = new Paho.MQTT.Message(JSON.stringify({ ac : { x : ac.x, y : ac.y, z : ac.z } }));
                                message.destinationName = 'iot-2/evt/status/fmt/json';
                                client.send(message);
                            }
                        }
            
                        function fncMqttConnect() {
                            var client_id = "d:quickstart:MyDevice:" + deviceid;
            
                            client = new Paho.MQTT.Client("ws://quickstart.messaging.internetofthings.ibmcloud.com:1883/", client_id);
                            client.connect({onSuccess: onConnect, onFailure: failConnect});
                            client.onConnectionLost = onConnectionLost;
            
                            function failConnect(e) { console.log(e); }
                            function onConnect() { console.log("connect success."); }
                            function onConnectionLost(response) { 
                                if (response.errorCode !== 0) {
                                    console.log("lost connection : " + response.errorMessage);
                                }
                                client.connect({onSuccess: onConnect, onFailure: onConnectFailure});
                            }
                        }
                    </script> 
                </body>
            </html>
            ```
        - 配置先    
        ![スクリーンショット 2017-01-17 23.41.41.png](https://qiita-image-store.s3.amazonaws.com/0/153015/8ee489e9-398c-add7-bc90-27ed160351e8.png)

            - 補足）GitHubでのPushやCFコマンドラインからのデプロイでも可

1. アプリのデプロイ
    - デプロイボタンをクリック    
    ![スクリーンショット 2017-01-17 23.41.42.png](https://qiita-image-store.s3.amazonaws.com/0/153015/23e5662c-d1b8-aa86-7514-b2ed38ea9361.png)

### Node-REDの実装
1. Device IDの取得
    - **http**://<アプリ名>.mybluemix.net/sensor.htmlをスマホで開いてDivice IDをコピー ※プロトコル（**http**）に注意    
    ![スクリーンショット 2017-01-17 23.49.31.png](https://qiita-image-store.s3.amazonaws.com/0/153015/84a3909f-61dc-0092-5fe7-68b8c7760fae.png)

1. Node-REDフローエディタ画面を開く
    - https://<アプリ名>.mybluemix.net/red

1. 以下の4つのノードを配置し、順番に連結させる
    - TBM IoT
    - function
    - switch
    - Twitter (output)
    - 例）完成図    
    ![スクリーンショット 2017-01-17 23.25.04.png](https://qiita-image-store.s3.amazonaws.com/0/153015/67022fcc-5231-12c2-5c45-51db1a0b56d0.png)

1. IBM IoTノードを設定する
    - Device ID入力欄に、取得したDevice IDをペースト
    ![スクリーンショット 2017-01-17 23.32.37.png](https://qiita-image-store.s3.amazonaws.com/0/153015/bbb5f9dd-3456-0411-8ee9-6a5b7cabbbd9.png)

1. functionノードを設定する
    - 加速度センサーXYZ軸のいずれかの値が-10～10の範囲外になったら、Tweetメッセージをセット
    - Tweetしたいメッセージを`msg.payload`に代入（連投を防ぐためメッセージに日付を入れる）

        ```js:参考
        if (Math.abs(msg.payload.ac.x) > 10 || Math.abs(msg.payload.ac.y) > 10 || Math.abs(msg.payload.ac.z) > 10) {
            var date = context.global.moment();
            date.locale("ja").tz("Asia/Tokyo");
            msg.payload = date.format("LLL") + " です。";
        } else {
            msg.payload = null;
        }
        
        return msg;
        ```
        補足）[Bluemix Node-REDに2行追加して日本時間を簡単に出力する](http://qiita.com/sear-azazel/items/953d4ca026457d8d721a) でタイムゾーン指定をできるようにしておく
        していない場合は、以下で代用

        ```js:参考
        if (Math.abs(msg.payload.ac.x) > 10 || Math.abs(msg.payload.ac.y) > 10 || Math.abs(msg.payload.ac.z) > 10) {
            msg.payload = "スマホを振りました。 " + new Date().getTime();
        } else {
            msg.payload = null;
        }
        
        return msg;
        ```

1. switchノードを設定する
    - `msg.payload`が`null`でなければ、次のノードへトークンが進むようにする
    ![スクリーンショット 2017-01-17 23.32.29.png](https://qiita-image-store.s3.amazonaws.com/0/153015/5cbc91cd-9e4e-b752-f87a-9170c86bb51e.png)

1. Twitterノードを設定する
    1. 編集ボタン（鉛筆マーク）をクリック    
    ![スクリーンショット 2017-01-17 23.34.27.png](https://qiita-image-store.s3.amazonaws.com/0/153015/02696fc1-ce7c-1e8b-18ff-1c95f1d29539.png)
    1. 「Click here to authenticate with Twitter.」ボタンをクリック    
    ![スクリーンショット 2017-01-17 23.34.32.png](https://qiita-image-store.s3.amazonaws.com/0/153015/931d059d-52c5-9abb-c12d-52c4f7d2f830.png)
    1. Twitterのページが開くので、「連携アプリを認証」をクリック（必要に応じてログイン）    
    ![スクリーンショット 2017-01-17 23.34.36.png](https://qiita-image-store.s3.amazonaws.com/0/153015/f746569e-d437-779e-19ab-f200e23bd37d.png)
    1. アカウント名が表示されるので、「Add」ボタンをクリック    
    ![スクリーンショット 2017-01-17 23.34.43.png](https://qiita-image-store.s3.amazonaws.com/0/153015/55af7377-a99f-cc18-3482-73ca211ff18b.png)
    1. 「Done」をクリック    
    ![スクリーンショット 2017-01-17 23.34.47.png](https://qiita-image-store.s3.amazonaws.com/0/153015/6b07a007-1022-6b8d-ba33-333c9e5e51a7.png)

1. アプリをデプロイ
    - 右上のDeployボタンをクリック    
    <img width="320" alt="スクリーンショット 2016-12-27 01.32.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/153015/1077b1f6-c892-4339-730c-4527e4473be9.png">

## 動作確認
1. スマホ（Android、iOS）でhttp://<アプリ名>.mybluemix.net/sensor.htmlを開く
1. スマホを振る
1. Tweetを確認

以上

## 補足
動作確認はAndroid 5.1.1 でのみ