openc3 5.10.0 → 5.11.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Rakefile +3 -2
  4. data/data/config/target.yaml +9 -0
  5. data/ext/openc3/ext/packet/packet.c +3 -0
  6. data/ext/openc3/ext/reducer_microservice/extconf.rb +13 -0
  7. data/ext/openc3/ext/reducer_microservice/reducer_microservice.c +165 -0
  8. data/ext/openc3/ext/structure/structure.c +7 -9
  9. data/lib/openc3/accessors/accessor.rb +53 -3
  10. data/lib/openc3/accessors/binary_accessor.rb +16 -0
  11. data/lib/openc3/accessors/cbor_accessor.rb +3 -3
  12. data/lib/openc3/accessors/form_accessor.rb +78 -0
  13. data/lib/openc3/accessors/http_accessor.rb +145 -0
  14. data/lib/openc3/accessors/json_accessor.rb +19 -3
  15. data/lib/openc3/accessors/xml_accessor.rb +18 -1
  16. data/lib/openc3/accessors.rb +3 -1
  17. data/lib/openc3/config/config_parser.rb +7 -5
  18. data/lib/openc3/config/meta_config_parser.rb +1 -1
  19. data/lib/openc3/core_ext/string.rb +16 -1
  20. data/lib/openc3/interfaces/http_client_interface.rb +202 -0
  21. data/lib/openc3/interfaces/http_server_interface.rb +183 -0
  22. data/lib/openc3/interfaces/interface.rb +86 -16
  23. data/lib/openc3/interfaces/mqtt_interface.rb +6 -5
  24. data/lib/openc3/interfaces/protocols/burst_protocol.rb +11 -11
  25. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +7 -7
  26. data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -7
  27. data/lib/openc3/interfaces/protocols/length_protocol.rb +6 -6
  28. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +9 -5
  29. data/lib/openc3/interfaces/protocols/protocol.rb +8 -6
  30. data/lib/openc3/interfaces/protocols/slip_protocol.rb +8 -8
  31. data/lib/openc3/interfaces/protocols/template_protocol.rb +6 -7
  32. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +4 -4
  33. data/lib/openc3/interfaces/simulated_target_interface.rb +2 -0
  34. data/lib/openc3/interfaces/stream_interface.rb +6 -4
  35. data/lib/openc3/interfaces/tcpip_server_interface.rb +2 -0
  36. data/lib/openc3/interfaces/udp_interface.rb +8 -5
  37. data/lib/openc3/interfaces.rb +2 -0
  38. data/lib/openc3/logs/buffered_packet_log_writer.rb +6 -7
  39. data/lib/openc3/logs/log_writer.rb +2 -10
  40. data/lib/openc3/logs/packet_log_constants.rb +13 -3
  41. data/lib/openc3/logs/packet_log_reader.rb +35 -98
  42. data/lib/openc3/logs/packet_log_writer.rb +24 -62
  43. data/lib/openc3/logs/text_log_writer.rb +32 -6
  44. data/lib/openc3/microservices/cleanup_microservice.rb +23 -16
  45. data/lib/openc3/microservices/decom_microservice.rb +8 -20
  46. data/lib/openc3/microservices/log_microservice.rb +3 -1
  47. data/lib/openc3/microservices/reaction_microservice.rb +22 -11
  48. data/lib/openc3/microservices/reducer_microservice.rb +174 -130
  49. data/lib/openc3/{models/notification_model.rb → microservices/scope_cleanup_microservice.rb} +20 -21
  50. data/lib/openc3/microservices/text_log_microservice.rb +2 -5
  51. data/lib/openc3/microservices/timeline_microservice.rb +0 -1
  52. data/lib/openc3/microservices/trigger_group_microservice.rb +6 -3
  53. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +44 -0
  54. data/lib/openc3/models/microservice_model.rb +1 -1
  55. data/lib/openc3/models/scope_model.rb +65 -34
  56. data/lib/openc3/models/target_model.rb +25 -5
  57. data/lib/openc3/models/tool_model.rb +14 -2
  58. data/lib/openc3/models/widget_model.rb +1 -1
  59. data/lib/openc3/packets/json_packet.rb +10 -2
  60. data/lib/openc3/packets/packet.rb +37 -22
  61. data/lib/openc3/packets/packet_config.rb +6 -2
  62. data/lib/openc3/packets/parsers/packet_item_parser.rb +11 -6
  63. data/lib/openc3/packets/structure.rb +19 -12
  64. data/lib/openc3/packets/structure_item.rb +0 -3
  65. data/lib/openc3/script/storage.rb +1 -1
  66. data/lib/openc3/script/web_socket_api.rb +17 -14
  67. data/lib/openc3/topics/command_decom_topic.rb +0 -4
  68. data/lib/openc3/topics/telemetry_decom_topic.rb +0 -4
  69. data/lib/openc3/topics/telemetry_reduced_topics.rb +1 -13
  70. data/lib/openc3/topics/telemetry_topic.rb +2 -1
  71. data/lib/openc3/topics/topic.rb +0 -8
  72. data/lib/openc3/utilities/aws_bucket.rb +40 -38
  73. data/lib/openc3/utilities/bucket_utilities.rb +2 -0
  74. data/lib/openc3/utilities/cli_generator.rb +1 -1
  75. data/lib/openc3/utilities/logger.rb +62 -47
  76. data/lib/openc3/utilities/metric.rb +19 -1
  77. data/lib/openc3/utilities/sleeper.rb +3 -1
  78. data/lib/openc3/utilities/throttle.rb +76 -0
  79. data/lib/openc3/version.rb +5 -5
  80. data/templates/tool_angular/package.json +20 -20
  81. data/templates/tool_angular/yarn.lock +1815 -1009
  82. data/templates/tool_react/package.json +24 -26
  83. data/templates/tool_react/yarn.lock +1269 -902
  84. data/templates/tool_svelte/.prettierrc.js +5 -0
  85. data/templates/tool_svelte/package.json +26 -26
  86. data/templates/tool_svelte/src/services/cable.js +1 -1
  87. data/templates/tool_svelte/src/services/openc3-api.js +173 -173
  88. data/templates/tool_svelte/yarn.lock +981 -735
  89. data/templates/tool_vue/package.json +13 -13
  90. data/templates/tool_vue/yarn.lock +363 -147
  91. data/templates/widget/package.json +14 -14
  92. data/templates/widget/yarn.lock +367 -99
  93. metadata +41 -4
  94. 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