UNPKG

homebridge-august-door-sense

Version:
212 lines 8.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.augustGetSerialNumber = exports.augustGetDoorStatus = exports.augustGetLocks = exports.augustGetHouses = exports.augustStartSession = exports.AugustDoorStatus = void 0; const https_1 = require("https"); const util_1 = require("util"); var AugustDoorStatus; (function (AugustDoorStatus) { AugustDoorStatus[AugustDoorStatus["UNKNOWN"] = 0] = "UNKNOWN"; AugustDoorStatus[AugustDoorStatus["CLOSED"] = 1] = "CLOSED"; AugustDoorStatus[AugustDoorStatus["OPEN"] = 2] = "OPEN"; })(AugustDoorStatus || (exports.AugustDoorStatus = AugustDoorStatus = {})); async function augustStartSession(options, log) { const { code } = options; const session = await augustLogin(options, log); log.debug(JSON.stringify(session)); const { status } = await augustGetMe(session, log); // Session isn't valid yet, so we need to validate it by sending a code if (status !== 200) { if (!code) { await augustSendCode(session, log); log.info('Session is not valid yet, but no 2FA code was provided. Please provide a 2FA code.'); } else { const resp = await augustValidateCode(code, session, log); if (resp.status !== 200) { await augustSendCode(session, log); log.error(`Invalid code: ${resp.status}, new code sent, please provide the new 2FA code.`); } else { session.token = resp.token; } } } return session; } exports.augustStartSession = augustStartSession; function getRequestOptions(apiKey, path, method, session) { const options = { hostname: 'api-production.august.com', port: 443, path: path, method: method, headers: { 'x-august-api-key': apiKey, 'x-kease-api-key': apiKey, 'Content-Type': 'application/json', 'Accept-Version': '0.0.1', 'User-Agent': 'August/Luna-3.2.2', }, }; if (session) { options['headers']['x-august-access-token'] = session.token; } return options; } async function makeRequest(options, data, log) { return new Promise((resolve) => { const req = (0, https_1.request)(options, res => { const chunks = []; res.on('data', d => { log.debug(`statusCode: ${res.statusCode}`); const buff = d; const buffStr = buff.toString('utf8'); log.debug(buffStr); chunks.push(buffStr); }); res.on('end', () => { const msg = chunks.join(); let payload; if (res.statusCode === 200) { try { payload = JSON.parse(msg); } catch (error) { log.error(`Error parsing JSON: ${msg}`); } } else { log.debug(`Received non-200 HTTP response ${res.statusCode}:\n${msg}`); } resolve({ status: res.statusCode, token: res.headers['x-august-access-token'], payload: payload, }); }); }); req.on('error', error => { log.error(`Error reaching August server: ${error}`); }); req.write(data); req.end(); }); } async function augustLogin(sessionOptions, log) { const { apiKey, uuid, idType, password, identifier } = sessionOptions; const data = new util_1.TextEncoder().encode(JSON.stringify({ identifier: `${idType}:${identifier}`, password: password, installId: uuid, })); const requestOptions = getRequestOptions(apiKey, '/session', 'POST'); const res = await makeRequest(requestOptions, data, log); if (res.status !== 200 || !res.payload['userId']) { throw new Error(`Invalid user credentials: ${res.status}`); } else { return { apiKey: apiKey, idType: idType, identifier: identifier, token: res.token, }; } } async function augustGetMe(session, log) { const options = getRequestOptions(session.apiKey, '/users/me', 'GET', session); return makeRequest(options, new Uint8Array(), log); } async function augustSendCode(session, log) { const data = new util_1.TextEncoder().encode(JSON.stringify({ value: session.identifier, })); const options = getRequestOptions(session.apiKey, `/validation/${session.idType}`, 'POST', session); return makeRequest(options, data, log); } async function augustValidateCode(code, session, log) { const payload = { code, }; payload[session.idType] = session.identifier; const data = new util_1.TextEncoder().encode(JSON.stringify(payload)); const options = getRequestOptions(session.apiKey, `/validate/${session.idType}`, 'POST', session); return makeRequest(options, data, log); } async function augustGetHouses(session, log) { const options = getRequestOptions(session.apiKey, '/users/houses/mine', 'GET', session); const results = await makeRequest(options, new Uint8Array(), log); if (results.status === 200 && Array.isArray(results.payload)) { const homes = (results.payload).map(home => ({ id: home['HouseID'], name: home['HouseName'], })); return homes; } else { return []; } } exports.augustGetHouses = augustGetHouses; async function augustGetLocks(session, log) { const options = getRequestOptions(session.apiKey, '/users/locks/mine', 'GET', session); const results = await makeRequest(options, new Uint8Array(), log); if (results.status === 200 && results.payload) { const locks = Object.keys(results.payload).map(id => { const lock = results.payload[id]; return { id: id, name: lock['LockName'], macAddress: lock['macAddress'], houseId: lock['HouseID'], houseName: lock['HouseName'], }; }); return locks; } else { return []; } } exports.augustGetLocks = augustGetLocks; async function augustGetDoorStatus(session, lockId, log) { var _a; const options = getRequestOptions(session.apiKey, `/remoteoperate/${lockId}/status`, 'PUT', session); const results = await makeRequest(options, new Uint8Array(), log); if (results.status === 200 && results.payload) { const status = results.payload['doorState']; const serialNumber = (_a = results.payload['info']) === null || _a === void 0 ? void 0 : _a['serialNumber']; if (status === 'kAugDoorState_Closed') { return { doorStatus: AugustDoorStatus.CLOSED, serialNumber: serialNumber }; } else if (status === 'kAugDoorState_Open') { return { doorStatus: AugustDoorStatus.OPEN, serialNumber: serialNumber }; } else if (status === 'kAugDoorState_Init') { return { doorStatus: AugustDoorStatus.UNKNOWN, serialNumber: serialNumber }; } else if (!status) { log.info(`Door status for lock ${lockId} unknown. Exclude this device in the config if DoorSense isn't enabled.`); return { doorStatus: AugustDoorStatus.UNKNOWN, serialNumber: serialNumber }; } else { throw new Error(`Unknown door status: ${status}`); } } else { return { doorStatus: AugustDoorStatus.UNKNOWN }; } } exports.augustGetDoorStatus = augustGetDoorStatus; async function augustGetSerialNumber(session, lockId, log) { const options = getRequestOptions(session.apiKey, `/remoteoperate/${lockId}/status`, 'PUT', session); const results = await makeRequest(options, new Uint8Array(), log); if (results.status === 200 && results.payload) { return results.payload['serialNumber']; } else { return ''; } } exports.augustGetSerialNumber = augustGetSerialNumber; //# sourceMappingURL=august.js.map