I discovered the ZCL (Zigbee Control Library) this weekend and have been reading through it. And at the same time, using what I’m learning to write my own device type for my Osram Lightify Tunable bulbs (just for learning purposes, I know there are device types already written for them).
One thing I’m having trouble understanding in the ZCL documentation is under the Level Control cluster (0x0008), the “onLevel” attribute (0x0011)? What is that attribute exactly? I’ve read through the whole section in the ZCL on that cluster, but I don’t really understand what it’s for. I know it’s optional, and I haven’t tested to see if those bulbs support it yet.
I’ve also played around with some of the different commands for level control…move to level and step (and their with on/off variants). I’m still trying to understand the point of the move command as well. I’m guessing that would be coupled with the stop command? For example, if you had a device that supported something like “hold button to dim up”, and then when the button is released, you would issue the stop command? Is that correct?
You’re pretty much spot on with the level control methods. The Hue Dimmer Switch uses the move level and stop commands for its “Dim Up”/“Dim Down” buttons. Pressing once moves by like 18. If you hold, it sends a move by 30 or so once a second and when you release, it sends a stop command. If you check out the devicetype for it on Github linked below, you can see some of this in the parse code.
As for onLevel attribute. It simply provides a default level for the bulb to turn on to when sent a zigbee “on” command (not when physically powered off). Typically the device will retain its currentLevel when turned off and return to that value when turned on. OnLevel provides a way to make sure the light comes on to a specific level.
You might say, why not just send the level you want directly? The light will turn on if the level with on/off is used, right? The big difference is that a level command moves immediately to the currentLevel then transitions to the new level, but an on command starts from 0 and moves to the onLevel (or currentLevel if onLevel isn’t set). Imagine a light is off, but was last on at full brightness and now you want 10%. If you use level with on/off the bulb will pop on to full bright then dim down to 10%. If you set the onLevel and send “on” it will simply dim up from nothing to 10%.
Okay, then that sounds like what I want to do then.
I set the OnOffTransitionTime to 1 second and I also have the move to level transition time set to 1 second. Most of the time it does what I want. But you’re right, if set the level to 100, then turn it off, then set it to 50, it’ll jump to 100 then fade to 50.
So I’m guessing if I want to take advantage of this onLevel attribute, I would need to change my setLevel function to say, IF it’s current switch state is off, THEN it should set the onLevel to X and THEN turn the bulb on, rather than just telling it to move to level X?
So something like this (pseudo code):
setLevel(X)
{
if current switch state == off {
switch.onLevel = X
switch.on()
}
if current switch state == on && X == 0 { //is this really necessary since it will turn off anyways?
switch.off()
}
switch.setLevel = X
}
aka: if it’s already off, then use onLevel and turn it on. If it’s already on and X is 0, then turn it off. If it’s on and X is not 0, then dim to that level.
The only problem so far is I have yet to learn how to retrieve information like switch states and currentLevel to use it in functions for logic decisions. But I think I recall seeing it in another device type so I can probably just hijack that code. I think I recall seeing something like last state or something.
The only issue is that onLevel is a persistent attribute, not a single command parameter, so the next on() command will set the light to the onLevel too.
Instead of using onLevel to solve it because of the need to manage that attribute constantly, I use a level 0 command with 0000 for the transitionTime (aka instant), then send the normal level command.
No need to turn the switch off via zigbee when level is 0. If you use the commands with on/off, the light will set its internal on/off status on its own. But I should clarify a distinction here between the device state vs the state in SmartThings. You won’t need to update the device state by sending the off() command, but you may want to update the ST state with a sendEvent() statement. Ideally, you can use zigbee binding and attribute reporting to have the device notify the hub when it updates its internal state and use those messages to update SmartThings. This is the current recommended practice. Check out the configure() method of some zigbee devices for binding and reporting code. Then in parse to break down the incoming device messages.
(PS: device.currentValue(“switch”) will give you the device’s current ST state. Replace “switch” with any ST attribute like “level” to get other states.)
Awesome, thanks for the help. I’m still learning, so I will probably stick with the sendEvents for now, the binding stuff sounds a little advanced for me at the moment.
I think I tried using that method before (set to zero first), but I think I was using the move to level with on/off and I was having problems. I’ll try using the move to level command, and then maybe throw in a delay of 100 ms or something.