diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..93f1361 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log diff --git a/.gitignore b/.gitignore index 7e087fe..b051c7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ node_modules +.vscode/launch.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..79cf5ca --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# CHANGELOG + +## 1.1.0 + +* Add try-catch around packet decryption to guard against a service crash resulting from an occasional packet decryption error. +* Pluralize getConnectedSocket + alias previous name +* Enhance settings handling +* Enhance Orvibo logging + +## 1.0.0 + +Initial release diff --git a/Docker.js b/Docker.js new file mode 100644 index 0000000..5e5abde --- /dev/null +++ b/Docker.js @@ -0,0 +1,86 @@ +const Orvibo = require('./Orvibo'); +const http = require('http'); +const url = require('url'); + +const httpPort = 3000; + +const createArray = str => { + // split on each comma + const arr = str.split(','); + // put back elements by pairs + const pairs = []; + for (let i=0; i { + console.log(`Connected ${uid} name = ${name}`); +}); + +// If the socket state is updated this event will fire +orvibo.on('plugStateUpdated', ({uid, state , name}) => { + console.log(`Plug ${name} ${uid} updated state ${state}`); +}); + +// The plug sends a hearbeat to let the server know it's still alive +orvibo.on('gotHeartbeat', ({uid, name}) => { + console.log(`Plug ${name} ${uid} sent heartbeat`); +}); + +// Called when the plug disconnects +orvibo.on('plugDisconnected', ({uid, name }) => { + console.log(`Plug ${uid} - ${name} disconnected`); +}); + +// Called when the plug disconnects with an error ie it's been unplugged +orvibo.on('plugDisconnectedWithError', ({uid, name }) => { + console.log(`Plug ${uid} - ${name} disconnected with error`); +}); + + + +// Start the Orvibo socket server +orvibo.startServer(); + +// Create a basic example HTTP server +// If there are no parameters it will return the uid, state, modelId and name of the socket +// You can then use the uid to toggle the state of the switch like +// http://localhost:3000?uid=5dcf7ff76e7a + +const requestHandler = (request, response) => { + response.writeHead(200, {'Content-Type': 'application/json'}); + let q = url.parse(request.url, true).query; + if (q.uid != null) { + orvibo.toggleSocket(q.uid); + } + + // Get all currently connected sockets, their names and states + // let sockets = orvibo.getConnectedSocket(); + let sockets = [{"name":"3D Printer","state":1,"uid":"5ccf7f22fba4","modelId":"f8b11bed724647e98bd07a66dca6d5b6"}] + + response.end(JSON.stringify(sockets)); +}; + +const httpServer = http.createServer(requestHandler); + +httpServer.listen(httpPort, (err) => { + if (err) { + return console.log('something bad happened', err) + } + console.log(`http server is listening on ${httpPort}`) +}); diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f16a057 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM node:10 + +WORKDIR /usr/src/app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +EXPOSE 3000 10001 + +CMD [ "node", "Docker.js" ] diff --git a/Orvibo.js b/Orvibo.js index 0de50c1..dbc1cb4 100644 --- a/Orvibo.js +++ b/Orvibo.js @@ -5,20 +5,21 @@ const Utils = require('./Utils'); const Settings = require('./OrviboSettings'); const EventEmitter = require('events').EventEmitter; +let logger = console; + let ORVIBO_KEY = Settings.ORVIBO_KEY; let LOG_PACKET = Settings.LOG_PACKET; let PLUG_INFO = Settings.plugInfo; -const Orvibo = function(userSettings) { +const Orvibo = function(userSettings = {}) { // Allow user to pass in settings - if (userSettings != null) { - ORVIBO_KEY = userSettings.ORVIBO_KEY; - LOG_PACKET = userSettings.LOG_PACKET; - PLUG_INFO = userSettings.plugInfo; - } + if('ORVIBO_KEY' in userSettings) ORVIBO_KEY = userSettings.ORVIBO_KEY; + if('plugInfo' in userSettings) PLUG_INFO = userSettings.plugInfo; + if('PLUG_INFO' in userSettings) PLUG_INFO = userSettings.PLUG_INFO; + if('LOG_PACKET' in userSettings) LOG_PACKET = userSettings.LOG_PACKET; if (ORVIBO_KEY === '') { - console.log('Please pass Orvibo PK key details via the constructor or add to OrviboSettings.js file. See Readme'); + logger.log('Please pass Orvibo PK key details via the constructor or add to OrviboSettings.js file. See Readme'); process.exit(1); } }; @@ -75,6 +76,7 @@ let handshakeHandler = function(plugPacket, socket, socketData) { name: getNameForUid(uid) }); respondAndSetData(pkData, socket, PacketBuilder.handshakePacket); + logger.log(`Connected ${pkData.uid} name = ${pkData.name}`); this.emit('plugConnected', {uid:pkData.uid, name: pkData.name}); }; @@ -84,6 +86,7 @@ let heartbeatHandler = function(plugPacket, socket, socketData) { uid: plugPacket.getUid() }); respondAndSetData(pkData, socket, PacketBuilder.heartbeatPacket); + logger.log(`Plug ${pkData.name} ${pkData.uid} sent heartbeat`); this.emit('gotHeartbeat', {uid:pkData.uid, name: pkData.name}); }; @@ -94,6 +97,7 @@ let stateUpdateHandler = function(plugPacket, socket, socketData) { state: plugPacket.getValue1() }); respondAndSetData(pkData, socket, PacketBuilder.comfirmStatePacket); + logger.log(`Plug ${pkData.name} ${pkData.uid} updated state ${pkData.state}`); this.emit('plugStateUpdated', {uid:pkData.uid, state: pkData.state, name: pkData.name}); }; @@ -125,7 +129,7 @@ Orvibo.prototype.startServer = function() { let self = this; let handlers = this.handlers(); - console.log(`Starting server Orvibo socket server on port ${port}`); + logger.log(`Starting server Orvibo socket server on port ${port}`); this.server = net.createServer(function(socket) { @@ -139,17 +143,22 @@ Orvibo.prototype.startServer = function() { let plugPacket = new Packet(data); if (!plugPacket.validCRC()) { - console.log('Got invalid CRC'); + logger.log('Got invalid CRC'); return; } - if (plugPacket.packetTypeText() === 'pk') { - plugPacket.processPacket(ORVIBO_KEY); - } else { - plugPacket.processPacket(socketData.encryptionKey); + try { + if (plugPacket.packetTypeText() === 'pk') { + plugPacket.processPacket(ORVIBO_KEY); + } else { + plugPacket.processPacket(socketData.encryptionKey); + } + } catch(err) { + logger.log('Failed to parse packet: ' + err); + return; } - LOG_PACKET && plugPacket.logPacket("Socket -> "); + LOG_PACKET && plugPacket.logPacket('Socket -> '); let handler = handlers[plugPacket.getCommand()]; if (handler != null) { @@ -161,14 +170,15 @@ Orvibo.prototype.startServer = function() { socket.on('end', function () { let pkData = getData(socket.id); + logger.log(`Plug ${pkData.uid} - ${pkData.name} disconnected`); self.emit('plugDisconnected', {uid: pkData.uid, name: pkData.name}); delete packetData[socket.id]; plugConnections.splice(plugConnections.indexOf(socket), 1); }); socket.on('error', (err) => { - console.log(err); - console.log('error with socket ' + socket.id); + logger.log(err); + logger.log(`Plug ${socket.id} - ${socket.name} disconnected with error`); self.emit('plugDisconnectedWithError', getData(socket.id)); delete packetData[socket.id]; plugConnections.splice(plugConnections.indexOf(socket), 1); @@ -190,7 +200,7 @@ Orvibo.prototype.toggleSocket = function(uid) { } } if (socketId === null) { - console.log('Could not find socket ' + uid); + logger.log('Could not find socket ' + uid); return; } let socket = plugConnections.find(s => s.id === socketId); @@ -209,11 +219,11 @@ Orvibo.prototype.toggleSocket = function(uid) { socket.write(packet); } else { - console.log('Can not find socket '); + logger.log('Can not find socket '); } }; -Orvibo.prototype.getConnectedSocket = function() { +Orvibo.prototype.getConnectedSockets = function() { let sockets = []; for (const key of Object.keys(packetData)) { let socketData = getData(key); @@ -227,4 +237,10 @@ Orvibo.prototype.getConnectedSocket = function() { return sockets; }; -module.exports = Orvibo; \ No newline at end of file +Orvibo.prototype.getConnectedSocket = Orvibo.prototype.getConnectedSockets; + +Orvibo.prototype.setLogger = function(newLogger) { + logger = newLogger; +}; + +module.exports = Orvibo; diff --git a/README.md b/README.md index 97b0478..d4f9208 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,15 @@ A list of Orvibo devices, confirmed by contributors, that work with this project | Orvibo Smart Socket (US/CAD) | S25 | @wichopy | | Orvibo Smart Socket (UK/GB) | B25UK | @valchonedelchev | +## Docker + +I have extened this project to also run in a docker container. + +PK and PlugArray can be passed in via enviroment variables. + +orviboPK = 'xxxxx' +plugArray = 'uid:MACADDRESS,name:PRINTERNAME' + ## Contributing I'm more than happy for other people to contribute to this library just send a pull request. diff --git a/package-lock.json b/package-lock.json index 2830cde..97d2c26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "orvibo-b25-server", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6069dcb..87fcbb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orvibo-b25-server", - "version": "1.0.1", + "version": "1.2.0", "description": "A server to control the Orvibo B25 range of smart sockets", "main": "index.js", "scripts": {