cosmos 4.1.0 → 4.1.1
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/Manifest.txt +5 -0
- data/appveyor.yml +2 -0
- data/autohotkey/tools/replay.ahk +45 -45
- data/autohotkey/tools/script_runner.ahk +3 -9
- data/cosmos.gemspec +1 -1
- data/data/config/interface_modifiers.yaml +23 -0
- data/data/config/screen.yaml +1 -1
- data/data/crc.txt +20 -18
- data/demo/config/targets/INST/cmd_tlm_server.txt +1 -1
- data/lib/cosmos/config/config_parser.rb +8 -3
- data/lib/cosmos/gui/dialogs/exception_dialog.rb +20 -5
- data/lib/cosmos/interfaces/protocols/burst_protocol.rb +13 -3
- data/lib/cosmos/interfaces/protocols/crc_protocol.rb +27 -3
- data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +4 -2
- data/lib/cosmos/interfaces/protocols/length_protocol.rb +4 -2
- data/lib/cosmos/interfaces/protocols/override_protocol.rb +2 -2
- data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +3 -2
- data/lib/cosmos/interfaces/protocols/protocol.rb +16 -4
- data/lib/cosmos/interfaces/protocols/template_protocol.rb +7 -2
- data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +4 -2
- data/lib/cosmos/packets/packet_config.rb +19 -859
- data/lib/cosmos/packets/packet_item.rb +56 -201
- data/lib/cosmos/packets/parsers/xtce_converter.rb +440 -0
- data/lib/cosmos/packets/parsers/xtce_parser.rb +682 -0
- data/lib/cosmos/tools/config_editor/config_editor.rb +143 -5
- data/lib/cosmos/tools/tlm_viewer/screen.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +5 -3
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +40 -27
- data/lib/cosmos/version.rb +4 -4
- data/spec/config/config_parser_spec.rb +39 -2
- data/spec/install/config/targets/INST/screens/hs.txt +42 -0
- data/spec/install/config/targets/INST/target.txt +2 -0
- data/spec/interfaces/protocols/burst_protocol_spec.rb +18 -0
- data/spec/interfaces/protocols/length_protocol_spec.rb +49 -0
- data/spec/interfaces/udp_interface_spec.rb +0 -9
- data/spec/packets/packet_config_spec.rb +21 -144
- data/spec/packets/packet_item_spec.rb +68 -4
- data/spec/packets/parsers/packet_item_parser_spec.rb +12 -0
- data/spec/packets/parsers/xtce_parser_spec.rb +398 -0
- data/spec/tools/tlm_viewer/tlm_viewer_config_spec.rb +401 -0
- metadata +9 -10
@@ -19,9 +19,31 @@ module Cosmos
|
|
19
19
|
ERROR = "ERROR" # on CRC mismatch
|
20
20
|
DISCONNECT = "DISCONNECT" # on CRC mismatch
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# @param write_item_name [String/nil] Item to fill with calculated CRC value for outgoing packets (nil = don't fill)
|
23
|
+
# @param strip_crc [Boolean] Whether or not to remove the CRC from incoming packets
|
24
|
+
# @param bad_strategy [ERROR/DISCONNECT] How to handle CRC errors on incoming packets. ERROR = Just log the error, DISCONNECT = Disconnect interface
|
25
|
+
# @param bit_offset [Integer] Bit offset of the CRC in the data. Can be negative to indicate distance from end of packet
|
26
|
+
# @param bit_size [Integer] Bit size of the CRC - Must be 16, 32, or 64
|
27
|
+
# @param endianness [BIG_ENDIAN/LITTLE_ENDIAN] Endianness of the CRC
|
28
|
+
# @param poly [Integer] Polynomial to use when calculating the CRC
|
29
|
+
# @param seed [Integer] Seed value to start the calculation
|
30
|
+
# @param xor [Boolean] Whether to XOR the CRC result with 0xFFFF
|
31
|
+
# @param reflect [Boolean] Whether to bit reverse each byte of data before calculating the CRC
|
32
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
33
|
+
def initialize(
|
34
|
+
write_item_name = nil,
|
35
|
+
strip_crc = false,
|
36
|
+
bad_strategy = "ERROR",
|
37
|
+
bit_offset = -32,
|
38
|
+
bit_size = 32,
|
39
|
+
endianness = 'BIG_ENDIAN',
|
40
|
+
poly = nil,
|
41
|
+
seed = nil,
|
42
|
+
xor = nil,
|
43
|
+
reflect = nil,
|
44
|
+
allow_empty_data = nil
|
45
|
+
)
|
46
|
+
super(allow_empty_data)
|
25
47
|
@write_item_name = ConfigParser.handle_nil(write_item_name)
|
26
48
|
@strip_crc = ConfigParser.handle_true_false(strip_crc)
|
27
49
|
raise "Invalid strip CRC of '#{strip_crc}'. Must be TRUE or FALSE." unless !!@strip_crc == @strip_crc
|
@@ -95,6 +117,8 @@ module Cosmos
|
|
95
117
|
end
|
96
118
|
|
97
119
|
def read_data(data)
|
120
|
+
return super(data) if (data.length <= 0)
|
121
|
+
|
98
122
|
crc = BinaryAccessor.read(@bit_offset, @bit_size, :UINT, data, @endianness)
|
99
123
|
calculated_crc = @crc.calc(data[0...(@bit_offset / 8)])
|
100
124
|
if calculated_crc != crc
|
@@ -25,15 +25,17 @@ module Cosmos
|
|
25
25
|
# telemetry (true) or commands (false)
|
26
26
|
# @param fill_fields (see BurstProtocol#initialize)
|
27
27
|
# @param unknown_raise Whether to raise an exception on an unknown packet
|
28
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
28
29
|
def initialize(
|
29
30
|
min_id_size,
|
30
31
|
discard_leading_bytes = 0,
|
31
32
|
sync_pattern = nil,
|
32
33
|
telemetry = true,
|
33
34
|
fill_fields = false,
|
34
|
-
unknown_raise = false
|
35
|
+
unknown_raise = false,
|
36
|
+
allow_empty_data = nil
|
35
37
|
)
|
36
|
-
super(discard_leading_bytes, sync_pattern, fill_fields)
|
38
|
+
super(discard_leading_bytes, sync_pattern, fill_fields, allow_empty_data)
|
37
39
|
@min_id_size = Integer(min_id_size)
|
38
40
|
@telemetry = telemetry
|
39
41
|
@unknown_raise = ConfigParser::handle_true_false(unknown_raise)
|
@@ -33,6 +33,7 @@ module Cosmos
|
|
33
33
|
# @param max_length [Integer] The maximum allowed value of the length field
|
34
34
|
# @param fill_length_and_sync_pattern [Boolean] Fill the length field and sync
|
35
35
|
# pattern when writing packets
|
36
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
36
37
|
def initialize(
|
37
38
|
length_bit_offset = 0,
|
38
39
|
length_bit_size = 16,
|
@@ -42,9 +43,10 @@ module Cosmos
|
|
42
43
|
discard_leading_bytes = 0,
|
43
44
|
sync_pattern = nil,
|
44
45
|
max_length = nil,
|
45
|
-
fill_length_and_sync_pattern = false
|
46
|
+
fill_length_and_sync_pattern = false,
|
47
|
+
allow_empty_data = nil
|
46
48
|
)
|
47
|
-
super(discard_leading_bytes, sync_pattern, fill_length_and_sync_pattern)
|
49
|
+
super(discard_leading_bytes, sync_pattern, fill_length_and_sync_pattern, allow_empty_data)
|
48
50
|
|
49
51
|
# Save length field attributes
|
50
52
|
@length_bit_offset = Integer(length_bit_offset)
|
@@ -17,8 +17,8 @@ module Cosmos
|
|
17
17
|
# methods. Clearing the override requires calling normalize_tlm.
|
18
18
|
class OverrideProtocol < Protocol
|
19
19
|
|
20
|
-
# @param allow_empty_data [true/false]
|
21
|
-
def initialize(allow_empty_data =
|
20
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
21
|
+
def initialize(allow_empty_data = nil)
|
22
22
|
super(allow_empty_data)
|
23
23
|
end
|
24
24
|
|
@@ -16,8 +16,9 @@ module Cosmos
|
|
16
16
|
|
17
17
|
# @param sync_pattern (see BurstProtocol#initialize)
|
18
18
|
# @param max_length [Integer] The maximum allowed value of the length field
|
19
|
-
|
20
|
-
|
19
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
20
|
+
def initialize(sync_pattern = nil, max_length = nil, allow_empty_data = nil)
|
21
|
+
super(0, sync_pattern, false, allow_empty_data)
|
21
22
|
@max_length = ConfigParser.handle_nil(max_length)
|
22
23
|
@max_length = Integer(@max_length) if @max_length
|
23
24
|
end
|
@@ -17,10 +17,12 @@ module Cosmos
|
|
17
17
|
attr_accessor :interface
|
18
18
|
attr_accessor :allow_empty_data
|
19
19
|
|
20
|
-
# @param allow_empty_data [true/false] Whether
|
21
|
-
|
20
|
+
# @param allow_empty_data [true/false/nil] Whether or not this protocol will allow an empty string
|
21
|
+
# to be passed down to later Protocols (instead of returning :STOP). Can be true, false, or nil, where
|
22
|
+
# nil is interpreted as true unless the Protocol is the last Protocol of the chain.
|
23
|
+
def initialize(allow_empty_data = nil)
|
22
24
|
@interface = nil
|
23
|
-
@allow_empty_data = ConfigParser.
|
25
|
+
@allow_empty_data = ConfigParser.handle_true_false_nil(allow_empty_data)
|
24
26
|
reset()
|
25
27
|
end
|
26
28
|
|
@@ -37,7 +39,17 @@ module Cosmos
|
|
37
39
|
|
38
40
|
# Ensure we have some data in case this is the only protocol
|
39
41
|
def read_data(data)
|
40
|
-
|
42
|
+
if (data.length <= 0)
|
43
|
+
if @allow_empty_data.nil?
|
44
|
+
if @interface and @interface.read_protocols[-1] == self
|
45
|
+
# Last read interface in chain with auto @allow_empty_data
|
46
|
+
return :STOP
|
47
|
+
end
|
48
|
+
elsif !@allow_empty_data
|
49
|
+
# Don't @allow_empty_data means STOP
|
50
|
+
return :STOP
|
51
|
+
end
|
52
|
+
end
|
41
53
|
data
|
42
54
|
end
|
43
55
|
|
@@ -36,6 +36,7 @@ module Cosmos
|
|
36
36
|
# for a response
|
37
37
|
# @param raise_exceptions [String] Whether to raise exceptions when errors
|
38
38
|
# occur in the protocol like unexpected responses or response timeouts.
|
39
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
39
40
|
def initialize(
|
40
41
|
write_termination_characters,
|
41
42
|
read_termination_characters,
|
@@ -48,7 +49,8 @@ module Cosmos
|
|
48
49
|
fill_fields = false,
|
49
50
|
response_timeout = 5.0,
|
50
51
|
response_polling_period = 0.02,
|
51
|
-
raise_exceptions = false
|
52
|
+
raise_exceptions = false,
|
53
|
+
allow_empty_data = nil
|
52
54
|
)
|
53
55
|
super(
|
54
56
|
write_termination_characters,
|
@@ -56,7 +58,8 @@ module Cosmos
|
|
56
58
|
strip_read_termination,
|
57
59
|
discard_leading_bytes,
|
58
60
|
sync_pattern,
|
59
|
-
fill_fields
|
61
|
+
fill_fields,
|
62
|
+
allow_empty_data)
|
60
63
|
@response_template = nil
|
61
64
|
@response_packet = nil
|
62
65
|
@response_packets = []
|
@@ -93,6 +96,8 @@ module Cosmos
|
|
93
96
|
end
|
94
97
|
|
95
98
|
def read_data(data)
|
99
|
+
return super(data) if (data.length <= 0)
|
100
|
+
|
96
101
|
# Drop all data until the initial_read_delay is complete.
|
97
102
|
# This gets rid of unused welcome messages,
|
98
103
|
# prompts, and other junk on initial connections
|
@@ -27,19 +27,21 @@ module Cosmos
|
|
27
27
|
# @param discard_leading_bytes (see BurstProtocol#initialize)
|
28
28
|
# @param sync_pattern (see BurstProtocol#initialize)
|
29
29
|
# @param fill_fields (see BurstProtocol#initialize)
|
30
|
+
# @param allow_empty_data [true/false/nil] See Protocol#initialize
|
30
31
|
def initialize(
|
31
32
|
write_termination_characters,
|
32
33
|
read_termination_characters,
|
33
34
|
strip_read_termination = true,
|
34
35
|
discard_leading_bytes = 0,
|
35
36
|
sync_pattern = nil,
|
36
|
-
fill_fields = false
|
37
|
+
fill_fields = false,
|
38
|
+
allow_empty_data = nil
|
37
39
|
)
|
38
40
|
@write_termination_characters = write_termination_characters.hex_to_byte_string
|
39
41
|
@read_termination_characters = read_termination_characters.hex_to_byte_string
|
40
42
|
@strip_read_termination = ConfigParser.handle_true_false(strip_read_termination)
|
41
43
|
|
42
|
-
super(discard_leading_bytes, sync_pattern, fill_fields)
|
44
|
+
super(discard_leading_bytes, sync_pattern, fill_fields, allow_empty_data)
|
43
45
|
end
|
44
46
|
|
45
47
|
def write_data(data)
|
@@ -18,6 +18,8 @@ require 'cosmos/packets/parsers/limits_response_parser'
|
|
18
18
|
require 'cosmos/packets/parsers/state_parser'
|
19
19
|
require 'cosmos/packets/parsers/format_string_parser'
|
20
20
|
require 'cosmos/packets/parsers/processor_parser'
|
21
|
+
require 'cosmos/packets/parsers/xtce_parser'
|
22
|
+
require 'cosmos/packets/parsers/xtce_converter'
|
21
23
|
require 'cosmos/conversions'
|
22
24
|
require 'cosmos/processors'
|
23
25
|
require 'nokogiri'
|
@@ -93,7 +95,7 @@ module Cosmos
|
|
93
95
|
def process_file(filename, process_target_name)
|
94
96
|
# Handle .xtce files
|
95
97
|
if File.extname(filename).to_s.downcase == ".xtce"
|
96
|
-
|
98
|
+
XtceParser.process(@commands, @telemetry, @warnings, filename, process_target_name)
|
97
99
|
return
|
98
100
|
end
|
99
101
|
|
@@ -205,33 +207,6 @@ module Cosmos
|
|
205
207
|
finish_packet()
|
206
208
|
end
|
207
209
|
|
208
|
-
# Read in a target definition from a .xtce file
|
209
|
-
def process_xtce(filename, override_target_name = nil)
|
210
|
-
doc = File.open(filename) { |f| Nokogiri::XML(f, nil, nil, Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NOBLANKS) }
|
211
|
-
xtce_process_element(doc.root, 0)
|
212
|
-
@current_target_name = override_target_name if override_target_name
|
213
|
-
doc.root.children.each do |child|
|
214
|
-
xtce_recurse_element(child, 1) do |element, depth|
|
215
|
-
xtce_process_element(element, depth)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
finish_packet()
|
219
|
-
|
220
|
-
# Remove abstract
|
221
|
-
if @commands[@current_target_name]
|
222
|
-
@commands[@current_target_name].delete_if {|packet_name, packet| packet.abstract}
|
223
|
-
end
|
224
|
-
if @telemetry[@current_target_name]
|
225
|
-
@telemetry[@current_target_name].delete_if {|packet_name, packet| packet.abstract}
|
226
|
-
end
|
227
|
-
|
228
|
-
# Reverse order of packets for the target so ids work correctly
|
229
|
-
reverse_packet_order(@current_target_name, @commands)
|
230
|
-
reverse_packet_order(@current_target_name, @telemetry)
|
231
|
-
|
232
|
-
reset_processing_variables()
|
233
|
-
end
|
234
|
-
|
235
210
|
# Convert the PacketConfig back to COSMOS configuration files for each target
|
236
211
|
def to_config(output_dir)
|
237
212
|
FileUtils.mkdir_p(output_dir)
|
@@ -284,832 +259,35 @@ module Cosmos
|
|
284
259
|
end
|
285
260
|
end
|
286
261
|
end
|
287
|
-
|
288
262
|
end # def to_config
|
289
263
|
|
290
|
-
# Convert the PacketConfig into a .xtce file for each target
|
291
264
|
def to_xtce(output_dir)
|
292
|
-
|
293
|
-
|
294
|
-
# Build target list
|
295
|
-
targets = []
|
296
|
-
@telemetry.each { |target_name, packets| targets << target_name }
|
297
|
-
@commands.each { |target_name, packets| targets << target_name }
|
298
|
-
targets.uniq!
|
299
|
-
|
300
|
-
targets.each do |target_name|
|
301
|
-
next if target_name == 'UNKNOWN'
|
302
|
-
|
303
|
-
# Reverse order of packets for the target so things are expected (reverse) order for xtce
|
304
|
-
reverse_packet_order(target_name, @commands)
|
305
|
-
reverse_packet_order(target_name, @telemetry)
|
306
|
-
|
307
|
-
FileUtils.mkdir_p(File.join(output_dir, target_name, 'cmd_tlm'))
|
308
|
-
filename = File.join(output_dir, target_name, 'cmd_tlm', target_name.downcase + '.xtce')
|
309
|
-
begin
|
310
|
-
File.delete(filename)
|
311
|
-
rescue
|
312
|
-
# Doesn't exist
|
313
|
-
end
|
314
|
-
|
315
|
-
# Gather an make unique all the packet items
|
316
|
-
unique_items = {}
|
317
|
-
@telemetry[target_name].each do |packet_name, packet|
|
318
|
-
packet.sorted_items.each do |item|
|
319
|
-
next if item.data_type == :DERIVED
|
320
|
-
unique_items[item.name] ||= []
|
321
|
-
unique_items[item.name] << item
|
322
|
-
end
|
323
|
-
end
|
324
|
-
unique_items.each do |item_name, items|
|
325
|
-
if items.length <= 1
|
326
|
-
unique_items[item_name] = items[0]
|
327
|
-
next
|
328
|
-
end
|
329
|
-
# TODO: need to make sure all the items in the array are exactly the same
|
330
|
-
unique_items[item_name] = items[0]
|
331
|
-
end
|
332
|
-
|
333
|
-
# Gather and make unique all the command parameters
|
334
|
-
unique_arguments = {}
|
335
|
-
@commands[target_name].each do |packet_name, packet|
|
336
|
-
packet.sorted_items.each do |item|
|
337
|
-
next if item.data_type == :DERIVED
|
338
|
-
unique_arguments[item.name] ||= []
|
339
|
-
unique_arguments[item.name] << item
|
340
|
-
end
|
341
|
-
end
|
342
|
-
unique_arguments.each do |item_name, items|
|
343
|
-
if items.length <= 1
|
344
|
-
unique_arguments[item_name] = items[0]
|
345
|
-
next
|
346
|
-
end
|
347
|
-
# TODO: need to make sure all the items in the array are exactly the same
|
348
|
-
unique_arguments[item_name] = items[0]
|
349
|
-
end
|
350
|
-
|
351
|
-
# Create the xtce file for this target
|
352
|
-
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
353
|
-
xml['xtce'].SpaceSystem("xmlns:xtce" => "http://www.omg.org/space/xtce",
|
354
|
-
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
355
|
-
"name" => target_name,
|
356
|
-
"xsi:schemaLocation" => "http://www.omg.org/space/xtce http://www.omg.org/spec/XTCE/20061101/06-11-06.xsd") do
|
357
|
-
xml['xtce'].TelemetryMetaData do
|
358
|
-
xml['xtce'].ParameterTypeSet do
|
359
|
-
unique_items.each do |item_name, item|
|
360
|
-
item.to_xtce_type('Parameter', xml)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
xml['xtce'].ParameterSet do
|
365
|
-
unique_items.each do |item_name, item|
|
366
|
-
item.to_xtce_item('Parameter', xml)
|
367
|
-
end
|
368
|
-
end
|
265
|
+
XtceConverter.convert(@commands, @telemetry, output_dir)
|
266
|
+
end
|
369
267
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
xml['xtce'].ArrayParameterRefEntry(:parameterRef => item.name) do
|
381
|
-
if !packed
|
382
|
-
if item.bit_offset >= 0
|
383
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerStart') do
|
384
|
-
xml['xtce'].FixedValue(item.bit_offset)
|
385
|
-
end
|
386
|
-
else
|
387
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerEnd') do
|
388
|
-
xml['xtce'].FixedValue(-item.bit_offset)
|
389
|
-
end
|
390
|
-
end
|
391
|
-
end
|
392
|
-
xml['xtce'].DimensionList do
|
393
|
-
xml['xtce'].Dimension do
|
394
|
-
xml['xtce'].StartingIndex do
|
395
|
-
xml['xtce'].FixedValue(0)
|
396
|
-
end
|
397
|
-
xml['xtce'].EndingIndex do
|
398
|
-
xml['xtce'].FixedValue((item.array_size / item.bit_size) - 1)
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
else
|
404
|
-
if packed
|
405
|
-
xml['xtce'].ParameterRefEntry(:parameterRef => item.name)
|
406
|
-
else
|
407
|
-
xml['xtce'].ParameterRefEntry(:parameterRef => item.name) do
|
408
|
-
if item.bit_offset >= 0
|
409
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerStart') do
|
410
|
-
xml['xtce'].FixedValue(item.bit_offset)
|
411
|
-
end
|
412
|
-
else
|
413
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerEnd') do
|
414
|
-
xml['xtce'].FixedValue(-item.bit_offset)
|
415
|
-
end
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
end # Abstract SequenceContainer
|
423
|
-
|
424
|
-
attrs = { :name => packet_name }
|
425
|
-
attrs['shortDescription'] = packet.description if packet.description
|
426
|
-
xml['xtce'].SequenceContainer(attrs) do
|
427
|
-
xml['xtce'].EntryList
|
428
|
-
xml['xtce'].BaseContainer(:containerRef => (packet_name + '_Base')) do
|
429
|
-
if packet.id_items and packet.id_items.length > 0
|
430
|
-
xml['xtce'].RestrictionCriteria do
|
431
|
-
xml['xtce'].ComparisonList do
|
432
|
-
packet.id_items.each do |item|
|
433
|
-
xml['xtce'].Comparison(:parameterRef => item.name, :value => item.id_value)
|
434
|
-
end
|
435
|
-
end
|
436
|
-
end
|
437
|
-
end
|
438
|
-
end
|
439
|
-
end # Actual SequenceContainer
|
440
|
-
|
441
|
-
end # @telemetry.each
|
442
|
-
end # ContainerSet
|
443
|
-
end # TelemetryMetaData
|
444
|
-
|
445
|
-
xml['xtce'].CommandMetaData do
|
446
|
-
xml['xtce'].ArgumentTypeSet do
|
447
|
-
unique_arguments.each do |arg_name, arg|
|
448
|
-
arg.to_xtce_type('Argument', xml)
|
449
|
-
end
|
450
|
-
end
|
451
|
-
xml['xtce'].MetaCommandSet do
|
452
|
-
@commands[target_name].each do |packet_name, packet|
|
453
|
-
attrs = { :name => packet_name + "_Base", :abstract => "true" }
|
454
|
-
xml['xtce'].MetaCommand(attrs) do
|
455
|
-
xml['xtce'].ArgumentList do
|
456
|
-
packet.sorted_items.each do |item|
|
457
|
-
next if item.data_type == :DERIVED
|
458
|
-
item.to_xtce_item('Argument', xml)
|
459
|
-
end
|
460
|
-
end # ArgumentList
|
461
|
-
xml['xtce'].CommandContainer(:name => "#{target_name}_#{packet_name}_CommandContainer") do
|
462
|
-
xml['xtce'].EntryList do
|
463
|
-
packed = packet.packed?
|
464
|
-
packet.sorted_items.each do |item|
|
465
|
-
next if item.data_type == :DERIVED
|
466
|
-
if item.array_size
|
467
|
-
xml['xtce'].ArrayArgumentRefEntry(:parameterRef => item.name) do
|
468
|
-
if !packed
|
469
|
-
if item.bit_offset >= 0
|
470
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerStart') do
|
471
|
-
xml['xtce'].FixedValue(item.bit_offset)
|
472
|
-
end
|
473
|
-
else
|
474
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerEnd') do
|
475
|
-
xml['xtce'].FixedValue(-item.bit_offset)
|
476
|
-
end
|
477
|
-
end
|
478
|
-
end
|
479
|
-
xml['xtce'].DimensionList do
|
480
|
-
xml['xtce'].Dimension do
|
481
|
-
xml['xtce'].StartingIndex do
|
482
|
-
xml['xtce'].FixedValue(0)
|
483
|
-
end
|
484
|
-
xml['xtce'].EndingIndex do
|
485
|
-
xml['xtce'].FixedValue((item.array_size / item.bit_size) - 1)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
end
|
489
|
-
end
|
490
|
-
else
|
491
|
-
if packed
|
492
|
-
xml['xtce'].ArgumentRefEntry(:argumentRef => item.name)
|
493
|
-
else
|
494
|
-
xml['xtce'].ArgumentRefEntry(:argumentRef => item.name) do
|
495
|
-
if item.bit_offset >= 0
|
496
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerStart') do
|
497
|
-
xml['xtce'].FixedValue(item.bit_offset)
|
498
|
-
end
|
499
|
-
else
|
500
|
-
xml['xtce'].LocationInContainerInBits(:referenceLocation => 'containerEnd') do
|
501
|
-
xml['xtce'].FixedValue(-item.bit_offset)
|
502
|
-
end
|
503
|
-
end
|
504
|
-
end
|
505
|
-
end
|
506
|
-
end
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end
|
510
|
-
end # Abstract MetaCommand
|
511
|
-
|
512
|
-
attrs = { :name => packet_name }
|
513
|
-
attrs['shortDescription'] = packet.description if packet.description
|
514
|
-
xml['xtce'].MetaCommand(attrs) do
|
515
|
-
xml['xtce'].BaseMetaCommand(:metaCommandRef => packet_name + "_Base") do
|
516
|
-
if packet.id_items and packet.id_items.length > 0
|
517
|
-
xml['xtce'].ArgumentAssignmentList do
|
518
|
-
packet.id_items.each do |item|
|
519
|
-
xml['xtce'].ArgumentAssignment(:argumentName => item.name, :argumentValue => item.id_value)
|
520
|
-
end
|
521
|
-
end # ArgumentAssignmentList
|
522
|
-
end
|
523
|
-
end # BaseMetaCommand
|
524
|
-
end # Actual MetaCommand
|
525
|
-
end # @commands.each
|
526
|
-
end # MetaCommandSet
|
527
|
-
end # CommandMetaData
|
528
|
-
end # SpaceSystem
|
529
|
-
end # builder
|
530
|
-
File.open(filename, 'w') do |file|
|
531
|
-
file.puts builder.to_xml
|
268
|
+
# Add current packet into hash if it exists
|
269
|
+
def finish_packet()
|
270
|
+
finish_item()
|
271
|
+
if @current_packet
|
272
|
+
@warnings += @current_packet.check_bit_offsets
|
273
|
+
if @current_cmd_or_tlm == COMMAND
|
274
|
+
PacketParser.check_item_data_types(@current_packet)
|
275
|
+
@commands[@current_packet.target_name][@current_packet.packet_name] = @current_packet
|
276
|
+
else
|
277
|
+
@telemetry[@current_packet.target_name][@current_packet.packet_name] = @current_packet
|
532
278
|
end
|
279
|
+
@current_packet = nil
|
280
|
+
@current_item = nil
|
533
281
|
end
|
534
282
|
end
|
535
283
|
|
536
284
|
protected
|
537
285
|
|
538
286
|
def reset_processing_variables
|
539
|
-
# Used during packet processing
|
540
287
|
@current_cmd_or_tlm = nil
|
541
288
|
@current_packet = nil
|
542
289
|
@current_item = nil
|
543
290
|
@current_limits_group = nil
|
544
|
-
|
545
|
-
# Used for xtce processing
|
546
|
-
@current_target_name = nil
|
547
|
-
@current_type = nil
|
548
|
-
@current_meta_command = nil
|
549
|
-
@current_parameter = nil
|
550
|
-
@current_argument = nil
|
551
|
-
@parameter_types = {}
|
552
|
-
@argument_types = {}
|
553
|
-
@parameters = {}
|
554
|
-
@arguments = {}
|
555
|
-
@containers = {}
|
556
|
-
end
|
557
|
-
|
558
|
-
def reverse_packet_order(target_name, cmd_or_tlm_hash)
|
559
|
-
if cmd_or_tlm_hash[target_name]
|
560
|
-
packets = []
|
561
|
-
names_to_remove = []
|
562
|
-
cmd_or_tlm_hash[target_name].each do |packet_name, packet|
|
563
|
-
packets << packet
|
564
|
-
names_to_remove << packet_name
|
565
|
-
end
|
566
|
-
cmd_or_tlm_hash[target_name].length.times do |i|
|
567
|
-
cmd_or_tlm_hash[target_name].delete(names_to_remove[i])
|
568
|
-
end
|
569
|
-
packets.reverse.each do |packet|
|
570
|
-
cmd_or_tlm_hash[target_name][packet.packet_name] = packet
|
571
|
-
end
|
572
|
-
end
|
573
|
-
end
|
574
|
-
|
575
|
-
XTCE_IGNORED_ELEMENTS = ['text', 'AliasSet', 'Alias', 'Header']
|
576
|
-
|
577
|
-
def xtce_process_element(element, depth)
|
578
|
-
if XTCE_IGNORED_ELEMENTS.include?(element.name)
|
579
|
-
return false
|
580
|
-
end
|
581
|
-
|
582
|
-
case element.name
|
583
|
-
when 'SpaceSystem'
|
584
|
-
@current_target_name = element["name"].to_s.upcase
|
585
|
-
|
586
|
-
when 'TelemetryMetaData'
|
587
|
-
finish_packet()
|
588
|
-
@current_cmd_or_tlm = TELEMETRY
|
589
|
-
|
590
|
-
when 'CommandMetaData'
|
591
|
-
finish_packet()
|
592
|
-
@current_cmd_or_tlm = COMMAND
|
593
|
-
|
594
|
-
when 'ParameterTypeSet', 'EnumerationList', 'ParameterSet', 'ContainerSet', 'EntryList', 'DefaultCalibrator', 'DefaultAlarm',
|
595
|
-
'RestrictionCriteria', 'ComparisonList', 'MetaCommandSet', 'DefaultCalibrator', 'ArgumentTypeSet', 'ArgumentList', 'ArgumentAssignmentList',
|
596
|
-
'LocationInContainerInBits'
|
597
|
-
|
598
|
-
# Do Nothing
|
599
|
-
|
600
|
-
when 'EnumeratedParameterType', 'EnumeratedArgumentType', 'IntegerParameterType', 'IntegerArgumentType', 'FloatParameterType', 'FloatArgumentType',
|
601
|
-
'StringParameterType', 'StringArgumentType', 'BinaryParameterType', 'BinaryArgumentType'
|
602
|
-
|
603
|
-
@current_type = OpenStruct.new
|
604
|
-
@current_type.endianness = :BIG_ENDIAN
|
605
|
-
element.attributes.each do |att_name, att|
|
606
|
-
@current_type[att.name] = att.value
|
607
|
-
end
|
608
|
-
if element.name =~ /Argument/
|
609
|
-
@argument_types[element["name"]] = @current_type
|
610
|
-
else
|
611
|
-
@parameter_types[element["name"]] = @current_type
|
612
|
-
end
|
613
|
-
|
614
|
-
case element.name
|
615
|
-
when 'EnumeratedParameterType', 'EnumeratedArgumentType'
|
616
|
-
@current_type.xtce_encoding = 'IntegerDataEncoding'
|
617
|
-
@current_type.sizeInBits = 8 # This is undocumented but appears to be the design
|
618
|
-
when 'IntegerParameterType', 'IntegerArgumentType'
|
619
|
-
@current_type.xtce_encoding = 'IntegerDataEncoding'
|
620
|
-
@current_type.sizeInBits = 32
|
621
|
-
when 'FloatParameterType', 'FloatArgumentType'
|
622
|
-
@current_type.xtce_encoding = 'FloatDataEncoding'
|
623
|
-
@current_type.sizeInBits = 32
|
624
|
-
when 'StringParameterType', 'StringArgumentType'
|
625
|
-
@current_type.xtce_encoding = 'StringDataEncoding'
|
626
|
-
when 'BinaryParameterType', 'BinaryArgumentType'
|
627
|
-
@current_type.xtce_encoding = 'BinaryDataEncoding'
|
628
|
-
@current_type.sizeInBits = 8 # This is undocumented but appears to be the design
|
629
|
-
end
|
630
|
-
|
631
|
-
when 'ArrayParameterType', 'ArrayArgumentType'
|
632
|
-
@current_type = OpenStruct.new
|
633
|
-
element.attributes.each do |att_name, att|
|
634
|
-
@current_type[att.name] = att.value
|
635
|
-
end
|
636
|
-
if element.name =~ /Argument/
|
637
|
-
@argument_types[element["name"]] = @current_type
|
638
|
-
else
|
639
|
-
@parameter_types[element["name"]] = @current_type
|
640
|
-
end
|
641
|
-
|
642
|
-
when 'ByteOrderList'
|
643
|
-
byte_list = []
|
644
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
645
|
-
if element.name == 'Byte'
|
646
|
-
if element['byteSignificance']
|
647
|
-
byte_list << element['byteSignificance'].to_i
|
648
|
-
end
|
649
|
-
end
|
650
|
-
true
|
651
|
-
end
|
652
|
-
if byte_list[0] == 0
|
653
|
-
# Little endian will always start with 0 - Its ok if a single byte item is marked little endian
|
654
|
-
@current_type.endianness = :LITTLE_ENDIAN
|
655
|
-
end
|
656
|
-
|
657
|
-
# Verify ordering of byte list is supported
|
658
|
-
if byte_list[0] >= byte_list[-1]
|
659
|
-
ordered_byte_list = byte_list.reverse
|
660
|
-
else
|
661
|
-
ordered_byte_list = byte_list.clone
|
662
|
-
end
|
663
|
-
if ordered_byte_list[0] != 0
|
664
|
-
msg = "Invalid ByteOrderList detected: #{byte_list.join(", ")}"
|
665
|
-
Logger.instance.warn msg
|
666
|
-
@warnings << msg
|
667
|
-
else
|
668
|
-
previous_byte = nil
|
669
|
-
ordered_byte_list.each do |byte|
|
670
|
-
if previous_byte
|
671
|
-
if byte - previous_byte != 1
|
672
|
-
msg = "Invalid ByteOrderList detected: #{byte_list.join(", ")}"
|
673
|
-
Logger.instance.warn msg
|
674
|
-
@warnings << msg
|
675
|
-
break
|
676
|
-
end
|
677
|
-
end
|
678
|
-
previous_byte = byte
|
679
|
-
end
|
680
|
-
end
|
681
|
-
|
682
|
-
return false # Already recursed
|
683
|
-
|
684
|
-
when "SizeInBits"
|
685
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
686
|
-
if element.name == 'FixedValue'
|
687
|
-
@current_type.sizeInBits = Integer(element.text)
|
688
|
-
false
|
689
|
-
else
|
690
|
-
true
|
691
|
-
end
|
692
|
-
end
|
693
|
-
return false # Already recursed
|
694
|
-
|
695
|
-
when 'UnitSet'
|
696
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
697
|
-
if element.name == 'Unit'
|
698
|
-
@current_type.units ||= ''
|
699
|
-
if @current_type.units.empty?
|
700
|
-
@current_type.units << element.text.to_s
|
701
|
-
else
|
702
|
-
@current_type.units << ('/' + element.text.to_s)
|
703
|
-
end
|
704
|
-
@current_type.units << "^#{element['power']}" if element['power']
|
705
|
-
@current_type.units_full ||= ''
|
706
|
-
description = element['description'].to_s
|
707
|
-
if description.empty?
|
708
|
-
@current_type.units_full = @current_type.units
|
709
|
-
else
|
710
|
-
if @current_type.units_full.empty?
|
711
|
-
@current_type.units_full << description
|
712
|
-
else
|
713
|
-
@current_type.units_full << ('/' + description)
|
714
|
-
end
|
715
|
-
end
|
716
|
-
end
|
717
|
-
true
|
718
|
-
end
|
719
|
-
return false # Already recursed
|
720
|
-
|
721
|
-
when 'PolynomialCalibrator'
|
722
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
723
|
-
if element.name == 'Term'
|
724
|
-
index = Float(element['exponent']).to_i
|
725
|
-
coeff = Float(element['coefficient'])
|
726
|
-
@current_type.conversion ||= PolynomialConversion.new([])
|
727
|
-
@current_type.conversion.coeffs[index] = coeff
|
728
|
-
@current_type.conversion.coeffs.each_with_index do |value, index|
|
729
|
-
@current_type.conversion.coeffs[index] = 0.0 if value.nil?
|
730
|
-
end
|
731
|
-
end
|
732
|
-
true
|
733
|
-
end
|
734
|
-
return false # Already recursed
|
735
|
-
|
736
|
-
when 'StaticAlarmRanges'
|
737
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
738
|
-
if element.name == 'WarningRange'
|
739
|
-
@current_type.limits ||= [0.0, 0.0, 0.0, 0.0]
|
740
|
-
@current_type.limits[1] = Float(element['minInclusive']) if element['minInclusive']
|
741
|
-
@current_type.limits[2] = Float(element['maxInclusive']) if element['maxInclusive']
|
742
|
-
elsif element.name == 'CriticalRange'
|
743
|
-
@current_type.limits ||= [0.0, 0.0, 0.0, 0.0]
|
744
|
-
@current_type.limits[0] = Float(element['minInclusive']) if element['minInclusive']
|
745
|
-
@current_type.limits[3] = Float(element['maxInclusive']) if element['maxInclusive']
|
746
|
-
end
|
747
|
-
true
|
748
|
-
end
|
749
|
-
return false # Already recursed
|
750
|
-
|
751
|
-
when "ValidRange"
|
752
|
-
@current_type.minInclusive = element['minInclusive']
|
753
|
-
@current_type.maxInclusive = element['maxInclusive']
|
754
|
-
|
755
|
-
when 'Enumeration'
|
756
|
-
@current_type.states ||= {}
|
757
|
-
@current_type.states[element['label']] = Integer(element['value'])
|
758
|
-
|
759
|
-
when 'IntegerDataEncoding', 'FloatDataEncoding', 'StringDataEncoding', 'BinaryDataEncoding'
|
760
|
-
@current_type.xtce_encoding = element.name
|
761
|
-
element.attributes.each do |att_name, att|
|
762
|
-
@current_type[att.name] = att.value
|
763
|
-
end
|
764
|
-
@current_type.sizeInBits = 8 unless element.attributes['sizeInBits']
|
765
|
-
|
766
|
-
when 'Parameter'
|
767
|
-
@current_parameter = OpenStruct.new
|
768
|
-
element.attributes.each do |att_name, att|
|
769
|
-
@current_parameter[att.name] = att.value
|
770
|
-
end
|
771
|
-
@parameters[element["name"]] = @current_parameter
|
772
|
-
|
773
|
-
when 'Argument'
|
774
|
-
@current_argument = OpenStruct.new
|
775
|
-
element.attributes.each do |att_name, att|
|
776
|
-
@current_argument[att.name] = att.value
|
777
|
-
end
|
778
|
-
@arguments[element["name"]] = @current_argument
|
779
|
-
|
780
|
-
when 'ParameterProperties'
|
781
|
-
element.attributes.each do |att_name, att|
|
782
|
-
@current_parameter[att.name] = att.value
|
783
|
-
end
|
784
|
-
|
785
|
-
when "SequenceContainer"
|
786
|
-
finish_packet()
|
787
|
-
@current_packet = Packet.new(@current_target_name, element['name'], :BIG_ENDIAN, element['shortDescription'])
|
788
|
-
@current_packet.abstract = ConfigParser.handle_true_false_nil(element['abstract'])
|
789
|
-
@containers[element['name']] = @current_packet
|
790
|
-
PacketParser.finish_create_telemetry(@current_packet, @telemetry, @latest_data, @warnings)
|
791
|
-
|
792
|
-
# Need to check for a BaseContainer now because if we hit it later it will be too late
|
793
|
-
xtce_handle_base_container('BaseContainer', element)
|
794
|
-
|
795
|
-
when 'LongDescription'
|
796
|
-
if @current_packet and !@current_packet.description
|
797
|
-
@current_packet.description = element.text
|
798
|
-
end
|
799
|
-
|
800
|
-
when 'ParameterRefEntry', 'ArgumentRefEntry', 'ArrayParameterRefEntry', 'ArrayArgumentRefEntry'
|
801
|
-
reference_location, bit_offset = xtce_handle_location_in_container_in_bits(element)
|
802
|
-
|
803
|
-
array_type = nil
|
804
|
-
array_bit_size = nil
|
805
|
-
if element.name =~ /Parameter/
|
806
|
-
# Look up the parameter and parameter type
|
807
|
-
parameter = @parameters[element['parameterRef']]
|
808
|
-
raise "parameterRef #{element['parameterRef']} not found" unless parameter
|
809
|
-
parameter_type = @parameter_types[parameter.parameterTypeRef]
|
810
|
-
raise "parameterTypeRef #{parameter.parameterTypeRef} not found" unless parameter_type
|
811
|
-
if element.name == 'ArrayParameterRefEntry'
|
812
|
-
array_type = parameter_type
|
813
|
-
parameter_type = @parameter_types[array_type.arrayTypeRef]
|
814
|
-
raise "arrayTypeRef #{parameter.arrayTypeRef} not found" unless parameter_type
|
815
|
-
end
|
816
|
-
refName = 'parameterRef'
|
817
|
-
object = parameter
|
818
|
-
type = parameter_type
|
819
|
-
else
|
820
|
-
# Look up the argument and argument type
|
821
|
-
if element.name == 'ArrayArgumentRefEntry'
|
822
|
-
# Requiring parameterRef for argument arrays appears to be a defect in the schema
|
823
|
-
argument = @arguments[element['parameterRef']]
|
824
|
-
raise "parameterRef #{element['parameterRef']} not found" unless argument
|
825
|
-
argument_type = @argument_types[argument.argumentTypeRef]
|
826
|
-
raise "argumentTypeRef #{argument.argumentTypeRef} not found" unless argument_type
|
827
|
-
array_type = argument_type
|
828
|
-
argument_type = @argument_types[array_type.arrayTypeRef]
|
829
|
-
raise "arrayTypeRef #{array_type.arrayTypeRef} not found" unless argument_type
|
830
|
-
refName = 'parameterRef'
|
831
|
-
else
|
832
|
-
argument = @arguments[element['argumentRef']]
|
833
|
-
raise "argumentRef #{element['argumentRef']} not found" unless argument
|
834
|
-
argument_type = @argument_types[argument.argumentTypeRef]
|
835
|
-
raise "argumentTypeRef #{argument.argumentTypeRef} not found" unless argument_type
|
836
|
-
refName = 'argumentRef'
|
837
|
-
end
|
838
|
-
object = argument
|
839
|
-
type = argument_type
|
840
|
-
end
|
841
|
-
|
842
|
-
bit_size = Integer(type.sizeInBits)
|
843
|
-
|
844
|
-
if array_type
|
845
|
-
array_num_items = 1
|
846
|
-
# Need to determine dimensions
|
847
|
-
xtce_recurse_element(element, depth + 1) do |element, depth|
|
848
|
-
if element.name == 'Dimension'
|
849
|
-
starting_index = 0
|
850
|
-
ending_index = 0
|
851
|
-
element.children.each do |child_element|
|
852
|
-
if child_element.name == 'StartingIndex'
|
853
|
-
child_element.children.each do |child_element2|
|
854
|
-
if child_element2.name == 'FixedValue'
|
855
|
-
starting_index = child_element2.text.to_i
|
856
|
-
end
|
857
|
-
end
|
858
|
-
elsif child_element.name == 'EndingIndex'
|
859
|
-
child_element.children.each do |child_element2|
|
860
|
-
if child_element2.name == 'FixedValue'
|
861
|
-
ending_index = child_element2.text.to_i
|
862
|
-
end
|
863
|
-
end
|
864
|
-
array_num_items *= ((ending_index - starting_index).abs + 1)
|
865
|
-
end
|
866
|
-
false # Don't recurse again
|
867
|
-
end
|
868
|
-
false # Don't recurse again
|
869
|
-
else
|
870
|
-
true # Keep recursing
|
871
|
-
end
|
872
|
-
end
|
873
|
-
array_bit_size = array_num_items * bit_size
|
874
|
-
end
|
875
|
-
|
876
|
-
# Add item to packet
|
877
|
-
data_type = nil
|
878
|
-
case type.xtce_encoding
|
879
|
-
when 'IntegerDataEncoding'
|
880
|
-
if type.signed == 'false' or type.encoding == 'unsigned'
|
881
|
-
data_type = :UINT
|
882
|
-
else
|
883
|
-
data_type = :INT
|
884
|
-
end
|
885
|
-
when 'FloatDataEncoding'
|
886
|
-
data_type = :FLOAT
|
887
|
-
when 'StringDataEncoding'
|
888
|
-
data_type = :STRING
|
889
|
-
when 'BinaryDataEncoding'
|
890
|
-
data_type = :BLOCK
|
891
|
-
else
|
892
|
-
raise "Referenced Parameter/Argument has no xtce_encoding: #{element[refName]}"
|
893
|
-
end
|
894
|
-
|
895
|
-
if bit_offset
|
896
|
-
case reference_location
|
897
|
-
when 'containerStart'
|
898
|
-
item = @current_packet.define_item(object.name, bit_offset, bit_size, data_type, array_bit_size, type.endianness) # overflow = :ERROR, format_string = nil, read_conversion = nil, write_conversion = nil, id_value = nil)
|
899
|
-
when 'containerEnd'
|
900
|
-
item = @current_packet.define_item(object.name, -bit_offset, bit_size, data_type, array_bit_size, type.endianness) # overflow = :ERROR, format_string = nil, read_conversion = nil, write_conversion = nil, id_value = nil)
|
901
|
-
when 'previousEntry', nil
|
902
|
-
item = @current_packet.define_item(object.name, @current_packet.length + bit_offset, bit_size, data_type, array_bit_size, type.endianness) # overflow = :ERROR, format_string = nil, read_conversion = nil, write_conversion = nil, id_value = nil)
|
903
|
-
when 'nextEntry'
|
904
|
-
raise 'nextEntry is not supported'
|
905
|
-
end
|
906
|
-
else
|
907
|
-
item = @current_packet.append_item(object.name, bit_size, data_type, array_bit_size, type.endianness) # overflow = :ERROR, format_string = nil, read_conversion = nil, write_conversion = nil, id_value = nil)
|
908
|
-
end
|
909
|
-
|
910
|
-
item.description = type.shortDescription if type.shortDescription
|
911
|
-
if type.states
|
912
|
-
item.states = type.states
|
913
|
-
end
|
914
|
-
if type.units and type.units_full
|
915
|
-
item.units = type.units
|
916
|
-
item.units_full = type.units_full
|
917
|
-
end
|
918
|
-
if @current_cmd_or_tlm == COMMAND
|
919
|
-
# Possibly add write conversion
|
920
|
-
if type.conversion and type.conversion.class == PolynomialConversion
|
921
|
-
item.write_conversion = type.conversion
|
922
|
-
end
|
923
|
-
|
924
|
-
# Need to set min, max, and default
|
925
|
-
if data_type == :INT or data_type == :UINT
|
926
|
-
if data_type == :INT
|
927
|
-
item.range = (-(2 ** (Integer(type.sizeInBits) - 1)))..((2 ** (Integer(type.sizeInBits) - 1)) - 1)
|
928
|
-
else
|
929
|
-
item.range = 0..((2 ** Integer(type.sizeInBits)) - 1)
|
930
|
-
end
|
931
|
-
if type.minInclusive and type.maxInclusive
|
932
|
-
item.range = Integer(type.minInclusive)..Integer(type.maxInclusive)
|
933
|
-
end
|
934
|
-
if item.array_size
|
935
|
-
item.default = []
|
936
|
-
else
|
937
|
-
item.default = 0
|
938
|
-
if item.states and item.states[type.initialValue.to_s.upcase]
|
939
|
-
item.default = Integer(item.states[type.initialValue.to_s.upcase])
|
940
|
-
else
|
941
|
-
item.default = Integer(type.initialValue) if type.initialValue
|
942
|
-
end
|
943
|
-
end
|
944
|
-
elsif data_type == :FLOAT
|
945
|
-
if Integer(type.sizeInBits) == 32
|
946
|
-
item.range = -3.402823e38..3.402823e38
|
947
|
-
else
|
948
|
-
item.range = -Float::MAX..Float::MAX
|
949
|
-
end
|
950
|
-
if type.minInclusive and type.maxInclusive
|
951
|
-
item.range = Float(type.minInclusive)..Float(type.maxInclusive)
|
952
|
-
end
|
953
|
-
if item.array_size
|
954
|
-
item.default = []
|
955
|
-
else
|
956
|
-
item.default = 0.0
|
957
|
-
item.default = Float(type.initialValue) if type.initialValue
|
958
|
-
end
|
959
|
-
elsif data_type == :STRING
|
960
|
-
if item.array_size
|
961
|
-
item.default = []
|
962
|
-
else
|
963
|
-
if type.initialValue
|
964
|
-
item.default = type.initialValue
|
965
|
-
else
|
966
|
-
item.default = ''
|
967
|
-
end
|
968
|
-
end
|
969
|
-
elsif data_type == :BLOCK
|
970
|
-
if item.array_size
|
971
|
-
item.default = []
|
972
|
-
else
|
973
|
-
if type.initialValue
|
974
|
-
item.default = type.initialValue
|
975
|
-
else
|
976
|
-
item.default = ''
|
977
|
-
end
|
978
|
-
end
|
979
|
-
end
|
980
|
-
else
|
981
|
-
# Possibly add read conversion
|
982
|
-
if type.conversion and type.conversion.class == PolynomialConversion
|
983
|
-
item.read_conversion = type.conversion
|
984
|
-
end
|
985
|
-
|
986
|
-
# Possibly add default limits
|
987
|
-
if type.limits
|
988
|
-
item.limits.enabled = true
|
989
|
-
values = {}
|
990
|
-
values[:DEFAULT] = type.limits
|
991
|
-
item.limits.values = values
|
992
|
-
end
|
993
|
-
end
|
994
|
-
|
995
|
-
return false # Already recursed
|
996
|
-
|
997
|
-
when 'BaseContainer'
|
998
|
-
# Handled in SequenceContainer/CommandContainer
|
999
|
-
|
1000
|
-
when 'BaseMetaCommand'
|
1001
|
-
# Handled in MetaCommand
|
1002
|
-
|
1003
|
-
when 'Comparison'
|
1004
|
-
# Need to set ID value for item
|
1005
|
-
item = @current_packet.get_item(element['parameterRef'])
|
1006
|
-
item.id_value = Integer(element['value'])
|
1007
|
-
if @current_cmd_or_tlm == COMMAND
|
1008
|
-
item.default = item.id_value
|
1009
|
-
end
|
1010
|
-
@current_packet.update_id_items(item)
|
1011
|
-
|
1012
|
-
when 'MetaCommand'
|
1013
|
-
finish_packet()
|
1014
|
-
@current_packet = Packet.new(@current_target_name, element['name'], :BIG_ENDIAN, element['shortDescription'])
|
1015
|
-
@current_packet.abstract = ConfigParser.handle_true_false_nil(element['abstract'])
|
1016
|
-
PacketParser.finish_create_command(@current_packet, @commands, @warnings)
|
1017
|
-
|
1018
|
-
# Need to check for a BaseContainer now because if we hit it later it will be too late
|
1019
|
-
xtce_handle_base_container('BaseMetaCommand', element)
|
1020
|
-
|
1021
|
-
when 'CommandContainer'
|
1022
|
-
@containers[element['name']] = @current_packet
|
1023
|
-
|
1024
|
-
# Need to check for a BaseContainer now because if we hit it later it will be too late
|
1025
|
-
xtce_handle_base_container('BaseContainer', element)
|
1026
|
-
|
1027
|
-
when 'ArgumentAssignment'
|
1028
|
-
# Need to set ID value for item
|
1029
|
-
item = @current_packet.get_item(element['argumentName'])
|
1030
|
-
value = element['argumentValue']
|
1031
|
-
if item.states and item.states[value.to_s.upcase]
|
1032
|
-
item.id_value = item.states[value.to_s.upcase]
|
1033
|
-
item.default = item.id_value
|
1034
|
-
else
|
1035
|
-
item.id_value = Integer(value)
|
1036
|
-
item.default = item.id_value
|
1037
|
-
end
|
1038
|
-
@current_packet.update_id_items(item)
|
1039
|
-
|
1040
|
-
else
|
1041
|
-
puts " Ignoring Unknown: <#{element.name}>"
|
1042
|
-
|
1043
|
-
end # case element.name
|
1044
|
-
|
1045
|
-
return true # Recurse further
|
1046
|
-
end
|
1047
|
-
|
1048
|
-
def xtce_format_attributes(element)
|
1049
|
-
string = ''
|
1050
|
-
element.attributes.each do |att_name, att|
|
1051
|
-
string << "#{att.name}:#{att.value} "
|
1052
|
-
end
|
1053
|
-
if string.length > 0
|
1054
|
-
string = '( ' + string + ')'
|
1055
|
-
end
|
1056
|
-
return string
|
1057
|
-
end
|
1058
|
-
|
1059
|
-
def xtce_recurse_element(element, depth, &block)
|
1060
|
-
return unless yield(element, depth)
|
1061
|
-
element.children.each do |child_element|
|
1062
|
-
xtce_recurse_element(child_element, depth + 1, &block)
|
1063
|
-
end
|
1064
|
-
end
|
1065
|
-
|
1066
|
-
def xtce_handle_base_container(base_name, element)
|
1067
|
-
if element.name == base_name
|
1068
|
-
# Need to add BaseContainer items to current_packet
|
1069
|
-
# Lookup the base packet
|
1070
|
-
if base_name == 'BaseMetaCommand'
|
1071
|
-
base_packet = @commands[@current_packet.target_name][element['metaCommandRef'].to_s.upcase]
|
1072
|
-
else
|
1073
|
-
base_packet = @containers[element['containerRef']]
|
1074
|
-
end
|
1075
|
-
if base_packet
|
1076
|
-
count = 0
|
1077
|
-
base_packet.sorted_items.each do |item|
|
1078
|
-
unless ['RECEIVED_TIMESECONDS', 'RECEIVED_TIMEFORMATTED', 'RECEIVED_COUNT'].include?(item.name)
|
1079
|
-
begin
|
1080
|
-
@current_packet.get_item(item.name)
|
1081
|
-
rescue
|
1082
|
-
# Item hasn't already been added so define it
|
1083
|
-
@current_packet.define(item.clone)
|
1084
|
-
count += 1
|
1085
|
-
end
|
1086
|
-
end
|
1087
|
-
end
|
1088
|
-
return
|
1089
|
-
else
|
1090
|
-
if base_name == 'BaseMetaCommand'
|
1091
|
-
raise "Unknown #{base_name}: #{element['metaCommandRef']}"
|
1092
|
-
else
|
1093
|
-
raise "Unknown #{base_name}: #{element['containerRef']}"
|
1094
|
-
end
|
1095
|
-
end
|
1096
|
-
end
|
1097
|
-
element.children.each do |child_element|
|
1098
|
-
xtce_handle_base_container(base_name, child_element)
|
1099
|
-
end
|
1100
|
-
end
|
1101
|
-
|
1102
|
-
def xtce_handle_location_in_container_in_bits(element)
|
1103
|
-
element.children.each do |child_element|
|
1104
|
-
if child_element.name == 'LocationInContainerInBits'
|
1105
|
-
child_element.children.each do |child_element2|
|
1106
|
-
if child_element2.name == 'FixedValue'
|
1107
|
-
return [child_element['referenceLocation'], Integer(child_element2.text)]
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
end
|
1111
|
-
end
|
1112
|
-
return [nil, nil]
|
1113
291
|
end
|
1114
292
|
|
1115
293
|
def process_current_packet(parser, keyword, params)
|
@@ -1352,22 +530,6 @@ module Cosmos
|
|
1352
530
|
end
|
1353
531
|
end
|
1354
532
|
|
1355
|
-
# Add current packet into hash if it exists
|
1356
|
-
def finish_packet
|
1357
|
-
finish_item()
|
1358
|
-
if @current_packet
|
1359
|
-
@warnings += @current_packet.check_bit_offsets
|
1360
|
-
if @current_cmd_or_tlm == COMMAND
|
1361
|
-
PacketParser.check_item_data_types(@current_packet)
|
1362
|
-
@commands[@current_packet.target_name][@current_packet.packet_name] = @current_packet
|
1363
|
-
else
|
1364
|
-
@telemetry[@current_packet.target_name][@current_packet.packet_name] = @current_packet
|
1365
|
-
end
|
1366
|
-
@current_packet = nil
|
1367
|
-
@current_item = nil
|
1368
|
-
end
|
1369
|
-
end
|
1370
|
-
|
1371
533
|
def start_item(parser)
|
1372
534
|
finish_item()
|
1373
535
|
@current_item = PacketItemParser.parse(parser, @current_packet, @current_cmd_or_tlm)
|
@@ -1387,7 +549,5 @@ module Cosmos
|
|
1387
549
|
@current_item = nil
|
1388
550
|
end
|
1389
551
|
end
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
end # module Cosmos
|
552
|
+
end
|
553
|
+
end
|