├── .gitignore ├── 2016-03-20 23:42:33屏幕截图.png ├── README.md ├── index.html └── serial-webDebug ├── app.js ├── bin └── www ├── package.json ├── public ├── javascripts │ └── serialop.js └── stylesheets │ └── style.css ├── routes ├── index.js └── users.js ├── serialdriver ├── serialdata.js └── serialscan.js └── views ├── error.ejs └── index.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /2016-03-20 23:42:33屏幕截图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Archie2035/web-serialDebug/7b51c5f0c85f22a0a7da3abda3b7cc2a3e3fc4d4/2016-03-20 23:42:33屏幕截图.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##serial-webDebug项目 2 | -------- 3 | 4 | ![效果](./2016-03-20 23:42:33屏幕截图.png) 5 | 6 | ##简介 7 | -------- 8 | 对于web爱好者来说,在web上做一些事情真的很酷。这个项目通过使用serialport包调用底层的串口,完成串口的收发。和桌面软件的串口调试助手功能类似。 9 | 由于本人也是web新手,所以界面粗糙,代码组织的不够好。但是可以供大家参考和日常的使用。 10 | 11 | ##技术说明 12 | -------- 13 | 前端使用ejs模板引擎开发,通过jquery发起ajax请求与后端的nodejs进行交互。 14 | 15 | ##TODO 16 | -------- 17 | 1.使用websocket代替ajax,使其实时性更强 18 | 2.前端添加自定义波特率功能 19 | 3.添加定时发送功能 20 | 4.添加自动解析json数据功能 21 | 5. ... -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | serial-webDebug 6 | 7 | 8 | 9 |

hello

10 | 11 | 12 | ##简介 13 | -------- 14 | 对于web爱好者来说,在web上做一些事情真的很酷。这个项目通过使用serialport包调用底层的串口,完成串口的收发。和桌面软件的串口调试助手功能类似。 15 | 由于本人也是web新手,所以界面粗糙,代码组织的不够好。但是可以供大家参考和日常的使用。 16 | 17 | ##技术说明 18 | -------- 19 | 前端使用ejs模板引擎开发,通过jquery发起ajax请求与后端的nodejs进行交互。 20 | 21 | ##TODO 22 | -------- 23 | 1.使用websocket代替ajax,使其实时性更强 24 | 2.前端添加自定义波特率功能 25 | 3.添加定时发送功能 26 | 4.添加自动解析json数据功能 27 | 5. ... 28 | 29 | -------------------------------------------------------------------------------- /serial-webDebug/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var routes = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | 11 | 12 | 13 | 14 | 15 | var app = express(); 16 | 17 | // view engine setup 18 | app.set('views', path.join(__dirname, 'views')); 19 | app.set('view engine', 'ejs'); 20 | 21 | // uncomment after placing your favicon in /public 22 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 23 | app.use(logger('dev')); 24 | app.use(bodyParser.json()); 25 | app.use(bodyParser.urlencoded({ extended: false })); 26 | app.use(cookieParser()); 27 | app.use(express.static(path.join(__dirname, 'public'))); 28 | 29 | app.use('/', routes); 30 | app.use('/users', users); 31 | 32 | // catch 404 and forward to error handler 33 | app.use(function(req, res, next) { 34 | var err = new Error('Not Found'); 35 | err.status = 404; 36 | next(err); 37 | }); 38 | 39 | // error handlers 40 | 41 | // development error handler 42 | // will print stacktrace 43 | if (app.get('env') === 'development') { 44 | app.use(function(err, req, res, next) { 45 | res.status(err.status || 500); 46 | res.render('error', { 47 | message: err.message, 48 | error: err 49 | }); 50 | }); 51 | } 52 | 53 | // production error handler 54 | // no stacktraces leaked to user 55 | app.use(function(err, req, res, next) { 56 | res.status(err.status || 500); 57 | res.render('error', { 58 | message: err.message, 59 | error: {} 60 | }); 61 | }); 62 | 63 | 64 | 65 | 66 | app.listen(3030,function(){ 67 | console.log("listen at 3030"); 68 | }); 69 | 70 | 71 | 72 | module.exports = app; 73 | -------------------------------------------------------------------------------- /serial-webDebug/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('serial-webDebug:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /serial-webDebug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serial-webDebug", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "~2.3.3", 13 | "express": "~4.13.1", 14 | "morgan": "~1.6.1", 15 | "serialport": "^2.0.6", 16 | "serve-favicon": "~2.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /serial-webDebug/public/javascripts/serialop.js: -------------------------------------------------------------------------------- 1 | var queryTimer; 2 | function querySerialData() { 3 | queryTimer = setInterval(function(){ 4 | $.ajax({ 5 | url: "/querySerialData", 6 | type: "get", 7 | dataType: "json", 8 | success: function (result) { 9 | if(result["serialData"]){ 10 | $('#serialDisplay').append("[接收]"+result["serialData"]+'\n'); 11 | var scrollTop = $("#serialDisplay")[0].scrollHeight; 12 | $("#serialDisplay").scrollTop(scrollTop); 13 | }else{ 14 | 15 | } 16 | } 17 | }); 18 | },1000); 19 | } 20 | function stopQuerySerialData(){ 21 | clearInterval(queryTimer); 22 | } 23 | $(function () { 24 | $('#sendButton').click(function(){ 25 | $.ajax({ 26 | url: "/serialSend", 27 | type: "post", 28 | dataType: "json", 29 | data:{'data':$('#serialInputData').val()}, 30 | beforeSend: function () { 31 | $('#serialDisplay').append("[发送]"+$('#serialInputData').val()+'\n'); 32 | }, 33 | success: function (result) { 34 | if (result) { 35 | } else { 36 | alert("sorry send faild"); 37 | } 38 | }, 39 | error: function () { 40 | alert("send data error!"); 41 | } 42 | }); 43 | }); 44 | $('#openSerial').click(function () { 45 | $.ajax({ 46 | url: "/serialStart", 47 | type: "post", 48 | dataType: "json", 49 | data:{'com':$('#devicecom option:selected').val()}, 50 | beforeSend: function () { 51 | $('#serialDisplay').append("[info]正在请求打开该串口...\n"); 52 | }, 53 | success: function (result) { 54 | if (result["serialOpen"] == 'OK') { 55 | $('#serialDisplay').append(result["serialOpen"] + '\n'); 56 | querySerialData(); 57 | } else { 58 | alert("sorry"); 59 | } 60 | }, 61 | error: function () { 62 | alert("ajax query error!");//执行 63 | } 64 | }); 65 | }); 66 | 67 | $('#closeSerial').click(function () { 68 | 69 | $.ajax({ 70 | url: "/serialStop", 71 | type: "get", 72 | dataType: "json", 73 | beforeSend: function () { 74 | $('#serialDisplay').append("[info]正在请求关闭该串口...\n"); 75 | }, 76 | success: function (result) { 77 | if (result["serialStop"] == 'OK') { 78 | $('#serialDisplay').append(result["serialStop"] + '\n'); 79 | stopQuerySerialData(); 80 | } else { 81 | alert("sorry"); 82 | } 83 | }, 84 | error: function () { 85 | alert("ajax query error!");//执行 86 | } 87 | }); 88 | 89 | }); 90 | 91 | }); 92 | -------------------------------------------------------------------------------- /serial-webDebug/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | body { 7 | background: #fff; 8 | color: #555; 9 | font-size: 14px; 10 | font-family: Verdana, Arial, Helvetica, sans-serif; 11 | } 12 | 13 | td, th, caption { 14 | font-size: 14px; 15 | } 16 | 17 | address, caption, cite, code, dfn, em, strong, th, var { 18 | font-style: normal; 19 | font-weight: normal; 20 | } 21 | 22 | a { 23 | color: #555; 24 | text-decoration: none; 25 | } 26 | 27 | a:hover { 28 | text-decoration: underline; 29 | } 30 | 31 | img { 32 | border: none; 33 | } 34 | 35 | ol, ul, li { 36 | list-style: none; 37 | } 38 | 39 | input, textarea, select, button { 40 | font: 14px Verdana, Helvetica, Arial, sans-serif; 41 | } 42 | 43 | table { 44 | border-collapse: collapse; 45 | } 46 | 47 | html { 48 | overflow-y: scroll; 49 | } 50 | 51 | /* css common */ 52 | .clearfix:after { 53 | content: "."; 54 | display: block; 55 | height: 0; 56 | clear: both; 57 | visibility: hidden; 58 | } 59 | 60 | .clearfix { 61 | *zoom: 1; 62 | } 63 | 64 | body { 65 | padding: 0px; 66 | margin: 0; 67 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 68 | background: #ffffff; 69 | } 70 | 71 | a { 72 | color: #00B7FF; 73 | } 74 | 75 | div { 76 | color: rgba(40, 50, 60, 0.91); 77 | } 78 | 79 | .left { 80 | height: 500px; 81 | float: left; 82 | width: 100px; 83 | background: #ffffff; 84 | _margin-right: -3px; 85 | } 86 | 87 | .right { 88 | height: 500px; 89 | float: right; 90 | width: 100px; 91 | background: #ffffff; 92 | _margin-left: -3px; 93 | } 94 | 95 | .center { 96 | overflow: hidden; 97 | height: 500px; 98 | background: #ffffff; 99 | margin: 0 100px; 100 | } 101 | 102 | .center h1 { 103 | color: #555555; 104 | text-align: center; 105 | } 106 | 107 | .serialMain { 108 | margin-top: 20px; 109 | margin-right: 20px; 110 | margin-left: 20px; 111 | margin-bottom: 20px; 112 | padding: 10px; 113 | height: 300px; 114 | border: 5px solid #dedede; 115 | border-radius: 15px; /* W3C syntax */ 116 | } 117 | 118 | #serialSide { 119 | padding-top: 5px; 120 | padding-left: 5px; 121 | border-radius: 5px; 122 | background: #eeeeee; 123 | width: 15%; 124 | height: 300px; 125 | float: left; 126 | } 127 | 128 | #serialCentor { 129 | padding: 5px; 130 | border-radius: 5px; 131 | background: #eeeeee; 132 | width: 83%; 133 | height: 300px; 134 | float: right; 135 | } 136 | 137 | #serialDisplay { 138 | border-radius: 5px; 139 | resize: none; 140 | height: 65%; 141 | width: 100%; 142 | user-select:none; 143 | } 144 | 145 | #serialInputData { 146 | border-radius: 5px; 147 | width: 100%; 148 | height: 10%; 149 | user-select:none; 150 | } 151 | 152 | #sendButton { 153 | margin-top: 20px; 154 | float: right; 155 | border: none; 156 | color: #fff; 157 | background: #00B7FF; 158 | width: 200px; 159 | height: 10%; 160 | 161 | } 162 | 163 | #openSerial{ 164 | margin-top: 115px; 165 | border: none; 166 | color: #fff; 167 | background: #00B7FF; 168 | width: 98%; 169 | height: 30px; 170 | } 171 | 172 | #closeSerial{ 173 | margin-top: 10px; 174 | border: none; 175 | color: #fff; 176 | background: #00B7FF; 177 | width: 98%; 178 | height: 30px; 179 | } 180 | 181 | #sendButton:hover { 182 | background: #00aaFF; 183 | } 184 | select{ 185 | height: 30px; 186 | margin-top: 5px; 187 | width: 80%; 188 | } 189 | 190 | .footer p { 191 | text-align: center; 192 | } -------------------------------------------------------------------------------- /serial-webDebug/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var serialScan = require('../serialdriver/serialscan'); 4 | var serialData = require('../serialdriver/serialdata'); 5 | var renderData= { 6 | 'serialData':serialScan(), 7 | title:"WEB SerialPort" 8 | } 9 | /* GET home page. */ 10 | router.get('/', function(req, res, next) { 11 | res.render('index',renderData); 12 | }); 13 | /* 打开串口 */ 14 | router.post('/serialStart', function(req, res, next) { 15 | serialData.open(req.body['com'],req.body['baud']); 16 | res.send({"serialOpen": "OK"}); 17 | 18 | }); 19 | /* 关闭串口 */ 20 | router.get('/serialStop', function(req, res, next) { 21 | res.send({"serialStop": "OK"}); 22 | }); 23 | router.post('/serialSend', function(req, res, next) { 24 | serialData.write(req.body['data']); 25 | res.send({"serialSendState":"OK"}); 26 | }); 27 | router.get('/querySerialData', function(req, res, next) { 28 | var dataBuffer = serialData.read(); 29 | res.send({"serialData":dataBuffer}); 30 | }); 31 | 32 | module.exports = router; 33 | -------------------------------------------------------------------------------- /serial-webDebug/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /serial-webDebug/serialdriver/serialdata.js: -------------------------------------------------------------------------------- 1 | var SerialPort = require("serialport").SerialPort; 2 | var serialPort; 3 | var serialData; 4 | function serialOpen(device,baud) { 5 | serialPort = new SerialPort(device, { 6 | baudrate: baud 7 | }); 8 | serialPort.on("open", function () { 9 | console.log('open'); 10 | serialPort.on('data', function (data) { 11 | console.log('data received: ' + data); 12 | serialData += data; 13 | }); 14 | }); 15 | } 16 | function serialClose() { 17 | serialPort.close(); 18 | } 19 | function serialWrite(data) { 20 | serialPort.write(data, function (err, results) { 21 | console.log('err ' + err); 22 | console.log('results ' + results); 23 | }); 24 | } 25 | function serialRead() { 26 | var dataBuffer = serialData; 27 | serialData = '';//清空 28 | return dataBuffer; 29 | } 30 | exports.open = serialOpen; 31 | exports.close = serialClose; 32 | exports.write = serialWrite; 33 | exports.read = serialRead; -------------------------------------------------------------------------------- /serial-webDebug/serialdriver/serialscan.js: -------------------------------------------------------------------------------- 1 | var serialPort = require("serialport"); 2 | var serialArray = []; 3 | 4 | function scanCom(){ 5 | if(serialArray.length){ 6 | serialArray = []; 7 | } 8 | serialPort.list(function (err, ports) { 9 | ports.forEach(function(port) { 10 | var thePort = { 11 | 'comName':port.comName, 12 | 'pnpId':port.pnpId, 13 | 'manufacturer':port.manufacturer 14 | }; 15 | if(port.comName.indexOf('USB') >= 0){ 16 | serialArray.push(thePort); 17 | } 18 | 19 | }); 20 | 21 | }); 22 | } 23 | scanCom(); 24 | setInterval(function () { 25 | scanCom(); 26 | },2000); 27 | 28 | module.exports = function() { 29 | return serialArray; 30 | } -------------------------------------------------------------------------------- /serial-webDebug/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /serial-webDebug/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 |

[web]串口调试工具

19 |
20 |
21 |

设备

22 | 28 |

波特率

29 | 36 |
  • 37 |
  • 38 |
    39 |
    40 | 41 | 42 | 43 | 44 | 45 |
    46 |
    47 |
    48 | 49 | 53 | 54 | 55 | --------------------------------------------------------------------------------