components_vendor_BrightWebSocket_web_socket_client_WebSocketClientTask.brs
' WebSocketClientTask.brs
' Copyright (C) 2018 Rolando Islas
' Released under the MIT license
'
' BrightScript, SceneGraph Task wrapper for the web socket client
'
' JellyRock modification (see ../../README.md): removed the `secure`/TLS field
' handling (ws:// only — upstream TLS was unimplemented and Roku can't do socket TLS).
' Entry point
sub init()
' Task init
m.top.functionName = "runSocketLoop"
m.top.control = "RUN"
end sub
' Main task loop.
' JellyRock modification: renamed from `run` — a top-level `run()` collides with the built-in
' global `Run()` (BSC: cannot-use-reserved-word / native-function-collision). It worked upstream
' only because the Task dispatches it by the `functionName` STRING, never a scope call; renamed so
' we don't rely on that and the diagnostic is genuinely resolved, not just suppressed.
sub runSocketLoop()
m.ws = WebSocketClient()
m.port = createObject("roMessagePort")
m.ws.set_message_port(m.port)
' Fields
m.top.STATE_CONNECTING = m.ws.STATE.CONNECTING
m.top.STATE_OPEN = m.ws.STATE.OPEN
m.top.STATE_CLOSING = m.ws.STATE.CLOSING
m.top.STATE_CLOSED = m.ws.STATE.CLOSED
m.top.ready_state = m.ws.get_ready_state()
m.top.protocols = m.ws.get_protocols()
m.top.headers = m.ws.get_headers()
m.top.buffer_size = m.ws.get_buffer_size()
' Event listeners
m.top.observeField("open", m.port)
m.top.observeField("send", m.port)
m.top.observeField("close", m.port)
m.top.observeField("buffer_size", m.port)
m.top.observeField("protocols", m.port)
m.top.observeField("headers", m.port)
m.top.observeField("log_level", m.port)
if len(m.top.open) > 0
m.ws.open(m.top.open)
end if
while true
' Check task messages. JellyRock hardening: poll every 100ms instead of the upstream
' 1ms busy-loop — this is a latency-tolerant remote-control channel (commands seconds
' apart), so ~100ms adds no perceptible latency but cuts idle CPU ~100x.
msg = wait(100, m.port)
' Field event
if type(msg) = "roSGNodeEvent"
if msg.getField() = "open"
m.ws.open(msg.getData())
else if msg.getField() = "send"
m.ws.send(msg.getData())
else if msg.getField() = "close"
m.ws.close(msg.getData())
else if msg.getField() = "buffer_size"
m.ws.set_buffer_size(msg.getData())
else if msg.getField() = "protocols"
m.ws.set_protocols(msg.getData())
else if msg.getField() = "headers"
m.ws.set_headers(msg.getData())
else if msg.getField() = "log_level"
m.ws.set_log_level(msg.getData())
end if
' WebSocket event
else if type(msg) = "roAssociativeArray"
if msg.id = "on_open"
m.top.on_open = msg.data
else if msg.id = "on_close"
m.top.on_close = msg.data
else if msg.id = "on_message"
m.top.on_message = msg.data
else if msg.id = "on_error"
m.top.on_error = msg.data
else if msg.id = "ready_state"
m.top.ready_state = msg.data
else if msg.id = "buffer_size"
m.top.unobserveField("buffer_size")
m.top.buffer_size = msg.data
m.top.observeField("buffer_size", m.task_port)
else if msg.id = "protocols"
m.top.unobserveField("protocols")
m.top.protocols = msg.data
m.top.observeField("protocols", m.task_port)
else if msg.id = "headers"
m.top.unobserveField("headers")
m.top.headers = msg.data
m.top.observeField("headers", m.task_port)
end if
end if
m.ws.run()
end while
end sub