UNPKG

homebridge-homeconnect

Version:

A Homebridge plugin that connects Home Connect appliances to Apple HomeKit

150 lines 5.25 kB
// Homebridge plugin for Home Connect home appliances // Copyright © 2023-2025 Alexander Thoukydides import { elementWithAbsolutePaths, cloneTemplate, getHTML } from './utils-dom.js'; // A configuration form handler export class Form { // Create a configuration form constructor(log) { this.log = log; } // Retrieve and display the form async createForm() { // Retrieve the form schema and data const schema = await this.getSchema(); const data = await this.getData(); // Create the form (adding header and footer) const patchedSchema = this.patchSchema(schema); this.log.debug('createForm', patchedSchema, data); this.form = window.homebridge.createForm(patchedSchema, data); // Return any changes to the configuration this.form.onChange(config => this.putData(config)); } // Hide the form (implicitly called if a different form is created) destroyForm() { this.form?.end(); this.form = undefined; } // Add a header and footer to the schema form patchSchema(schema) { const form = [ ...(schema.form ?? []), ...this.formFromTemplate('hc-form-footer') ]; return { ...schema, form }; } // Create a form item from a template formFromTemplate(...args) { const template = cloneTemplate(...args); const absTemplate = elementWithAbsolutePaths(template); return this.formFromHTML(absTemplate); } // Create a form item from an HTML element formFromHTML(element) { return [{ type: 'help', helpvalue: getHTML(element) }]; } } // A global configuration form handler export class GlobalForm extends Form { constructor(log, ipc, config) { super(log); this.ipc = ipc; this.config = config; } getSchema() { return this.ipc.request('/schema/global', null); } getData() { return this.config.getGlobal(); } putData(data) { return this.config.setGlobal(data); } } // An configuration form handler for a specific appliance export class ApplianceForm extends Form { constructor(log, ipc, config, haid) { super(log); this.ipc = ipc; this.config = config; this.haid = haid; } getSchema() { return this.ipc.request('/schema/appliance', this.haid); } getData() { return this.config.getAppliance(this.haid); } putData(data) { return this.config.setAppliance(this.haid, data); } } // A placeholder form handler export class TemplateForm extends Form { constructor(log, ...args) { super(log); this.elementAsForm = this.formFromTemplate(...args); } // Create a placeholder schema using the specified HTML element async getSchema() { return Promise.resolve({ schema: { type: 'object', properties: {} }, form: this.elementAsForm }); } async getData() { return Promise.resolve({}); } async putData() { } } // Identifiers for special forms export var FormId; (function (FormId) { FormId["Global"] = "global"; FormId["Placeholder"] = "placeholder"; FormId["Unavailable"] = "unavailable"; })(FormId || (FormId = {})); // Type guard to check whether a string is a special form identifier function isFormId(value) { return Object.values(FormId).includes(value); } // Manage the configuration forms export class Forms { // Create a new form manager constructor(log, ipc, config) { this.log = log; this.ipc = ipc; this.config = config; this.showForm(); } // Display the specified form (defaulting to the placeholder) async showForm(formId) { try { // The forms are retrieved from the server, so display a spinner window.homebridge.showSpinner(); // Display the requested form, with fallback to the error form try { await this.constructAndShowForm(formId ?? FormId.Placeholder); } catch (err) { this.log.warn('Failed to display form', formId, err); await this.constructAndShowForm(FormId.Unavailable); } } finally { // Ensure that the spinner is always hidden window.homebridge.hideSpinner(); } } // Try to create the requested form, with fallback to the placeholder async constructAndShowForm(formId) { const form = this.constructForm(formId); await form.createForm(); this.currentForm = form; } // Create a specific form constructForm(formId) { if (isFormId(formId)) { switch (formId) { case FormId.Placeholder: return new TemplateForm(this.log, 'hc-form-placeholder'); case FormId.Unavailable: return new TemplateForm(this.log, 'hc-form-unavailable'); case FormId.Global: return new GlobalForm(this.log, this.ipc, this.config); } } else { return new ApplianceForm(this.log, this.ipc, this.config, formId); } } } //# sourceMappingURL=forms.js.map