cosmos 5.0.4 → 5.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/cosmos +182 -41
- data/data/config/plugins.yaml +10 -0
- data/ext/cosmos/ext/cosmos_io/cosmos_io.c +14 -14
- data/ext/cosmos/ext/packet/packet.c +3 -3
- data/ext/cosmos/ext/structure/structure.c +31 -31
- data/lib/cosmos/api/tlm_api.rb +4 -4
- data/lib/cosmos/logs/log_writer.rb +76 -27
- data/lib/cosmos/microservices/interface_microservice.rb +0 -15
- data/lib/cosmos/models/gem_model.rb +7 -1
- data/lib/cosmos/models/interface_model.rb +16 -7
- data/lib/cosmos/models/metadata_model.rb +39 -15
- data/lib/cosmos/models/microservice_model.rb +6 -3
- data/lib/cosmos/models/model.rb +7 -0
- data/lib/cosmos/models/note_model.rb +4 -6
- data/lib/cosmos/models/plugin_model.rb +107 -47
- data/lib/cosmos/models/scope_model.rb +2 -0
- data/lib/cosmos/models/sorted_model.rb +3 -1
- data/lib/cosmos/models/target_model.rb +24 -15
- data/lib/cosmos/models/tool_model.rb +8 -8
- data/lib/cosmos/models/widget_model.rb +10 -10
- data/lib/cosmos/packets/packet.rb +1 -1
- data/lib/cosmos/packets/structure.rb +30 -33
- data/lib/cosmos/script/calendar.rb +13 -2
- data/lib/cosmos/tools/table_manager/table_config.rb +16 -1
- data/lib/cosmos/tools/table_manager/table_manager_core.rb +213 -309
- data/lib/cosmos/topics/config_topic.rb +68 -0
- data/lib/cosmos/version.rb +5 -5
- metadata +7 -8
- data/bin/xtce_converter +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 520339a0daade42a51611f9e17fe6e5a2c1343d9bab3ad6b36dbb03f11f55f28
|
4
|
+
data.tar.gz: 59a4d41cc6ef453ea1f375c5e9671aa0b14b390da42d8413bd080ab7bdb18ff4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 700274a130767236a08e76ce223a09fa0229e659153c8a5f50896447796d3ca0e4487423704ece2d655511a642c6dfed0a8fc9482f8ee7ef9681f1726c23a2ce
|
7
|
+
data.tar.gz: 20773c2fd54d95674f66252edbd51faee8107cca83c05bace69a4607fd5563dc543d10f670513b4fb2df25d6ca6c18d0e58923f517e66f7f186fe7bc0e1eecbb
|
data/bin/cosmos
CHANGED
@@ -24,6 +24,7 @@ require 'cosmos'
|
|
24
24
|
require 'cosmos/utilities/s3'
|
25
25
|
require 'cosmos/models/scope_model'
|
26
26
|
require 'cosmos/models/plugin_model'
|
27
|
+
require 'cosmos/packets/packet_config'
|
27
28
|
require 'cosmos/bridge/bridge'
|
28
29
|
require 'ostruct'
|
29
30
|
require 'optparse'
|
@@ -32,6 +33,7 @@ require 'fileutils'
|
|
32
33
|
require 'find'
|
33
34
|
require 'json'
|
34
35
|
require 'redis'
|
36
|
+
require 'psych'
|
35
37
|
require 'erb'
|
36
38
|
|
37
39
|
$redis_url = "redis://#{ENV['COSMOS_REDIS_HOSTNAME']}:#{ENV['COSMOS_REDIS_PORT']}"
|
@@ -40,25 +42,27 @@ $redis_url = "redis://#{ENV['COSMOS_REDIS_HOSTNAME']}:#{ENV['COSMOS_REDIS_PORT']
|
|
40
42
|
MIGRATE_OPTIONS = OpenStruct.new
|
41
43
|
MIGRATE_OPTIONS.all = false
|
42
44
|
MIGRATE_PARSER = OptionParser.new do |op|
|
43
|
-
op.banner = "cosmos migrate PLUGIN [TGT1...]
|
44
|
-
op.on("-a", "--all", "Move all COSMOS 4 targets into a single COSMOS 5 plugin") do
|
45
|
+
op.banner = "cosmos migrate PLUGIN [TGT1...] # Create a COSMOS 5 plugin from existing COSMOS 4 targets"
|
46
|
+
op.on("-a", "--all", " Move all COSMOS 4 targets into a single COSMOS 5 plugin") do
|
45
47
|
MIGRATE_OPTIONS.all = true
|
46
48
|
end
|
47
49
|
end
|
50
|
+
ERROR_CODE = 67 # ASCII 'C' for COSMOS
|
48
51
|
|
49
52
|
# Prints the usage text for the cosmos executable
|
50
53
|
def print_usage
|
51
54
|
puts "Usage:"
|
52
55
|
puts " cosmos help # Displays this information"
|
53
56
|
puts " cosmos rake # Runs rake in the local directory"
|
54
|
-
puts " cosmos
|
57
|
+
puts " cosmos validate /PATH/FILENAME.gem SCOPE variables.txt # Validate a COSMOS plugin gem file"
|
58
|
+
puts " cosmos load /PATH/FILENAME.gem SCOPE variables.txt # Loads a COSMOS plugin gem file"
|
55
59
|
puts " cosmos generate plugin PLUGIN_NAME # Generate a COSMOS plugin"
|
56
60
|
puts " #{MIGRATE_PARSER}"
|
57
61
|
puts " cosmos bridge CONFIG_FILENAME # Run COSMOS host bridge"
|
58
62
|
puts " cosmos bridgesetup CONFIG_FILENAME # Create a default config file"
|
59
63
|
puts " cosmos geminstall GEMFILENAME # Install loaded gem to /gems"
|
60
64
|
puts " cosmos rubysloc # Counts Ruby SLOC recursively. Run with --help for more info."
|
61
|
-
|
65
|
+
puts " cosmos xtce_converter # Convert to and from the XTCE format. Run with --help for more info."
|
62
66
|
puts " cosmos cstol_converter # Converts CSTOL files (.prc) to COSMOS. Run with --help for more info."
|
63
67
|
puts ""
|
64
68
|
end
|
@@ -185,6 +189,76 @@ def migrate(args)
|
|
185
189
|
puts "Plugin complete: #{File.expand_path('.')}" # Remember we're inside the plugin dir
|
186
190
|
end
|
187
191
|
|
192
|
+
def xtce_converter(args)
|
193
|
+
options = {}
|
194
|
+
option_parser = OptionParser.new do |option_parser|
|
195
|
+
option_parser.banner = "Usage: xtce_converter [options] --import input_xtce_filename --output output_dir\n"+
|
196
|
+
" xtce_converter [options] --plugin /PATH/FILENAME.gem --output output_dir --variables variables.txt"
|
197
|
+
option_parser.separator("")
|
198
|
+
option_parser.on("-h", "--help", "Show this message") do
|
199
|
+
puts option_parser
|
200
|
+
exit
|
201
|
+
end
|
202
|
+
option_parser.on("-i VALUE", "--import VALUE", "Import the specified .xtce file") do |arg|
|
203
|
+
options[:import] = arg
|
204
|
+
end
|
205
|
+
option_parser.on("-o", "--output DIRECTORY", "Create files in the directory") do |arg|
|
206
|
+
options[:output] = arg
|
207
|
+
end
|
208
|
+
option_parser.on("-p", "--plugin PLUGIN", "Export .xtce file(s) from the plugin") do |arg|
|
209
|
+
options[:plugin] = arg
|
210
|
+
end
|
211
|
+
option_parser.on("-v", "--variables", "Optional variables file to pass to the plugin") do |arg|
|
212
|
+
options[:variables] = arg
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
begin
|
217
|
+
option_parser.parse!(args)
|
218
|
+
rescue => err
|
219
|
+
abort(option_parser.to_s)
|
220
|
+
end
|
221
|
+
|
222
|
+
if options[:import] && options[:plugin]
|
223
|
+
puts "xtce_converter options --import and --plugin are mutually exclusive"
|
224
|
+
abort(option_parser.to_s)
|
225
|
+
end
|
226
|
+
|
227
|
+
ENV['COSMOS_NO_STORE'] = '1' # it can be anything
|
228
|
+
Cosmos::Logger.stdout = false
|
229
|
+
Cosmos::Logger.level = Cosmos::Logger::DEBUG
|
230
|
+
|
231
|
+
if options[:import] && options[:output]
|
232
|
+
packet_config = Cosmos::PacketConfig.new
|
233
|
+
puts "Processing #{options[:import]}..."
|
234
|
+
packet_config.process_file(options[:import], nil)
|
235
|
+
puts "Writing COSMOS config files to #{options[:output]}/"
|
236
|
+
packet_config.to_config(options[:output])
|
237
|
+
exit(0)
|
238
|
+
elsif options[:plugin] && options[:output]
|
239
|
+
begin
|
240
|
+
variables = nil
|
241
|
+
variables = JSON.parse(File.read(options[:variables])) if options[:variables]
|
242
|
+
puts "Installing #{File.basename(options[:plugin])}"
|
243
|
+
plugin_hash = Cosmos::PluginModel.install_phase1(options[:plugin], variables, scope: 'DEFAULT', validate_only: true)
|
244
|
+
plugin_hash['variables']['xtce_output'] = options[:output]
|
245
|
+
Cosmos::PluginModel.install_phase2(plugin_hash['name'], plugin_hash['variables'], scope: 'DEFAULT', validate_only: true,
|
246
|
+
gem_file_path: options[:plugin])
|
247
|
+
result = 0 # bash and Windows consider 0 success
|
248
|
+
rescue => e
|
249
|
+
puts "Error: #{e.message}"
|
250
|
+
result = ERROR_CODE
|
251
|
+
ensure
|
252
|
+
name = Psych.safe_load(`gem spec #{options[:plugin]} name`).to_s
|
253
|
+
version = Psych.safe_load(`gem spec #{options[:plugin]} version`, permitted_classes: [Gem::Version]).to_s
|
254
|
+
Gem::Uninstaller.new(name, {:version => version, :force => true}).uninstall
|
255
|
+
exit(result)
|
256
|
+
end
|
257
|
+
else
|
258
|
+
abort(option_parser.to_s)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
188
262
|
# A helper method to make the zip writing recursion work
|
189
263
|
def write_zip_entries(base_dir, entries, zip_path, io)
|
190
264
|
io.add(zip_path, base_dir) # Add the directory whether it has entries or not
|
@@ -212,7 +286,66 @@ def put_into_archive(disk_file_path, io, zip_file_path)
|
|
212
286
|
end
|
213
287
|
end
|
214
288
|
|
215
|
-
def
|
289
|
+
def validate_plugin(plugin_file_path, scope:, variables_file: nil)
|
290
|
+
ENV['COSMOS_NO_STORE'] = '1' # it can be anything
|
291
|
+
Cosmos::Logger.stdout = false
|
292
|
+
Cosmos::Logger.level = Cosmos::Logger::DEBUG
|
293
|
+
scope ||= 'DEFAULT'
|
294
|
+
variables = nil
|
295
|
+
variables = JSON.parse(File.read(variables_file)) if variables_file
|
296
|
+
puts "Installing #{File.basename(plugin_file_path)}"
|
297
|
+
plugin_hash = Cosmos::PluginModel.install_phase1(plugin_file_path, variables, scope: scope, validate_only: true)
|
298
|
+
Cosmos::PluginModel.install_phase2(plugin_hash['name'], plugin_hash['variables'], scope: scope, validate_only: true,
|
299
|
+
gem_file_path: plugin_file_path)
|
300
|
+
puts "Successfully validated #{File.basename(plugin_file_path)}"
|
301
|
+
result = 0 # bash and Windows consider 0 success
|
302
|
+
rescue => e
|
303
|
+
puts "Error: #{e.message}"
|
304
|
+
result = ERROR_CODE
|
305
|
+
ensure
|
306
|
+
name = Psych.safe_load(`gem spec #{plugin_file_path} name`).to_s
|
307
|
+
version = Psych.safe_load(`gem spec #{plugin_file_path} version`, permitted_classes: [Gem::Version]).to_s
|
308
|
+
Gem::Uninstaller.new(name, {:version => version, :force => true}).uninstall
|
309
|
+
exit(result)
|
310
|
+
end
|
311
|
+
|
312
|
+
def update_plugin(plugin_file_path, plugin_name, variables: nil, plugin_txt_lines: nil, scope:)
|
313
|
+
new_gem = File.basename(plugin_file_path)
|
314
|
+
old_gem = plugin_name.split("__")[0]
|
315
|
+
puts "Updating existing plugin: #{plugin_name} with #{File.basename(plugin_file_path)}"
|
316
|
+
plugin_model = Cosmos::PluginModel.get_model(name: plugin_name, scope: scope)
|
317
|
+
begin
|
318
|
+
# Only update if something has changed
|
319
|
+
if (new_gem != old_gem) or (variables != plugin_model.variables) or (plugin_txt_lines != plugin_model.plugin_txt_lines)
|
320
|
+
variables = plugin_model.variables unless variables
|
321
|
+
plugin_model.destroy
|
322
|
+
plugin_hash = Cosmos::PluginModel.install_phase1(plugin_file_path, existing_variables: variables, existing_plugin_txt_lines: plugin_txt_lines, process_existing: true, scope: scope)
|
323
|
+
Cosmos::PluginModel.install_phase2(plugin_hash, scope: scope)
|
324
|
+
else
|
325
|
+
puts "No changes detected - Exiting without change"
|
326
|
+
end
|
327
|
+
rescue => error
|
328
|
+
puts error.formatted
|
329
|
+
plugin_model.restore if plugin_model.destroyed?
|
330
|
+
raise error
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# Loads a plugin into the COSMOS system
|
335
|
+
# This code is used from the command line and is the same code that gets called if you
|
336
|
+
# edit/upgrade or install a new plugin from the Admin interface
|
337
|
+
#
|
338
|
+
# Usage: cosmos load gemfile_path [scope] [plugin_hash_file_path]
|
339
|
+
#
|
340
|
+
# With just gemfile_path and/or scope: Will do nothing if any plugin
|
341
|
+
# with the same gem file already exists
|
342
|
+
#
|
343
|
+
# Otherwise will do what the plugin_hash_file says to do
|
344
|
+
# Plugin hash file must have the exact name of an existing plugin for upgrades and edits
|
345
|
+
# Otherwise, it will be assumed that the plugin is intentionally being installed for a second
|
346
|
+
# time
|
347
|
+
#
|
348
|
+
def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil)
|
216
349
|
scope ||= 'DEFAULT'
|
217
350
|
# Only create the scope if it doesn't already exist
|
218
351
|
unless Cosmos::ScopeModel.names.include?(scope)
|
@@ -226,41 +359,47 @@ def load_plugin(plugin_file_path, scope:, variables_file: nil)
|
|
226
359
|
end
|
227
360
|
|
228
361
|
begin
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
if
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
362
|
+
if plugin_hash_file
|
363
|
+
# Admin Create / Edit / or Upgrade Plugin
|
364
|
+
Cosmos::PluginModel.install_phase1(plugin_file_path, scope: scope)
|
365
|
+
plugin_hash = JSON.parse(File.read(plugin_hash_file))
|
366
|
+
else
|
367
|
+
# Init or Command Line cosmos load with no plugin_hash_file
|
368
|
+
file_full_name = File.basename(plugin_file_path, ".gem")
|
369
|
+
file_gem_name = file_full_name.split('-')[0..-2].join('-')
|
370
|
+
found = false
|
371
|
+
plugin_names = Cosmos::PluginModel.names(scope: scope)
|
372
|
+
plugin_names.each do |plugin_name|
|
373
|
+
gem_name = plugin_name.split("__")[0]
|
374
|
+
full_name = File.basename(gem_name, ".gem")
|
375
|
+
gem_name = full_name.split('-')[0..-2].join('-')
|
376
|
+
if file_gem_name == gem_name
|
377
|
+
found = true
|
378
|
+
# Upgrade if version changed else do nothing
|
379
|
+
if file_full_name != full_name
|
380
|
+
update_plugin(plugin_file_path, plugin_name, scope: scope)
|
381
|
+
end
|
249
382
|
end
|
250
|
-
Cosmos::PluginModel.install_phase2(plugin_hash['name'], plugin_hash['variables'], scope: scope)
|
251
|
-
found = true
|
252
383
|
end
|
384
|
+
return if found
|
385
|
+
|
386
|
+
plugin_hash = Cosmos::PluginModel.install_phase1(plugin_file_path, scope: scope)
|
253
387
|
end
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
388
|
+
|
389
|
+
# Determine if plugin named in plugin_hash exists
|
390
|
+
existing_plugin_hash = Cosmos::PluginModel.get(name: plugin_hash['name'], scope: scope)
|
391
|
+
|
392
|
+
# Existing plugin hash will be present if plugin is being edited or upgraded
|
393
|
+
# If editing, gem name will match existing hash name
|
394
|
+
# If upgrading, gem name will not match the existing hash name
|
395
|
+
|
396
|
+
if existing_plugin_hash
|
397
|
+
# Upgrade or Edit
|
398
|
+
update_plugin(plugin_file_path, plugin_hash['name'], variables: plugin_hash['variables'], plugin_txt_lines: plugin_hash['plugin_txt_lines'], scope: scope)
|
399
|
+
else
|
400
|
+
# New Install
|
401
|
+
puts "Loading new plugin: #{plugin_file_path}\n#{plugin_hash}"
|
402
|
+
Cosmos::PluginModel.install_phase2(plugin_hash, scope: scope)
|
264
403
|
end
|
265
404
|
rescue => err
|
266
405
|
abort("Error installing plugin: #{scope}: #{plugin_file_path}: #{err.formatted}")
|
@@ -305,8 +444,11 @@ if not ARGV[0].nil? # argument(s) given
|
|
305
444
|
when 'rake'
|
306
445
|
puts `rake #{ARGV[1..-1].join(' ')}`
|
307
446
|
|
447
|
+
when 'validate'
|
448
|
+
validate_plugin(ARGV[1], scope: ARGV[2], variables_file: ARGV[3])
|
449
|
+
|
308
450
|
when 'load'
|
309
|
-
load_plugin(ARGV[1], scope: ARGV[2],
|
451
|
+
load_plugin(ARGV[1], scope: ARGV[2], plugin_hash_file: ARGV[3])
|
310
452
|
|
311
453
|
when 'geminstall'
|
312
454
|
gem_install(ARGV[1])
|
@@ -333,9 +475,8 @@ if not ARGV[0].nil? # argument(s) given
|
|
333
475
|
when 'cstol_converter'
|
334
476
|
puts `ruby /cosmos/bin/cstol_converter #{ARGV[1..-1].join(' ')}`
|
335
477
|
|
336
|
-
|
337
|
-
|
338
|
-
# puts `ruby /cosmos/bin/xtce_converter #{ARGV[1..-1].join(' ')}`
|
478
|
+
when 'xtce_converter'
|
479
|
+
xtce_converter(ARGV[1..-1])
|
339
480
|
|
340
481
|
when 'bridge'
|
341
482
|
ENV['COSMOS_NO_STORE'] = '1'
|
data/data/config/plugins.yaml
CHANGED
@@ -68,3 +68,13 @@ ROUTER:
|
|
68
68
|
<%= MetaConfigParser.load('target.yaml').to_meta_config_yaml() %>
|
69
69
|
<%= MetaConfigParser.load('microservice.yaml').to_meta_config_yaml() %>
|
70
70
|
<%= MetaConfigParser.load('tool.yaml').to_meta_config_yaml() %>
|
71
|
+
WIDGET:
|
72
|
+
summary: Define a custom widget
|
73
|
+
example: WIDGET HELLOWORLD
|
74
|
+
description: Defines a custom widget that can be used in Telemetry Viewer screens.
|
75
|
+
parameters:
|
76
|
+
- name: Widget Name
|
77
|
+
description: The name of the widget wil be used to build a path to the widget implementation. For example, `WIDGET HELLOWORLD` will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the [Custom Widgets](/docs/v5/custom-widgets)
|
78
|
+
guide for more details.
|
79
|
+
required: true
|
80
|
+
values: .+
|
@@ -30,19 +30,19 @@ VALUE mCosmosIO = Qnil;
|
|
30
30
|
static ID id_method_read = 0;
|
31
31
|
|
32
32
|
/* Reads a length field and then return the String resulting from reading the
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
33
|
+
* number of bytes the length field indicates
|
34
|
+
*
|
35
|
+
* For example:
|
36
|
+
* io = StringIO.new
|
37
|
+
* # where io is "\x02\x01\x02\x03\x04...."
|
38
|
+
* result = io.read_length_bytes(1)
|
39
|
+
* # result will be "\x01x02" because the length field was given
|
40
|
+
* # to be 1 byte. We read 1 byte which is a 2. So we then read two
|
41
|
+
* # bytes and return.
|
42
|
+
*
|
43
|
+
* @param length_num_bytes [Integer] Number of bytes in the length field
|
44
|
+
* @return [String] A String of "length field" number of bytes
|
45
|
+
*/
|
46
46
|
static VALUE read_length_bytes(int argc, VALUE *argv, VALUE self)
|
47
47
|
{
|
48
48
|
int length_num_bytes = 0;
|
@@ -134,7 +134,7 @@ static VALUE read_length_bytes(int argc, VALUE *argv, VALUE self)
|
|
134
134
|
}
|
135
135
|
|
136
136
|
/* Read String */
|
137
|
-
temp_string_length = UINT2NUM(string_length);
|
137
|
+
temp_string_length = UINT2NUM((unsigned int)string_length);
|
138
138
|
return_value = rb_funcall(self, id_method_read, 1, temp_string_length);
|
139
139
|
if (NIL_P(return_value) || (RSTRING_LEN(return_value) != string_length))
|
140
140
|
{
|
@@ -196,7 +196,7 @@ static VALUE packet_initialize(int argc, VALUE *argv, VALUE self)
|
|
196
196
|
packet_name = argv[1];
|
197
197
|
default_endianness = symbol_BIG_ENDIAN;
|
198
198
|
description = Qnil;
|
199
|
-
buffer =
|
199
|
+
buffer = Qnil;
|
200
200
|
item_class = cPacketItem;
|
201
201
|
break;
|
202
202
|
case 3:
|
@@ -204,7 +204,7 @@ static VALUE packet_initialize(int argc, VALUE *argv, VALUE self)
|
|
204
204
|
packet_name = argv[1];
|
205
205
|
default_endianness = argv[2];
|
206
206
|
description = Qnil;
|
207
|
-
buffer =
|
207
|
+
buffer = Qnil;
|
208
208
|
item_class = cPacketItem;
|
209
209
|
break;
|
210
210
|
case 4:
|
@@ -212,7 +212,7 @@ static VALUE packet_initialize(int argc, VALUE *argv, VALUE self)
|
|
212
212
|
packet_name = argv[1];
|
213
213
|
default_endianness = argv[2];
|
214
214
|
description = argv[3];
|
215
|
-
buffer =
|
215
|
+
buffer = Qnil;
|
216
216
|
item_class = cPacketItem;
|
217
217
|
break;
|
218
218
|
case 5:
|
@@ -56,6 +56,7 @@ static ID id_method_reverse = 0;
|
|
56
56
|
static ID id_method_Integer = 0;
|
57
57
|
static ID id_method_Float = 0;
|
58
58
|
static ID id_method_kind_of = 0;
|
59
|
+
static ID id_method_allocate_buffer_if_needed = 0;
|
59
60
|
|
60
61
|
static ID id_ivar_buffer = 0;
|
61
62
|
static ID id_ivar_bit_offset = 0;
|
@@ -520,7 +521,8 @@ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE para
|
|
520
521
|
{
|
521
522
|
string_length = upper_bound - lower_bound + 1;
|
522
523
|
string = malloc(string_length + 1);
|
523
|
-
if (string == NULL)
|
524
|
+
if (string == NULL)
|
525
|
+
{
|
524
526
|
rb_raise(rb_eNoMemError, "malloc of %d returned NULL", string_length + 1);
|
525
527
|
}
|
526
528
|
memcpy(string, buffer + lower_bound, string_length);
|
@@ -577,7 +579,8 @@ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE para
|
|
577
579
|
string_length = ((bit_size - 1) / 8) + 1;
|
578
580
|
array_length = string_length + 4; /* Required number of bytes plus slack */
|
579
581
|
unsigned_char_array = (unsigned char *)malloc(array_length);
|
580
|
-
if (unsigned_char_array == NULL)
|
582
|
+
if (unsigned_char_array == NULL)
|
583
|
+
{
|
581
584
|
rb_raise(rb_eNoMemError, "malloc of %d returned NULL", array_length);
|
582
585
|
}
|
583
586
|
read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
|
@@ -692,7 +695,8 @@ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE para
|
|
692
695
|
string_length = ((bit_size - 1) / 8) + 1;
|
693
696
|
array_length = string_length + 4; /* Required number of bytes plus slack */
|
694
697
|
unsigned_char_array = (unsigned char *)malloc(array_length);
|
695
|
-
if (unsigned_char_array == NULL)
|
698
|
+
if (unsigned_char_array == NULL)
|
699
|
+
{
|
696
700
|
rb_raise(rb_eNoMemError, "malloc of %d returned NULL", array_length);
|
697
701
|
}
|
698
702
|
read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
|
@@ -1147,7 +1151,8 @@ static VALUE binary_accessor_write(VALUE self, VALUE value, VALUE param_bit_offs
|
|
1147
1151
|
string_length = ((bit_size - 1) / 8) + 1;
|
1148
1152
|
array_length = string_length + 4; /* Required number of bytes plus slack */
|
1149
1153
|
unsigned_char_array = (unsigned char *)malloc(array_length);
|
1150
|
-
if (unsigned_char_array == NULL)
|
1154
|
+
if (unsigned_char_array == NULL)
|
1155
|
+
{
|
1151
1156
|
rb_raise(rb_eNoMemError, "malloc of %d returned NULL", array_length);
|
1152
1157
|
}
|
1153
1158
|
|
@@ -1275,15 +1280,8 @@ static VALUE binary_accessor_write(VALUE self, VALUE value, VALUE param_bit_offs
|
|
1275
1280
|
*/
|
1276
1281
|
static int get_int_length(VALUE self)
|
1277
1282
|
{
|
1278
|
-
|
1279
|
-
|
1280
|
-
{
|
1281
|
-
return (int)RSTRING_LEN(buffer);
|
1282
|
-
}
|
1283
|
-
else
|
1284
|
-
{
|
1285
|
-
return 0;
|
1286
|
-
}
|
1283
|
+
rb_funcall(self, id_method_allocate_buffer_if_needed, 0);
|
1284
|
+
return (int)RSTRING_LEN(rb_ivar_get(self, id_ivar_buffer));
|
1287
1285
|
}
|
1288
1286
|
|
1289
1287
|
/*
|
@@ -1310,24 +1308,21 @@ static VALUE read_item_internal(VALUE self, VALUE item, VALUE buffer)
|
|
1310
1308
|
return Qnil;
|
1311
1309
|
}
|
1312
1310
|
|
1313
|
-
if (RTEST(buffer))
|
1311
|
+
if (!(RTEST(buffer)))
|
1314
1312
|
{
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
{
|
1325
|
-
return binary_accessor_read(cBinaryAccessor, bit_offset, bit_size, data_type, buffer, endianness);
|
1326
|
-
}
|
1313
|
+
buffer = rb_funcall(self, id_method_allocate_buffer_if_needed, 0);
|
1314
|
+
}
|
1315
|
+
bit_offset = rb_ivar_get(item, id_ivar_bit_offset);
|
1316
|
+
bit_size = rb_ivar_get(item, id_ivar_bit_size);
|
1317
|
+
array_size = rb_ivar_get(item, id_ivar_array_size);
|
1318
|
+
endianness = rb_ivar_get(item, id_ivar_endianness);
|
1319
|
+
if (RTEST(array_size))
|
1320
|
+
{
|
1321
|
+
return rb_funcall(cBinaryAccessor, id_method_read_array, 6, bit_offset, bit_size, data_type, array_size, buffer, endianness);
|
1327
1322
|
}
|
1328
1323
|
else
|
1329
1324
|
{
|
1330
|
-
|
1325
|
+
return binary_accessor_read(cBinaryAccessor, bit_offset, bit_size, data_type, buffer, endianness);
|
1331
1326
|
}
|
1332
1327
|
}
|
1333
1328
|
|
@@ -1404,8 +1399,8 @@ static VALUE structure_item_spaceship(VALUE self, VALUE other_item)
|
|
1404
1399
|
if ((bit_offset == 0) && (other_bit_offset == 0))
|
1405
1400
|
{
|
1406
1401
|
/* Both bit_offsets are 0 so sort by bit_size
|
1407
|
-
|
1408
|
-
|
1402
|
+
* This allows derived items with bit_size of 0 to be listed first
|
1403
|
+
* Compare based on bit size */
|
1409
1404
|
bit_size = FIX2INT(rb_ivar_get(self, id_ivar_bit_size));
|
1410
1405
|
other_bit_size = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_size));
|
1411
1406
|
if (bit_size == other_bit_size)
|
@@ -1518,12 +1513,12 @@ static VALUE structure_initialize(int argc, VALUE *argv, VALUE self)
|
|
1518
1513
|
{
|
1519
1514
|
case 0:
|
1520
1515
|
default_endianness = HOST_ENDIANNESS;
|
1521
|
-
buffer =
|
1516
|
+
buffer = Qnil;
|
1522
1517
|
item_class = cStructureItem;
|
1523
1518
|
break;
|
1524
1519
|
case 1:
|
1525
1520
|
default_endianness = argv[0];
|
1526
|
-
buffer =
|
1521
|
+
buffer = Qnil;
|
1527
1522
|
item_class = cStructureItem;
|
1528
1523
|
break;
|
1529
1524
|
case 2:
|
@@ -1592,6 +1587,10 @@ static VALUE resize_buffer(VALUE self)
|
|
1592
1587
|
rb_str_concat(buffer, rb_str_times(ZERO_STRING, INT2FIX(defined_length - current_length)));
|
1593
1588
|
}
|
1594
1589
|
}
|
1590
|
+
else
|
1591
|
+
{
|
1592
|
+
rb_funcall(self, id_method_allocate_buffer_if_needed, 0);
|
1593
|
+
}
|
1595
1594
|
|
1596
1595
|
return self;
|
1597
1596
|
}
|
@@ -1618,6 +1617,7 @@ void Init_structure(void)
|
|
1618
1617
|
id_method_Integer = rb_intern("Integer");
|
1619
1618
|
id_method_Float = rb_intern("Float");
|
1620
1619
|
id_method_kind_of = rb_intern("kind_of?");
|
1620
|
+
id_method_allocate_buffer_if_needed = rb_intern("allocate_buffer_if_needed");
|
1621
1621
|
|
1622
1622
|
MIN_INT8 = INT2NUM(-128);
|
1623
1623
|
MAX_INT8 = INT2NUM(127);
|
data/lib/cosmos/api/tlm_api.rb
CHANGED
@@ -111,11 +111,11 @@ module Cosmos
|
|
111
111
|
|
112
112
|
# Injects a packet into the system as if it was received from an interface
|
113
113
|
#
|
114
|
-
# @param target_name[String] Target name of the packet
|
115
|
-
# @param packet_name[String] Packet name of the packet
|
116
|
-
# @param item_hash[Hash] Hash of item_name and value for each item you want to change from the current value table
|
114
|
+
# @param target_name [String] Target name of the packet
|
115
|
+
# @param packet_name [String] Packet name of the packet
|
116
|
+
# @param item_hash [Hash] Hash of item_name and value for each item you want to change from the current value table
|
117
117
|
# @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
|
118
|
-
def inject_tlm(target_name, packet_name, item_hash = nil,
|
118
|
+
def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token)
|
119
119
|
authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
120
120
|
unless CvtModel::VALUE_TYPES.include?(type.intern)
|
121
121
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name}"
|