LoginSignup
4
3

More than 5 years have passed since last update.

【追記】Node.jsでsocket.ioを使ってserialportの受信データをブラウザモニタリング

Last updated at Posted at 2019-02-20

これは色々応用できそうなので最小構成を記事にしようかと

今回シリアルデータのソースはArduinoの赤外線リモコンの受信値をそのままUSBシリアルに流したものを利用したが
基本的にArduinoのなんらかのセンサーで受信した情報をSerial.println()で送ればなんにでも応用はできるんじゃないかと

前準備はこんな感じ

mkdir serial_monitor
cd serial_monitor
npm init -y
npm install ejs serialport socket.io

その他にプロジェクトディレクトリにindex.jsとindex.ejsを作成し以下の様な内容

index.js
const app = require('http').createServer(requestHandler);
const io = require('socket.io')(app);
const fs = require('fs');
const ejs = require('ejs');
const ip = "127.0.0.1";

const page = fs.readFileSync(__dirname + '/index.ejs', 'utf-8');

function requestHandler(req,res){
    var output = null;
    console.log(req.url);
    switch(req.url)
    {
        case '/':
            res.writeHead(200,{'Content-Type': 'text/html'});
            output = ejs.render(page,{ip:ip});
            break;
    }
    if(output !== null)
    {
        res.write(output);
    }
    res.end();
}

const serialport = require('serialport');
const portName = 'COM3';// /dev/ttyACM0, /dev/ttyUSB0などOSによって適宜選択
const sp = new serialport(portName,{
    baudRate: 9600,
    dataBits: 8,
    parity: 'none',
    stopBits: 1,
    flowControl: false,
});

const Readline = serialport.parsers.Readline;
const parser = new Readline();
sp.pipe(parser);

io.on('connection', (socket)=>{
    parser.on('data', (data)=>{
        console.log(data);
        socket.emit('status', { message: data });
    });
});

app.listen(3000);
console.log('Ready!');
index.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>TEST</title>
</head>
<body>
    <div id="message">message waiting...</div>
    <script type="text/javascript">
    </script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
    var socket = io('http://<%=ip%>:3000');
    socket.on('status', (data)=>{
        document.getElementById('message').innerText = data.message.trim();
    });
    </script>
</body>
</html>
node index.js

で実行しブラウザで開くと初期画面が表示され

img_20190220.png

↓シリアル信号を受信すると

img_20190220(1).png
のようにブラウザ画面にリアルタイムに受信情報が反映される

【追記】

上記のコードを使用した場合ブラウザのリロードで際限なくparser.on('data',…)のイベントが積み重なってしまうため
(イベント発生毎にconsole.logを吐かせてたら酷い事になってた)
それに対しての修正案
disconnect字に適宜切断する事が必要だと分かったので受信系と通知系を分離するのが望ましいかと…

index.js
+var message=null;
// メイン受付用(双方向通信など送信、書き込み系処理はすべてこちらで行う)
+parser.on('data',masterReciever);
+function masterReciever(data){
+        console.log(data);
+        message=data;
+}
io.on('connection', (socket)=>{
-    parser.on('data', (data)=>{
-        console.log(data);
-        socket.emit('status', { message: data });
-    });
// Socket通信の為のシリアルレシーバー(状態の通知のみで書き込みなどは行わないこと)
+    parser.on('data',slaveReciever);
//   切断時Removeの為関数化
+    function slaveReciever(data){
+        console.log(data);
+        socket.emit('status', { message: message});
+    }
// ブラウザ切断時は必ずparser.on('data',…)イベントを解除する
+    socket.on('disconnect',()=>{
+        parser.removeListener('data',slaveReciever);
+    });
});
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3