やったのはこんなことです
SesameとLINEを連帯させて動かしたいと思っていた所に、女児が自宅で一人でいた所襲われたという痛ましい事件がありました。施錠されていなかったという情報もありましたが、同じ歳の娘がいる親としては他人事ではなかったので、以下のようなものを作りました。
実行環境
Rasberry Pi。
pi@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 9.4 (stretch)
Release: 9.4
Codename: stretch
LINEのMessaging APIを使える状態にする
以下のページの「1. Botアカウントを作成する」を参考に、LINEのBot環境を構築する
https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d
LINE Botの応答プログラムを動かす
以下のページの「2. Node.jsでBot開発」を参考に、LINE Botのプログラムを動かす。
https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d
LINEからアクセスできるようにする
以下のページの「3. ngrokでトンネリング」を参考に、ngrokでトンネリングする。
https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d
server.jsを使って、グループIDを取得する
投稿先を指定するために投稿先のグループIDが必要だが、取得の仕方が分からない。とりあえず、LINE Botのwebhookを使って取得する。
* すみません。このグループIDの取得はMacOS上で実行していました。
* 初めはトークのIDを取得を試みましたが、うまく行きませんでした。
ngrokを起動して、URLをコピー。
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Session Expires 7 hours, 32 minutes
Version 2.3.34
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://8f719f6c.ngrok.io -> http://localhost:3000
Forwarding https://8f719f6c.ngrok.io -> http://localhost:3000
Connections ttl opn rt1 rt5 p50 p90
3 0 0.00 0.00 1.86 5.03
HTTP Requests
-------------
LINEのwebhookに入力して「接続確認」を押すと、うまく行っていれば「成功しました」と表示される。
また、server.jsのログには接続確認のPOSTがきたことが表示される。
[ { replyToken: '00000000000000000000000000000000',
type: 'message',
timestamp: 1566021124737,
source:
{ type: 'user', userId: 'Udeadbeefdeadbeefdeadbeefdeadbeef' },
message: { id: '100001', type: 'text', text: 'Hello, world' } },
{ replyToken: 'ffffffffffffffffffffffffffffffff',
type: 'message',
timestamp: 1566021124737,
source:
{ type: 'user', userId: 'Udeadbeefdeadbeefdeadbeefdeadbeef' },
message:
{ id: '100002', type: 'sticker', packageId: '1', stickerId: '1' } } ]
疎通確認用
LINE Botに「テスト」とメッセージを送ってみる。すると、以下のようにPOSTされた情報が表示される。
[ { type: 'message',
replyToken: '658f1ac5c89b43a484534554f2419aba',
source:
{ userId: 'U019077dcf770eafc447f5f26xxxxxxxx', type: 'user' },
timestamp: 1566021143082,
message: { type: 'text', id: '10406822402420', text: 'テスト' } } ]
では、LINE Botをグループに追加してみる。すると、以下のようにPOSTされた情報が表示されて、グループIDが取得できる。
[ { type: 'join',
replyToken: 'b4062059659b470d8de8e465a5452059',
source:
{ groupId: 'C2b7154c5f92d0435e274d38exxxxxxxx', type: 'group' },
timestamp: 1566021198238 } ]
npmプロジェクトの作成と必要なモジュールのインストール
Node.jsのプロジェクトはpackage.jsonがあるディレクトリが起点となります。
まずはnpm initコマンドでpackage.jsonを作成します。
$ mkdir sesame
$ cd sesame
$ npm init -y
requestモジュールのインストール
$npm install request
Lineモジュールのインストール
$ npm i @line/bot-sdk express
プログラムの作成
postSesame.jsを以下をコピペして作成する。
"use strict";
var request = require('request');
// LINE
const Client = require('@line/bot-sdk').Client;
// LINE information
const config = {
channelSecret: '[[your LINE Channel Secret]]',
channelAccessToken: '[[your LINE Access Token]]'
};
const line_group_id = '[[your LINE group ID]]';
// LINE interface
const client = new Client(config);
// Sesame information
const token_sesame = '[[your Sesame Token]]';
var options_device = {
uri: 'https://api.candyhouse.co/public/sesames',
headers: {
'Authorization': token_sesame,
'Content-type': 'application/json',
},
json: true
};
// Variables
let device_id = "";
let locked_current;
let unlocked_count = 0;
// Configuration
let check_interval_sec = 15;
let auto_locked_sec = 5*60; // use your favorite value
// Get initial status of sesame
request.get(options_device, function(error, response, body){
device_id = body[0].device_id;
console.log(device_id);
getStatus(function(locked){
locked_current = locked;
console.log('first lock status: ' + locked);
});
});
// Get sesame status
function getStatus(callback) {
var options_status = {
uri: 'https://api.candyhouse.co/public/sesame/' + device_id,
headers: {
'Authorization': token_sesame,
'Content-type': 'application/json',
},
json: true
};
request.get(options_status, function(error, response, body){
if ( response ){
if (response.statusCode == 200) {
callback(body.locked);
}
}else{
console.log(error);
}
});
}
// Send command to Sesame
function sendCommand(command_param) {
var options_status = {
uri: 'https://api.candyhouse.co/public/sesame/' + device_id,
headers: {
'Authorization': token_sesame,
'Content-type': 'application/json',
},
json: {
'command': command_param
}
};
request.post(options_status, function(error, response, body){
if ( response ){
if (response.statusCode == 200) {
console.log(body.task_id);
}
}else{
console.log(error);
}
});
}
// Send message to Line
function sendMessage(message) {
//Send Line Message to Specific Group
client
.pushMessage(line_group_id, {
type: 'text',
text: message
})
.catch((err) => {
console.error(err);
});
}
// Main Loop
setInterval(function(){
getStatus(function(locked){
//console.log('current lock status: ' + locked);
if ( locked ){
unlocked_count = 0;
}else{
unlocked_count++;
}
if ( locked != locked_current ){
console.log('lock status changed.');
var message;
if ( locked ){
message = "玄関:鍵が閉まりました (^ ^)";
}else{
message = "玄関:鍵が開けれました (o o)";
}
sendMessage(message);
}
if ( unlocked_count>=auto_locked_sec/check_interval_sec ){
console.log('locked_count = '+unlocked_count);
sendMessage("玄関:鍵が"+unlocked_count*check_interval_sec/60+"分開いているので勝手に閉めます (' ')");
sendCommand("lock");
}
locked_current = locked;
});
}, check_interval_sec * 1000);
[[your LINE group ID]]は上で取得したLINEのグループIDをコピペする。
[[your Sesame Token]]は以下を参照してコピペする。
https://qiita.com/asakura_junji/items/baed089b52287dca3039
[[your LINE Channel Secret]]と[[your LINE Access Token]]は以下を参照してください。
LineのChannel Secretとアクセストークンの取得
以下からラインにログイン。
https://developers.line.biz/console/
プロバイダーの選択→チャンネルの選択→「チャンネルの基本設定」からChannel Secretをコピーし、プログラム中の[[your LINE Channel Secret]]にペーストする。
そのまま下の方に行き、メッセージ送受信設定をコピーし、プログラム中の[[your LINE Access Token]]にペーストする。
セサミをクラウドでの連帯をONにする
プログラム実行前にセサミのクラウドでの連帯をONにしないとerrorが帰ってくる
body: { error: 'CLOUD_INTEGRATION_NOT_ENABLED' } }
「管理」->「設定を変更」->「連帯」で「クラウド」をONにする
使用してみた感想
- 自動的に閉まる機能はデフォルトであることに途中で気付いた。
- LINEのフリープランを使っていたが、PUSHMESSGEがすぐに1000件/月に達してしまった。
- ドアの施錠(開閉)がLINEでリアルタイムで分かるのは安全上良い機能と感じた。