娘(@kosamari)のgithubのIoT-Boilerplate
Node.js, Express.js, Soket.io, Johnny-five 等を使ってArduino UNOにつないだLEDとスイッチを制御する例。
まず,これをそのままトレースして見ます。
概念図

IoT-Boilerplateより引用
準備
- 配線, IoT-Boilerplateより。
- Arduino UNOにStandardFirmataを書き込む。
- Arduino IDEのメニューバーから「ファイル」→「スケッチの例」→「Firmata」と進む。
- StandardFirmataを開きArduino UNOに書き込む。
- ソースコードのダウンロードと展開 (Linux, mac OSX)
- https://github.com/kosamari/IoT-Boilerplate のページを開く。
- [Download ZIP]ボタンをクリックして「IoT-Boilerplate-master.zip」をダウンロードする。
- ZIPファイルを展開するとIoT-Boilerplate-masterフォルダが生成される。
- ターミナル・シェルを起動してcdコマンドでIoT-Boilerplate-masterフォルダ(ディレクトリ)に移動する。
- lsコマンドでファイル一覧を表示し,package.jsonがあることを確認する。
- package.json に記述されているモジュールを自動インストールする
$npm install [enter] - johnny-five モジュールはpackage.jsonに記述されていないので手動インストールする。
$npm install johnny-five [enter]
実行
- バックグラウンドでserver.jsを実行する。
$node server.js & [enter] - client.jsを実行する。
$node client.js[enter] - server.js, client.js を実行しているマシンでブラウザを起動する。
- ブラウザで http://localhost:5030 を開くと下のページが表示される。
- LED conroll セクションのTurn On, Turne Off ボタンのクリックでLEDを点消灯することができる。
- ブレッドボード上のタクトスイッチを押すと Button Reciver セクションのメッセージが button connected to pin 8 is pressed! と変化する。
停止
- CTRL+Cを2回入力してclient.jsの実行を止める。
- psコマンドでプロセスを表示するとnode server.js のプロセス番号 xxxxx が見える。
- プロセスxxxxxをkill(停止)する。
$kill xxxxx [enter]
動作の理解
- ブラウザ操作→LED点消灯
- Webブラウザでserver.jsにアクセスするとserver.jsは ./view/controller.html をWebブラウザに向けて送り出す。
このとき,controller.html に記述されている{{port}}の部分をioportの値 5040 に置換する。app.get('/', function (req, res) { res.render('controller', {port:ioport}); });
同時に,http://localhost:5040/socket.io/socket.io.js のスクリプトをブラウザで利用できるようにする。(controller.htmlの記述)
<script src="http://localhost:{{port}}/socket.io/socket.io.js"></script>
注:{{port}}は5040と置き換えられる。
- WebブラウザでTurnOnボタンをクリックすると,
<button class="btn" onclick="led('on')" disabled/>Turn On</button>
により,次のfunction led(command)が駆動される。このとき引数commandには’on’が引き渡される。
function led(command) { socket.emit('led', {command:command}); }
function ledが実行されると,server.js に向けて ‘led’ ‘on’ のメッセージが送出される。
- このメッセージを受けたserver.jsは,そのままブロードキャスト(プッシュ)する。
socket.on('led', function(data) { socket.broadcast.emit('led', data); });
- ブロードキャストされたメッセージをclient.jsが受信すると,’led’メッセージであれば,それに続く引数’on’,’off’により function led.on(), led.off() を実行する。
socket.on('led', function(data){ if(data.command === 'on'){ led.on(); }else if(data.command === 'off'){ led.off(); } });
ledは次によりD13に割り振られている。on(), off() は johnny-five が持っているfunctionでon()はHIGHT,off() はLOWを出力する。
var led = new five.Led(13);
- led.on() は johnny-five で Firmata プロトコルのメッセージに変換されUSB-serialポートを通してArduino UNOに送られる。
- Arduino UNOではStandardFirmataがメッセージを受け取ってD13にHIGHTを出力する。
- D13に接続されたLEDが点灯する。
- Webブラウザでserver.jsにアクセスするとserver.jsは ./view/controller.html をWebブラウザに向けて送り出す。
- タクトスイッチを押す→Webブラウザで表示しているメッセージが変わる
- タクトスイッチを押すと,Arduino UNO StandardFirmata がUSB-Serialを通してclient.jsにメッセージ ‘press’ を送る。
- メッセージ ‘press’ を受信したclient.jsは,’press’, ‘pin:8’ のメッセージを server.js に送る。
button.on('press', function() { socket.emit('press', {pin:8}); });
- メッセージ ‘press’, ‘pin:8’ を受信した server.js は,そのままブロードキャスト(プシュ)する。
socket.on('press', function(data) { socket.broadcast.emit('press', data); });
- ブロードキャストされたメッセージをWebブラウザが受信すると,socket.on(‘press’, function (data){ });のスクリプトが実行される。
socket.on('press', function (data) { var message = document.getElementById("message"); message.innerHTML = 'button connected to pin '+ data.pin +' is pressed!'; });
結果,<span id=’message’>〜</span> が書き換わって表示される。
<span id='message'>Press the button on your hardware</span> が <span id='message'>button connected to pin 8 is pressed!</span> と書き換えられる
改編
- IoT-Boilderplateの localhost の部分を書き換えて,他のコンピュータのwebブラウザからアクセスしLチカできるようにしてみる。server.js, client.jsを稼働させるコンピュータのIPアドレスが192.168.10.209と仮定する。
- server.jsの改編
6行目 追加,14行目 変更var express = require('express'); var app = express(); var port = 5030; var ioport = 5040; var io = require('socket.io').listen(ioport); var iohost = '192.168.10.209';//追加 /* * express server setup */ app.set('view engine', 'html'); app.engine('html', require('hbs').__express); app.get('/', function (req, res) { res.render('controller', {host:iohost, port:ioport});//変更 }); //-- 以下略 --//
- controller.htmlの改編
19行目と26行目を変更<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>IoT Controller</title> <link rel="stylesheet" type="text/css" href="./controller.css"> </head> <body> <h1>IoT Controller</h1> <h2>LED controll</h2> <button class="btn" onclick="led('on')" disabled/>Turn On</button> <button class="btn" onclick="led('off')" disabled/>Turn Off</button> <br> <br> <h2>Button Reciver</h2> <span id='message'>Press the button on your hardware</span> <script src="http://{{host}}:{{port}}/socket.io/socket.io.js"></script> <script type="text/javascript"> /* * Setup */ //1. specify domain and port of your socket.io server var socket = io.connect('http://{{host}}:{{port}}'); //-- 以下略 --//
- client.jsの改編
6行目を変更/* * Setup */ //1. specify domain and port of your socket.io server var socket = require('socket.io-client')('http://192.168.10.209:5040'); //-- 以下略 --//
- server.jsの改編
- タクトスイッチを押すとメッセージが変化するが,離してもメッセージがbutton connected to pin 8 is pressed!のままなので,離すと元のメッセージに戻るようにしてみる。
- client.jsの改編
// 3. Create socket message emitter の下に次の行を追加button.on('up',function(){ socket.emit('up',{pin:8}); });
- server.jsの改編
// Define socket messages used in your application の下に次の行を追加socket.on('up', function(data) { socket.broadcast.emit('up', data); });
- controller.htmlの改編
<script type=”text/javascript”>〜 </script> の間に次の行を追加socket.on('up', function (data) { var message = document.getElementById("message"); message.innerHTML = 'Press the button on your hardware'; });
- client.jsの改編
- server と client を別マシンにする。
- server.js を Linuxマシン(192.168.10.209)で稼働させる。
- client.js をArduino UNO を接続した Rasspberry Pi(192.168.10.210) で稼働させる。
- さらに,別マシンでWebブラウザを起動しhttp://192.168.10.209:5030(Linuxマシン)にアクセスしLEDのTurnOn/TurnOffを行う。
- ブレッドボードのタクトスイッチの操作を行う。
ソースコードは1,2の改編のままで正しく動く。