myThings + milkcocoaで高齢者見守りデバイスを作ってみた

本記事は
myThings Advent Calendar 2015(http://qiita.com/advent-calendar/2015/mythings)
と
Milkcocoa Advent Calendar 2015(http://qiita.com/advent-calendar/2015/mlkcca)
の10日目の記事です。

今回は**一人暮らしの祖母の安否をゆるく確認できるデバイスを作った**ことの記録を書きます。
初のAdvent Calendarですので、不足がありましたら是非コメントでお知らせいただければと存じます。

***

#背景・抱えていた問題
僕の**祖母は遠くで一人暮らし**をしています。
高齢の一人暮らしなので両親は心配しており、祖母に近くに引っ越してくるように・もしくは同居するように提案したものの、**引っ越すことは嫌**だということで、何か出来ることはないかと悩んでいました。

##解決案
そこで、ゆるくでも良いので安否確認ができたら両親が少しは安心するかもと考え、**何かしらの動きを検知して、毎日決まった時間に通知をするもの**を作ることにしました。

##何を作るか
動きの検知という意味では[ポットの使用状況から安否を確認できるという商品](http://www.mimamori.net/)もありますが、僕の祖母が**毎日ポットを使っているかがわからない**。
そこで、まずは**「誰でも・毎日使っている」トイレの扉の開閉**のログを取ります。
そして、毎日朝8時・夜8時の時点で安否（動きがあったかどうか）の通知をしてくれるようにします。

#技術的課題
さて、作るものは決まりましたが技術的な課題が色々とあります。

課題その1 : 通信環境をどうするか
課題その2 : サーバーをどうするか
課題その3 : 通知をどうするか

###課題その1.通信環境をどうするか
祖母の家には電気はかろうじて通っているものの、インターネットなんていう現代的なものは当然ありません。
しかし、新しくインターネットの契約をするというのは今回の利用目的を考えるとコスパが悪い。

そこで、**[simフリーのポケットWiFi](http://amzn.to/1Q0Wth8)**を購入し、ヨドバシで契約した**月額500円・低速・無制限のsim**を入れて使うことにしました。（なんとか通信できました。）
![simcard.jpg](https://lh3.googleusercontent.com/936TI9Wb3jy5wdhJswSGmW3GUHJ2df04gn2I--2cEfkbBWjfGxMy3NcN5vbuwRjPdeD7b6-15_NBO0R2QMTq0-XDF8tAyBG8fUEn9zLcZGj2Vs9D7MzJTV3C_NUZ_HBwoG50Q_XzrISJzrOUdbDPpt0JjhAEfoR9zSFyknTdReyFNHgmrDbfIUaJ3j8v-zPtO2u78hivGKMCW_vo8hT6DV-P0lQTh8wqj0diAoLDPwyO3pFQnwmTOcl9MrcOoeoPo78GGDe2MuqyGvvWzehUu16fOR5Uufm8lbqrPVtXJLB9lEkKJKcvAgt3EgzhKym5-xI3W2tvGPslyNIsS6irf72iZ0DdY-K-0z2CY0AJ5NJeWUUpWk7rbCdKd9SXvQsJZSaNiTMstWk-QVZDMLIe3mwZdMAlmhRZJmzBfv6SpbDg6jqWhR_zxWuShoBpYZGyGc7OWp-CjZQlfDT-yeHTiflOgbIfEmNXNiBz6hFsVDudkOJWt9F7x04GAR2m37Kp9cw1biqlRWFfPaLWlI1iSltfLpTTCfbSYq7lNgWgueM=w1024-h768-no)


###課題その2.サーバーをどうするか
データを受け入れたり取り出したりという**サーバー側のプログラムを書くのは意外と面倒**です。

そこで、今回は
>自前でサーバを準備せずに、クライアントSDKを介してデータの保存、更新、取得またPub/Sub通信を行うことが出来る

という[milkcocoa](https://mlkcca.com/)を使いたいと思います。
###課題その３.スマホへの通知をどうするか
アプリの知識は0なので、**スマホへのプッシュ通知のさせ方がわかりません**。ということで、[myThings](http://mythings.yahoo.co.jp/)を使います。

#改めて作るもの
だいたいこんな流れです。
![gaiyou.jpg](https://lh3.googleusercontent.com/lgiAsQBa8kCn56l1BGJblaXoL2xujOZxg9zQD_gHfIUlUmW-3lcizV57NOYdZbBRhjdLrDEiNKv3eUGedheelWeg2arrsxM7Rg9HU1MzWlMItaWLh8pUm0Her1v0tKkcr0YVqz7pBvAQex01cOSDL47ljmct_fC91pxMY6nTuI_KpuwJ_kvg9NvQpkZo0dfvBpfxumKAcHoReUD8Zg7TN1Dr2e918kO9TXVrQKyLP11pJ5V44VKA7sww_ok1Lt_nFJFwnNZAw22uchhrXnSQmGSIDFaOxgmpduR3i6XNHlDi9SsdsY0Y4bkFEPXioGpcFkbstDo2jybvjetRqfTXBr9fxVmSfAl00abl0GykddoD2O1BBR1j0y8vFPzklMArDyeBOSEmfDI6WggHR0xAQTEKIpQ8IbekZoVBn58ksgT7qqWL3lIh7hwBZ8UQ90TDT9RsK-bI0iu0Xsj28_0hL242-Kd2Np-lq4JIhRthg7K2txyEDmk3qCFFPhvO_IAyoxRG960eKNQw3MHcAIVBdawS3tQg-TsgOTM4gzbcp4g=w957-h657-no)

#実際の製作の流れ
さて、前置きが長くなりましたが、製作の流れの説明に入ります。
ざっくりとした流れはこんな感じです。

1. raspberry_piのセットアップとmilkcocoaに登録
2. IDCFクラウドに契約とmyThingsセットアップ
3. 扉の開閉データをmilkcocoaに送信
4. 開閉データの有無を確認して、mythingsに通知するようデータをセット
5. myThingsでプッシュ通知を受ける

では、一つずつ見ていきます
##1.raspberry_piのセットアップとmilkcocoaの登録
この辺りはこちらの記事を参考にしました。
http://blog.mlkcca.com/iot/realtime-data-visualization-with-raspberry-pi-1/

##2.IDCFクラウドに契約とmyThingsセットアップ
IDCFクラウド契約・myThingsのセットアップはこちらの記事を参考にしました。
[myThingsを始めよう](http://www.idcf.jp/cloud/iot/detail01.html)

##3.扉の開閉をmilkcocoaに送信
さて、ここまでのステップで環境ができたので、プログラムを書いていきます。

今回は扉の開閉を監視するので、リードスイッチ（磁石の接近でon/offが切り替わるスイッチ）を使います。

[こちらの記事](http://engineer.recruit-lifestyle.co.jp/techblog/2015-08-21-node6/)の**スイッチ入力を受け付ける**という箇所のサンプルを書き換えて、**milkcocoaにデータを送信する仕組みを追加**しました。

このプログラムはバックグラウンドで実行し続けます。
>$ sudo node door_check.js &

```js:door_check.js
var fs = require('fs');

var MilkCocoa = require('milkcocoa');
var milkcocoa = new MilkCocoa('*******.mlkcca.com');
var ds = milkcocoa.dataStore('door');

fs.writeFileSync('/sys/class/gpio/export', 21);
fs.writeFileSync('/sys/class/gpio/gpio21/direction', 'in');

var pre_value = 1;
loop();
function loop() {
    var value = parseInt(fs.readFileSync('/sys/class/gpio/gpio21/value', 'ascii'));
    if ( value != pre_value  ) {
        console.log(value);
        ds.push({DoorOpenFlag:value});
        pre_value = value;
    }
     setTimeout(loop, 1000/10);
}
```
###動作中の動画
以前pythonで書いたバージョンなので、微妙に挙動が違いますが大体こんな感じです。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/LKlMrWo4tVU/0.jpg)](http://www.youtube.com/watch?v=LKlMrWo4tVU)

##4. 開閉データの有無を確認して、mythingsに通知するようデータをセット
下記のプログラムを朝の8時と夜の8時にcronで回します。

```js:cronfile.js
var MilkCocoa = require('milkcocoa');
var milkcocoa = new MilkCocoa('********.mlkcca.com');
var history = milkcocoa.dataStore('door').history();
var execSync = require('child_process').execSync;


var myD = new Date();

var myYear = myD.getFullYear();
var myMonth = myD.getMonth();
var myDate = myD.getDate();
var yesterday = beforeDay(myYear,myMonth,myDate);

if(myD.getHours() >= 19){
	var myYear_start = myYear_end = myYear;
	var myMonth_start= myMonth_end = myMonth;
	var myDate_start = myMonth_end = myDate;
	var myHour_start = 8;
	var myHour_end = 20;
}else{
	var myYear_start = yesterday['year'];
	var myMonth_start= yesterday['month'];
	var myDate_start = yesterday['date'];
	var myYear_end = myYear;
	var myMonth_end = myMonth;
	var myDate_end = myDate;
	var myHour_start = 20;
	var myHour_end = 8;
}

history.sort('desc');
history.size(1);
history.limit(1);
history.span(new Date(myYear_start,myMonth_start,myDate_start,myHour_start,0,0).getTime(), new Date(myYear_end,myMonth_end,myDate_end,myHour_end,0,0).getTime());
history.on('data', function(data) {
	if (data) {
		console.log('data_exists');
		execSync('curl -X POST "https://***.***.***.***/data/UUID" --insecure --header "meshblu_auth_uuid: UUID" --header "meshblu_auth_token: TOKEN"');
		process.exit();
	}else{
		console.log('data_nothing');
		execSync('curl -X POST "https://***.***.***.***/data/UUID" --insecure --header "meshblu_auth_uuid: UUID" --header "meshblu_auth_token: TOKEN"');
		process.exit();
	}
});
history.run();


function beforeDay(year, month, date) {
    var d = new Date(year, month, date);
    d.setDate(d.getDate() - 1);
    return {
        year: d.getFullYear(),
        month: d.getMonth(),
        date: d.getDate()
    };
}
```

内容としては
実行された時間が朝の8時であれば「前日の20時から当日の8時までのデータ」を、実行された時間が20時であれば「当日の8時から20時までのデータ」を確認しに行きます。

データが入っていたらmyThingsのトリガー1にデータを送信。
データが入っていなければトリガー2にデータを送信。

という感じです。

##5. myThingsでプッシュ通知を受ける
myThingsで下記のように設定をしました。
###トリガー1の時は無事であることの通知
![triger1.jpg](https://lh3.googleusercontent.com/222e1KsCE9A_pDOmgK9zcHd3FoXxolQHG3F-zWFKBFLsu5txWxM4ub94RtGCbEYvhFB5ldso_WjSFcVMQcPnOaj42x_y8QYYu4YJ_AamffiHNhLVe2ZLJNzzV6Lvr6YW0XbLPhm2aUbXuaJJdjyL7F6eek9xVGV5R814c33JEt1qbDdDn7hAppWaBkh4mxIiCdSG-x4dJCfWzvCEfXEG_mqj37rjQ3y9hTFGT5oIxgfa5mDNeJBoW0AeX6pvtV16OEbPI8jT6QufpnRLttGqHOPdUGSyODQWNymy0KyqBuq2DzssQmfA45mKj_au098npUWlaIEFQ3b2tcFG6uYhJHydCaj8HwppPzlOz_7uSUrvvEC1tAw1G83EgNPdyet97I6wCjBuQFZ2Fv8kyIgEaNN6FkOdLbTo2pK6SLvTJJZhF72ZoSBXFBMTjr6Z3xDk86J_jJ1xiJXR2edWHUIquVaRZCw1lhSYHsr-OLED7VRH6ORM6Eyog9l14vRw--PjV0VGdDZQoPn6QLpvkIn1mboijUIv93q3Fa9zwjDMATg7aZUC5UUYIPMZFwYoLB6ZVVwL=w820-h1456-no)

###トリガー2の時はデータが無いことの通知
![triger2.jpg](https://lh3.googleusercontent.com/tn2lJK3v41llJEMTKgkQTzOn0fDBzo-TjGZ7y4mDecP9oGwcNg3nRCvhRGrfO1-icLRyVwj5u20P_Od5hfIfEMDHxn64wXgaOkGbknjF_4DTg2Sy1g4pTSRpRAYMJGrsgH9COYA3plzKSH6nwftpnP3gANIkYogZPMd9t6aQzMJ7Y6sSRyH1Zd5smr58ToPLjXcSGujXWLihV5MIY3XvvQ1AOC6V19xRAW0P7TH8YckoDiO2U4iO1sDQtMj6IhQ7jKYL7_LgZLSaQEI7-k5DUrzpuEVfYrGBpE0ndifUYG0ARbCWQ8Fra2U_QDRbidsrgGeKz6SF0yufRrPWiToZbTjhGp-ZLDYg9WsfDZXSU-d_BqCwh4gTqtaDZ5ii_97yOmsuIMgJRVHO2PiaMsQiHqt4FxTvjD_rcAhGMLNZDbumtnYixhry8pP8VXIszCKXvXAs9kAsXL8R35n-7mPG_BWhz-9mmwiFypSrPkJysZoDD0jP0ajE9VW1lKJgIJ-ffCZbwtUwhCPGjDiuuS1P8thD0W7mGvjmOHZuJOTFRj0ATpMXJaL7lbIT6zjHCFSZIBhd=w820-h1456-no)

#使ってみた・感想
ソースの書き方や仕組みについて怪しい部分は多々あるものの、なんとか動作しました。
便利かどうかで言うと、まだ微妙です。
朝の通知に関しては**祖母が起きているかどうかがわかるのは便利**ですが、昼〜夕方に関しては**夜にならないと安否がわからない**ので改善が必要だと感じています。

#今後
認知症になった時を考え、扉のセンサーだけでなく人感センサーなどを追加して部屋の中にいるかどうかも確認できるようにしようと考えています。
また、データを通知だけではなく、Web上から見れるようにします。

[github](https://github.com/takuya-andou/door_checker_node)上で更新していますので、もしよければご覧ください。

それでは、長文を読んでいただきありがとうございました。