openc3 5.5.0.pre.beta0 → 5.5.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 +58 -74
- data/data/config/item_modifiers.yaml +1 -1
- data/data/config/plugins.yaml +5 -0
- data/data/config/widgets.yaml +13 -11
- data/lib/openc3/api/cmd_api.rb +43 -17
- data/lib/openc3/api/tlm_api.rb +37 -4
- data/lib/openc3/bridge/bridge.rb +3 -3
- data/lib/openc3/bridge/bridge_config.rb +68 -20
- data/lib/openc3/interfaces/interface.rb +8 -0
- data/lib/openc3/microservices/decom_microservice.rb +0 -3
- data/lib/openc3/microservices/interface_microservice.rb +2 -0
- data/lib/openc3/microservices/reaction_microservice.rb +0 -1
- data/lib/openc3/models/cvt_model.rb +1 -2
- data/lib/openc3/models/metadata_model.rb +1 -1
- data/lib/openc3/models/microservice_model.rb +1 -1
- data/lib/openc3/models/note_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +14 -7
- data/lib/openc3/models/timeline_model.rb +1 -1
- data/lib/openc3/models/trigger_group_model.rb +1 -1
- data/lib/openc3/packets/packet_item.rb +1 -1
- data/lib/openc3/script/storage.rb +5 -5
- data/lib/openc3/streams/web_socket_client_stream.rb +0 -1
- data/lib/openc3/tools/table_manager/table_manager_core.rb +1 -2
- data/lib/openc3/utilities/aws_bucket.rb +22 -4
- data/lib/openc3/utilities/bucket_file_cache.rb +3 -2
- data/lib/openc3/utilities/bucket_utilities.rb +1 -1
- data/lib/openc3/utilities/cli_generator.rb +210 -0
- data/lib/openc3/utilities/local_mode.rb +2 -2
- data/lib/openc3/utilities/target_file.rb +43 -32
- data/lib/openc3/version.rb +5 -5
- data/templates/conversion/conversion.rb +43 -0
- data/templates/limits_response/response.rb +51 -0
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +62 -0
- data/templates/plugin/plugin.txt +1 -0
- metadata +19 -15
- data/templates/plugin-template/plugin.txt +0 -9
- /data/templates/{plugin-template → plugin}/LICENSE.txt +0 -0
- /data/templates/{plugin-template → plugin}/README.md +0 -0
- /data/templates/{plugin-template → plugin}/Rakefile +0 -0
- /data/templates/{plugin-template → plugin}/plugin.gemspec +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/cmd_tlm/cmd.txt +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/cmd_tlm/tlm.txt +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/lib/target.rb +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/procedures/procedure.rb +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/screens/status.txt +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/target.txt +0 -0
@@ -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/utilities/logger'
|
@@ -30,28 +30,55 @@ module OpenC3
|
|
30
30
|
# @return [Hash<String, Interface>] Routers hash
|
31
31
|
attr_accessor :routers
|
32
32
|
|
33
|
-
def initialize(filename)
|
33
|
+
def initialize(filename, existing_variables = {})
|
34
34
|
@interfaces = {}
|
35
35
|
@routers = {}
|
36
|
-
process_file(filename)
|
36
|
+
process_file(filename, existing_variables)
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.generate_default(filename)
|
40
40
|
default_config = <<~EOF
|
41
|
-
|
42
|
-
|
43
|
-
# INTERFACE <Interface Name> <Interface File> <Interface Params...>
|
44
|
-
# INTERFACE <Interface Name> serial_interface.rb <Write Port> <Read Port> <Baud Rate> <Parity ODD/EVEN/NONE> <Stop Bits> <Write Timeout> <Read Timeout> <Protocol Name> <Protocol Params>
|
45
|
-
# INTERFACE <Interface Name> serial_interface.rb <Write Port> <Read Port> <Baud Rate> <Parity ODD/EVEN/NONE> <Stop Bits> <Write Timeout> <Read Timeout> BURST <Discard Leading Bytes> <Sync Pattern> <Add Sync On Write>
|
46
|
-
# INTERFACE SERIAL_INT serial_interface.rb /dev/ttyS1 /dev/ttyS1 38400 ODD 1 10.0 nil BURST 4 0xDEADBEEF
|
47
|
-
INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 9600 NONE 1 10.0 nil BURST
|
41
|
+
# Write serial port name
|
42
|
+
VARIABLE write_port_name COM1
|
48
43
|
#{' '}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
# Read serial port name
|
45
|
+
VARIABLE read_port_name COM1
|
46
|
+
#{' '}
|
47
|
+
# Baud Rate
|
48
|
+
VARIABLE baud_rate 115200
|
49
|
+
#{' '}
|
50
|
+
# Parity - NONE, ODD, or EVEN
|
51
|
+
VARIABLE parity NONE
|
52
|
+
#{' '}
|
53
|
+
# Stop bits - 0, 1, or 2
|
54
|
+
VARIABLE stop_bits 1
|
55
|
+
#{' '}
|
56
|
+
# Write Timeout
|
57
|
+
VARIABLE write_timeout 10.0
|
58
|
+
#{' '}
|
59
|
+
# Read Timeout
|
60
|
+
VARIABLE read_timeout nil
|
61
|
+
#{' '}
|
62
|
+
# Flow Control - NONE, or RTSCTS
|
63
|
+
VARIABLE flow_control NONE
|
64
|
+
#{' '}
|
65
|
+
# Data bits per word - Typically 8
|
66
|
+
VARIABLE data_bits 8
|
67
|
+
#{' '}
|
68
|
+
# Port to listen for connections from COSMOS - Plugin must match
|
69
|
+
VARIABLE router_port 2950
|
70
|
+
#{' '}
|
71
|
+
# Port to listen on for connections from COSMOS. Defaults to localhost for security. Will need to be opened
|
72
|
+
# if COSMOS is on another machine.
|
73
|
+
VARIABLE router_listen_address 127.0.0.1
|
74
|
+
#{' '}
|
75
|
+
INTERFACE SERIAL_INT serial_interface.rb <%= write_port_name %> <%= read_port_name %> <%= baud_rate %> <%= parity %> <%= stop_bits %> <%= write_timeout %> <%= read_timeout %>
|
76
|
+
OPTION FLOW_CONTROL <%= flow_control %>
|
77
|
+
OPTION DATA_BITS <%= data_bits %>
|
78
|
+
#{' '}
|
79
|
+
ROUTER SERIAL_ROUTER tcpip_server_interface.rb <%= router_port %> <%= router_port %> 10.0 nil BURST
|
80
|
+
ROUTE SERIAL_INT
|
81
|
+
OPTION LISTEN_ADDRESS <%= router_listen_address %>
|
55
82
|
#{' '}
|
56
83
|
EOF
|
57
84
|
|
@@ -66,18 +93,39 @@ module OpenC3
|
|
66
93
|
# Processes a file and adds in the configuration defined in the file
|
67
94
|
#
|
68
95
|
# @param filename [String] The name of the configuration file to parse
|
69
|
-
|
70
|
-
# recursively
|
71
|
-
def process_file(filename, recursive = false)
|
96
|
+
def process_file(filename, existing_variables = {})
|
72
97
|
current_interface_or_router = nil
|
73
98
|
current_type = nil
|
74
99
|
current_interface_log_added = false
|
75
100
|
|
76
101
|
Logger.info "Processing Bridge configuration in file: #{File.expand_path(filename)}"
|
77
102
|
|
103
|
+
variables = {}
|
78
104
|
parser = ConfigParser.new
|
79
|
-
parser.parse_file(filename
|
105
|
+
parser.parse_file(filename,
|
106
|
+
false,
|
107
|
+
true,
|
108
|
+
false) do |keyword, params|
|
80
109
|
case keyword
|
110
|
+
when 'VARIABLE'
|
111
|
+
usage = "#{keyword} <Variable Name> <Default Value>"
|
112
|
+
parser.verify_num_parameters(2, nil, usage)
|
113
|
+
variable_name = params[0]
|
114
|
+
value = params[1..-1].join(" ")
|
115
|
+
variables[variable_name] = value
|
116
|
+
if existing_variables && existing_variables.key?(variable_name)
|
117
|
+
variables[variable_name] = existing_variables[variable_name]
|
118
|
+
end
|
119
|
+
# Ignore everything else during phase 1
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
parser = ConfigParser.new
|
124
|
+
parser.parse_file(filename, false, true, true, variables) do |keyword, params|
|
125
|
+
case keyword
|
126
|
+
|
127
|
+
when 'VARIABLE'
|
128
|
+
# Ignore during this pass
|
81
129
|
|
82
130
|
when 'INTERFACE'
|
83
131
|
usage = "INTERFACE <Name> <Filename> <Specific Parameters>"
|
@@ -25,6 +25,11 @@ require 'openc3/io/raw_logger_pair'
|
|
25
25
|
require 'openc3/utilities/secrets'
|
26
26
|
|
27
27
|
module OpenC3
|
28
|
+
# Define a class to allow interfaces and protocols to reject commands without
|
29
|
+
# disconnecting the interface
|
30
|
+
class WriteRejectError < StandardError
|
31
|
+
end
|
32
|
+
|
28
33
|
# Defines all the attributes and methods common to all interface classes
|
29
34
|
# used by OpenC3.
|
30
35
|
class Interface
|
@@ -330,6 +335,9 @@ module OpenC3
|
|
330
335
|
else
|
331
336
|
@write_mutex.synchronize { yield }
|
332
337
|
end
|
338
|
+
rescue WriteRejectError => err
|
339
|
+
Logger.error("#{@name}: Write rejected by interface: #{err.message}")
|
340
|
+
raise err
|
333
341
|
rescue Exception => err
|
334
342
|
Logger.error("#{@name}: Error writing to interface")
|
335
343
|
disconnect()
|
@@ -95,7 +95,6 @@ module OpenC3
|
|
95
95
|
# @param log_change [Boolean] Whether to log this limits change event
|
96
96
|
def limits_change_callback(packet, item, old_limits_state, value, log_change)
|
97
97
|
return if @cancel_thread
|
98
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
99
98
|
packet_time = packet.packet_time
|
100
99
|
message = "#{packet.target_name} #{packet.packet_name} #{item.name} = #{value} is #{item.limits.state}"
|
101
100
|
message << " (#{packet.packet_time.sys.formatted})" if packet_time
|
@@ -136,8 +135,6 @@ module OpenC3
|
|
136
135
|
@logger.error e.formatted
|
137
136
|
end
|
138
137
|
end
|
139
|
-
|
140
|
-
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
141
138
|
end
|
142
139
|
end
|
143
140
|
end
|
@@ -264,7 +264,6 @@ module OpenC3
|
|
264
264
|
when 'trigger'
|
265
265
|
process_enabled_trigger(data: data)
|
266
266
|
end
|
267
|
-
current_time = Time.now.to_i
|
268
267
|
rescue StandardError => e
|
269
268
|
@logger.error "ReactionWorker-#{@ident} failed to evaluate kind: #{kind} data: #{data}\n#{e.formatted}"
|
270
269
|
end
|
@@ -240,11 +240,10 @@ module OpenC3
|
|
240
240
|
# return an ordered array of hash with keys
|
241
241
|
def self._parse_item(lookups, overrides, item, scope:)
|
242
242
|
target_name, packet_name, item_name, value_type = item.split('__')
|
243
|
-
raise ArgumentError, "items must be formatted as TGT__PKT__ITEM__TYPE" if target_name.nil? || packet_name.nil? || item_name.nil? || value_type.nil?
|
244
243
|
|
245
244
|
# We build lookup keys by including all the less formatted types to gracefully degrade lookups
|
246
245
|
# This allows the user to specify WITH_UNITS and if there is no conversions it will simply return the RAW value
|
247
|
-
case value_type
|
246
|
+
case value_type
|
248
247
|
when 'RAW'
|
249
248
|
keys = [item_name]
|
250
249
|
when 'CONVERTED'
|
@@ -69,7 +69,7 @@ module OpenC3
|
|
69
69
|
if @color.nil?
|
70
70
|
@color = '#%06x' % (rand * 0xffffff)
|
71
71
|
end
|
72
|
-
unless @color =~ /(#*)([0-
|
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?('#')
|
@@ -163,7 +163,7 @@ module OpenC3
|
|
163
163
|
parser.verify_num_parameters(1, 2, usage)
|
164
164
|
begin
|
165
165
|
@ports << [Integer(parameters[0])]
|
166
|
-
rescue
|
166
|
+
rescue # In case Integer fails
|
167
167
|
raise ConfigParser::Error.new(parser, "Port must be an integer: #{parameters[0]}", usage)
|
168
168
|
end
|
169
169
|
protocol = ConfigParser.handle_nil(parameters[1])
|
@@ -78,7 +78,7 @@ module OpenC3
|
|
78
78
|
if @color.nil?
|
79
79
|
@color = '#%06x' % (rand * 0xffffff)
|
80
80
|
end
|
81
|
-
unless @color =~ /(#*)([0-
|
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?('#')
|
@@ -72,7 +72,7 @@ module OpenC3
|
|
72
72
|
temp_dir = Dir.mktmpdir
|
73
73
|
tf = nil
|
74
74
|
begin
|
75
|
-
if File.
|
75
|
+
if File.exist?(gem_file_path)
|
76
76
|
# Load gem to internal gem server
|
77
77
|
OpenC3::GemModel.put(gem_file_path, gem_install: false, scope: scope) unless validate_only
|
78
78
|
else
|
@@ -122,7 +122,6 @@ module OpenC3
|
|
122
122
|
if existing_variables && existing_variables.key?(variable_name)
|
123
123
|
variables[variable_name] = existing_variables[variable_name]
|
124
124
|
end
|
125
|
-
# Ignore everything else during phase 1
|
126
125
|
end
|
127
126
|
end
|
128
127
|
|
@@ -162,14 +161,21 @@ module OpenC3
|
|
162
161
|
gem_path = File.join(temp_dir, "gem")
|
163
162
|
FileUtils.mkdir_p(gem_path)
|
164
163
|
pkg = Gem::Package.new(gem_file_path)
|
165
|
-
needs_dependencies = pkg.spec.runtime_dependencies.length > 0
|
166
164
|
pkg.extract_files(gem_path)
|
167
165
|
Dir[File.join(gem_path, '**/screens/*.txt')].each do |filename|
|
168
166
|
if File.basename(filename) != File.basename(filename).downcase
|
169
|
-
raise "Invalid screen
|
167
|
+
raise "Invalid screen filename: #{filename}. Screen filenames must be lowercase."
|
170
168
|
end
|
171
169
|
end
|
170
|
+
needs_dependencies = pkg.spec.runtime_dependencies.length > 0
|
172
171
|
needs_dependencies = true if Dir.exist?(File.join(gem_path, 'lib'))
|
172
|
+
# If needs_dependencies hasn't already been set we need to scan the plugin.txt
|
173
|
+
# to see if they've explicitly set the NEEDS_DEPENDENCIES keyword
|
174
|
+
unless needs_dependencies
|
175
|
+
if plugin_hash['plugin_txt_lines'].join("\n").include?('NEEDS_DEPENDENCIES')
|
176
|
+
needs_dependencies = true
|
177
|
+
end
|
178
|
+
end
|
173
179
|
if needs_dependencies
|
174
180
|
plugin_model.needs_dependencies = true
|
175
181
|
plugin_model.update unless validate_only
|
@@ -198,7 +204,7 @@ module OpenC3
|
|
198
204
|
current_model = nil
|
199
205
|
parser.parse_file(plugin_txt_path, false, true, true, variables) do |keyword, params|
|
200
206
|
case keyword
|
201
|
-
when 'VARIABLE'
|
207
|
+
when 'VARIABLE', 'NEEDS_DEPENDENCIES'
|
202
208
|
# Ignore during phase 2
|
203
209
|
when 'TARGET', 'INTERFACE', 'ROUTER', 'MICROSERVICE', 'TOOL', 'WIDGET'
|
204
210
|
if current_model
|
@@ -206,12 +212,13 @@ module OpenC3
|
|
206
212
|
current_model.deploy(gem_path, variables, validate_only: validate_only)
|
207
213
|
current_model = nil
|
208
214
|
end
|
209
|
-
current_model = OpenC3.const_get((keyword.capitalize + 'Model').intern).handle_config(parser,
|
215
|
+
current_model = OpenC3.const_get((keyword.capitalize + 'Model').intern).handle_config(parser,
|
216
|
+
keyword, params, plugin: plugin_model.name, needs_dependencies: needs_dependencies, scope: scope)
|
210
217
|
else
|
211
218
|
if current_model
|
212
219
|
current_model.handle_config(parser, keyword, params)
|
213
220
|
else
|
214
|
-
raise "Invalid keyword #{keyword} in plugin.txt"
|
221
|
+
raise "Invalid keyword '#{keyword}' in plugin.txt"
|
215
222
|
end
|
216
223
|
end
|
217
224
|
end
|
@@ -91,7 +91,7 @@ module OpenC3
|
|
91
91
|
if color.nil?
|
92
92
|
color = '#%06x' % (rand * 0xffffff)
|
93
93
|
end
|
94
|
-
valid_color = color =~ /[0-
|
94
|
+
valid_color = color =~ /[0-9a-fA-F]{6}/
|
95
95
|
if valid_color.nil?
|
96
96
|
raise RuntimeError.new "invalid color but in hex format. #FF0000"
|
97
97
|
end
|
@@ -92,7 +92,7 @@ module OpenC3
|
|
92
92
|
if color.nil?
|
93
93
|
color = '#%06x' % (rand * 0xffffff)
|
94
94
|
end
|
95
|
-
valid_color = color =~ /[0-
|
95
|
+
valid_color = color =~ /[0-9a-fA-F]{6}/
|
96
96
|
if valid_color.nil?
|
97
97
|
raise TriggerGroupInputError.new "invalid color must be in hex format. #FF0000"
|
98
98
|
end
|
@@ -80,7 +80,7 @@ module OpenC3
|
|
80
80
|
|
81
81
|
# @return [Hash] Whether or not messages should be printed for this state.
|
82
82
|
# Given as STATE_NAME => true / false.
|
83
|
-
|
83
|
+
attr_reader :messages_disabled
|
84
84
|
|
85
85
|
# Colors associated with states
|
86
86
|
# @return [Hash] State colors given as STATE_NAME => COLOR
|
@@ -77,7 +77,7 @@ module OpenC3
|
|
77
77
|
else
|
78
78
|
request.body_stream = io_or_string
|
79
79
|
end
|
80
|
-
|
80
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
81
81
|
http.request(request) do |response|
|
82
82
|
response.value() # Raises an HTTP error if the response is not 2xx (success)
|
83
83
|
return response
|
@@ -157,17 +157,17 @@ module OpenC3
|
|
157
157
|
if $openc3_in_cluster
|
158
158
|
case ENV['OPENC3_CLOUD']
|
159
159
|
when 'local'
|
160
|
-
|
160
|
+
URI.parse("http://openc3-minio:9000" + url)
|
161
161
|
when 'aws'
|
162
|
-
|
162
|
+
URI.parse("https://s3.#{ENV['AWS_REGION']}.amazonaws.com" + url)
|
163
163
|
when 'gcp'
|
164
|
-
|
164
|
+
URI.parse("https://storage.googleapis.com" + url)
|
165
165
|
# when 'azure'
|
166
166
|
else
|
167
167
|
raise "Unknown cloud #{ENV['OPENC3_CLOUD']}"
|
168
168
|
end
|
169
169
|
else
|
170
|
-
|
170
|
+
URI.parse($api_server.generate_url + url)
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
@@ -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'
|
@@ -148,7 +148,6 @@ module OpenC3
|
|
148
148
|
}
|
149
149
|
col = 0
|
150
150
|
row = 0
|
151
|
-
num_cols = table.num_columns
|
152
151
|
table.sorted_items.each_with_index do |item, index|
|
153
152
|
next if item.hidden
|
154
153
|
if table.num_columns == 1
|
@@ -111,7 +111,12 @@ module OpenC3
|
|
111
111
|
token = nil
|
112
112
|
result = []
|
113
113
|
while true
|
114
|
-
resp = @client.list_objects_v2(
|
114
|
+
resp = @client.list_objects_v2({
|
115
|
+
bucket: bucket,
|
116
|
+
max_keys: max_request,
|
117
|
+
prefix: prefix,
|
118
|
+
continuation_token: token
|
119
|
+
})
|
115
120
|
result.concat(resp.contents)
|
116
121
|
break if result.length >= max_total
|
117
122
|
break unless resp.is_truncated
|
@@ -119,12 +124,12 @@ module OpenC3
|
|
119
124
|
end
|
120
125
|
# Array of objects with key and size methods
|
121
126
|
result
|
122
|
-
rescue Aws::S3::Errors::NoSuchBucket
|
127
|
+
rescue Aws::S3::Errors::NoSuchBucket
|
123
128
|
raise NotFound, "Bucket '#{bucket}' does not exist."
|
124
129
|
end
|
125
130
|
|
126
131
|
# Lists the files under a specified path
|
127
|
-
def list_files(bucket:, path:, only_directories: false)
|
132
|
+
def list_files(bucket:, path:, only_directories: false, include_head: false)
|
128
133
|
# Trailing slash is important in AWS S3 when listing files
|
129
134
|
# See https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Types/ListObjectsV2Output.html#common_prefixes-instance_method
|
130
135
|
if path[-1] != '/'
|
@@ -158,6 +163,9 @@ module OpenC3
|
|
158
163
|
item['name'] = aws_item.key.split('/')[-1]
|
159
164
|
item['modified'] = aws_item.last_modified
|
160
165
|
item['size'] = aws_item.size
|
166
|
+
if include_head
|
167
|
+
item['head'] = head_object(bucket: bucket, key: aws_item.key)
|
168
|
+
end
|
161
169
|
files << item
|
162
170
|
end
|
163
171
|
result = [dirs, files]
|
@@ -166,10 +174,20 @@ module OpenC3
|
|
166
174
|
token = resp.next_continuation_token
|
167
175
|
end
|
168
176
|
result
|
169
|
-
rescue Aws::S3::Errors::NoSuchBucket
|
177
|
+
rescue Aws::S3::Errors::NoSuchBucket
|
170
178
|
raise NotFound, "Bucket '#{bucket}' does not exist."
|
171
179
|
end
|
172
180
|
|
181
|
+
# get metadata for a specific object
|
182
|
+
def head_object(bucket:, key:)
|
183
|
+
head = @client.head_object({
|
184
|
+
bucket: bucket,
|
185
|
+
key: key
|
186
|
+
})
|
187
|
+
rescue Aws::S3::Errors::NotFound => error
|
188
|
+
raise NotFound, "Object: #{bucket}/#{key}"
|
189
|
+
end
|
190
|
+
|
173
191
|
# put_object fires off the request to store but does not confirm
|
174
192
|
def put_object(bucket:, key:, body:, content_type: nil, cache_control: nil, metadata: nil)
|
175
193
|
@client.put_object(bucket: bucket, key: key, body: body,
|
@@ -57,10 +57,10 @@ class BucketFile
|
|
57
57
|
cmd_or_tlm = path_split[2].to_s.upcase
|
58
58
|
target_name = path_split[3].to_s.upcase
|
59
59
|
if stream_mode == 'RAW'
|
60
|
-
type = (
|
60
|
+
type = (cmd_or_tlm == 'CMD') ? 'COMMAND' : 'TELEMETRY'
|
61
61
|
else
|
62
62
|
if stream_mode == 'DECOM'
|
63
|
-
type = (
|
63
|
+
type = (cmd_or_tlm == 'CMD') ? 'DECOMCMD' : 'DECOM'
|
64
64
|
else
|
65
65
|
type = stream_mode # REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
|
66
66
|
end
|
@@ -156,6 +156,7 @@ class BucketFileCache
|
|
156
156
|
@current_disk_usage = 0
|
157
157
|
@queued_bucket_files = []
|
158
158
|
@bucket_file_hash = {}
|
159
|
+
bucket_file = nil
|
159
160
|
|
160
161
|
@thread = Thread.new do
|
161
162
|
client = OpenC3::Bucket.getClient()
|
@@ -162,7 +162,7 @@ module OpenC3
|
|
162
162
|
|
163
163
|
def self.get_file_times(bucket_path)
|
164
164
|
basename = File.basename(bucket_path)
|
165
|
-
file_start_timestamp, file_end_timestamp,
|
165
|
+
file_start_timestamp, file_end_timestamp, _ = basename.split("__")
|
166
166
|
file_start_time = DateTime.strptime(file_start_timestamp, FILE_TIMESTAMP_FORMAT).to_time
|
167
167
|
file_end_time = DateTime.strptime(file_end_timestamp, FILE_TIMESTAMP_FORMAT).to_time
|
168
168
|
return file_start_time, file_end_time
|