Catch UDP Timeout warning?

I'm writing a driver that uses UDP to check a device's status. If the UDP packet doesn't receive a response, the Hubitat log shows the warning "Error occured with UDP message: SocketTimeoutException: Receive timed out" attributed to that device.

Is there a way to catch that warning/timeout somewhere in the driver code? (so that I can set the device as 'off')

My specified callback function on the HubAction isn't called at all, and neither is the default parse() function
I have tried wrapping the sendHubCommand(hubAction) in a try-catch, but the catch doesn't get triggered.
Can't see any relevant options in the HubAction docs either.

As far as I know there's currently no way to catch that warning - I could do with it too for my LIFX drivers.

Any thoughts on this @chuck.schwer? I remember you were considering sending a type of LAN_TYPE_UDPCLIENT_ERROR with the error details to the parse method. Is that still possible?

Ideal is to catch the timeout. This does not currently happen. In my TP-Link drivers, I use:

private sendCmd(command, action) {
	runIn(5, setCommsError)
	def myHubAction = new hubitat.device.HubAction( <deleted for clarity>)
	sendHubCommand(myHubAction)
}
def setCommsError() {
	<Code to handle comms error in driver>
}

I hope this helps.

Dave

Be careful with this... It’s not reliable. If there is any chance that more than one HubAction could be called while another is still executing the next call to runIn overwrites the previous one and the error is never caught.

Correct; with the condition "from the same device" for a device driver. Not necessarily good for a Smart App providing communications services for multiple devices.

It is the only option available to catch UDP error or no response from the device. So I am stuck with it. In one of my multi-plugs, a command to a specific plug is ignored if the system is busy responding to another command. I use 5 seconds, but a shorter time is acceptable.

Yeah I was thinking of doing something similar to that if there's no better option (with a state variable to prevent a second execution if the first is still running).

There's a telnetStatus function that is called when a telnet connection has an error - I was hoping there was something similar for UDP.

How are you defining it because that's exactly the same that I was thinking. So, like this:

try{
     sendHubCommand(myHubAction)
}catch(Exception e){
     log.warn e
}

You could then take actions based on what the contents of "e" are.

Yep exactly like that. It doesn't trigger the catch section at all.

That wouldn't work anyway since sendHubCommand returns once the HubAction has been sent.
The UDP timeout will occur many seconds later; you really wouldn't want sendHubCommand to wait around that long.

It would have to be dealt with in the callback method - parse() probably wouldn't be sufficient for this.

It waits for a response for every other request. I would have assumed it would wait around for this request as well. Otherwise, how would you catch any exceptions?

I don't believe it waits for requests, my use of sendHubCommand is that it's asynchronous. What I think they really need here is the way JavaScript handles things like this, have one callback for success (already exists) and a different callback that gets fired when an exception occurs. At least that'd be one way to design it... @chuck.schwer

1 Like

No, it doesn't wait. That's the whole point of the parse() method or the callback parameter. The only exception would be from a badly formed HubAction.

Yes, that is still the plan.

3 Likes

Hi @chuck.schwer Just checking if there was any update on LAN_TYPE_UDPCLIENT_ERROR I need to be able to capture a UDP SocketTimeoutException as well.

Thanks

1 Like

Yes, it will be available in 2.2.0 as an option to enable it and then we will have to decide if we make it the default in some future version and add an option to disable it.

https://docs.hubitat.com/index.php?title=HubAction_Object

parseWarning - (true/false) Used as part of UDP messages, instructs the system to send any error message back to the parse method of the device. (Since 2.2.0)

5 Likes

Can I like this 20 times!!!!!

1 Like

Is there a way to correlate the warning/error passed back by parseWarning to the original request sent via HubAction? Conceptually would like to use this capability to catch the timeout and retry the same UDP request again.

I don't believe so. Once you get into that, that's really what TCP is all about. UDP is intended to be fire and forget.

1 Like

fair enough - I don't have a choice in the device protocol - what benefit do I gain from using parseWarning=true, then? Simply the ability to hide these "errors" from the logs?

One example would be to keep a counter of consecutive failures. If failureCount > X, send a push notification "the connection to device XYZ appears to be down" Something like that maybe? Perhaps the people on this thread who asked for it will weigh in on what they're using it for! :slight_smile: