Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[openhabcloud] Handle WebSocket connections to server. #16403

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

GiviMAD
Copy link
Member

@GiviMAD GiviMAD commented Feb 13, 2024

These changes are related to PR at openhab-cloud openhab/openhab-cloud#447.

The PR implements and registers a custom ProtocolHandler in the Jelly Http client to catch upgraded websocket responses, access its underling EndPoint and upgrade its Connection to a custom implementation that will proxy the plain socket data between the connector and the OpenHAB server allowing the websocket protocol to work.

These PR needs from the core PR openhab/openhab-core#4092 which allows to access the Jetty EndPoint used to read/write from the request socket.

@GiviMAD GiviMAD added awaiting other PR Depends on another PR enhancement An enhancement or new feature for an existing add-on labels Feb 18, 2024
@wborn wborn removed the awaiting other PR Depends on another PR label Mar 2, 2024
@lolodomo
Copy link
Contributor

Dores it depend on openhab-cloud openhab/openhab-cloud#447 ?

@lolodomo
Copy link
Contributor

@digitaldan or @kaikreuzer : as openHAB cloud maintainer or binding maintainer, you would like to review this PR?

@digitaldan
Copy link
Contributor

Yes, i will review. I have been procrastinating getting the cloud side of a related PR merged in and deployed to a dev instance so i can test these changes end to end. I'm out of town until the end of next week, so it may be a bit longer for me to review.

@digitaldan digitaldan self-requested a review March 27, 2024 14:18
@digitaldan digitaldan self-assigned this Mar 27, 2024
@digitaldan
Copy link
Contributor

digitaldan commented Apr 14, 2024

Hi @GiviMAD I finally found some time to review this as well as the cloud PR . Took me a bit to get everything up for testing. Just FYI after my first test i'm running into an issue where a simple web socket connection seems to be failing in the binding. I'm sure it's something small and easily fixable, but it does make me curious how you are testing this? I don't really use the websocket API in OH, which is a shame, as it would be nice to get our Main UI on it. Right now i have postman creating a websocket connection and sending heartbeat messages. This works against the local OH instance, but when i do it through OH cloud, the cloud binding does receive the request, but with this error:

09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - on(): request
09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - Got request 669
09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - Path /ws/
09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - Method GET
09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - Headers: {"upgrade":"websocket","sec-websocket-extensions":"permessage-deflate; client_max_window_bits","host":"*******","connection":"upgrade","sec-websocket-key":"d3tiKK5c3jE8stTc2bWaaQ==","sec-websocket-version":"13","user-agent":"openhab-cloud/0.0.1"}
09:29:26.791 [DEBUG] [.io.openhabcloud.internal.CloudClient] - JSONObject["body"] not found.

I'll keep looking at it, but curious what your setup is and how you are testing. Thanks!!!

@GiviMAD
Copy link
Member Author

GiviMAD commented Apr 27, 2024

Hello @digitaldan, thank you for looking at it.

For my initial testing I just created a websocket connection to the server using the browser console

let exampleSocket = new WebSocket("ws://localhost:8080/ws/logs");
function startPing() {
    setInterval(()=>{
        console.log('send noop')
        exampleSocket.send('{}');
    }, 5000)
}
exampleSocket.onopen = function() {console.log("ws OPEN");startPing();};
exampleSocket.onclose = function() {console.log("ws CLOSE")};
exampleSocket.onmessage = function (event) { console.log(event.data)};

I send an empty json each 5 seconds to about connection to be closed in case of no logs, because the browser websocket client doesn't allow to send a ping to the server.

I also tested it with the audio websocket I have WIP in different PRs.

I just tested it on my laptop but it worked fine for me.

I'm going to setup a custom cloud instance for my normal oh installation and see if it works fine and share here the steps I have followed.

Best regards.

@lsiepel
Copy link
Contributor

lsiepel commented Jun 14, 2024

@GiviMAD did you have any success with the custom cloud instance? Only a few weeks left for next stable.

@digitaldan
Copy link
Contributor

@GiviMAD let me know when you are ready for testing and i will help out.

@GiviMAD
Copy link
Member Author

GiviMAD commented Jun 24, 2024

Hey @digitaldan , @lsiepel.

I've been looking at this today and I was able to make it work with the included docker-compose setup, and for me it seems to be working correctly.

I followed these steps:

  • After setting up my domain and the port forward in the router, I setup the cloud connector from PR Proxy WebSocket connections openhab-cloud#447 following the docker-compose deployment instructions, and create my user with the openHAB UUID and secret.
  • I updated my docker container for openHAB to the snapshot tag.
  • I built this PR as a kar mvn clean install karaf:kar -pl :org.openhab.io.openhabcloud
  • I uninstall the official version and installed the add-on moving the kar file to the addons folder, after installed, I edited the cloud connector config "Base URL" with the url of my personal domain.
  • At this point I can connect to my openHAB instance through my cloud instance.

To verify the websocket, after loading my openHAB dashboard through the cloud, I pasted these javascript code in the console, it connects to the event websocket and ping it each 6 seconds to keep the connection open.

let exampleSocket = new WebSocket("wss://home.mydomain.com/ws/event-subscriber");
let intervalRef = null;
function startPing() {
    intervalRef = setInterval(() => {
        exampleSocket.send(JSON.stringify({ type: 'WebSocketEvent', topic: 'openhab/websocket/heartbeat', payload: 'PING' }));
    }, 6000)
}
function stopPing() {
    if (intervalRef !== null) {
        clearInterval(intervalRef);
        intervalRef = null;
    }
}
exampleSocket.onopen = function () {
    console.log("ws OPEN");
    startPing();
};
exampleSocket.onerror = function (err) {
    console.log("WebSocket error: ", err)
    stopPing()
};
exampleSocket.onclose = function () {
    console.log("ws CLOSE")
    stopPing();
};
exampleSocket.onmessage = function (event) { console.log(event.data) };

I can see the openHAB events and the responses to the PING messages in the log.

Screenshot 2024-06-24 at 18 26 55

Copy link
Contributor

@lsiepel lsiepel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM. @GiviMAD had a positive test result, after @digitaldan is also fine with this I’ll merge this.

@lsiepel
Copy link
Contributor

lsiepel commented Aug 1, 2024

@GiviMAD can you solve the conflicts? Hopefully @digitaldan can approve this pr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting feedback enhancement An enhancement or new feature for an existing add-on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants