openc3 5.5.2 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +167 -69
  3. data/data/config/_interfaces.yaml +1 -6
  4. data/data/config/interface_modifiers.yaml +55 -4
  5. data/data/config/microservice.yaml +30 -3
  6. data/ext/openc3/ext/crc/crc.c +82 -1
  7. data/lib/openc3/api/cmd_api.rb +19 -7
  8. data/lib/openc3/api/tlm_api.rb +13 -12
  9. data/lib/openc3/bridge/bridge_config.rb +4 -4
  10. data/lib/openc3/config/config_parser.rb +1 -0
  11. data/lib/openc3/conversions/unix_time_conversion.rb +3 -1
  12. data/lib/openc3/ext/.keep +0 -0
  13. data/lib/openc3/interfaces/interface.rb +54 -26
  14. data/lib/openc3/interfaces/serial_interface.rb +4 -5
  15. data/lib/openc3/interfaces/simulated_target_interface.rb +4 -4
  16. data/lib/openc3/interfaces/stream_interface.rb +2 -2
  17. data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -3
  18. data/lib/openc3/interfaces/tcpip_server_interface.rb +18 -19
  19. data/lib/openc3/interfaces/udp_interface.rb +10 -4
  20. data/lib/openc3/io/json_api.rb +72 -0
  21. data/lib/openc3/io/serial_driver.rb +4 -5
  22. data/lib/openc3/logs/buffered_packet_log_writer.rb +2 -4
  23. data/lib/openc3/logs/log_writer.rb +9 -8
  24. data/lib/openc3/logs/packet_log_reader.rb +8 -1
  25. data/lib/openc3/logs/packet_log_writer.rb +3 -4
  26. data/lib/openc3/logs/stream_log.rb +116 -0
  27. data/lib/openc3/logs/stream_log_pair.rb +70 -0
  28. data/lib/openc3/microservices/cleanup_microservice.rb +1 -1
  29. data/lib/openc3/microservices/decom_microservice.rb +17 -2
  30. data/lib/openc3/microservices/interface_decom_common.rb +42 -0
  31. data/lib/openc3/microservices/interface_microservice.rb +24 -17
  32. data/lib/openc3/microservices/router_microservice.rb +46 -4
  33. data/lib/openc3/migrations/20221202214600_add_target_names.rb +1 -1
  34. data/lib/openc3/migrations/20230319154100_log_stream.rb +40 -0
  35. data/lib/openc3/migrations/20230413101100_remove_log.rb +30 -0
  36. data/lib/openc3/models/gem_model.rb +2 -2
  37. data/lib/openc3/models/interface_model.rb +13 -14
  38. data/lib/openc3/models/metadata_model.rb +1 -1
  39. data/lib/openc3/models/note_model.rb +1 -1
  40. data/lib/openc3/models/plugin_model.rb +3 -2
  41. data/lib/openc3/operators/operator.rb +2 -0
  42. data/lib/openc3/packets/commands.rb +2 -0
  43. data/lib/openc3/packets/packet_config.rb +3 -2
  44. data/lib/openc3/packets/parsers/xtce_converter.rb +2 -1
  45. data/lib/openc3/script/gems.rb +125 -0
  46. data/lib/openc3/script/plugins.rb +186 -0
  47. data/lib/openc3/script/screen.rb +119 -0
  48. data/lib/openc3/script/script.rb +3 -0
  49. data/lib/openc3/script/script_runner.rb +19 -8
  50. data/lib/openc3/script/suite_results.rb +2 -2
  51. data/lib/openc3/script/web_socket_api.rb +5 -1
  52. data/lib/openc3/streams/serial_stream.rb +14 -11
  53. data/lib/openc3/streams/tcpip_client_stream.rb +5 -2
  54. data/lib/openc3/streams/tcpip_socket_stream.rb +37 -71
  55. data/lib/openc3/streams/web_socket_client_stream.rb +5 -3
  56. data/lib/openc3/system/system.rb +2 -0
  57. data/lib/openc3/topics/interface_topic.rb +13 -4
  58. data/lib/openc3/topics/router_topic.rb +6 -6
  59. data/lib/openc3/topics/telemetry_decom_topic.rb +10 -1
  60. data/lib/openc3/utilities/bucket_utilities.rb +12 -5
  61. data/lib/openc3/utilities/cli_generator.rb +56 -4
  62. data/lib/openc3/utilities/crc.rb +42 -7
  63. data/lib/openc3/utilities/process_manager.rb +3 -1
  64. data/lib/openc3/utilities/ruby_lex_utils.rb +265 -504
  65. data/lib/openc3/version.rb +6 -6
  66. data/templates/conversion/conversion.rb +10 -2
  67. data/templates/microservice/microservices/TEMPLATE/microservice.rb +1 -1
  68. data/templates/plugin/Rakefile +8 -1
  69. data/templates/widget/.browserslistrc +16 -0
  70. data/templates/widget/.eslintrc.js +43 -0
  71. data/templates/widget/.nycrc +3 -0
  72. data/templates/widget/.prettierrc.js +5 -0
  73. data/templates/widget/LICENSE.txt +20 -0
  74. data/templates/widget/Rakefile +24 -0
  75. data/templates/widget/babel.config.json +11 -0
  76. data/templates/widget/package.json +35 -0
  77. data/templates/widget/src/Widget.vue +46 -0
  78. data/templates/widget/vue.config.js +25 -0
  79. data/templates/widget/yarn.lock +8938 -0
  80. metadata +23 -4
  81. data/lib/openc3/io/raw_logger.rb +0 -170
  82. data/lib/openc3/io/raw_logger_pair.rb +0 -80
@@ -28,7 +28,7 @@ require 'rubygems'
28
28
  require 'rubygems/uninstaller'
29
29
  require 'tempfile'
30
30
  require 'openc3/utilities/process_manager'
31
- require "pathname"
31
+ require 'pathname'
32
32
 
33
33
  module OpenC3
34
34
  # This class acts like a Model but doesn't inherit from Model because it doesn't
@@ -55,7 +55,7 @@ module OpenC3
55
55
  if gem_install
56
56
  Logger.info "Installing gem: #{gem_filename}"
57
57
  result = OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "geminstall", gem_filename, scope], "gem_install", gem_filename, Time.now + 3600.0, scope: scope)
58
- return result
58
+ return result.name
59
59
  end
60
60
  else
61
61
  message = "Gem file #{gem_file_path} does not exist!"
@@ -14,7 +14,7 @@
14
14
  # GNU Affero General Public License for more details.
15
15
 
16
16
  # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
17
+ # All changes Copyright 2023, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -41,8 +41,7 @@ module OpenC3
41
41
  attr_accessor :secret_options
42
42
  attr_accessor :protocols
43
43
  attr_accessor :interfaces
44
- attr_accessor :log
45
- attr_accessor :log_raw
44
+ attr_accessor :log_stream
46
45
  attr_accessor :needs_dependencies
47
46
  attr_accessor :secrets
48
47
 
@@ -105,8 +104,7 @@ module OpenC3
105
104
  options: [],
106
105
  secret_options: [],
107
106
  protocols: [],
108
- log: true,
109
- log_raw: false,
107
+ log_stream: nil,
110
108
  updated_at: nil,
111
109
  plugin: nil,
112
110
  needs_dependencies: false,
@@ -129,8 +127,7 @@ module OpenC3
129
127
  @options = options
130
128
  @secret_options = secret_options
131
129
  @protocols = protocols
132
- @log = log
133
- @log_raw = log_raw
130
+ @log_stream = log_stream
134
131
  @needs_dependencies = needs_dependencies
135
132
  @secrets = secrets
136
133
  end
@@ -165,6 +162,10 @@ module OpenC3
165
162
  klass = OpenC3.require_class(protocol[1])
166
163
  interface_or_router.add_protocol(klass, protocol[2..-1], protocol[0].upcase.intern)
167
164
  end
165
+ if @log_stream
166
+ interface_or_router.stream_log_pair = StreamLogPair.new(interface_or_router.name, @log_stream)
167
+ interface_or_router.start_raw_logging
168
+ end
168
169
  interface_or_router
169
170
  end
170
171
 
@@ -182,8 +183,7 @@ module OpenC3
182
183
  'options' => @options,
183
184
  'secret_options' => @secret_options,
184
185
  'protocols' => @protocols,
185
- 'log' => @log,
186
- 'log_raw' => @log_raw,
186
+ 'log_stream' => @log_stream,
187
187
  'plugin' => @plugin,
188
188
  'needs_dependencies' => @needs_dependencies,
189
189
  'secrets' => @secrets.as_json(*a),
@@ -249,12 +249,11 @@ module OpenC3
249
249
  @protocols << parameters.dup
250
250
 
251
251
  when 'DONT_LOG'
252
- parser.verify_num_parameters(0, 0, "#{keyword}")
253
- @log = false
252
+ Logger.warn "DONT_LOG is deprecated and does nothing."
254
253
 
255
- when 'LOG_RAW'
256
- parser.verify_num_parameters(0, 0, "#{keyword}")
257
- @log_raw = true
254
+ when 'LOG_STREAM', 'LOG_RAW'
255
+ parser.verify_num_parameters(0, nil, "#{keyword} <Log Stream Class File (optional)> <Log Stream Parameters (optional)>")
256
+ @log_stream = parameters.dup # Even if it is empty we copy it to set it as not nil
258
257
 
259
258
  when 'SECRET'
260
259
  parser.verify_num_parameters(3, 5, "#{keyword} <Secret Type: ENV or FILE> <Secret Name> <Environment Variable Name or File Path> <Option Name (Optional)> <Secret Store Name (Optional)>")
@@ -69,7 +69,7 @@ module OpenC3
69
69
  if @color.nil?
70
70
  @color = '#%06x' % (rand * 0xffffff)
71
71
  end
72
- unless @color =~ /(#*)([0-9a-fA-F]{6})/
72
+ unless @color =~ /#?([0-9a-fA-F]{6})/
73
73
  raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
74
74
  end
75
75
  @color = "##{@color}" unless @color.start_with?('#')
@@ -78,7 +78,7 @@ module OpenC3
78
78
  if @color.nil?
79
79
  @color = '#%06x' % (rand * 0xffffff)
80
80
  end
81
- unless @color =~ /(#*)([0-9a-fA-F]{6})/
81
+ unless @color =~ /#?([0-9a-fA-F]{6})/
82
82
  raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
83
83
  end
84
84
  @color = "##{@color}" unless @color.start_with?('#')
@@ -36,6 +36,7 @@ require 'openc3/models/widget_model'
36
36
  require 'openc3/models/microservice_model'
37
37
  require 'tmpdir'
38
38
  require 'tempfile'
39
+ require 'fileutils'
39
40
 
40
41
  module OpenC3
41
42
  # Represents a OpenC3 plugin that can consist of targets, interfaces, routers
@@ -155,7 +156,7 @@ module OpenC3
155
156
  end
156
157
 
157
158
  # Actually install the gem now (slow)
158
- OpenC3::GemModel.install(gem_file_path, scope: scope)
159
+ OpenC3::GemModel.install(gem_file_path, scope: scope) unless validate_only
159
160
 
160
161
  # Extract gem contents
161
162
  gem_path = File.join(temp_dir, "gem")
@@ -284,7 +285,7 @@ module OpenC3
284
285
  microservice_count += 1
285
286
  end
286
287
  # Wait for the operator to wake up and remove the microservice processes
287
- sleep 12 if microservice_count > 0 # Cycle time 5s times 2 plus 2s wait for soft stop and then hard stop
288
+ sleep 15 if microservice_count > 0 # Cycle time 5s times 2 plus 5s wait for soft stop and then hard stop
288
289
  # Remove all the other models now that the processes have stopped
289
290
  # Save TargetModel for last as it has the most to cleanup
290
291
  [InterfaceModel, RouterModel, ToolModel, WidgetModel, TargetModel].each do |model|
@@ -83,6 +83,7 @@ module OpenC3
83
83
  attr_accessor :new_temp_dir
84
84
  attr_reader :temp_dir
85
85
  attr_reader :scope
86
+ attr_reader :name
86
87
 
87
88
  def self.setup
88
89
  # Perform any setup steps necessary
@@ -139,6 +140,7 @@ module OpenC3
139
140
  @process.io.stdout = OperatorProcessIO.new('microservice-stdout')
140
141
  @process.io.stderr = OperatorProcessIO.new('microservice-stderr')
141
142
  @process.start
143
+ @name = "#{Socket.gethostname}__#{@process.pid}"
142
144
  end
143
145
 
144
146
  def alive?
@@ -205,6 +205,8 @@ module OpenC3
205
205
  else
206
206
  output_string = 'cmd("'
207
207
  end
208
+ target_name = 'UNKNOWN' unless target_name
209
+ cmd_name = 'UNKNOWN' unless cmd_name
208
210
  output_string << target_name + ' ' + cmd_name
209
211
  if cmd_params.nil? or cmd_params.empty?
210
212
  output_string << '")'
@@ -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 'openc3/config/config_parser'
@@ -35,6 +35,7 @@ require 'openc3/conversions'
35
35
  require 'openc3/processors'
36
36
  require 'nokogiri'
37
37
  require 'ostruct'
38
+ require 'fileutils'
38
39
 
39
40
  module OpenC3
40
41
  # Reads a command or telemetry configuration file and builds a hash of packets.
@@ -523,7 +524,7 @@ module OpenC3
523
524
  @converted_bit_size = nil
524
525
  if params[0]
525
526
  @converted_type = params[0].upcase.intern
526
- raise parser.error("Invalid converted_type: #{@converted_type}.") unless [:INT, :UINT, :FLOAT, :STRING, :BLOCK].include? @converted_type
527
+ raise parser.error("Invalid converted_type: #{@converted_type}.") unless [:INT, :UINT, :FLOAT, :STRING, :BLOCK, :RUBY_TIME].include? @converted_type
527
528
  end
528
529
  @converted_bit_size = Integer(params[1]) if params[1]
529
530
  if @converted_type.nil? or @converted_bit_size.nil?
@@ -17,11 +17,12 @@
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 'nokogiri'
24
24
  require 'openc3/packets/parsers/xtce_parser'
25
+ require 'fileutils'
25
26
 
26
27
  module OpenC3
27
28
  class XtceConverter
@@ -0,0 +1,125 @@
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/script/plugins'
20
+
21
+ module OpenC3
22
+ module Script
23
+ private
24
+
25
+ def gem_list(scope: $openc3_scope)
26
+ response_body = nil
27
+ begin
28
+ endpoint = "/openc3-api/gems?scope=#{scope}"
29
+ uri = URI.parse($api_server.generate_url + endpoint)
30
+ auth = $api_server.generate_auth
31
+
32
+ request = Net::HTTP::Get.new(uri)
33
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
34
+ request['Content-Type'] = 'application/json'
35
+ request['Authorization'] = auth.token
36
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
37
+ http.request(request) do |response|
38
+ response_body = response.body
39
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
40
+ return JSON.parse(response.body, allow_nan: true, create_additions: true)
41
+ end
42
+ end
43
+ rescue => error
44
+ raise "gem_list failed due to #{error.formatted}\nResponse:\n#{response_body}"
45
+ end
46
+ end
47
+
48
+ def gem_install(file_path, scope: $openc3_scope)
49
+ response_body = nil
50
+ begin
51
+ endpoint = "/openc3-api/gems?scope=#{scope}"
52
+ uri = URI.parse($api_server.generate_url + endpoint)
53
+ auth = $api_server.generate_auth
54
+
55
+ File.open(file_path, 'rb') do |file|
56
+ request = Net::HTTP::Post.new(uri)
57
+ form_data = [["gem", file]]
58
+ request.set_form(form_data, "multipart/form-data")
59
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
60
+ request['Authorization'] = auth.token
61
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
62
+ http.request(request) do |response|
63
+ response_body = response.body
64
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
65
+ return response_body.remove_quotes
66
+ end
67
+ end
68
+ end
69
+ rescue => error
70
+ raise "gem_install failed due to #{error.formatted}\nResponse:\n#{response_body}"
71
+ end
72
+ end
73
+
74
+ def gem_uninstall(gem_name, scope: $openc3_scope)
75
+ response_body = nil
76
+ begin
77
+ endpoint = "/openc3-api/gems/#{gem_name}?scope=#{scope}"
78
+ uri = URI.parse($api_server.generate_url + endpoint)
79
+ auth = $api_server.generate_auth
80
+ request = Net::HTTP::Delete.new(uri)
81
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
82
+ request['Authorization'] = auth.token
83
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
84
+ http.request(request) do |response|
85
+ response_body = response.body
86
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
87
+ return true
88
+ end
89
+ end
90
+ rescue => error
91
+ raise "gem_uninstall failed due to #{error.formatted}\nResponse:\n#{response_body}"
92
+ end
93
+ end
94
+
95
+ def gem_status(process_name, scope: $openc3_scope)
96
+ return plugin_status(process_name, scope: scope)
97
+ end
98
+
99
+ def gem_download(gem_name, local_file_path, scope: $openc3_scope)
100
+ response_body = nil
101
+ begin
102
+ endpoint = "/openc3-api/gems/#{gem_name}/download?scope=#{scope}"
103
+ uri = URI.parse($api_server.generate_url + endpoint)
104
+ auth = $api_server.generate_auth
105
+ request = Net::HTTP::Post.new(uri)
106
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
107
+ request['Authorization'] = auth.token
108
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
109
+ http.request(request) do |response|
110
+ response_body = response.body
111
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
112
+ parsed = JSON.parse(response.body, allow_nan: true, create_additions: true)
113
+ File.open(local_file_path, 'wb') do |file|
114
+ file.write(Base64.decode64(parsed['contents']))
115
+ end
116
+ return local_file_path
117
+ end
118
+ end
119
+ rescue => error
120
+ raise "gem_uninstall failed due to #{error.formatted}\nResponse:\n#{response_body}"
121
+ end
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,186 @@
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
+ module OpenC3
20
+ module Script
21
+ private
22
+
23
+ def plugin_list(scope: $openc3_scope)
24
+ response_body = nil
25
+ begin
26
+ endpoint = "/openc3-api/plugins?scope=#{scope}"
27
+ uri = URI.parse($api_server.generate_url + endpoint)
28
+ auth = $api_server.generate_auth
29
+
30
+ request = Net::HTTP::Get.new(uri)
31
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
32
+ request['Content-Type'] = 'application/json'
33
+ request['Authorization'] = auth.token
34
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
35
+ http.request(request) do |response|
36
+ response_body = response.body
37
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
38
+ return JSON.parse(response.body, allow_nan: true, create_additions: true)
39
+ end
40
+ end
41
+ rescue => error
42
+ raise "get_plugin_list failed due to #{error.formatted}\nResponse:\n#{response_body}"
43
+ end
44
+ end
45
+
46
+ def plugin_get(plugin_name, scope: $openc3_scope)
47
+ response_body = nil
48
+ begin
49
+ endpoint = "/openc3-api/plugins/#{plugin_name}?scope=#{scope}"
50
+ uri = URI.parse($api_server.generate_url + endpoint)
51
+ auth = $api_server.generate_auth
52
+
53
+ request = Net::HTTP::Get.new(uri)
54
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
55
+ request['Content-Type'] = 'application/json'
56
+ request['Authorization'] = auth.token
57
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
58
+ http.request(request) do |response|
59
+ response_body = response.body
60
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
61
+ return JSON.parse(response.body, allow_nan: true, create_additions: true)
62
+ end
63
+ end
64
+ rescue => error
65
+ raise "get_plugin failed due to #{error.formatted}\nResponse:\n#{response_body}"
66
+ end
67
+ end
68
+
69
+ def plugin_install_phase1(file_path, update: false, existing_plugin_name: nil, scope: $openc3_scope)
70
+ response_body = nil
71
+ begin
72
+ if update
73
+ endpoint = "/openc3-api/plugins/#{existing_plugin_name}?scope=#{scope}"
74
+ else
75
+ endpoint = "/openc3-api/plugins?scope=#{scope}"
76
+ end
77
+ uri = URI.parse($api_server.generate_url + endpoint)
78
+ auth = $api_server.generate_auth
79
+
80
+ File.open(file_path, 'rb') do |file|
81
+ if update
82
+ request = Net::HTTP::Put.new(uri)
83
+ else
84
+ request = Net::HTTP::Post.new(uri)
85
+ end
86
+ form_data = [["plugin", file]]
87
+ request.set_form(form_data, "multipart/form-data")
88
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
89
+ request['Authorization'] = auth.token
90
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
91
+ http.request(request) do |response|
92
+ response_body = response.body
93
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
94
+ return JSON.parse(response.body, allow_nan: true, create_additions: true)
95
+ end
96
+ end
97
+ end
98
+ rescue => error
99
+ raise "plugin_install_phase1 failed due to #{error.formatted}\nResponse:\n#{response_body}"
100
+ end
101
+ end
102
+
103
+ def plugin_install_phase2(plugin_hash, update: false, scope: $openc3_scope)
104
+ response_body = nil
105
+ begin
106
+ plugin_name = plugin_hash['name']
107
+ if update
108
+ endpoint = "/openc3-api/plugins/#{plugin_name}?scope=#{scope}"
109
+ else
110
+ endpoint = "/openc3-api/plugins/install/#{plugin_name}?scope=#{scope}"
111
+ end
112
+ uri = URI.parse($api_server.generate_url + endpoint)
113
+ auth = $api_server.generate_auth
114
+
115
+ if update
116
+ request = Net::HTTP::Put.new(uri)
117
+ else
118
+ request = Net::HTTP::Post.new(uri)
119
+ end
120
+ form_data = [["plugin_hash", JSON.generate(plugin_hash, allow_nan: true)]]
121
+ request.set_form(form_data)
122
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
123
+ request['Content-Type'] = 'application/json'
124
+ request['Authorization'] = auth.token
125
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
126
+ http.request(request) do |response|
127
+ response_body = response.body
128
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
129
+ return response_body.remove_quotes
130
+ end
131
+ end
132
+ rescue => error
133
+ raise "plugin_install_phase2 failed due to #{error.formatted}\nResponse:\n#{response_body}"
134
+ end
135
+ end
136
+
137
+ def plugin_update_phase1(file_path, existing_plugin_name, scope: $openc3_scope)
138
+ return plugin_install_phase1(file_path, existing_plugin_name: existing_plugin_name, update: true, scope: scope)
139
+ end
140
+
141
+ def plugin_uninstall(plugin_name, scope: $openc3_scope)
142
+ response_body = nil
143
+ begin
144
+ endpoint = "/openc3-api/plugins/#{plugin_name}?scope=#{scope}"
145
+ uri = URI.parse($api_server.generate_url + endpoint)
146
+ auth = $api_server.generate_auth
147
+ request = Net::HTTP::Delete.new(uri)
148
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
149
+ request['Authorization'] = auth.token
150
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
151
+ http.request(request) do |response|
152
+ response_body = response.body
153
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
154
+ return response_body.remove_quotes
155
+ end
156
+ end
157
+ rescue => error
158
+ raise "plugin_uninstall failed due to #{error.formatted}\nResponse:\n#{response_body}"
159
+ end
160
+ end
161
+
162
+ def plugin_status(process_name, scope: $openc3_scope)
163
+ response_body = nil
164
+ begin
165
+ endpoint = "/openc3-api/process_status/#{process_name}?scope=#{scope}"
166
+ uri = URI.parse($api_server.generate_url + endpoint)
167
+ auth = $api_server.generate_auth
168
+
169
+ request = Net::HTTP::Get.new(uri)
170
+ request['User-Agent'] = JsonDRbObject::USER_AGENT
171
+ request['Content-Type'] = 'application/json'
172
+ request['Authorization'] = auth.token
173
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
174
+ http.request(request) do |response|
175
+ response_body = response.body
176
+ response.value() # Raises an HTTP error if the response is not 2xx (success)
177
+ return JSON.parse(response.body, allow_nan: true, create_additions: true)
178
+ end
179
+ end
180
+ rescue => error
181
+ raise "plugin_status failed due to #{error.formatted}\nResponse:\n#{response_body}"
182
+ end
183
+ end
184
+
185
+ end
186
+ end
@@ -0,0 +1,119 @@
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
+ module OpenC3
20
+ module Script
21
+ private
22
+
23
+ def get_screen_list(scope: $openc3_scope)
24
+ begin
25
+ endpoint = "/openc3-api/screens"
26
+ # Pass the name of the ENV variable name where we pull the actual bucket name
27
+ response = $api_server.request('get', endpoint, scope: scope)
28
+ if response.nil? || response.code != 200
29
+ raise "Unexpected response to get_screen_list: #{response.inspect}"
30
+ end
31
+ screen_list = {}
32
+ filenames = JSON.parse(response.body)
33
+ filenames.each do |filename|
34
+ # TARGET/screens/filename.txt
35
+ split_filename = filename.split('/')
36
+ target_name = split_filename[0]
37
+ screen_name = File.basename(filename, '.txt').to_s.upcase
38
+ screen_list[target_name] ||= []
39
+ screen_list[target_name] << screen_name
40
+ end
41
+ return screen_list
42
+ rescue => error
43
+ raise "get_screen_list failed due to #{error.formatted}"
44
+ end
45
+ end
46
+
47
+ def get_screen_definition(target_name, screen_name, scope: $openc3_scope)
48
+ begin
49
+ endpoint = "/openc3-api/screen/#{target_name.upcase}/#{screen_name.upcase}"
50
+ response = $api_server.request('get', endpoint, headers: {
51
+ Accept: 'text/plain',
52
+ }, scope: scope)
53
+ if response.nil? || response.code != 200
54
+ raise "Screen definition not found: #{target_name} #{screen_name}"
55
+ end
56
+ return response.body
57
+ rescue => error
58
+ raise "get_screen_definition failed due to #{error.formatted}"
59
+ end
60
+ end
61
+
62
+ def create_screen(target_name, screen_name, definition, scope: $openc3_scope)
63
+ begin
64
+ endpoint = "/openc3-api/screen"
65
+ data = {
66
+ "target" => target_name,
67
+ "screen" => screen_name,
68
+ "text" => definition
69
+ }
70
+ response = $api_server.request('post', endpoint, :data => data, scope: scope)
71
+ if response.nil? || response.code != 200
72
+ if response
73
+ parsed = JSON.parse(response)
74
+ raise "create_screen error: #{parsed['error']}"
75
+ else
76
+ raise "create_screen failed"
77
+ end
78
+ end
79
+ return response.body
80
+ rescue => error
81
+ raise "create_screen failed due to #{error.formatted}"
82
+ end
83
+ end
84
+
85
+ def delete_screen(target_name, screen_name, scope: $openc3_scope)
86
+ begin
87
+ endpoint = "/openc3-api/screen/#{target_name.upcase}/#{screen_name.upcase}"
88
+ response = $api_server.request('delete', endpoint, scope: scope)
89
+ if response.nil? || response.code != 200
90
+ if response
91
+ parsed = JSON.parse(response)
92
+ raise "delete_screen error: #{parsed['error']}"
93
+ else
94
+ raise "delete_screen failed"
95
+ end
96
+ end
97
+ return response.body
98
+ rescue => error
99
+ raise "delete_screen failed due to #{error.formatted}"
100
+ end
101
+ end
102
+
103
+ def display_screen(target_name, screen_name, x = nil, y = nil, scope: $openc3_scope)
104
+ # Noop outside of ScriptRunner
105
+ end
106
+
107
+ def clear_screen(target_name, screen_name)
108
+ # Noop outside of ScriptRunner
109
+ end
110
+
111
+ def clear_all_screens
112
+ # Noop outside of ScriptRunner
113
+ end
114
+
115
+ def local_screen(screen_name, definition, x = nil, y = nil)
116
+ # Noop outside of ScriptRunner
117
+ end
118
+ end
119
+ end
@@ -29,9 +29,12 @@ require 'openc3/script/commands'
29
29
  require 'openc3/script/telemetry'
30
30
  require 'openc3/script/limits'
31
31
  require 'openc3/script/exceptions'
32
+ require 'openc3/script/screen'
32
33
  require 'openc3/script/script_runner'
33
34
  require 'openc3/script/storage'
34
35
  require 'openc3/script/web_socket_api'
36
+ require 'openc3/script/gems'
37
+ require 'openc3/script/plugins'
35
38
  require 'openc3/utilities/authentication'
36
39
 
37
40
  $api_server = nil