UNPKG

homey-api

Version:
297 lines (257 loc) 7.91 kB
'use strict'; const Util = require('../Util'); const EventEmitter = require('../EventEmitter'); /** * An authenticated Homey API. Do not construct this class manually. * @class * @hideconstructor */ class HomeyAPI extends EventEmitter { /** * Platforms * @memberof HomeyAPI * @property {object} PLATFORMS * @property {string} PLATFORMS.LOCAL - Homey (2016 — 2019) & Homey Pro (2019 — 2023) * @property {string} PLATFORMS.CLOUD - Homey Cloud * @static */ static PLATFORMS = { LOCAL: 'local', CLOUD: 'cloud', }; /** * Discovery Strategies * @memberof HomeyAPI * @property {object} DISCOVERY_STRATEGIES * @property {string} DISCOVERY_STRATEGIES.CLOUD - Cloud HTTPS, e.g. `https://abcdef.connect.athom.com`. * @property {string} DISCOVERY_STRATEGIES.MDNS - Local HTTP, e.g. `http://homey-abcdef.local` * @property {string} DISCOVERY_STRATEGIES.LOCAL - Local HTTP, e.g. `http://192.168.1.100`. * @property {string} DISCOVERY_STRATEGIES.LOCAL_SECURE - Local HTTPS, e.g. `https://192-168-1-100.homey.homeylocal.com`. * @property {string} DISCOVERY_STRATEGIES.REMOTE_FORWARDED - Remote HTTPS, e.g. `https://12-34-56-78.homey.homeylocal.com:12345`. * @static */ static DISCOVERY_STRATEGIES = { MDNS: 'mdns', CLOUD: 'cloud', LOCAL: 'local', LOCAL_SECURE: 'localSecure', REMOTE_FORWARDED: 'remoteForwarded', }; constructor({ api = null, properties = {}, debug = () => { }, }) { super(); // Set Debug Enabled Object.defineProperty(this, '__debugFunction', { value: debug, enumerable: false, writable: true, }); // Set API Object.defineProperty(this, '__api', { value: api, enumerable: false, writable: true, }); // Set ID Object.defineProperty(this, 'id', { value: properties.id ?? properties._id ?? null, enumerable: true, writable: true, }); // Set Version Object.defineProperty(this, 'version', { value: properties.softwareVersion ?? null, enumerable: true, writable: true, }); // Set Name Object.defineProperty(this, 'name', { value: properties.name ?? null, enumerable: true, writable: true, }); // Set Language Object.defineProperty(this, 'language', { value: properties.language ?? null, enumerable: true, writable: true, }); // Set Role Object.defineProperty(this, 'role', { value: properties.role ?? null, enumerable: true, writable: true, }); // Set Properties Object.defineProperty(this, '__properties', { value: properties, enumerable: false, writable: false, }); } get _id() { throw new Error('HomeyAPI._id is not supported, please use HomeyAPI.id'); } __debug(...props) { if (!this.__debugFunction) return; this.__debugFunction(...props); } /* * Storage */ async __getStore() { if (!this.__api) return {}; const store = await this.__api.__getStore(); return store[`homey-${this.id}`] || {}; } async __setStore(value) { if (!this.__api) return; const store = await this.__getStore(); await this.__api.__setStore({ [`homey-${this.id}`]: { ...store, ...value, }, }); } /* * Internationalization */ /** * Translates an i18n-object (e.g. `{ en: 'My String', nl: 'Mijn tekst' }` to a string. * Uses the language of Homey as defined in {@link Homey}. * @param {object} input * @param {string} input.en - English translation * @param {string} input.nl - Dutch translation * @returns {string|null} - The translated string, or null * @example * homeyApi.__({ * en: 'Hello', * nl: 'Hallo', * fr: 'Bonjour', * }); // returns "Hello" if Homey is set to English */ __(input) { if (typeof input === 'object' && input !== null) { if (typeof input[this.__properties.language] === 'string') { return input[this.__properties.language]; } if (typeof input['en'] === 'string') { return input['en']; } } return null; } /** * Check the current role. * @param {string} roleId - The role ID, e.g. `owner`, `manager`, `user` or `guest`. */ hasRole(roleId) { return this.role === roleId; } /** * Creates a {@link HomeyAPIV3Local} or {@link HomeyAPIV2} instance for use in the Apps SDK. * @param {Object} opts * @param {Homey} opts.homey — Homey (Apps SDK) instance. * @param {Function|null} [opts.debug=null] — Debug function, defaults to `null`. * @example * const { HomeyAPI } = require('homey-api'); * * module.exports = class MyApp extends Homey.App { * * async onInit() { * // Create a HomeyAPI instance. Ensure your app has the `homey:manager:api` permission. * this.homeyApi = await HomeyAPI.createAppAPI({ * homey: this.homey, * }); * * // Get all the devices, and log their names. * const devices = await this.{@link HomeyAPIV3Local homeyApi}.{@link HomeyAPIV3Local.ManagerDevices devices}.{@link HomeyAPIV3Local.ManagerDevices#getDevices getDevices}(); * for(const device of Object.values(devices)) { * this.log(device.name); * } * } * * } */ static async createAppAPI({ homey, debug = null, } = {}) { if (!homey) { throw new Error('Invalid Homey'); } if (debug === true) { debug = (...props) => homey.app.log('[homey-api]', ...props); } const props = { debug: debug ?? function debug() { }, token: await homey.api.getOwnerApiToken(), baseUrl: await homey.api.getLocalUrl(), strategy: [], properties: { id: await homey.cloud.getHomeyId(), softwareVersion: homey.version, }, }; if (homey.platform === 'local' && homey.platformVersion === 1) { const HomeyAPIV2 = require('./HomeyAPIV2'); return new HomeyAPIV2(props); } if (homey.platform === 'local' && homey.platformVersion === 2) { const HomeyAPIV3Local = require('./HomeyAPIV3Local'); return new HomeyAPIV3Local(props); } if (homey.platform === 'cloud' && homey.platformVersion === 2) { const HomeyAPIV3Cloud = require('./HomeyAPIV3Cloud'); return new HomeyAPIV3Cloud(props); } throw new Error(`Invalid Homey Platform Version: ${homey.platformVersion}`); } /** * Creates a {@link HomeyAPIV3Local} instance for use in a project. * @param {Object} opts * @param {String} opts.address — The address of the Homey, e.g. `http://192.168.1.123:80`. * @param {String} opts.token — A Personal Access Token created in the Homey Web App. * @param {Function|null} opts.debug — Debug function, defaults to `null`. * @example * import { HomeyAPI } from 'homey-api'; * const homeyApi = await HomeyAPI.createLocalAPI({ * address: 'http://192.169.1.123', * token: '<my_personal_access_token>', * }); * const devices = await homeyApi.devices.getDevices(); */ static async createLocalAPI({ address, token, debug = null, }) { if (!address) { throw new Error('Invalid Address'); } if (!token) { throw new Error('Invalid Token'); } const res = await Util.fetch(`${address}/api/manager/system/ping`); if (!res.headers.has('X-Homey-ID')) { throw new Error(`No Homey Found At Address: ${address}`); } const props = { token, debug: debug ?? function debug() { }, baseUrl: address, strategy: [], properties: { id: res.headers.get('X-Homey-ID'), softwareVersion: res.headers.get('X-Homey-Version'), }, }; const HomeyAPIV3Local = require('./HomeyAPIV3Local'); return new HomeyAPIV3Local(props); } } module.exports = HomeyAPI;