2.2.4 User Zigbee Outbound message

What might the fix be for these errors I now see! Thanks team for 2.2.4

I'm using Marcus' drivers. This device is an Xbee. I'm getting the same error for Tradfi repeaters.

Getting the same with aqara sensors

These are errors that were not exposed prior to 2.2.4, but were observed in support tickets. Unfortunately, the drivers need to be corrected.

2 Likes

Yes, I realise that. Is there any direction for those who maintain drivers?

a single command of "delay xxx" is invalid, delay is designed to be used within a list of commands.
hubAction only sends one command.
So as a start any hubAction that's trying to send a "delay xxx" needs to be removed.

2 Likes

I'm getting same on salus sp600 driver
But I can't see any where where its calling up a delay
sendZigbeeCommands(ArrayList<String> cmds) {

// All hub commands go through here for immediate transmission and to avoid some method() weirdness.

logging("${device} : sendZigbeeCommands received : $cmds", "trace")

hubitat.device.HubMultiAction allActions = new hubitat.device.HubMultiAction()
cmds.each {

	if (it.startsWith("he raw") == true) {
		allActions.add(it)
	} else if (it.startsWith("delay") == true) {
		allActions.add(new hubitat.device.HubAction(it))
	} else {
		allActions.add(new hubitat.device.HubAction(it,     hubitat.device.Protocol.ZIGBEE))
		}

	}

	logging("${device} : sendZigbeeCommands : $cmds", "debug")
	sendHubCommand(allActions)

add -> ,hubitat.device.Protocol.ZIGBEE to each HubAction method

1 Like

Thanks seem to have sorted it,
I'd use the generic zigbee outlet put the power reporting is off

Hi @mark.cockcroft can you tell me what you did to stop the error you listed above. I'm getting the same.
I see you were advised to put in ,hubitat.device.Protocol.ZIGBEE
I've looked through the device driver I'm using and I actually have that in the driver I'm using.
In fact it looks the same as the extract from the driver that you have shown above.
What did you actually do to stop the error.

BTW I'm using the driver called "Salus SP600 Smart Plug" by Andrew Davison.
Thanks.

@mark.cockcroft

It would be helpful to list what you started with, and what the replacement was.

Eg:
Started with: HubAction
Replaced with: hubitat.device.Protocol.ZIGBEE.HubAction

.....with an example please

I've not updated yet so I'm not seeing this, but try this version.

Let me know how it goes.

Hi @andydvsn
I think this has done the trick.
Now when I hit any of 'configure', 'initialise' or 'refresh', I no longer see that error.
Thanks.
Can I ask what you chenged?
Thanks again. :+1:

Ah, that's good to hear.

To double-check, does the driver still return a power reading when 'refresh' is triggered? If it does, all is well.

There was a check which, for reasons I don't remember, didn't append hubitat.device.Protocol.ZIGBEE to the list of actions if the action began with 'delay'. Which, in theory, means there must have been occasions where delay was the only item in the list of commands to transmit. Which doesn't make much sense, but why else would it complain?

Ah, well. In the end it was just deleting these two lines.

I'll have to upgrade a hub and test this out I guess!

1 Like

Yes. When refreshed it reports power.
Here are the logs.
dev:58232020-11-18 09:38:43.750 infoBathroom-Shower Outlet : Switch : On

dev:58232020-11-18 09:38:43.744 infoBathroom-Shower Outlet : Power : 4 W

dev:58232020-11-18 09:38:43.597 infoBathroom-Shower Outlet : Refreshing

1 Like

Okay, just to clarify, is this the correct way to handle things?

	cmds.each {

        if(it.startsWith('delay') == true) {
            allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.DELAY))
        } else {
            allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.ZIGBEE))
        }

	}

Or is my catchall method below fine?

	cmds.each {

		allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.ZIGBEE))

	}

might want to move it over to the SP600 drive thread but yea all i added was the bold bit after the it on the delay line to match the line below in the deriver
startsWith('delay') == true) { allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.DELAY))

As @mike.maxwell mentioned, sending a "delay" to a ZigBee device as a singular HubAction command makes no sense, there's no such device command as delay.

A delay is supposed to be used within a sequence of commands, so for ZigBee like:

"zdo bind ZZZZZZ, delay AAA, he cr YYYYY"

delay is just a marker to signal to HE to delay sending the next command by AAA ms, it doesn't actually get sent to the device.

I've not looked fully at your code, but IMO it would make more sense to use HubMultiAction:

https://docs.hubitat.com/index.php?title=HubMultiAction_Object

allActions.add(new hubitat.device.HubMultiAction(cmds, 
hubitat.device.Protocol.ZIGBEE))

But it depends on what you do with "allActions" ..... for example if that just gets passed to sendHubCommand then I'd just do:

sendHubCommand(new hubitat.device.HubMultiAction(cmds, hubitat.device.Protocol.ZIGBEE))

i.e. just pass your raw cmds list (assuming it's a List of Strings) and let HE figure the rest out :slight_smile:

2 Likes

Sorry, I should have included the context! :slight_smile:

It used to be this:

void sendZigbeeCommands(ArrayList<String> cmds) {

	// All hub commands go through here for immediate transmission and to avoid some method() weirdness.

	logging("${device} : sendZigbeeCommands received : $cmds", "trace")

	hubitat.device.HubMultiAction allActions = new hubitat.device.HubMultiAction()
	cmds.each {

		if (it.startsWith("he raw") == true) {
			allActions.add(it)
		} else if (it.startsWith("delay") == true) {
			allActions.add(new hubitat.device.HubAction(it))
		} else {
			allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.ZIGBEE))
		}

	}

	logging("${device} : sendZigbeeCommands : $cmds", "debug")
	sendHubCommand(allActions)

}

To account for including a (non transmitted) delay, should it now be this:

void sendZigbeeCommands(ArrayList<String> cmds) {

	// All hub commands go through here for immediate transmission and to avoid some method() weirdness.

	logging("${device} : sendZigbeeCommands received : $cmds", "trace")

	hubitat.device.HubMultiAction allActions = new hubitat.device.HubMultiAction()
	cmds.each {

		if (it.startsWith("he raw") == true) {
			allActions.add(it)
		} else if (it.startsWith("delay") == true) {
			allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.DELAY))
		} else {
			allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.ZIGBEE))
		}

	}

	logging("${device} : sendZigbeeCommands : $cmds", "debug")
	sendHubCommand(allActions)

}

For the time being I've just stripped it out as below, but I'm just thinking of code reusability and "the correct way". :slight_smile:

void sendZigbeeCommands(ArrayList<String> cmds) {

	// All hub commands go through here for immediate transmission and to avoid some method() weirdness.

	logging("${device} : sendZigbeeCommands received : $cmds", "trace")

	hubitat.device.HubMultiAction allActions = new hubitat.device.HubMultiAction()
	cmds.each {

		if (it.startsWith("he raw") == true) {
			allActions.add(it)
		} else {
			allActions.add(new hubitat.device.HubAction(it, hubitat.device.Protocol.ZIGBEE))
		}

	}

	logging("${device} : sendZigbeeCommands : $cmds", "debug")
	sendHubCommand(allActions)

}

I would do it as mentioned in my post above .....

void sendZigbeeCommands(List<String> cmds) {
        logging("${device} : sendZigbeeCommands received : ${cmds}", "trace")
        sendHubCommand(new hubitat.device.HubMultiAction(cmds, hubitat.device.Protocol.ZIGBEE))
}

HubMultiAction takes a List of Strings so you can just pass them to the constructor as shown in the doc - HubMultiAction Object - Hubitat Documentation

1 Like

Well, would you look at that! It works for commands both raw and cooked!

Thanks, @martyn, appreciate it. Always happy to simplify some code. :slight_smile: