SSE Connection established but no messages are fired

  • Platform information:
    • Docker Installation
runtimeInfo:
  version: 3.3.0
  buildString: Release Build
locale: de-DE
systemInfo:
  configFolder: /openhab/conf
  userdataFolder: /openhab/userdata
  logFolder: /openhab/userdata/logs
  javaVersion: 11.0.15
  javaVendor: Eclipse Adoptium
  javaVendorVersion: Temurin-11.0.15+10
  osName: Linux
  osVersion: 4.19.0-18-amd64
  osArchitecture: amd64
  availableProcessors: 4
  freeMemory: 498278032
  totalMemory: 810549248
  startLevel: 70
  • External Server:
    • local nginx (docker)
const eventSource = new EventSource(`http://192.168.178.50:8088/rest/events/states`);
eventSource.addEventListener('ready', (e) => {
    console.log(e.data);
})

TL;DR: No event data in the console.

Long version: Iā€™m trying to respond to item changes via a small local website and was glad openHAB has an excellent REST API. When I learned about the SSE I tried to get this to work, however the browser stubbornly refuses to output anything to me. The EventSource task has a pending in the network log, but no data is received.
The test via CURL delivers the desired result.

curl "http://192.168.178.50:8088/rest/events/states" 
$ curl "http://192.168.178.50:8088/rest/events/states" -v
*   Trying 192.168.178.50:8088...
* Connected to 192.168.178.50 (192.168.178.50) port 8088 (#0)
> GET /rest/events/states HTTP/1.1
> Host: 192.168.178.50:8088
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/event-stream
< X-Accel-Buffering: no
< Content-Encoding: identity
< Transfer-Encoding: chunked
< Server: Jetty(9.4.46.v20220331)
<
event: ready
id: 0
data: 2176313b-40b1-4095-871e-27d73c748520

Does anyone have an idea what this could be?

Here is a link to a very old post I used to get SSE running back in the day, maybe help

Thank you for your hint, but iā€™ve stumbled across this thread before and unfortunately it doesnā€™t help at this problem.

Here is the extract of the header informations:

Request URL: http://192.168.178.50:8088/rest/events/states
Referrer Policy: strict-origin-when-cross-origin
Accept: text/event-stream
Accept-Encoding: gzip, deflate
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Host: 192.168.178.50:8088
Origin: http://localhost:8000
Pragma: no-cache
Referer: http://localhost:8000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36

As you can see I have no authentication or CORS problems at all.

I just debugged a bit deeper and tried to rebuild the implementation from the BasicUI page.
As it turned out, a lib is used there, which provides the polyfill at the same time. Practical, but not what I need since I donā€™t use any unsupported browsers. (Link to the script: GitHub - Yaffle/EventSource: a polyfill for http://www.w3.org/TR/eventsource/)

Then I tried again to see how this looks like in API Explorer. But there I only get a perpetual loading spinner at the events.

Another try was testing different browsers (Google Chrome, Firefox): No luck

I also put the HTML page on the same host as the OpenHAB instance to avoid CORS errors, although I disabled CORS in runtime.cfg: No luck.

Or in short: So far I have found nothing

To listen to all events use http://192.168.178.50:8088/rest/events , this will produce json topics on the default message event type like so:

event: message
data: {"topic":"openhab/items/Item1/statechanged","payload":"{\"type\":\"String\",\"value\":\"1665291370278\",\"oldType\":\"String\",\"oldValue\":\"1665291365278\"}","type":"ItemStateChangedEvent"}

This can also be filtered by topics

This call is used to set up a downstream SSE channel that uses another REST endpoint to request content. The data: 2176313b-40b1-4095-871e-27d73c748520 that it returns is then used by posting an array of item names, like ["Item1", "Item2"] to:

http://192.168.178.50:8088/rest/events/states/2176313b-40b1-4095-871e-27d73c748520

The SSE channel will then start receiving those events, you can continue to post new arrays of items using that id, and the persistant SSE connection will only stream those.

Right now the Main UI uses these endpoints, so you can open your browser dev tools to see it in action,

Thank you for the detailed explanation of the SSE downstream connection. Should consider including this in the documentation.

Unfortunately this knowledge does not help me. Because even if I set up a downstream connection I should at least get the ā€˜connectionIdā€™, right?

Especially I find strange that in the API explorer at the normal ā€˜eventsā€™ as well as at the ā€˜events/statesā€™ a permanent loading spinner appears.
Iā€™ve tried a clean openhab installation on a bare linux PC with the same results. why does it work an the MainUI but not via API-Explorer or external request? The only difference i spottet is the used lib.

The connection id, is returned in the sample curl response that you posted in your original post, thats the example i used. so the data:

event: ready
id: 0
data: 2176313b-40b1-4095-871e-27d73c748520

the data field is the connection id

Do you mean in the browser? Loading a SSE endpoint directly from a browser is not how the SSE standard was designed to work, so the results will probably vary from browser to browser on how it displays a text stream of various formats and not html. Youā€™re better off loading the Main UI or the Classic UI and inspecting the event stream with the browser dev console. This specifically will recognize a SSE event stream and give a nice UI to view messages. Curl is also your friend here for quick prototyping.

Iā€™m not sure what it was originally designed for, but according to the MDN documentation and my experience so far, itā€™s a very convenient way to get updates from the server without having to constantly ask for them from the client side. And another advantage is that it is not bidirectional (ex: WebSockets), so no attack vector on the server.

But Iā€™m not interested in fundamental discussions about which technology was originally developed for what and when :wink:

I donā€™t think that was made entirely clear in the opening post. I made a small web page as a dashboard because I wasnā€™t quite happy with the visualization options.
This can excellently control the items via the REST API, however for completion I need a way to keep the states of the items up to date without periodically checking on all of them.

In the API Explorer you can test the individual REST requests very well with the help of the ā€œTry outā€ button, the following parameter settings and the final click on ā€œExecuteā€.
Only with the two ā€œeventsā€ this does not work. There I get a loading spinner that never ends.
Similarly, when I make the call to the events from the external web server using JavaScriptā€¦ I have an endless ā€œpendingā€ and even if I restrict the topics to e.g. ā€œopenhab/itemsā€, I donā€™t get any messages.

Iā€™m not arguing anything you are mentioning, i understand how sse works. It was not clear to me if you were just pointing a browser to the event URL, but it sounds like you are trying to use the API explorer for this.

I donā€™t think using the API explorer is going to work, the api explorer page is autogenerated from annotations in the core REST code, uses a off the shelf swagger UI, and probably does not have any concept of what an SSE stream is, and is not going to have javascript logic set up to use an EventSource and display the results (thereā€™s no annotations i know of for SSE support).

My advice is to stick with using Javascript or curl to play with SSE.

That is an interesting fact. Thank you.

When I request the /rest/events?topics=openhab/items in the browser the connection is set to pending, so I have an open stream.
However, no matter what action I perform in the openhab app, I do not receive any messages.
This is my main problem.

Try /rest/events?topics=openhab/items/*

1 Like

Unfortunately it does not work even if I specify the item directly.
I do not receive any messages

Can you show a curl output or something?