Zigbee Fan Canopy Module | Project Cheryl

Here’s the binding instructions for Home Assistant:

I also received my blue canopy controllers last week! I installed one on the fan in my office and will debug the process there before deploying to places where my wife will be unhappy if things don’t work properly :rofl:

I am a hubitat user and am having several issues. I am trying to use zigbee bindings to directly connect a blue 2 in 1 switch to the blue canopy, and then also use the hubitat button controller to also control the canopy so I can toggle the light on/off and fan speeds from my desk with a sonoff zigbee button (which I already use to toggle office power on/off).

The canopy and drivers work great using commands from the hubitat web xface. But I can’t get the bindings to work at all. Tapping the switch paddles and config button do-nothing at the canopy. I’ve tried binding the switch to the canopy parent driver – that didn’t work. I also tried binding the switch to one of the child drivers for fan or light – that didn’t work either.

My button controller doesn’t work either. I have a button tap setup to toggle the light on/off. But it will only turn the light on. I checked events for the light and tapping the button always calls for “light on” even though the button is set to “toggle” a switch. Similar for the fan. Double-tapping the button should cycle the fan, but it only turns it on. I’ve used sonoff buttons around my home for similar toggling actions with various zwave and zigbee switches and never had a problem until using with the blue canopy.

1 Like

Not sure if you referred to these, but here are the official help docs:

1 Like

Yup – I have those resources. Again, the driver works fine within the hubitat xface. WRT button mapping, when I use the hubitat button app to map a button gesture to toggle the fan or light it only turns them on. But if I press the toggle button within the hubitat driver web xface the light and/or fan toggle on/off correctly. I am confident that I’m using the button toggle feature in hubitat correctly because the capability works with every button and every other switch I own. The same button I’m using here properly toggles my peanut plug on/off.

WRT the bindings help and setup for inovelli on hubitat, I am admittedly new to using them. My problem is the instructions are for switch-to-switch and switch-to-smartbulb. There are no specific instructions for the proper way to map bindings for the 2 in 1 blue switch to the canopy device (or child devices). I’m probably doing something wrong and just need guidance for this specific config.

Will try to focus on what might be the easier part first: Button controller problems… Here are screen shots of the fan and light child events. The events at the top are responses to the button presses that are setup to toggle the device. They only turn things on, not off. The events below them are responses to the toggle box on the driver web xface in hubitat (works properly).


Here is the event log from my sonoff button. Ignore the label on the events I need to update that. Single-tap is toggle light on/off, double-tap is cycle-fan speeds.

I just got it today, and with a VZM31-SN, i want it to do:

Hubitat

paddle = light and fan on/off
config button = toggle though fan speeds off-low-med-high

i figured i could do some of this via zigbee binding…
at least paddle do light, and config button toggle speeds
i did bind VZM31-SN ep 0x02 to modules ep 0x01 and got light going.
but that’s about all i can achieve
i figured bind VZM31-SN ep 0x03 to modules ep 0x02 and fan would work, on the config button, it doesnt… how to know the endpoints available on the switch, im guessing its just 1? so how should the config button change fan speed? (via binding)

also is the fan child device missing the current fanspeed feedback?

also where does one find the button numbering scheme for VZM31-SN?

oh man the drivers for hubitat are quite beta, why the fan child has stuff in it about LEDs
needs cleanup bigtime

so i did what i needed to do with button controller…
but the fan child doesnt even track the current state of the fan
these drivers are very incomplete… or the firmware isnt reporting fan speed
cyclespeed always, does off->low
just a mess right now

@mitchjs which hub are you using? In hubitat, I used the zigbee bindings app recommended by Inovelli.
I configured “Office Light Switch” which is a VZM31-SN blue 2-in-1 to the “Office Light-Fan” which is a VZM36 Blue Canopy Light-Fan Switch. Binding is from switch to canopy switch itself and not the canopy switch child(s) for fan/light… Tapping the paddle and config buttons on the wall switch do nothing at the canopy, but the canopy is working because I can control it from the hubitat web xface. I’m using latest drivers and firmware for the wall switch and canopy switch. Stumped…

OK – PROGRESS!!! After my last post, I removed the binding instance and re-created it EXACTLY THE SAME WAY. That resulted in the paddle switch turning the light on and off. But the config switch does not control the fan.

So… I added another binding from the blue wall switch to the blue canopy module, but this time specified 0x02 (wall) to 0x02 (canopy). That resulted in the paddle turning on the fan and light on tap-up and turning both off with tap-down. Config switch did nothing. I removed the binding from 0x02 to 0x02 but the wall switch continued to turn-on both light and fan. So I re-created the binding from 0x02 to 0x02 but selected “unbind” in hubitat zigbee bindings app and saved it. This returned the paddle to turning on the light-only.

So… What I’ve learned is…

  1. Bindings created in the app can get corrupted or something. Unbinding and/or uninstalling a binding can sometimes fix a problem.
  2. Binding to the canopy module (not the child) is correct. 0x01 is the light and 0x02 is the fan.
  3. The blue 2 in 1 switch bound to either endpoint in the blue canopy binds the paddles but the config button presently does nothing.

Based on my experience and reading other threads here, that the blue 2-in-1 switch needs a firmware update so that it can control two devices (fan and light) separately. Inovelli: What say you???

@geekdaddy i was able to already do what you discovered
the paddle binds to the light
i got hunch we need some firmware update for the switch, to add endpoint of the config button

Yup, same with the light … So the fan always shows as off in HomeKit

Again agreed, “Cycle Speed” button will never work since it can’t get the current speed to set the next. Both

device.currentValue("level")

and

device.currentValue("speed")

return “null”.

i been fixing up the drivers, they are a COMPLETE MESS!!!
at this point @Eric_Inovelli needs to get involved!!!

i got a working cyclespeed… but its actually more than that…
there is crap that is in the child that shouldnt be and stuff missing in the main device missing
ie bindings for reporting of clusters

I can also confirm that fan cycle-speed is not working for me in Hubitat. It simply turns the fan on, doesn’t cycle the speed, and therefore doesn’t cycle to an off position.

i have hacked it to work…
there are 2 lines in the main device code, that need to be uncommented
the reporting bindings for endpoint #2

then there are bunch of lines in the fan child that need a tweak

but the driver still is what i call a MESS, and needs to be fixed ASAP
sure i can do it, but really should be done by Inovelli :slightly_smiling_face:

prob shouldnt post any code here… i could put them in a temp folder in my github
but in main driver, remove // on line 504 & 506, save, then go to driver and click configure
that will bind ep2 (fan) to report on/off and speed

but because they started with another driver for the children… which are a complete mess of code

you have to fix a few lines in the fan child driver
line 874 & 943 should be: if (state.model?.substring(0,5)=="VZM36") { //FOR FANs ONLY

then a little tweak to the if statement in the the cyclespeed method

def cycleSpeed() {    // FOR FAN ONLY
    def cmds =[]
    if (parameter158=="1" || parameter258=="1") {
		toggle()    //if we are in on/off mode then do a toggle instead of cycle
		return
    } else {
        def currentLevel = device.currentValue("level")==null?0:device.currentValue("level").toInteger()
        if (device.currentValue("switch")=="off") currentLevel = 0
		boolean smartMode = device.currentValue("smartFan")=="Enabled"
        def newLevel = 0
		def newSpeed =""
		if (smartMode)
			if      (currentLevel<=0 ) {newLevel=20;  newSpeed="low" }
			else if (currentLevel<=20) {newLevel=40;  newSpeed=(smartMode?"medium-low":"medium")}
			else if (currentLevel<=40) {newLevel=60;  newSpeed="medium"}
			else if (currentLevel<=60) {newLevel=80;  newSpeed=(smartMode?"medium-high":"high")}
			else if (currentLevel<=80) {newLevel=100; newSpeed="high"}
			else                       {newLevel=0;   newSpeed="off"}
		else 
            if      (currentLevel<=0 ) {newLevel=33;  newSpeed="low" }
			else if (currentLevel<=33) {newLevel=66;  newSpeed="medium"}
			else if (currentLevel<=66) {newLevel=100; newSpeed="high"}
			else                       {newLevel=0;   newSpeed="off"}
        if (infoEnable) log.info "${device.displayName} cycleSpeed(${device.currentValue("speed")?:off}->${newSpeed})"
        state.lastCommandSent =                        "cycleSpeed(${device.currentValue("speed")?:off}->${newSpeed})"
        state.lastCommandTime = nowFormatted()
		//cmds += zigbee.command(CLUSTER_LEVEL, LEVEL_CMD_MOVE_TO_LEVEL_ON_OFF, zigbee.convertToHexString(newLevel,2), "ffff")
		cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(newLevel),2)} FFFF}"
    }
    if (debugEnable) log.debug "${device.displayName} cycleSpeed $cmds"
    sendHubCommand(new HubMultiAction(delayBetween(cmds, shortDelay), Protocol.ZIGBEE))
}

it seems when not in smartfan mode (what ever that concept is)
the speeds are 0,33,66,100
course i dont know what the modules real numbers are for the 3 speeds, but
the setSpeed method uses these too

just want to be clear, there is much more that needs to be cleaned up, especially in the child drivers

I believe they forgot to push the updated code and firmware. The driver for 2-1 switch mentions 2.16+ firmware yet we only have 2.15. So I am sure once they get on an realize they will get an update pushed. Just give them at least a day before we get the torches and pitchforks .

@Courtney_Inovelli @Eric_Inovelli @EricM_Inovelli

1 Like

Thanks!

Hmm those seem to be lines 890 and 959 with the latest driver code on GitHub (ON_OFF CLUSTER and LEVEL CONTROL CLUSTER, correct?)

Beyond the change to “cycleSpeed” (which should really call setSpeed …) if you want the fan to play nice with HomeBridge you’ll also need to modify “setSpeed” since HomeBridge is sending the speeds “medium-low” and “medium-high” or low and medium respectively. the need to be set to “33” and “66” in non-smartMode:

def setSpeed(value) {  // FOR FAN ONLY
    if (infoEnable) log.info "${device.displayName} setSpeed(${value})"
    state.lastCommandSent =                        "setSpeed(${value})"
    state.lastCommandTime = nowFormatted()
	def currentLevel = device.currentValue("level")==null?0:device.currentValue("level").toInteger()
	if (device.currentValue("switch")=="off") currentLevel = 0
	boolean smartMode = device.currentValue("smartFan")=="Enabled"
	def newLevel = 0
    def cmds = []
    switch (value) {
        case "off":
            //cmds += zigbee.off(shortDelay) 
            cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 6 0 {}"
            break
        case "low": 
            //cmds += zigbee.setLevel(smartMode?20:33)
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(smartMode?20:33),2)} 0xFFFF}"
            break
        case "medium-low":             //placeholder since Hubitat natively supports 5-speed fans
            //cmds += zigbee.setLevel(40) 
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(smartMode?40:33),2)} 0xFFFF}"
            break
        case "medium": 
            //cmds += zigbee.setLevel(smartMode?60:66) 
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(smartMode?60:66),2)} 0xFFFF}"
            break
        case "medium-high":            //placeholder since Hubitat natively supports 5-speed fans
            //cmds += zigbee.setLevel(80)
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(smartMode?80:66),2)} 0xFFFF}"
            break
        case "high": 
            //cmds += zigbee.setLevel(100) 
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(100),2)} 0xFFFF}"
            break
        case "on":
            //cmds += zigbee.on(shortDelay)
            cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 6 1 {}"
            break
		case "up":
			if      (currentLevel<=0 )  {newLevel=20}
			else if (currentLevel<=20)  {newLevel=(smartMode?40:60)}
			else if (currentLevel<=40)  {newLevel=60}
			else if (currentLevel<=60)  {newLevel=(smartMode?80:100)}
			else if (currentLevel<=100) {newLevel=100}
            //cmds += zigbee.setLevel(newLevel)
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(newLevel),2)} 0xFFFF}"
			break
		case "down":
			if      (currentLevel>80) {newLevel=(smartMode?80:60)}
			else if (currentLevel>60) {newLevel=60}
			else if (currentLevel>40) {newLevel=(smartMode?40:20)}
			else if (currentLevel>20) {newLevel=20}
			else if (currentLevel>0)  {newLevel=currentLevel}
            //cmds += zigbee.setLevel(newLevel)
	        cmds += "he cmd 0x${parent.deviceNetworkId} 0x${device.deviceNetworkId?.substring(device.deviceNetworkId.length()-2)?:"00"} 0x0008 0x04 {${zigbee.convertToHexString(convertPercentToByte(newLevel),2)} 0xFFFF}"
			break
    }
    if (debugEnable) log.debug "${device.displayName} setSpeed $cmds"
    sendHubCommand(new HubMultiAction(delayBetween(cmds, shortDelay), Protocol.ZIGBEE))
}

yes… 890 and 959, woops i also just removed all the bad configure code
434-455, they wouldnt work right anyway… cause it would use the child device address
its all left over code… hopefully Inovelli gets up some clean code ASAP
make sure you change the substring to 0,5 too
really that whole if is pointless, of course its a vzm36, that what the driver is for :slight_smile:

Hmmm, I’m not sure if the latest driver didn’t graduate from beta to production, but I can look into it. We had a couple people on the beta team using Hubitat and didn’t get any complaints. @mitchjs If you have made updates and fixes to what is in github, can you submit a PR and I can merge them into production? Or I can submit them if you want to get them to me.

3 Likes

@EricM_Inovelli , whats now in github, is a mess…
the child drivers where copied from the VMZ35 fan switch
needs tons of cleanup… and you guys know the VMZ36 better than me
like why the fan child has LED stuff, unless your gonna tell me there is some LED on the canopy module itself that can do animations :slight_smile: i of course put it in the fan canopy and can no longer see the module
so to me, all that code should go away

this is what i pulled from github as per your websites instructions
MAIN driverDate : 2024-02-16 (beta)

Yup the latest on Master on GitHub shows the Feb date and beta. Last change was 5 days ago to add the production fingerprint.

Also, any plans to release into Hubitat Package Manager so we don’t have to manually upgrade?