最近在学习如何实现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界面:
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>Titletitle>
<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+="" +evt.data+"";
};
};
//$(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,就可以在一体机上单机按钮,控制灯的开关啦。