openc3 5.0.9 → 5.0.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/data/config/_id_items.yaml +2 -1
  3. data/data/config/_id_params.yaml +2 -1
  4. data/data/config/_items.yaml +2 -1
  5. data/data/config/_params.yaml +2 -1
  6. data/data/config/command_modifiers.yaml +30 -0
  7. data/data/config/item_modifiers.yaml +10 -0
  8. data/data/config/microservice.yaml +12 -0
  9. data/data/config/param_item_modifiers.yaml +10 -0
  10. data/data/config/plugins.yaml +0 -9
  11. data/data/config/telemetry_modifiers.yaml +10 -0
  12. data/ext/openc3/ext/packet/packet.c +20 -2
  13. data/ext/openc3/ext/structure/structure.c +12 -17
  14. data/lib/openc3/accessors/accessor.rb +71 -0
  15. data/lib/openc3/accessors/binary_accessor.rb +1226 -0
  16. data/lib/openc3/accessors/cbor_accessor.rb +83 -0
  17. data/lib/openc3/accessors/html_accessor.rb +28 -0
  18. data/lib/openc3/accessors/json_accessor.rb +131 -0
  19. data/lib/openc3/accessors/xml_accessor.rb +67 -0
  20. data/lib/openc3/accessors.rb +23 -0
  21. data/lib/openc3/api/interface_api.rb +10 -3
  22. data/lib/openc3/config/config_parser.rb +10 -4
  23. data/lib/openc3/core_ext/tempfile.rb +20 -0
  24. data/lib/openc3/core_ext.rb +1 -0
  25. data/lib/openc3/interfaces/interface.rb +1 -1
  26. data/lib/openc3/models/auth_model.rb +0 -1
  27. data/lib/openc3/models/cvt_model.rb +1 -10
  28. data/lib/openc3/models/microservice_model.rb +26 -0
  29. data/lib/openc3/models/note_model.rb +5 -5
  30. data/lib/openc3/packets/binary_accessor.rb +2 -1207
  31. data/lib/openc3/packets/packet.rb +106 -6
  32. data/lib/openc3/packets/packet_config.rb +30 -7
  33. data/lib/openc3/packets/parsers/limits_response_parser.rb +1 -3
  34. data/lib/openc3/packets/parsers/processor_parser.rb +1 -2
  35. data/lib/openc3/packets/structure.rb +39 -14
  36. data/lib/openc3/packets/structure_item.rb +15 -1
  37. data/lib/openc3/script/storage.rb +2 -0
  38. data/lib/openc3/utilities/authentication.rb +6 -4
  39. data/lib/openc3/utilities/local_mode.rb +10 -1
  40. data/lib/openc3/utilities/s3.rb +3 -1
  41. data/lib/openc3/utilities/s3_autoload.rb +8 -6
  42. data/lib/openc3/utilities/simulated_target.rb +3 -2
  43. data/lib/openc3/utilities/target_file.rb +45 -6
  44. data/lib/openc3/version.rb +5 -5
  45. data/lib/openc3.rb +1 -0
  46. metadata +38 -2
@@ -21,6 +21,7 @@ require 'digest'
21
21
  require 'openc3/packets/structure'
22
22
  require 'openc3/packets/packet_item'
23
23
  require 'openc3/ext/packet' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
24
+ require 'base64'
24
25
 
25
26
  module OpenC3
26
27
  # Adds features common to all OpenC3 packets of data to the Structure class.
@@ -85,6 +86,9 @@ module OpenC3
85
86
  # @return [Symbol] :CMD or :TLM
86
87
  attr_accessor :cmd_or_tlm
87
88
 
89
+ # @return [String] Base data for building packet
90
+ attr_reader :template
91
+
88
92
  # Valid format types
89
93
  VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED, :WITH_UNITS]
90
94
 
@@ -98,7 +102,7 @@ module OpenC3
98
102
  # @param buffer [String] String buffer to hold the packet data
99
103
  # @param item_class [Class] Class used to instantiate items (Must be a
100
104
  # subclass of PacketItem)
101
- def initialize(target_name, packet_name, default_endianness = :BIG_ENDIAN, description = nil, buffer = nil, item_class = PacketItem)
105
+ def initialize(target_name = nil, packet_name = nil, default_endianness = :BIG_ENDIAN, description = nil, buffer = nil, item_class = PacketItem)
102
106
  super(default_endianness, buffer, item_class)
103
107
  # Explictly call the defined setter methods
104
108
  self.target_name = target_name
@@ -123,6 +127,7 @@ module OpenC3
123
127
  @stored = false
124
128
  @extra = nil
125
129
  @cmd_or_tlm = nil
130
+ @template = nil
126
131
  end
127
132
 
128
133
  # Sets the target name this packet is associated with. Unidentified packets
@@ -290,7 +295,9 @@ module OpenC3
290
295
  begin
291
296
  internal_buffer_equals(buffer)
292
297
  rescue RuntimeError
293
- Logger.instance.error "#{@target_name} #{@packet_name} received with actual packet length of #{buffer.length} but defined length of #{@defined_length}"
298
+ if BinaryAccessor == @accessor
299
+ Logger.instance.error "#{@target_name} #{@packet_name} received with actual packet length of #{buffer.length} but defined length of #{@defined_length}"
300
+ end
294
301
  end
295
302
  @read_conversion_cache.clear if @read_conversion_cache
296
303
  process()
@@ -353,6 +360,20 @@ module OpenC3
353
360
  end
354
361
  end
355
362
 
363
+ # Sets the template data for the packet
364
+ # Template data is used as the default buffer contents if provided
365
+ #
366
+ # @param hazardous_description [String] Hazardous description of the packet
367
+ def template=(template)
368
+ if template
369
+ raise ArgumentError, "template must be a String but is a #{template.class}" unless String === template
370
+
371
+ @template = template.freeze
372
+ else
373
+ @template = nil
374
+ end
375
+ end
376
+
356
377
  # Review bit offset to look for overlapping definitions. This will allow
357
378
  # gaps in the packet, but not allow the same bits to be used for multiple
358
379
  # variables.
@@ -531,11 +552,16 @@ module OpenC3
531
552
  # @param value_type [Symbol] How to convert the item before returning it.
532
553
  # Must be one of {VALUE_TYPES}
533
554
  # @param buffer (see Structure#read_item)
555
+ # @param given_raw Given raw value to optimize
534
556
  # @return The value. :FORMATTED and :WITH_UNITS values are always returned
535
557
  # as Strings. :RAW values will match their data_type. :CONVERTED values
536
558
  # can be any type.
537
- def read_item(item, value_type = :CONVERTED, buffer = @buffer)
538
- value = super(item, :RAW, buffer)
559
+ def read_item(item, value_type = :CONVERTED, buffer = @buffer, given_raw = nil)
560
+ if given_raw
561
+ value = given_raw
562
+ else
563
+ value = super(item, :RAW, buffer)
564
+ end
539
565
  derived_raw = false
540
566
  if item.data_type == :DERIVED && value_type == :RAW
541
567
  value_type = :CONVERTED
@@ -632,6 +658,31 @@ module OpenC3
632
658
  return value
633
659
  end
634
660
 
661
+ # Read a list of items in the structure
662
+ #
663
+ # @param items [StructureItem] Array of PacketItem or one of its subclasses
664
+ # @param value_type [Symbol] Value type to read for every item
665
+ # @param buffer [String] The binary buffer to read the items from
666
+ # @return Hash of read names and values
667
+ def read_items(items, value_type = :RAW, buffer = @buffer, raw_value = nil)
668
+ buffer = allocate_buffer_if_needed() unless buffer
669
+ if value_type == :RAW
670
+ result = super(items, value_type, buffer)
671
+ # Must handle DERIVED special
672
+ items.each do |item|
673
+ if item.data_type == :DERIVED
674
+ result[item.name] = read_item(item, value_type, buffer)
675
+ end
676
+ end
677
+ else
678
+ result = {}
679
+ items.each do |item|
680
+ result[item.name] = read_item(item, value_type, buffer)
681
+ end
682
+ end
683
+ return result
684
+ end
685
+
635
686
  # Write an item in the packet
636
687
  #
637
688
  # @param item [PacketItem] Instance of PacketItem or one of its subclasses
@@ -674,6 +725,24 @@ module OpenC3
674
725
  end
675
726
  end
676
727
 
728
+ # Write values to the buffer based on the item definitions
729
+ #
730
+ # @param items [StructureItem] Array of StructureItem or one of its subclasses
731
+ # @param value [Object] Array of values based on the item definitions.
732
+ # @param value_type [Symbol] Value type of each item to write
733
+ # @param buffer [String] The binary buffer to write the values to
734
+ def write_items(items, values, value_type = :RAW, buffer = @buffer)
735
+ buffer = allocate_buffer_if_needed() unless buffer
736
+ if value_type == :RAW
737
+ return super(items, values, value_type, buffer)
738
+ else
739
+ items.each_with_index do |item, index|
740
+ write_item(item, values[index], value_type, buffer)
741
+ end
742
+ end
743
+ return buffer
744
+ end
745
+
677
746
  # Read an item in the packet by name
678
747
  #
679
748
  # @param name [String] Name of the item to read
@@ -738,12 +807,17 @@ module OpenC3
738
807
  #
739
808
  # @param buffer [String] Raw buffer of binary data
740
809
  # @param skip_item_names [Array] Array of item names to skip
741
- def restore_defaults(buffer = @buffer, skip_item_names = nil)
810
+ # @param use_templase [Boolean] Apply template before setting defaults (or not)
811
+ def restore_defaults(buffer = @buffer, skip_item_names = nil, use_template = true)
812
+ buffer = allocate_buffer_if_needed() unless buffer
742
813
  upcase_skip_item_names = skip_item_names.map(&:upcase) if skip_item_names
814
+ buffer.replace(@template) if @template and use_template
743
815
  @sorted_items.each do |item|
744
816
  next if RESERVED_ITEM_NAMES.include?(item.name)
745
817
 
746
- write_item(item, item.default, :CONVERTED, buffer) unless skip_item_names and upcase_skip_item_names.include?(item.name)
818
+ unless item.default.nil?
819
+ write_item(item, item.default, :CONVERTED, buffer) unless skip_item_names and upcase_skip_item_names.include?(item.name)
820
+ end
747
821
  end
748
822
  end
749
823
 
@@ -986,6 +1060,8 @@ module OpenC3
986
1060
  config['disabled'] = true if @disabled
987
1061
  config['hidden'] = true if @hidden
988
1062
  config['stale'] = true if @stale
1063
+ config['accessor'] = @accessor.to_s
1064
+ config['template'] = Base64.encode64(@template) if @template
989
1065
 
990
1066
  if @processors
991
1067
  processors = []
@@ -1024,6 +1100,14 @@ module OpenC3
1024
1100
  packet.disabled = hash['disabled']
1025
1101
  packet.hidden = hash['hidden']
1026
1102
  # packet.stale is read only
1103
+ if hash['accessor']
1104
+ begin
1105
+ packet.accessor = OpenC3::const_get(hash['accessor'])
1106
+ rescue => error
1107
+ Logger.instance.error "#{packet.target_name} #{packet.packet_name} accessor of #{hash['accessor']} could not be found due to #{error}"
1108
+ end
1109
+ end
1110
+ packet.template = Base64.decode64(hash['template']) if hash['template']
1027
1111
  packet.meta = hash['meta']
1028
1112
  # Can't convert processors
1029
1113
  hash['items'].each do |item|
@@ -1032,6 +1116,22 @@ module OpenC3
1032
1116
  packet
1033
1117
  end
1034
1118
 
1119
+ def decom
1120
+ # Read all the RAW at once because this could be optimized by the accessor
1121
+ json_hash = read_items(@sorted_items)
1122
+
1123
+ # Now read all other value types - no accessor required
1124
+ @sorted_items.each do |item|
1125
+ given_raw = json_hash[item.name]
1126
+ json_hash["#{item.name}__C"] = read_item(item, :CONVERTED, @buffer, given_raw) if item.states or (item.read_conversion and item.data_type != :DERIVED)
1127
+ json_hash["#{item.name}__F"] = read_item(item, :FORMATTED, @buffer, given_raw) if item.format_string
1128
+ json_hash["#{item.name}__U"] = read_item(item, :WITH_UNITS, @buffer, given_raw) if item.units
1129
+ limits_state = item.limits.state
1130
+ json_hash["#{item.name}__L"] = limits_state if limits_state
1131
+ end
1132
+ json_hash
1133
+ end
1134
+
1035
1135
  protected
1036
1136
 
1037
1137
  # Performs packet specific processing on the packet.
@@ -209,7 +209,7 @@ module OpenC3
209
209
  'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
210
210
  'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
211
211
  'APPEND_ARRAY_PARAMETER', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META',\
212
- 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
212
+ 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE'
213
213
  raise parser.error("No current packet for #{keyword}") unless @current_packet
214
214
 
215
215
  process_current_packet(parser, keyword, params)
@@ -221,7 +221,7 @@ module OpenC3
221
221
  'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION',\
222
222
  'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED',\
223
223
  'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',\
224
- 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP'
224
+ 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP', 'KEY'
225
225
  raise parser.error("No current item for #{keyword}") unless @current_item
226
226
 
227
227
  process_current_item(parser, keyword, params)
@@ -427,7 +427,30 @@ module OpenC3
427
427
  parser.verify_num_parameters(0, 0, usage)
428
428
  @current_packet.hidden = true
429
429
  @current_packet.disabled = true
430
+ when 'ACCESSOR'
431
+ usage = "#{keyword} <Accessor class name>"
432
+ parser.verify_num_parameters(1, 1, usage)
433
+ begin
434
+ klass = OpenC3.require_class(params[0])
435
+ @current_packet.accessor = klass
436
+ rescue Exception => err
437
+ raise parser.error(err)
438
+ end
439
+
440
+ when 'TEMPLATE'
441
+ usage = "#{keyword} <Template string>"
442
+ parser.verify_num_parameters(1, 1, usage)
443
+ @current_packet.template = params[0]
430
444
 
445
+ when 'TEMPLATE_FILE'
446
+ usage = "#{keyword} <Template file path>"
447
+ parser.verify_num_parameters(1, 1, usage)
448
+
449
+ begin
450
+ @current_packet.template = parser.read_file(params[0])
451
+ rescue Exception => err
452
+ raise parser.error(err)
453
+ end
431
454
  end
432
455
  end
433
456
 
@@ -444,14 +467,11 @@ module OpenC3
444
467
  usage = "#{keyword} <conversion class filename> <custom parameters> ..."
445
468
  parser.verify_num_parameters(1, nil, usage)
446
469
  begin
447
- # require should be performed in target.txt
448
- klass = params[0].filename_to_class_name.to_class
449
- raise parser.error("#{params[0].filename_to_class_name} class not found. Did you require the file in target.txt?", usage) unless klass
450
-
470
+ klass = OpenC3.require_class(params[0])
451
471
  conversion = klass.new(*params[1..(params.length - 1)])
452
472
  @current_item.public_send("#{keyword.downcase}=".to_sym, conversion)
453
473
  if klass != ProcessorConversion and (conversion.converted_type.nil? or conversion.converted_bit_size.nil?)
454
- msg = "Read Conversion #{params[0].filename_to_class_name} on item #{@current_item.name} does not specify converted type or bit size"
474
+ msg = "Read Conversion #{params[0]} on item #{@current_item.name} does not specify converted type or bit size"
455
475
  @warnings << msg
456
476
  Logger.instance.warn @warnings[-1]
457
477
  end
@@ -600,6 +620,9 @@ module OpenC3
600
620
  parser.verify_num_parameters(0, 0, 'OVERLAP')
601
621
  @current_item.overlap = true
602
622
 
623
+ when 'KEY'
624
+ parser.verify_num_parameters(1, 1, 'KEY <key or path into data>')
625
+ @current_item.key = params[0]
603
626
  end
604
627
  end
605
628
 
@@ -45,9 +45,7 @@ module OpenC3
45
45
 
46
46
  # @param item [PacketItem] The item the limits response should be added to
47
47
  def create_limits_response(item)
48
- # require should be performed in target.txt
49
- klass = @parser.parameters[0].filename_to_class_name.to_class
50
- raise @parser.error("#{@parser.parameters[0].filename_to_class_name} class not found. Did you require the file in target.txt?", @usage) unless klass
48
+ klass = OpenC3.require_class(@parser.parameters[0])
51
49
 
52
50
  if @parser.parameters[1]
53
51
  item.limits.response = klass.new(*@parser.parameters[1..(@parser.parameters.length - 1)])
@@ -48,8 +48,7 @@ module OpenC3
48
48
  # @param packet [Packet] The packet the processor should be added to
49
49
  def create_processor(packet)
50
50
  # require should be performed in target.txt
51
- klass = @parser.parameters[1].filename_to_class_name.to_class
52
- raise @parser.error("#{@parser.parameters[1].filename_to_class_name} class not found. Did you require the file in target.txt?", @usage) unless klass
51
+ klass = OpenC3.require_class(@parser.parameters[1])
53
52
 
54
53
  if @parser.parameters[2]
55
54
  processor = klass.new(*@parser.parameters[2..(@parser.parameters.length - 1)])
@@ -51,6 +51,9 @@ module OpenC3
51
51
  # required data size is allowed.
52
52
  attr_accessor :short_buffer_allowed
53
53
 
54
+ # @return [Accessor] Class used to access raw data of structure from buffer
55
+ attr_reader :accessor
56
+
54
57
  if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
55
58
  # Used to force encoding
56
59
  ASCII_8BIT_STRING = "ASCII-8BIT".freeze
@@ -86,6 +89,7 @@ module OpenC3
86
89
  @fixed_size = true
87
90
  @short_buffer_allowed = false
88
91
  @mutex = nil
92
+ @accessor = BinaryAccessor
89
93
  else
90
94
  raise(ArgumentError, "Unknown endianness '#{default_endianness}', must be :BIG_ENDIAN or :LITTLE_ENDIAN")
91
95
  end
@@ -103,11 +107,7 @@ module OpenC3
103
107
  return nil if item.data_type == :DERIVED
104
108
 
105
109
  buffer = allocate_buffer_if_needed() unless buffer
106
- if item.array_size
107
- return BinaryAccessor.read_array(item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness)
108
- else
109
- return BinaryAccessor.read(item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness)
110
- end
110
+ return @accessor.read_item(item, buffer)
111
111
  end
112
112
 
113
113
  # Get the length of the buffer used by the structure
@@ -133,6 +133,26 @@ module OpenC3
133
133
  end
134
134
  end
135
135
 
136
+ # Configure the accessor for this packet
137
+ #
138
+ # @param accessor [Accessor] The class to use as an accessor
139
+ def accessor=(accessor)
140
+ @accessor = accessor
141
+ @short_buffer_allowed = true if @accessor != BinaryAccessor
142
+ end
143
+
144
+ # Read a list of items in the structure
145
+ #
146
+ # @param items [StructureItem] Array of StructureItem or one of its subclasses
147
+ # @param value_type [Symbol] Not used. Subclasses should overload this
148
+ # parameter to check whether to perform conversions on the item.
149
+ # @param buffer [String] The binary buffer to read the item from
150
+ # @return Hash of read names and values
151
+ def read_items(items, value_type = :RAW, buffer = @buffer)
152
+ buffer = allocate_buffer_if_needed() unless buffer
153
+ return @accessor.read_items(items, buffer)
154
+ end
155
+
136
156
  # Allocate a buffer if not available
137
157
  def allocate_buffer_if_needed
138
158
  unless @buffer
@@ -180,11 +200,8 @@ module OpenC3
180
200
  # dependant on the item_class but by default see StructureItem.
181
201
  # @return [StrutureItem] The struture item defined
182
202
  def define_item(name, bit_offset, bit_size, data_type, array_size = nil, endianness = @default_endianness, overflow = :ERROR)
183
- # Handle case-insensitive naming
184
- name_upcase = name.upcase
185
-
186
203
  # Create the item
187
- item = @item_class.new(name_upcase, bit_offset, bit_size, data_type, endianness, array_size, overflow)
204
+ item = @item_class.new(name, bit_offset, bit_size, data_type, endianness, array_size, overflow)
188
205
  define(item)
189
206
  end
190
207
 
@@ -348,11 +365,19 @@ module OpenC3
348
365
  # @param buffer [String] The binary buffer to write the value to
349
366
  def write_item(item, value, value_type = :RAW, buffer = @buffer)
350
367
  buffer = allocate_buffer_if_needed() unless buffer
351
- if item.array_size
352
- BinaryAccessor.write_array(value, item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness, item.overflow)
353
- else
354
- BinaryAccessor.write(value, item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness, item.overflow)
355
- end
368
+ return @accessor.write_item(item, value, buffer)
369
+ end
370
+
371
+ # Write values to the buffer based on the item definitions
372
+ #
373
+ # @param items [StructureItem] Array of StructureItem or one of its subclasses
374
+ # @param value [Object] Array of values based on the item definitions.
375
+ # @param value_type [Symbol] Not used. Subclasses should overload this
376
+ # parameter to check whether to perform conversions on the item.
377
+ # @param buffer [String] The binary buffer to write the values to
378
+ def write_items(items, values, value_type = :RAW, buffer = @buffer)
379
+ buffer = allocate_buffer_if_needed() unless buffer
380
+ return @accessor.write_items(items, values, buffer)
356
381
  end
357
382
 
358
383
  # Read an item in the structure by name
@@ -34,6 +34,9 @@ module OpenC3
34
34
  # @return [String] Name of the item
35
35
  attr_reader :name
36
36
 
37
+ # Key is used to access into nested structures during decom if applicable
38
+ attr_reader :key
39
+
37
40
  # Indicates where in the binary buffer the StructureItem exists.
38
41
  # @return [Integer] 0 based bit offset
39
42
  attr_reader :bit_offset
@@ -89,6 +92,7 @@ module OpenC3
89
92
  @structure_item_constructed = false
90
93
  # Assignment order matters due to verifications!
91
94
  self.name = name
95
+ self.key = name # Key defaults to name as given (not upcased)
92
96
  self.endianness = endianness
93
97
  self.data_type = data_type
94
98
  self.bit_offset = bit_offset
@@ -110,6 +114,13 @@ module OpenC3
110
114
  verify_overall() if @structure_item_constructed
111
115
  end
112
116
 
117
+ def key=(key)
118
+ raise ArgumentError, "key must be a String but is a #{name.class}" unless String === key
119
+ raise ArgumentError, "key must contain at least one character" if key.empty?
120
+
121
+ @key = key
122
+ end
123
+
113
124
  def endianness=(endianness)
114
125
  raise ArgumentError, "#{@name}: endianness must be a Symbol" unless Symbol === endianness
115
126
  unless BinaryAccessor::ENDIANNESS.include? endianness
@@ -297,13 +308,16 @@ module OpenC3
297
308
  endianness = hash['endianness'] ? hash['endianness'].intern : nil
298
309
  data_type = hash['data_type'] ? hash['data_type'].intern : nil
299
310
  overflow = hash['overflow'] ? hash['overflow'].intern : nil
300
- StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
311
+ si = StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
301
312
  endianness, hash['array_size'], overflow)
313
+ si.key = hash['key'] || hash['name']
314
+ si
302
315
  end
303
316
 
304
317
  def as_json(*a)
305
318
  hash = {}
306
319
  hash['name'] = self.name
320
+ hash['key'] = self.key
307
321
  hash['bit_offset'] = self.bit_offset
308
322
  hash['bit_size'] = self.bit_size
309
323
  hash['data_type'] = self.data_type
@@ -17,6 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
 
20
+ require 'tempfile'
20
21
  require 'net/http'
21
22
 
22
23
  module OpenC3
@@ -53,6 +54,7 @@ module OpenC3
53
54
 
54
55
  if ENV['OPENC3_LOCAL_MODE'] and $openc3_in_cluster
55
56
  OpenC3::LocalMode.put_target_file(upload_path, io_or_string, scope: scope)
57
+ io_or_string.rewind if io_or_string.respond_to?(:rewind)
56
58
  end
57
59
 
58
60
  endpoint = "/openc3-api/storage/upload/#{upload_path}"
@@ -55,6 +55,8 @@ module OpenC3
55
55
  # "scope": "openid email profile"
56
56
  # }
57
57
 
58
+ REFRESH_OFFSET_SECONDS = 60
59
+
58
60
  # @param url [String] The url of the openc3 or keycloak in the cluster
59
61
  def initialize(url)
60
62
  @url = url
@@ -97,8 +99,8 @@ module OpenC3
97
99
  oath = _make_request(headers, data)
98
100
  @token = oath['access_token']
99
101
  @refresh_token = oath['refresh_token']
100
- @expires_at = current_time + oath['expires_in']
101
- @refresh_expires_at = current_time + oath['refresh_expires_in']
102
+ @expires_at = current_time + oath['expires_in'] - REFRESH_OFFSET_SECONDS
103
+ @refresh_expires_at = current_time + oath['refresh_expires_in'] - REFRESH_OFFSET_SECONDS
102
104
  end
103
105
 
104
106
  # Refresh the token and save token to instance
@@ -112,8 +114,8 @@ module OpenC3
112
114
  oath = _make_request(headers, data)
113
115
  @token = oath["access_token"]
114
116
  @refresh_token = oath["refresh_token"]
115
- @expires_at = current_time + oath["expires_in"]
116
- @refresh_expires_at = current_time + oath["refresh_expires_in"]
117
+ @expires_at = current_time + oath["expires_in"] - REFRESH_OFFSET_SECONDS
118
+ @refresh_expires_at = current_time + oath["refresh_expires_in"] - REFRESH_OFFSET_SECONDS
117
119
  end
118
120
 
119
121
  # Make the post request to keycloak
@@ -306,6 +306,9 @@ module OpenC3
306
306
  puts "Removing local plugin files: #{full_folder_path}"
307
307
  File.delete(gems[0])
308
308
  File.delete(plugin_instance)
309
+ if Dir.empty?(File.dirname(gems[0]))
310
+ FileUtils.rm_rf(File.dirname(gems[0]))
311
+ end
309
312
  break
310
313
  end
311
314
  end
@@ -390,11 +393,17 @@ module OpenC3
390
393
  return nil
391
394
  end
392
395
 
393
- def self.local_target_files(scope:, path_matchers:)
396
+ def self.local_target_files(scope:, path_matchers:, include_temp: false)
394
397
  files = []
395
398
  local_catalog = build_local_catalog(scope: scope)
396
399
  local_catalog.each do |key, size|
397
400
  split_key = key.split('/')
401
+ # DEFAULT/targets_modified/__TEMP__/YYYY_MM_DD_HH_MM_SS_mmm_temp.rb
402
+ # See target_file.rb TEMP_FOLDER
403
+ if split_key[2] === '__TEMP__'
404
+ files << split_key[2..-1].join('/') if include_temp
405
+ next
406
+ end
398
407
  found = false
399
408
  path_matchers.each do |path|
400
409
  if split_key.include?(path)
@@ -17,7 +17,9 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
 
20
- autoload(:Aws, 'openc3/utilities/s3_autoload.rb')
20
+ module Aws
21
+ autoload(:S3, 'openc3/utilities/s3_autoload.rb')
22
+ end
21
23
  require 'openc3/models/reducer_model'
22
24
 
23
25
  module OpenC3
@@ -1,9 +1,11 @@
1
1
  require 'aws-sdk-s3'
2
2
 
3
3
  Aws.config.update(
4
- endpoint: ENV['OPENC3_S3_URL'] || (ENV['OPENC3_DEVEL'] ? 'http://127.0.0.1:9000' : 'http://openc3-minio:9000'),
5
- access_key_id: ENV['OPENC3_MINIO_USERNAME'],
6
- secret_access_key: ENV['OPENC3_MINIO_PASSWORD'],
7
- force_path_style: true,
8
- region: 'us-east-1'
9
- )
4
+ s3: {
5
+ endpoint: ENV['OPENC3_S3_URL'] || (ENV['OPENC3_DEVEL'] ? 'http://127.0.0.1:9000' : 'http://openc3-minio:9000'),
6
+ access_key_id: ENV['OPENC3_MINIO_USERNAME'],
7
+ secret_access_key: ENV['OPENC3_MINIO_PASSWORD'],
8
+ force_path_style: true,
9
+ region: 'us-east-1'
10
+ }
11
+ )
@@ -42,8 +42,9 @@ module OpenC3
42
42
  @tlm_packets[name].enable_method_missing
43
43
  end
44
44
 
45
- # Set id values
45
+ # Set defaults, template, and id values
46
46
  @tlm_packets.each do |name, packet|
47
+ packet.restore_defaults
47
48
  ids = packet.id_items
48
49
  ids.each do |id|
49
50
  packet.public_send((id.name + '=').to_sym, id.id_value)
@@ -62,7 +63,7 @@ module OpenC3
62
63
  end
63
64
 
64
65
  def read(count_100hz, time)
65
- raise "Error: read must be implemented by subclass"
66
+ get_pending_packets(count_100hz)
66
67
  end
67
68
 
68
69
  def tick_period_seconds
@@ -22,10 +22,13 @@ module OpenC3
22
22
  class TargetFile
23
23
 
24
24
  DEFAULT_BUCKET_NAME = 'config'
25
+ # Matches ScriptRunner.vue const TEMP_FOLDER
26
+ TEMP_FOLDER = '__TEMP__'
25
27
 
26
- def self.all(scope, path_matchers)
28
+ def self.all(scope, path_matchers, include_temp: false)
27
29
  result = []
28
30
  modified = []
31
+ temp = []
29
32
 
30
33
  rubys3_client = Aws::S3::Client.new
31
34
  token = nil
@@ -39,6 +42,12 @@ module OpenC3
39
42
 
40
43
  resp.contents.each do |object|
41
44
  split_key = object.key.split('/')
45
+ # DEFAULT/targets_modified/__TEMP__/YYYY_MM_DD_HH_MM_SS_mmm_temp.rb
46
+ if split_key[2] == TEMP_FOLDER
47
+ temp << split_key[2..-1].join('/') if include_temp
48
+ next
49
+ end
50
+
42
51
  found = false
43
52
  path_matchers.each do |path|
44
53
  if split_key.include?(path)
@@ -60,10 +69,14 @@ module OpenC3
60
69
 
61
70
  # Add in local targets_modified if present
62
71
  if ENV['OPENC3_LOCAL_MODE']
63
- local_modified = OpenC3::LocalMode.local_target_files(scope: scope, path_matchers: path_matchers)
72
+ local_modified = OpenC3::LocalMode.local_target_files(scope: scope, path_matchers: path_matchers, include_temp: include_temp)
64
73
  local_modified.each do |filename|
65
- modified << filename unless modified.include?(filename)
66
- result << filename unless result.include?(filename)
74
+ if include_temp and filename.include?(TEMP_FOLDER)
75
+ temp << filename
76
+ else
77
+ modified << filename unless modified.include?(filename)
78
+ result << filename unless result.include?(filename)
79
+ end
67
80
  end
68
81
  end
69
82
 
@@ -79,9 +92,36 @@ module OpenC3
79
92
 
80
93
  # Concat any remaining modified files (new files not in original target)
81
94
  result.concat(modified)
95
+ result.concat(temp.uniq)
82
96
  result.sort
83
97
  end
84
98
 
99
+ def self.delete_temp(scope)
100
+ rubys3_client = Aws::S3::Client.new
101
+ token = nil
102
+ while true
103
+ resp = rubys3_client.list_objects_v2({
104
+ bucket: DEFAULT_BUCKET_NAME,
105
+ prefix: "#{scope}/targets_modified/#{TEMP_FOLDER}",
106
+ max_keys: 1000,
107
+ continuation_token: token
108
+ })
109
+
110
+ resp.contents.each do |object|
111
+ rubys3_client.delete_object(
112
+ bucket: DEFAULT_BUCKET_NAME,
113
+ key: object.key,
114
+ )
115
+ if ENV['OPENC3_LOCAL_MODE']
116
+ OpenC3::LocalMode.delete_local(object.key)
117
+ end
118
+ end
119
+ break unless resp.is_truncated
120
+ token = resp.next_continuation_token
121
+ end
122
+ true
123
+ end
124
+
85
125
  def self.body(scope, name)
86
126
  name = name.split('*')[0] # Split '*' that indicates modified
87
127
  rubys3_client = Aws::S3::Client.new
@@ -141,6 +181,5 @@ module OpenC3
141
181
  )
142
182
  true
143
183
  end
144
-
145
184
  end
146
- end
185
+ end