Basic vs Binary report

Very new here...

I have a GE Z-wave Switch that I'm using without a load, to mirror another connected to a load.

Had it set up through Smartthings and it worked okay, but felt that the latency was kinda inconsistent.

Set it up with Hubitat and the latency was worse, way worse -- nearly three seconds.

I looked at the log and it was obvious that the latency was from the switch, not the hub, since the event was delayed with respect to the push.

If I held the button, the latency was much better.

Hooked it all back up to Smartthings and found that the switch is sending two reports. The basic report (nearly instant) and the binary report (about 2.5 seconds later). From reading, it looks like these go out on separate comm channels.

I don't see this basic report in Hubitat. Why not? Is it not looking at the second comm channel? Is there something I need to do to select which report I want to act on?

I don't care about the scenes/double taps/holds, just the toggles that are included in the basic report.

Looks like the type of reports that get logged could be driver dependent, as discussed here:

How annoying.. Per z-wave spec:
SwitchBinary is the preferred switch command class..
SwitchMultilevel is the preferred dimmer command class..

Basic is like a catch all, it’s supposed to be used for command classes that aren’t supported. It’s functionality is sometimes ambiguous and I really wish manufacturers would just stop using this.

1 Like

I have at least 3 devices where the basic report happens measurably faster than the binary report, though...

So for devices where you want the best performance, sometimes you need to use basic... Can say "well they screwed up the firmware then", which I would probably agree is true. But in the end, it is what it is - at least without replacing devices.

It is annoyingly redundant, and inconsistent across manufacturers, though. Agree 100% there!

1 Like

So is there any way to choose which command class is used by the built-in driver? It's using:

GE Enbrighten Z-Wave Smart Switch

Or do I need to write/install an alternate user driver?

Or is there a generic driver that only supposed basic?

Nice, so when we were having the C7 certified one of the failures they noted was that our switch and dimmer drivers were responding to basic reports and not binary and multilevel reports, since they wouldn't tell us which device/drivers they were using for testing we had no choice but to update all of them...

1 Like

Figures.. Right @mike.maxwell

2 Likes

Yeah... On the device cert process they only look that the device responds as expected to the command classes, not that it is performant - although they will comment if they see something crazy slow.

Had a very in depth discussion with an unnamed company that has many certified devices on this very topic.

It is a funny world we live in. And certification is only as good as what they test in said certification.

2 Likes

Well, I'm absolutely sure that Z-Wave LR will fix everything...

6 Likes

+1 for Mike.

1 Like

Hmm, I'm sensing a lot of snark, but what do you guys suggest doing?

for now I would use one of @JasonJoel's drivers (presuming he's parsing basic)...
It's possible we may revisit this in the future, but for now that's the best that we can do.

Okay sounds good, does he have a github or something?

Yes. Also available in Hubitat Package Manager, too.

What device are we taking about though? What I did largely depends on the device.

  • In my GE Enbrighten driver (new zwave plus models) I am NOT using the basic report...
  • In my pre-Enbrighten driver (older zwave plus models) I am using Basic Report. Probably because it was faster, but who can remember?

:man_shrugging:

Thanks! Will have to look up the package manager, hadn't heard of it yet.

The device is the GE branded version of ZW4008:
https://products.z-wavealliance.org/products/3317

That is the new style, so would use the Enbrighten driver. I'm not sure that you will find mine any faster than the in-box though as I think we are processing the same zwave reports (as mentioned above I don't use the basic report in that driver).

[quote="[RELEASE] GE/Jasco Z-Wave Plus Dimmer Driver, post:94, topic:9492"]
else, would have noticed it before though. [EDIT: See 2 posts below for the reason why it doesn't send a basic report on ON/OFF] @mike.maxwell Did anything change on zwave basic report parsin…
[/quote]

I don't know if this concept will help anybody else developing a driver that they want to use for multiple devices and may have to resolve the ambiguity of BasicReport versus SwitchBinary versus the multiLevel reports, but since I haven't seen this done anywere else, I'll toss out a suggestion.

What I do is I catch all the report types and then hand them off to a common processing routine for handling. In that routine, I then use some device.hasCapability and device.hasAttribute processing to figure out what really needs to be done (I have other sections of code where I pre-gather all of the class version #s and look at the inClusters to figure out aspects of what needs to be done). This saves me from writing multiple handling routines and ensures that the handling considers all possibilities and their interactions in one code block.

See below for a sample where I catch any of SwitchBinary, Basic, and SwitchMultiLevel, in any of their versions (I include all versions so code can be more easily re-used, though I can probably just handle the latest version) and process them using a common set of handling code with works for basic, SwitchBinary, and SwitchMultiLevel, and in both non-endpoint and endpoint cases. This is part of a "larger" package of code that I plan to release to the "community" as a library of re-usable routines after 2.2.5 is out - I'm still fixing a few bugs and improving clarity and there are a few 2.2.5 command class upgrades/fixes that I want to incorporate.

//////////////////////////////////////////////////////////////////////
//////        Handle Basic Reports and Device Functions        ///////
////////////////////////////////////////////////////////////////////// 

// @Field static  ConcurrentHashMap<Long, Boolean> EventTypeIsDigital = new ConcurrentHashMap<Long, Boolean>()

// next two functions use a ConcurrentHashMap to store operating state information. I found this more reliable than storing to "state" or "device"

Boolean isDigitalEvent() { return getDeviceMapByNetworkID().get("EventTypeIsDigital") as Boolean }
void setIsDigitalEvent(Boolean value) { getDeviceMapByNetworkID().put("EventTypeIsDigital", value as Boolean)}

void zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, ep = null) 			{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.switchbinaryv2.SwitchBinaryReport cmd, ep = null)  			{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd, ep = null) 							{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.basicv2.BasicReport cmd, ep = null) 							{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, ep = null)	{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.switchmultilevelv2.SwitchMultilevelReport cmd, ep = null)	{ processDeviceReport(cmd, ep) }
void zwaveEvent(hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd, ep = null)	{ processDeviceReport(cmd, ep) }
void processDeviceReport(cmd,  ep)
{
	def targetDevice
	if (ep) {
		targetDevice = getChildDevices().find{ (it.deviceNetworkId.split("-ep")[-1] as Integer) == ep}
	} else { targetDevice = device }	

	Boolean isSwitch = targetDevice.hasAttribute("switch") || targetDevice.hasCapability("Switch") || targetDevice.hasCapability("Bulb")  \
					|| targetDevice.hasCapability("Light") || targetDevice.hasCapability("Outlet")  || targetDevice.hasCapability("RelaySwitch")
	Boolean isDimmer = targetDevice.hasAttribute("level")  || targetDevice.hasCapability("SwitchLevel")
	Boolean turnedOn = false
	Integer newLevel = 0

	if (cmd.hasProperty("duration")) //  Consider duration and target, but only when process a BasicReport Version 2
	{
		turnedOn = ((cmd.duration as Integer == 0 ) && ( cmd.value as Integer != 0 )) || ((cmd.duration as Integer != 0 ) && (cmd.targetValue as Integer != 0 ))
		newLevel = ((cmd.duration as Integer == 0 ) ? cmd.value : cmd.targetValue ) as Integer
	} else {
		turnedOn = (cmd.value as Integer) > (0 as Integer)
		newLevel = cmd.value as Integer
	}
	
	String priorSwitchState = targetDevice.currentValue("switch")
	String newSwitchState = (turnedOn ? "on" : "off")
	Integer priorLevel = targetDevice.currentValue("level")
	Integer targetLevel = ((newLevel == 99) ? 100 : newLevel)
	
    if (isSwitch && (priorSwitchState != newSwitchState))
	{
		targetDevice.sendEvent(	name: "switch", value: newSwitchState, 
						descriptionText: "Device ${targetDevice.displayName} set to ${newSwitchState}.", 
						type: isDigitalEvent() ? "digital" : "physical" )
		if (txtEnable) log.info "Device ${targetDevice.displayName} set to ${newSwitchState}."
	}
	if (isDimmer && turnedOn) // If it was turned off, that would be handle in the "isSwitch" block above.
	{
		// Don't send the event if the level doesn't change except if transitioning from off to on, always send!
		if ((priorLevel != targetLevel) || (priorSwitchState != newSwitchState))
		{
			targetDevice.sendEvent( 	name: "level", value: (newLevel == 99) ? 100 : newLevel, 
					descriptionText: "Device ${targetDevice.displayName} level set to ${targetLevel}%", 
					type: isDigitalEvent() ? "digital" : "physical" )
			if (txtEnable) log.info "Device ${targetDevice.displayName} level set to ${targetLevel}%"		
		}
	}

	if (!isSwitch && !isDimmer) log.warn "For device ${targetDevice.displayName} receive a BasicReport which wasn't processed. Need to check BasicReport handling code." + cmd
	setIsDigitalEvent( false )
}

For those interested, the more complete code is here: GitHub - jvmahon/HubitatCustom

2 Likes

As you expected, I tried out your Enbrighten driver and got similar results.

I then added the Hub to association group 2 using zwave.associationV2.associationSet.

That seemed to have the desired effect to receive the basic reports, but they are actually delayed more than the binary reports (about a half second later).

Now I'm pretty confused. As I mentioned in the first post, I was able to see basic reports in the SmartThings hub logs almost instantly (using the Z-Wave tweaker).

Now I'm thinking maybe I should query the device configuration when connected to Smart Things to see what else could be different.

Okay, now I'm stumped.

When I am attached to SmartThings, I see CommandClass 0x20, 0x25, and 0x5B reports on association group 1. Generally, the basic report (0x20) is sent about 2 seconds before the binary report (0x25), which is sent about 0.5 seconds before the CentralScene report (0x5B).

When I am attached to Hubitat (C-7, fw 2.2.4.158), I only see CommandClass 0x25 and 0x5B reports on association group 1. Generally, the the binary report (0x25) is sent about 0.5 seconds before the CentralScene report (0x5B). I do see 'basic sets' on association group 2, though they are delayed with respect to the binary report on association group 1.

I'm printing everything I receive in the parse() function. Is it possible that the Hubitat is filtering out basic reports/sets on association group 1 before they are passed to the driver?

Wouldn't think so - I get basic reports on all sorts of devices.

If I get time this weekend I can take a peek at this device again, though.