Nodejs 串口通信 : websocket , serialport
最近在学习如何实现web页面和串口间通信,网页请求使用websocket,实现的基本功能如下:
1、基本需求:硬件:有两个信号灯(TLA-505-1T),一个485继电器(开关),电压转换器,工业触屏一体机。
2、原理图:
3工作原理:
首先一体机中采用node开发服务器,网页请求采用websocket协议,直接放代码了:
var express = require('express'); var SerialPort = require('serialport'); var app = express(); var expressWs = require('express-ws')(app); var util = require('util'); /* var com =require('./com.js'); var logger = require('./log.js').logger; */ app.use(express.static('public')); //ejs app.set('view engine','ejs'); app.get('/',function(req,res){ res.render('control'); }) app.ws('/ws', function(ws, req) { util.inspect(ws); ws.on("message",function(str){ console.log('1234'); //hander(str,ws); }); ws.on("close",function(code,reason){ console.log('connection closed'); }) //处理错误事件信息 ws.on('error',function(err){ console.log('throw err',err); }) }) function hander(str,ws) { //发送数据到客户端 //console.log(str); var arr = str.split(''); if(arr[2]==1){//close arr[2]=0; }else{ arr[2]=1; } //console.log(arr.join('')); ws.send(arr.join('')); } app.listen(3004);
这样一个server服务写好,然后在写html界面:
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="js/jquery.mobile-1.4.5.min.css"> <script src="js/jquery-1.11.3.min.js"></script> <script src="js/jquery.mobile-1.4.5.min.js"></script> <title>Title</title> <style> form{ margin: 30px auto; width: 35%; } </style> </head> <body> <br> <form class="form"> <fieldset> <legend>websocket 控制</legend> <br> <br> <div> <button type="button" style="background: #EEF9F3" id="deng1" value="100">灯1关闭状态</button> <button type="button" style="background: #EEF9F3" id="deng2" value="110">灯2关闭状态</button> </div> <br> <span id='content'>客户端未连接</span></br> <input type="button" value="连接" id="connect" class="connect"/> </fieldset> </form> <script> var oUl=document.getElementById('content'); var oConnect=document.getElementById('connect'); var oSend=document.getElementById('send'); var oInput=document.getElementById('message'); var ws=null; oConnect.onclick=function(){ ws = new WebSocket('ws://localhost:3004/ws'); ws.onopen=function(){ document.getElementById('content').innerHTML = "客户端已连接"; } ws.onmessage=function(evt){ //document.getElementById('states').innerHTML = "deng : "+evt.data var arr = evt.data.split(''); if(arr[1]==0){//deng1 var deng = "deng1"; changeState(deng,'states1'); }else if(arr[1]==1){//deng2 var deng = "deng2"; changeState(deng,'states2'); } function changeState(deng,state){ $('#'+deng).val(evt.data); if(arr[2]==1){//open // document.getElementById(state).innerHTML = deng+" open:"+evt.data; document.getElementById(deng).innerHTML = (deng =='deng1'?'灯1':'灯2')+"关闭状态"; $('#'+deng).css("background-color","#B3B4A6"); }else if(arr[2]==0){ // document.getElementById(state).innerHTML = deng+" close:"+evt.data; document.getElementById(deng).innerHTML = (deng =='deng1'?'灯1':'灯2')+"打开状态"; $('#'+deng).css("background-color","#EEF9F3"); } } } ws.onclose=function(){ document.getElementById('content').innerHTML = "客户端已断开连接"; }; ws.onerror=function(evt){ oUl.innerHTML+="<li>"+evt.data+"</li>"; }; }; //$(document).on("pagecreate","#pageone",function(){ $("#deng1").on("tap",function(){ ws.send($("#deng1").val()); }); //}); $("#deng2").on("tap",function(){ ws.send($("#deng2").val()); }); /*function clickDend(val){ console.log(val) if(ws){ ws.send(val); } }*/ </script> </body> </html>
这样一个完整的websocket协议完成,最后在socket协议中加入串口通信:
var express = require('express'); var SerialPort = require('serialport'); var app = express(); var expressWs = require('express-ws')(app); var util = require('util'); var com =require('./com.js'); /* var com =require('./com.js'); var logger = require('./log.js').logger; */ app.use(express.static('public')); //ejs app.set('view engine','ejs'); app.get('/',function(req,res){ res.render('control'); }) app.ws('/ws', function(ws, req) { util.inspect(ws); var sendDelay = 2000; ws.on("message",function(str){ console.log('1234'); var arr = str.split(''); if(arr[2]==1){//close arr[2]=0; }else{ arr[2]=1; } sendData(arr,ws); //setInterval(sendData,sendDelay); }); ws.on("close",function(code,reason){ console.log('connection closed'); }) //处理错误事件信息 ws.on('error',function(err){ console.log('throw err',err); }) }) var defaults = { //reportVersionTimeout: 5000, receiveInterval: 100, sendInterval: 500, repeatSendTimes: 30, // ?????? SerialName:'/dev/ttyAMA0', SerialPort: { baudRate: 9600, autoOpen: false, parity: 'none', xon: false, xoff: false, xany: false, rtscts: false, hupcl: true, dataBits: 8, stopBits: 1, bufferSize: 11 } }; var SerialPort = com.SerialPort; //logger.info('List all serialport'); SerialPort.list(function (err, ports) { ports.forEach(function(port) { console.log(port.comName); console.log(port.pnpId); console.log(port.manufacturer); }); }); var test = new com.SerialPort(defaults.SerialName, defaults.SerialPort); var count=0; var sendTime = Date.now(); test.on('data', function (data) { console.log("receive:"+util.inspect(data)); count++; var elapsed = Date.now() - sendTime; console.log("count:"+count+",elapsed:"+elapsed+" ms"); }); test.on('error',function (err){ console.log("error:"+err); }); test.on('close',function (){ console.log("close occured"); }); test.open(function (error) { console.log(error); console.log('com port opened'); }); var cmd1 = Buffer.from([0xaa,0x07,0xde,0x03,0x03,0x01,0x27,0x34,0x10,0x08,0x09]); var cmd2 = Buffer.from([0xaa,0x07,0xde,0x03,0x03,0x01,0x27,0x34,0x10,0x02,0x03]); var cmd3 = Buffer.from([0xFE,0x05,0x00,0x00,0xFF,0x00,0x98,0x35]); var cmd4 = Buffer.from([0xFE,0x05,0x00,0x00,0x00,0x00,0xD9,0xC5]); var cmd5 = Buffer.from([0xFE,0x05,0x00,0x01,0xFF,0x00,0xc9,0xf5]); var cmd6 = Buffer.from([0xFE,0x05,0x00,0x01,0x00,0x00,0x88,0x05]); var sendCount = 0; function sendData(arr,ws){ console.log("send count:"+arr[1]); if(arr[1]==0){ if(arr[2]==0){ test.write(cmd3); //灯1 打开 arr[2]==1; }else if(arr[2]==1){ test.write(cmd4); //灯1 关闭 arr[2]==0; } } else if(arr[1]==1){ if(arr[2]==0){ test.write(cmd5); //灯1 打开 arr[2]==1; }else if(arr[2]==1){ test.write(cmd6); //灯1 关闭 arr[2]==0; } } ws.send(arr.join('')); } app.listen(3004);ok,就可以在一体机上单机按钮,控制灯的开关啦。