Class: OpenC3::WebSocketApi
- Defined in:
- lib/openc3/script/web_socket_api.rb
Overview
Base class - Do not use directly
Direct Known Subclasses
Constant Summary collapse
- USER_AGENT =
'OpenC3 / v7 (ruby/openc3/lib/io/web_socket_api)'.freeze
Instance Method Summary collapse
-
#connect ⇒ Object
Connect to the websocket with authorization in query params.
-
#connected? ⇒ Boolean
Are we connected?.
-
#disconnect ⇒ Object
Disconnect from the websocket and attempt to send unsubscribe message.
-
#generate_auth ⇒ Object
Generate the appropriate token for OpenC3.
-
#initialize(url:, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope, &block) ⇒ WebSocketApi
constructor
Create the WebsocketApi object.
-
#read(ignore_protocol_messages: true, timeout: nil) ⇒ Object
Read the next message with json parsing, filtering, and timeout support.
-
#read_message ⇒ Object
Read the next message without filtering / parsing.
-
#subscribe ⇒ Object
Will subscribe to the channel based on @identifier.
-
#unsubscribe ⇒ Object
Will unsubscribe to the channel based on @identifier.
-
#write(data) ⇒ Object
General write to the websocket.
-
#write_action(data_hash) ⇒ Object
Send an ActionCable command.
Constructor Details
#initialize(url:, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope, &block) ⇒ WebSocketApi
Create the WebsocketApi object. If a block is given will automatically connect/disconnect
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/openc3/script/web_socket_api.rb', line 24 def initialize(url:, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope, &block) @scope = scope @authentication = authentication.nil? ? generate_auth() : authentication @url = url @write_timeout = write_timeout @read_timeout = read_timeout @connect_timeout = connect_timeout @subscribed = false if block_given? begin connect() yield self ensure disconnect() end end end |
Instance Method Details
#connect ⇒ Object
Connect to the websocket with authorization in query params
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/openc3/script/web_socket_api.rb', line 129 def connect disconnect() final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.get_otp(scope: @scope)}" @stream = WebSocketClientStream.new(final_url, @write_timeout, @read_timeout, @connect_timeout) @stream.headers = { 'Sec-WebSocket-Protocol' => 'actioncable-v1-json, actioncable-unsupported', 'User-Agent' => USER_AGENT } @stream.connect end |
#connected? ⇒ Boolean
Are we connected?
141 142 143 144 145 146 147 |
# File 'lib/openc3/script/web_socket_api.rb', line 141 def connected? if @stream @stream.connected? else false end end |
#disconnect ⇒ Object
Disconnect from the websocket and attempt to send unsubscribe message
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/openc3/script/web_socket_api.rb', line 150 def disconnect if connected?() begin unsubscribe() rescue # Oh well, we tried end @stream.disconnect end end |
#generate_auth ⇒ Object
Generate the appropriate token for OpenC3
164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/openc3/script/web_socket_api.rb', line 164 def generate_auth if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil? if ENV['OPENC3_API_PASSWORD'] return OpenC3Authentication.new() else raise "Environment Variables Not Set for Authentication" end else return OpenC3KeycloakAuthentication.new(ENV['OPENC3_KEYCLOAK_URL']) end end |
#read(ignore_protocol_messages: true, timeout: nil) ⇒ Object
Read the next message with json parsing, filtering, and timeout support
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/openc3/script/web_socket_api.rb', line 49 def read(ignore_protocol_messages: true, timeout: nil) start_time = Time.now while true = () # Empty string is a normal end-of-stream signal when ActionCable / anycable-go # closes the WS. Treat it the same as nil so consumer `while (resp = api.read)` # loops exit cleanly instead of hitting JSON::ParserError on JSON.parse(""). return nil if .nil? || .empty? begin json_hash = JSON.parse(, allow_nan: true, create_additions: true) rescue JSON::ParserError # Defense-in-depth: treat malformed frames as end-of-stream rather than crashing. return nil end if type = json_hash['type'] if type # ping, welcome, confirm_subscription, reject_subscription, disconnect if type == 'disconnect' if json_hash['reason'] == 'unauthorized' raise "Unauthorized" end end if type == 'reject_subscription' raise "Subscription Rejected" end if timeout end_time = Time.now if (end_time - start_time) > timeout raise Timeout::Error, "No Data Timeout" end end if defined? RunningScript and RunningScript.instance raise StopScript if RunningScript.instance.stop? end next end end return json_hash['message'] end end |
#read_message ⇒ Object
Read the next message without filtering / parsing
43 44 45 46 |
# File 'lib/openc3/script/web_socket_api.rb', line 43 def subscribe() return @stream.read end |
#subscribe ⇒ Object
Will subscribe to the channel based on @identifier
92 93 94 95 96 97 98 99 100 |
# File 'lib/openc3/script/web_socket_api.rb', line 92 def subscribe unless @subscribed json_hash = {} json_hash['command'] = 'subscribe' json_hash['identifier'] = JSON.generate(@identifier, allow_nan: true) @stream.write(JSON.generate(json_hash, allow_nan: true)) @subscribed = true end end |
#unsubscribe ⇒ Object
Will unsubscribe to the channel based on @identifier
103 104 105 106 107 108 109 110 111 |
# File 'lib/openc3/script/web_socket_api.rb', line 103 def unsubscribe if @subscribed json_hash = {} json_hash['command'] = 'unsubscribe' json_hash['identifier'] = JSON.generate(@identifier, allow_nan: true) @stream.write(JSON.generate(json_hash, allow_nan: true)) @subscribed = false end end |
#write(data) ⇒ Object
General write to the websocket
123 124 125 126 |
# File 'lib/openc3/script/web_socket_api.rb', line 123 def write(data) subscribe() @stream.write(data) end |
#write_action(data_hash) ⇒ Object
Send an ActionCable command
114 115 116 117 118 119 120 |
# File 'lib/openc3/script/web_socket_api.rb', line 114 def write_action(data_hash) json_hash = {} json_hash['command'] = 'message' json_hash['identifier'] = JSON.generate(@identifier, allow_nan: true) json_hash['data'] = JSON.generate(data_hash, allow_nan: true) write(JSON.generate(json_hash, allow_nan: true)) end |