最近在学习如何实现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,就可以在一体机上单机按钮,控制灯的开关啦。