Written by

Question Touggourt · Jul 16

Websocket client failing to return data

Hi,

Using the below code to connect and get data from a server:

Class SX3.Production.HTTP.AdvCredenials Extends (%RegisteredObject, %Net.WebSocket.ICredentials)
{Method GetUsername() As %String
{
quit ""
}/// Returns the password to use for authentication with the web socket
/// @API.Overrideable
Method GetPassword() As %String
{
quit ""
}Method GetSSLConfiguration() As %String
{
"RTLS"
}}

Class SX3.Production.HTTP.AdvListener Extends (%RegisteredObject, %Net.WebSocket.IEventListener)
{Method OnOpen()
{
 ^badis("mess",3)=1
if $increment(%ct("O")) set io=$io use 0 write "OPEN",! break:$get(%b) use io
}/// Called when an error occurs in the web socket connection.<br />
/// @API.Overrideable
Method OnError(pError As %Exception.AbstractException)
{
^badis("mess",4)=1
if $increment(%ct("E")) set io=$io use 0 write !
do $system.OBJ.DisplayError()
if pError.Code=28000 kill ws   use io quit     ;connection lost
zwrite pError write ! break:$get(%b) use io
}/// Called when the web socket connection is closed by either the client (%OnClose) or the server (by sending a close frame).<br />
/// @API.Overrideable
Method OnClose()
{
 if $increment(%ct("C")) set io=$io use 0 write "CLOSE",! BREAK:$get(%b) use io
}

/// Called when the client receives a message from the server. <br />
/// <var>pContent</var> may be a binary or UTF8-decoded character stream. <br />
/// @API.Overrideable
Method OnMessage(pContent As %Stream.Object)
{
^badis("mess",5)=1
if $increment(%ct("M")) set io=$io use 0 write "MESSAGE:",pContent,!
if $isobject(pContent) write pContent.Read(),! ^badis("mess")=pContent 
if $get(%b) zwrite pContent BREAK  
use io
}}
 

ClassMethod GetAdvData() As %String
{

 Token=##class(SX3.Task.TemperatureCollection).GetAuth()
BleMac="DC:0D:30:9D:14:49",GatewayMac="CC:1B:E0:E2:42:80"  // this for testing
set cre=##class(SX3.Production.HTTP.AdvCredenials).%New()
set evl=##class(SX3.Production.HTTP.AdvListener).%New()
^track("onmess",1)=cre_"|"_evl
Set WebSocURL="https://ac1.mqtt.sx3ac.com/api/gap/nodes?filter_mac="_BleMac_"&filter_rssi=-75&mac="_GatewayMac_"&active=1&event=1&chip=1&access_token="_Token
^track("onmess",2)=WebSocURL
Set WebSoc=##class(%Net.WebSocket.Client).%New(WebSocURL,cre,evl)
Quit WebSoc_"|"_WebSocURL

}

WebSockets are enabled on ports 80 & 443, but the code fails at Set WebSoc=##class(%Net.WebSocket.Client).%New(WebSocURL,cre,evl) call, any help would be much appreciated, also how can I get the generated data ?

iris version: IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2024.3 (Build 217U) Thu Nov 14 2024 17:30:43 EST 

BTW the same url runs fine and returns data if I run it in a browser:

Thanks Guys

Product version: IRIS 2024.3

Comments

Robert Cemper · Jul 16

You mentioned:

WebSockets are enabled on ports 80 & 443, but the code fails

Websockets work bi-directional
SO: Did you assign / map  those ports also in your docker-compose ?

0
Touggourt  Jul 16 to Robert Cemper

I would think so but double check with our system admin, but if they are exposed in the container with different port number how can I specify them in my code?  
Thx

0
Touggourt  Jul 16 to Robert Cemper

Yes just confirmed they are exposed with custom numbers, so how can I assign them in my code?

0
Robert Cemper · Jul 16

Hi 

your code
Set WebSoc=##class(%Net.WebSocket.Client).%New(WebSocURL,cre,evl)   
Just uses the Default %Net.HTTPrequest that contains url port, ....
But %New offers more
• Methode %OnNew(pURL As %String, pCredentials As %Net.WebSocket.ICredentials = $$$NULLOREF, pEventListener As %Net.WebSocket.IEventListener = $$$NULLOREF, pAcceptedProtocols As %String = "", pRequest As %Net.HttpRequest = $$$NULLOREF) als %Status
and in %Net.HTTPrequest you have a property port
https://docs.intersystems.com/iris20251/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&PRIVATE=1&CLASSNAME=%25Net.HttpRequest
I never needed it as protocol ws and wss was sufficient.
But there is no other place for a port to be assigned
 

0
Robert Cemper · Jul 16

My personal preference would be

  • verify Websockets with a js client (even in CSP)
  • then move it to IRIS with all hidden and default features if required at all.

You may check all the old WS examples in OEX

0