Websocket Client

Is there a websocket client implementation available from Hubitat for use in apps?

Yes. Take a look at @ogiewon's code as a reference. His code uses websockets to communicate with Harmony hubs.

[Release] Logitech Harmony Hub Driver v0.1.20190220

1 Like

Great. I'll look through it.

Using @ogiewon's Logitech hub code I've succesfully connected as a client to my server based PHP websocket, and can send messages from the the client to the server websocket.

However, I am unable to receive messages sent to the client, although no errors are generated, nothing occurs. Hope someone has the code for receiving client side messages, similar to Javascript's client side onmessage or addEventListener, and is willing to share it.

You should look at @kewashi housepanel. He has a websocket setup in there.

Here is a very simple JS implementation of connecting to the websocket and receiving data

    const WebSocket = require('ws');
    var that = this;
    function connect() {
        var url = 'ws://192.168.1.10/eventsocket';
        var ws = new WebSocket(url);
        console.log('attempt connection to ' + url);
        ws.onopen = function() {
            console.log('connection to ' + url + ' established');
        };

        ws.onmessage = function(e) {
            try {
                var jsonData = JSON.parse(e.data);
            } catch (e) {
                console.log('Invalid JSON data received from websocket', e.data);
                return;
            }
        };

        ws.onclose = function(e) {
          console.log('HE Eventsocket is closed. Reconnect will be attempted in 1 second. ', e.reason);
          setTimeout(function() {
            connect();
          }, 1000);
        };

        ws.onerror = function(err) {
          console.log('HE Eventsocket encountered error: ', err.message, 'Closing socket');
          ws.close();
        };

    }
    connect();
1 Like

Thank you for the JS Code. I already have a fully functioning JS client.

What I need is how to receive a socket message in a Hubitat groovy client module (driver) using "import hubitat.helper.InterfaceUtils", connection and sending are working.

You should be able to see any data coming back I the parse method?

Edit. Nm. I see that's not what you need.

Prior to posting I looked at the groovy code from both SmartThings and Hubitat. The Hubitat side does not appear to use "import hubitat.helper.InterfaceUtils", and I'm uncertain on how to use the code I did find for receiving messages.

Ok, I misunderstood.

So, you are looking to have a socket open on your Hubitat where you can connect to from an external application and send commands to your hubitat?

I don't think that is supported. Hubitat only supports connecting to a websocket application. Not being a server.

EDIT: However, a websocket is usually two way. So you should be able to post something to your websocket connection on the PHP end

I have some debugging logic in the parse method, but get nothing in the logs. What I want is to receive random unsolicited messages.

I also contacted support for "hubitat.helper.InterfaceUtils" documentation, I was advised to post questions on the forum.

Using Hubitat’s webSockets implementation, all replies are simply handled in the parse() routine. At least that’s how my Logitech Harmony Hub Driver works. It handles unsolicited messages.

Correct. I'm able to use the Maker API app, but was hoping to bypass it once the socket was connected.

WebSockets by definition are bi-directional. My Javascript client can receive and send messages. I want the Groovy client device to do the same. The websocket server runs on my local WAMP server.

That is how Hubitat’s webSocket implementation is designed. Works for my driver.

You are absolutely correct, had a brain lock here. Something like this here should work:

import hubitat.helper.InterfaceUtils

def connect()
{
	InterfaceUtils.webSocketConnect(device, "ws://192.168.10.207/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}"
}

The parse method gets called as long as the server posts on the channel. I am not sure if that has to be done in a driver though. Not sure that the parse message would get called in an app. Never tried it.....

1 Like

I believe it only works in a driver, but I’m not 100% sure about that.

It is a driver.

I followed @ogiewon's example, but nothing seems to happen in the parse method when a message is sent by my websocket server, although the Javasript client sees the general broadcast message, and the Hubitat groovy webSocketStatus open triggers

//Connect the webSocket
try {
    InterfaceUtils.webSocketConnect(device, "ws://192.168.0.101:9000/cz/shmdelay/Socket.php")
	} 
catch(e) 
	{
    log.error "WebSocket connect failed initialize error: ${e.message}"
	}
}

// parse 
def parse(String description) {
log.debug "Parsing ${description}"

I know @chuck.schwer also implemented the webSocket ping/pong keep alive functionality... Does your webSocket server implement this as well?

Maybe load up @ogiewon code and see if it connects to the ws at works? Likely to produce some errors but might help to see what is going awry.

I'm not sure what happened, but it now seems to be working. Thank you to everyone for the suggestions.

[dev:123]2019-06-17 12:47:50.907 [debug]Parsing {"type":"system","message":"192.168.0.nnn connected"}

[dev:123]2019-06-17 12:47:49.866 [info]websocket is open

1 Like