Hey Folks,
Firstly, thank you for your responses, the help is much appreciated. The tech in me couldn’t let this go as a simple bug or with a hacky workaround, I really needed to get to the bottom of it, and I believe I have. I don’t actually think this is a bug but in fact the way it works. I am putting the detail here in case anyone else comes across this issue, sorry if you already know this.
So firstly, the on() and off() methods within a device handler don’t seem to be treated strictly as methods in the true sense that they are called and expected to do something and then return. In fact, the purpose of these methods is simply to return either a single, or collection of commands in an array.
In the code example given here, the on() method is simply returning an array of zwave commands. Note the lack of a return() method which is not needed providing there is nothing after what is the desired return.
def on() {
delayBetween([
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.basicV1.basicGet().format()
], 5000) // 5 second delay for dimmers that change gradually, can be left out for immediate switches
}
If I modify that code slightly to print some debug messages, we can see what the output of the delayBetween() method is actually doing:
def on() {
def cmds = delayBetween([
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.basicV1.basicGet().format()
], 5000) // 5 second delay for dimmers that change gradually, can be left out for immediate switches
log.debug(cmds)
}
This gives me the following debug output:
8:05:36 PM: debug [2001FF, delay 5000, 2002]
So basically, what the delayBetween() method is doing, it pretty much the same thing as the physicalgraph.device.HubAction() class constructor does, expect it adds a delay in-between the commands. See the following code for an example:
def on() {
def cmds = [
new physicalgraph.device.HubAction(zwave.basicV1.basicSet(value: 0xFF).format()),
new physicalgraph.device.HubAction(zwave.basicV1.basicGet().format())
]
log.debug(cmds)
}
This gives me the following debug output:
8:09:25 PM: debug [2001FF, 2002]
As you can see, its the same commands except that the delayBetween() method simply adds the delay in the middle. In fact, this is noted in the developer documentation here.
There is a shorthand provided to create command objects: zwave.basicV1.basicSet(value: 0xFF) is the same as new physicalgraph.zwave.commands.basicv1.BasicSet(value: 0xFF). Note the different capitalization of the command name and the ‘V’ in the command class name.
So I now understand a couple of things. First, the reason that the default on() and off() methods work when called from the UI is because whatever code is calling the on() or off() method is simply using these methods to create an array of commands which I assume it is then processing using something like the sendHubCommand() method.
This also explains why calling the on() or off() method directly, from another method or something like the runIn() method doesn’t actually do anything, its because the function is doing nothing but returning an array; its not actually sending any commands to the switch.
This makes sense because the various zwave message formatting methods do the same exact thing.
With all of this in mind, I now understand why my solution worked, but also why it wasn’t desirable. If the on() method is supposed to just return an array, then its best to let it return that array as under the hood, whatever is calling it may now or at some point in the future do something more with the data.
As was suggested by the fine gentlemen @tgauchat and @krlaframboise in this post, its best to create a new method to turn on the switch programmatically, and another one that handles the sending the commands to the hub itself.
The way in which the device handlers are architected, in that they are an instance of a class which is then created by some other code, makes a lot of sense and is very similar to how iOS applications are architected with methods for example drawing tables.
Again, thanks for you help, and hopefully this long text helps someone else.
Cheers,
Jon