homebridge-adt-pulse
Version:
Homebridge security system platform for ADT Pulse
210 lines • 11.9 kB
JavaScript
import repl from 'node:repl';
import chalk from 'chalk';
import { ADTPulseAPI } from '../lib/api.js';
import { ADTPulseAuth } from '../lib/auth.js';
import { debugLog } from '../lib/utility.js';
class ADTPulseRepl {
#api;
#auth;
#replServer;
constructor() {
ADTPulseRepl.displayStartupHeader();
ADTPulseRepl.displayHelpMenu();
this.#replServer = repl.start({
ignoreUndefined: true,
prompt: '> ',
});
this.#replServer.context.repl = this;
this.#replServer.defineCommand('break', {
help: 'Sometimes you get stuck, this gets you out',
action() {
debugLog(null, 'repl.ts / ADTPulseRepl.startRepl()', 'error', 'The ".break" command is not allowed');
this.displayPrompt();
},
});
this.#replServer.defineCommand('clear', {
help: 'Break, and also clear the local context',
action() {
debugLog(null, 'repl.ts / ADTPulseRepl.startRepl()', 'error', 'The ".clear" command is not allowed');
this.displayPrompt();
},
});
this.#replServer.defineCommand('editor', {
help: 'Enter editor mode',
action() {
debugLog(null, 'repl.ts / ADTPulseRepl.startRepl()', 'error', 'The ".editor" command is not allowed');
this.displayPrompt();
},
});
this.#replServer.defineCommand('help', {
help: 'Print this help message',
action() {
ADTPulseRepl.displayHelpHeader();
ADTPulseRepl.displayHelpMenu();
this.displayPrompt();
},
});
this.#replServer.defineCommand('load', {
help: 'Load JS from a file into the REPL session',
action() {
debugLog(null, 'repl.ts / ADTPulseRepl.startRepl()', 'error', 'The ".load" command is not allowed');
this.displayPrompt();
},
});
this.#replServer.defineCommand('save', {
help: 'Save all evaluated commands in this REPL session to a file',
action() {
debugLog(null, 'repl.ts / ADTPulseRepl.startRepl()', 'error', 'The ".save" command is not allowed');
this.displayPrompt();
},
});
}
setApiInstance(subdomain, username, password, fingerprint) {
if (subdomain !== 'portal' && subdomain !== 'portal-ca') {
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'error', 'Invalid subdomain specified. Valid values are either "portal" or "portal-ca"');
return;
}
if (typeof username !== 'string' || username === '') {
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'error', 'Username must be a string and cannot be empty');
return;
}
if (typeof password !== 'string' || password === '') {
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'error', 'Password must be a string and cannot be empty');
return;
}
if (typeof fingerprint !== 'string' || fingerprint === '') {
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'error', 'Fingerprint must be a string and cannot be empty');
return;
}
this.#api = new ADTPulseAPI({
platform: 'ADTPulse',
name: 'ADT Pulse',
subdomain,
username,
password,
fingerprint,
mode: 'normal',
speed: 1,
options: [],
sensors: [],
}, {
debug: true,
});
if (this.#replServer === undefined) {
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'error', 'Failed to set API context because "this.#replServer" is undefined');
return;
}
this.#replServer.context.api = this.#api;
debugLog(null, 'repl.ts / ADTPulseRepl.setApiInstance()', 'success', 'API instance has been successfully set');
}
setAuthInstance(subdomain, username, password) {
if (subdomain !== 'portal' && subdomain !== 'portal-ca') {
debugLog(null, 'repl.ts / ADTPulseRepl.setAuthInstance()', 'error', 'Invalid subdomain specified. Valid values are either "portal" or "portal-ca"');
return;
}
if (typeof username !== 'string' || username === '') {
debugLog(null, 'repl.ts / ADTPulseRepl.setAuthInstance()', 'error', 'Username must be a string and cannot be empty');
return;
}
if (typeof password !== 'string' || password === '') {
debugLog(null, 'repl.ts / ADTPulseRepl.setAuthInstance()', 'error', 'Password must be a string and cannot be empty');
return;
}
this.#auth = new ADTPulseAuth({
subdomain,
username,
password,
}, {
debug: true,
});
if (this.#replServer === undefined) {
debugLog(null, 'repl.ts / ADTPulseRepl.setAuthInstance()', 'error', 'Failed to set auth context because "this.#replServer" is undefined');
return;
}
this.#replServer.context.auth = this.#auth;
debugLog(null, 'repl.ts / ADTPulseRepl.setAuthInstance()', 'success', 'Auth instance has been successfully set');
}
static displayHelpHeader() {
console.info([
chalk.cyanBright('##########################################################'),
chalk.cyanBright('#### ADT Pulse for Homebridge Plugin REPL Help Menu ####'),
chalk.cyanBright('##########################################################'),
'',
'This is the help menu on how to use this REPL interface. If you have questions on how',
'to use this, please refer to the documentation using the link below:',
'',
'https://github.com/mrjackyliang/homebridge-adt-pulse',
].join('\n'));
}
static displayHelpMenu() {
console.info([
'',
chalk.bold('Method parameter documentation:'),
` {'portal' | 'portal-ca'} ${chalk.magentaBright('subdomain')} - Set the domain for either USA or Canada subscribers`,
` {string} ${chalk.magentaBright('username')} - The username for logging in to ADT Pulse portal`,
` {string} ${chalk.magentaBright('password')} - The password for logging in to ADT Pulse portal`,
` {string} ${chalk.magentaBright('fingerprint')} - The fingerprint for logging in to ADT Pulse portal`,
` {'arm' | 'night' | 'off' | 'stay'} ${chalk.magentaBright('armFrom')} - Specify the current system arm state`,
` {'arm' | 'night' | 'off' | 'stay'} ${chalk.magentaBright('armTo')} - Specify the arm state you would like to set`,
` {boolean} ${chalk.magentaBright('isAlarmActive')} - If the alarm system is ringing`,
` {string} ${chalk.magentaBright('methodId')} - Which device to request a verification code from (usually "SMS" or "EMAIL")`,
` {string} ${chalk.magentaBright('otpCode')} - The one-time password code received from the verification method`,
` {string} ${chalk.magentaBright('deviceName')} - The name to use when saving as a trusted device after verification`,
'',
chalk.bold('Before you use the API, set the instances using this command:'),
` ${chalk.yellowBright(`repl.setApiInstance(${chalk.magentaBright('subdomain')}, ${chalk.magentaBright('username')}, ${chalk.magentaBright('password')}, ${chalk.magentaBright('fingerprint')});`)}`,
` ${chalk.yellowBright(`repl.setAuthInstance(${chalk.magentaBright('subdomain')}, ${chalk.magentaBright('username')}, ${chalk.magentaBright('password')});`)}`,
'',
chalk.bold('Once the API instance is set, interact with the portal using these methods:'),
` ${chalk.yellowBright('await api.login();')}`,
` ${chalk.yellowBright('await api.logout();')}`,
` ${chalk.yellowBright('await api.getGatewayInformation();')}`,
` ${chalk.yellowBright('await api.getPanelInformation();')}`,
` ${chalk.yellowBright('await api.getPanelStatus();')}`,
` ${chalk.yellowBright(`await api.setPanelStatus(${chalk.magentaBright('armFrom')}, ${chalk.magentaBright('armTo')}, ${chalk.magentaBright('isAlarmActive')});`)}`,
` ${chalk.yellowBright('await api.getSensorsInformation();')}`,
` ${chalk.yellowBright('await api.getSensorsStatus();')}`,
` ${chalk.yellowBright('await api.getOrbSecurityButtons();')}`,
` ${chalk.yellowBright('await api.performSyncCheck();')}`,
` ${chalk.yellowBright('await api.performKeepAlive();')}`,
` ${chalk.yellowBright(' api.isAuthenticated();')}`,
` ${chalk.yellowBright(' api.resetSession();')}`,
'',
chalk.bold('Once the auth instance is set, interact with the portal using these methods:'),
` ${chalk.yellowBright('await auth.getVerificationMethods();')}`,
` ${chalk.yellowBright(`await auth.requestCode(${chalk.magentaBright('methodId')});`)}`,
` ${chalk.yellowBright(`await auth.validateCode(${chalk.magentaBright('otpCode')});`)}`,
` ${chalk.yellowBright('await auth.getTrustedDevices();')}`,
` ${chalk.yellowBright(`await auth.addTrustedDevice(${chalk.magentaBright('deviceName')});`)}`,
` ${chalk.yellowBright('await auth.completeSignIn();')}`,
` ${chalk.yellowBright('await auth.getSensors();')}`,
` ${chalk.yellowBright(' auth.getFingerprint();')}`,
'',
chalk.bold('You may also wrap the above methods with this to see the entire response:'),
` ${chalk.yellowBright(`console.log(util.inspect(${chalk.magentaBright('replace me without the ending semi-colon')}, false, null, true));`)}`,
chalk.bold('A small reference for REPL commands:'),
` ${chalk.yellowBright('.exit')}`,
` ${chalk.yellowBright('.help')}`,
'',
].join('\n'));
}
static displayStartupHeader() {
console.info([
chalk.cyanBright('################################################################'),
chalk.cyanBright('#### ADT Pulse for Homebridge Plugin REPL ####'),
chalk.cyanBright('#### https://github.com/mrjackyliang/homebridge-adt-pulse ####'),
chalk.cyanBright('#### ####'),
chalk.cyanBright('#### Copyright (c) 2024 Jacky Liang ####'),
chalk.cyanBright('################################################################'),
'',
'Welcome to the REPL interface for ADT Pulse for Homebridge. This interface',
'allows you to interact with the ADT Pulse portal via the included API and is designed',
`for advanced users only. ${chalk.redBright('PLEASE USE WITH CAUTION, NO WARRANTY IS PROVIDED.')}`,
'',
`${chalk.yellowBright('NOTICE')}: The API gathers anonymous analytics to detect potential bugs or issues.`,
' All personally identifiable information will be redacted.',
].join('\n'));
}
}
new ADTPulseRepl();
//# sourceMappingURL=repl.js.map