diff --git a/api/lib/ZwaveClient.ts b/api/lib/ZwaveClient.ts index 24e6473d96..27ee7f3ece 100644 --- a/api/lib/ZwaveClient.ts +++ b/api/lib/ZwaveClient.ts @@ -108,6 +108,9 @@ import { ProvisioningEntryStatus, AssociationCheckResult, LinkReliabilityCheckResult, + JoinNetworkOptions, + JoinNetworkStrategy, + JoinNetworkResult, } from 'zwave-js' import { getEnumMemberName, parseQRCodeString } from 'zwave-js/Utils' import { configDbDir, logsDir, nvmBackupsDir, storeDir } from '../config/app' @@ -217,6 +220,8 @@ export const allowedApis = validateMethods([ 'checkForConfigUpdates', 'installConfigUpdate', 'shutdownZwaveAPI', + 'startLearnMode', + 'stopLearnMode', 'pingNode', 'restart', 'grantSecurityClasses', @@ -2927,6 +2932,50 @@ class ZwaveClient extends TypedEventEmitter { } } + /** + * Stops learn mode + */ + stopLearnMode(): Promise { + if (this.driverReady) { + if (this.commandsTimeout) { + clearTimeout(this.commandsTimeout) + this.commandsTimeout = null + } + return this._driver.controller.stopJoiningNetwork() + } + + throw new DriverNotReadyError() + } + + /** + * Starts learn mode + */ + async startLearnMode(): Promise { + if (this.driverReady) { + if (this.commandsTimeout) { + clearTimeout(this.commandsTimeout) + this.commandsTimeout = null + } + + this.commandsTimeout = setTimeout( + () => { + this.stopLearnMode().catch(logger.error) + }, + (this.cfg.commandsTimeout || 0) * 1000 || 30000, + ) + + const joinNetworkOptions: JoinNetworkOptions = { + strategy: JoinNetworkStrategy.Default, + } + + return this._driver.controller.beginJoiningNetwork( + joinNetworkOptions, + ) + } + + throw new DriverNotReadyError() + } + /** * Request an update of this value * diff --git a/src/views/ControlPanel.vue b/src/views/ControlPanel.vue index 52deb02f82..c13080fa42 100644 --- a/src/views/ControlPanel.vue +++ b/src/views/ControlPanel.vue @@ -321,6 +321,25 @@ export default { color: 'warning', desc: 'Allows to shutdown the Zwave API to safely unplug the Zwave stick.', }, + { + text: 'Learn mode', + options: [ + { + name: 'Start', + action: 'startLearnMode', + args: { + confirm: + 'Initiate learn mode on primary controller first and then click OK here.', + }, + }, + { + name: 'Stop', + action: 'stopLearnMode', + }, + ], + icon: 'join_inner', + desc: 'Instruct controller to run learning mode (can join pre-existing network)', + }, ], rules: { required: (value) => {