From 92d502a0ab9aef4efd713e1c9a6286aafd6ee449 Mon Sep 17 00:00:00 2001 From: Daniel Lando Date: Thu, 4 Mar 2021 15:00:22 +0100 Subject: [PATCH] fix: checks on `sendCommand` api (#816) * fix: `sendCommand` api checks * docs: fix typo * fix: lint issues * docs: add link to CCs * fix: cleaner error --- docs/guide/mqtt.md | 5 ++++- lib/ZwaveClient.js | 38 ++++++++++++++++++++++---------------- types/index.d.ts | 6 +++++- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/docs/guide/mqtt.md b/docs/guide/mqtt.md index 37272308bf9..132b0aabf5e 100644 --- a/docs/guide/mqtt.md +++ b/docs/guide/mqtt.md @@ -80,7 +80,10 @@ This are the available apis: - `beginFirmwareUpdate(nodeId, fileName, data, target)`: Starts a firmware update of a node. The `fileName` is used to check the extension (used to detect the firmware file type) and data is a `Buffer` - `abortFirmwareUpdate(nodeId)`: Aborts a firmware update - `writeValue(valueId, value)`: Write a specific value to a [valueId](https://zwave-js.github.io/node-zwave-js/#/api/valueid?id=valueid) -- `sendCommand(valueId, command, args)`: Send a custom command +- `sendCommand(ctx, command, args)`: Send a custom command. + - `ctx`:context to get the instance to send the command (`{ nodeId: number, endpoint: number, commandClass: number }`) + - `command`: the command name. Check available commands by selecting a CC [here](https://zwave-js.github.io/node-zwave-js/#/api/CCs/index) + - `args`: array of arguments to pass to the command ### Api call examples diff --git a/lib/ZwaveClient.js b/lib/ZwaveClient.js index a85d129e498..5754bb736d5 100644 --- a/lib/ZwaveClient.js +++ b/lib/ZwaveClient.js @@ -2376,45 +2376,51 @@ ZwaveClient.prototype.hardReset = async function () { throw Error('Driver is closed') } - -ZwaveClient.prototype.sendCommand = async function (valueId, command, args) { +/** + * Send a command + * + * @param {{nodeId: number, endpoint: number, commandClass: number}} ctx context to get the instance to send the command + * @param {string} command command name + * @param {any[]} args args to pass to `command` + * @returns {Promise} + */ +ZwaveClient.prototype.sendCommand = async function (ctx, command, args) { if (this.driver && !this.closed) { - if (typeof valueId.nodeId !== 'number') { + if (typeof ctx.nodeId !== 'number') { throw Error('nodeId must be a number') } - const error = utils.isValueId(valueId) - - if (typeof error === 'string') { - throw Error(error) - } - if (args !== undefined && !Array.isArray(args)) { throw Error('if args is given, it must be an array') } - const node = this.getNode(valueId.nodeId) + // get node instance + const node = this.getNode(ctx.nodeId) if (!node) { - throw Error(`Node ${valueId.nodeId} was not found!`) + throw Error(`Node ${ctx.nodeId} was not found!`) } - const endpoint = node.getEndpoint(valueId.endpoint || 0) + + // get the endpoint instance + const endpoint = node.getEndpoint(ctx.endpoint || 0) if (!endpoint) { throw Error( - `Endpoint ${valueId.endpoint} does not exist on Node ${valueId.nodeId}!` + `Endpoint ${ctx.endpoint} does not exist on Node ${ctx.nodeId}!` ) } - const api = endpoint.commandClasses[valueId.commandClass] + // get the command class instance to send the command + const api = endpoint.commandClasses[ctx.commandClass] if (!api || !api.isSupported()) { throw Error( - `Node ${valueId.nodeId} (Endpoint ${valueId.endpoint}) does not support CC ${valueId.commandClass}` + `Node ${ctx.nodeId} (Endpoint ${ctx.endpoint}) does not support CC ${ctx.commandClass} or it has not been implemented yet` ) } else if (!(command in api)) { throw Error( - `The command ${command} does not exist for CC ${valueId.commandClass}` + `The command ${command} does not exist for CC ${ctx.commandClass}` ) } + // send the command with args const method = api[command].bind(api) const result = args ? await method(...args) : await method() return result diff --git a/types/index.d.ts b/types/index.d.ts index 848fda907d6..ee30fd97469 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -390,7 +390,11 @@ export interface ZwaveClient extends EventEmitter { ...args: any ): Promise<{ success: boolean; message: string; result: any; args: any[] }> writeValue(valueId: Z2MValueId, value: number | string): Promise - sendCommand(valueId: Z2MValueId, command: string, args: any[]): Promise + sendCommand( + ctx: { nodeId: number; endpoint: number; commandClass: number }, + command: string, + args: any[] + ): Promise } export interface Z2MGateway {