homebridge-adt-pulse
Version:
Homebridge security system platform for ADT Pulse
255 lines • 10.1 kB
JavaScript
import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils';
import _ from 'lodash';
import { isErrorLike, serializeError } from 'serialize-error';
import { ADTPulseAuth } from '../lib/auth.js';
import { configServerLogin, configServerRequestCode, configServerValidate } from '../lib/schema.js';
import { debugLog } from '../lib/utility.js';
class ADTPulseConfigServer extends HomebridgePluginUiServer {
#auth;
#userInput;
startBackend() {
this.onRequest('/initialize', this.initialize.bind(this));
this.onRequest('/get-methods', this.getMethods.bind(this));
this.onRequest('/request-code', this.requestCode.bind(this));
this.onRequest('/validate', this.validate.bind(this));
this.onRequest('/generate-config', this.generateConfig.bind(this));
this.ready();
}
async initialize(payload) {
const parsedPayload = configServerLogin.safeParse(payload);
if (!parsedPayload.success) {
debugLog(null, 'server.ts / ADTPulseConfigServer.initialize()', 'error', 'Invalid payload');
return {
action: 'UI_INITIALIZE',
success: false,
info: {
message: 'Invalid payload',
},
};
}
this.#auth = new ADTPulseAuth({
subdomain: parsedPayload.data.subdomain,
username: parsedPayload.data.username,
password: parsedPayload.data.password,
}, {
debug: false,
});
this.#userInput = {
subdomain: parsedPayload.data.subdomain,
username: parsedPayload.data.username,
password: parsedPayload.data.password,
};
return {
action: 'UI_INITIALIZE',
success: true,
info: null,
};
}
async getMethods() {
if (this.#auth === undefined || this.#userInput === undefined) {
debugLog(null, 'server.ts / ADTPulseConfigServer.getMethods()', 'error', 'Auth API has not been initialized');
return {
action: 'UI_GET_METHODS',
success: false,
info: {
message: 'Auth API has not been initialized',
},
};
}
try {
const response = await this.#auth.getVerificationMethods();
if (!response.success) {
if (response.info.message) {
debugLog(null, 'server.ts / ADTPulseConfigServer.getMethods()', 'error', response.info.message);
}
return {
action: 'UI_GET_METHODS',
success: false,
info: response.info,
};
}
return {
action: 'UI_GET_METHODS',
success: true,
info: response.info,
};
}
catch (error) {
throw new RequestError('Failed to get methods', {
message: error,
});
}
}
async requestCode(payload) {
if (this.#auth === undefined || this.#userInput === undefined) {
debugLog(null, 'server.ts / ADTPulseConfigServer.requestCode()', 'error', 'Auth API has not been initialized');
return {
action: 'UI_REQUEST_CODE',
success: false,
info: {
message: 'Auth API has not been initialized',
},
};
}
const parsedPayload = configServerRequestCode.safeParse(payload);
if (!parsedPayload.success) {
debugLog(null, 'server.ts / ADTPulseConfigServer.requestCode()', 'error', 'Invalid payload');
return {
action: 'UI_REQUEST_CODE',
success: false,
info: {
message: 'Invalid payload',
},
};
}
try {
const response = await this.#auth.requestCode(parsedPayload.data.methodId);
if (!response.success) {
if (response.info.message) {
debugLog(null, 'server.ts / ADTPulseConfigServer.requestCode()', 'error', response.info.message);
}
return {
action: 'UI_REQUEST_CODE',
success: false,
info: response.info,
};
}
return {
action: 'UI_REQUEST_CODE',
success: true,
info: response.info,
};
}
catch (error) {
const serializedError = (isErrorLike(error)) ? serializeError(error) : serializeError(new Error('Unknown error'));
debugLog(null, 'server.ts / ADTPulseConfigServer.requestCode()', 'error', 'Method encountered an error during execution');
return {
action: 'UI_REQUEST_CODE',
success: false,
info: {
error: serializedError,
},
};
}
}
async validate(payload) {
if (this.#auth === undefined || this.#userInput === undefined) {
debugLog(null, 'server.ts / ADTPulseConfigServer.validate()', 'error', 'Auth API has not been initialized');
return {
action: 'UI_VALIDATE',
success: false,
info: {
message: 'Auth API has not been initialized',
},
};
}
const parsedPayload = configServerValidate.safeParse(payload);
if (!parsedPayload.success) {
debugLog(null, 'server.ts / ADTPulseConfigServer.validate()', 'error', 'Invalid payload');
return {
action: 'UI_VALIDATE',
success: false,
info: {
message: 'Invalid payload',
},
};
}
try {
const requests = [
this.#auth.validateCode.bind(this.#auth, parsedPayload.data.otpCode),
this.#auth.getTrustedDevices.bind(this.#auth),
this.#auth.addTrustedDevice.bind(this.#auth, parsedPayload.data.deviceName),
this.#auth.completeSignIn.bind(this.#auth),
];
for (let i = 0; i < requests.length; i += 1) {
const response = await requests[i]();
if (!response.success) {
if (response.info.message) {
debugLog(null, 'server.ts / ADTPulseConfigServer.validate()', 'error', response.info.message);
}
return {
action: 'UI_VALIDATE',
success: false,
info: response.info,
};
}
}
return {
action: 'UI_VALIDATE',
success: true,
info: null,
};
}
catch (error) {
const serializedError = (isErrorLike(error)) ? serializeError(error) : serializeError(new Error('Unknown error'));
debugLog(null, 'server.ts / ADTPulseConfigServer.validate()', 'error', 'Method encountered an error during execution');
return {
action: 'UI_VALIDATE',
success: false,
info: {
error: serializedError,
},
};
}
}
async generateConfig(payload) {
if (this.#auth === undefined || this.#userInput === undefined) {
debugLog(null, 'server.ts / ADTPulseConfigServer.generateConfig()', 'error', 'Auth API has not been initialized');
return {
action: 'UI_GENERATE_CONFIG',
success: false,
info: {
message: 'Auth API has not been initialized',
},
};
}
try {
let payloadSensors = payload.oldConfig.sensors ?? [];
if (payload.updateSensors === true) {
const response = await this.#auth.getSensors();
if (!response.success) {
return {
action: 'UI_GENERATE_CONFIG',
success: false,
info: {
message: 'Failed to get new sensors',
},
};
}
payloadSensors = _.merge(payloadSensors, response.info.sensors);
}
return {
action: 'UI_GENERATE_CONFIG',
success: true,
info: {
config: {
platform: payload.oldConfig.platform ?? 'ADTPulse',
name: payload.oldConfig.name ?? 'ADT Pulse',
subdomain: this.#userInput.subdomain,
username: this.#userInput.username,
password: this.#userInput.password,
fingerprint: this.#auth.getFingerprint(),
mode: payload.oldConfig.mode ?? 'normal',
speed: payload.oldConfig.speed ?? 1,
options: payload.oldConfig.options ?? [],
sensors: payloadSensors,
},
},
};
}
catch (error) {
const serializedError = (isErrorLike(error)) ? serializeError(error) : serializeError(new Error('Unknown error'));
debugLog(null, 'server.ts / ADTPulseConfigServer.generateConfig()', 'error', 'Method encountered an error during execution');
return {
action: 'UI_GENERATE_CONFIG',
success: false,
info: {
error: serializedError,
},
};
}
}
}
const instance = new ADTPulseConfigServer();
instance.startBackend();
//# sourceMappingURL=server.js.map