UNPKG

dirigera-simple

Version:

A simple tool that can be used to set up a local controller for your new IKEA smart home system, based on the Dirigera hub.

166 lines (151 loc) 5.76 kB
const { startLoading, endLoading, fetchForm, fetchJson, encodeDataToURL } = require('./utils.cjs'); const { Discover } = require('./Discover.cjs'); /* The authentication is used to get a bearer code from the hub. With that access code it is possible to communicate with the hub. */ const os = require('node:os'); const { createHash } = require('crypto'); /** * The Authenticate class is used to get a bearer code from the hub. * With that access code it is possible to do all further communicate with the hub. * * @since v0.1.0 */ class Authenticate { /** * Get the access code from the hub by intiating the class. * ```js * var auth = new Authenticate(dirigeraIp, data => { * console.log(data); * var access_token = data.access_token; * }) * ``` * * @param {string} ip - The IP address of the hub. * @param {function} callback - The callback function to be called when the access code is received. * @since v0.1.0 */ constructor(ip = null, callback = (data) => { }) { this.ip = ip; this.options = { CODE_LENGTH: 128, CODE_CHALLENGE_METHOD: 'S256', authUrl: `https://${this.ip}:8443/v1/oauth/authorize`, tokenUrl: `https://${this.ip}:8443/v1/oauth/token`, callback: callback, maxRetry: 10, retryCounter: 0 } this.codeVerifier = this.getCodeVerifier(); const hash = createHash('sha256'); this.codeChallenge = hash.update(this.codeVerifier).digest('base64url'); if (!this.ip) { new Discover((data) => { // console.log(data); console.log("|| >>> Found device on IP: " + data.ip) this.setIPaddress(data.ip); this.startAuthProcess(); }) } else { this.startAuthProcess(); } } /** * Set the IP address of the hub. * * @param {string} ip - The IP address of the hub. */ setIPaddress(ip) { this.ip = ip; this.options.authUrl = `https://${this.ip}:8443/v1/oauth/authorize`; this.options.tokenUrl = `https://${this.ip}:8443/v1/oauth/token`; } startAuthProcess() { startLoading(); var code = ''; fetchJson(this.options.authUrl + '?' + encodeDataToURL({ audience: 'homesmart.local', response_type: 'code', code_challenge: this.codeChallenge, code_challenge_method: this.options.CODE_CHALLENGE_METHOD, }), data => { setTimeout(() => { endLoading(); if (data.error) { console.log(`we got an pairing error: ${data.message} `) if (data.message == 'Already one ongoing pairing request') { setTimeout(() => { if (this.options.retryCounter++ > this.options.maxRetry) { console.log('Could not get into pairing mode!!!') } else { console.log('retrying pairing mode') this.startAuthProcess(); } }, 5000); } } else { this.code = data.code; console.log(`code received: ${this.code}`); // console.log(`all data: ${JSON.stringify(data)}`); this.checkForAccessCode(); } }, 1500); }) } checkForAccessCode() { console.log('|| >>> Press the Action Button <<< || '); console.log('|| >>> On the bottom of your Dirigera Hub, it should automatically get the access token! <<< || '); var data = { code: this.code, name: os.hostname(), grant_type: 'authorization_code', code_verifier: this.codeVerifier, } this.encodedData = encodeDataToURL(data); startLoading(); setTimeout(() => { this.tryToGetAuth(); }, 1000); } tryToGetAuth() { fetchForm(this.options.tokenUrl, this.encodedData, data => { var result = JSON.parse(data); if (result.error) { if (result.message == 'Button not pressed or presence time stamp timed out.') { setTimeout(() => { this.tryToGetAuth(); }, 1000); } else { endLoading(); this.options.callback({ error: true, message: result.message, additional: 'sadly not got a accaess code for you.' }) // console.log(result); } } else { endLoading(); result.ip = this.ip; this.options.callback(result) // console.log(result); } } ) } getChar() { const CODE_CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split(''); return CODE_CHARACTERS[Math.round(Math.random() * CODE_CHARACTERS.length)]; } getCodeVerifier() { let s = "" for (var i = 0; i < this.options.CODE_LENGTH; i++) { s += this.getChar() } return s; } } module.exports = { Authenticate };