前言:最近这两天在研究如何实现web页面和串口间通信,在网上也查了各种资料,electron、nw或者chrome serial,发现对于我来说都太难实现了,一来可用的资料太少,二来安装东西老是出问题,算了还是放弃吧,自己用常用且最熟悉的方式来实现吧,作为一名前端码农,选用的肯定是node作为服务器了,然后网页请求方式用ajax或websocket都可以,实现方式下文都有。
先说说基本需求:硬件:usb插口的led蜂鸣器(就一个单片机),有红黄蓝三种灯,通过下发相应的指令,实现亮相应的登或者响起蜂鸣器
1) 安装serialport
npm install serialport
2)新建server.js文件
var SerialPort = require('serialport') //Opening a Port var serialPort = new SerialPort('COM4', { //波特率,可在设备管理器中对应端口的属性中查看 baudRate : 9600, autoOpen:false }) //连接串口后进行写入指令操作 serialPort.open(function (err) { console.log('IsOpen:',serialPort.isOpen) console.log('err:',err) if(!err){ //16进制Buffer流 const buf1 = new Buffer("01050000ff008C3A","hex") //打开红灯 const buf11 = new Buffer("010500000000CDCA","hex") //关闭红灯 const buf2 = new Buffer("01050001f000D80A","hex") //打开黄灯 const buf21 = new Buffer("0105000100009C0A","hex") //关闭黄灯 const buf3 = new Buffer("01050002f000280A","hex") //打开绿灯 const buf31 = new Buffer("0105000200006C0A","hex") //关闭绿灯 const bufs = [buf1,buf2,buf3] // const bufs = [buf11,buf21,buf31] var i = 0 eachWrite(bufs[i]) function eachWrite(item) { console.log(item) serialPort.write(item, function (error, result) { i++ if(i>=bufs.length)return //指令是一条一条下发的 setTimeout(function () { eachWrite(bufs[i]) },40) }) } } }) //指令监听 serialPort.on('data',function (data) { console.log('data received: '+data) }) //错误监听 serialPort.on('error',function (error) { console.log('error: '+error) }) //获取端口列表 SerialPort.list(function (error, ports) { ports.forEach(function(port) { console.log(port.comName); console.log(port.pnpId); console.log(port.manufacturer); }); })
3)执行代码
node server.js
4)运行代码 最终结果
1) 安装nodejs-websocket
npm install nodejs-websocket
2)新建文件websocket.js
var ws=require('nodejs-websocket'); var SerialPort = require('serialport') var server = ws.createServer(function (conn, res) { conn.on("text",function(str){ broadcast(server,str.split(',')); server.emit('my other event', { my: 'data' }); }); conn.on("close",function(code,reason){ console.log('connection closed'); }) //处理错误事件信息 conn.on('error',function(err){ console.log('throw err',err); }) }).listen(5000); /* **指令下发 * msg:string ; eg: '01050000ff008C3A,01050001f000D80A' * server:socket server * */ function broadcast(server, msg) { var recData = []; msg.map(function (item, index) { //发送数据到客户端 server.connections.forEach(function (conn) { conn.sendText(item); }) //16进制Buffer流 const str = new Buffer(item,"hex") recData.push(str) }) var i = 0 eachWrite(recData[i]) function eachWrite(item) { serialPort.write(item, function (error, result) { i++ if(i>=recData.length)return //指令是一条一条下发的 setTimeout(function () { eachWrite(recData[i]) },40) }) } } //Opening a Port var serialPort = new SerialPort('COM4', { baudRate : 9600, autoOpen:false }) //连接串口 serialPort.open(function (err) { console.log('IsOpen:',serialPort.isOpen) }) //指令监听 serialPort.on('data',function (data) { console.log('data received: '+data) }) //错误监听 serialPort.on('error',function (error) { console.log('error: '+error) }) //获取端口列表 SerialPort.list(function (error, ports) { ports.forEach(function(port) { console.log(port.comName); console.log(port.pnpId); console.log(port.manufacturer); }); })
3)新建html文件,index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> form{ margin: 30px auto; width: 35%; } </style> </head> <body> <br> <form class="form"> <fieldset> <legend>wobsocket 控制</legend> <br> <br> <div> <input type="button" onclick="clickDend('01050000ff008C3A,01050001f000D80A')" value="红黄灯"> <input type="button" onclick="clickDend('01050001f000D80A')" value="黄灯"> <input type="button" onclick="clickDend('01050002f000280A')" value="绿灯"> <input type="button" onclick="clickDend('01050003f300793A')" value="蜂鸣器"> <input type="button" onclick="clickDend('0105000300003DCA')" value="关闭蜂鸣器"> <input type="button" onclick="clickDend('010500000000CDCA,0105000100009C0A,0105000200006C0A,0105000300003DCA')" value="关闭所有"> </div> <br> <ul id="content"></ul> <input type="text" placeholder="请输入发送的消息" class="message" id="message"/> <input type="button" value="发送" id="send" class="connect"/> <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:5000'); ws.onopen=function(){ oUl.innerHTML+="<li>客户端已连接</li>"; } ws.onmessage=function(evt){ oUl.innerHTML+="<li>"+evt.data+"</li>"; } ws.onclose=function(){ oUl.innerHTML+="<li>客户端已断开连接</li>"; }; ws.onerror=function(evt){ oUl.innerHTML+="<li>"+evt.data+"</li>"; }; }; oSend.onclick=function(){ if(ws){ ws.send(oInput.value); } } function clickDend(val){ console.log(val) if(ws){ // ws.send('010500000000CDCA,0105000100009C0A,0105000200006C0A,0105000300003DCA'); ws.send(val); } } </script> </body> </html>
4)启动服务,执行代码
node server.js
5)运行页面
1) 安装express,cors
npm install express cors
2)新建http.js文件
var express = require('express') var cors = require('cors') //解决跨域 var app = express(); var port = process.env.PORT || 1124; var SerialPort = require('serialport') var serveStatic = require('serve-static'); var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json({limit: '1mb'})); app.use('/static',serveStatic('public')); app.listen(port) app.use(cors()) app.post('/ledControl/on.do',function (req,res) { const str = req.body.data if(setContrl(str.split(','))){ res.send({ code:100, data:'开启成功!', message:'信息' }) return } res.send({ code:101, data:'开启失败!', message:'信息' }) }) /* **指令下发 * msg:string ; eg: '01050000ff008C3A,01050001f000D80A' * */ function setContrl(msg){ return new Promise(function (resolve,reject) { let recData=[]; msg.map(function (item, index) { //16进制Buffer流 const str = new Buffer(item,"hex") recData.push(str) }) var i = 0 eachWrite(recData[i]) function eachWrite(item) { serialPort.write(item, function (error, result) { i++ if(i>=recData.length){ resolve(true) return } //指令是一条一条下发的 setTimeout(function () { eachWrite(recData[i]) },40) }) } //错误监听 serialPort.on('error',function (error) { console.log('error: '+error) resolve(false) }) }) } //Opening a Port var serialPort = new SerialPort('COM4', { baudRate : 9600, autoOpen:false }) //连接串口 serialPort.open(function (err) { console.log('IsOpen:',serialPort.isOpen) }) //指令监听 serialPort.on('data',function (data) { console.log('data received: '+data) }) //获取端口列表 SerialPort.list(function (error, ports) { ports.forEach(function(port) { console.log(port.comName); console.log(port.pnpId); console.log(port.manufacturer); }); })
3)补充上面index.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> form{ margin: 30px auto; width: 35%; } </style> </head> <body> <form action=""> <fieldset> <legend>http控制</legend> <br> <br> <div id="httpCtrol"> <input type="button" sy-val = '01050001f000D80A' value="黄灯"> <input type="button" sy-val = '01050002f000280A' value="绿灯"> <input type="button" sy-val = '010500000000CDCA,0105000100009C0A,0105000200006C0A,0105000300003DCA' value="关闭所有"> </div> </fieldset> </form> <br> <form class="form"> <fieldset> <legend>wobsocket 控制</legend> <br> <br> <div> <input type="button" onclick="clickDend('01050000ff008C3A,01050001f000D80A')" value="红黄灯"> <input type="button" onclick="clickDend('01050001f000D80A')" value="黄灯"> <input type="button" onclick="clickDend('01050002f000280A')" value="绿灯"> <input type="button" onclick="clickDend('01050003f300793A')" value="蜂鸣器"> <input type="button" onclick="clickDend('0105000300003DCA')" value="关闭蜂鸣器"> <input type="button" onclick="clickDend('010500000000CDCA,0105000100009C0A,0105000200006C0A,0105000300003DCA')" value="关闭所有"> </div> <br> <ul id="content"></ul> <input type="text" placeholder="请输入发送的消息" class="message" id="message"/> <input type="button" value="发送" id="send" class="connect"/> <input type="button" value="连接" id="connect" class="connect"/> </fieldset> </form> <script src="jquery.min.js"></script> <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:5000'); ws.onopen=function(){ oUl.innerHTML+="<li>客户端已连接</li>"; } ws.onmessage=function(evt){ oUl.innerHTML+="<li>"+evt.data+"</li>"; } ws.onclose=function(){ oUl.innerHTML+="<li>客户端已断开连接</li>"; }; ws.onerror=function(evt){ oUl.innerHTML+="<li>"+evt.data+"</li>"; }; }; oSend.onclick=function(){ if(ws){ ws.send(oInput.value); } } function clickDend(val){ console.log(val) if(ws){ // ws.send('010500000000CDCA,0105000100009C0A,0105000200006C0A,0105000300003DCA'); ws.send(val); } } </script> <script> $(function () { $('#httpCtrol input').on('click',function () { var $this = $(this) $.ajax({ method:'post', url:'http://localhost:1124/ledControl/on.do', data:{data:$this.attr('sy-val')}, success:function (res) { console.log(res) } }) }) }) </script> </body> </html>
4)启动服务
node server.js
文章来源: NodeJs串口通信