Hubaction() not executed when scheduled via runIn() from device handler?

I am trying to write a device handler that connects to a local IP device on automatically pulls new data every 5 minutes (which is the update frequency of the device).

An abbreviated version looks like this:

[…]

def poll() {
  pullData()
}

def refresh() {
  pullData()
}

def pullData() {
  log.debug "Requesting latest data…"
  runIn(300, pullData)
  new physicalgraph.device.HubAction([
    method: "GET",
    path: uri,
    headers: [HOST:getHostAddress()]
  ])
}

def parse(String message) {
  log.debug "Response received…"
  […]
}

From the logs I can clearly see that the pullData() method is called every 5 minutes. However, unless I manually refresh the device in the app (or use Pollster to refresh it), the parse() method is not called.

Is the hubaction not executed from called this way from within the device handler? Anything I can do to make this work without having to resort to Pollster?

Just to confirm, are you setting your DIN to be the IP:PORT in Hex? If you don’t do this then you will not get a response. Also, if you are nesting the function that calls hubAction you need to return your hubAction in order to get it to parse. See one of my devicetypes for an example:

Yes - I am. As I said, the parse() function get called correctly when using the refresh tile in the device or using Pollster to call refresh() - it just doesn’t work when pullData() is called via runIn() from within pullData() itself.

I added a return and it doesn’t make a difference…

Could you move the runIn() command into the parse() command, so that it avoids calling the function within itself?

Tried that and it didn’t make a difference. The reason I had it in pullData() was that parse() didn’t seem to be called in the first place when pullData() was triggered by a runIn(). It seems to me as if there is something in the hub that causes this to fail…

Agreed, it’s probably something that’s turned off on purpose. Makes no sense for me not to be able to have a simple sleep/pause/runIn that works on the DEVICE HANDLER level not SmartApps where it does seem to work.

ST Devs hopefully watching. Here’s a simple call in a Device handler that fails:
runIn(5,sendEvent(name: “rebootnow”, value: “default”))

Fails with this error:
groovy.lang.MissingMethodException: No signature of
method: script14595755330201108996166.null() is applicable for argument
types: () values: [] Possible solutions: now(), run(), dump(), html(java.lang.String), tile(java.util.Map), use([Ljava.lang.Object;)

Hoping to see it fixed/enhanced one day.

@slagle Any official statement on this? The ticket I created about this issue (185862) has been closed as “solved” without ever getting any resolution. Creating a follow-up ticket using the links provided doesn’t work either.

It seems as if there is no working way to get any developer help these days :cry:

did this get addressed? @ahndee how did you get around this?

I don’t think so.

I use the following function to schedule the hubaction (which is in the pullData function):

def startPoll() {
	unschedule()
	// Schedule polling based on preference setting
	def sec = Math.round(Math.floor(Math.random() * 60))
	def min = Math.round(Math.floor(Math.random() * settings.pollingInterval.toInteger()))
	def cron = "${sec} ${min}/${settings.pollingInterval.toInteger()} * * * ?" // every N min
	log.trace("$device.displayName - startPoll: schedule('$cron', pullData)")
	schedule(cron, pullData)
}

The startPoll function is called in the updated() function for my DTH.

thanks - not pretty but as long as I dont have to write a smartapp and have to deal with this

Are you both saying that schedule and unschedule works properly inside of a DTH?

If possible, would love to see the entire DTH code as reference. Thanks for sharing the above as it closes an interesting gap.

Here is my DTH:

Please note that the issues SmartThings introduced in the mobile app last Friday currently cause an error (though things work just fine in the simulator).

1 Like

Damn that’s pretty looking, nice work! Thanks again for sharing!!!

1 Like

Your DH looks very nice will take a look at your code. It could be quite useful for a gas/water meter app that I have been semi working on.

The polling loop didn’t work from within the DH - what worked however was a very whacky thing. I had given up on this and started writing a service manager app, as I was in the beginning of the the app, I saw messages being handled by the DH.

So the trick that worked for me was this - leave the server and port in hex in the NID field, put the scheduler, request and, subscribe to location events from the app, and have a stub handler, now every time the response comes backs it is routed to the DH and the app doesn’t get it. This is probably a walk in the side-effect land, and can break with any release, but it works as of now

Writing this out because it can be used for other interesting models - especially for sensor polling and management

I am curious if anyone has any updates on the original issue? I found this searching for answers because I am having the same issue, hubAction from runIn() states that it sent the message but in actuality, it was never received by the device on the network and so no response and parse() was not called. Doing a refresh will send the hubaction, same code, and it works every time. Basically trying to execute runIn(5,refresh) only once, not recurring from the device handler after an event.

Answering my own question. Finally found the answer in another post after searching. Turns out in my case it was not RunIn versus Schedule or calling from another function, it was this from CopyCat73:

So I was wondering why my hubaction that I scheduled to run every minute was not returning anything to the parse() method. Turns out that in this case returning hubAction from the scheduled method does not work, it has to be sendHubCommand(hubAction).

Hope this can help others in the future.

1 Like