Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multicast/broadcast apis #25

Merged
merged 32 commits into from
Mar 15, 2021
Merged

feat: multicast/broadcast apis #25

merged 32 commits into from
Mar 15, 2021

Conversation

robertsLando
Copy link
Member

Fixes #24

@coveralls
Copy link

coveralls commented Nov 24, 2020

Pull Request Test Coverage Report for Build 653435850

  • 15 of 129 (11.63%) changed or added relevant lines in 4 files are covered.
  • 14 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.2%) to 18.201%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/MqttClient.js 0 8 0.0%
types/index.d.ts 0 8 0.0%
lib/Gateway.js 15 57 26.32%
lib/ZwaveClient.js 0 56 0.0%
Files with Coverage Reduction New Missed Lines %
lib/Gateway.js 14 19.63%
Totals Coverage Status
Change from base Build 653429998: -0.2%
Covered Lines: 2025
Relevant Lines: 11410

💛 - Coveralls

@robertsLando robertsLando requested a review from chrisns November 24, 2020 16:07
lib/Gateway.js Outdated
Comment on lines 471 to 476
for (let i = 0; i < values.length; i++) {
const valueId = this.topicValues[values[i]]
if (nodes.indexOf(valueId.nodeId) >= 0) {
this.zwave.writeValue(valueId, payload.value)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm never a fan of this syntax.
personally find

values
  .filter(value => nodes.includes(this.topicValues[value].nodeId))
  .forEach(value => this.zwave.writeValue(this.topicValues[value], payload.value))

easier to read, but may just personal choice

README.md Outdated
@@ -728,6 +729,30 @@ I will set the Heating setpoint of the node with id `4` located in the `office`

`zwave/office/nodeID_4/thermostat_setpoint/heating`

### Multicast

You can send Multicast requests to _all values with a specific suffix_ of a _group_ of nodes in the network.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really clear on this, maybe provide a use case from the outset such as adjusting all your thermostats/lights?

be clearer that this is just a shorthand, it's not an actual multicast, behind the scenes zj2m is doing the heavy lifting and iterating

Copy link
Member

@AlCalzone AlCalzone Nov 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zwave-js does support actual multicast (if you use the same command and target the same endpoint of all nodes).

But it doesn't go through the commandClasses API that is being used here. Might be a good idea for a new feature , so you can grab a group of nodes and send a single multicast command to all of them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've raised zwave-js/node-zwave-js#1150 to track that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, what you can do already is this:

const cmd = new BinarySwitchCCSet(driver, {
	nodeId: [2,3,4,5],
	targetValue: true,
});
await driver.sendCommand(cmd);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree with that i really would like to send a group of nodes the command at the same time using a real multicast if that is possible.

Why, because i found it nice that all nodes respond at the same time, now it takes upto 5 seconds to respond.
Which is also generating errors like #26

My feeling about this is that since all these nodes are generating data (e.g. power reports, closing / dimming duration reports) that it become quite busy on the network, therefore i would like to send it using a real multicast to the nodes so that they all do receive the command before it is getting busy on the network.

If i see it now it looks like this is the same as what i can do within openhab

Shutters_Goup_All.members.forEach[ shutter | shutter.sendCommand(100) ]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should wait for: zwave-js/node-zwave-js#1150 Before going on with this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, what you can do already is this:

@AlCalzone How could I get the correct command class constructor based on the command class id?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README.md Outdated
@@ -728,6 +729,30 @@ I will set the Heating setpoint of the node with id `4` located in the `office`

`zwave/office/nodeID_4/thermostat_setpoint/heating`

### Multicast

You can send Multicast requests to _all values with a specific suffix_ of a _group_ of nodes in the network.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree with that i really would like to send a group of nodes the command at the same time using a real multicast if that is possible.

Why, because i found it nice that all nodes respond at the same time, now it takes upto 5 seconds to respond.
Which is also generating errors like #26

My feeling about this is that since all these nodes are generating data (e.g. power reports, closing / dimming duration reports) that it become quite busy on the network, therefore i would like to send it using a real multicast to the nodes so that they all do receive the command before it is getting busy on the network.

If i see it now it looks like this is the same as what i can do within openhab

Shutters_Goup_All.members.forEach[ shutter | shutter.sendCommand(100) ]

README.md Outdated Show resolved Hide resolved
@robertsLando
Copy link
Member Author

@ODINServ Could you give this a try?

@robertsLando
Copy link
Member Author

@ODINServ @AlCalzone I'm still not 100% sure about using this way as it just works for not secure devices. I think the old way was 'dirty' and slow but at least it works

@AlCalzone
Copy link
Member

AlCalzone commented Dec 14, 2020

I'm still not 100% sure about using this way as it just works for not secure devices. I think the old way was 'dirty' and slow but at least it works

What about this approach you could extend later when we have S2 support to create and use S2 Multicast groups.

  1. checking which devices are insecure and using multicast on them. If that fails (command not supported), fall back to 2.
  2. doing one-by-one singlecast on the rest

The tricky part about real multicast is that you can only use it for set-type commands, not ones that expect a response.

try {
const multicastGroup = this.driver.controller.getMulticastGroup(nodes)

await multicastGroup.setValue(valueId, value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I wrote in my comment, I would check for ZWaveErrorCodes.CC_NotSupported and fall back to iterating singlecast requests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlCalzone Could this cause multiple writes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the checks happen before anything is sent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧
I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

lib/Gateway.js Outdated Show resolved Hide resolved
lib/Gateway.js Outdated Show resolved Hide resolved
lib/Gateway.js Outdated Show resolved Hide resolved
lib/Gateway.js Outdated Show resolved Hide resolved
lib/Gateway.js Outdated Show resolved Hide resolved
lib/ZwaveClient.js Outdated Show resolved Hide resolved
lib/ZwaveClient.js Outdated Show resolved Hide resolved
@robertsLando
Copy link
Member Author

@AlCalzone

@AlCalzone
Copy link
Member

Multicast SETs don't poll (because that would require one GET for each node, defeating the purpose of a multicast). But we should assume that the command was accepted by all nodes if it succeeds like we already do for singlecasts.

@ODINServ
Copy link

ODINServ commented Feb 2, 2021

I was very busy lately and did not have any time to work on my home automation stuff.

So to summarize what i did:

  • I re-included all nodes unsecured to reduce my strange network issues. (I dont have any now :))
  • The last thing i did was running my setup "the npm way" just after the new broadcast API became available via MQTT.
    • Which i'm using now for 1.5 months without any issues!

From: @blhoward2

This does exactly what I'm looking for and I think it would be heavily used if people knew what it could do

Agreed maby this feature requests will solve this: #70

I'd switched to this branch (without linking the node-zwave-js module) and tested it.

For me with my FGR223 modules this is working as expected with the same results and question that @blhoward2 has.

Node 3 turned off physically, but remained on in HA.

From @AlCalzone

Multicast SETs don't poll (because that would require one GET for each node, defeating the purpose of a multicast). But we should assume that the command was accepted by all nodes if it succeeds like we already do for singlecasts.

So when using the (new) broadcast API, the values are updated when (in my case) the shutters reach there targetValue, not sure if this info helps.

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

3 similar comments
@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

@robertsLando robertsLando requested a review from AlCalzone March 10, 2021 07:58
@robertsLando
Copy link
Member Author

@blhoward2 Could you give this a try?

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

@zwave-js-assistant
Copy link

🚧 It seems like this PR has lint errors 🚧

I should be able to fix them for you. If you want me to, just comment
@zwave-js-bot fix lint

docs/guide/mqtt.md Outdated Show resolved Hide resolved
docs/guide/mqtt.md Outdated Show resolved Hide resolved
docs/guide/mqtt.md Outdated Show resolved Hide resolved
@robertsLando robertsLando requested a review from AlCalzone March 10, 2021 09:18
AlCalzone
AlCalzone previously approved these changes Mar 10, 2021
@blhoward2
Copy link
Collaborator

blhoward2 commented Mar 15, 2021

@robertsLando So I've tested this around a dozen times on a variety of devices and it seems to work pretty flawlessly. The weirdness I had before with one switch that didn't go off the full way has resolved itself. Some of my switches do in fact call back in their new state, so they update in HA. For others, they do not change as we're still waiting on @AlCalzone for zwave-js/node-zwave-js#1550. I think this is ready to go.

Topic: homeassistant/_CLIENTS/ZWAVE_GATEWAY-MQTT/multicast/set

{
"commandClass": 32,
"property": "targetValue",
"value": 255,
"nodes": [3, 5, 9, 13, 14, 19, 20, 21, 70, 112, 113, 114, 116, 117, 125]
}

@robertsLando
Copy link
Member Author

Thanks for your feedback @blhoward2, based on this seems that it should be good on my side, can I merge this?

docs/guide/mqtt.md Outdated Show resolved Hide resolved
@robertsLando robertsLando changed the title feat: multicast api feat: multicast/broadcast apis Mar 15, 2021
@robertsLando robertsLando merged commit 98e145d into master Mar 15, 2021
@robertsLando robertsLando deleted the feat#multicast branch March 15, 2021 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feat] Multicast commands
6 participants