openc3 5.5.2 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/openc3cli +167 -69
- data/data/config/_interfaces.yaml +1 -6
- data/data/config/interface_modifiers.yaml +55 -4
- data/data/config/microservice.yaml +30 -3
- data/ext/openc3/ext/crc/crc.c +82 -1
- data/lib/openc3/api/cmd_api.rb +19 -7
- data/lib/openc3/api/tlm_api.rb +13 -12
- data/lib/openc3/bridge/bridge_config.rb +4 -4
- data/lib/openc3/config/config_parser.rb +1 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +3 -1
- data/lib/openc3/ext/.keep +0 -0
- data/lib/openc3/interfaces/interface.rb +54 -26
- data/lib/openc3/interfaces/serial_interface.rb +4 -5
- data/lib/openc3/interfaces/simulated_target_interface.rb +4 -4
- data/lib/openc3/interfaces/stream_interface.rb +2 -2
- data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -3
- data/lib/openc3/interfaces/tcpip_server_interface.rb +18 -19
- data/lib/openc3/interfaces/udp_interface.rb +10 -4
- data/lib/openc3/io/json_api.rb +72 -0
- data/lib/openc3/io/serial_driver.rb +4 -5
- data/lib/openc3/logs/buffered_packet_log_writer.rb +2 -4
- data/lib/openc3/logs/log_writer.rb +9 -8
- data/lib/openc3/logs/packet_log_reader.rb +8 -1
- data/lib/openc3/logs/packet_log_writer.rb +3 -4
- data/lib/openc3/logs/stream_log.rb +116 -0
- data/lib/openc3/logs/stream_log_pair.rb +70 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +1 -1
- data/lib/openc3/microservices/decom_microservice.rb +17 -2
- data/lib/openc3/microservices/interface_decom_common.rb +42 -0
- data/lib/openc3/microservices/interface_microservice.rb +24 -17
- data/lib/openc3/microservices/router_microservice.rb +46 -4
- data/lib/openc3/migrations/20221202214600_add_target_names.rb +1 -1
- data/lib/openc3/migrations/20230319154100_log_stream.rb +40 -0
- data/lib/openc3/migrations/20230413101100_remove_log.rb +30 -0
- data/lib/openc3/models/gem_model.rb +2 -2
- data/lib/openc3/models/interface_model.rb +13 -14
- data/lib/openc3/models/metadata_model.rb +1 -1
- data/lib/openc3/models/note_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +3 -2
- data/lib/openc3/operators/operator.rb +2 -0
- data/lib/openc3/packets/commands.rb +2 -0
- data/lib/openc3/packets/packet_config.rb +3 -2
- data/lib/openc3/packets/parsers/xtce_converter.rb +2 -1
- data/lib/openc3/script/gems.rb +125 -0
- data/lib/openc3/script/plugins.rb +186 -0
- data/lib/openc3/script/screen.rb +119 -0
- data/lib/openc3/script/script.rb +3 -0
- data/lib/openc3/script/script_runner.rb +19 -8
- data/lib/openc3/script/suite_results.rb +2 -2
- data/lib/openc3/script/web_socket_api.rb +5 -1
- data/lib/openc3/streams/serial_stream.rb +14 -11
- data/lib/openc3/streams/tcpip_client_stream.rb +5 -2
- data/lib/openc3/streams/tcpip_socket_stream.rb +37 -71
- data/lib/openc3/streams/web_socket_client_stream.rb +5 -3
- data/lib/openc3/system/system.rb +2 -0
- data/lib/openc3/topics/interface_topic.rb +13 -4
- data/lib/openc3/topics/router_topic.rb +6 -6
- data/lib/openc3/topics/telemetry_decom_topic.rb +10 -1
- data/lib/openc3/utilities/bucket_utilities.rb +12 -5
- data/lib/openc3/utilities/cli_generator.rb +56 -4
- data/lib/openc3/utilities/crc.rb +42 -7
- data/lib/openc3/utilities/process_manager.rb +3 -1
- data/lib/openc3/utilities/ruby_lex_utils.rb +265 -504
- data/lib/openc3/version.rb +6 -6
- data/templates/conversion/conversion.rb +10 -2
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +1 -1
- data/templates/plugin/Rakefile +8 -1
- data/templates/widget/.browserslistrc +16 -0
- data/templates/widget/.eslintrc.js +43 -0
- data/templates/widget/.nycrc +3 -0
- data/templates/widget/.prettierrc.js +5 -0
- data/templates/widget/LICENSE.txt +20 -0
- data/templates/widget/Rakefile +24 -0
- data/templates/widget/babel.config.json +11 -0
- data/templates/widget/package.json +35 -0
- data/templates/widget/src/Widget.vue +46 -0
- data/templates/widget/vue.config.js +25 -0
- data/templates/widget/yarn.lock +8938 -0
- metadata +23 -4
- data/lib/openc3/io/raw_logger.rb +0 -170
- 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
|
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
|
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 :
|
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
|
-
|
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
|
-
@
|
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
|
-
'
|
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
|
-
|
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,
|
257
|
-
@
|
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 =~
|
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 =~
|
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
|
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
|
data/lib/openc3/script/script.rb
CHANGED
@@ -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
|