// // serialserver.js // WebSocket serial server // // Neil Gershenfeld // (c) Massachusetts Institute of Technology 2016 // // This work may be reproduced, modified, distributed, performed, and // displayed for any purpose, but must acknowledge the mods // project. Copyright is retained and must be preserved. The work is // provided as is; no warranty is provided, and users accept all // liability. // // check command line // if (process.argv.length < 4) { console.log("command line: node serialserver.js client_address server_port") process.exit(-1) } // // start server // var client_address = process.argv[2] var server_port = process.argv[3] console.log("listening for connection from client address "+client_address+" on server port "+server_port) var SerialPort = require('serialport') var port = null var WebSocketServer = require('ws').Server wss = new WebSocketServer({port:server_port}) // // handle connection // wss.on('connection',function(ws) { // // check address // if (ws._socket.remoteAddress != client_address) { console.log("connection rejected from "+ws._socket.remoteAddress) ws.send('socket closed') ws.close() } else { console.log("connection accepted from "+ws._socket.remoteAddress) } // // handle messages // var cancel ws.on("message",function(message) { var msg = JSON.parse(message) // // open port // if (msg.type == 'open') { var device = msg.device var baud = parseInt(msg.baud) var flow = msg.flow console.log('open '+device+' at '+baud+' flow '+flow) if (flow == 'none') port = new SerialPort(device,{baudRate:baud}) else if (flow == 'rtscts') port = new SerialPort(device,{baudRate:baud,rtscts:true}) port.on('open',function() { ws.send('serial port opened') if (flow == 'dsrdtr') { port.set({dsr:true,dtr:true}) port.set({rts:false,cts:false}) } }) port.on('error',function(err) { ws.send(err.message) }) port.on('data',function(data) { ws.send(data.toString('binary')) }) } // // close port // else if (msg.type == 'close') { var device = msg.device console.log('close '+device) ws.send('serial port closed') port.close() port = null } // // send string // else if (msg.type == 'string') { console.log(msg.string) port.write(msg.string,function(){ port.drain(function(err){ if (err) ws.send(err.message) }) }) } // // send command // else if (msg.type == 'command') { console.log(msg.contents) port.write(msg.contents,function(){ port.drain(function(err){ if (err) ws.send(err.message) else ws.send('done') }) }) } // // cancel job // if (msg.type == 'cancel') { cancel = true } // // send file // else if (msg.type == 'file') { var count = 0 console.log('writing '+msg.name+' length '+msg.contents.length) cancel = false write_char() // // character writer // function write_char() { // // cancel // if (cancel) { console.log('cancel') ws.send('cancel') } // // continue // else { port.write(msg.contents[count],function(){ port.drain(function(err){ if (err) ws.send('error '+err.message) else { ws.send((count+1)+'/'+msg.contents.length) count += 1 if (count < msg.contents.length) write_char() else { console.log('done') ws.send('done') } } }) }) } } } }) // // close // ws.on("close",function() { console.log("connection closed") if (port != null) port.close() port = null }) })