Leviton Fan Controller needs SwitchLevel

It seems other drivers such as GE include SwitchLevel or at least port them to MakerAPI. Can we get this added? Workaround is to simply use GE Fan Controller driver.

There's been some historical inconsistency regarding how these are handled, but I think ideally they'd like to see all fan drivers use the FanControl capability. That being said, SwitchLevel has been used on lots of these. I think implenentation of the FanControl capability on the platform side might be a bit newer (SwitchLevel has always been with us, but I can't remember the history of the other). Despite that being perhaps the "purest" way to do it, I'm not denying that SwitchLevel has some advantages--just staying the way they (Hubitat staff) might prefer things to be. Lots of Hubitat apps work with SwitchLevel, probably far more than FanControl. Some third-party integrations also handle one better than the other; for example, I think the Alexa Skill only works with SwitchLevel, as it is basically seen as a dimmer then, though there are plans to address that soon if it hasn't been already.

So, we may or may not see that change. A related question is: do you have a problem you're trying to solve that SwitchLevel solves for you and FanControl doesn't? If so, there might be a workaround. But if you've already found something that works for you (I don't know what specific differences there are between those two drivers, though you may have parameters that exist on one but not the other), I'm not trying to stop you; the only alternative, assuming this won't change, might be seeing if there's a community driver (or writing your own) to expose it as a SwitchLevel device too.

I know this is more of a history lesson than actual help, but maybe something in there will help (or again you might get better ideas if you have a specific problem to solve). Sorry about that part. :laughing:

1 Like

Yes. An issue comes about when interfacing Hubitat to other control systems like HomeKit.

There are several homebridge plugins to interface Hubitat and Homekit, including the one I've published here: homebridge-hubitat - npm. HomeKit fan control is a percentage-based speed control (0 - 100%) rather than a low-medium-high type of control. This also more closely aligns with the Z-Wave system where fan controllers often accept 0 - 99% values (though they often deal with them as 3 or 4 groups, so 1-33 = Low, 34-66 = Medium, 67-99 = high). With these systems in mind, it is useful for drivers to implement both the "FanControl" mechanism as well as use the SwitchLevel mechanism and to have them operate in parallel (even clearer would be for fans to have their own FanSpeedPercent" defined attribute / control).

On a going-forward basis, ceiling fans are now beginning to switch to DC motors rather than AC motors. With DC motors you can get a true percentage-based control so, for future planning, it would make sense to also have drivers understand a percentage-based command. I suspect Apple had this forward-looking view then they decided HomeKit would use a percentage based control. As a practical matter, AC motor fans, which use a fixed bank of capacitors to control speed, are being aged out by manufacturers as they have many disadvantages compared to DC (including hum and higher power usage).

For future use, it seems that it makes a lot of sense to have a percentage based fan control included, and even better if it were a clearly defined "fan-specific" - i.e., a new "FanSpeedPercent"

Finally, there should be a "reverse" control function which is currently lacking.

2 Likes

Also, as a FYI - I plan to submit some of this as feature request to Hubitat, but I'm waiting until after 2.2.4 gets released - I don't think they'll pay attention until after they get control of bugs in the 2.2.3 / C7 rollout.

Dunno if this is the fan controller in question, but I put together a driver for the ZW4SF recently that is working great for me. I specifically wanted to avoid using the dimmer driver and present as a fan control, but under the hood it’s still using levels.

Thanks @erniemiller! Attempted that but still looking for a driver that provides SwitchLevel to MakerAPI, but it doesn’t seem that exists with either Leviton Fan driver.

If you dig through my commits you can see where I pulled out the capability “Switch Level”. Adding that back along with the setLevel method should get that back for you, I believe.

[Edit: here’s the commit]

Great stuff! Why was it removed?

Disregard. I guess checking the commit and link would help :slightly_smiling_face:

I’ll probably fork and use that diff since you’ve since cleaned it up a bit. Although I know if you had separate files I probably wouldn’t be the last one in your debt. I can always submit a PR once done. Too bad we can’t generate groovy using es6 classes so these little variants can share a little.

No promises, but I'll fiddle around with an idea and see if it works.

Hey @drew.covi -- I added the SwitchLevel back. I'd been hoping to potentially give the option to enable/disable the slider based on a preference setting, After that didn't work, I did some digging, and it looks like turning on/off capabilities was specifically ruled out by the Hubitat team.

It's a bit of a good news / bad news situation, though, at least in the case of the ZW4SF controllers. They automatically step to the next-highest speed, and report that back. I'd expected that since this time around I didn't add in any special work to round to the next highest speed, it'd allow precise percentage control of the fan speed, but the switch rounds up and reports back 25, 50, 75, or 100 (99).

Great stuff @erniemiller. In the past (and how I was considering it in the homebridge plug-in) would have split the difference and rounded up or down based on which was nearest. Since iOS surfaces a slider that often makes more sense than having the slider jump all the way up to 50 because someone just happens to set it to 26.

But seriously this is huge for anyone with a Leviton fan speed controller hoping to lean into homebridge.

I'm not a Homekit user, so haven't messed with Homebridge, but I would think that depending on which way the information flows, you'd still be able to do that. If the plugin receives a request for 30, for instance, could opt to send 25 to the driver. If the intent, though, is to have the driver handle it, the changes you'd want to make to do this would be in setLevel, doing the rounding in the parameter to toDisplayLevel there.

That being said, it feels a bit weird to me to change the user input on a setLevel call. Better to send through unmodified to the switch and let the switch report back what it does with that. If and when something changes in switch firmware (or there are other switches released which behave differently) the implementation here right now will "just work".

Oh that makes perfect sense. I didn’t realize the Leviton controller actually accepted a switchlevel (I’ve also heard it called loadlevel). I had assumed we only had a finite number of options so it had to be done in the driver or in the plug-in.

As a FYI (I think this is correct!)
In Z-Wave, there isn't a specific Fan control class (at least not for non-Thermostat devices) - instead, the "general" Switch MutliLevel command class is used (so its controlled like a dimmer). See, e.g., Product Command Classes for the Leviton fan controller.

Internally, these controllers may actually only implement 3 or 4 levels (AC motor fans usually use capacitor banks for control and there are typically only a few settings), so the controller device typically splits up the 1-99 into ranges (1-33 = Low, 34-66 = Medium, 67-99 = High). I think its undefined what happens if you send a "mid-range" value, but I think the switch may simply put the value at the upper end of the range. I suppose if you had a fan with a DC motor, it may use the actual percentage as DC motors have more precise control ability (only newer fans tend to have DC motors).

So in my example for the AC motor conroller, if you send anything from 1-33, the Switch reports back a value of 33 (but I don't think this is a requirement - its conceivable that the switch just reports back what you last sent). As a practical matter, the best way to "know" how the switch behaved is to read back the switch's value after sending it a command (Based on some analysis I did with Zniffer, I think Hubitat always queries for the new value after sending a change value command, so this is pretty much automatic). Thus, a driver should set both the "level" and "FanControl" settings based on the report back from the switch and, if it does that, both should stay properly synchronized. At least the driver for my Inoveli LZW36 controller seems to do it this way.

1 Like

Hey @jvm33!

This is correct.

Yep, this is the behavior I described here.

This isn't quite right, in my experience so far. The driver is responsible for how to send commands to the device, and how to parse responses. In fact, in verifying this just now, I realized that my driver was unnecessarily sending a get to the device after setting a level, because I was getting duplicate SwitchMultilevelReport entries on each command. The ZW4SF reports status by sending a SwitchMultilevelReport back to the hub upon change, whether from a z-wave command or from interaction at the switch.

So, for instance, in my logs after sending a SwitchMultilevelSet to 49:

2020-10-30 10:18:35.904 am debug Parsed SwitchMultilevelReport(value:50) to [[name:speed, value:medium], [name:level, value:50, unit:%], [name:switch, value:on]]
2020-10-30 10:18:35.545 am debug setLevel: 49

Many older z-wave devices worked around a patent that Lutron held on "instant status updates" such as this by instead sending a hail to the hub, at which point the hub (via its driver) would respond with a request for status. This was, essentially, needless indirection and network traffic and proves once again that software patents are evil.

Anyway, hope this helps!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.