dirigera
Version:
A TypeScript client for IKEA's DIRIGERA smart home hub
150 lines (149 loc) • 6.62 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDirigeraClient = createDirigeraClient;
const node_os_1 = __importDefault(require("node:os"));
const node_https_1 = require("node:https");
const authCode_1 = require("./authCode");
const certificate_1 = __importDefault(require("./certificate"));
const mdnsDiscovery_1 = require("./mdnsDiscovery");
const ws_1 = require("./ws");
const hub_1 = __importDefault(require("./api/hub"));
const devices_1 = __importDefault(require("./api/devices"));
const lights_1 = __importDefault(require("./api/lights"));
const outlets_1 = __importDefault(require("./api/outlets"));
const controllers_1 = __importDefault(require("./api/controllers"));
const speakers_1 = __importDefault(require("./api/speakers"));
const blinds_1 = __importDefault(require("./api/blinds"));
const airPurifiers_1 = __importDefault(require("./api/airPurifiers"));
const repeaters_1 = __importDefault(require("./api/repeaters"));
const motionSensors_1 = __importDefault(require("./api/motionSensors"));
const lightSensors_1 = __importDefault(require("./api/lightSensors"));
const environmentSensors_1 = __importDefault(require("./api/environmentSensors"));
const openCloseSensors_1 = __importDefault(require("./api/openCloseSensors"));
const waterSensors_1 = __importDefault(require("./api/waterSensors"));
const deviceSets_1 = __importDefault(require("./api/deviceSets"));
const rooms_1 = __importDefault(require("./api/rooms"));
const scenes_1 = __importDefault(require("./api/scenes"));
const music_1 = __importDefault(require("./api/music"));
const users_1 = __importDefault(require("./api/users"));
async function createDirigeraClient({ gatewayIP, accessToken, rejectUnauthorized = true, } = {}) {
const ip = gatewayIP ?? (await (0, mdnsDiscovery_1.discoverGatewayIP)());
const { got } = await import('got');
const gotInstance = got.extend({
prefixUrl: `https://${ip}:8443/v1`,
headers: {
...(accessToken ? { authorization: `Bearer ${accessToken}` } : null),
},
...(rejectUnauthorized
? {
agent: {
https: new node_https_1.Agent({
ca: [certificate_1.default],
checkServerIdentity: () => undefined,
}),
},
}
: { https: { rejectUnauthorized: false } }),
hooks: {
beforeError: [
(error) => {
if (error.code === 'ERR_NON_2XX_3XX_RESPONSE' &&
error?.response?.body) {
error.name = 'DirigeraError';
error.message = `${error.response.body}`;
}
return error;
},
],
},
});
return {
async authenticate({ verbose = false } = {}) {
const codeVerifier = (0, authCode_1.generateCodeVerifier)();
const codeChallenge = (0, authCode_1.calculateCodeChallenge)(codeVerifier);
const { code } = await gotInstance
.get(`oauth/authorize`, {
searchParams: {
audience: 'homesmart.local',
response_type: 'code',
code_challenge: codeChallenge,
code_challenge_method: authCode_1.CODE_CHALLENGE_METHOD,
},
})
.json();
const { default: pRetry } = await import('p-retry');
if (verbose) {
console.log('Press the Action Button on the bottom of your Dirigera Hub within 60 seconds.');
}
return await pRetry(async () => {
const { access_token } = await gotInstance
.post(`oauth/token`, {
form: {
code,
name: node_os_1.default.hostname(),
grant_type: 'authorization_code',
code_verifier: codeVerifier,
},
})
.json();
if (!access_token) {
throw new Error('Access token is missing.');
}
if (verbose) {
process.stdout.write('\n');
}
return access_token;
}, {
retries: 59,
minTimeout: 1000,
factor: 1,
onFailedAttempt: (error) => {
if (verbose) {
process.stdout.write(`\rTime left: ${String(error.retriesLeft).padStart(2, ' ')} seconds`);
if (error.retriesLeft === 0) {
process.stdout.write('\n');
}
}
},
});
},
async home() {
return await gotInstance.get(`home`).json();
},
hub: (0, hub_1.default)(gotInstance),
devices: (0, devices_1.default)(gotInstance),
lights: (0, lights_1.default)(gotInstance),
outlets: (0, outlets_1.default)(gotInstance),
controllers: (0, controllers_1.default)(gotInstance),
speakers: (0, speakers_1.default)(gotInstance),
blinds: (0, blinds_1.default)(gotInstance),
airPurifiers: (0, airPurifiers_1.default)(gotInstance),
repeaters: (0, repeaters_1.default)(gotInstance),
motionSensors: (0, motionSensors_1.default)(gotInstance),
lightSensors: (0, lightSensors_1.default)(gotInstance),
environmentSensors: (0, environmentSensors_1.default)(gotInstance),
openCloseSensors: (0, openCloseSensors_1.default)(gotInstance),
waterSensors: (0, waterSensors_1.default)(gotInstance),
deviceSets: (0, deviceSets_1.default)(gotInstance),
rooms: (0, rooms_1.default)(gotInstance),
scenes: (0, scenes_1.default)(gotInstance),
music: (0, music_1.default)(gotInstance),
users: (0, users_1.default)(gotInstance),
startListeningForUpdates(callback) {
if (!accessToken) {
throw new Error('Access token is missing.');
}
(0, ws_1.initializeWebSocket)({
ip,
accessToken,
callback,
});
},
stopListeningForUpdates() {
(0, ws_1.closeWebSocket)();
},
};
}