[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