mirror of
https://github.com/karl0ss/orvibo-b25-server-kex.git
synced 2025-04-29 12:53:40 +01:00
Inital commit of Orvibo socket server code
This commit is contained in:
parent
196493e7e2
commit
4ad59b2a46
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea/
|
||||||
|
node_modules
|
64
Example.js
Normal file
64
Example.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
const Orvibo = require('./Orvibo');
|
||||||
|
const http = require('http');
|
||||||
|
const url = require('url');
|
||||||
|
|
||||||
|
const httpPort = 3000;
|
||||||
|
|
||||||
|
let orvbio = new Orvibo();
|
||||||
|
|
||||||
|
// When a socket first connects and initiates the handshake it will emit the connected event with the uid of the socket;
|
||||||
|
orvbio.on('plugConnected', ({uid, name}) => {
|
||||||
|
console.log(`Connected ${uid} name = ${name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the socket state is updated this event will fire
|
||||||
|
orvbio.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
|
||||||
|
orvbio.on('gotHeartbeat', ({uid, state , name}) => {
|
||||||
|
console.log(`Plug ${name} ${uid} sent heartbeat`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Called when the plug disconnects
|
||||||
|
orvbio.on('plugDisconnected', ({uid, name }) => {
|
||||||
|
console.log(`Plug ${uid} - ${name} disconnected`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Called when the plug disconnects with an error ie it's been unplugged
|
||||||
|
orvbio.on('plugDisconnectedWithError', ({uid, name }) => {
|
||||||
|
console.log(`Plug ${uid} - ${name} disconnected with error`);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Start the Orvibo socket server
|
||||||
|
orvbio.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) {
|
||||||
|
orvbio.toggleSocket(q.uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all currently connected sockets, their names and states
|
||||||
|
let sockets = orvbio.getConnectedSocket();
|
||||||
|
|
||||||
|
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}`)
|
||||||
|
});
|
226
Orvibo.js
Normal file
226
Orvibo.js
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
const net = require('net');
|
||||||
|
const util = require('util');
|
||||||
|
const Packet = require('./OrviboPacket');
|
||||||
|
const PacketBuilder = require('./PacketBuilder');
|
||||||
|
const Utils = require('./Utils');
|
||||||
|
const Settings = require('./OrviboSettings');
|
||||||
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
|
const ORVIBO_KEY = Settings.ORVIBO_KEY;
|
||||||
|
const LOG_PACKET = Settings.LOG_PACKET;
|
||||||
|
|
||||||
|
if (ORVIBO_KEY === '') {
|
||||||
|
console.log('Please add Orvibo PK key to OrviboSettings.js file. See Readme');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Orvibo = function() {};
|
||||||
|
|
||||||
|
Object.assign(Orvibo.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
|
let HEARTBEAT = 32;
|
||||||
|
let HELLO = 0;
|
||||||
|
let HANDSHAKE = 6;
|
||||||
|
let STATE_UPDATE = 42;
|
||||||
|
let STATE_UPDATE_CONFIRM = 15;
|
||||||
|
let UNKNOWN_CMD = 'UNKNOWN_CMD';
|
||||||
|
|
||||||
|
let port = 10001;
|
||||||
|
let bindHost = '0.0.0.0';
|
||||||
|
|
||||||
|
console.log(`Starting server Orvibo socket server on port ${port}`);
|
||||||
|
|
||||||
|
let plugConnections = [];
|
||||||
|
let packetData = {};
|
||||||
|
|
||||||
|
// Put your smart socket data here and it will be matched to the uid
|
||||||
|
let plugInfo = Settings.plugInfo;
|
||||||
|
|
||||||
|
let getNameForUid = (uid) => {
|
||||||
|
let item = plugInfo.find(item => item.uid === uid);
|
||||||
|
return item != null ? item.name : 'unknown';
|
||||||
|
};
|
||||||
|
|
||||||
|
let getData = (id) => {
|
||||||
|
return packetData[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
let setData = (id, data) => {
|
||||||
|
packetData[id] = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
let respondAndSetData = (data, socket, packetFunction) => {
|
||||||
|
setData(socket.id, data);
|
||||||
|
socket.write(packetFunction(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
let helloHandler = (plugPacket, socket) => {
|
||||||
|
let pkData = {
|
||||||
|
serial: plugPacket.getSerial(),
|
||||||
|
encryptionKey: Utils.generateRandomTextValue(16),
|
||||||
|
id: Utils.generateRandomHexValue(32),
|
||||||
|
modelId: plugPacket.getModelId(),
|
||||||
|
};
|
||||||
|
respondAndSetData(pkData, socket, PacketBuilder.helloPacket);
|
||||||
|
};
|
||||||
|
|
||||||
|
let handshakeHandler = function(plugPacket, socket, socketData) {
|
||||||
|
let uid = plugPacket.getUid();
|
||||||
|
let pkData = Object.assign({}, socketData, {
|
||||||
|
serial: plugPacket.getSerial(),
|
||||||
|
uid,
|
||||||
|
name: getNameForUid(uid)
|
||||||
|
});
|
||||||
|
respondAndSetData(pkData, socket, PacketBuilder.handshakePacket);
|
||||||
|
this.emit('plugConnected', {uid:pkData.uid, name: pkData.name});
|
||||||
|
};
|
||||||
|
|
||||||
|
let heartbeatHandler = function(plugPacket, socket, socketData) {
|
||||||
|
let pkData = Object.assign({}, socketData, {
|
||||||
|
serial: plugPacket.getSerial(),
|
||||||
|
uid: plugPacket.getUid()
|
||||||
|
});
|
||||||
|
respondAndSetData(pkData, socket, PacketBuilder.heartbeatPacket);
|
||||||
|
this.emit('gotHeartbeat', {uid:pkData.uid, name: pkData.name});
|
||||||
|
};
|
||||||
|
|
||||||
|
let stateUpdateHandler = function(plugPacket, socket, socketData) {
|
||||||
|
let pkData = Object.assign({}, socketData, {
|
||||||
|
serial: plugPacket.getSerial(),
|
||||||
|
uid: plugPacket.getUid(),
|
||||||
|
state: plugPacket.getValue1()
|
||||||
|
});
|
||||||
|
respondAndSetData(pkData, socket, PacketBuilder.comfirmStatePacket);
|
||||||
|
this.emit('plugStateUpdated', {uid:pkData.uid, state: pkData.state, name: pkData.name});
|
||||||
|
};
|
||||||
|
|
||||||
|
let stateConfirmHandler = function() {
|
||||||
|
// Do nothing at this stage
|
||||||
|
};
|
||||||
|
|
||||||
|
let unknownCmdHandler = function(plugPacket, socket, socketData) {
|
||||||
|
let pkData = Object.assign({}, socketData, {
|
||||||
|
serial: plugPacket.getSerial(),
|
||||||
|
uid: plugPacket.getUid(),
|
||||||
|
});
|
||||||
|
respondAndSetData(pkData, socket, PacketBuilder.defaultPacket);
|
||||||
|
};
|
||||||
|
|
||||||
|
Orvibo.prototype.handlers = function() {
|
||||||
|
return {
|
||||||
|
[HELLO]: helloHandler.bind(this),
|
||||||
|
[HANDSHAKE]: handshakeHandler.bind(this),
|
||||||
|
[HEARTBEAT]: heartbeatHandler.bind(this),
|
||||||
|
[STATE_UPDATE]: stateUpdateHandler.bind(this),
|
||||||
|
[STATE_UPDATE_CONFIRM] : stateConfirmHandler,
|
||||||
|
[UNKNOWN_CMD]: unknownCmdHandler.bind(this)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Orvibo.prototype.startServer = function() {
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
let handlers = this.handlers();
|
||||||
|
|
||||||
|
this.server = net.createServer(function(socket) {
|
||||||
|
|
||||||
|
socket.id = Utils.generateRandomTextValue(16);
|
||||||
|
socket.setKeepAlive(true, 10000);
|
||||||
|
plugConnections.push(socket);
|
||||||
|
|
||||||
|
socket.on('data', function (data) {
|
||||||
|
|
||||||
|
let socketData = getData(socket.id);
|
||||||
|
let plugPacket = new Packet(data);
|
||||||
|
|
||||||
|
if (!plugPacket.validCRC()) {
|
||||||
|
console.log('Got invalid CRC');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugPacket.packetTypeText() === 'pk') {
|
||||||
|
plugPacket.processPacket(ORVIBO_KEY);
|
||||||
|
} else {
|
||||||
|
plugPacket.processPacket(socketData.encryptionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_PACKET && plugPacket.logPacket("Socket -> ");
|
||||||
|
|
||||||
|
let handler = handlers[plugPacket.getCommand()];
|
||||||
|
if (handler != null) {
|
||||||
|
handler(plugPacket, socket, socketData);
|
||||||
|
} else {
|
||||||
|
handlers[UNKNOWN_CMD](plugPacket, socket, socketData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('end', function () {
|
||||||
|
let pkData = getData(socket.id);
|
||||||
|
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);
|
||||||
|
self.emit('plugDisconnectedWithError', getData(socket.id));
|
||||||
|
delete packetData[socket.id];
|
||||||
|
plugConnections.splice(plugConnections.indexOf(socket), 1);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.server.listen(port, bindHost);
|
||||||
|
};
|
||||||
|
|
||||||
|
Orvibo.prototype.toggleSocket = function(uid) {
|
||||||
|
|
||||||
|
let socketId = null;
|
||||||
|
for (const key of Object.keys(packetData)) {
|
||||||
|
if (packetData[key].uid === uid) {
|
||||||
|
socketId = key;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (socketId === null) {
|
||||||
|
console.log('Could not find socket ' + uid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let socket = plugConnections.find(s => s.id === socketId);
|
||||||
|
if (socket != null) {
|
||||||
|
let socketData = getData(socketId);
|
||||||
|
let data = Object.assign({}, socketData,{
|
||||||
|
state: socketData.state === 1 ? 0 : 1,
|
||||||
|
serial: Utils.generateRandomNumber(8),
|
||||||
|
clientSessionId: socketData.clientSessionId ? socketData.clientSessionId : Utils.generateRandomHexValue(32),
|
||||||
|
deviceId: socketData.deviceId ? socketData.deviceId : Utils.generateRandomHexValue(32),
|
||||||
|
});
|
||||||
|
|
||||||
|
setData(socket.id, data);
|
||||||
|
|
||||||
|
let packet = PacketBuilder.updatePacket(data);
|
||||||
|
socket.write(packet);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log('Can not find socket ');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Orvibo.prototype.getConnectedSocket = function() {
|
||||||
|
let sockets = [];
|
||||||
|
for (const key of Object.keys(packetData)) {
|
||||||
|
let socketData = getData(key);
|
||||||
|
sockets.push({
|
||||||
|
name: socketData.name,
|
||||||
|
state: socketData.state,
|
||||||
|
uid: socketData.uid,
|
||||||
|
modelId: socketData.modelId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return sockets;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Orvibo;
|
71
OrviboPacket.js
Normal file
71
OrviboPacket.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
const crc32 = require('buffer-crc32');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
let pkt = function(packetBuffer) {
|
||||||
|
this.magic = packetBuffer.slice(0,2);
|
||||||
|
this.packetLength = packetBuffer.slice(2,4);
|
||||||
|
this.packetType = packetBuffer.slice(4,6);
|
||||||
|
this.crc32 = packetBuffer.slice(6,10);
|
||||||
|
this.packetId = packetBuffer.slice(10,42);
|
||||||
|
this.payload = packetBuffer.slice(42, packetBuffer.length);
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.logPacket = function(type) {
|
||||||
|
let output = {
|
||||||
|
PacketId : this.packetIdText(),
|
||||||
|
Payload : this.payloadJSON
|
||||||
|
};
|
||||||
|
console.log(type, JSON.stringify(this.payloadJSON));
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getCommand = function() {
|
||||||
|
return this.payloadJSON.cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getSerial = function() {
|
||||||
|
return this.payloadJSON.serial;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getUid = function() {
|
||||||
|
return this.payloadJSON.uid;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getValue1 = function() {
|
||||||
|
return this.payloadJSON.value1;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getModelId = function() {
|
||||||
|
return this.payloadJSON.modelId;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.processPacket = function(key) {
|
||||||
|
this.payloadJSON = this.decodeJSON(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.getKeyValue = function() {
|
||||||
|
return this.payloadJSON.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.validCRC = function() {
|
||||||
|
return crc32(this.payload).toString('hex') === this.crc32.toString('hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.packetTypeText = function() {
|
||||||
|
return this.packetType.toString('ascii');
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.packetIdText = function() {
|
||||||
|
return this.packetId.toString('ascii');
|
||||||
|
};
|
||||||
|
|
||||||
|
pkt.prototype.decodeJSON = function(key) {
|
||||||
|
let decipher = crypto.createDecipheriv('aes-128-ecb', key, '');
|
||||||
|
decipher.setAutoPadding(true);
|
||||||
|
let decrypted = decipher.update(this.payload.toString('hex'), 'hex', 'utf8');
|
||||||
|
decrypted += decipher.final('utf8');
|
||||||
|
// Sometimes there are bad chars on the end of the JSON so check here
|
||||||
|
decrypted = decrypted.substring(0, decrypted.indexOf('}') + 1);
|
||||||
|
return JSON.parse(decrypted);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = pkt;
|
13
OrviboSettings.js
Normal file
13
OrviboSettings.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Settings/Config store for orvibo socket server
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
LOG_PACKET: false,
|
||||||
|
ORVIBO_KEY: '', // put your PK key here as plain text
|
||||||
|
plugInfo : [
|
||||||
|
// Add uid and a name so you can easily identify the connected sockets
|
||||||
|
{
|
||||||
|
uid :'53dd7fe74de7',
|
||||||
|
name: "Lamp in Kitchen"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
182
PacketBuilder.js
Normal file
182
PacketBuilder.js
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
const crc32 = require('buffer-crc32');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const Settings = require('./orviboSettings');
|
||||||
|
|
||||||
|
const ORVIBO_KEY = Settings.ORVIBO_KEY;
|
||||||
|
|
||||||
|
let Packet = {
|
||||||
|
encryptionKey : ORVIBO_KEY,
|
||||||
|
magic: new Buffer("6864", 'hex'),
|
||||||
|
build: function () {
|
||||||
|
let packetId = new Buffer(this.id, 'ascii');
|
||||||
|
let payload = encodePayload(JSON.stringify(this.json), this.encryptionKey);
|
||||||
|
let crc = crc32(payload);
|
||||||
|
let length = getLength([this.magic, this.packetType, packetId, crc, payload], 2); // Extra 2 for the length field itself
|
||||||
|
return Buffer.concat([this.magic, length, this.packetType, crc, packetId, payload]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let PKPacket = Object.assign({}, Packet, {
|
||||||
|
packetType: new Buffer('pk', 'ascii'),
|
||||||
|
});
|
||||||
|
|
||||||
|
let DKPacket = Object.assign({}, Packet, {
|
||||||
|
packetType: new Buffer('dk', 'ascii'),
|
||||||
|
});
|
||||||
|
|
||||||
|
let helloPacket = function({ serial, encryptionKey, id }) {
|
||||||
|
let json = {
|
||||||
|
cmd: 0,
|
||||||
|
status: 0,
|
||||||
|
serial: serial,
|
||||||
|
key: encryptionKey
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(PKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
let handshakePacket = function({ serial, encryptionKey, id }) {
|
||||||
|
|
||||||
|
let json = {
|
||||||
|
cmd: 6,
|
||||||
|
status:0,
|
||||||
|
serial: serial
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(DKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id,
|
||||||
|
encryptionKey, encryptionKey
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
let heartbeatPacket = function({serial, uid, encryptionKey, id}) {
|
||||||
|
let json = {
|
||||||
|
cmd: 32,
|
||||||
|
status:0,
|
||||||
|
serial: serial,
|
||||||
|
uid: uid,
|
||||||
|
utc: new Date().getTime()
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(DKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id,
|
||||||
|
encryptionKey, encryptionKey
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
let comfirmStatePacket = function({serial, uid, state, encryptionKey, id}) {
|
||||||
|
|
||||||
|
var json = {
|
||||||
|
uid: uid,
|
||||||
|
cmd: 42,
|
||||||
|
statusType: 0,
|
||||||
|
value3: 0,
|
||||||
|
alarmType: 1,
|
||||||
|
serial: serial,
|
||||||
|
value4: 0,
|
||||||
|
deviceId: 0,
|
||||||
|
value1: state,
|
||||||
|
value2: 0,
|
||||||
|
updateTimeSec: new Date().getTime(),
|
||||||
|
status: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(DKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id,
|
||||||
|
encryptionKey, encryptionKey
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
let defaultPacket = function({serial, uid, cmd, id, encryptionKey}) {
|
||||||
|
|
||||||
|
let json = {
|
||||||
|
uid: uid,
|
||||||
|
cmd: cmd,
|
||||||
|
serial: serial,
|
||||||
|
status: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(DKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id,
|
||||||
|
encryptionKey, encryptionKey
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let updatePacket = function({ uid, state, serial, id, clientSessionId , deviceId, encryptionKey}) {
|
||||||
|
let json = {
|
||||||
|
uid: uid,
|
||||||
|
delayTime: 0,
|
||||||
|
cmd: 15,
|
||||||
|
order: state === 0 ? "on" : "off",
|
||||||
|
userName: "iloveorvibo@orvibo.com",
|
||||||
|
ver: "3.0.0",
|
||||||
|
value3: 0,
|
||||||
|
serial: serial,
|
||||||
|
value4: 0,
|
||||||
|
deviceId: deviceId,
|
||||||
|
value1: state,
|
||||||
|
value2: 0,
|
||||||
|
clientSessionId: clientSessionId
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkt = Object.assign(Object.create(DKPacket), {
|
||||||
|
json: json,
|
||||||
|
id: id,
|
||||||
|
encryptionKey, encryptionKey
|
||||||
|
});
|
||||||
|
|
||||||
|
return pkt.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let encodePayload = function(json, key) {
|
||||||
|
let cipher = crypto.createCipheriv('aes-128-ecb', key, '');
|
||||||
|
cipher.setAutoPadding(true);
|
||||||
|
let crypted = cipher.update(json,'utf8','hex');
|
||||||
|
crypted += cipher.final('hex');
|
||||||
|
return new Buffer(crypted, 'hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
let getLength = function(items, extra) {
|
||||||
|
let length = extra || 0;
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
length += items[i].length;
|
||||||
|
}
|
||||||
|
return getHexLengthPadded(length);
|
||||||
|
};
|
||||||
|
|
||||||
|
let getHexLengthPadded = function(lengthDecimal) {
|
||||||
|
let lengthHex = lengthDecimal.toString(16);
|
||||||
|
let paddingLength = 4 - lengthHex.length;
|
||||||
|
let padding = '';
|
||||||
|
for (let i = 0; i < paddingLength; i++) {
|
||||||
|
padding +=0;
|
||||||
|
}
|
||||||
|
return new Buffer(padding + lengthHex, 'hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports.helloPacket = helloPacket;
|
||||||
|
module.exports.handshakePacket = handshakePacket;
|
||||||
|
module.exports.heartbeatPacket = heartbeatPacket;
|
||||||
|
module.exports.comfirmStatePacket = comfirmStatePacket;
|
||||||
|
module.exports.defaultPacket = defaultPacket;
|
||||||
|
module.exports.updatePacket = updatePacket;
|
@ -16,10 +16,7 @@ You will need to add the Orvibo PK key to decrypt and encrypt the initial packet
|
|||||||
Once you have this key you will need to add it the ``OrviboSettings.js`` file.
|
Once you have this key you will need to add it the ``OrviboSettings.js`` file.
|
||||||
|
|
||||||
|
|
||||||
Because these new sockets don't use UDP packets to communicate like the older versions you will also need to redirect all traffic from the host name
|
Because these new sockets don't use UDP packets to communicate like the older versions you will also need to redirect all traffic from the host name ``homemate.orvibo.com``
|
||||||
```
|
|
||||||
homemate.orvibo.com
|
|
||||||
```
|
|
||||||
on TCP port 10001 the computer running the server.
|
on TCP port 10001 the computer running the server.
|
||||||
|
|
||||||
I used an Ubuntu machine running dnsmasq and set this server as my DNS server in my router but depending on your network you might have to do it differntly.
|
I used an Ubuntu machine running dnsmasq and set this server as my DNS server in my router but depending on your network you might have to do it differntly.
|
||||||
@ -37,7 +34,6 @@ to the official Orvibo server.
|
|||||||
Clone the repo and then run
|
Clone the repo and then run
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
```
|
```
|
||||||
to install the dependencies (buffer-crc32)
|
to install the dependencies (buffer-crc32)
|
||||||
|
|
||||||
@ -50,7 +46,6 @@ To start the example http server run
|
|||||||
|
|
||||||
```
|
```
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
```
|
```
|
||||||
This will start the Orvibo socket server create a basic example HTTP server used for interacting with sockets.
|
This will start the Orvibo socket server create a basic example HTTP server used for interacting with sockets.
|
||||||
Calling this http server with no parameters will return the uid, state, modelId and name of the socket.
|
Calling this http server with no parameters will return the uid, state, modelId and name of the socket.
|
||||||
|
27
Utils.js
Normal file
27
Utils.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
module.exports.generateRandomTextValue = function(length) {
|
||||||
|
let chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
let result = '';
|
||||||
|
for (let i = length; i > 0; --i) {
|
||||||
|
result += chars[Math.floor(Math.random() * chars.length)];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.generateRandomHexValue = function(length) {
|
||||||
|
let chars = '0123456789abcdef';
|
||||||
|
let result = '';
|
||||||
|
for (let i = length; i > 0; --i) {
|
||||||
|
result += chars[Math.floor(Math.random() * chars.length)];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.generateRandomNumber = function(length) {
|
||||||
|
let numbers = '0123456789';
|
||||||
|
let result = '';
|
||||||
|
for (let i = length; i > 0; --i) {
|
||||||
|
result += numbers[Math.floor(Math.random() * numbers.length)];
|
||||||
|
}
|
||||||
|
return parseInt(result);
|
||||||
|
};
|
||||||
|
|
13
package-lock.json
generated
Normal file
13
package-lock.json
generated
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "orvibo-b25-server",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-crc32": {
|
||||||
|
"version": "0.2.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||||
|
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
package.json
Normal file
29
package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "orvibo-b25-server",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A server to control the Orvibo B25 range of smart sockets",
|
||||||
|
"main": "Orvibo.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "node Example.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/sandysound/orvibo-b25-server.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"Orvibo",
|
||||||
|
"B25",
|
||||||
|
"Smart",
|
||||||
|
"Socket"
|
||||||
|
],
|
||||||
|
"author": "Sandy Milne",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/sandysound/orvibo-b25-server/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/sandysound/orvibo-b25-server#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-crc32": "^0.2.13"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user