UNPKG

homebridge-homeconnect

Version:

A Homebridge plugin that connects Home Connect appliances to Apple HomeKit

158 lines 8.2 kB
// Homebridge plugin for Home Connect home appliances // Copyright © 2023-2025 Alexander Thoukydides import chalk from 'chalk'; import { APIStatusCodeError } from './api-errors.js'; import { assertIsDefined, columns } from './utils.js'; // Colours for the help message const COLOUR_LO = chalk.green.dim; const COLOUR_HI = chalk.greenBright; // Generate helpful information for authorisation errors export class AuthHelp { // Retrieve the structured help message getStructured() { return this.message; } // Retrieve the message as text getText(useColour = false) { // Help isn't always available if (!this.message) return []; // Add text with optional formatting const text = []; const addLines = (lines, colour = COLOUR_LO) => { text.push(...lines.map(line => useColour ? colour(line) : line)); }; const addLink = (description, uri, colour = COLOUR_LO) => { let lines = [`${description}:`, ` ${uri}`]; if (useColour) lines = [colour(lines[0]), colour.bold(lines[1])]; text.push(...lines); }; // Prescript addLines(this.message.prescript, COLOUR_HI); // Write the client creation/modification guide if (this.message.client) { const { action, uri, settings } = this.message.client; addLink(`${{ create: 'Create a new', modify: 'Edit the' }[action]} application`, uri, COLOUR_HI); addLines(['Ensure that the application settings are configured as follows:']); addLines(columns(Object.entries(settings)).map(line => ` ${line}`)); } // Postscript with extra support from the Home Connect Developer Portal addLines(this.message.postscript); addLink('Descriptions of authorisation error messages can be found in the Home Connect API documentation', 'https://api-docs.home-connect.com/authorization?#authorization-errors'); addLink('For additional support contact the Home Connect Developer team', 'https://developer.home-connect.com/support/contact'); return text; } // Write the help message to the log log(log) { for (const line of this.getText(true)) log.warn(line); } } // Generate helpful information for Device Flow authorisation errors export class AuthHelpDeviceFlow extends AuthHelp { // Create a new help object constructor(err, clientid) { super(); // Only provide help when the status code was 400 if (!(err instanceof APIStatusCodeError)) return; if (err.response?.statusCode !== 400) return; // Decode the problem this.message = { prescript: [], postscript: [] }; const action = this.decodeError(err, clientid); // Provide guidance for modifying or recreating the client if (action === 'create' || action === 'modify') this.clientSettingsGuide(action, clientid); // Provide guidance for setting the clientid this.clientChangeGuide(action); } // Decode the error message to provide suitable advice decodeError(err, clientid) { assertIsDefined(this.message); const { prescript } = this.message; switch (err.key) { case 'access_denied': prescript.push('The specified Home Connect or SingleKey ID account cannot currently be used.' + ' Check that it works correctly in the iPhone Home Connect app.' + ' It may be necessary to convert a Home Connect account to a SingleKey ID,' + ' or accept new terms of use within the app.'); break; case 'expired_token': // "Device authorization session not found, expired or blocked" prescript.push('Authorisation of the Home Connect or SingleKey ID took too long.' + ' Visit the provided web link and complete authorisation quickly.', 'Pay careful attention to any error messages displayed on the Home Connect / SingleKey ID web pages.'); break; case 'invalid_client': // "client secret validation failed" prescript.push('Client Secret is not required with Device Flow authorisation.' + ' Remove "clientsecret" from the "config.json" file (or set it to the correct value).'); break; case 'unauthorized_client': return this.decodeUnauthorizedClient(err, clientid); } } // Decode an 'unauthorized_client' error message decodeUnauthorizedClient(err, clientid) { assertIsDefined(this.message); const { prescript } = this.message; switch (err.description) { case 'Invalid client id': if (clientid.length !== 64) { prescript.push('The Client ID should be 64 hexadecimal characters,' + ` but the value specified for "clientid" is ${clientid.length} characters long.`); return 'set'; } else if (!/^[0-9A-F]+$/i.test(clientid)) { prescript.push('The Client ID should be 64 hexadecimal characters,' + ' but the value specified for "clientid" includes non-hexadecimal characters.'); return 'set'; } else { prescript.push('The configured Client ID does not appear to be a valid Home Connect application.'); return 'modify'; } case 'request rejected by client authorization authority (developer portal)': prescript.push('The configured Client ID does not appear to be a valid Home Connect application.' + ' If it was created recently then it may still be propagating to the authorisation servers.'); return 'modify'; case 'client not authorized for this oauth flow (grant_type)': prescript.push('The configured Client ID has been incorrectly configured' + ' with the OAuth Flow set to "Authorization Code Grant Flow".' + ' Create a new application using "Device Flow" instead.' + ' This setting cannot be changed after the application has been created.'); return 'create'; } } // Provide guidance for creating or modifying an application clientSettingsGuide(action, clientid) { const settings = { 'Home Connect User Account': 'Same as the Home Connect or SingleKey ID email address', 'Success Redirect': 'Leave blank', 'One Time Token': 'Not ticked', 'Status': 'Enabled', 'Client Secret Always Required': 'No', 'Sync to China': 'Enabled if located in China, otherwise Disabled' }; if (action === 'create') settings['OAuth Flow'] = 'Set to "Device Flow"'; const uri = action === 'create' ? 'https://developer.home-connect.com/applications/add' : `https://developer.home-connect.com/applications/${clientid}/edit`; assertIsDefined(this.message); this.message.client = { action, settings, uri }; } clientChangeGuide(action) { assertIsDefined(this.message); const { postscript } = this.message; if (action === 'create' || action === 'modify') { postscript.push('Accurately copy the Client ID value (64 hexadecimal characters) from the Home Connect Developer Program' + ' site to the "clientid" field of the "config.json" configuration file.'); } postscript.push('Note that applications created or edited on the Home Connect Developer Program site often take' + ' several minutes to propagate to the authorisation servers.' + ' If you think the configuration is correct, then wait 15 minutes and try again' + ' before seeking help elsewhere or reporting an issue.'); } } //# sourceMappingURL=api-ua-auth-help.js.map