ラズパイでTrackrr.io APIを使って、距離が近づいたらslack通知してみる

[Trackrr.io API](https://trackrr.io/swagger-ui/index.html)の一つに距離を計算してくれるものがあります。
たとえばTrackrr.io上でトラッキングしているバスAと、自分との間の距離を計算します。

今回は[以前作成したhtml](http://qiita.com/YusukeHasegawa/items/f2d2c6af1b6caab03cc6)でスマフォの位置情報をトラッキングして、ラズパイに近づいたらslackで通知してみようと思います。

先ほどの例だと、スマフォをバスA、ラズパイを自分に置き換えるとわかりやすいと思います。

#Slackに通知してみる
##Node Library for the Slack APIsのインストール
```shell-session
pi@raspberrypi:~/trackrr.io-sdk-js-sample$ npm install @slack/client --save
npm WARN package.json trackrr.io-sdk-js-sample@1.0.0 No description
npm WARN package.json trackrr.io-sdk-js-sample@1.0.0 No repository field.
npm WARN package.json trackrr.io-sdk-js-sample@1.0.0 No README data
@slack/client@3.5.3 node_modules/@slack/client
tqq inherits@2.0.1
tqq eventemitter3@1.2.0
tqq url-join@0.0.1
tqq async@1.5.2
tqq retry@0.9.0
tqq ws@1.1.1 (options@0.0.6, ultron@1.0.2)
tqq bluebird@3.4.1
tqq https-proxy-agent@1.0.0 (extend@3.0.0, debug@2.2.0, agent-base@2.0.1)
tqq winston@2.2.0 (cycle@1.0.3, stack-trace@0.0.9, isstream@0.1.2, eyes@0.1.8, async@1.0.0, pkginfo@0.3.1, colors@1.0.3)
tqq request@2.74.0 (aws-sign2@0.6.0, tunnel-agent@0.4.3, forever-agent@0.6.1, oauth-sign@0.8.2, is-typedarray@1.0.0, caseless@0.11.0, stringstream@0.0.5, aws4@1.4.1, isstream@0.1.2, extend@3.0.0, json-stringify-safe@5.0.1, form-data@1.0.0-rc4, tough-cookie@2.3.1, qs@6.2.1, node-uuid@1.4.7, combined-stream@1.0.5, mime-types@2.1.11, bl@1.1.2, hawk@3.1.3, http-signature@1.1.1, har-validator@2.0.6)
mqq lodash@4.14.0
pi@raspberrypi:~/trackrr.io-sdk-js-sample$
```

##slack.jsを作成
今回はTest tokenで送信します。

```js:slack.js
var WebClient = require('@slack/client').WebClient;
var token = process.env.SLACK_API_TOKEN || '';
var web = new WebClient(token);
web.chat.postMessage('チャンネル名','paspberrypiから送信');
```
※Test tokenは環境変数にセットしています。
`node slack.js`で実行するとメッセージが送信されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/132516/67b8d6ba-7efd-621b-63e4-82e0d732c614.png)

#距離を取得してみる
ラズパイに接続しているGPSモジュールの情報で距離を取得してみます。

##distance.jsを作成

```js:distance.js
//シリアルポートの設定
var serialport = require("serialport");
var nmea = require('nmea-0183');
var port = '/dev/ttyUSB0';
var baudrate = 4800;
var readline = '\r\n';
var https = require('https');

var receiver = new serialport(port, {
  baudrate: parseInt(baudrate),
  parser: serialport.parsers.readline(readline)
});

//Trackrr.io APIの設定
var options = {
    hostname: 'trackrr.io',
    port: 443,
    path: '/api/geoCalc/calc-distance-by-location',
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    }
};
//GPSの受信
receiver.on('data', function(data) {
        var nmeaData = nmea.parse(data);
    if (nmeaData['id'] == 'GPRMC') {
                var postData = JSON.stringify({
                  "destCoords": {
                    "latitude": Number(nmeaData.latitude),
                    "longitude": Number(nmeaData.longitude)
                  },
                  "startGpsKey": "844ebb8f1c9deb4bcbaf1acf765c90d34c19fde2bd6b590556015e56f7ba323647c520f2e409d4f9f93f"
                });
                console.log(postData);
                var req = https.request(options, (res) => {
                        res.on('data', (body) => {
                        var data = JSON.parse(body);
                        console.log(data);
                        });
                });
                req.write(postData);
                req.end();
    }
});
```
で、実行結果は

```shell-session
pi@raspberrypi:~/trackrr.io-sdk-js-sample$ node distance.js
{"destCoords":{"latitude":35.69545667,"longitude":139.76682167},"gpsKey":"844ebb8f1c9deb4bcbaf1acf765c90d34c19fde2bd6b590556015e56f7ba323647c520f2e409d4f9f93f"}
{"destCoords":{"latitude":35.69545667,"longitude":139.76682167},"gpsKey":"844ebb8f1c9deb4bcbaf1acf765c90d34c19fde2bd6b590556015e56f7ba323647c520f2e409d4f9f93f"}
{ value: 13.946871637221008 }
{ value: 13.946871637221008 }
{"destCoords":{"latitude":35.69545667,"longitude":139.76682167},"gpsKey":"844ebb8f1c9deb4bcbaf1acf765c90d34c19fde2bd6b590556015e56f7ba323647c520f2e409d4f9f93f"}
{ value: 13.946871637221008 }
{"destCoords":{"latitude":35.69545667,"longitude":139.76682167},"gpsKey":"844ebb8f1c9deb4bcbaf1acf765c90d34c19fde2bd6b590556015e56f7ba323647c520f2e409d4f9f93f"}
{ value: 13.946871637221008 }
```
{ value: 13.946871637221008 }の値がAPIの返却値になります。単位はメートルなので約14メートルということになります。

あとは、両方を組み合わせれば**「近づいてきたらslack通知」**ができます。

#距離が近づいたらslack通知してみる

```js:notification.js
//シリアルポートの設定
var serialport = require("serialport");
var nmea = require('nmea-0183');
var port = '/dev/ttyUSB0';
var baudrate = 4800;
var readline = '\r\n';
var https = require('https');

var receiver = new serialport(port, {
  baudrate: parseInt(baudrate),
  parser: serialport.parsers.readline(readline)
});

//Trackrr.io APIの設定
var options = {
    hostname: 'trackrr.io',
    port: 443,
    path: '/api/geoCalc/calc-distance-by-location',
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    }
};
//GPSの受信
var threshold = 5;
receiver.on('data', function(data) {
    var nmeaData;
        try{
                nmeaData = nmea.parse(data);
        }catch(e){
                return;
        }
    if (nmeaData['id'] == 'GPRMC') {
            receiver.pause();
            var postData = JSON.stringify({
              "destCoords": {
                "latitude": Number(nmeaData.latitude),
                "longitude": Number(nmeaData.longitude)
              },
              "startGpsKey": "3daaa2bb091ba1b325b4cfc1fd4e8c5f2f11e9e499608df969420389248a465feb6d43397ed4af7ab708"
            });
            var req = https.request(options, (res) => {
                    res.on('data', (body) => {
                    var data = JSON.parse(body);
                    console.log(data.value + ' メートル');
                    if(data.value <= threshold ){
                        alreadyPost = true;
                        var WebClient = require('@slack/client').WebClient;
                        var token = process.env.SLACK_API_TOKEN || '';
                        var web = new WebClient(token);

                        web.chat.postMessage('XXXXXXXXXX', threshold + 'メートル以内に接近しました',{},()=>{
                            try{
                                receiver.close();
                            }catch(e){}
                            });

                    }else{
                        receiver.resume();
                    }
                });
            });
            req.write(postData);
            req.end();
    }
});
```
APIの戻りを待つために`pause`と`resume`の制御を入れています。
で、実行結果は

```shell-session
pi@raspberrypi:~/trackrr.io-sdk-js-sample$ node notification.js
8.616847940533734 メートル
8.616847940533734 メートル
8.616847940533734 メートル
8.616847940533734 メートル
8.616847940533734 メートル
8.616847940533734 メートル
7.088631416607953 メートル
7.088631416607953 メートル
7.088631416607953 メートル
7.088631416607953 メートル
7.088631416607953 メートル
7.088631416607953 メートル
7.037313556063385 メートル
7.037313556063385 メートル
7.037313556063385 メートル
6.9891696750310555 メートル
6.9891696750310555 メートル
6.9891696750310555 メートル
6.943679953067919 メートル
6.724093703647338 メートル
6.901201531272668 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.50715297385343 メートル
10.111587767226975 メートル
10.111587767226975 メートル
11.93416830479277 メートル
11.93416830479277 メートル
11.413325129551174 メートル
11.413325129551174 メートル
10.895831331792595 メートル
10.895831331792595 メートル
2.4974182395343565 メートル
pi@raspberrypi:~/trackrr.io-sdk-js-sample$
```
![ScreenClip.png](https://qiita-image-store.s3.amazonaws.com/0/132516/54702445-8ac2-7546-587a-c302854cab4e.png)

来てますね～。
なかなか5メートル以内にならないので、ラズパイの横にスマフォを置いたら、いきなり2メートルになって通知が来ました。 :sweat_smile: 
とりあえず成功です。