Skip to content

Commit

Permalink
0.2.2 - Adds raw call and ability to read settings
Browse files Browse the repository at this point in the history
  • Loading branch information
128keaton committed Apr 25, 2022
1 parent 21f8342 commit e1ef279
Show file tree
Hide file tree
Showing 16 changed files with 1,537 additions and 338 deletions.
30 changes: 25 additions & 5 deletions dist/tibbo-device-server.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,33 @@ export declare class TibboDeviceServer {
private activeSockets;
private readonly key;
constructor(key?: string);
login(ipAddress: string, password: string, key?: string): Promise<TibboDeviceLoginResponse>;
buzz(ipAddress: string, password: string, key?: string): Promise<unknown>;
reboot(ipAddress: string, password: string, key?: string): Promise<unknown>;
raw(ipAddress: string, password: string, message: string, key?: string): Promise<unknown>;
initializeSettings(ipAddress: string, password: string, key?: string): Promise<unknown>;
login(ipAddress: string, password: string, key?: string, timeout?: number): Promise<TibboDeviceLoginResponse>;
buzz(ipAddress: string, password: string, key?: string): Promise<{
message?: any;
data?: any;
}>;
reboot(ipAddress: string, password: string, key?: string): Promise<{
message?: any;
data?: any;
}>;
raw(ipAddress: string, password: string, message: string, key?: string): Promise<{
message?: any;
data?: any;
}>;
readSetting(ipAddress: string, password: string, setting: string, key?: string): Promise<string | null>;
initializeSettings(ipAddress: string, password: string, key?: string): Promise<{
message?: any;
data?: any;
}>;
updateSetting(setting: string, value: string, ipAddress: string, password: string): Promise<TibboDeviceUpdateSettingResponse[] | TibboDeviceLoginResponse>;
updateSettings(settings: TibboDeviceSetting[], ipAddress: string, password: string): Promise<TibboDeviceUpdateSettingResponse[] | TibboDeviceLoginResponse>;
stop(): Promise<void>;
private static handleTimeout;
private appendSocket;
private handleLoginResponse;
private setupLoginTimeout;
private setupTimeout;
private sendSingleAuthMessage;
private static handleGenericPacket;
private static handleDenied;
}
229 changes: 170 additions & 59 deletions dist/tibbo-device-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const tibbo_helpers_1 = require("./tibbo-helpers");
const buffer_1 = require("buffer");
const promises_1 = require("timers/promises");
const tibbo_shared_1 = require("./tibbo-shared");
const commander_1 = require("commander");
class TibboDeviceServer {
constructor(key) {
this.activeSockets = [];
Expand All @@ -17,41 +18,28 @@ class TibboDeviceServer {
this.key = key;
}
}
login(ipAddress, password, key = this.key) {
login(ipAddress, password, key = this.key, timeout = 3000) {
const socket = dgram_as_promised_1.default.createSocket("udp4");
const message = tibbo_helpers_1.TibboHelpers.loginMessage(password, key);
const encodedMessage = buffer_1.Buffer.from(message);
const ac = new AbortController();
const signal = ac.signal;
const abortController = new AbortController();
const signal = abortController.signal;
return new Promise((resolve) => {
let didResolve = false;
(0, promises_1.setTimeout)(3000, 'timeout', { signal }).then(() => {
if (!didResolve) {
this.stop().then(() => {
resolve({ key, success: false, message: 'ERR_TIMEOUT' });
}).catch(() => {
resolve({ key, success: false, message: 'ERR_TIMEOUT' });
});
}
}).catch(() => resolve({ key, success: false, message: 'ERR_TIMEOUT' }));
socket.bind().then(() => {
this.activeSockets.push(socket);
socket.setBroadcast(true);
return socket.send(encodedMessage, 0, encodedMessage.length, tibbo_shared_1.TIBBO_BROADCAST_PORT, ipAddress);
}).then(() => socket.recv())
this.setupLoginTimeout(resolve, key, signal, socket, timeout);
socket.bind()
.then(() => this.appendSocket(socket, true))
.then(socket => socket.send(encodedMessage, 0, encodedMessage.length, tibbo_shared_1.TIBBO_BROADCAST_PORT, ipAddress))
.then(() => socket.recv())
.then(packet => tibbo_helpers_1.TibboHelpers.processLoginResponse(packet))
.then(response => {
return socket.close()
.catch(() => response)
.then(() => response);
})
.then(response => socket.close().catch(() => response).then(() => response))
.then(response => ({
success: (response || false),
key,
}))
.then(response => {
didResolve = true;
ac.abort();
abortController.abort();
resolve(response);
});
});
Expand All @@ -60,11 +48,15 @@ class TibboDeviceServer {
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.buzzMessage(key));
}
reboot(ipAddress, password, key = this.key) {
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.rebootMessage(key));
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.rebootMessage(key), true);
}
raw(ipAddress, password, message, key = this.key) {
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.rawMessage(message, key));
}
readSetting(ipAddress, password, setting, key = this.key) {
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.getSettingMessage(setting, key), false, 10000)
.then(response => tibbo_helpers_1.TibboHelpers.stripSettingsResponse(key, response));
}
initializeSettings(ipAddress, password, key = this.key) {
return this.sendSingleAuthMessage(ipAddress, password, key, tibbo_helpers_1.TibboHelpers.initializeSettingsMessage(key));
}
Expand All @@ -85,11 +77,10 @@ class TibboDeviceServer {
const socket = dgram_as_promised_1.default.createSocket("udp4");
const settingMessages = settings.map(setting => tibbo_helpers_1.TibboHelpers.updateSettingMessage(setting.settingName, setting.settingValue, didAuth.key))
.map(string => buffer_1.Buffer.from(string));
return socket.bind().then(() => {
this.activeSockets.push(socket);
socket.setBroadcast(true);
return Promise.all(settingMessages.map(setting => tibbo_helpers_1.TibboHelpers.iterateSend(socket, setting, ipAddress, tibbo_shared_1.TIBBO_BROADCAST_PORT)));
}).then((results) => {
return socket.bind()
.then(() => this.appendSocket(socket, true))
.then(socket => Promise.all(settingMessages.map(setting => tibbo_helpers_1.TibboHelpers.iterateSend(socket, setting, ipAddress, tibbo_shared_1.TIBBO_BROADCAST_PORT))))
.then((results) => {
return results.map((result, index) => ({
success: result,
setting: settings[index]
Expand All @@ -106,40 +97,160 @@ class TibboDeviceServer {
.then(() => finished())
.catch(() => finished());
}
sendSingleAuthMessage(ipAddress, password, key, message) {
static handleTimeout(expectTimeout, resolver) {
if (expectTimeout) {
resolver({ message: 'SUCCESS' });
}
else {
resolver({ message: 'ERR_TIMEOUT' });
}
}
appendSocket(socket, broadcast = false) {
if (broadcast) {
socket.setBroadcast(true);
}
this.activeSockets.push(socket);
return socket;
}
handleLoginResponse(result, encodedMessage, ipAddress, socket, resolver) {
if (result.success) {
return socket.bind()
.then(() => this.appendSocket(socket))
.then(socket => socket.send(encodedMessage, 0, encodedMessage.length, tibbo_shared_1.TIBBO_BROADCAST_PORT, ipAddress))
.catch(() => resolver({ message: 'Could not send message' }));
}
else {
TibboDeviceServer.handleDenied(resolver);
}
}
setupLoginTimeout(resolver, key, signal, socket, timeout = 2000) {
(0, promises_1.setTimeout)(timeout, 'timeout', { signal })
.then(() => Promise.all([this.stop(), socket.close()])
.then(() => resolver({ key, message: 'ERR_TIMEOUT', success: false })))
.catch(() => resolver({ key, message: 'ERR_TIMEOUT', success: false }));
}
setupTimeout(resolver, signal, socket, timeout = 2000, expectTimeout = false) {
(0, promises_1.setTimeout)(timeout, 'timeout', { signal })
.then(() => Promise.all([this.stop(), socket.close()])
.then(() => TibboDeviceServer.handleTimeout(expectTimeout, resolver)))
.catch(() => {
});
}
sendSingleAuthMessage(ipAddress, password, key, message, expectTimeout = false, timeout = 2000) {
const socket = dgram_as_promised_1.default.createSocket("udp4");
const encodedMessage = buffer_1.Buffer.from(message);
const ac = new AbortController();
const signal = ac.signal;
const abortController = new AbortController();
const signal = abortController.signal;
return new Promise(resolve => {
(0, promises_1.setTimeout)(1000, 'timeout', { signal }).then(() => {
Promise.all([this.stop(), socket.close()])
.catch(() => resolve({ message: 'Success' }))
.then(() => resolve({ message: 'Success' }));
}).catch(() => resolve({ message: 'Success' }));
this.login(ipAddress, password, key).then(result => {
if (!result.success) {
resolve({ message: 'Access denied' });
}
else {
return socket.bind().then(() => {
this.activeSockets.push(socket);
socket.setBroadcast(true);
return socket.send(encodedMessage, 0, encodedMessage.length, tibbo_shared_1.TIBBO_BROADCAST_PORT, ipAddress);
}).catch(() => resolve(false));
}
}).then(() => socket.recv()).then(packet => {
const denied = tibbo_helpers_1.TibboHelpers.checkIfDenied(packet);
ac.abort();
if (denied) {
return { message: 'Access denied' };
}
if (packet) {
return { message: 'Success', data: packet.msg.toString() };
}
return { message: 'Success' };
}).then(response => this.stop().then(() => response));
this.setupTimeout(resolve, signal, socket, timeout, expectTimeout);
this.login(ipAddress, password, key, timeout)
.then(result => this.handleLoginResponse(result, encodedMessage, ipAddress, socket, resolve))
.then(() => socket.recv())
.then(packet => TibboDeviceServer.handleGenericPacket(abortController, packet))
.then(response => this.stop().then(() => resolve(response)));
});
}
static handleGenericPacket(abortController, packet) {
const denied = tibbo_helpers_1.TibboHelpers.checkIfDenied(packet);
abortController.abort();
if (denied) {
return { message: 'ACCESS_DENIED' };
}
if (packet) {
return { message: 'Success', data: packet.msg.toString() };
}
return { message: 'SUCCESS' };
}
static handleDenied(resolver) {
resolver({ message: 'ACCESS_DENIED' });
}
}
exports.TibboDeviceServer = TibboDeviceServer;
/* istanbul ignore if */
if (require.main == module) {
const tibboDeviceServer = new TibboDeviceServer();
commander_1.program
.name('tibbo-device-server')
.description('CLI to modify DS-Tibbo devices on the network')
.version(tibbo_shared_1.PACKAGE_VERSION);
commander_1.program
.command('login')
.description('Login to a Tibbo DS on the network')
.argument('<ipAddress>', 'IP address of Tibbo device to login into')
.argument('<password>', 'Password of the Tibbo device to login into')
.action((ipAddress, password) => tibboDeviceServer.login(ipAddress, password)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2))));
commander_1.program
.command('buzz')
.description('Buzz a Tibbo DS on the network')
.argument('<ipAddress>', 'IP address of Tibbo device to buzz')
.argument('<password>', 'Password of the Tibbo device to buzz')
.action((ipAddress, password) => tibboDeviceServer.buzz(ipAddress, password)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2))));
commander_1.program
.command('reboot')
.description('Reboot a Tibbo DS on the network')
.argument('<ipAddress>', 'IP address of Tibbo device to reboot')
.argument('<password>', 'Password of the Tibbo device to reboot')
.action((ipAddress, password) => tibboDeviceServer.reboot(ipAddress, password)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2))));
commander_1.program
.command('raw')
.description('Send a raw command to a Tibbo DS on the network')
.argument('<ipAddress>', 'IP address of Tibbo device to send the raw command rto')
.argument('<password>', 'Password of the Tibbo device to send the raw command to')
.argument('<raw>', 'The raw command')
.action((ipAddress, password, raw) => tibboDeviceServer.raw(ipAddress, password, raw)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2))));
const setting = commander_1.program.command('setting');
setting.command('set')
.description('Update a setting on the Tibbo device')
.argument('<ipAddress>', 'IP address of Tibbo device to login into')
.argument('<password>', 'Password of the Tibbo device to login into')
.argument('<setting>', 'Setting name on the Tibbo device')
.argument('<value>', 'New value of the setting')
.action((ipAddress, password, setting, value) => tibboDeviceServer.updateSetting(setting, value, ipAddress, password)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2))));
setting.command('get')
.description('Update a setting on the Tibbo device')
.argument('<ipAddress>', 'IP address of Tibbo device to login into')
.argument('<password>', 'Password of the Tibbo device to login into')
.argument('<setting>', 'Setting name on the Tibbo device')
.action((ipAddress, password, setting) => tibboDeviceServer.readSetting(ipAddress, password, setting)
.then(result => tibboDeviceServer.stop().then(() => {
const object = {};
object[setting] = result;
return object;
}))
.then(result => console.log(JSON.stringify(result, null, 2))));
setting.command('set-multiple')
.description('Update a setting on the Tibbo device')
.argument('<ipAddress>', 'IP address of Tibbo device to login into')
.argument('<password>', 'Password of the Tibbo device to login into')
.argument('<settings>', 'Comma-separated values to set')
.action((ipAddress, password, csv) => {
const rawSettings = csv.split(',');
const settings = [];
let currentSetting;
rawSettings.forEach((value, index) => {
if (index % 2 === 0) {
currentSetting = value;
}
else {
settings.push({
settingName: currentSetting,
settingValue: value
});
}
});
return tibboDeviceServer.updateSettings(settings, ipAddress, password)
.then(result => tibboDeviceServer.stop().then(() => result))
.then(result => console.log(JSON.stringify(result, null, 2)));
});
commander_1.program.parse();
}
Loading

0 comments on commit e1ef279

Please sign in to comment.