openc3 5.10.1 → 5.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -2
  3. data/data/config/target.yaml +9 -0
  4. data/ext/openc3/ext/packet/packet.c +3 -0
  5. data/ext/openc3/ext/reducer_microservice/extconf.rb +13 -0
  6. data/ext/openc3/ext/reducer_microservice/reducer_microservice.c +165 -0
  7. data/ext/openc3/ext/structure/structure.c +7 -9
  8. data/lib/openc3/accessors/accessor.rb +53 -3
  9. data/lib/openc3/accessors/binary_accessor.rb +16 -0
  10. data/lib/openc3/accessors/cbor_accessor.rb +3 -3
  11. data/lib/openc3/accessors/form_accessor.rb +78 -0
  12. data/lib/openc3/accessors/http_accessor.rb +145 -0
  13. data/lib/openc3/accessors/json_accessor.rb +19 -3
  14. data/lib/openc3/accessors/xml_accessor.rb +18 -1
  15. data/lib/openc3/accessors.rb +3 -1
  16. data/lib/openc3/config/config_parser.rb +7 -5
  17. data/lib/openc3/config/meta_config_parser.rb +1 -1
  18. data/lib/openc3/core_ext/string.rb +16 -1
  19. data/lib/openc3/interfaces/http_client_interface.rb +202 -0
  20. data/lib/openc3/interfaces/http_server_interface.rb +183 -0
  21. data/lib/openc3/interfaces/interface.rb +86 -16
  22. data/lib/openc3/interfaces/mqtt_interface.rb +6 -5
  23. data/lib/openc3/interfaces/protocols/burst_protocol.rb +11 -11
  24. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +7 -7
  25. data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -7
  26. data/lib/openc3/interfaces/protocols/length_protocol.rb +6 -6
  27. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +9 -5
  28. data/lib/openc3/interfaces/protocols/protocol.rb +8 -6
  29. data/lib/openc3/interfaces/protocols/slip_protocol.rb +8 -8
  30. data/lib/openc3/interfaces/protocols/template_protocol.rb +6 -7
  31. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +4 -4
  32. data/lib/openc3/interfaces/simulated_target_interface.rb +2 -0
  33. data/lib/openc3/interfaces/stream_interface.rb +6 -4
  34. data/lib/openc3/interfaces/tcpip_server_interface.rb +2 -0
  35. data/lib/openc3/interfaces/udp_interface.rb +8 -5
  36. data/lib/openc3/interfaces.rb +2 -0
  37. data/lib/openc3/logs/buffered_packet_log_writer.rb +6 -7
  38. data/lib/openc3/logs/log_writer.rb +2 -10
  39. data/lib/openc3/logs/packet_log_constants.rb +13 -3
  40. data/lib/openc3/logs/packet_log_reader.rb +35 -98
  41. data/lib/openc3/logs/packet_log_writer.rb +24 -62
  42. data/lib/openc3/logs/text_log_writer.rb +32 -6
  43. data/lib/openc3/microservices/cleanup_microservice.rb +23 -16
  44. data/lib/openc3/microservices/decom_microservice.rb +8 -20
  45. data/lib/openc3/microservices/log_microservice.rb +3 -1
  46. data/lib/openc3/microservices/reaction_microservice.rb +22 -11
  47. data/lib/openc3/microservices/reducer_microservice.rb +174 -130
  48. data/lib/openc3/{models/notification_model.rb → microservices/scope_cleanup_microservice.rb} +20 -21
  49. data/lib/openc3/microservices/text_log_microservice.rb +2 -5
  50. data/lib/openc3/microservices/timeline_microservice.rb +0 -1
  51. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -1
  52. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +44 -0
  53. data/lib/openc3/models/microservice_model.rb +1 -1
  54. data/lib/openc3/models/scope_model.rb +65 -34
  55. data/lib/openc3/models/target_model.rb +25 -5
  56. data/lib/openc3/models/tool_model.rb +14 -2
  57. data/lib/openc3/models/widget_model.rb +1 -1
  58. data/lib/openc3/packets/json_packet.rb +10 -2
  59. data/lib/openc3/packets/packet.rb +30 -9
  60. data/lib/openc3/packets/packet_config.rb +6 -2
  61. data/lib/openc3/packets/parsers/packet_item_parser.rb +11 -6
  62. data/lib/openc3/packets/structure.rb +19 -12
  63. data/lib/openc3/script/storage.rb +1 -1
  64. data/lib/openc3/script/web_socket_api.rb +17 -14
  65. data/lib/openc3/topics/telemetry_topic.rb +2 -1
  66. data/lib/openc3/utilities/bucket_utilities.rb +2 -0
  67. data/lib/openc3/utilities/cli_generator.rb +1 -1
  68. data/lib/openc3/utilities/logger.rb +62 -47
  69. data/lib/openc3/utilities/metric.rb +19 -1
  70. data/lib/openc3/utilities/sleeper.rb +3 -1
  71. data/lib/openc3/utilities/throttle.rb +76 -0
  72. data/lib/openc3/version.rb +6 -6
  73. data/templates/tool_angular/package.json +20 -20
  74. data/templates/tool_angular/yarn.lock +112 -106
  75. data/templates/tool_react/package.json +16 -18
  76. data/templates/tool_react/yarn.lock +977 -664
  77. data/templates/tool_svelte/.prettierrc.js +5 -0
  78. data/templates/tool_svelte/package.json +18 -18
  79. data/templates/tool_svelte/src/services/cable.js +1 -1
  80. data/templates/tool_svelte/src/services/openc3-api.js +173 -173
  81. data/templates/tool_svelte/yarn.lock +767 -665
  82. data/templates/tool_vue/package.json +10 -10
  83. data/templates/tool_vue/yarn.lock +225 -43
  84. data/templates/widget/package.json +10 -10
  85. data/templates/widget/yarn.lock +223 -46
  86. metadata +41 -4
  87. data/lib/openc3/topics/notifications_topic.rb +0 -31
@@ -13,7 +13,7 @@
13
13
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
  # GNU Affero General Public License for more details.
15
15
  #
16
- # This file may also be used under the terms of a commercial license
16
+ # This file may also be used under the terms of a commercial license
17
17
  # if purchased from OpenC3, Inc.
18
18
 
19
19
  require 'json'
@@ -45,7 +45,7 @@ module OpenC3
45
45
  buffer.replace(JSON.generate(decoded, :allow_nan => true))
46
46
  end
47
47
 
48
- return buffer
48
+ return value
49
49
  end
50
50
 
51
51
  def self.read_items(items, buffer)
@@ -78,7 +78,7 @@ module OpenC3
78
78
  buffer.replace(JSON.generate(decoded, :allow_nan => true))
79
79
  end
80
80
 
81
- return buffer
81
+ return values
82
82
  end
83
83
 
84
84
  def self.write_item_internal(item, value, decoded)
@@ -130,5 +130,21 @@ module OpenC3
130
130
  end
131
131
  return decoded
132
132
  end
133
+
134
+ def enforce_encoding
135
+ return nil
136
+ end
137
+
138
+ def enforce_length
139
+ return false
140
+ end
141
+
142
+ def enforce_short_buffer_allowed
143
+ return true
144
+ end
145
+
146
+ def enforce_derived_write_conversion(item)
147
+ return true
148
+ end
133
149
  end
134
150
  end
@@ -13,7 +13,7 @@
13
13
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
  # GNU Affero General Public License for more details.
15
15
  #
16
- # This file may also be used under the terms of a commercial license
16
+ # This file may also be used under the terms of a commercial license
17
17
  # if purchased from OpenC3, Inc.
18
18
 
19
19
  require 'nokogiri'
@@ -33,6 +33,7 @@ module OpenC3
33
33
  node = doc.xpath(item.key).first
34
34
  node.content = value.to_s
35
35
  buffer.replace(doc_to_buffer(doc))
36
+ return value
36
37
  end
37
38
 
38
39
  def self.read_items(items, buffer)
@@ -56,6 +57,7 @@ module OpenC3
56
57
  node.content = values[index].to_s
57
58
  end
58
59
  buffer.replace(doc_to_buffer(doc))
60
+ return values
59
61
  end
60
62
 
61
63
  def self.buffer_to_doc(buffer)
@@ -66,5 +68,20 @@ module OpenC3
66
68
  doc.to_xml
67
69
  end
68
70
 
71
+ def enforce_encoding
72
+ return nil
73
+ end
74
+
75
+ def enforce_length
76
+ return false
77
+ end
78
+
79
+ def enforce_short_buffer_allowed
80
+ return true
81
+ end
82
+
83
+ def enforce_derived_write_conversion(item)
84
+ return true
85
+ end
69
86
  end
70
87
  end
@@ -13,14 +13,16 @@
13
13
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
  # GNU Affero General Public License for more details.
15
15
  #
16
- # This file may also be used under the terms of a commercial license
16
+ # This file may also be used under the terms of a commercial license
17
17
  # if purchased from OpenC3, Inc.
18
18
 
19
19
  module OpenC3
20
20
  autoload(:Accessor, 'openc3/accessors/accessor.rb')
21
21
  autoload(:BinaryAccessor, 'openc3/accessors/binary_accessor.rb')
22
22
  autoload(:CborAccessor, 'openc3/accessors/cbor_accessor.rb')
23
+ autoload(:FormAccessor, 'openc3/accessors/form_accessor.rb')
23
24
  autoload(:HtmlAccessor, 'openc3/accessors/html_accessor.rb')
25
+ autoload(:HttpAccessor, 'openc3/accessors/http_accessor.rb')
24
26
  autoload(:JsonAccessor, 'openc3/accessors/json_accessor.rb')
25
27
  autoload(:XmlAccessor, 'openc3/accessors/xml_accessor.rb')
26
28
  end
@@ -166,7 +166,7 @@ module OpenC3
166
166
  options[:locals].each { |key, value| b.local_variable_set(key, value) }
167
167
  end
168
168
 
169
- return ERB.new(read_file(template_name), trim_mode: "-").result(b)
169
+ return ERB.new(read_file(template_name).comment_erb(), trim_mode: "-").result(b)
170
170
  end
171
171
 
172
172
  # Can be called during parsing to read a referenced file
@@ -178,7 +178,7 @@ module OpenC3
178
178
  path = File.join(File.dirname(@filename), filename)
179
179
  end
180
180
  OpenC3.set_working_dir(File.dirname(path)) do
181
- return File.read(path)
181
+ return File.read(path).force_encoding("UTF-8")
182
182
  end
183
183
  end
184
184
 
@@ -385,10 +385,10 @@ module OpenC3
385
385
  output = nil
386
386
  if run_erb
387
387
  OpenC3.set_working_dir(File.dirname(filename)) do
388
- output = ERB.new(File.read(filename), trim_mode: "-").result(binding.set_variables(variables))
388
+ output = ERB.new(File.read(filename).force_encoding("UTF-8").comment_erb(), trim_mode: "-").result(binding.set_variables(variables))
389
389
  end
390
390
  else
391
- output = File.read(filename)
391
+ output = File.read(filename).force_encoding("UTF-8")
392
392
  end
393
393
  rescue => e
394
394
  # The first line of the backtrace indicates the line where the ERB
@@ -453,8 +453,10 @@ module OpenC3
453
453
  message += "\n#{File.basename(error.filename)}:#{error.line_number}: #{error.line}"
454
454
  message += "\nError: #{error.message}"
455
455
  message += "\nUsage: #{error.usage}" unless error.usage.empty?
456
+ message += "\nBacktrace:"
457
+ message += "\n#{error.backtrace.join("\n")}"
456
458
  else
457
- message += "\n#{error.message}"
459
+ message += "\n#{error.formatted}"
458
460
  end
459
461
  message += "\n"
460
462
  end
@@ -17,7 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'erb'
@@ -389,4 +389,19 @@ class String
389
389
  end
390
390
  end
391
391
 
392
- end # class String
392
+ def comment_erb
393
+ output = self.lines.collect! do |line|
394
+ # If we have a commented out line that starts with #
395
+ # but not followed by % (allows for disabling ERB comments),
396
+ # which contains an ERB statement (<% ...)
397
+ # then comment out the ERB statement (<%# ...).
398
+ # We explicitly don't comment out trailing ERB statements
399
+ # as that is not typical and is difficult to regex
400
+ if line =~ /^\s*#[^%]*<%/
401
+ line.gsub!('<%', '<%#')
402
+ end
403
+ line
404
+ end
405
+ return output.join("")
406
+ end
407
+ end
@@ -0,0 +1,202 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2023 OpenC3, Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # This file may also be used under the terms of a commercial license
17
+ # if purchased from OpenC3, Inc.
18
+
19
+ require 'openc3/interfaces/interface'
20
+ require 'openc3/config/config_parser'
21
+ require 'faraday'
22
+ require 'faraday/follow_redirects'
23
+ require 'openc3/accessors/http_accessor'
24
+
25
+ # TODO: Header Log Filtering? File Uploads? Authorization from secrets?
26
+
27
+ module OpenC3
28
+ class HttpClientInterface < Interface
29
+ # @param hostname [String] HTTP/HTTPS server to connect to
30
+ # @param port [Integer] HTTP/HTTPS port
31
+ # @param protocol [String] http or https
32
+ def initialize(hostname, port = 80, protocol = 'http', write_timeout = 5, read_timeout = nil, connect_timeout = 5, include_request_in_response = false)
33
+ super()
34
+ @hostname = hostname
35
+ @port = Integer(port)
36
+ @protocol = protocol
37
+ if (port == 80 and protocol == 'http') or (port == 443 and protocol == 'https')
38
+ @url = "#{protocol}://#{hostname}"
39
+ else
40
+ @url = "#{protocol}://#{hostname}:#{port}"
41
+ end
42
+ @write_timeout = ConfigParser.handle_nil(write_timeout)
43
+ @write_timeout = Float(@write_timeout) if @write_timeout
44
+ @read_timeout = ConfigParser.handle_nil(read_timeout)
45
+ @read_timeout = Float(@read_timeout) if @read_timeout
46
+ @connect_timeout = ConfigParser.handle_nil(connect_timeout)
47
+ @connect_timeout = Float(@connect_timeout) if @connect_timeout
48
+ @include_request_in_response = ConfigParser.handle_true_false(include_request_in_response)
49
+
50
+ @response_queue = Queue.new
51
+ end
52
+
53
+ # Connects the interface to its target(s)
54
+ def connect
55
+ # Per https://github.com/lostisland/faraday/blob/main/lib/faraday/options/env.rb
56
+ # :timeout - time limit for the entire request (Integer in seconds)
57
+ # :open_timeout - time limit for just the connection phase (e.g. handshake) (Integer in seconds)
58
+ # :read_timeout - time limit for the first response byte received from the server (Integer in seconds)
59
+ # :write_timeout - time limit for the client to send the request to the server (Integer in seconds)
60
+ request = {}
61
+ request['open_timeout'] = @connect_timeout if @connect_timeout
62
+ request['read_timeout'] = @read_timeout if @read_timeout
63
+ request['write_timeout'] = @write_timeout if @write_timeout
64
+ @http = Faraday.new(request: request) do |f|
65
+ f.response :follow_redirects # use Faraday::FollowRedirects::Middleware
66
+ f.adapter :net_http # adds the adapter to the connection, defaults to `Faraday.default_adapter`
67
+ end
68
+ super()
69
+ end
70
+
71
+ def connected?
72
+ if @http
73
+ return true
74
+ else
75
+ return false
76
+ end
77
+ end
78
+
79
+ # Disconnects the interface from its target(s)
80
+ def disconnect
81
+ @http.close if @http
82
+ @http = nil
83
+ while @response_queue.length > 0
84
+ @response_queue.pop
85
+ end
86
+ super()
87
+ @response_queue.push(nil)
88
+ end
89
+
90
+ # Reads from the socket if the read_port is defined
91
+ def read_interface
92
+ # Get the Faraday Response
93
+ data, extra = @response_queue.pop
94
+ return nil if data.nil?
95
+
96
+ read_interface_base(data, extra)
97
+ return data, extra
98
+ end
99
+
100
+ # Writes to the socket
101
+ # @param data [Hash] For the HTTP Interface, data is a hash with the needed request info
102
+ def write_interface(data, extra = nil)
103
+ extra ||= {}
104
+ queries = extra['HTTP_QUERIES']
105
+ queries ||= {}
106
+ headers = extra['HTTP_HEADERS']
107
+ headers ||= {}
108
+ uri = extra['HTTP_URI']
109
+ method = extra['HTTP_METHOD']
110
+
111
+ resp = nil
112
+ case method
113
+ when 'get'
114
+ resp = @http.get(uri, queries, headers)
115
+ when 'put'
116
+ resp = @http.put(uri) do |req|
117
+ req.params = queries
118
+ req.headers = headers
119
+ req.body = data
120
+ end
121
+ when 'delete'
122
+ resp = @http.delete(uri, queries, headers)
123
+ else # 'post'
124
+ resp = @http.post(uri) do |req|
125
+ req.params = queries
126
+ req.headers = headers
127
+ req.body = data
128
+ end
129
+ end
130
+
131
+ # Normalize Response into simple hash
132
+ response_data = nil
133
+ response_extra = {}
134
+ if resp
135
+ response_extra['HTTP_REQUEST'] = [data, extra]
136
+ if resp.headers and resp.headers.length > 0
137
+ response_extra['HTTP_HEADERS'] = resp.headers
138
+ end
139
+ response_extra['HTTP_STATUS'] = resp.status
140
+ response_data = resp.body
141
+ response_data ||= '' # Ensure an empty string if we got a response but no data
142
+ end
143
+
144
+ @response_queue.push([response_data, response_extra])
145
+
146
+ write_interface_base(data, extra)
147
+ return data, extra
148
+ end
149
+
150
+ # Called to convert the read data into a OpenC3 Packet object
151
+ #
152
+ # @param data [String] Raw packet data
153
+ # @return [Packet] OpenC3 Packet with buffer filled with data
154
+ def convert_data_to_packet(data, extra = nil)
155
+ packet = Packet.new(nil, nil, :BIG_ENDIAN, nil, data.to_s)
156
+ packet.accessor = HttpAccessor.new(packet)
157
+ if extra
158
+ # Identify the response
159
+ request_target_name = extra['HTTP_REQUEST_TARGET_NAME']
160
+ if request_target_name
161
+ request_target_name = request_target_name.to_s.upcase
162
+ response_packet_name = extra['HTTP_PACKET']
163
+ error_packet_name = extra['HTTP_ERROR_PACKET']
164
+ status = extra['HTTP_STATUS'].to_i
165
+ if status >= 300 and error_packet_name
166
+ # Handle error special case response packet
167
+ packet.target_name = request_target_name
168
+ packet.packet_name = error_packet_name.to_s.upcase
169
+ else
170
+ if response_packet_name
171
+ packet.target_name = request_target_name
172
+ packet.packet_name = response_packet_name.to_s.upcase
173
+ end
174
+ end
175
+ end
176
+
177
+ if not @include_request_in_response
178
+ extra.delete("HTTP_REQUEST")
179
+ end
180
+ extra.delete("HTTP_REQUEST_TARGET_NAME")
181
+ extra.delete("HTTP_REQUEST_PACKET_NAME")
182
+ packet.extra = extra
183
+ end
184
+
185
+ return packet
186
+ end
187
+
188
+ # Called to convert a packet into the data to send
189
+ #
190
+ # @param packet [Packet] Packet to extract data from
191
+ # @return data
192
+ def convert_packet_to_data(packet)
193
+ extra = packet.extra
194
+ extra ||= {}
195
+ data = packet.buffer(true) # Copy buffer so logged command isn't modified
196
+ extra['HTTP_URI'] = URI("#{@url}#{packet.read('HTTP_PATH')}").to_s
197
+ extra['HTTP_REQUEST_TARGET_NAME'] = packet.target_name
198
+ extra['HTTP_REQUEST_PACKET_NAME'] = packet.packet_name
199
+ return data, extra
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,183 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2023 OpenC3, Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # This file may also be used under the terms of a commercial license
17
+ # if purchased from OpenC3, Inc.
18
+
19
+ require 'openc3/interfaces/interface'
20
+ require 'openc3/config/config_parser'
21
+ require 'openc3/accessors/http_accessor'
22
+ require 'webrick'
23
+
24
+ module OpenC3
25
+ class HttpServerInterface < Interface
26
+ # @param port [Integer] HTTP port
27
+ def initialize(port = 80)
28
+ super()
29
+ @port = Integer(port)
30
+ @server = nil
31
+ @request_queue = Queue.new
32
+ end
33
+
34
+ # Connects the interface to its target(s)
35
+ def connect
36
+ @server = WEBrick::HTTPServer.new :Port => @port
37
+ @request_queue = Queue.new
38
+
39
+ # Create a response hook for every command packet
40
+ @target_names.each do |target_name|
41
+ System.commands.packets(target_name).each do |packet_name, packet|
42
+ packet.restore_defaults
43
+ path = nil
44
+ begin
45
+ path = packet.read('HTTP_PATH')
46
+ rescue => err
47
+ # No HTTP_PATH is an error
48
+ Logger.error("HttpServerInterface Packet #{target_name} #{packet_name} unable to read HTTP_PATH\n#{err.formatted}")
49
+ end
50
+ if path
51
+ @server.mount_proc path do |req, res|
52
+ # Build the Response
53
+ begin
54
+ status = packet.read('HTTP_STATUS')
55
+ if status
56
+ res.status = status
57
+ end
58
+ rescue
59
+ # No HTTP_STATUS - Leave at default
60
+ end
61
+
62
+ if packet.extra
63
+ headers = packet.extra['HTTP_HEADERS']
64
+ if headers
65
+ headers.each do |key, value|
66
+ res[key] = value
67
+ end
68
+ end
69
+ end
70
+
71
+ res.body = packet.buffer
72
+
73
+ # Save the Request
74
+ packet_name = nil
75
+ begin
76
+ packet_name = packet.read('HTTP_PACKET')
77
+ rescue
78
+ # No packet name means dont save the request as telemetry
79
+ end
80
+ if packet_name
81
+ data = req.body.to_s.dup # Dup to remove frozen
82
+ extra = {}
83
+ extra['HTTP_REQUEST_TARGET_NAME'] = target_name
84
+ extra['HTTP_REQUEST_PACKET_NAME'] = packet_name
85
+
86
+ headers = req.header
87
+ if headers
88
+ extra['HTTP_HEADERS'] = {}
89
+ headers.each do |key, value|
90
+ extra['HTTP_HEADERS'][key.downcase] = value
91
+ end
92
+ end
93
+
94
+ queries = req.query
95
+ if queries
96
+ extra['HTTP_QUERIES'] = {}
97
+ queries.each do |key, value|
98
+ extra['HTTP_QUERIES'][key] = value
99
+ end
100
+ end
101
+
102
+ @request_queue << [data, extra]
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ super()
110
+
111
+ Thread.new do
112
+ # This blocks, but will be unblocked by server.shutdown called in disconnect()
113
+ @server.start
114
+ end
115
+ end
116
+
117
+ def connected?
118
+ if @server
119
+ return true
120
+ else
121
+ return false
122
+ end
123
+ end
124
+
125
+ # Disconnects the interface from its target(s)
126
+ def disconnect
127
+ @server.shutdown if @server
128
+ @server = nil
129
+ while @request_queue.length > 0
130
+ @request_queue.pop
131
+ end
132
+ super()
133
+ @request_queue.push(nil)
134
+ end
135
+
136
+ # Reads from the socket if the read_port is defined
137
+ def read_interface
138
+ # Get the Faraday Response
139
+ data, extra = @request_queue.pop
140
+ return nil if data.nil?
141
+
142
+ read_interface_base(data, extra)
143
+ return data, extra
144
+ end
145
+
146
+ # Writes to the socket
147
+ # @param data [Hash] For the HTTP Interface, data is a hash with the needed request info
148
+ def write_interface(data, extra = nil)
149
+ raise "Commands cannot be sent to HttpServerInterface"
150
+ end
151
+
152
+ # Called to convert the read data into a OpenC3 Packet object
153
+ #
154
+ # @param data [String] Raw packet data
155
+ # @return [Packet] OpenC3 Packet with buffer filled with data
156
+ def convert_data_to_packet(data, extra = nil)
157
+ packet = Packet.new(nil, nil, :BIG_ENDIAN, nil, data.to_s)
158
+ packet.accessor = HttpAccessor.new(packet)
159
+ if extra
160
+ # Identify the response
161
+ request_target_name = extra['HTTP_REQUEST_TARGET_NAME']
162
+ request_packet_name = extra['HTTP_REQUEST_PACKET_NAME']
163
+ if request_target_name and request_packet_name
164
+ packet.target_name = request_target_name.to_s.upcase
165
+ packet.packet_name = request_packet_name.to_s.upcase
166
+ end
167
+ extra.delete("HTTP_REQUEST_TARGET_NAME")
168
+ extra.delete("HTTP_REQUEST_PACKET_NAME")
169
+ packet.extra = extra
170
+ end
171
+
172
+ return packet
173
+ end
174
+
175
+ # Called to convert a packet into the data to send
176
+ #
177
+ # @param packet [Packet] Packet to extract data from
178
+ # @return data
179
+ def convert_packet_to_data(packet)
180
+ raise "Commands cannot be sent to HttpServerInterface"
181
+ end
182
+ end
183
+ end