#invoke API Multi Channel Encapsulation Command zwavejs-ui

1 messages · Page 1 of 1 (latest)

prime flower
#

Hi guys.
I would like to send the multichannel encapsulation command with a binary switch to turn off multiple lights (endpoints) at the same time.

action:` zwave_js.invoke_cc_api
data:
  device_id:
    - 1b91e4e4bbe15a3788a8a2535e997f5d
  command_class: "96"
  method_name: sendEncapsulated
  parameters:
    - encapsulated:
        command_class: "37"
        method_name: set
        device_id: 1b91e4e4bbe15a3788a8a2535e997f5d
        value: false
      destination: "123456" ```


I have tried several times changing the syntax but I always get an error:

zwave_js.invoke_cc_api Endpoint(node_id=3, index=0) - FailedCommand: unknown_error: TypeError: this.encapsulated.serialize is not a function at MultiChannelCCCommandEncapsulation2.serialize (/usr/src/app/node_modules/@zwave-js/cc/src/cc/MultiChannelCC.ts:1460:28) at SendDataBridgeRequest2.serializeCC (/usr/src/app/node_modules/@zwave-js/serial/src/serialapi/transport/SendDataBridgeMessages.ts:178:43) at Driver.exceedsMaxPayloadLength (/usr/src/app/node_modules/zwave-js/src/lib/driver/Driver.ts:7852:34) at simpleMessageGenerator (/usr/src/app/node_modules/zwave-js/src/lib/driver/MessageGenerators.ts:140:39) at AsyncGenerator.next () at maybeTransportServiceGenerator (/usr/src/app/node_modules/zwave-js/src/lib/driver/MessageGenerators.ts:244:17) at AsyncGenerator.next () at gen (/usr/src/app/node_modules/zwave-js/src/lib/driver/MessageGenerators.ts:981:41) at gen.next () at Transaction.generateNextMessage (/usr/src/app/node_modules/zwave-js/src/lib/driver/Transaction.ts:149:49).

what am I doing wrong?
thanks in advance
exotic jasper
#

First destination is a number, or an array of numbers. So [1, 2, 3, 4, 5, 6]

#

Second, HA doesn't know anything about the shape of the parameters. The encapsulated entry needs to be a Z-Wave JS data type

#
export interface MultiChannelCCCommandEncapsulationOptions {
    encapsulated: CommandClass;
    destination: MultiChannelCCDestination;
}
#

The type is a class, not a simple object

#

The HA action passes data as JSON to the Z-Wave JS API, I don't know if it's possible to do what you want

#
export interface CCAddress {
    nodeId: number | MulticastDestination;
    endpointIndex?: number;
}

export interface CommandClassOptions extends CCAddress {
    ccId?: number; // Used to overwrite the declared CC ID
    ccCommand?: number; // undefined = NoOp
    payload?: Uint8Array;
}
#

Not sure if this will even work:

  parameters:
    - encapsulated:
        nodeId: <your node id>
        ccId: 37
        ccCommand: 1
        payload: [0]
      destination: [1, 2, 3, 4, 5, 6]
#

Or

  parameters:
    - encapsulated:
        nodeId: <your node id>
        ccId: 37
        ccCommand: 1
        payload:
          type: Buffer
          data: [0]
      destination: [1, 2, 3, 4, 5, 6]
polar blaze
#

I think the main problem is that encapsulated is supposed to be a CC instance, not a dictionary. So this particular api is not going to work like you attempt to use it (as json via websockets).

Executing a JS driver function via MQTT may be an alternative.

exotic jasper
#

Also the root endpoint will often set all the endpoints, not sure if that's an option with this device.

prime flower
#

I tried both of your solutions and I still get the exact same error.
how can i send this via mqtt? can you give me an example?

polar blaze
#

Which device is that?

prime flower
polar blaze
#

Can you share a driver log on loglevel debug where you interview both?
It might be that using endpoint 0 would control both channels, but Z-Wave JS hides it because it thinks it's unnecessary

prime flower
#

do you mean this log?
https://paste.debian.net/1369060

together with a friend of mine with more programming skills we modified the file located in MultiChannelCC.js:
/var/lib/docker/overlay2/979b01a99ed086bb2584328cc87ab7a56dab49878a3c4a5b7221dc1cefead34d/diff/opt/node_modules/@zwave-js/cc/build/cjs/cc/MultiChannelCC.js

so done it works correctly on vitrum keyboards with the string that I pasted at the beginning of the post.
this obviously means not being able to update zwave js anymore and so I was looking for a way to make it work natively.

this is the link to see the file differences:
https://www.diffchecker.com/ObZWA2oU/

polar blaze
#

The "native" way would be telling Z-Wave JS UI to execute some JS code, we call that "driver function". AFAIK that's not exposed via websockets, so you'd need an mqtt connection to Z-Wave JS UI on top

#

Will check the log when I find some time. May be tonight, maybe tomorrow.

prime flower
exotic jasper
prime flower
exotic jasper
#

You just write javascript code similar to that

#

referring to the CommandClass parts

#

I think your log posted is incomplete. The start of the interview is not included.

prime flower
prime flower
polar blaze
#

Before we go too deep into driver functions, can you try setting the corresponding value on endpoint 0?

Essentially take this as a starting point and select the device you want to control:

action: zwave_js.set_value
data:
  command_class: 37
  endpoint: 0
  property: targetValue
  value: true
#

Many multichannel devices expose functionality to control all channels at once on endpoint 0

prime flower
#

I tried but unfortunately I get this error

Impossibile eseguire l'azione: zwave_js.set_value Node(node_id=2) - NotFoundError: Value 2-37-0-targetValue not found on node Node(node_id=2)

polar blaze
#

ah, that's probably HA being too strict

#

I think there's a way around

#

@exotic jasper do you remember how to have Z-Wave JS set the value even if HA thinks it does not exist?

prime flower
#

maybe I'm not good with java but I still haven't managed to get the direct commands from driver function to work.
if you give me an example I can try to send the message directly from there bypassing home assistant.

polar blaze
#

This should do it, replace 3 with your node ID, and true with falseif you want to turn off:

const node = driver.controller.nodes.get(3);
node.commandClasses["Binary Switch"].set(true);
prime flower
#

ok I did the test. it only turns on enpoint 1

polar blaze
#

😦

#

Ok, give me a minute to translate the multi-endpoint stuff into a driver function

#

Try this:

const { logger, zwaveClient, require } = this;
const { BinarySwitchCCSet, MultiChannelCCCommandEncapsulation } = require("zwave-js");

const nodeId = 3;
let cc = new BinarySwitchCCSet({
    nodeId,
    targetValue: true
});
cc = new MultiChannelCCCommandEncapsulation({
    nodeId,
    destination: [1,2,3,4,5,6],
    encapsulated: cc,
});
await driver.sendCommand(cc)
prime flower
#

It works perfectly like this.
What magic!! THANKS
Now I have to figure out how to convert this string to mqtt and I have solved my problem for now.
any help is welcome

prime flower
#

nothing to do I can't do it in any way!
if you have a solution I will gladly accept it otherwise thanks anyway for all the help guys!!

polar blaze
#

There should be a way, but I don't know how.

prime flower
#

thanks anyway you were so helpful. let's see if @exotic jasper answers in the next few hours otherwise I'll close.

exotic jasper
#

You have to use the set_value service

#

Oh, you were doing that

#

You can't

#

invoke_cc_api is the workaround

polar blaze
#

The question is how to execute a driver function from HA via MQTT

#

Multi endpoint addressing doesn't work via other apis

exotic jasper
prime flower
#

I already tried but with this specific action I couldn't make it work via mqtt

#

If you want to create an example for me I would be grateful otherwise don't worry

exotic jasper
#

what's your action code?

#

and topic?

prime flower
#

I would like to send exactly this via mqtt:

const { logger, zwaveClient, require } = this;
const { BinarySwitchCCSet, MultiChannelCCCommandEncapsulation } = require("zwave-js");

const nodeId = 3;
let cc = new BinarySwitchCCSet({
    nodeId,
    targetValue: true
});
cc = new MultiChannelCCCommandEncapsulation({
    nodeId,
    destination: [1,2,3,4,5,6],
    encapsulated: cc,
});
await driver.sendCommand(cc)

topic:
zwave/_CLIENTS/ZWAVE_GATEWAY-Mosquitto/api/driverFunction/set

exotic jasper
#

The code just goes into the payload. { "args": [ code ] }. What did you try?

#

It's JSON so the code needs to be wrapped in a string, { "args": [ "const { logger ..."] }

#

It probably doesn't like the multilines, so you may need to collapse everything to a single line (; separated). Also, use ' instead of "" or escape them.

#
{"args": ["const { logger, zwaveClient, require } = this; const { BinarySwitchCCSet, MultiChannelCCCommandEncapsulation } = require(\"zwave-js\"); const nodeId = 3; let cc = new BinarySwitchCCSet({ nodeId, targetValue: true }); cc = new MultiChannelCCCommandEncapsulation({ nodeId, destination: [1,2,3,4,5,6], encapsulated: cc, }); await driver.sendCommand(cc);"]}
prime flower
#

awesome!!!!! it worked perfectly!
Thanks guys. I love this world because there are people like you!

exotic jasper
#

A bit of a pain, but does the job

#

I posted in your GH discussion

prime flower
#

I saw. Thanks again.

exotic jasper
#

This might work as well:

{% set code %}
const { logger, zwaveClient, require } = this;
const { BinarySwitchCCSet, MultiChannelCCCommandEncapsulation } = require("zwave-js");

const nodeId = 3;
let cc = new BinarySwitchCCSet({
    nodeId,
    targetValue: true
});
cc = new MultiChannelCCCommandEncapsulation({
    nodeId,
    destination: [1,2,3,4,5,6],
    encapsulated: cc,
});
await driver.sendCommand(cc)
{% endset %}

action: mqtt.publish
data:
  topic: zwave/_CLIENTS/ZWAVE_GATEWAY-Mosquitto/api/driverFunction/set
  payload: >
    {"args": {{ code|tojson }}}