EventStream / WebSocket closes immediately after connect to Hue bridge

So glad someone is looking at this, and I appreciate your efforts, would love to see this available in HE. I can't offer a great deal of expertise, basic REST APIs are my limits atm, though I can offer another Hue setup to test on. I would need to fire up my bridge again, but that shouldn't be a problem, and I have a couple of lights I could test with, if / when you need someone to do that.

Simon

My hue code doesn’t really have a beta branch so as soon as I can test it, and get feed back from a friend of mine that will force push the update, then I will publish the changes to GitHub and HSM.

So far, their interface looks promising. Contrary to what other online documents state, this appears to support mine mulipart message and event stream messages. I will be going with event stream, as there is less parsing and less data in the payload. I am curious if it supports other formats, I will play with it to see. The event stream is JSON encapsulated in a simple message packet.

1 Like

Anything jumping out yet? is the issue related to support for HTML/2?

So, this is not an http/2 issue, as I forced curl to only use http/1.1 and http/1.0 in separate tests, and the system works fine w/o http/2. Though I do wonder if it has anything to do with the default behavior being to connect http/1.1 then negotiate http/2 which establishes a multi-stream interface.

I tried funneling my Bridge-to-Hubitat traffic through a reverse proxy (NGINX) that I don't think would require HTTP/2 (I have that option disabled), and--the reason I set this up in the first place since I initially suspected something with ignoreSSLIssues--has a valid HTTPS certificate and, in a different configuration, can be used with plain HTTP. I've also had no luck with these options.

So, no good news to share, just basically sharing that you're not alone. :slight_smile: I'm also unable to figure out what's going on, and the lack of helpful error messages from the EventStream interface is...well, not helpful. (I can see what I expect via curl with any of these methods.)

I really don't want to setup a wrapper docker container, just to establish the connection, and feed the data back to HE. The whole point of HE is to manage the integrations and automations, so I try to keep adaptor services as close to none as possible. Such a container would be quite simple though. Just create a persistent connection via curl to the hub, and provide a web socket interface to the output of the curl session, or even a simple telnet connection to the session data. But all this is what I am trying to avoid, since I could just as easily convert to Home Assistant and then use the HA integration to pull the data, since I have HA running for my cameras to integrate with my wall panel. Doing this would be a huge step backwards. So I am just waiting for some follow-up on the issue. My hunch is HE staff will likely fix this so that they can pull this data with their Hue integration, it's just a matter of time.
And in all fairness, I would rather use the official integration, if they simply had scenes support,

I agree; this was just a (failed) experiment, not a suggestion for a long term solution. :slight_smile: I'd probably use the built-in integration too if it weren't for scenes, though last I checked it also lacked startLevelChange() on groups.

same. I use the start stop level change too in code. Was an easy thing to implement using the transition time with a fixed time of 2 seconds and a level of 100 or -100, no matter the current level.. so it always ramps up/down at the same rate, and can be canceled with the level exceeds the limits, or bri_inc of 0.

I worked with @gopher.ny the last couple days, and with any luck the fixes to make this work will be in the next major update. Once I can get access, I will jump on implementing the new code to receive and parse the data for the push service. If you want to start prepping, it will be based on the the Event Stream I believe.

7 Likes

So I have push notifications working in beta code. Something to be aware of is that the push notification will not eliminate the need for periodic refresh. The push notifications are also incomplete. Hue moved away from direct light control, so setting a light will change the group, but hue will not publish that the group changed. Also hue only report color changes in xy format, and I have not been able to find an algorithm for converting xy + brightness to hsv accurately. All the white balance profiles I can find compute the wrong hsv for any given xy+bri and the wrong xy for any given hsv. I will not be able to provide this facility the way I wanted until I can find out how to map Hue's xy to hubitat's hue and saturation.

I may consider using few discreet device refreshes for groups affected by light changes, and for color bulb lights reporting an xy color change. the good news is the push updates are working, and my system will auto-switch between push/poll mode based on web socket state.

4 Likes

Neat! Are you in the 2.2.9 beta? I tried again with one of the first releases but haven't looked at it since, though at the time it wasn't working for me (using the EventSocket interface). Disappointing about the xy format thing, and I've also been unable to find an algorithm that reliably converts between it and HSV. (I once was able to get something that matched what Home Assistant reported, which...it turns out is also not accurate. Hubitat also introduced something around 2.2.6, but I don't know if that conversion, which some "Advanced..." Zigbee bulb drivers use, is part of a public API, and I suspect it suffers from the same issue--it's just better than nothing for devices that only use xy, like some Ikea bulbs.)

1 Like

Well... I ended up here after working on a driver for my Amcrest camera. Same issue outlined above. They publish their updates to an event stream.

Trying on the latest beta build and it still is an issue.

This is the basic event stream template I use. This code must be implemented in a driver, not an app, as documented in the EventStream Documentation

The keys here are:

  1. ignoreSSLIssues: true - This is required for https protocol where server has invalid certs
  2. Accept: text/event-stream - This tells the server the media type you are expecting
  3. rawData: true - This allows the parser to receive each line of data as raw text
//
// Life-cycle methods for eventStream
//

void connect() {

    String apiKey = state.apiKey
    String url = "https://${parent.getBridgeHost()}/eventstream/clip/v2"

    // The 'Accept' header must be set to a supported media type.  For the official event-stream protocol, this is typically "text/event-stream"
    Map headers = ['hue-application-key': apiKey, Accept: 'text/event-stream']

    if (this[SETTING_DBG_ENABLE]) { 
        log.debug "Attempting to establish streaming connection to ${url}"
    }

    interfaces.eventStream.connect(url, [
        ignoreSSLIssues: true,
        rawData: true,
        readTimeout: 3600,
        'headers': headers])
}

void disconnect() {
    interfaces.eventStream.close()
}

void eventStreamStatus(String text) {
    def (String type, String message) = text.split(':', 2)
    switch (type) {    
        case 'STOP':
            sendEvent(name: 'networkStatus', value: 'offline')
            log.info 'Event Stream disconnected'
            break

        case 'START':
            sendEvent(name: 'networkStatus', value: 'online')
            log.info 'Event Stream connected'
            break

        default:
            log.debug "Received unhandled Event Stream status message: ${message}"
    }
}

void parse(String text) {

    // EventStream is documented here
    //  https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format

    // Ignore comment lines from event stream
    if (text.startsWith(':')) { 
        return
    }

    // Parse the lines of data.  Expected types are: event, data, id, retry -- all other fields ignored.
    def (String type, String message) = text.split(':', 2)
    switch (type) {
        case 'id':
            log.debug "Received ID ${message}"
            break

        case 'data':
            log.debug "Received data ${message}"
            break

        case 'event':
            log.debug "Received event ${message}"
            break

        case 'retry':
            log.debug "Received retry ${message}"
            break

        default:
            log.debug "Received unknown data $text"
    }
}
1 Like

Hi @armand and @gopher.ny,

Maybe you could help me out with a problem I have. I am trying to integrate Home Connect appliances using their API. For now if I start the event stream and turn on/off my dishwasher I receive the correct information. But after around one minute the connection is closed with the error below:

2021-11-02 11:10:22.644 pm Received eventstream status message: STOP: EventStream Stopped

2021-11-02 11:10:22.532 pm Received eventstream status message: ERROR: Exception during EventStream Request: java.lang.Exception: Unexpected length of data line.

2021-11-02 11:10:22.502 pm Received eventstream status message: ERROR: Unexpected length of data line.

2021-11-02 11:09:26.846 pm Received eventstream status message: START: EventStream Started

The code I'm using is this:


interfaces.eventStream.connect("${apiUrl}/api/homeappliances/${haId}/events",
            [pingInterval: 5, 
             rawData: true,
             readTimeout: 3600,
             ignoreSSLIssues: true,
             headers: ([ 'Accept': 'text/event-stream' ] << authHeaders())])
    }

I tried every possible combination of the parameters but all of them gave me the same error. Do you have an idea of what could be wrong?

Thanks!

Edit:

I found this while searching around:

Could this be a problem on how hubitat reads the data received?

Could you please PM me your hub's hubUID, I'll take a look at the engineering logs.

According to the apiclient.home-connect.com documentation for the event stream, what you provided seems to be acceptable.

https://apiclient.home-connect.com/#/status_events

I would recommend adding the Accept-Language head too, and assign it one of the values: de-DE, en-GB, or en-US. I am wondering if it is defaulting to a unicode encoding which is resulting in odd behavior. I would also recommend trying with and without the pingInterval.

I see @gopher.ny already is interested in looking at the raw code of the EventStream, so maybe he will find something. I know in my case, with Hue, I get Event Status notifications that the EventStream was closed, but it remains open, and continues to receive updates -- I still have not been able to resolve that issue. The beauty of your solution, is that the API is fully documented, and publicly available.

I tried your suggestion of adding the language and removing the ping and I still got the same error. For me after receiving the STOP event I don't receive any new updates when turning on/off the dishwasher. I sent the information to @gopher.ny. Hopefully he will be able to figure it out.

@armand another question, is the stream supposed to close by itself or do you think that's due to the aforementioned error?

@gopher.ny In my case, the event stream disconnect happens after receiving the first id packet (line of input), followed by the first data packet (line of input).

I doubt it is related, though I still would like to know more about what is causing this.

The "unexpected length of data line" error will need a hub code change to be handled properly with rawData. Right now, it still attempts to handle messages and only resorts to returning raw data if nothing matches expected headers.

@gopher.ny Cool you found the problem! So the interface is closed because of that error? Do you think this change is going to make it for the next update?

Thanks for you help!