-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from montoyamoraga/main
restore classes Client and SerialPort from repo
- Loading branch information
Showing
2 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/** | ||
* @fileOverview Client object that gets created when new web socket client connects to server. Maintains SerialPort objects that the client subscribes to. | ||
* | ||
* @author Shawn Van Every | ||
* @author Jiwon Shin | ||
* | ||
* @requires NPM:serialport | ||
* @requires NPM:ws | ||
* @requires classes/SerialPort.js:SerialPort | ||
* */ | ||
|
||
let sp = require('serialport'); | ||
let SerialPort = require('./SerialPort'); | ||
let WebSocketServer = require('ws').Server; | ||
|
||
/** | ||
* Represents a web socket client. Maintains {@link SerialPort SerialPort} objects that the client subscribes to. | ||
*/ | ||
class Client { | ||
/** | ||
* create a web socket client | ||
* @constructor | ||
* @param {ws} ws - Web socket object | ||
* @property {SerialPort[]} serialPorts - list of subscribed {@link SerialPort SerialPort} objects | ||
* @property {string[]} serialPortsList - list of string names of subscribed {@link SerialPort SerialPort} objects. Used for checking whether duplicate serial port is requested to open. | ||
*/ | ||
constructor(ws) { | ||
this.LOGGING = true; | ||
|
||
//websocket object for this client | ||
this.ws = ws; | ||
//list of serial ports that this client has opened | ||
this.serialPorts = []; | ||
this.serialPortsList = []; | ||
} | ||
|
||
/** echo received message back to web client */ | ||
echo(msg) { | ||
this.sendit({ method: 'echo', data: msg }); | ||
} | ||
|
||
/** list all available serial ports and send it to the client*/ | ||
list() { | ||
let self = this; | ||
|
||
sp.list(function (err, ports) { | ||
let portNames = []; | ||
ports.forEach(function (port) { | ||
portNames.push(port.comName); | ||
}); | ||
|
||
self.sendit({ method: 'list', data: portNames }); | ||
}); | ||
} | ||
|
||
/** | ||
* add opened SerialPort object and its name | ||
* @param {SerialPort} port - SerialPort object opened by client | ||
* */ | ||
openSerial(port) { | ||
this.serialPortsList.push(port.serialPortName); | ||
this.serialPorts.push(port); | ||
} | ||
|
||
/** | ||
* write received data to subscribed serial ports. | ||
* @param {String} msg - received string data from client | ||
* */ | ||
write(msg) { | ||
for (let i = 0; i < this.serialPorts.length; i++) { | ||
this.serialPorts[i].serialPort.write(msg); | ||
} | ||
} | ||
|
||
/** | ||
* close client connection. Set serialPorts and serialPortsList array to null. | ||
*/ | ||
close() { | ||
//this needs to be updated per port | ||
//also with client-side library | ||
this.serialPorts = []; | ||
this.serialPortsList = []; | ||
|
||
//close message via sendit? | ||
//close ws? | ||
//this.sendit() | ||
} | ||
|
||
/** | ||
* console.log log messages when LOGGING == true | ||
* @function logit | ||
* @param {String} mess - String to log when LOGGING == true*/ | ||
logit(mess) { | ||
if (this.LOGGING) { | ||
console.log(mess); | ||
} | ||
} | ||
|
||
/** | ||
* send data via websocket to the client | ||
* @param {Object} toSend - JSON object received to be sent. Contains message method and data. | ||
*/ | ||
sendit(toSend) { | ||
let dataToSend = JSON.stringify(toSend); | ||
|
||
try { | ||
this.ws.send(dataToSend); | ||
} catch (error) { | ||
console.log('Error sending: ', error); | ||
} | ||
} | ||
} | ||
|
||
module.exports = Client; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
/** | ||
* @fileOverview SerialPort class that gets created when new serial port is opened. Maintains list of connected Client objects to forward data received from the serial port. | ||
* | ||
* @author Shawn Van Every | ||
* @author Jiwon Shin | ||
* | ||
* @requires NPM:serialport | ||
* */ | ||
|
||
let sp = require('serialport'); | ||
|
||
/** | ||
* Represents a serialport object. Maintains an array of {@link Client Client} objects subscribed to the serial port. | ||
* @see https://www.npmjs.com/package/serialport | ||
* */ | ||
class SerialPort { | ||
/** | ||
* creates a SerialPort object | ||
* @constructor | ||
* @param {serialport} serialport - serialport object | ||
* @param {Object} serialoptions - JSON object of options for the serialport object | ||
* @property {Boolean} LOGGING - sets whether to console.log detailed information | ||
* @property {String} serialPortName - name of the connected serialport | ||
* @property {Object} serialOptions - JSON array of options for the serialport | ||
* @property {Client[]} messageListeners - array of subscribed {@link Client Client} objects | ||
* */ | ||
constructor(serialport, serialoptions) { | ||
this.LOGGING = true; | ||
|
||
this.serialPortName = serialport; | ||
this.serialOptions = serialoptions; | ||
|
||
this.serialPort = null; | ||
|
||
this.messageListeners = []; | ||
|
||
this.openSerial(); | ||
|
||
this.logit(`initialize with serial port ${this.serialPortName}`); | ||
} | ||
|
||
/** | ||
* add a web client to messageListeners array | ||
* @param {Client} client - {@link Client Client} object subscribing to the SerialPort | ||
* */ | ||
addClient(client) { | ||
this.messageListeners.push(client); | ||
|
||
console.log( | ||
`total number of ${this.messageListeners.length} clients subscribed`, | ||
); | ||
//this.onMessage({method: 'clientNumber', data: this.messageListeners.length}); | ||
} | ||
|
||
/** | ||
* remove client from messageListeners array to unsubscribe client | ||
* @param {Client} client - {@link Client Client} object unsubscribing to the SerialPort | ||
* */ | ||
removeClient(client) { | ||
this.messageListeners = this.messageListeners.filter( | ||
(clientToRemove) => clientToRemove !== client, | ||
); | ||
console.log( | ||
`removeClient - total number of ${this.messageListeners.length} clients subscribed`, | ||
); | ||
} | ||
|
||
/** | ||
* Forwards message emitted by SerialPort events to the susbscribed clients in the messageListeners array | ||
* @param {Object} msg - JSON object containing message method and data | ||
* */ | ||
onMessage(msg) { | ||
this.messageListeners.forEach((client) => client.sendit(msg)); | ||
} | ||
|
||
/** | ||
* Opens SerialPort of serialPortName with serialOptions. | ||
* Sets serialport event listeners of method 'data', 'close' and 'error' and sends messages to the client via onMessage function | ||
* */ | ||
openSerial() { | ||
let self = this; | ||
|
||
if (!self.serialOptions.hasOwnProperty('autoOpen')) { | ||
self.serialOptions.autoOpen = false; | ||
} | ||
|
||
self.serialPort = new sp( | ||
self.serialPortName, | ||
self.serialOptions, | ||
function (err) { | ||
if (err) { | ||
console.log(err); | ||
self.onMessage({ method: 'error', data: err }); | ||
} | ||
}, | ||
); | ||
|
||
self.serialPort.on('data', function (incoming) { | ||
for (let i = 0; i < incoming.length; i++) { | ||
self.onMessage({ method: 'data', data: incoming[i] }); | ||
} | ||
}); | ||
|
||
self.serialPort.on('close', function (data) { | ||
self.logit('serialPort.on close'); | ||
self.onMessage({ method: 'close', data: data }); | ||
|
||
for (let i = 0; i < self.messageListeners.length; i++) { | ||
let serialIndex = self.messageListeners[ | ||
i | ||
].serialPortsList.indexOf(self.serialPortName); | ||
|
||
console.log( | ||
'need to take out ' + | ||
self.serialPortName + | ||
' from client at index ' + | ||
serialIndex, | ||
); | ||
|
||
self.messageListeners[i].serialPorts.splice(serialIndex, 1); | ||
self.messageListeners[i].serialPortsList.splice( | ||
serialIndex, | ||
1, | ||
); | ||
} | ||
|
||
self.closeSerial(); | ||
}); | ||
|
||
self.serialPort.on('error', function (data) { | ||
self.logit('serialPort.on error ' + data, true); | ||
self.onMessage({ method: 'error', data: data }); | ||
}); | ||
|
||
self.serialPort.open(function (err) { | ||
self.logit('serialPort.open'); | ||
|
||
if (err) { | ||
console.log(err); | ||
self.onMessage({ | ||
method: 'error', | ||
data: "Couldn't open port: " + this.serialport, | ||
}); | ||
} else { | ||
self.onMessage({ method: 'openserial', data: {} }); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* closes the serialport connection and sends message to the connected clients that the serialport is closed. | ||
* */ | ||
closeSerial() { | ||
let self = this; | ||
|
||
//need to emit back to client that this port was forcefully closed | ||
|
||
self.logit(`closeSerial for ${self.serialPortName}`); | ||
|
||
if ( | ||
self.serialPort != null && | ||
typeof self.serialPort === 'object' && | ||
self.serialPort.isOpen | ||
) { | ||
self.logit('serialPort != null && serialPort.isOpen so close'); | ||
self.logit('serialPort.flush, drain, close'); | ||
|
||
self.serialPort.flush(); | ||
self.serialPort.drain(); | ||
self.serialPort.close(function (error) { | ||
if (error) { | ||
self.onMessage({ method: 'error', data: error }); | ||
console.log(error); | ||
} | ||
}); | ||
|
||
self.onMessage({ | ||
method: 'close', | ||
data: `${self.serialPort} is closed`, | ||
}); | ||
|
||
self.serialPort = null; | ||
} | ||
|
||
// if (self.serialPort != null && typeof self.serialPort === "object" && self.serialPort.isOpen) { | ||
// self.logit("serialPort != null && serialPort.isOpen is true so serialPort = null"); | ||
// | ||
// self.serialPort = null; | ||
// } | ||
|
||
self.logit('serialPort closed'); | ||
} | ||
|
||
/** | ||
* console.log log messages when LOGGING == true | ||
* @function logit | ||
* @param {String} mess - String to log when LOGGING == true*/ | ||
logit(mess) { | ||
if (this.LOGGING) { | ||
console.log(mess); | ||
} | ||
} | ||
} | ||
|
||
module.exports = SerialPort; |