mirror of
https://github.com/karl0ss/orvibo-b25-server-kex.git
synced 2025-04-29 12:53:40 +01:00
commit
3bbdbcde9b
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.idea/
|
.idea/
|
||||||
node_modules
|
node_modules
|
||||||
|
.vscode/launch.json
|
||||||
|
12
CHANGELOG.md
Normal file
12
CHANGELOG.md
Normal file
@ -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
|
86
Docker.js
Normal file
86
Docker.js
Normal file
@ -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<arr.length; i+=2) {
|
||||||
|
let o = {};
|
||||||
|
o.uid = arr[i].split(':')[1];
|
||||||
|
o.name = arr[i+1].split(':')[1];
|
||||||
|
pairs.push(o);
|
||||||
|
}
|
||||||
|
return pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a settings object to pass PK key and map sockets to names
|
||||||
|
const settings = {
|
||||||
|
LOG_PACKET: true, //Show incoming packet data from the socket
|
||||||
|
ORVIBO_KEY: process.env.orviboPK,
|
||||||
|
plugInfo : [
|
||||||
|
createArray(process.env.plugArray)
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let orvibo = new Orvibo(settings);
|
||||||
|
// When a socket first connects and initiates the handshake it will emit the connected event with the uid of the socket;
|
||||||
|
orvibo.on('plugConnected', ({uid, name}) => {
|
||||||
|
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}`)
|
||||||
|
});
|
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@ -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" ]
|
56
Orvibo.js
56
Orvibo.js
@ -5,20 +5,21 @@ const Utils = require('./Utils');
|
|||||||
const Settings = require('./OrviboSettings');
|
const Settings = require('./OrviboSettings');
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
|
let logger = console;
|
||||||
|
|
||||||
let ORVIBO_KEY = Settings.ORVIBO_KEY;
|
let ORVIBO_KEY = Settings.ORVIBO_KEY;
|
||||||
let LOG_PACKET = Settings.LOG_PACKET;
|
let LOG_PACKET = Settings.LOG_PACKET;
|
||||||
let PLUG_INFO = Settings.plugInfo;
|
let PLUG_INFO = Settings.plugInfo;
|
||||||
|
|
||||||
const Orvibo = function(userSettings) {
|
const Orvibo = function(userSettings = {}) {
|
||||||
// Allow user to pass in settings
|
// Allow user to pass in settings
|
||||||
if (userSettings != null) {
|
if('ORVIBO_KEY' in userSettings) ORVIBO_KEY = userSettings.ORVIBO_KEY;
|
||||||
ORVIBO_KEY = userSettings.ORVIBO_KEY;
|
if('plugInfo' in userSettings) PLUG_INFO = userSettings.plugInfo;
|
||||||
LOG_PACKET = userSettings.LOG_PACKET;
|
if('PLUG_INFO' in userSettings) PLUG_INFO = userSettings.PLUG_INFO;
|
||||||
PLUG_INFO = userSettings.plugInfo;
|
if('LOG_PACKET' in userSettings) LOG_PACKET = userSettings.LOG_PACKET;
|
||||||
}
|
|
||||||
|
|
||||||
if (ORVIBO_KEY === '') {
|
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);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -75,6 +76,7 @@ let handshakeHandler = function(plugPacket, socket, socketData) {
|
|||||||
name: getNameForUid(uid)
|
name: getNameForUid(uid)
|
||||||
});
|
});
|
||||||
respondAndSetData(pkData, socket, PacketBuilder.handshakePacket);
|
respondAndSetData(pkData, socket, PacketBuilder.handshakePacket);
|
||||||
|
logger.log(`Connected ${pkData.uid} name = ${pkData.name}`);
|
||||||
this.emit('plugConnected', {uid: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()
|
uid: plugPacket.getUid()
|
||||||
});
|
});
|
||||||
respondAndSetData(pkData, socket, PacketBuilder.heartbeatPacket);
|
respondAndSetData(pkData, socket, PacketBuilder.heartbeatPacket);
|
||||||
|
logger.log(`Plug ${pkData.name} ${pkData.uid} sent heartbeat`);
|
||||||
this.emit('gotHeartbeat', {uid:pkData.uid, name: pkData.name});
|
this.emit('gotHeartbeat', {uid:pkData.uid, name: pkData.name});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,6 +97,7 @@ let stateUpdateHandler = function(plugPacket, socket, socketData) {
|
|||||||
state: plugPacket.getValue1()
|
state: plugPacket.getValue1()
|
||||||
});
|
});
|
||||||
respondAndSetData(pkData, socket, PacketBuilder.comfirmStatePacket);
|
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});
|
this.emit('plugStateUpdated', {uid:pkData.uid, state: pkData.state, name: pkData.name});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,7 +129,7 @@ Orvibo.prototype.startServer = function() {
|
|||||||
let self = this;
|
let self = this;
|
||||||
let handlers = this.handlers();
|
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) {
|
this.server = net.createServer(function(socket) {
|
||||||
|
|
||||||
@ -139,17 +143,22 @@ Orvibo.prototype.startServer = function() {
|
|||||||
let plugPacket = new Packet(data);
|
let plugPacket = new Packet(data);
|
||||||
|
|
||||||
if (!plugPacket.validCRC()) {
|
if (!plugPacket.validCRC()) {
|
||||||
console.log('Got invalid CRC');
|
logger.log('Got invalid CRC');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugPacket.packetTypeText() === 'pk') {
|
try {
|
||||||
plugPacket.processPacket(ORVIBO_KEY);
|
if (plugPacket.packetTypeText() === 'pk') {
|
||||||
} else {
|
plugPacket.processPacket(ORVIBO_KEY);
|
||||||
plugPacket.processPacket(socketData.encryptionKey);
|
} 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()];
|
let handler = handlers[plugPacket.getCommand()];
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
@ -161,14 +170,15 @@ Orvibo.prototype.startServer = function() {
|
|||||||
|
|
||||||
socket.on('end', function () {
|
socket.on('end', function () {
|
||||||
let pkData = getData(socket.id);
|
let pkData = getData(socket.id);
|
||||||
|
logger.log(`Plug ${pkData.uid} - ${pkData.name} disconnected`);
|
||||||
self.emit('plugDisconnected', {uid: pkData.uid, name: pkData.name});
|
self.emit('plugDisconnected', {uid: pkData.uid, name: pkData.name});
|
||||||
delete packetData[socket.id];
|
delete packetData[socket.id];
|
||||||
plugConnections.splice(plugConnections.indexOf(socket), 1);
|
plugConnections.splice(plugConnections.indexOf(socket), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
console.log(err);
|
logger.log(err);
|
||||||
console.log('error with socket ' + socket.id);
|
logger.log(`Plug ${socket.id} - ${socket.name} disconnected with error`);
|
||||||
self.emit('plugDisconnectedWithError', getData(socket.id));
|
self.emit('plugDisconnectedWithError', getData(socket.id));
|
||||||
delete packetData[socket.id];
|
delete packetData[socket.id];
|
||||||
plugConnections.splice(plugConnections.indexOf(socket), 1);
|
plugConnections.splice(plugConnections.indexOf(socket), 1);
|
||||||
@ -190,7 +200,7 @@ Orvibo.prototype.toggleSocket = function(uid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (socketId === null) {
|
if (socketId === null) {
|
||||||
console.log('Could not find socket ' + uid);
|
logger.log('Could not find socket ' + uid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let socket = plugConnections.find(s => s.id === socketId);
|
let socket = plugConnections.find(s => s.id === socketId);
|
||||||
@ -209,11 +219,11 @@ Orvibo.prototype.toggleSocket = function(uid) {
|
|||||||
socket.write(packet);
|
socket.write(packet);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Can not find socket ');
|
logger.log('Can not find socket ');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Orvibo.prototype.getConnectedSocket = function() {
|
Orvibo.prototype.getConnectedSockets = function() {
|
||||||
let sockets = [];
|
let sockets = [];
|
||||||
for (const key of Object.keys(packetData)) {
|
for (const key of Object.keys(packetData)) {
|
||||||
let socketData = getData(key);
|
let socketData = getData(key);
|
||||||
@ -227,4 +237,10 @@ Orvibo.prototype.getConnectedSocket = function() {
|
|||||||
return sockets;
|
return sockets;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Orvibo;
|
Orvibo.prototype.getConnectedSocket = Orvibo.prototype.getConnectedSockets;
|
||||||
|
|
||||||
|
Orvibo.prototype.setLogger = function(newLogger) {
|
||||||
|
logger = newLogger;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Orvibo;
|
||||||
|
@ -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 (US/CAD) | S25 | @wichopy |
|
||||||
| Orvibo Smart Socket (UK/GB) | B25UK | @valchonedelchev |
|
| 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
|
## Contributing
|
||||||
|
|
||||||
I'm more than happy for other people to contribute to this library just send a pull request.
|
I'm more than happy for other people to contribute to this library just send a pull request.
|
||||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "orvibo-b25-server",
|
"name": "orvibo-b25-server",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "orvibo-b25-server",
|
"name": "orvibo-b25-server",
|
||||||
"version": "1.0.1",
|
"version": "1.2.0",
|
||||||
"description": "A server to control the Orvibo B25 range of smart sockets",
|
"description": "A server to control the Orvibo B25 range of smart sockets",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user