最近のHDDレコーダーには、メーカーが用意したクラウドサービスを使って外出先から予約ができるものも多いですが、少し前の機種ではそうもいきません。私は東芝のRD-BZ810という機種を使っています。メールを使った外出先からの予約録画の機能はありますが、使い勝手が悪く使っていません。
この機種は、
- マジックパケットによるWake-on-LANが可能
- ウェブブラウザからの予約録画可能
という特長があります。ということは、HDDレコーダーの80番ポートをポート開放することができれば、先日の記事「自宅のPCを外出先からボタン一つで起動」がそのまま使えます。しかし、私の場合、すでに80番ポートは別の用途に使ってしまっていますのでこの方法が使えません。HDDレコーダーのhttpサーバーのポート番号の変更も多分できません。
そこで、Raspberry Piを、外出先からHDDレコーダーのhttpサーバーへの中継にも使おうと考えました。具体的にはリバースプロキシサーバーの機能を持たせて、外出先から自宅のグローバルIPの9005番へのアクセスをRaspbery Piで受けて、Raspberry PiからHDDレコーダーの80番ポートへ転送するようにします。
Wake-on-LANのきっかけには、先日の記事と同様にスマートフォンのボタンを使います。
- スマートフォンのボタンを押す
- ConnectからのWebHookをRasbperry Piで受ける
- Rasbperry PiからHDDレコーダーにWake-on-LANのマジックパケットを送信
- Rasbeprry PiからConnectにWebHookでURLを送信する
- ConnectからスマートフォンにURLを通知
- スマートフォンで通知をタップするとブラウザが起動して、自宅のHDDレコーダーに接続される。
という流れです。2〜5はConnectのシナリオとRasbpery Piのプログラムが協調して自動で動くので、意識して操作するのは1と6だけです。
前提知識
この記事では、下記の説明は省略します。
HDDレコーダーがオフの状態で、テストしてみましょう。下記のeth0はRasbperry Piが有線LANに接続されている場合の例です。無線LANの場合はwlan0に変更してください。また、XX:XX:XX:XX:XX:XXはHDDレコーダーのMACアドレスに書き換えてください。
Connectのアカウント登録がまだであれば、Connectアプリからアカウント登録が可能です。アカウント登録を済ませて、ログインしましょう。
- 自宅ネットワークの固定グローバルIPまたはダイナミックDNS設定手順
- 自宅ネットワークのポート開放手順
- HDDレコーダーに自宅LAN内の固定IPアドレスを設定する手順
用意するもの
- HDDレコーダー
- Wake-on-LANの機能を持つこと
- ブラウザから録画予約可能なこと
- Raspberry Pi
- SDカードにraspbianインストール済み
- 有線LANまたは無線LAN
- ネットワーク環境
- インターネットに常時接続
- グローバルアドレスで接続されていること
- 固定グローバルIPまたはダイナミックDNSが使えること
- スマートフォン
- iOS 9.3以降のiPhone
作業1 HDDレコーダーに固定IPアドレスを設定
ルーターの設定でDHCPで固定IPを払い出すように設定する方法と、HDDレコーダーの設定で、DHCPではなく固定IPを使うようにする方法があります。詳細は省略します。
作業2 Raspberry Piにetherwakeをセットアップ
etherwakeをインストールして、一般ユーザーからもWake-on-LANのマジックパケットを送信できるようにします。
- sudo apt-get install -y etherwake
- sudo chmod +s /usr/sbin/etherwake
- etherwake -i eth0 -b -D XX:XX:XX:XX:XX:XX
コマンド実行してHDDレコーダーが起動すればOKです。
作業3 Raspberry Piのプログラムを用意
まずは最新の安定版nodejsをセットアップしましょう。
- sudo apt-get install -y nodejs npm
- sudo npm cache clean
- sudo npm install n -g
- sudo n stable
- node --version
- sudo apt-get install -y uuid-runtime
- mkdir webhook_etherwake_recorder
- cd webhook_etherwake_recorder/
- npm install express
- npm install body-parser
- npm install http-proxy
下記の内容をwebhook_etherwake_recorder.jsというファイル名で保存します。このプログラムはConnectからのWebHookの受信、HDDレコーダーへのマジックパケットの送信、ConnectへのWebHookの送信、インターネットからHDDレコーダーへのhttpの転送(リバースプロキシサーバー)の機能をまとめたものです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// parameters to be modified | |
var TOKEN='XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'; // Your own secret token | |
var MACADDR='XX:XX:XX:XX:XX:XX'; // MAC address of your recorder | |
var IP='192.168.0.1'; // local IP address of your recorder | |
var PUBLIC_HOST='xxx.ddns.net'; // Your public domain name | |
var POST_URL='https://connect.codyltech.com/connectors/webhook/push/XXXXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXX'; | |
var PORT=9004; // PORT for webhook | |
var PORT_PROXY=9005; // PORT for proxy | |
var DEBUG=true; // set true for console.log | |
// | |
var command='/usr/sbin/etherwake -i eth0 -b -D ' + MACADDR; | |
var express = require('express'); | |
var bodyParser = require('body-parser'); | |
var exec = require('child_process').exec; | |
var app = express(); | |
app.set('port', process.env.PORT || PORT); | |
app.use(bodyParser.json()); | |
app.post('/wake', function (req, res) { | |
var wake_event = req.body; | |
DEBUG && console.log('incoming event:' + JSON.stringify(wake_event)); | |
if (!wake_event.token || | |
wake_event.token != TOKEN) { | |
DEBUG && console.log('invalid token'); | |
res.send('invalid token'); | |
return; | |
} | |
var child = exec(command,function(error, stdout, stderr){ | |
DEBUG && console.log('exec command:' + command); | |
DEBUG && console.log(stdout); | |
res.send('OK'); | |
wait_wakeup(function() { | |
post_webhook(); | |
}); | |
}); | |
}); | |
var server = app.listen(app.get('port'), function() { | |
DEBUG && console.log('Listening on port %d', server.address().port); | |
}); | |
// reverse proxy | |
var httpProxy = require('http-proxy'); | |
httpProxy.createServer({target: "http://" + IP + "/"}) | |
.listen(PORT_PROXY) | |
.on('error', function(err, req, res) { | |
res.writeHead(500, { | |
'Content-Type': 'text/plain' | |
}); | |
res.end("Proxy error"); | |
}) | |
// wait wakeup recorder | |
function wait_wakeup (done) { | |
// just wait 10 sec | |
setTimeout(function() { | |
DEBUG && console.log("wait_wakeup done"); | |
done(); | |
}, 10000); | |
} | |
function post_webhook () { | |
const https = require('https'); | |
const url = require('url'); | |
var urlobj = url.parse(POST_URL); | |
var postData = { | |
"url": "http://" + PUBLIC_HOST + ":" + PORT_PROXY, | |
}; | |
var postDataStr = JSON.stringify(postData); | |
var options = { | |
host: urlobj.host, | |
path: urlobj.path, | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
} | |
}; | |
var req = https.request(options, (res) => { | |
}); | |
req.write(postDataStr); | |
req.end(); | |
} |
プログラムの先頭のTOKEN、MACADDR、IP、PUBLIC_HOST、POST_URLは書き換えます。TOKENはuuidgenコマンドで生成したランダムなUUIDを使うのが良いでしょう。これが漏洩すると、誰でもあなたのHDDレコーダーを起動できるようになります(大した実害はないかもしれませんが)。MACADDRとIPは、それぞれHDDレコーダーのMACアドレスとIPアドレスに書き換えます。PUBLIC_HOSTは固定グローバルIPまたはダイナミックDNSのホスト名(FQDN)に書き換えます。POST_URLは後で書き換えます。
作業4 ポート開放
Raspberry Piのポート9004, 9005をインターネットからアクセスできるようにポート開放します。
作業5 Connectアプリをインストール
スマートフォンにCodyl Connectアプリがインストールされていなければ、インストールします。AppStoreでcodylで検索するか、下記のリンクから開いてください。
Connectのアカウント登録がまだであれば、Connectアプリからアカウント登録が可能です。アカウント登録を済ませて、ログインしましょう。
作業6 シナリオ作成
ブラウザからCodyl Connectにログインしてシナリオを作成します。
これでシナリオの設定は完了です。
- (1)シナリオタブから「新規シナリオ作成」をクリック
- (2)わかりやすいシナリオ名に変更
- (3)説明を書く
- (4)再実行頻度を0分に変更
- (5)「イベントウォーク新規作成」をクリック
- (6)mainの箱の下のプラス記号をクリックしてステートを追加
- (7)追加されたステート(state2)をクリック
- (8)「ステートにコネクターを追加」をクリック
- (9)新しいコネクターを作成を選んで、「ボタン」を選択
- (10)4つのボタンのうち好きなものを選択
- (11)「作成」をクリック
- (12)メソッドに「TRIGGER: when pushed」を選択
- (13)textの値に「HDDレコーダー起動」と記述。この文字列がスマートフォンのボタンに表示されます。一番下の「閉じる」をクリック
- (14)state2の下のプラス記号をクリックしてステートを追加、追加されたステート(state5)をクリック。
- (15)「ステートにコネクターを追加」をクリック
- (16)新しいコネクターを作成を選んで、「WebHook」を選択
- (17)わかりやすい名前を入力(例:「WebHook(HDDレコーダー起動)」)
- (18)外部サービスのURLに、「http://自宅のアドレス:9004/wake」と入力。自宅のアドレスには固定IPの場合はIPアドレス、ダイナミックDNSの場合はDNSホスト名を入れます。
- (19)「作成」をクリック
- (20)メソッドに「ACTION: post message」を選択
- (21)tokenの値にRaspberry Piで設定したTOKENを入力。一番下の「閉じる」をクリック。
- (22)state5の下のプラス記号をクリックしてステートを追加、追加されたステート(state8)をクリック。
- (23)「ステートにコネクターを追加」をクリック
- (24)コネクター一覧から「WebHook(HDDレコーダー起動)」を選択
- (25)メソッドに「TRIGGER: when received」を選択
- (26)message_TTLの値に1を入力。一番下の「閉じる」をクリック。
- (27)state8の下のプラス記号をクリックしてステートを追加、追加されたステート(state11)をクリック。
- (28)「ステートにコネクターを追加」をクリック
- (29)コネクター一覧から「プッシュ通知」を選択。まだ作成していなければ、新しいコネクターを作成を選んで、「プッシュ通知」を選択して作成。
- (30)メソッドに「ACTION: push message」を選択
- (31)messageに、「HDDレコーダーを起動しました。{{label_10.url}}」を入力。一番下の「閉じる」をクリック。
- (32)上部のリストからシナリオ名をクリックしてシナリオプロパティ画面に戻る
- (33)スケジュール設定を有効にする
これでシナリオの設定は完了です。
作業7 Raspberry Piのプログラムを完成させる
webhook_etherwake_recorder.jsの変更部分のうち、作業3で後回しにしていた、POST_URLを書き換えます。コネクタータブから「WebHook(HDDレッコーダー起動)」を選択したときに表示される「外部サービス→Connect」のWebHook URLをコピーして、POST_URLの値としてください。
準備ができたら早速起動してみましょう。下記のコマンドで起動したらListening on port 9004と表示されます。
- chmod +x webhook_etherwake_recorder.js
- ./webhook_etherwake_recorder.js
別のシェルから下記のコマンドを実行して動作確認します。(XXXXの部分は設定したTOKENに変更してください)
- curl -X POST -H "Content-type:application/json" -d '{"token":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}' http://localhost:9004/wake
OKと表示されて、レコーダーが起動することを確認しましょう。
続いてこのプログラムをRaspberry Piで自動的に起動するように設定します。
続いてこのプログラムをRaspberry Piで自動的に起動するように設定します。
- crontab -e
- @reboot /usr/local/bin/node $HOME/webhook_etherwake_recorder/webhook_etherwake_recorder.js > /dev/null 2>&1 &
リブート後、先ほどのcurlコマンドをもう一度実行して、正しく動作することを確認します。
完成
シナリオの動作中は、スマートフォンのConnectアプリ上で、「HDDレコーダー起動」ボタンがアクティブになります。
このボタンを押したらHDDレコーダーが起動し、スマートフォンにプッシュ通知が届きます。
通知をタップすると、メッセージが表示されます。
このメッセージの矢印アイコンをタップすると、ブラウザが起動し、HDDレコーダーに接続します。
その後は、自宅で接続しているときと同様に予約録画が可能です。私の所有している機種の場合は、録画予約一覧から、新規予約を選択します。
HDDレコーダーの残り容量が少ないときなど、HDDレコーダーの画面にアラートが通知されているときには、リモコンでアラートを解除するまでは新規予約ができないようです。ここまで準備して外出先でその状態になるととても残念なので、ご注意を。
また、ボタンを押してから通知が届いたタイミングでは、まだHDDレコーダーが起動完了していない場合があります。その場合はスマホのブラウザに「Proxy error」と表示されます。少し待ってリロードしてみてください。
0 件のコメント:
コメントを投稿