UNPKG

homebridge-hilo

Version:

Plugin Homebridge (non officiel) pour la passerelle et les appareils Hilo de Hydro-Québec | Unofficial Homebridge plugin for Hydro-Québec Hilo bridge and devices

254 lines 11.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = default_1; const config_1 = require("./config"); const logger_1 = require("./logger"); const api_1 = require("./api"); const hiloApi_1 = require("./hiloApi"); const devices_1 = require("./devices"); const subscription_1 = require("./subscription"); const location_1 = require("./location"); const types_1 = require("./devices/types"); const HiloChallengeSensor_1 = require("./devices/HiloChallengeSensor"); const axios_1 = __importDefault(require("axios")); const PLUGIN_NAME = "homebridge-hilo"; const PLATFORM_NAME = "Hilo"; function default_1(api) { api.registerPlatform(PLATFORM_NAME, Hilo); } class Hilo { constructor(log, config, api, accessories = {}) { this.log = log; this.config = config; this.api = api; this.accessories = accessories; this.pluginAccessories = {}; this.locations = []; this.subscriptions = {}; this.oldApiDevices = []; this.staleAccessories = []; (0, config_1.setConfig)(config); this.config = (0, config_1.getConfig)(); if (!this.config.refreshToken) { this.log.error("Please login with hilo in the plugin configuration page"); return; } (0, logger_1.setLogger)(log); (0, api_1.setApi)(api); log.info("Initializing Hilo platform"); api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, async () => { this.locations = await fetchLocations(); if (this.locations.length === 0) { log.error("No locations found"); return; } const devices = (await Promise.all(this.locations.map((location) => (0, location_1.fetchDevicesForLocation)(location.locationHiloId)))) .flatMap((response) => response) .filter((device) => types_1.SUPPORTED_DEVICES.includes(device.__typename)); this.oldApiDevices = (await Promise.all(this.locations.map((location) => fetchDevices(location)))).flatMap((response) => response); if (devices.length === 0) { log.error("No devices found"); return; } devices.forEach((device) => { this.log.debug("Initializing device", device); const oldDevice = this.oldApiDevices.find((d) => d.hiloId === device.hiloId); if (!oldDevice) { this.log.error("No old device found for", device); return; } let accessory = this.accessories[device.hiloId]; if (!accessory) { this.log.debug(`Setting up new accessory for device ${device.hiloId}`); accessory = this.setupNewAccessory(device, oldDevice); } else if (accessory.context.device.type !== "Challenge") { this.log.debug(`Setting up cached accessory for device ${device.hiloId}`); accessory.context = { device: oldDevice, graphqlDevice: device, }; } const pluginAccessory = devices_1.initializeHiloDevice[device.__typename](accessory, this.api); this.pluginAccessories[device.hiloId] = pluginAccessory; }); this.setupSubscriptions(); const currentDeviceHiloIds = this.oldApiDevices.map((device) => device.hiloId); this.staleAccessories.concat(Object.values(this.accessories).filter((accessory) => { if (accessory.context.device.type === "Challenge") { return false; } else { return !currentDeviceHiloIds.includes(accessory.context.device.hiloId); } })); this.log.debug(`Found ${this.staleAccessories.length} stale accessories removing...`); this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, this.staleAccessories); if (this.config.noChallengeSensor !== true) { // Add Hilo Challenge sensor for each location this.log.info("Setting up Hilo Challenge sensors"); this.locations.forEach((location) => { const challengeDevices = this.setupHiloChallengeDevices(location); setInterval(async () => { this.updateChallenges(location, challengeDevices); }, /* 4 hours */ 4 * 60 * 60 * 1000); this.updateChallenges(location, challengeDevices); }); } log.info("Hilo platform is ready"); }); } setupHiloChallengeDevices(location) { return [ "preheat", "reduction", "recovery", "plannedAM", "plannedPM", "inProgress", ].map((phase, index) => { const challengeId = `${phase}-hilo-challenge-${location.id}`; const challengeName = `${phase.charAt(0).toUpperCase() + phase.slice(1)} Hilo Challenge ${location.name}`; let challengeAccessory = this.accessories[challengeId]; if (!challengeAccessory) { const uuid = this.api.hap.uuid.generate(challengeId); challengeAccessory = new this.api.platformAccessory(challengeName, uuid); challengeAccessory.context = { device: { assetId: challengeId, id: location.id + index + 100, name: challengeName, type: "Challenge", locationId: location.id, modelNumber: "Hilo Challenge", identifier: challengeId, hiloId: challengeId, }, v4Device: { value: false, phase, localId: challengeId, }, }; this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [ challengeAccessory, ]); this.accessories[challengeId] = challengeAccessory; } else { challengeAccessory.context = { device: { assetId: challengeId, id: location.id + index + 100, name: challengeName, type: "Challenge", locationId: location.id, modelNumber: "Hilo Challenge", identifier: challengeId, hiloId: challengeId, }, v4Device: { value: false, phase, localId: challengeId, }, }; } return new HiloChallengeSensor_1.HiloChallengeSensor(challengeAccessory, this.api, this.log); }); } async setupSubscriptions() { for (const location of this.locations) { try { const subscription = await (0, subscription_1.setupSubscription)(location.locationHiloId, (device) => { this.log.debug(`Device update received:`, device); const oldApiDevice = this.oldApiDevices.find((d) => d.hiloId === device.hiloId); if (!oldApiDevice) { this.log.error("No old device found for", device); return; } const accessory = this.accessories[device.hiloId]; const pluginAccessory = this.pluginAccessories[device.hiloId]; if (!accessory || !pluginAccessory) { this.log.debug(`No accessory for device ${device.hiloId}`); return; } pluginAccessory.updateDevice(device); }); this.subscriptions[location.locationHiloId] = subscription; this.log.info(`Subscribed to updates for location ${location.locationHiloId}`); } catch (error) { this.log.error(`Failed to subscribe to location ${location.locationHiloId}:`, error instanceof Error ? error.message : String(error)); } } } configureAccessory(accessory) { this.log.debug(`Configuring accessory from cache ${accessory.displayName}`); if (accessory.context.device.type !== "Challenge" && !accessory.context.device.hiloId) { this.log.warn(`Could not configure accessory ${accessory.displayName}`); this.staleAccessories.push(accessory); return; } this.accessories[accessory.context.device.hiloId] = accessory; } setupNewAccessory(device, oldApiDevice) { const uuid = this.api.hap.uuid.generate(oldApiDevice.assetId); const accessory = new this.api.platformAccessory(oldApiDevice.name.trim(), uuid); accessory.context = { device: oldApiDevice, graphqlDevice: device, }; this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [ accessory, ]); this.accessories[device.hiloId] = accessory; return accessory; } async updateChallenges(location, challengeDevices) { if (this.config.noChallengeSensor === true) { return; } try { const response = await hiloApi_1.hiloApi.get(`/GDService/v1/api/Locations/${location.id}/Events`, { params: { active: true } }); const challenges = response.data; challengeDevices.forEach((device) => device.updateChallengeStatus(challenges)); } catch (error) { this.log.error("Could not retrieve Hilo Challenges", error); } } } async function fetchLocations() { (0, logger_1.getLogger)().debug("Fetching locations"); try { const response = await hiloApi_1.hiloApi.get("/Automation/v1/api/Locations", { params: { force: true }, }); return response.data; } catch (error) { (0, logger_1.getLogger)().error("Error while fetching locations", error instanceof Error ? error.message : String(error)); return []; } } async function fetchDevices(location) { var _a; (0, logger_1.getLogger)().debug("Fetching devices for location", location.name); try { const response = await hiloApi_1.hiloApi.get(`/Automation/v1/api/Locations/${location.id}/Devices`, { params: { force: true }, }); return response.data; } catch (error) { (0, logger_1.getLogger)().error("Error while fetching devices", axios_1.default.isAxiosError(error) ? (_a = error.response) === null || _a === void 0 ? void 0 : _a.data : error); return []; } } //# sourceMappingURL=hilo.js.map