Testing socket, telnet and websocket interfaces

Hello all,

I'm in the process of reviewing socket, telnet and websocket implementations used by drivers and apps. Before someone asks, there are/will be no changes to the APIs interfaces.

We need some pointers to apps or drivers that use these interfaces and do not require a physical device. We got JUnit tests (of course!), but I'd also like to see real world usage patterns and incorporate it into automated testing as much as possible. I've been looking through GitHub for usages, but likely have missed a bunch.

Please let me know, and thank you in advance!

2 Likes

telnet

  • intesis driver (needs login)

web socket

  • echo speaks (needs login)
  • older nest manager (needs old style working google login)
  • weather flow light (needs login)

Also an option, deprecated by some, in Node-RED nodes for hubitat

Here's my app/driver that uses Telnet...

HubConnect, of course. :smiley:

Any of my MagicHome/EcoPlugs/Lightify drivers use Telnet/Socket. NetCat has been my go-to for virtually testing these, but a simple response server could also do the trick. As long as there is a response, the drivers stay alive.

Let me know if I can do anything to help. I’d love to see these interfaces smoothed out.

Don't forget Envisalink

I use Raw Socket (in beta) in the Kasa Plug, Bulb, and Switch drivers (as well as UDP). Some of the interesting items I have included is:
Concatenation of multi-message replies,
Working without socket status messages from client (it does not generate these),
Error handling (to assure delivery of commands to client).

Link: [DEPRECATED] Kasa Plug, Switch, and Bulb integration

PS: One thing I am interested in is the Hubitat resource utilization of UDP vs Raw Socket for my system. I can do both; however, Chose raw socket because of user desire for quick polling. But I can create a hybrid with minimal code impact.

Update: I no longer user raw sockets.

I know this is an old thread. Is there a way of opening an encrypted socket using rawSocket? The endpoint I'm connecting to (currently using openssl in node-red) is not an http, mqtt or websocket endpoint, all of which support ssl/tls connections.

Seems odd that rawSocket doesn't support that. Am I missing something or perhaps it's not documented?

would be nice but dont think it is implemented.

It's not implemented at the moment. Which device/functionality do you have in mind?

There is an undocumented interface into my alarm panel, a QolSys IQ2+. I can access it by running

openssl s_client -host 10.0.0.199 -port 12345

It is a bi-directional interface that periodically reports the state of all alarm sensors and allows the alarm to be armed and disarmed. At the moment, I have to have a node-red flow connect to the alarm panel using a daemon node that runs openssl, then massage and push the data to a mqtt broker (an Aedes node in Node-Red). then have a HE device connect to the broker.

It works but it's really cumbersome and adds several failure points to the whole thing. Would be so much simpler and self-contained if I could just open the connection to the alarm panel directly in HE,

Seems to me that you already have the whole ssl/tls thing implemented as we can open https and wss connections in HE. Wouldn't an encrypted raw socket mostly be a subset of already existing functionality? In my case, the ability to ignore cert errors is a must, as the cert in the alarm panel is self-signed. But you already have that option in https and wss as well.

I intend to publish my driver sooner or later, but the whole openssl/node-red thing complicates it.

Thanks.

I need SSL or tls to be able to allow my sendmail to basically work with any server.

Feature request noted. The usual "no promises" policy applies.

2 Likes

Reviving old thread @gopher.ny, but I wanted to give some feedback from my first foray into rawSocket after being successful with webSocket in multiple integrations in the past.

The error and status reporting to socketStatus for rawSocket is really scant. With webSocket, you get connect and disconnect statuses as well as useful errors along the way about connection health.

With rawSocket, I don't get anything on connect or disconnect, so I can only sort of sense connection status by trying to sendMessage and getting a broken pipe error. And that only works if I had a connection previously opened. If it wasn't opened, sendMessage just fails silently.

Would it be possible to at least report when the pipe is closed by the server? This would allow for much more resilient communication for streams.

1 Like

You're not getting anything in void socketStatus(String message) callback when an error occurs?
Also, I don't think there's no reliable way to see if socket is still connected without some sort of a ping/pong protocol...
What's the use case? GitHub link works.

1 Like

I get this when writing to a socket connection that was previously working but was dropped by the remote server. Otherwise, I haven't seen anything else handled by socketStatus for rawSocket.

def socketStatus(String message)
{
    log.debug "socketStatus: ${message}"
}

dev:2612021-09-13 19:32:06.298 debug socketStatus: send error: Broken pipe (Write failed)

By comparison, I get this sort of feedback on the webSocket interface:

[dev:4281](http://10.0.0.4/logs#pastdev4281)2021-09-14 11:56:50.901 am [debug](http://10.0.0.4/device/edit/4281)webSocketStatus: status: open
[dev:4281](http://10.0.0.4/logs#pastdev4281)2021-09-14 11:56:40.020 am [debug](http://10.0.0.4/device/edit/4281)webSocketStatus: status: closing

...plus errors (don't have a print handy) that I handle like this:

def webSocketStatus(String message)
{
    log.debug "webSocketStatus: ${message}"
    
    if(message.startsWith("failure:"))
    {
        ...
    }
}

Yeah, I'm not surprised that it would necessarily be less responsive than a ping/pong ws thing, but I guess I figured if the remote server quits the connection that it would be possible to observe that and report an error or closed status on the client side.

My use-case is kind of complicated. I'll share more details over PM to avoid polluting this thread further. Just let me know if you want me to bring it back here instead.

I’ve noticed something like this too. When the TCP server I’m connected to send an RST I get a broken pipe which does register on the socket status callback, however calling .close or .disconnect does nothing to put the socket back in a state where it can reconnect to the server. After repeated connection attempts it will randomly decide to reestablish connection in 1-2 minutes. Pushing the “Save Preferences” button on the driver configuration page will also reset the socket somehow. It’s almost as if it has to wait for a keep-alive (that’s set at 1-2 minutes) to timeout before the connection registers as closed.

I’ve also when sending two or more packets in rapid succession (which generate two or more responses in rapid succession) I only receive the parse callback for one of them. I’ve have to put a 300ms delay between transmissions in order for parse to register both responses. It’s almost as if packets are dropped if the come in while parse is processing something.

Another request, unrelated to my earlier point, would be for synchronous write/read. Only having an asynchronous parse when a known reply is expected adds overhead to the implementation. It would be great to have that for all of the socket implementations (I would move directly to it in multiple integrations for ws and raw sockets).