openc3 6.9.2 → 6.10.0
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/data/config/command_modifiers.yaml +79 -0
- data/data/config/item_modifiers.yaml +5 -0
- data/data/config/parameter_modifiers.yaml +5 -0
- data/data/config/telemetry_modifiers.yaml +79 -0
- data/ext/openc3/ext/packet/packet.c +9 -0
- data/lib/openc3/accessors/accessor.rb +27 -3
- data/lib/openc3/accessors/binary_accessor.rb +21 -4
- data/lib/openc3/accessors/template_accessor.rb +3 -2
- data/lib/openc3/api/cmd_api.rb +7 -3
- data/lib/openc3/api/tlm_api.rb +17 -7
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +19 -13
- data/lib/openc3/io/json_rpc.rb +6 -0
- data/lib/openc3/microservices/decom_microservice.rb +97 -17
- data/lib/openc3/microservices/interface_decom_common.rb +32 -0
- data/lib/openc3/microservices/interface_microservice.rb +3 -75
- data/lib/openc3/microservices/queue_microservice.rb +16 -1
- data/lib/openc3/migrations/20251022000000_remove_unique_id.rb +23 -0
- data/lib/openc3/models/plugin_model.rb +7 -1
- data/lib/openc3/models/queue_model.rb +32 -5
- data/lib/openc3/models/reaction_model.rb +25 -9
- data/lib/openc3/models/target_model.rb +78 -10
- data/lib/openc3/packets/commands.rb +33 -7
- data/lib/openc3/packets/packet.rb +75 -71
- data/lib/openc3/packets/packet_config.rb +78 -29
- data/lib/openc3/packets/packet_item.rb +11 -103
- data/lib/openc3/packets/parsers/packet_item_parser.rb +177 -34
- data/lib/openc3/packets/parsers/xtce_converter.rb +2 -2
- data/lib/openc3/packets/structure.rb +29 -21
- data/lib/openc3/packets/structure_item.rb +31 -19
- data/lib/openc3/packets/telemetry.rb +37 -11
- data/lib/openc3/script/suite_results.rb +2 -2
- data/lib/openc3/subpacketizers/subpacketizer.rb +18 -0
- data/lib/openc3/system/target.rb +3 -32
- data/lib/openc3/tools/table_manager/table_config.rb +9 -1
- data/lib/openc3/tools/table_manager/table_item_parser.rb +2 -2
- data/lib/openc3/top_level.rb +45 -19
- data/lib/openc3/topics/decom_interface_topic.rb +31 -0
- data/lib/openc3/utilities/env_helper.rb +10 -0
- data/lib/openc3/utilities/logger.rb +7 -11
- data/lib/openc3/version.rb +6 -6
- data/tasks/spec.rake +2 -1
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/widget/package.json +2 -2
- metadata +4 -1
|
@@ -33,16 +33,17 @@ module OpenC3
|
|
|
33
33
|
# @param packet [Packet] The packet the item should be added to
|
|
34
34
|
# @param cmd_or_tlm [String] Whether this is a command or telemetry packet
|
|
35
35
|
# @param warnings [Array<String>] Array of warning strings from PacketConfig
|
|
36
|
-
def self.parse(parser, packet, cmd_or_tlm, warnings)
|
|
37
|
-
parser = PacketItemParser.new(parser, warnings)
|
|
36
|
+
def self.parse(parser, packet_config, packet, cmd_or_tlm, warnings)
|
|
37
|
+
parser = PacketItemParser.new(parser, packet_config, warnings)
|
|
38
38
|
parser.verify_parameters(cmd_or_tlm)
|
|
39
39
|
parser.create_packet_item(packet, cmd_or_tlm)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# @param parser [ConfigParser] Configuration parser
|
|
43
43
|
# @param warnings [Array<String>] Array of warning strings from PacketConfig
|
|
44
|
-
def initialize(parser, warnings)
|
|
44
|
+
def initialize(parser, packet_config, warnings)
|
|
45
45
|
@parser = parser
|
|
46
|
+
@packet_config = packet_config
|
|
46
47
|
@warnings = warnings
|
|
47
48
|
@usage = get_usage()
|
|
48
49
|
end
|
|
@@ -57,8 +58,12 @@ module OpenC3
|
|
|
57
58
|
# The usage is formatted with brackets <XXX> around each option so
|
|
58
59
|
# count the number of open brackets to determine the number of options
|
|
59
60
|
max_options = @usage.count("<")
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
if @parser.keyword.include?('STRUCTURE')
|
|
62
|
+
@parser.verify_num_parameters(max_options, max_options, @usage)
|
|
63
|
+
else
|
|
64
|
+
# The last two options (description and endianness) are optional
|
|
65
|
+
@parser.verify_num_parameters(max_options - 2, max_options, @usage)
|
|
66
|
+
end
|
|
62
67
|
@parser.verify_parameter_naming(1) # Item name is the 1st parameter
|
|
63
68
|
end
|
|
64
69
|
|
|
@@ -69,24 +74,38 @@ module OpenC3
|
|
|
69
74
|
Logger.instance.warn msg
|
|
70
75
|
@warnings << msg
|
|
71
76
|
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
item
|
|
77
|
+
if @parser.keyword.include?("STRUCTURE")
|
|
78
|
+
item = PacketItem.new(item_name,
|
|
79
|
+
get_bit_offset(),
|
|
80
|
+
get_bit_size(true),
|
|
81
|
+
:BLOCK,
|
|
82
|
+
:BIG_ENDIAN,
|
|
83
|
+
nil,
|
|
84
|
+
:ERROR) # overflow
|
|
85
|
+
else
|
|
86
|
+
item = PacketItem.new(item_name,
|
|
87
|
+
get_bit_offset(),
|
|
88
|
+
get_bit_size(),
|
|
89
|
+
get_data_type(),
|
|
90
|
+
get_endianness(packet),
|
|
91
|
+
get_array_size(),
|
|
92
|
+
:ERROR) # overflow
|
|
93
|
+
if cmd_or_tlm == PacketConfig::COMMAND
|
|
94
|
+
item.range = get_range()
|
|
95
|
+
item.default = get_default()
|
|
96
|
+
end
|
|
97
|
+
item.id_value = get_id_value(item)
|
|
98
|
+
item.description = get_description()
|
|
82
99
|
end
|
|
83
|
-
item.id_value = get_id_value(item)
|
|
84
|
-
item.description = get_description()
|
|
85
100
|
if append?
|
|
86
101
|
item = packet.append(item)
|
|
87
102
|
else
|
|
88
103
|
item = packet.define(item)
|
|
89
104
|
end
|
|
105
|
+
if @parser.keyword.include?("STRUCTURE")
|
|
106
|
+
structure = lookup_packet(get_cmd_or_tlm(), get_target_name(), get_packet_name())
|
|
107
|
+
packet.structurize_item(item, structure)
|
|
108
|
+
end
|
|
90
109
|
item
|
|
91
110
|
end
|
|
92
111
|
|
|
@@ -108,9 +127,15 @@ module OpenC3
|
|
|
108
127
|
raise @parser.error(e, @usage)
|
|
109
128
|
end
|
|
110
129
|
|
|
111
|
-
def get_bit_size
|
|
130
|
+
def get_bit_size(check_structure = false)
|
|
112
131
|
index = append? ? 1 : 2
|
|
113
|
-
|
|
132
|
+
bit_size = @parser.parameters[index]
|
|
133
|
+
if not check_structure or bit_size.to_s.upcase != 'DEFINED'
|
|
134
|
+
return Integer(bit_size)
|
|
135
|
+
else
|
|
136
|
+
structure = lookup_packet(get_cmd_or_tlm(), get_target_name(), get_packet_name())
|
|
137
|
+
return structure.defined_length_bits
|
|
138
|
+
end
|
|
114
139
|
rescue => e
|
|
115
140
|
raise @parser.error(e, @usage)
|
|
116
141
|
end
|
|
@@ -152,7 +177,7 @@ module OpenC3
|
|
|
152
177
|
return nil if @parser.keyword.include?('ARRAY')
|
|
153
178
|
|
|
154
179
|
data_type = get_data_type()
|
|
155
|
-
return nil
|
|
180
|
+
return nil unless data_type == :INT or data_type == :UINT or data_type == :FLOAT
|
|
156
181
|
|
|
157
182
|
index = append? ? 3 : 4
|
|
158
183
|
return nil if @parser.parameters[index] == 'nil'
|
|
@@ -165,6 +190,31 @@ module OpenC3
|
|
|
165
190
|
min..max
|
|
166
191
|
end
|
|
167
192
|
|
|
193
|
+
def get_cmd_or_tlm
|
|
194
|
+
index = append? ? 2 : 3
|
|
195
|
+
cmd_or_tlm = @parser.parameters[index].to_s.upcase.intern
|
|
196
|
+
raise ArgumentError, "Unknown type: #{cmd_or_tlm}" unless %i(CMD TLM COMMAND TELEMETRY).include?(cmd_or_tlm)
|
|
197
|
+
cmd_or_tlm
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def get_target_name
|
|
201
|
+
index = append? ? 3 : 4
|
|
202
|
+
@parser.parameters[index].to_s.upcase
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def get_packet_name
|
|
206
|
+
index = append? ? 4 : 5
|
|
207
|
+
@parser.parameters[index].to_s.upcase
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def lookup_packet(cmd_or_tlm, target_name, packet_name)
|
|
211
|
+
if cmd_or_tlm == :CMD or cmd_or_tlm == :COMMAND
|
|
212
|
+
return @packet_config.commands[target_name][packet_name]
|
|
213
|
+
else
|
|
214
|
+
return @packet_config.telemetry[target_name][packet_name]
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
168
218
|
def convert_string_value(index)
|
|
169
219
|
# If the default value is 0x<data> (no quotes), it is treated as
|
|
170
220
|
# binary data. Otherwise, the default value is considered to be a string.
|
|
@@ -182,8 +232,52 @@ module OpenC3
|
|
|
182
232
|
|
|
183
233
|
index = append? ? 3 : 4
|
|
184
234
|
data_type = get_data_type()
|
|
185
|
-
|
|
186
|
-
|
|
235
|
+
if data_type == :BOOL
|
|
236
|
+
value = @parser.parameters[index].to_s.upcase
|
|
237
|
+
if value == "TRUE" or value == "FALSE"
|
|
238
|
+
return ConfigParser.handle_true_false(@parser.parameters[index])
|
|
239
|
+
else
|
|
240
|
+
raise @parser.error("Default for BOOL data type must be TRUE or FALSE")
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
if data_type == :ARRAY
|
|
244
|
+
value = @parser.parameters[index].to_s
|
|
245
|
+
begin
|
|
246
|
+
value = JSON.parse(value, allow_nan: true)
|
|
247
|
+
rescue Exception
|
|
248
|
+
raise @parser.error("Unparsable value for ARRAY: #{value}")
|
|
249
|
+
end
|
|
250
|
+
if Array === value
|
|
251
|
+
return value
|
|
252
|
+
else
|
|
253
|
+
raise @parser.error("Default for ARRAY data type must be an Array")
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
if data_type == :OBJECT
|
|
257
|
+
value = @parser.parameters[index].to_s
|
|
258
|
+
begin
|
|
259
|
+
value = JSON.parse(value, allow_nan: true)
|
|
260
|
+
rescue Exception
|
|
261
|
+
raise @parser.error("Unparsable value for OBJECT: #{value}")
|
|
262
|
+
end
|
|
263
|
+
if Hash === value
|
|
264
|
+
return value
|
|
265
|
+
else
|
|
266
|
+
raise @parser.error("Default for OBJECT data type must be a Hash")
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
if data_type == :ANY
|
|
270
|
+
value = @parser.parameters[index].to_s
|
|
271
|
+
if value.length > 0
|
|
272
|
+
begin
|
|
273
|
+
return JSON.parse(value, allow_nan: true)
|
|
274
|
+
rescue Exception
|
|
275
|
+
return value
|
|
276
|
+
end
|
|
277
|
+
else
|
|
278
|
+
return ""
|
|
279
|
+
end
|
|
280
|
+
end
|
|
187
281
|
if data_type == :STRING or data_type == :BLOCK
|
|
188
282
|
return convert_string_value(index)
|
|
189
283
|
else
|
|
@@ -209,6 +303,52 @@ module OpenC3
|
|
|
209
303
|
end
|
|
210
304
|
|
|
211
305
|
index = append? ? 3 : 4
|
|
306
|
+
if data_type == :BOOL
|
|
307
|
+
value = @parser.parameters[index].to_s.upcase
|
|
308
|
+
if value == "TRUE" or value == "FALSE"
|
|
309
|
+
return ConfigParser.handle_true_false(@parser.parameters[index])
|
|
310
|
+
else
|
|
311
|
+
raise @parser.error("ID Value for BOOL data type must be TRUE or FALSE")
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
if data_type == :ARRAY
|
|
315
|
+
value = @parser.parameters[index].to_s
|
|
316
|
+
begin
|
|
317
|
+
value = JSON.parse(value, allow_nan: true)
|
|
318
|
+
rescue Exception
|
|
319
|
+
raise @parser.error("Unparsable value for ARRAY: #{value}")
|
|
320
|
+
end
|
|
321
|
+
if Array === value
|
|
322
|
+
return value
|
|
323
|
+
else
|
|
324
|
+
raise @parser.error("ID Value for ARRAY data type must be an Array")
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
if data_type == :OBJECT
|
|
328
|
+
value = @parser.parameters[index].to_s
|
|
329
|
+
begin
|
|
330
|
+
value = JSON.parse(value, allow_nan: true)
|
|
331
|
+
rescue Exception
|
|
332
|
+
raise @parser.error("Unparsable value for OBJECT: #{value}")
|
|
333
|
+
end
|
|
334
|
+
if Hash === value
|
|
335
|
+
return value
|
|
336
|
+
else
|
|
337
|
+
raise @parser.error("ID Value for OBJECT data type must be a Hash")
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
if data_type == :ANY
|
|
341
|
+
value = @parser.parameters[index].to_s
|
|
342
|
+
if value.length > 0
|
|
343
|
+
begin
|
|
344
|
+
return JSON.parse(value, allow_nan: true)
|
|
345
|
+
rescue Exception
|
|
346
|
+
return value
|
|
347
|
+
end
|
|
348
|
+
else
|
|
349
|
+
return ""
|
|
350
|
+
end
|
|
351
|
+
end
|
|
212
352
|
if data_type == :STRING or data_type == :BLOCK
|
|
213
353
|
return convert_string_value(index)
|
|
214
354
|
else
|
|
@@ -229,10 +369,14 @@ module OpenC3
|
|
|
229
369
|
usage = "#{@parser.keyword} <ITEM NAME> "
|
|
230
370
|
usage << "<BIT OFFSET> " unless @parser.keyword.include?("APPEND")
|
|
231
371
|
usage << bit_size_usage()
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
372
|
+
if not @parser.keyword.include?("STRUCTURE")
|
|
373
|
+
usage << type_usage()
|
|
374
|
+
usage << "<TOTAL ARRAY BIT SIZE> " if @parser.keyword.include?("ARRAY")
|
|
375
|
+
usage << id_usage()
|
|
376
|
+
usage << "<DESCRIPTION (Optional)> <ENDIANNESS (Optional)>"
|
|
377
|
+
else
|
|
378
|
+
usage << "<CMD or TLM> <Target Name> <Packet Name>"
|
|
379
|
+
end
|
|
236
380
|
usage
|
|
237
381
|
end
|
|
238
382
|
|
|
@@ -247,13 +391,13 @@ module OpenC3
|
|
|
247
391
|
def type_usage
|
|
248
392
|
keyword = @parser.keyword
|
|
249
393
|
# Item type usage is simple so just return it
|
|
250
|
-
return "<TYPE: INT/UINT/FLOAT/STRING/BLOCK/DERIVED/ARRAY/OBJECT> " if keyword.include?("ITEM")
|
|
394
|
+
return "<TYPE: INT/UINT/FLOAT/STRING/BLOCK/DERIVED/BOOL/ARRAY/OBJECT/ANY> " if keyword.include?("ITEM")
|
|
251
395
|
|
|
252
396
|
# Build up the parameter type usage based on the keyword
|
|
253
397
|
usage = "<TYPE: "
|
|
254
398
|
# ARRAY types don't have min or max or default values
|
|
255
399
|
if keyword.include?("ARRAY")
|
|
256
|
-
usage << "INT/UINT/FLOAT/STRING/BLOCK/OBJECT> "
|
|
400
|
+
usage << "INT/UINT/FLOAT/STRING/BLOCK/BOOL/OBJECT/ANY> "
|
|
257
401
|
else
|
|
258
402
|
begin
|
|
259
403
|
data_type = get_data_type()
|
|
@@ -261,14 +405,13 @@ module OpenC3
|
|
|
261
405
|
# If the data type could not be determined set something
|
|
262
406
|
data_type = :INT
|
|
263
407
|
end
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
usage << "STRING/BLOCK/ARRAY/OBJECT> "
|
|
408
|
+
if data_type == :INT || data_type == :UINT || data_type == :FLOAT || data_type == :DERIVED
|
|
409
|
+
usage << "INT/UINT/FLOAT/DERIVED> <MIN VALUE> <MAX VALUE> "
|
|
267
410
|
else
|
|
268
|
-
usage << "
|
|
411
|
+
usage << "STRING/BLOCK/BOOL/ARRAY/OBJECT/ANY> "
|
|
269
412
|
end
|
|
270
|
-
# ID Values do not have default values
|
|
271
|
-
unless keyword.include?("ID")
|
|
413
|
+
# ID Values do not have default values
|
|
414
|
+
unless keyword.include?("ID")
|
|
272
415
|
usage << "<DEFAULT_VALUE> "
|
|
273
416
|
end
|
|
274
417
|
end
|
|
@@ -261,8 +261,8 @@ module OpenC3
|
|
|
261
261
|
to_xtce_string(item, param_or_arg, xml, 'String')
|
|
262
262
|
when :BLOCK
|
|
263
263
|
to_xtce_string(item, param_or_arg, xml, 'Binary')
|
|
264
|
-
|
|
265
|
-
raise "
|
|
264
|
+
else
|
|
265
|
+
raise "#{item.data_type} data type not supported in XTCE"
|
|
266
266
|
end
|
|
267
267
|
|
|
268
268
|
# Handle arrays
|
|
@@ -248,32 +248,34 @@ module OpenC3
|
|
|
248
248
|
|
|
249
249
|
# Recalculate the overall defined length of the structure
|
|
250
250
|
update_needed = false
|
|
251
|
-
if item.
|
|
252
|
-
if item.
|
|
253
|
-
if item.
|
|
254
|
-
if item.array_size
|
|
255
|
-
|
|
251
|
+
if not item.parent_item
|
|
252
|
+
if item.bit_offset >= 0
|
|
253
|
+
if item.bit_size > 0
|
|
254
|
+
if item.array_size
|
|
255
|
+
if item.array_size >= 0
|
|
256
|
+
item_defined_length_bits = item.bit_offset + item.array_size
|
|
257
|
+
else
|
|
258
|
+
item_defined_length_bits = item.bit_offset
|
|
259
|
+
end
|
|
256
260
|
else
|
|
257
|
-
item_defined_length_bits = item.bit_offset
|
|
261
|
+
item_defined_length_bits = item.bit_offset + item.bit_size
|
|
262
|
+
end
|
|
263
|
+
if item_defined_length_bits > @pos_bit_size
|
|
264
|
+
@pos_bit_size = item_defined_length_bits
|
|
265
|
+
update_needed = true
|
|
258
266
|
end
|
|
259
267
|
else
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
update_needed = true
|
|
268
|
+
if item.bit_offset > @pos_bit_size
|
|
269
|
+
@pos_bit_size = item.bit_offset
|
|
270
|
+
update_needed = true
|
|
271
|
+
end
|
|
265
272
|
end
|
|
266
273
|
else
|
|
267
|
-
if item.bit_offset > @
|
|
268
|
-
@
|
|
274
|
+
if item.bit_offset.abs > @neg_bit_size
|
|
275
|
+
@neg_bit_size = item.bit_offset.abs
|
|
269
276
|
update_needed = true
|
|
270
277
|
end
|
|
271
278
|
end
|
|
272
|
-
else
|
|
273
|
-
if item.bit_offset.abs > @neg_bit_size
|
|
274
|
-
@neg_bit_size = item.bit_offset.abs
|
|
275
|
-
update_needed = true
|
|
276
|
-
end
|
|
277
279
|
end
|
|
278
280
|
if update_needed
|
|
279
281
|
@defined_length_bits = @pos_bit_size + @neg_bit_size
|
|
@@ -349,7 +351,7 @@ module OpenC3
|
|
|
349
351
|
elsif item.variable_bit_size['length_value_bit_offset'] > 0
|
|
350
352
|
minimum_data_bits = item.variable_bit_size['length_value_bit_offset'] * item.variable_bit_size['length_bits_per_count']
|
|
351
353
|
end
|
|
352
|
-
if minimum_data_bits > 0 and item.bit_offset >= 0 and @defined_length_bits == item.bit_offset
|
|
354
|
+
if minimum_data_bits > 0 and item.bit_offset >= 0 and @defined_length_bits == item.bit_offset and not item.parent_item
|
|
353
355
|
@defined_length_bits += minimum_data_bits
|
|
354
356
|
end
|
|
355
357
|
end
|
|
@@ -436,7 +438,11 @@ module OpenC3
|
|
|
436
438
|
def read_all(value_type = :RAW, buffer = @buffer, top = true)
|
|
437
439
|
item_array = []
|
|
438
440
|
synchronize_allow_reads(top) do
|
|
439
|
-
@sorted_items.each
|
|
441
|
+
@sorted_items.each do |item|
|
|
442
|
+
unless item.hidden
|
|
443
|
+
item_array << [item.name, read_item(item, value_type, buffer)]
|
|
444
|
+
end
|
|
445
|
+
end
|
|
440
446
|
end
|
|
441
447
|
return item_array
|
|
442
448
|
end
|
|
@@ -454,7 +460,7 @@ module OpenC3
|
|
|
454
460
|
string = ''
|
|
455
461
|
synchronize_allow_reads(true) do
|
|
456
462
|
@sorted_items.each do |item|
|
|
457
|
-
next if ignored && ignored.include?(item.name)
|
|
463
|
+
next if item.hidden || (ignored && ignored.include?(item.name))
|
|
458
464
|
|
|
459
465
|
if (item.data_type != :BLOCK) ||
|
|
460
466
|
(item.data_type == :BLOCK and value_type != :RAW and
|
|
@@ -631,6 +637,8 @@ module OpenC3
|
|
|
631
637
|
def recalculate_bit_offsets
|
|
632
638
|
adjustment = 0
|
|
633
639
|
@sorted_items.each do |item|
|
|
640
|
+
# Parented items rely on the parent
|
|
641
|
+
next if item.parent_item
|
|
634
642
|
# Anything with a negative bit offset should be left alone
|
|
635
643
|
if item.original_bit_offset >= 0
|
|
636
644
|
item.bit_offset = item.original_bit_offset + adjustment
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# GNU Affero General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
|
18
18
|
# All Rights Reserved
|
|
19
19
|
#
|
|
20
20
|
# This file may also be used under the terms of a commercial license
|
|
@@ -31,7 +31,7 @@ module OpenC3
|
|
|
31
31
|
@@create_index = 0
|
|
32
32
|
|
|
33
33
|
# Valid data types adds :DERIVED, :ARRAY, :OBJECT to those defined by BinaryAccessor
|
|
34
|
-
DATA_TYPES =
|
|
34
|
+
DATA_TYPES = [:INT, :UINT, :FLOAT, :STRING, :BLOCK, :BOOL, :OBJECT, :ARRAY, :ANY, :DERIVED]
|
|
35
35
|
|
|
36
36
|
# Name is used by higher level classes to access the StructureItem.
|
|
37
37
|
# @return [String] Name of the item
|
|
@@ -98,6 +98,15 @@ module OpenC3
|
|
|
98
98
|
# @return [Integer] Incrementing value that shows relative order items are created
|
|
99
99
|
attr_reader :create_index
|
|
100
100
|
|
|
101
|
+
# @return [Boolean] Indicates if item should be listed in items and in read all type methods
|
|
102
|
+
attr_accessor :hidden
|
|
103
|
+
|
|
104
|
+
# @return [StructureItem] Parent structure item
|
|
105
|
+
attr_accessor :parent_item
|
|
106
|
+
|
|
107
|
+
# @return [Structure] Structure associated with item
|
|
108
|
+
attr_accessor :structure
|
|
109
|
+
|
|
101
110
|
# Create a StructureItem by setting all the attributes. It
|
|
102
111
|
# calls all the setter routines to do the attribute verification and then
|
|
103
112
|
# verifies the overall integrity.
|
|
@@ -126,6 +135,9 @@ module OpenC3
|
|
|
126
135
|
self.overflow = overflow
|
|
127
136
|
self.overlap = false
|
|
128
137
|
self.variable_bit_size = nil
|
|
138
|
+
self.hidden = false
|
|
139
|
+
self.parent_item = nil
|
|
140
|
+
self.structure = nil
|
|
129
141
|
@create_index = @@create_index
|
|
130
142
|
@@create_index += 1
|
|
131
143
|
@structure_item_constructed = true
|
|
@@ -198,7 +210,7 @@ module OpenC3
|
|
|
198
210
|
when *DATA_TYPES
|
|
199
211
|
# Valid data_type
|
|
200
212
|
else
|
|
201
|
-
raise ArgumentError, "#{@name}: unknown data_type: #{data_type} - Must be
|
|
213
|
+
raise ArgumentError, "#{@name}: unknown data_type: #{data_type} - Must be #{DATA_TYPES.join(", ")}"
|
|
202
214
|
end
|
|
203
215
|
|
|
204
216
|
@data_type = data_type
|
|
@@ -308,31 +320,31 @@ module OpenC3
|
|
|
308
320
|
end
|
|
309
321
|
alias dup clone
|
|
310
322
|
|
|
311
|
-
def self.from_json(hash)
|
|
312
|
-
# Convert strings to symbols
|
|
313
|
-
endianness = hash['endianness'] ? hash['endianness'].intern : nil
|
|
314
|
-
data_type = hash['data_type'] ? hash['data_type'].intern : nil
|
|
315
|
-
overflow = hash['overflow'] ? hash['overflow'].intern : nil
|
|
316
|
-
si = StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
|
|
317
|
-
endianness, hash['array_size'], overflow)
|
|
318
|
-
si.key = hash['key'] || hash['name']
|
|
319
|
-
si.variable_bit_size = hash['variable_bit_size']
|
|
320
|
-
si
|
|
321
|
-
end
|
|
322
|
-
|
|
323
323
|
def as_json(*a)
|
|
324
324
|
hash = {}
|
|
325
325
|
hash['name'] = self.name
|
|
326
326
|
hash['key'] = self.key
|
|
327
327
|
hash['bit_offset'] = self.original_bit_offset
|
|
328
328
|
hash['bit_size'] = self.original_bit_size
|
|
329
|
-
hash['data_type'] = self.data_type
|
|
330
|
-
hash['endianness'] = self.endianness
|
|
331
|
-
hash['
|
|
332
|
-
hash['
|
|
329
|
+
hash['data_type'] = self.data_type.to_s
|
|
330
|
+
hash['endianness'] = self.endianness.to_s
|
|
331
|
+
hash['overflow'] = self.overflow.to_s
|
|
332
|
+
hash['overlap'] = self.overlap
|
|
333
|
+
hash['create_index'] = self.create_index
|
|
334
|
+
hash['hidden'] = self.hidden
|
|
335
|
+
if self.original_array_size
|
|
336
|
+
hash['array_size'] = self.original_array_size
|
|
337
|
+
end
|
|
333
338
|
if @variable_bit_size
|
|
334
339
|
hash['variable_bit_size'] = @variable_bit_size
|
|
335
340
|
end
|
|
341
|
+
if self.parent_item
|
|
342
|
+
hash['parent_item'] = self.parent_item.as_json
|
|
343
|
+
end
|
|
344
|
+
if self.structure
|
|
345
|
+
hash['structure'] = self.structure.as_json
|
|
346
|
+
end
|
|
347
|
+
|
|
336
348
|
hash
|
|
337
349
|
end
|
|
338
350
|
|
|
@@ -264,8 +264,8 @@ module OpenC3
|
|
|
264
264
|
# default value of nil means to search all known targets.
|
|
265
265
|
# @return [Packet] The identified packet with its data set to the given
|
|
266
266
|
# packet_data buffer. Returns nil if no packet could be identified.
|
|
267
|
-
def identify!(packet_data, target_names = nil)
|
|
268
|
-
identified_packet = identify(packet_data, target_names)
|
|
267
|
+
def identify!(packet_data, target_names = nil, subpackets: false)
|
|
268
|
+
identified_packet = identify(packet_data, target_names, subpackets: subpackets)
|
|
269
269
|
identified_packet.buffer = packet_data if identified_packet
|
|
270
270
|
return identified_packet
|
|
271
271
|
end
|
|
@@ -277,7 +277,7 @@ module OpenC3
|
|
|
277
277
|
# @param target_names [Array<String>] List of target names to limit the search. The
|
|
278
278
|
# default value of nil means to search all known targets.
|
|
279
279
|
# @return [Packet] The identified packet, Returns nil if no packet could be identified.
|
|
280
|
-
def identify(packet_data, target_names = nil)
|
|
280
|
+
def identify(packet_data, target_names = nil, subpackets: false)
|
|
281
281
|
target_names = target_names() unless target_names
|
|
282
282
|
|
|
283
283
|
target_names.each do |target_name|
|
|
@@ -292,18 +292,36 @@ module OpenC3
|
|
|
292
292
|
next
|
|
293
293
|
end
|
|
294
294
|
|
|
295
|
-
|
|
296
|
-
if target and target.tlm_unique_id_mode
|
|
295
|
+
if (not subpackets and System.telemetry.tlm_unique_id_mode(target_name)) or (subpackets and System.telemetry.tlm_subpacket_unique_id_mode(target_name))
|
|
297
296
|
# Iterate through the packets and see if any represent the buffer
|
|
298
297
|
target_packets.each do |_packet_name, packet|
|
|
299
|
-
|
|
298
|
+
if subpackets
|
|
299
|
+
next unless packet.subpacket
|
|
300
|
+
else
|
|
301
|
+
next if packet.subpacket
|
|
302
|
+
end
|
|
303
|
+
return packet if packet.identify?(packet_data) # Handles virtual
|
|
300
304
|
end
|
|
301
305
|
else
|
|
302
306
|
# Do a hash lookup to quickly identify the packet
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
packet = nil
|
|
308
|
+
target_packets.each do |_packet_name, target_packet|
|
|
309
|
+
next if target_packet.virtual
|
|
310
|
+
if subpackets
|
|
311
|
+
next unless target_packet.subpacket
|
|
312
|
+
else
|
|
313
|
+
next if target_packet.subpacket
|
|
314
|
+
end
|
|
315
|
+
packet = target_packet
|
|
316
|
+
break
|
|
317
|
+
end
|
|
318
|
+
if packet
|
|
305
319
|
key = packet.read_id_values(packet_data)
|
|
306
|
-
|
|
320
|
+
if subpackets
|
|
321
|
+
hash = @config.tlm_subpacket_id_value_hash[target_name]
|
|
322
|
+
else
|
|
323
|
+
hash = @config.tlm_id_value_hash[target_name]
|
|
324
|
+
end
|
|
307
325
|
identified_packet = hash[key]
|
|
308
326
|
identified_packet = hash['CATCHALL'.freeze] unless identified_packet
|
|
309
327
|
return identified_packet if identified_packet
|
|
@@ -314,9 +332,9 @@ module OpenC3
|
|
|
314
332
|
return nil
|
|
315
333
|
end
|
|
316
334
|
|
|
317
|
-
def identify_and_define_packet(packet, target_names = nil)
|
|
335
|
+
def identify_and_define_packet(packet, target_names = nil, subpackets: false)
|
|
318
336
|
if !packet.identified?
|
|
319
|
-
identified_packet = identify(packet.buffer(false), target_names)
|
|
337
|
+
identified_packet = identify(packet.buffer(false), target_names, subpackets: subpackets)
|
|
320
338
|
return nil unless identified_packet
|
|
321
339
|
|
|
322
340
|
identified_packet = identified_packet.clone
|
|
@@ -425,5 +443,13 @@ module OpenC3
|
|
|
425
443
|
def dynamic_add_packet(packet, affect_ids: false)
|
|
426
444
|
@config.dynamic_add_packet(packet, :TELEMETRY, affect_ids: affect_ids)
|
|
427
445
|
end
|
|
446
|
+
|
|
447
|
+
def tlm_unique_id_mode(target_name)
|
|
448
|
+
return @config.tlm_unique_id_mode[target_name.upcase]
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def tlm_subpacket_unique_id_mode(target_name)
|
|
452
|
+
return @config.tlm_subpacket_unique_id_mode[target_name.upcase]
|
|
453
|
+
end
|
|
428
454
|
end # class Telemetry
|
|
429
455
|
end
|
|
@@ -172,11 +172,11 @@ module OpenC3
|
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
def write(string)
|
|
175
|
-
@report << (Time.now.
|
|
175
|
+
@report << (Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%6NZ") + ': ' + string)
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
def puts(string)
|
|
179
|
-
@report << (Time.now.
|
|
179
|
+
@report << (Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%6NZ") + ': ' + string)
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
# def collect_metadata(parent = nil)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Subpacketizer
|
|
2
|
+
attr_reader :args
|
|
3
|
+
|
|
4
|
+
def initialize(packet=nil)
|
|
5
|
+
@packet = packet
|
|
6
|
+
@args = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Subclass and implement this method to break packet into array of subpackets
|
|
10
|
+
# Subpackets should be fully identified and defined
|
|
11
|
+
def call(packet)
|
|
12
|
+
return [packet]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def as_json(*a)
|
|
16
|
+
{ 'class' => self.class.name, 'args' => @args.as_json(*a) }
|
|
17
|
+
end
|
|
18
|
+
end
|