Schedule() runs but is not sending commands to device


(codersaur) #1

I wonder if anyone can help me with this problem?

I’m using schedule() within a device handler to run a command once per day. The command updates some device attributes and sends some z-wave commands to the physical device.

If the command is triggered from a tile action, then it executes as expected: I see the log messages in the IDE, the device attributes are updated, the command is sent, and a response from the device is received.

However, if the command is triggered by schedule(), then it executes at the right time, I see the log messages in the IDE, the device attributes are updated, BUT no command appears to be sent!

The following code demonstrates the issue:

def test() {
	log.debug "test(): scheduling schedTest()"
	schedule(now()+15000, schedTest) // Schedule in 15 seconds.
	return  schedTest() // Run immediatly

def schedTest() {
	log.debug "schedTest()"
	def cmds = []
	sendEvent(name: "fault", value: "testFault", isStateChange: true)
	cmds << zwave.versionV1.versionGet()
	return cmds

When test() is triggered from a tile, we see the following in the IDE Log:

14:53:34: debug schedTest()
14:53:25: info Version Report: Application Version: 3.04, Z-Wave Protocol Version: 4.05, Z-Wave Library Type: 03 (Enhanced Slave)
14:53:25: trace zwaveEvent(): Version Report received: VersionReport(applicationSubVersion: 4, applicationVersion: 3, zWaveLibraryType: 3, zWaveProtocolSubVersion: 5, zWaveProtocolVersion: 4)
14:53:25: trace zwaveEvent(): CRC-16 Encapsulation Command received: Crc16Encap(checksum: 28444, command: 18, commandClass: 134, data: [3, 4, 5, 3, 4, 2, 1, 3, 4])
14:53:25: trace parse(): Parsing raw message: zw device: 0C, command: 5601, payload: 86 12 03 04 05 03 04 02 01 03 04 6F 1C
14:53:23: debug schedTest()
14:53:23: debug test(): scheduling schedTest()

Here we can see that when schedTest() is executed directly from test(), we get a VersionReport back from the device after ~2 seconds. Then schedTest() is triggered from schedule(), we get nothing back… (note the attribute is still updated from the sendEvent() call).

Anyone got any ideas?

I have tried wrapping the output from schedTest() in response(), but it makes no difference.
I’ve also tried removing the sendEvent(…) line, but this also makes no difference.

The really annoying thing is that this all seemed to work six months ago, but something seems to have changed…

Thanks, Z

(Eric) #2

A schedule run is logically a void method. so you your returning commands is incorrect as it was not a call back from the device itself.

You need to issue the commands, likely with a hubAction.

(codersaur) #3

Isn’t that what response() does?

I tried this, it still doesn’t work:

def schedTest() {
	log.debug "schedTest()"
	def cmds = []
	sendEvent(name: "fault", value: "testFault", isStateChange: true)
	cmds << response(zwave.versionV1.versionGet())
	return cmds

(Eric) #4

I think that builds a command, but does not execute it. Again I think you want

sendHubCommand(new physicalgraph.device.HubAction(zwave.sensorMultilevelV2.sensorMultilevelGet().format()))

(fill in your appropriate command…)

(codersaur) #5

ah, I think we’ve solved it. Need to use sendHubCommand:

def schedTest() {
	log.debug "schedTest()"
	def cmds = []
	sendEvent(name: "fault", value: "testFault", isStateChange: true)
	cmds << response(zwave.versionV1.versionGet())

This begs the question, why not use sendHubCommand() in all commands?

Also, why has schedule() been changed so that it no longer automatically sends commands? As I’m pretty sure it used to.

(codersaur) #6

Another weird thing, is that if you use schedule() from a SmartApp, which triggers a command, which calls a command in a child device, then sendHubCommand() is not needed.

It would seem logical that schedule() should be able to trigger commands, so I would be very interested to hear from any SmartThings staff why this is no longer the case.

(Kevin) #7

A scheduled method in a SmartApp doesn’t require hubaction to send commands to the device, but it is required for scheduled methods in a device handler. The ability to run schedules from within a device handler is relatively new so I’m pretty sure it’s always been required.

As far as I know, that’s the only place within a device handler that hubaction is needed to send a command to the device.

Response is needed when returning commands from the updated method or the parse method, but it’s not needed from the configure method (the first time it’s called by SmartThings).

The “updated” method is executed twice when tapping done from the device’s settings screen which can cause problems if you’re sending a lot of commands to the device from that method. I’m not sure if this happens with iOS, but it’s been doing this on Android for over a year.

Most of this isn’t documented, but it’s the behavior I’ve observed for all the zwave devices I’ve created handlers for.

Device handler not executing switch.on/off command during runIn scheduler
(codersaur) #8

I wrote a device handler middle of last year that used schedule(), and at the time it worked, without needing to use sendHubCommand(). However, it broke at some point, which is why I’m re-visiting it now.

Yep, got that covered here: Updated() being called twice?

I really wish these kind of things were better-documented! :imp:

(Kevin) #9

That’s odd that they would have changed something like that, especially since earlier in the year before they supported recurring schedules, runin required it. This is SmartThings so I guess I should be that surprised.

I noticed that the “Latest Updates” section of the documentation had an entry from 10/5/2016 which said “Added scheduling APIs to the Device Handler reference documentation (including all runEvery* APIs, which are now supported in Device Handlers).” so I assumed it was something they just added.