眠っているRaspberry pi 3をLINEのビーコンにしてみた
この記事はGMOペパボ Advent Calendar 2017の8日目の記事です
なぜつくったか
GMOペパボ Advent Calendar 2017の3日目の記事、「"Hello, World."の次としてのチャットボット」に触発されて、大急ぎでつくりました。家でRaspberry pi 3を眠らせておくのももったいなかったので、活用してみました。
どのようにして使える想定か
趣味で外回りの営業さん向けに、営業さんがLINE@にメッセージを送ると自動的にメールで本社宛に転送できるシステムを昔につくりました。実際に帰社したら、帰社をビーコンにより検知してイベント発火させて色々できることを想定してつくりました。(想定であり、実運用はしてません)
どうやってつくるか
準備編
前提知識
- LINE BOTで
Hello World
をリプライできる - Raspberry piがBluetoothを使える状態にできるぐらいの習熟度
用意するもの
- Raspberry pi 3
- LINEの入ったスマホ
- Messaging APIのアカウント
動作環境
- PHP5.6.32
- line-bot-sdk1.1
今回つくったLINEbotはline-bot-sdk
を導入しています。
LINE BOTを作成したことがない人は、こちらのページを見れば比較的に簡単につくれます。
作成編
まずは、Raspberry pi 3側の設定をします。
LINEの公式ブログで詳しい記事があるので、詳細はそちらを参照してください。
HWIDの発行
上記のサイトのLINE Simple BeaconのハードウェアIDの払い出し
> アカウント一覧
で連携したいアカウントを選択 > ハードウェアID発行
でHWIDの発行は完了です。
次にRaspberry pi 3側でコマンドを実行していきます。
まずはパッケージのインストールです。Linux向けのBluetoothのプロトコルスタックであるbluezおよび関連するパッケージをインストールします。
sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
パッケージがインストールできたら、実行します。
# 発行されたHWIDを2桁ごとにスペースで区切ったものを指定 # ここで気をつけるのが、英字がLINE@MANAGERでは小文字なので大文字にします HWID='01 0C 36 A2 95' ADVERTISE_DATA="13 02 01 06 03 03 6F FE 0B 16 6F FE 02 ${HWID} 7F 00" # Bluetooth HCIを有効にし、初期化します sudo hciconfig hci0 up # LE Controller Commands(OGF: 0x08), HCI_LE_Set_Advertising_Data(OCF: 0x0008) を実行し、 # 出力データを設定します sudo hcitool -i hci0 cmd 0x08 0x0008 ${ADVERTISE_DATA} # Non connectable undirected advertising(3)で、Bluetooth LEのアドバタイズを有効にします sudo hciconfig hci0 leadv 3
以上でRaspberry pi 3側の処理は完了です。次はwebhook先の処理です。
PHPでコードを書く
webhookとして設定しているサーバー側のエンドポイントに、ビーコンイベントをキャッチできるコードを書きます。これはビーコンイベント処理周辺部分のみを切り取ったものです。
<?php // SDKをrequire require __DIR__ . '/vendor/autoload.php'; // path to vendor/ $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN')); $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('CHANNEL_SECRET')]); $signature = $_SERVER["HTTP_" . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE]; $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature); //ユーザーからのメッセージ取得 $json_string = file_get_contents('php://input'); $json_object = json_decode($json_string); foreach ($events as $event) { // ビーコン処理 if (($event instanceof \LINE\LINEBot\Event\BeaconDetectionEvent)) { $type = $json_object->{"events"}[0]->{"beacon"}->{"type"}; if ($type === "enter") { $message = "お帰りなさい"; } elseif (($type === "leave")) { $message = "行ってらっしゃい"; } $body = <<<EOD {$message}!! EOD; replyTextMessage($bot, $event->getReplyToken(), $body); exit; } } function replyTextMessage($bot, $replyToken, $text) { $response = $bot->replyMessage($replyToken, new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($text)); if (!$response->isSucceeded()) { error_log('Failed!'. $response->getHTTPStatus . ' ' . $response->getRawBody()); } } ?>
ビーコン処理部分のみ解説していきます。
if (($event instanceof \LINE\LINEBot\Event\BeaconDetectionEvent)) {
line-bot-sdk
を利用して、LINEビーコンのイベントを簡単にハンドリングできるようになります。
$type = $json_object->{"events"}[0]->{"beacon"}->{"type"};
LINEビーコンイベントによりwebhookされて送られてくるjson形式は、このような形になっています。
{ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "beacon", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "beacon": { "hwid": "d41d8cd98f", "type": "enter" } }
詳細なドキュメントは、こちらを参照してください。
webhookされて送られてきたjsonオブジェクトの{"events"}[0]->{"beacon"}->{"type"}
を参照して、ビーコンのイベントにより文言を変更します。
if ($type === "enter") { $message = "お帰りなさい"; } elseif (($type === "leave")) { $message = "行ってらっしゃい"; }
テスト
早速ビーコンの範囲外に出てから範囲内に入ってみましょう。
赤丸の部分がleave
イベント(ビーコンの範囲外になる)とenter
イベント(ビーコンの範囲内になる)を拾っています。
ビーコンから離れると行ってらっしゃい!!
、ビーコンに近くとお帰りなさい!!
が返ってきました!うれしいですね!ここからさらにIFTTTなどを使えば様々な応用が効きそうです。
大変だったこと
テストです。ビーコンの有効範囲が10メートル近くあり、物理的に移動しないとビーコンが反応しないので、外出から帰宅時しかテストできないのが辛かったです。
またline-bot-sdk
の仕様のドキュメントが無さすぎて、手探りな感じも辛かったです。コードをみて使い方を覚えよみたいな感じでした。
それらの困難を乗り越えて動いたら楽しいですよ!!!家で余っているRaspberry piがあったらぜひ試してみてください。