How to receive device state updates in driver? (websocket / eventsocket)

I tried searching but couldn't find anything so I'm hoping someone could point me in the right direction. I was just trying to write a test device driver which would get notified anytime a device state is updated (door open/closed, etc)

Maybe there's a better way but one I'm somewhat familiar with is the eventsocket websocket. I'm connecting to it from a phone app and it works great. Now I just want to test this in a Hubitat device driver.

I've tried connecting using several variations like this but all result in the same error. Does anyone know what I'm missing or if there's a better way to get updates to any device?

   interfaces.webSocket.connect("https://localhost:443/eventsocket")
   //interfaces.webSocket.connect("https://192.168.0.201/eventsocket")
   //interfaces.webSocket.connect("ws://localhost/eventsocket")

The error I get is:

Connection has failed with error [failure: Failed to connect to localhost/127.0.0.1:443].

The important parts of the driver are here:

void connectEventStream() {
   log.debug "connectEventStream()"

   interfaces.webSocket.connect("https://localhost:443/eventsocket")
   //interfaces.webSocket.connect("https://192.168.0.201/eventsocket")
   //interfaces.webSocket.connect("ws://localhost/eventsocket")
}

def webSocketStatus(String socketStatus)
{
   if (socketStatus.startsWith("status: open"))
   {
      log.info "Connected"
      return
   } 
   else if (socketStatus.startsWith("status: closing"))
   {
      log.info "Closing connection"
      return
   } 
   else if (socketStatus.startsWith("failure:"))
   {
      log.warn "Connection has failed with error [${socketStatus}]."
   } 
   else
   {
      log.warn "Connection to has been lost due to an unknown error"   
   }
}

def parse(String description)
{
   log.debug "Got Data ${description}"
}

If you are talking about detecting a state change on device A that is configured in the HE hub, then updating the status on Device B, also on the HE hub, then I would expect the more common way would be to write an App that subscribes to the appropriate events on device A and then updates the status of device B. I can't claim to have done this myself, but would imagine there would be an example in the HE repository somewhere or in the documentation.

Re-reading your OP, though, if you are wanting something more generic, then that could be a little more interesting... i.e. if you don't know the types of events the device may produce.

I actually want to listen to updates to any device state change. I'm open to writing an app instead of a driver -- the kind that lets you select all devices you want to monitor. I'm not sure how to do that either but I can look at some examples to see how they work.


It would be nice to understand why I can't connect to the /eventsocket from a device driver though

The apps and drivers on the hub cannot talk to the same hub using the default port 80. You’ll need to specify port 8080, IIRC.

2 Likes

If you are wanting a broader detection method where you don't want to have to define all the possible event types, then perhaps what I was suggesting with an App may not be as useful as I first thought, though others may be able to offer alternatives within the App space.

Though not as relevant to your situation, there is a good simple run through of subscribing to a defined event in the App developer documentation:

If you are wanting to connect, @ogiewon can hopefully help out, otherwise there is also a rpi events and logs script that I have used from here on the Community, which I can find if you are still having issues.

That worked! Never thought to try that..

   interfaces.webSocket.connect("ws://localhost:8080/eventsocket")
1 Like

Feels like some more detail like what you described would be useful on the EventStream documentation page, unless it is a different thing....:

https://docs2.hubitat.com/developer/interfaces/eventstream-interface

Well, it is pretty odd that anyone would connect a driver to the eventsocket on the same hub. One should just create an app, and select the devices that one wants to subscribe to. Yes, it is a little tedious, but that is actually the intended design. Hubitat has decided to not let end users create apps that subscribe to ALL devices.

Thus, I don’t believe the documentation should be changed.

2 Likes

That's a fair point.

Perhaps a more appropriate response would be to request an easier way to detect / subscribe to any state change in a device, regardless of the types of events. Though I expect even that could have unintended consequences I have not thought of...

On the documentation, while I agree that it is not worth documenting an undesirable setup, i.e. connecting from a driver to the eventstream, the other reason I made that comment was I would like to have seen a similar worked example to the App documentation I linked earlier, showing how you might connect from, say a shell script on Linux, for example. Not to say it has to be included, but it does help give people a head start to have some sample code.

You can. This is one of the documented signatures for the subscribe() method (ones without an attribute name). But it's also a little unusual and not something I would do without a specific reason.

1 Like

@jpage4500 not sure what you are targeting, but your questions made me think of this

Do you happen to know of any examples doing this?

void subscribe(InstalledAppWrapper app, handlerMethod)
void subscribe(Location location, handlerMethod)
void subscribe(DeviceWrapper device, String handlerMethod, Map options = null) (Since 2.2.1)
void subscribe(DeviceWrapperList devices, String handlerMethod, Map options = null) (Since 2.2.1)
void subscribe(DeviceWrapper device, String attributeName, handlerMethod, Map options = null)
void subscribe(DeviceWrapperList devices, String attributeName, handlerMethod, Map options = null)
void subscribe(Location location, String attributeName, handlerMethod, Map options = null)

But it's also a little unusual and not something I would do without a specific reason.

I do have a long-term goal of what I want to do with all of this but haven't exactly decided how far I want to take it. For now though I just want to play around with what can be done.

More specifically, I've got an Android dashboard app, HD+, which receives 'push' updates using the websocket ('eventsocket') locally. But, when away from home I have to poll the MakerAPI every few seconds and for years I've wanted to find a better / more efficient way to push updates to devices. I've opened a few threads about it: Access /eventstream from cloud? Or, alternative ways for hub to 'push' updates to a mobile device

I've finally got around to adding support for FCM (google push messages) to the app - so now I have a way to notify devices (removing the need to poll MakerAPI). The next step is detecting changes in devices and sending out updates via FCM. There's a lot more to it than that.. I don't actually want to send out updates for every device or attribute change -- just the important ones. But, I can have the app tell the driver to look for a list of device ID's so the user doesn't have to worry about any of it.

Certainly the subscribe() method looks promising but I would love to see an example of how to do this for multiple devices. And/or how to do this for 'all' devices and I can do the filtering myself in the driver

That is the difference between a DeviceWrapper (single device) and DeviceWrapperList (possibly multiple devices) in the method sigantures above. From a practical prespective, this is multiple: false (or the default, not specified) versus multiple: true on your input.

In your unusual case, it might actually be not odd to just listen for the eventstream if that's basically what your app is doing, but traditional subscriptions certainly should work too.