Hampton Bay Zigbee Ceiling Fan/Light Controller installation HOWTO

I wanted to document and share my experience installing and configuring the Hampton Bay Zigbee Ceiling Fan/Light Controller to work with my ADT Smartthings. Both for your benefit, but also for me so I can come back and reference this once I get more of these things are do the next ones.

Background. Well it should be obvious since I am doing home automation that I wanted to automate the functions of the fan and light, and I didn’t want to run extra wires, do drywall work, change boxes, repaint etc… to be able to control the ceiling fan and the ceiling fan light.
I could have gone with smart bulbs and just controlled the lights remotely, the fan itself never gets turned off, just speed adjusted. Even in winter all my ceiling fans are run on low to move air around.

I also needed to refresh this fixture, the thing wobbled like crazy due to bent fan blade arms, and the bulbs were on the way out anyway, this fixture had old CFLs in it, and needed to have some LED bulbs swapped in.

As soon as the controller came in from Home Depot, which is this one, https://www.homedepot.com/p/Hampton-Bay-Universal-Wink-Enabled-White-Ceiling-Fan-Premier-Remote-Control-99432/206591100,

Per the video directions, I set the speed of the fan on high, set the light on, turned the light switch off, and went to the panel and threw the breaker for that room.

Before any of the Zigbee work could start, I had to fix a problem I was having with this ceiling fan. At some point something was run into the blades with the fan on high, damaging the blades and blade arms. Not relevant to MOST folks here, but this bit is, I found it easier to install the ZigBee controller if the blades were uninstalled, it allowed much easier access to the canopy.

I grabbed a set of polished brass Westinghouse ceiling fan blade arms https://amzn.to/2YhmRKY,

And the blades used were Westinghouse 52" reversible oak / walnut ceiling fan blades https://amzn.to/2HB10J9

To perform the installation of the ZigBee controller. I left the fan blades / arms off of the fan until the physical installation was done. I know Home Depot said to fully remove the fan, but why? I need the fan close to make the electrical connections after all! I just loosened each bracket screw until I could shimmy the spacer between it, and the ceiling.

For starters, I started with the first post in the thread


Keep this open in a tab on your browser.
Open each of the github links in a new tab.

Open a new tab and following the instructions linked at


gets me most of the way there, but is missing CRITICAL information. Follow the part about using USING A CUSTOM DEVICE TYPE HANDLER get down to the point of
“DT5) Once the Device Handler is published in your own library,” We then go off on a tangent because it’s at this point things go bad. The instructions just aren’t clear enough at least for me.

Now we go into your mobile device and launch the Smartthings classic app.

Perform the physical installation of the device per the directions.
I found the video on Home Depot’s product website to be FAR more informative than the included documentation.

After the breaker is turned back on, and before you turn on the power switch, this would be a good time to put the fan blades / arms back on and tighten them down.

Once installed and the breaker is on, go to the room with the device, if you are more than say 10’ from the hub, make sure you have a working ZigBee repeater in the room with it.

Turn on the light switch controlling the circuit.

Tap the My Home bottom tab.
Tap the Things tab.
Tap + Add a Thing,

Let it search and find, don’t go looking through the suggestions. Mine comes up as a “Buscop SmartPower Outlet V1”.
That’s fine. Change the device name to what you want.
In this case I just put front room fan.

Go back to the IDE.
click on My Devices.

From the Display Name column, find the name of the device you just found and click it.
Scroll to the bottom of the page and click Edit.
Under the Type drop down list, scroll down almost to the bottom to find and select KOF Zigbee Fan Controller, then go to the bottom of the page and click Update.

Close out any Smarthings app, New or Classic, and relaunch your classic app. Your fan and light controls now show up in the Things tab.
Test, all should work well at this point.

NOTES:

1.) In my case I had misread a setting on the remote itself that actually interfered with the function of the controller. There is a switch that has an O and a D setting for dimmin on and off. I thought I had it in the O position but but lights wouldn’t dim. If dimming fails, try switching this to the other side.
2.) During the physical install, I found it tricky at best to stuff the wiring in a manner that would allow me to actually get the canopy back on. I found that if I stuffed the wires above the controller and back into the box, particularly the wire nuts, the canopy was able to be reinstalled, but boy is it a tight fit! And this is an older (at least 20 year old) Hampton Bay fan.

Lastly the installed pics I kept the antenna wire for the remote outside of the canopy for better reception however I really don’t like the look I have to figure something out.

In order to prevent accidentally turning the power off And to provide storage for the remote but I did was I took a strip of clear packing tape and taped the switch in the open position so that there were as few air bubbles physical as possible. I then took Velcro and cut it in 2 pieces, put a piece on the main part of the remote and the other half on the battery cover and stuck it to the switch plate.

4 Likes

The FAQ was originally written in 2015 and somethings have changed since then. But posts in the forum (unlike the community – created wiki) age out after a while and then you can’t edit them anymore. :disappointed_relieved:

If you read all the way through that thread, you will see that in post 27, the instructions for step five were updated. That would probably have cleared up the confusion.

I know that’s annoying, but it happens in some of the older FAQs.

I figured since I got hit with A bit of confusion by that thread that I will go ahead and write an end-to-end installation write up.

Don’t get me wrong it’s a very good thread as most of them here are, it’s just a very long thread. When you are trying to get to the meat of the matter without being only go back in and re edit see your 1st entry the stuff in the middle tends to get lost.

1 Like

For those that are unaware, these controllers are reported to work best with a zigbee repeater in close proximity.

The IKEA Tradfri Wireless Control Outlet (smart plug) is reportedly a good one, and is currently on sale for $9.99

I’ve got 5 coming that will cover all spaces nicely and give me bedside lamps Automation…

Never mind, that’s the regular price on these!

Fail moment. So I live in Canada and you aren’t able to buy the Hampton Bay Zigbee Ceiling Fan/Light Controller here so I was able to find someone selling one on eBay for a decent deal. I received it and recently installed it. Issue is I did a dumb move when I was installing the fan casing to the housing I cut off the zigbee (white) antenna by accident. So no pairing to SmartThings. I can’t get it to work at all… to no surprise. Without ordering a new one, anyone have any ideas to “MacGyver” a new zigbee antenna on? I tried crimping the antenna back together but that doesn’t seem to have worked. So maybe another solution would be to open the controller and install a new antenna… if there is such a thing.

Thanks in advance.

You can buy replacement antennas on Amazon. I’m in the states so availability might differ from CA?

I don’t remember exactly what the connector on the board was like but I thought it was something like this.

uxcell FPC Built-in Antenna 5dBi 2400-2500MHz U.FL Female Connector RF1.13 Cable, Compatible with WiFi Bluetooth Zigbee Module 2Pcs https://www.amazon.com/dp/B07ZFF1L2P/ref=cm_sw_r_cp_apa_i_Zie2DbR528AVP

Question- I’ve had this working for almost 3 years now but I’ve recently heard that Samsung will force everyone to move to their new app this year. This implementation doesn’t work on the new app, does anyone know if someone has got this going on the new Samsung app?

The information needed to modify the DTH for the new app is not available yet from smartthings. As soon as they release the information, more than likely, someone will modify the DTH to work. Until then I guess we will have to be patient.

I think I have my answer - I just installed the parent/2 child apps and am having the same problem. I’m a recent convert from Wink to ST so I have the latest app installed (IOS). I only see a power button to turn on the fan and the 3 on/off/delay sliders but no control over the fan speed/light (at all inclusive of any dimming).
This is b/c of the need to modify the DTH for the new app, correct, not because of my ineptitude?

That’s correct. Until Smartthings releases the information so that the DTH can be updated, you will have to use the classic app if you want manual control of the fan. The speeds and the light can be controlled with automations in the new app, though.

1 Like

OCW, thanks. I did install the classic app but now, while I can see the “master bedroom fan”, the only ‘control’ I have is an on/off button that when pressed, does not change the status of the either the light or fan. Still not seeing the child handlers or buttons for the fan speed light, nor that nice interface I’ve seen in this (and other threads).
The fan on the classic app only shows the “fan speeed child”
Edit: Weirdly the DTH changed to the fan speed child. I had to reset it to the KOF parent device.

I would try deleting and recreating the child devices.

Press the gear icon in the top right corner to get to the point to recreate them.

Has anyone figured out how to get this to work with the new SmartThings Hub v3 and App?
I was going to program a solution myself, but the tutorials on the new developer website were less than helpful.

Looks like they are working on decommissioning the classic app… I need a working DTH or whatever the new app uses for this device. Is there one that works yet?

BigHoss, just found this update which updated everything inside 'New" Smartthings app.

/*

  • King Of Fans Zigbee Fan Controller
  • Also contains code from https://github.com/DavinKD/SmartThings/blob/master/devicetypes/davindameron/tasmota-fan.src/tasmota-fan.groovy
  • To be used with Ceiling Fan Remote Controller Model MR101Z receiver by Chungear Industrial Co. Ltd
  • at Home Depot Gardinier 52" Ceiling Fan, Universal Ceiling Fan/Light Premier Remote Model #99432
  • Copyright 2020 Rafael Borja, Ranga Pedamallu, Stephan Hackett, Dale Coffing
  • Contributing Authors (based on https://github.com/dcoffing/KOF-CeilingFan):
  •  Ranga Pedamallu; initial release and zigbee parsing mastermind!
    
  •  Stephan Hackett; new composite (child) device type genius! 
    
  •  Dale Coffing; icons, multiAttribute fan, code maintenance flunky
    
  •  Rafael Borja; New version for new Smartthings app (2019)
    
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.
    */

metadata {
definition(name: “King of Fans Zigbee Fan Controller”, namespace: “rafaelborja”, author: “Rafael Borja”, ocfDeviceType: “oic.d.fan”, genericHandler: “Zigbee”) {
capability “Switch Level”
capability “Switch”
capability “Fan Speed”
capability “Health Check”
capability “Actuator”
capability “Refresh”
capability “Sensor”
capability “Configuration”

	command "low"
	command "medium"
	command "high"
	command "raiseFanSpeed"
	command "lowerFanSpeed"
    
    attribute "lastFanMode", "string" // Last fan speed value

	fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0003,0019,0202", outClusters: "0003,0019" , model: "HDC52EastwindFan"
 }
 
   tiles(scale: 2) {
	multiAttributeTile(name: "fanSpeed", type: "generic", width: 6, height: 4, canChangeIcon: true) {
		tileAttribute("device.fanSpeed", key: "PRIMARY_CONTROL") {
			attributeState "0", label: "Off", action: "switch.on", icon: "st.thermostat.fan-off", backgroundColor: "#ffffff"
			attributeState "1", label: "Low", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
			attributeState "2", label: "Medium", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
			attributeState "3", label: "High", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
		}
		tileAttribute("device.fanSpeed", key: "VALUE_CONTROL") {
			attributeState "VALUE_UP", action: "raiseFanSpeed"
			attributeState "VALUE_DOWN", action: "lowerFanSpeed"
		}
	}

	standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
		state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"
	}
	main "fanSpeed"
	details(["fanSpeed", "refresh"])
}

preferences {
    // section("Google assistant fan control using dimmer") {
    input ( type: "paragraph", element: "paragraph", title: "Google assistant fan control using dimmer", description: "\
    		If you are using Google assistant you can set this option to true to control fan speed using light dimmer.\
            Google asistant does not properly support fan speed dial, showing it as a light dimmer instead.\
            When this option is activiated you can set fan speed with the command \"Set <FAN NAME> speed to <0 to 100>\", where:\n\
             - 0 to 24 is speed 25 (turn off),\n\
             - 24 to 49 is speed 1 (low),\n\
             - 50 to 74 is speed 2 (medium),\n\
             - 75 to 100 is speed 3 (high),\n\
             \n\
             \n\
             You can still use the on/off button as usual (fan on/off). To control light level you must use child light device (shown as a regular light)")
             
    	input "dimmerAsFanControl", "enum", title: "Use dimmer to control fan?", options: ["1":"Yes", "0":"No"], displayDuringSetup: true, default: "0"
   // }
   
}

}

def parse(String description) {
log.info “parse($description)”
def event = zigbee.getEvent(description)
if (event) {
// “Sample 0104 0006 01 01 0000 00 D42D 00 00 0000 01 01 010086”

    log.info "Parse description ${description}"
	log.info "Light event detected on controller (event): ${event}"
    
	def childDevice = getChildDevices()?.find {		//find light child device
    	log.debug "parse() child device found"
        it.device.deviceNetworkId == "${device.deviceNetworkId}-Light" 
    }          
    event.displayed = true
    event.isStateChange = true
    
    // TODO find right event
    childDevice.createAndSendEvent(event)
    // childDevice.createAndSendEvent(description)
    childDevice.sendEvent(event)
    // TODO not needed? childDevice.parse(description)
    
    //send light events to light child device and update lightBrightness attribute
    if(event.value != "on" && event.value != "off" && !useDimmerAsFanControl()) {
    	log.debug "sendEvent lightBrightness"
    	
        //  TODO remove unused events
    	// TODO refactor to a single method
        sendEvent(name: "lightBrightness", value: event.value, displayed: true, isStateChange: true) 
        sendEvent(name: "levelSliderControl", value: event.value, displayed: true, isStateChange: true) 
        sendEvent(name: "level", value: event.value, displayed: true, isStateChange: true) 
        sendEvent(name: "switch level", value: event.value, displayed: true, isStateChange: true) 
        
    } else {
    	log.debug "not sending lightBrightness"
    }
}
else {
 	// "Sample: 0104 0006 01 01 0000 00 D42D 00 00 0000 07 01 86000100"
    // "Sample: 0104 0006 01 01 0000 00 D42D 00 00 0000 07 01 00"
    // "Sample: D42D0102020800003000, dni: D42D, endpoint: 01, cluster: 0202, size: 8, attrId: 0000, result: success, encoding: 30, value: 00"
   	log.info "Fan event detected on controller"
	def map = [:]
	if (description?.startsWith("read attr -")) {
		def descMap = zigbee.parseDescriptionAsMap(description)
        log.debug "descMap in parse $descMap"
		if (descMap.cluster == "0202" && descMap.attrId == "0000") {     // Fan Control Cluster Attribute Read Response            	                  
			map.name = "fanMode"
			map.value = descMap.value
            return fanEvents(descMap.value.toInteger())
		} 
	}	// End of Read Attribute Response
	def result = null            
    if (map) {            
		result = createEvent(map)                
	} else {
    	log.debug("parse: event map is null")
    }
	log.debug "Parse returned $map"            
	
    return result 
}                

}

/*

  • Returns the string representing speed value:
    */
    def speedToLabel(speed) {
    def labelMap = [
    “0”:“Off”,
    “1”:“Low”,
    “2”:“Medium”,
    “3”:“Medium-Hi”,
    “4”:“High”,
    “5”:“Off”,
    “6”:“Comfort Breeze™”,
    “7”:“Light”
    ]

    return labelMap["${speed}"]
    }

/**

  • Creates events for Fan based on speed value (switch, level and fan level)
    */
    def fanEvents(speed) {
    log.trace “fanEvents(${speed})”

    def value = (speed ? “on” : “off”) // TODO review this portion as it is sensing light off to child device when changing dimmer value
    def result = [createEvent(name: “switch”, value: value)]
    // result << createEvent(name: “level”, value: speed == 99 ? 100 : speed)
    result << createEvent(name: “fanSpeed”, value: speed)

    // In case dimmer is being used to control fan (Google assitant compatibility)
    if (useDimmerAsFanControl()) {
    log.trace “Sending dimmer events for fan event”
    // TODO remove unused events
    // TODO refactor to a single method
    result << sendEvent(name: “lightBrightness”, value: speedToDimmerLevel(speed), displayed: true, isStateChange: true)
    result << sendEvent(name: “levelSliderControl”, value: speedToDimmerLevel(speed), displayed: true, isStateChange: true)
    result << sendEvent(name: “level”, value: speedToDimmerLevel(speed), displayed: true, isStateChange: true)
    result << sendEvent(name: “switch level”, value: speedToDimmerLevel(speed), displayed: true, isStateChange: true)
    }

    log.trace “fanEvents({speed}) returning {result}”

    return result
    }

def installed() {
log.debug “installed()”
initialize()
}

def updated() {
log.debug “updated()”
/ * if(state.oldLabel != device.label) {updateChildLabel()} */ // TODO DEV ONLY
initialize()
}

def initialize() {
log.info “initialize()”

if(refreshChildren) { 
    deleteChildren()            
    device.updateSetting("refreshChildren", false) 
    refresh()
}
else {
    // createFanChild()
    createLightChild()
    response(refresh() + configure())
}

}

def updateChildLabel() {
log.info “updateChildLabel()”

def childDeviceL = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDeviceL) {childDeviceL.label = "${device.displayName}-Light"}    // rename with new label

}

def createLightChild() {
log.debug “createLightChild()”
def childDevice = getChildDevices()?.find {
it.device.deviceNetworkId == “${device.deviceNetworkId}-Light”
}
if (!childDevice) {

	childDevice = addChildDevice("King of Fans Zigbee Fan - Light Child Device", "${device.deviceNetworkId}-Light", null,[completedSetup: true,
    label: "${device.displayName} Light" ]) /*, isComponent: false, componentName: "fanLight" */
    log.info "Creating child light ${childDevice}" 
}
else {
    log.info "Child already exists"          
}	

}

def deleteChildren() {
def children = getChildDevices()
children.each {child->
deleteChildDevice(child.deviceNetworkId)
}
log.info “Deleting children”
}

def configure() {
log.info “configure() Configuring Reporting and Bindings.”

// Sample "[zdo bind 0xD42D 0x01 0x01 0x0006 {0022A3000016B5F4} {}, delay 2000, st cr 0xD42D 0x01 0x0006 0x0000 0x10 0x0000 0x0258 {}, delay 2000]"

def cmd = 
[
  //Set long poll interval
  "raw 0x0020 {11 00 02 02 00 00 00}", "delay 100",
  "send 0x${device.deviceNetworkId} 1 1", "delay 100",
  //Bindings for Fan Control
  // "zdo bind 0x${device.deviceNetworkId} 1 0 0x006 {${device.zigbeeId}} {}", "delay 100",
  
  "zdo bind 0x${device.deviceNetworkId} 1 1 0x006 {${device.zigbeeId}} {}", "delay 100",
  "zdo bind 0x${device.deviceNetworkId} 1 1 0x008 {${device.zigbeeId}} {}", "delay 100",
  "zdo bind 0x${device.deviceNetworkId} 1 1 0x202 {${device.zigbeeId}} {}", "delay 100",
  //Fan Control - Configure Report
  "zcl global send-me-a-report 0x006 0 0x10 1 300 {}", "delay 100",
   "send 0x${device.deviceNetworkId} 0 1", "delay 100",
   // Light?
  "zcl global send-me-a-report 0x006 1 0x10 1 300 {}", "delay 100",
   "send 0x${device.deviceNetworkId} 1 1", "delay 100",
   
  "zcl global send-me-a-report 0x008 0 0x20 1 300 {}", "delay 100",
   "send 0x${device.deviceNetworkId} 1 1", "delay 100",
  "zcl global send-me-a-report 0x202 0 0x30 1 300 {}", "delay 100",
  "send 0x${device.deviceNetworkId} 1 1", "delay 100",
  //Light Control - Configure Report
  //Update values
  "st rattr 0x${device.deviceNetworkId} 1 0x006 0", "delay 100",
  "st rattr 0x${device.deviceNetworkId} 1 0x006 1", "delay 100", // Light?
  "st rattr 0x${device.deviceNetworkId} 1 0x008 0", "delay 100",
  "st rattr 0x${device.deviceNetworkId} 1 0x202 0", "delay 100",
  
 //Set long poll interval
  "raw 0x0020 {11 00 02 1C 00 00 00}", "delay 100",
  "send 0x${device.deviceNetworkId} 1 1", "delay 100",
  zigbee.configureReporting(0x0006, 0x00011, 0x10, 0, 600, null),
]
return cmd + refresh()

}

def getEndpoint (child) {
log.debug “getEndpoint (${child})”

def endpoint = child.deviceNetworkId == device.deviceNetworkId?getInitialEndpoint():child.deviceNetworkId.minus("-Light")

log.debug "getEndpoint (${child}): {endpoint}"

return endpoint

}

def off (physicalgraph.device.cache.DeviceDTO child) {
log.debug “off (physicalgraph.device.cache.DeviceDTO child ${child})”

def childDevice = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDevice) {
	log.debug "Sending event to child $childDevice"
    log.debug childDevice
	childDevice.createAndSendEvent(name: "switch", value: "off", displayed: true, isStateChange: true) // childDevice.sendEvent(name: "device.switch", value: "off", displayed: true, isStateChange: true) + 
    	// childDevice.sendEvent(name: "switch", value: "off", displayed: true, isStateChange: true) +
    	// childDevice.createAndSendEvent(name: "switch", value: "off", displayed: true, isStateChange: true)
}

lightOff(getEndpoint(child))

}

def on (physicalgraph.device.cache.DeviceDTO child) {
log.debug “on (physicalgraph.device.cache.DeviceDTO child ${child})”

def childDevice = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDevice) {
	log.debug "Sending event to child $childDevice"
    log.debug childDevice
    
	childDevice.createAndSendEvent(name: "switch", value: "on", displayed: true, isStateChange: true) // childDevice.sendEvent(name: "device.switch", value: "on", displayed: true, isStateChange: true) +
    	//childDevice.sendEvent(name: "switch", value: "on", displayed: true, isStateChange: true) +
    	
}

lightOn(getEndpoint(child))

}

/*

  • Called from child device
    */
    def ping(physicalgraph.device.cache.DeviceDTO child) {
    log.debug “ping(${child})”

    return ping()
    }

def on() {
log.debug “on()”
log.info “Resuming Previous Fan Speed”
def lastFan = device.currentValue(“lastFanMode”) //resumes previous fanspeed
return setFanSpeed("$lastFan")
}

def off() {
log.debug “off()”
def fanNow = device.currentValue(“fanSpeed”) //save fanspeed before turning off so it can be resumed when turned back on
log.debug “off(): Current fan speed: $fanNow”
if (fanNow != “00”) {
//do not save lastfanmode if fan is already off
sendEvent(“name”:“lastFanMode”, “value”:fanNow)
}

def cmds=[
"st wattr 0x${device.deviceNetworkId} 1 0x202 0 0x30 {00}"
]
log.info "off(): Turning fan Off"    
return cmds

}

def lightOn(String dni) {
log.info “lightOn(${dni})”

log.debug "Loading childlights"
def childDevice = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDevice) {
	log.debug "Sending event to child"
    log.debug childDevice
	childDevice.sendEvent(name: "device.switch", value: "on", displayed: true, isStateChange: true)
    childDevice.sendEvent(name: "switch", value: "on", displayed: true, isStateChange: true)
    childDevice.createEvent(childDevice.createAndSendEvent(name: "switch", value: "on", displayed: true, isStateChange: true ))
}

return zigbee.on()

}

def lightOff(String id) {
log.info “lightOff(${id})”

log.debug "Loading childlights"
def childDevice = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDevice) {
	log.debug "Sending event to child"
    log.debug childDevice
	childDevice.sendEvent(name: "device.switch", value: "off", displayed: true, isStateChange: true)
    childDevice.sendEvent(name: "switch", value: "off", displayed: true, isStateChange: true)
    childDevice.createEvent(childDevice.createAndSendEvent(name: "switch", value: "off", displayed: true, isStateChange: true ))
}

return zigbee.off()

}

void childOn(String dni) {
log.debug “childOn(String {dni})" lightOn(null) // onOffCmd(0xFF, channelNumber(dni)) } void childOff(String dni) { log.debug "childOff(String {dni})”
lightOff(null)
// onOffCmd(0, channelNumber(dni))
}

def lightLevel(val) {
log.debug “lightLevel(${val})”

zigbee.setLevel(val) + (val?.toInteger() >= 1 ? zigbee.on() : []) 
sendEvent(name:"level",value: val)

log.debug "Loading childlights"
def childDevice = getChildDevices()?.find {
    	it.device.deviceNetworkId == "${device.deviceNetworkId}-Light"
}
if (childDevice) {
	log.debug "Sending event to child"
    log.debug childDevice
	//childDevice.sendEvent(name: "device.value", value: val)
    // childDevice.sendEvent(name: "device.switch", value: "on", isStatusChange: true)
    childDevice.sendEvent(name: "switch", value: isDeviceOn? "on": "off", isStatusChange: true, display: true)
    childDevice.sendEvent(name: "value", value: val, isStatusChange: true, display: true)
    childDevice.createEvent(childDevice.createAndSendEvent(name: "level", value: value,  isStatusChange: true, display: true))
}

}

/**

  • Called from APP when sliding light dimmer
    */
    def setLevel(val, rate = null, device=null) {
    log.debug “setLevel(val={val}, rate={rate},device=${device})”

    def cmds
    if (device != null || !useDimmerAsFanControl() ) {
    // Dimmer acts on lights as usual
    log.info “Adjusting Light Brightness via setlevel on parent: {$val}”
    def isDeviceOn = val?.toInteger() >= 1
    cmds = zigbee.setLevel(val.toInteger(), 1) + refresh()
    }
    else {
    log.info “Slider acting for fan control on setLevel”
    // Dimmer acts on fan control
    cmds = setFanSpeed(dimmerLevelToSpeed(val?.toInteger()))

    }

    log.debug “setLevel(val={val}, rate={rate},device={device}) return {cmds}”

    return cmds
    }

def poll() {
log.debug(“poll()”)
}

// Called from main device from app to set fan speed
def setFanSpeed(speed) {
log.debug “setFanSpeed(${speed})”

def cmds=[
"st wattr 0x${device.deviceNetworkId} 1 0x202 0 0x30 {${speed}}"
]
log.info "Adjusting Fan Speed to "+ speedToLabel(speed)    
return cmds

}

def ping() {
log.debug(“ping()”)
return zigbee.onOffRefresh()
}

def refresh(physicalgraph.device.cache.DeviceDTO child=null) {
log.info "refresh($child) called "

return zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(0x0202, 0x0000) + zigbee.readAttribute(0x0006, 0x0000) +
zigbee.readAttribute(0x0202, 0x0000) + zigbee.readAttribute(0x0202, 0x0001) + zigbee.readAttribute(0x0006, 0x0001) + zigbee.readAttribute(0x0006, 0x0000) +
zigbee.readAttribute(0x0008, 0x0004) + zigbee.readAttribute(0x0008, 0x0004)

}

/**

  • Returns true if 1, dimmer will control fan speed (for Google assistant compatibility)
    */
    def useDimmerAsFanControl() {
    log.trace(“useDimmerAsFanControl(): ${dimmerAsFanControl == 1}”)

    // TODO using number since bool prefs are not saving
    return dimmerAsFanControl == 1
    }

/**

  • Returns a dimmer value for a given speed
    • 0 to 24 is speed 25 (turn off)
    • 24 to 49 is speed 1 (low)
    • 50 to 74 is speed 2 (medium)
    • 75 to 100 is speed 3 (high)
      /
      def speedToDimmerLevel(speed) {
      return speed
      25
      }

/**

  • Returns a fan value for a given dimmer value
    • 0 to 24 is speed 25 (turn off)
    • 24 to 49 is speed 1 (low)
    • 50 to 74 is speed 2 (medium)
    • 75 to 100 is speed 3 (high)
      */
      def dimmerLevelToSpeed(dimmerLevel) {
      if (dimmerLevel == null) {
      dimmerLevel = 0
      }
      return Math.round(dimmerLevel/25)
      }

def raiseFanSpeed() {
setFanSpeed(Math.min((device.currentValue(“fanSpeed”) as Integer) + 1, 3))
}

def lowerFanSpeed() {
setFanSpeed(Math.max((device.currentValue(“fanSpeed”) as Integer) - 1, 0))
}

def low() {
setLevel(32)
}

def medium() {
setLevel(66)
}

def high() {
setLevel(99)
}

Is this in a github repository anywhere?

Hello,

Samsung forced me over to the new app a couple of weeks ago (nightmare). I began using your King of Fans device handlers at that time and they worked fine.

Last night the lights on two fans - without touching any physical switch or the app - started coming on. While on they pulse, dimming down and then back up. If you turn the lights off on the app they come back on, on their own, within a few minutes. The only way to turn them off and keep them off is by using the wall switch, which in our case also disables the fan.

We’re using the Hampton Bay controllers. So far I’ve seen this occur on two of the eight fans we have.

I updated to your latest device handler last night through the IDE Github pull and then directly from Github today (copy and paste) today, but the problem continues. Any help you could provide would be really appreciated.

The github link is 3 years old. Is this the right one? Are the e more recent updates?