迷える子羊の苦悩

アクセスカウンタ

zoom RSS スマホ から ESP8266リモコン を リモートコントロール

<<   作成日時 : 2016/06/18 23:16   >>

ブログ気持玉 0 / トラックバック 0 / コメント 0

前回は、MQTTプロトコルで、ESP8266リモコンを操作しましたので、
今回は、スマホからESP8266リモコンを操作したいです。

普通(?)に考えると、スマホのアプリからAWS IoTへ接続し、
MQTTでPublishするのかもしれませんが、

スマホのアプリを作るのも面倒ですので、
ブラウザ(@スマホ)から、AWS EC2上のWEBサーバーにアクセスして、
そのサーバーからAWS IoTへMQTTでPublishする方法を取ります

ブラウザから操作するようにすれば、スマホからでもPCからでも、
タブレットからでも、操作出来て、一石二鳥以上です

まずは、javascriptでAWS IoTへPublishしてみます。

このサイトに書いてある通りに、、、
1:var awsIot = require('aws-iot-device-sdk');
2:
3:var device = awsIot.device({
4: keyPath: './certs/private.pem.key',
5: certPath: './certs/certificate.pem.crt',
6: caPath: './certs/iot-rootca.pem.crt',
7: clientId: 'test-devdev',
8: region: 'ap-northeast-1'
9:});
10:
11:device
12: .on('connect', function() {
13: console.log('connect');
14: device.subscribe('#');
15: device.publish('topic_2', JSON.stringify({ test_data: 1}));
16: });
17:
18:device
19: .on('message', function(topic, payload) {
20: console.log('message', topic, payload.toString());
21: });
このファイルを app.js として保存して、
証明書は、AWS IoTで作成した証明書を用意します。
ルート証明書は、 VeriSign root CA certificate を用意します。
これで、

npm install aws-iot-device-sdk
node app.js

とすれば、AWS IoTに接続して、publish と subscribe してくれます
簡単すぎますね。

接続先を指定していませんが、なんかうまいことやってくれているのかな

あとは、これをAWS EC2上で動かして、WEB APIのように見せればよいかと思います。

ということで、作成したWEBページがこんな感じ。
画像
初めてのWEBデザインなので素人感満載です
こんなデザインですが、このページ作成には、結構な時間がかかっています

温度、湿度、気圧の最新データはDynamoDBから取得しています。
これも、ブラウザから直接DynamoDBにアクセスせずに、
WEB APIを用意して、AWS EC2がDynamoDBから取得しています。

スピンボタンで設定温度を調整します。
本物のリモコン同様に、下限14℃、上限30℃にしました。
温度設定後に、冷房と暖房、停止ボタンを押すと、
AWS EC2からESP8266リモコンにコマンドが送られます。

コマンドを送信して、ESP8266リモコンからの応答を受信すると、
下からニョキニョキっとメッセージが上がってきて、送信できたことを知らせてくれます
画像
応答が来ない場合は、失敗した旨を知らせてくれます。

さて、これで一応WEBページはできましたが、
AWS EC2上にWEBサーバを立てるとなると、セキュリティの問題が出ちゃいます。
エアコンのON/OFFしかないけどね。

ということで、HTTPS限定にして、さらにクライアント認証必須にすることにしました。
自己ルート認証局、サーバー証明書、クライアント証明書に関しては、
以前お勉強したので、すんなり行けますが、問題は、これをNode.jsで
どのようにHTTPS + クライアント認証にするかです。。。

このページを参考にして、app.jsを以下のようにしました。
1:var
2: routes = require('./lib/routes'),
3: fs = require('fs'),
4: https = require('https'),
5: http = require('http'),
6: express = require('express'),
7: morgan = require('morgan'),
8: app = express(),
9: options = {
10: key : fs.readFileSync('./certs/server/server.key.pem'),
11: cert : fs.readFileSync('./certs/server/server.cert.pem'),
12: passphrase: process.env.CERT_PASS,
13: ca : fs.readFileSync('./certs/server/rootca.cert.pem'),
14:
15: honorCipherOrder: true,
16: requestCert: true,
17: rejectUnauthorized: true
18: };
19:// ------------- END MODULE SCOPE VARIABLES ---------------
20:
21:// ------------- BEGIN SERVER CONFIGURATION ---------------
22:app.use(morgan(':date[iso] : :remote-addr - :method :url :status'));
23:app.use(express.static(__dirname + '/public'));
24:
25:routes.configRoutes(app);
26:// -------------- END SERVER CONFIGURATION ----------------
27:
28:// ----------------- BEGIN START SERVER -------------------
29:var server_port = process.env.WEB_PORT || 3000;
30:if (process.env.OS === 'Windows_NT') {
31: http.createServer(app).listen(server_port, function () {
32: console.log('HTTP server listening on port %d in %s mode',
33: server_port, app.settings.env);
34: });
35:}
36:else {
37: https.createServer(options, app).listen(server_port, function () {
38: console.log('HTTPS server listening on port %d in %s mode',
39: server_port, app.settings.env);
40: });
41:}
42:// ------------------ END START SERVER --------------------
43:

optionsにhttpsの設定が入っています。証明書は、自分で作成した証明書になります。
passphraseは、サーバーの秘密鍵のパスワードです。
ブログに間違ってアップロードしないように、環境変数に入っています
honorCipherOrderは、よくわからない攻撃用に推奨しているので入れました。
requestCertが、クライアント認証要求です。
rejectUnauthorizedは、認証されていないクライアントを拒否るようです。

httpも入っているのは、localhostでhttpsをやろうとしたら怒られたからです。
判定はいい加減で、OSがWindows_NTかどうかで見ています。

あと、ルーティング部分は、
1:configRoutes = function (app) {
2: if (process.env.OS !=='Windows_NT') {
3: app.all('*', function (req, res, next) {
4: // 証明書の検証
5: var cert = res.connection.getPeerCertificate();
6:
7: if (cert.subject.CN !== 'home-controller' ||
8: new Date(cert.valid_to) < Date.now()) {
9: console.log("CN :" + cert.subject.CN); // for debug
10: console.log("Valid:" + cert.valid_to);
11: res.sendStatus(406); //Not Acceptable
12: return;
13: }
14: next();
15: });
16: }
17:
として、クライアント証明書の検証を入れています。
Node.js側でどのくらいやってくれているかよく分からないので、
とりあえず、クライアント証明書のCNと有効期限をチェックしています。
CNは、home-controller用に証明書を発行しましたので、これ以外の目的は
拒否するようにしています。まだ、これ以外は無いんですけどね

これで、クライアント側にルート認証局証明書、クライアント証明書を入れて、
AWS EC2上で、Node.js WEBサーバーを立てれば完了です。

PCのChromeからアクセスすると、証明書の選択画面が出てきました。
画像
OKをおすと、無事にhttpsでアクセスできました
画像

同様にスマホからも、証明書をインストールして、
画像
となりました

ここで注意
スマホからテストするとき、WiFiを切ってアクセスしましょう。
AWS EC2側でIPアドレス制限している場合、外に行ったらスマホから
アクセスできないってことになります

もう一点
EC2上にバックグラウンドでNode.js WEBサーバーを立てる場合、
単に、

node app.js &

としただけでは、PUTTYを切った後、しばらくすると、
nodeプロセスは死んでしまいます

いろいろ調べたところ、どうやらSSHで接続すると、
SSHのプロセスが親プロセスになって、nodeプロセスは子プロセス
として動作するため、親がいなくなると、子は消されるようです

これを回避するためには、

nohup node app.js > test.log 2>&1 &

のように、nohupコマンドを使用します。
ログはエラー含めて、test.logに出力されます

なんとか、真夏になる前に、外から冷房を入れられるようになりました
真夏が楽しみでなりません

最後に、証明書は入ってないですが、WEBサーバーのソースコードを参考まで ⇒ ここ

さて、つぎは、何つくろうかな

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
スマホ から ESP8266リモコン を リモートコントロール 迷える子羊の苦悩/BIGLOBEウェブリブログ
文字サイズ:       閉じる