SkyWayとenebularでLINEに通知する監視カメラを作るハンズオン資料になります。
この資料について
- 2/21ハンズオン実施後のアップデート版です。
- 3/23のv2ハンズオン実施後にもアップデートしました。
自己紹介
- 名前: のびすけ
- よく言われること: 「本名ですか?」
- 所属など
- dotstudio inc
- IoTLTという国内最大のIoTコミュニティの主催です。
- LINE API ExpertとかMicrosoft MVP (Node.js)を取得してます。
- デジタルハリウッド大学大学院の教員だったりもします。
- コメント: SkyWayとenebularを少しづつ使っていますが初心者の域を抜けてないです。
- つぶやき: 最近はmicro:bitでLINE Thingsがやれてテンションが上がりました
https://www.instagram.com/p/BvRuBsxDnrD/
今回作るもの
- 全体イメージ
おことわりとお願い
- 使ってるライブラリ(僕が作ってるのですが)が不安定な面があるのでご容赦下さい。
- 時間の都合上、個々のAPIの細かい話を触れることは出来ない可能性があります。 細かい技術説明よりも、全体を通してモノを作る体験にフォーカスしていきます。
- 技術的に深いところを知りたい方は別の会もあると思うのでそちらにも顔を出してみましょう。
- センサーを使う部分は配線などでトラブル可能性があるので一番最後にしています!その前までが大事
- 細かな部分は懇親会でお話しましょう。
- 助け合い精神で、早く進んでいる人は隣の人の様子も見てあげましょう。
準備物
-
デバイス側
- Raspberry Pi 3 B+ (Raspbian)
- Node.js v11.10.0
- npm v6.8.0
- gst-rpicamsrc
- skyway-webrtc-gateway v0.0.4
- 電子工作パーツ
- RasPi Camera
- 超音波センサ
- ブレットボード
- ジャンパワイヤー
- 抵抗
- LED
- 配線を先にやれる人はやっておいてもらいたい
- Raspberry Pi 3 B+ (Raspbian)
-
母艦PC側
- ブラウザ
- Google Chrome v72 (手元のバージョンを確認しましょう)
- Safari
- ブラウザ
事前にやってる内容(ハンズオン的にはスキップ)
今回のハンズオンではセットアップ済みのラズパイを利用しますが、本来のセットアップ手順はこちらです。
- aptで関連するソフトウェアのインストール
$ sudo apt update
$ sudo apt -y upgrade
$ sudo apt install -y autoconf automake libtool
$ sudo apt install -y gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
- gst-rpicamsrcのインストール
$ wget https://github.com/thaytan/gst-rpicamsrc/archive/master.zip
$ unzip master.zip
$ cd gst-rpicamsrc-master
$ ./autogen.sh --prefix=/usr --libdir=/usr/lib/arm-linux-gnueabihf/
$ make
$ sudo make install
- Node.jsのインストール (nodebrew経由です)
$ curl -L git.io/nodebrew | perl - setup
$ export PATH=$HOME/.nodebrew/current/bin:$PATH ( ~/.bashrcへの環境変数追加 )
$ nodebrew install-binary 11.12.0
$ nodebrew use v11.12.0
ハンズオンスタート
STEP1: enebularでWebアプリケーションを作成する
参考: LINE Messaging APIノードを利用します。
STEP1のポイント
- enebularを使うと処理を簡略化できる
- enebularを使うと他の人が書いた処理をフォークして実行できる
- SkyWayでは利用するドメインを指定してあげる必要がある
1. enebularでDiscoverまで
- ログイン後、
Create Project

- プロジェクト名を付けます。任意で大丈夫ですが、進行上「skyway-enebular-line」とsiteokimasu.

- メニューのDiscoverを選択します。

ついてこれなくなった人はこちら: enebularの紹介とユーザー登録
2. 既存のフローをimport(フォーク)します
- フォームに「skyway-enebular」と検索して出てくるフローを選択します。

-
import
しましょう

- プロジェクト名で
skyway-enebular-line
を選択して、ロールはsuperdev
を選択して進みます。

- インポート出来たらEditボタンを押して編集していきます。

3. URLを確認してみる
- 右上の
iマーク
をマウスオーバーしてURLを確認します。

- 別タブで、URLにアクセスしてみましょう。たぶん
API Key "undefined" is invalid.
などのアラートが出ます。

4. SkyWayのAPIキー取得とenebularのドメインを登録する
- SkyWayのコンソールからアプリケーションを作成します。
- SkyWayにenebularのデプロイ後URLを登録する必要があるので登録しましょう。
- この時生成されるAPIキーを覚えておきましょう。

STEP2. Raspberry PiでSkyWay WebRTC GateWayの利用
STEP2で抑えたいポイント
- SkyWay WebRTC GateWayを使うとRasPiの映像ストリーミングが簡単に出来る
1. ラズパイにログインするまで
$ ssh pi@raspberry
パスワード入力を求められるのでraspberry
と入力します。
2. ラズパイでNode.jsアプリケーション作成
ここからはSSH接続しているRasPi内のターミナルです。
- 準備
handsonフォルダを作成してその中にNode.jsのプロジェクトを作っていきます。
$ mkdir handson
$ cd handson
$ npm init -y
$ npm i skyway-gateway
補足ですが、
npm i skyway-gateway
をすると内部でskyway-webrtc-gatewayがDLされます。
※ skyway-gatewayという非公式パッケージです。
- プログラム記述
$ vim server.js
> ※ vim: ターミナル上で使えるエディタです。
vimの使い方が分からない人は周りのメンターに助けを求めましょう!!!僕もよくわかってません。
今回のハンズオンの最難関な気がしてます。
server.js
というファイルを作成します。これがRasPi側のメインプログラムです。
API KEYの箇所にSkyWayで取得したAPI Keyをコピペして保存します。
'use strict';
const SkyWay = require('skyway-gateway');
const options = {
apikey: `API KEY`,
peerid: process.argv[2],
camera: 'RASPI',
codec: 'H264'
}
const skyway = new SkyWay(options);
(async () => {
await skyway.startGateWay();
const peerData = await skyway.start();
console.log(peerData);
})();
skyway.dataListen((msg, rinfo) => {
const mes = msg.toString('ascii', 0, rinfo.size);
console.log(`data len: ${rinfo.size} data: ${mes}`);
});
vimの保存は
escキー
押して:wq
かShift+ZZ
です。
3. プログラムの実行
-
nodeコマンド
で実行していきます。
$ node server.js hoge
{ peer_id: 'hoge',
token: 'pt-ee0d470d-6a3c-4612-8a02-xxxxxxxxxx' }
OPEN
{ data_id: 'da-39156e92-6bbd-48d0-9bb5-xxxxxxxxx',
ip_v4: '192.168.8.7',
port: 50008 }
PeerId(※)がhoge
で起動します。
> ※ PeerID: 接続ごとのセッションIDみたいなもの
- トラブルシューティング
もし
create peer error!!!
などのエラーが出た人がいたらCtrl+Cで一度プロセスを削除してからもう一度起動して見て下さい。
もし
PEERを作成することが出来ませんでした。
と出た人は最後のhogeをhoge1などにしてみて下さい。
以下のエラーが出る場合がありますが取り急ぎ気にしないでください。(ライブラリ側の問題っぽいです)
--LONG POLLING ERROR---
- プロセスの停止
Ctrl+cで停止です。
4. enebular上でSkyWay対応のWebアプリが動くことを確認する。
- PCのブラウザで
URL
+/?apikey=xxxxx&peerid=xxxxxx
という形式でアクセスしなおしてみましょう。apikeyはSkyWayのAPI KEYです。(ここでThe domain~
というアラートが出る人はSkyWayの設定画面にenebularのURLが設定されているか再確認しましょう。)

- アクセス出来たらcallボタンを押しましょう。少し待つと映像が流れると思います。

PC画面で確認出来たら一旦休憩しましょうね。
余裕のある人はスマホでも確認してみましょう。
STEP3: enebularからLINE通知をしてみる
1. LINE Notifyのトークン取得
- LINE Notifyと友達になってね☆ ↓のQRです。

- https://notify-bot.line.me/my/ にアクセスしましょう。

- ページ下部の
トークンを発行する
-> トークン名:from enebular
->1:1でLINE Notifyから通知を受け取る
-> 発行する

- 発行されるトークンをコピーしておきましょう。

2. LINE Notifyのノードにトークンを貼り付け
ちなみにこの辺でenebular画面に戻ると画面が消えてる場合がありますが、仕様です。リロードしましょう。
- 緑色のNotifyノードをダブルクリックして設定フォームを開き、LINE Notifyのトークンを貼り付けて
完了
を押しましょう。

3. デプロイして試す。
- injectノードを追加して試して通知を試してみます。線で↓のように結んだら右上のボタンで
デプロイ
して下さい。

- 完了したらinjectノードの横のボタンを押すとLINEに通知されます。

4. 通知があったらLINEにURLを流すようにしてみる
- JSの方(下)のtemplateノードのプログラムを以下の2点、編集します。
- APIKEYの箇所にAPIKEYを入れ込んでください。
- peerIdの箇所にPeer IDを入れ込んでください。

- templateノード(上)を編集します(元々もへっろーって書いてた方です)

こんな感じのテキストを入れてみましょう。 /?~
などのパラメータは削除して大丈夫です。
人が来た模様です。
https://ev2-prod-node-red-xxxxxx.herokuapp.com
ちなみに、enebularからLINE NotifyにURLを送る際に
&
がエスケープされてしまう問題が生じてるので、パラメータ無しでも見れるような処置にしています。
- デプロイ -> injectボタンを押して確認しましょう。
LINEで通知が来るのでURLにアクセスしてスマホなどからチェックしてみましょう。
- POSTリクエストを送ってみる
ターミナルで別タブを開いて以下のコマンド(URLは自身のenebularのアドレス)で確認してみましょう。
curl -X POST https://ev2-prod-node-red-xxxxxxx.herokuapp.com/notify
Windowsの人は別ウィンドウでSSHでラズパイに入ってコマンド実行してみましょう。
STEP4: 距離センサを利用してみる
いよいよ配線して、距離センサの値を取得してみましょう。
電子工作感出る箇所ですね。
(TIPS) 利用センサを自分で買うときはご注意ください
今回利用する超音波センサのhc-sr04ですが、ロットによってはやばい奴があるらしいので気をつけましょう。
https://www.instagram.com/p/BskhqeVDGiy/
1. 配線 (慎重に......!)
- 一度、Rapberry Piをシャットダウンして電源を抜きましょう。
配線中にショートさせてしまうかもしれないので、一旦Raspberry Piの電源をOFFにします。
sudo shutdown now
- ↑のコマンドでシャットダウンしたらUSBケーブルも抜きましょう。
- まずは、写真のようにブレッドボードに超音波センサを外向きに差し込みます。
- 超音波センサは目玉みたいになっている箇所がブレッドボードに対して外側を向くようにしましょう。
-
超音波センサからは4つの足が生えていて、それぞれに名前が振られています。電池などと同様に+(VCC)から電気が流れて-(GND)に落ちる形になります。TrigとEchoは超音波の発信/受信です。発信して壁などにあったって跳ね返って来た信号を受信して距離を図っています。
- VCC: 電源(+)
- Trig: 超音波発信
- Echo: 超音波受信
- GND: グラウンド(-)
-
Raspberry Piのピンマップの参考です。対応した箇所にジャンパワイヤーで配線してきます。
引用元: https://www.elektronik-kompendium.de/sites/raspberry-pi/1907101.htm
- このような形で配線します。Raspberry Piのピンは何番ピンかがわかりにくいのでこんな覚え方でも良いかも
- VCC: 右上
- GND: 左下
- Trig(GPIO21): 右下
- Echo(GPIO20): Trigの一個上

こんなイメージです。
#webrtcskyway #enebular pic.twitter.com/VMuEIqNQtM
— のびすけ / sugawara (@n0bisuke) 2019年3月23日
今回のハンズオンでは使ってないですが、配線知識不要のGrove対応の超音波センサもあるのでこっちを購入するのもアリだと思います。
参考: Raspberry Pi 3 で超音波距離センサを使ってみる
-
(要注意)配線が完了したら、電源を付ける前に講師やメンターにチェックしてもらいましょう。
- 間違って配線してセンサーが焼けてしまったりすると危ないです。
2. とりあえずセンシングしてみよう
- 先ほどのhandsonフォルダに移動
cd handson
- 利用モジュールの追加
pigpioとjohnny-fiveで制御します。
npm i johnny-five pi-io axios
(ここでエラーでないといいなぁ)
修正時刻 10659412 は未来の時刻です
みたいなエラー出る人は↓
- エラーが出た場合は時刻設定をしてから再インストールします。以下を実行してみてください。
$ sudo date --set='2019/03/23 15:51:20'
$ rm -rf node_modules package-lock.json
$ npm i
- 最難関、vimでapp.jsを作成
vim app.js
'use strict';
const five = require('johnny-five');
const PiIO = require('pi-io');
const board = new five.Board({io: new PiIO()});
board.on('ready', function() {
const proximity = new five.Proximity({
controller: PiIO.HCSR04, // Custom controller
triggerPin: 'GPIO21',
echoPin: 'GPIO20'
});
proximity.on("change", function() {
console.log("cm: ", this.cm);
});
});
- 実行
GPIOにアクセスする際にsudo権限で実行しないといけないため、以下のコマンドでNode.jsを実行しましょう。
$ sudo /home/pi/.nodebrew/current/bin/node app.js
動くとこんな感じです。

おまけ、 LED連携
- GPIO16(右下の二つ上=Echoの一個上)にLEDを接続した例です。
- 配線的にはLEDの足の短い方をGNDに、足の長い方をGPIO16に接続します。

'use strict';
const five = require('johnny-five');
const PiIO = require('pi-io');
const board = new five.Board({io: new PiIO()});
board.on('ready', function() {
const proximity = new five.Proximity({
controller: PiIO.HCSR04, // Custom controller
triggerPin: 'GPIO21',
echoPin: 'GPIO20'
});
const led = new five.Led('GPIO16');
proximity.on("data", function() {
console.log("cm: ", this.cm);
if(this.cm >= 1 && this.cm <= 7){
led.on();
console.log("!!!");
}else{
led.off();
console.log("---");
}
});
// proximity.on("change", function() {
// console.log("cm: ", this.cm);
// });
});
3. 検知したらHTTP POSTでenebularに投げる
'use strict';
const five = require('johnny-five');
const PiIO = require('pi-io');
const axios = require('axios');
const ENEBULER_URL = 'https://enebularのドメイン/notify';
const board = new five.Board({io: new PiIO()});
board.on('ready', function() {
const proximity = new five.Proximity({
controller: PiIO.HCSR04,
triggerPin: 'GPIO21',
echoPin: 'GPIO20'
});
proximity.on("change", function() {
console.log("cm: ", this.cm);
if(this.cm >= 1 && this.cm <= 7){
console.log("検知したよん");
axios.post(ENEBULER_URL, {})
.then(response => console.log(response))
.catch(error => console.log(error));
}else{
console.log("---");
}
});
});
- 実行して試してみましょう!
STEP5: プロセスを永続化してみる
永続化ツールのpm2で永続化してみます。
1. インストール
$ npm i -g pm2
2. package.jsonを編集
- カメラ映像を配信するプロセス(server.js)を永続化準備
通常だとpm2 start server.js
でOKなのですが、今回のように引数がある場合は少し別のやり方をします。
vimでpackage.jsonを編集します。
$ vim package.json
scriptsの箇所にcamera
を追記し、先ほどの実行コマンドを記載します。
"scripts": {
"camera": "node server.js hoge",
"test": "echo \"Error: no test specified\" && exit 1"
}
- 超音波センサのプロセス(app.js)を永続化準備
scriptsの箇所にsensor
を追記し、先ほどの実行コマンドを記載します。
"scripts": {
"camera": "node server.js hoge",
"sensor": "sudo /home/pi/.nodebrew/current/bin/node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
3. pm2コマンドを実行
以下でcameraのスクリプトの永続化が出来ます。
$ pm2 start npm --name "camera" -- run camera
$ pm2 start npm --name "sensor" -- run sensor
- 確認
以下のコマンドで確認ができます。
$ pm2 list
$ pm2 logs
永続化ができたら、ラズパイのターミナルからログアウトしてもちゃんとした挙動になってるか確認してみましょう。
- pm2起動した場合の再起動方法 / 更新方法
pm2 restart <プロセス名>
で再起動できます。ファイルを編集して変更を適用させたい場合などに使います。
pm2 restart sensor
- エラーが出る場合
pm2はNode.jsのプログラムがエラーを起こして落ちても自動的に再起動させてくれます。そのおかげでちょっとしたクラッシュが起きても勝手に再起動してくれるのですが、致命的なエラーがあって起動してすぐにエラーで落ちるようなプログラムになってしまうと永遠と再起動を繰り返してしまってCPU利用率がすごいことになってしまいます。こういった場合はプロセスを削除しましょう。
pm2 delete <プロセス名>
でプロセスを削除できます。
pm2 delete sensor
早く終わった人演習
時間があまったらチャレンジしましょう。
演習1: 通知が来まくってしまう問題をenebularを使って解消してみましょう。
クラウド側での調整です。
演習1: 解答例
-
delayノード
を使う
-
delayノード
の動作をメッセージの流量制限
にして、xx秒に1回メッセージを流すようにする
-
http inノード([post] /notify)
とtemplateノード
の間にdelayノード
を入れる
演習2: 通知が来まくってしまう問題をapp.jsを編集して解消してみましょう。
エッジ(デバイス)側での調整です。
演習2: 解答例
- flag変数を作って、flagの基本はfalseにしておく
- flagがfalseの時だけ反応するようにする
- 反応があったらflagをtrueにする
- xx秒後だったりxx分後にflagをfalseに戻す
'use strict';
const five = require('johnny-five');
const PiIO = require('pi-io');
const axios = require('axios');
const ENEBULER_URL = 'https://enebularのドメイン/notify';
const board = new five.Board({io: new PiIO()});
let flag = false;
board.on('ready', function() {
const proximity = new five.Proximity({
controller: PiIO.HCSR04,
triggerPin: 'GPIO21',
echoPin: 'GPIO20'
});
proximity.on("change", function() {
console.log("cm: ", this.cm);
if(this.cm >= 1 && this.cm <= 7 && flag === false){
console.log("検知したよん");
flag = true;
axios.post(ENEBULER_URL, {})
.then(response => console.log(response))
.catch(error => console.log(error));
setTimeout(() => {
flag = false;
},1000 * 10); //10秒たったらflagを元に戻す
}else{
console.log("---");
}
});
});
まとめ
(たぶんバタバタでしたが)お疲れ様でした!
最初に少し話をした全体図はイメージできたでしょうか。
こんな感じで、SkyWay WebRTC Gatewayとenebularを使うことでデバイスのセンサデータとカメラデータをLINE側で通知させることができました。そこまで深い知識が無くても 作る体験をするといったことが出来たと思います。
SkyWayやenebularを今後も活用して見て下さい。