openc3 5.10.1 → 5.11.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -2
  3. data/data/config/target.yaml +9 -0
  4. data/ext/openc3/ext/packet/packet.c +3 -0
  5. data/ext/openc3/ext/reducer_microservice/extconf.rb +13 -0
  6. data/ext/openc3/ext/reducer_microservice/reducer_microservice.c +165 -0
  7. data/ext/openc3/ext/structure/structure.c +7 -9
  8. data/lib/openc3/accessors/accessor.rb +53 -3
  9. data/lib/openc3/accessors/binary_accessor.rb +16 -0
  10. data/lib/openc3/accessors/cbor_accessor.rb +3 -3
  11. data/lib/openc3/accessors/form_accessor.rb +78 -0
  12. data/lib/openc3/accessors/http_accessor.rb +145 -0
  13. data/lib/openc3/accessors/json_accessor.rb +19 -3
  14. data/lib/openc3/accessors/xml_accessor.rb +18 -1
  15. data/lib/openc3/accessors.rb +3 -1
  16. data/lib/openc3/config/config_parser.rb +7 -5
  17. data/lib/openc3/config/meta_config_parser.rb +1 -1
  18. data/lib/openc3/core_ext/string.rb +16 -1
  19. data/lib/openc3/interfaces/http_client_interface.rb +202 -0
  20. data/lib/openc3/interfaces/http_server_interface.rb +183 -0
  21. data/lib/openc3/interfaces/interface.rb +86 -16
  22. data/lib/openc3/interfaces/mqtt_interface.rb +6 -5
  23. data/lib/openc3/interfaces/protocols/burst_protocol.rb +11 -11
  24. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +7 -7
  25. data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -7
  26. data/lib/openc3/interfaces/protocols/length_protocol.rb +6 -6
  27. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +9 -5
  28. data/lib/openc3/interfaces/protocols/protocol.rb +8 -6
  29. data/lib/openc3/interfaces/protocols/slip_protocol.rb +8 -8
  30. data/lib/openc3/interfaces/protocols/template_protocol.rb +6 -7
  31. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +4 -4
  32. data/lib/openc3/interfaces/simulated_target_interface.rb +2 -0
  33. data/lib/openc3/interfaces/stream_interface.rb +6 -4
  34. data/lib/openc3/interfaces/tcpip_server_interface.rb +2 -0
  35. data/lib/openc3/interfaces/udp_interface.rb +8 -5
  36. data/lib/openc3/interfaces.rb +2 -0
  37. data/lib/openc3/logs/buffered_packet_log_writer.rb +6 -7
  38. data/lib/openc3/logs/log_writer.rb +2 -10
  39. data/lib/openc3/logs/packet_log_constants.rb +13 -3
  40. data/lib/openc3/logs/packet_log_reader.rb +35 -98
  41. data/lib/openc3/logs/packet_log_writer.rb +24 -62
  42. data/lib/openc3/logs/text_log_writer.rb +32 -6
  43. data/lib/openc3/microservices/cleanup_microservice.rb +23 -16
  44. data/lib/openc3/microservices/decom_microservice.rb +8 -20
  45. data/lib/openc3/microservices/log_microservice.rb +3 -1
  46. data/lib/openc3/microservices/reaction_microservice.rb +22 -11
  47. data/lib/openc3/microservices/reducer_microservice.rb +174 -130
  48. data/lib/openc3/{models/notification_model.rb → microservices/scope_cleanup_microservice.rb} +20 -21
  49. data/lib/openc3/microservices/text_log_microservice.rb +2 -5
  50. data/lib/openc3/microservices/timeline_microservice.rb +0 -1
  51. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -1
  52. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +44 -0
  53. data/lib/openc3/models/microservice_model.rb +1 -1
  54. data/lib/openc3/models/scope_model.rb +65 -34
  55. data/lib/openc3/models/target_model.rb +25 -5
  56. data/lib/openc3/models/tool_model.rb +14 -2
  57. data/lib/openc3/models/widget_model.rb +1 -1
  58. data/lib/openc3/packets/json_packet.rb +10 -2
  59. data/lib/openc3/packets/packet.rb +30 -9
  60. data/lib/openc3/packets/packet_config.rb +6 -2
  61. data/lib/openc3/packets/parsers/packet_item_parser.rb +11 -6
  62. data/lib/openc3/packets/structure.rb +19 -12
  63. data/lib/openc3/script/storage.rb +1 -1
  64. data/lib/openc3/script/web_socket_api.rb +17 -14
  65. data/lib/openc3/topics/telemetry_topic.rb +2 -1
  66. data/lib/openc3/utilities/bucket_utilities.rb +2 -0
  67. data/lib/openc3/utilities/cli_generator.rb +1 -1
  68. data/lib/openc3/utilities/logger.rb +62 -47
  69. data/lib/openc3/utilities/metric.rb +19 -1
  70. data/lib/openc3/utilities/sleeper.rb +3 -1
  71. data/lib/openc3/utilities/throttle.rb +76 -0
  72. data/lib/openc3/version.rb +6 -6
  73. data/templates/tool_angular/package.json +20 -20
  74. data/templates/tool_angular/yarn.lock +112 -106
  75. data/templates/tool_react/package.json +16 -18
  76. data/templates/tool_react/yarn.lock +977 -664
  77. data/templates/tool_svelte/.prettierrc.js +5 -0
  78. data/templates/tool_svelte/package.json +18 -18
  79. data/templates/tool_svelte/src/services/cable.js +1 -1
  80. data/templates/tool_svelte/src/services/openc3-api.js +173 -173
  81. data/templates/tool_svelte/yarn.lock +767 -665
  82. data/templates/tool_vue/package.json +10 -10
  83. data/templates/tool_vue/yarn.lock +225 -43
  84. data/templates/widget/package.json +10 -10
  85. data/templates/widget/yarn.lock +223 -46
  86. metadata +41 -4
  87. data/lib/openc3/topics/notifications_topic.rb +0 -31
@@ -23,6 +23,7 @@
23
23
  require 'openc3/api/api'
24
24
  require 'openc3/logs/stream_log_pair'
25
25
  require 'openc3/utilities/secrets'
26
+ require 'rufus-scheduler'
26
27
 
27
28
  module OpenC3
28
29
  # Define a class to allow interfaces and protocols to reject commands without
@@ -140,6 +141,9 @@ module OpenC3
140
141
  # @return [Secrets] Interface secrets manager class
141
142
  attr_accessor :secrets
142
143
 
144
+ # @return [Scheduler] Scheduler used for periodic commanding
145
+ attr_accessor :scheduler
146
+
143
147
  # Initialize default attribute values
144
148
  def initialize
145
149
  @name = self.class.to_s.split("::")[-1] # Remove namespacing if present
@@ -177,12 +181,38 @@ module OpenC3
177
181
  @config_params = []
178
182
  @interfaces = []
179
183
  @secrets = Secrets.getClient
184
+ @scheduler = nil
180
185
  end
181
186
 
182
187
  # Connects the interface to its target(s). Must be implemented by a
183
188
  # subclass.
184
189
  def connect
185
190
  (@read_protocols | @write_protocols).each { |protocol| protocol.connect_reset }
191
+
192
+ periodic_cmds = @options['PERIODIC_CMD']
193
+ if periodic_cmds
194
+ if not @scheduler
195
+ @scheduler = Rufus::Scheduler.new
196
+
197
+ periodic_cmds.each do |log_dont_log, period, cmd_string|
198
+ log_dont_log.upcase!
199
+ period = "#{period.to_f}s"
200
+ @scheduler.every period do
201
+ begin
202
+ if log_dont_log == 'DONT_LOG'
203
+ cmd(cmd_string, log_message: false)
204
+ else
205
+ cmd(cmd_string)
206
+ end
207
+ rescue Exception => err
208
+ Logger.error("Error sending periodic cmd(#{cmd_string}):\n#{err.formatted}")
209
+ end
210
+ end
211
+ end
212
+ else
213
+ @scheduler.resume
214
+ end
215
+ end
186
216
  end
187
217
 
188
218
  # Indicates if the interface is connected to its target(s) or not. Must be
@@ -194,6 +224,11 @@ module OpenC3
194
224
  # Disconnects the interface from its target(s). Must be implemented by a
195
225
  # subclass.
196
226
  def disconnect
227
+ periodic_cmds = @options['PERIODIC_CMD']
228
+ if periodic_cmds and @scheduler
229
+ @scheduler.pause
230
+ end
231
+
197
232
  (@read_protocols | @write_protocols).each { |protocol| protocol.disconnect_reset }
198
233
  end
199
234
 
@@ -201,7 +236,7 @@ module OpenC3
201
236
  raise "read_interface not defined by Interface"
202
237
  end
203
238
 
204
- def write_interface
239
+ def write_interface(data, extra = nil)
205
240
  raise "write_interface not defined by Interface"
206
241
  end
207
242
 
@@ -217,9 +252,10 @@ module OpenC3
217
252
  # Protocols may have cached data for a packet, so initially just inject a blank string
218
253
  # Otherwise we can hold off outputing other packets where all the data has already
219
254
  # been received
255
+ extra = nil
220
256
  if !first or @read_protocols.length <= 0
221
257
  # Read data for a packet
222
- data = read_interface()
258
+ data, extra = read_interface()
223
259
  unless data
224
260
  Logger.info("#{@name}: read_interface requested disconnect")
225
261
  return nil
@@ -230,7 +266,12 @@ module OpenC3
230
266
  end
231
267
 
232
268
  @read_protocols.each do |protocol|
233
- data = protocol.read_data(data)
269
+ # Extra check is for backwards compatibility
270
+ if extra
271
+ data, extra = protocol.read_data(data, extra)
272
+ else
273
+ data, extra = protocol.read_data(data)
274
+ end
234
275
  if data == :DISCONNECT
235
276
  Logger.info("#{@name}: Protocol #{protocol.class} read_data requested disconnect")
236
277
  return nil
@@ -239,7 +280,12 @@ module OpenC3
239
280
  end
240
281
  next if data == :STOP
241
282
 
242
- packet = convert_data_to_packet(data)
283
+ # Extra check is for backwards compatibility
284
+ if extra
285
+ packet = convert_data_to_packet(data, extra)
286
+ else
287
+ packet = convert_data_to_packet(data)
288
+ end
243
289
 
244
290
  # Potentially modify packet
245
291
  @read_protocols.each do |protocol|
@@ -283,11 +329,16 @@ module OpenC3
283
329
  return if packet == :STOP
284
330
  end
285
331
 
286
- data = convert_packet_to_data(packet)
332
+ data, extra = convert_packet_to_data(packet)
287
333
 
288
334
  # Potentially modify packet data
289
335
  @write_protocols.each do |protocol|
290
- data = protocol.write_data(data)
336
+ # Extra check is for backwards compatibility
337
+ if extra
338
+ data, extra = protocol.write_data(data, extra)
339
+ else
340
+ data, extra = protocol.write_data(data)
341
+ end
291
342
  if data == :DISCONNECT
292
343
  Logger.info("#{@name}: Protocol #{protocol.class} write_data requested disconnect")
293
344
  disconnect()
@@ -297,11 +348,20 @@ module OpenC3
297
348
  end
298
349
 
299
350
  # Actually write out data if not handled by protocol
300
- write_interface(data)
351
+ # Extra check is for backwards compatibility
352
+ if extra
353
+ write_interface(data, extra)
354
+ else
355
+ write_interface(data)
356
+ end
301
357
 
302
358
  # Potentially block and wait for response
303
359
  @write_protocols.each do |protocol|
304
- packet, data = protocol.post_write_interface(packet, data)
360
+ if extra
361
+ packet, data, extra = protocol.post_write_interface(packet, data, extra)
362
+ else
363
+ packet, data, extra = protocol.post_write_interface(packet, data)
364
+ end
305
365
  if packet == :DISCONNECT
306
366
  Logger.info("#{@name}: Protocol #{protocol.class} post_write_packet requested disconnect")
307
367
  disconnect()
@@ -317,12 +377,12 @@ module OpenC3
317
377
  # Writes preformatted data onto the interface. Malformed data may cause
318
378
  # problems.
319
379
  # @param data [String] The raw data to send out the interface
320
- def write_raw(data)
380
+ def write_raw(data, extra = nil)
321
381
  raise "Interface not connected for write_raw: #{@name}" unless connected?
322
382
  raise "Interface not write-rawable: #{@name}" unless write_raw_allowed?
323
383
 
324
384
  _write do
325
- write_interface(data)
385
+ write_interface(data, extra)
326
386
  end
327
387
  end
328
388
 
@@ -429,15 +489,25 @@ module OpenC3
429
489
  # @param option_name name of the option
430
490
  # @param option_values array of option values
431
491
  def set_option(option_name, option_values)
432
- @options[option_name.upcase] = option_values.clone
492
+ option_name_upcase = option_name.upcase
493
+
494
+ if option_name_upcase == 'PERIODIC_CMD'
495
+ # OPTION PERIODIC_CMD LOG/DONT_LOG 1.0 "INST COLLECT with TYPE NORMAL"
496
+ @options[option_name_upcase] ||= []
497
+ @options[option_name_upcase] << option_values.clone
498
+ else
499
+ @options[option_name_upcase] = option_values.clone
500
+ end
433
501
  end
434
502
 
435
503
  # Called to convert the read data into a OpenC3 Packet object
436
504
  #
437
505
  # @param data [String] Raw packet data
438
506
  # @return [Packet] OpenC3 Packet with buffer filled with data
439
- def convert_data_to_packet(data)
440
- Packet.new(nil, nil, :BIG_ENDIAN, nil, data)
507
+ def convert_data_to_packet(data, extra = nil)
508
+ packet = Packet.new(nil, nil, :BIG_ENDIAN, nil, data)
509
+ packet.extra = extra
510
+ return packet
441
511
  end
442
512
 
443
513
  # Called to convert a packet into the data to send
@@ -445,7 +515,7 @@ module OpenC3
445
515
  # @param packet [Packet] Packet to extract data from
446
516
  # @return data
447
517
  def convert_packet_to_data(packet)
448
- packet.buffer(true) # Copy buffer so logged command isn't modified
518
+ return packet.buffer(true), packet.extra # Copy buffer so logged command isn't modified
449
519
  end
450
520
 
451
521
  # Called to read data and manipulate it until enough data is
@@ -456,7 +526,7 @@ module OpenC3
456
526
  # method is called. Subclasses must implement this method.
457
527
  #
458
528
  # @return [String] Raw packet data
459
- def read_interface_base(data)
529
+ def read_interface_base(data, extra = nil)
460
530
  @read_raw_data_time = Time.now
461
531
  @read_raw_data = data.clone
462
532
  @bytes_read += data.length
@@ -469,7 +539,7 @@ module OpenC3
469
539
  #
470
540
  # @param data [String] Raw packet data
471
541
  # @return [String] The exact data written
472
- def write_interface_base(data)
542
+ def write_interface_base(data, extra = nil)
473
543
  @written_raw_data_time = Time.now
474
544
  @written_raw_data = data.clone
475
545
  @bytes_written += data.length
@@ -196,19 +196,20 @@ module OpenC3
196
196
  return nil
197
197
  end
198
198
  @read_topics << topic
199
- read_interface_base(data)
200
- return data
199
+ extra = nil
200
+ read_interface_base(data, extra)
201
+ return data, extra
201
202
  rescue IOError # Disconnected
202
203
  return nil
203
204
  end
204
205
 
205
206
  # Writes to the socket
206
207
  # @param data [String] Raw packet data
207
- def write_interface(data)
208
- write_interface_base(data)
208
+ def write_interface(data, extra = nil)
209
+ write_interface_base(data, extra)
209
210
  topic = @write_topics.shift
210
211
  @client.publish(topic, data)
211
- data
212
+ return data, extra
212
213
  end
213
214
 
214
215
  # Supported Options
@@ -61,15 +61,16 @@ module OpenC3
61
61
  # protocols giving them the same opportunity.
62
62
  #
63
63
  # @return [String|nil] Data for a packet consisting of the bytes read
64
- def read_data(data)
64
+ def read_data(data, extra = nil)
65
65
  @data << data
66
+ @extra = extra
66
67
 
67
68
  while true
68
69
  control = handle_sync_pattern()
69
70
  return control if control and data.length > 0 # Only return here if not blank string test
70
71
 
71
72
  # Reduce the data to a single packet
72
- packet_data = reduce_to_single_packet()
73
+ packet_data, extra = reduce_to_single_packet()
73
74
  if packet_data == :RESYNC
74
75
  @sync_state = :SEARCHING
75
76
  next if data.length > 0 # Only immediately resync if not blank string test
@@ -81,9 +82,9 @@ module OpenC3
81
82
  # On blank string test, return blank string (unless we had a packet or need disconnect)
82
83
  # The base class handles the special case of returning STOP if on the last protocol in the
83
84
  # chain
84
- return super(data)
85
+ return super(data, extra)
85
86
  else
86
- return packet_data # Return any control code if not on blank string test
87
+ return packet_data, extra # Return any control code if not on blank string test
87
88
  end
88
89
  end
89
90
 
@@ -91,7 +92,7 @@ module OpenC3
91
92
 
92
93
  # Discard leading bytes if necessary
93
94
  packet_data.replace(packet_data[@discard_leading_bytes..-1]) if @discard_leading_bytes > 0
94
- return packet_data
95
+ return packet_data, extra
95
96
  end
96
97
  end
97
98
 
@@ -115,7 +116,7 @@ module OpenC3
115
116
  #
116
117
  # @param data [String] Raw packet data
117
118
  # @return [String] Potentially modified packet data
118
- def write_data(data)
119
+ def write_data(data, extra = nil)
119
120
  # If we're filling the sync pattern and discarding the leading bytes
120
121
  # during a read then we need to put them back during a write.
121
122
  # If we're discarding the bytes then by definition they can't be part
@@ -127,7 +128,7 @@ module OpenC3
127
128
  data, :BIG_ENDIAN, :ERROR)
128
129
  end
129
130
  end
130
- super(data)
131
+ return super(data, extra)
131
132
  end
132
133
 
133
134
  # @return [Boolean] control code (nil, :STOP)
@@ -156,8 +157,7 @@ module OpenC3
156
157
 
157
158
  if found
158
159
  if sync_index != 0
159
- discard_length = @data[0..(sync_index - 1)].length
160
- log_discard(discard_length, true)
160
+ log_discard(sync_index, true)
161
161
  # Delete Data Before Sync Pattern
162
162
  @data.replace(@data[sync_index..-1])
163
163
  end
@@ -165,7 +165,7 @@ module OpenC3
165
165
  return nil
166
166
 
167
167
  else # not found
168
- log_discard(@data[0..sync_index].length, false)
168
+ log_discard(sync_index + 1, false)
169
169
  # Delete Data Before and including first character of suspected sync Pattern
170
170
  @data.replace(@data[(sync_index + 1)..-1])
171
171
  next
@@ -203,7 +203,7 @@ module OpenC3
203
203
  # Reduce to packet data and clear data for next packet
204
204
  packet_data = @data.clone
205
205
  @data.replace('')
206
- packet_data
206
+ return packet_data, @extra
207
207
  end
208
208
  end
209
209
  end
@@ -53,9 +53,9 @@ module OpenC3
53
53
  )
54
54
  end
55
55
 
56
- def read_data(data)
57
- data = super(data)
58
- return data if data.length <= 0 or Symbol === data
56
+ def read_data(data, extra = nil)
57
+ data, extra = super(data, extra)
58
+ return data, extra if data.length <= 0 or Symbol === data
59
59
 
60
60
  result_data = ''
61
61
  while data.length > 1
@@ -75,10 +75,10 @@ module OpenC3
75
75
  end
76
76
  end
77
77
 
78
- return result_data
78
+ return result_data, extra
79
79
  end
80
80
 
81
- def write_data(data)
81
+ def write_data(data, extra = nil)
82
82
  # Intentionally not calling super()
83
83
 
84
84
  need_insert = false
@@ -90,7 +90,7 @@ module OpenC3
90
90
  result_data << data[0..253]
91
91
  data = data[254..-1]
92
92
  need_insert = false
93
- else # index <= 254 or (index.nil? and data.length < 254)
93
+ else # index <= 253 or (index.nil? and data.length < 254)
94
94
  if index
95
95
  result_data << [index + 1].pack('C')
96
96
  if index >= 1
@@ -113,7 +113,7 @@ module OpenC3
113
113
  # Terminate message with 0x00
114
114
  result_data << "\x00"
115
115
 
116
- return result_data
116
+ return result_data, extra
117
117
  end
118
118
  end
119
119
 
@@ -17,7 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/config/config_parser'
@@ -147,8 +147,8 @@ module OpenC3
147
147
  end
148
148
  end
149
149
 
150
- def read_data(data)
151
- return super(data) if data.length <= 0
150
+ def read_data(data, extra = nil)
151
+ return super(data, extra) if data.length <= 0
152
152
 
153
153
  crc = BinaryAccessor.read(@bit_offset, @bit_size, :UINT, data, @endianness)
154
154
  calculated_crc = @crc.calc(data[0...(@bit_offset / 8)])
@@ -163,9 +163,9 @@ module OpenC3
163
163
  new_data = new_data[0...(@bit_offset / 8)]
164
164
  end_range = (@bit_offset + @bit_size) / 8
165
165
  new_data << data[end_range..-1] if end_range != 0
166
- return new_data
166
+ return new_data, extra
167
167
  end
168
- return data
168
+ return data, extra
169
169
  end
170
170
 
171
171
  def write_packet(packet)
@@ -177,7 +177,7 @@ module OpenC3
177
177
  packet
178
178
  end
179
179
 
180
- def write_data(data)
180
+ def write_data(data, extra = nil)
181
181
  unless @write_item_name
182
182
  if @bit_size == 64
183
183
  crc = @crc.calc(data)
@@ -190,7 +190,7 @@ module OpenC3
190
190
  BinaryAccessor.write(crc, -@bit_size, @bit_size, :UINT, data, @endianness, :ERROR)
191
191
  end
192
192
  end
193
- data
193
+ return data, extra
194
194
  end
195
195
  end
196
196
  end
@@ -17,7 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/packets/binary_accessor'
@@ -96,7 +96,7 @@ module OpenC3
96
96
  # If the start of the length field is past what we discard, then the
97
97
  # length field is inside the packet
98
98
  if @length_bit_offset >= (@discard_leading_bytes * 8)
99
- length = calculate_length(packet.buffer.length + @discard_leading_bytes)
99
+ length = calculate_length(packet.buffer(false).length + @discard_leading_bytes)
100
100
  # Subtract off the discarded bytes since they haven't been added yet
101
101
  # Adding bytes happens in the write_data method
102
102
  offset = @length_bit_offset - (@discard_leading_bytes * 8)
@@ -112,8 +112,8 @@ module OpenC3
112
112
  #
113
113
  # @param data [String] Raw packet data
114
114
  # @return [String] Potentially modified packet data
115
- def write_data(data)
116
- data = super(data)
115
+ def write_data(data, extra = nil)
116
+ data, extra = super(data, extra)
117
117
  if @fill_fields
118
118
  # If the start of the length field is before what we discard, then the
119
119
  # length field is outside the packet
@@ -122,7 +122,7 @@ module OpenC3
122
122
  data, @length_endianness, :ERROR)
123
123
  end
124
124
  end
125
- return data
125
+ return data, extra
126
126
  end
127
127
 
128
128
  protected
@@ -162,7 +162,7 @@ module OpenC3
162
162
  packet_data = @data[0..(packet_length - 1)]
163
163
  @data.replace(@data[packet_length..-1])
164
164
 
165
- return packet_data
165
+ return packet_data, @extra
166
166
  end
167
167
  end
168
168
  end
@@ -17,7 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/interfaces/protocols/burst_protocol'
@@ -49,7 +49,11 @@ module OpenC3
49
49
  packet.packet_name = @read_packet_name
50
50
  if @mode == 4 # COSMOS4.3+ Protocol
51
51
  packet.stored = @read_stored
52
- packet.extra = @read_extra
52
+ if packet.extra and @read_extra
53
+ packet.extra.merge(@read_extra)
54
+ else
55
+ packet.extra = @read_extra
56
+ end
53
57
  end
54
58
  return packet
55
59
  end
@@ -75,7 +79,7 @@ module OpenC3
75
79
  return packet
76
80
  end
77
81
 
78
- def write_data(data)
82
+ def write_data(data, extra = nil)
79
83
  data_length = [data.length].pack('N') # UINT32
80
84
  data_to_send = ''
81
85
  data_to_send << @sync_pattern if @sync_pattern
@@ -94,7 +98,7 @@ module OpenC3
94
98
  data_to_send << @write_packet_name
95
99
  data_to_send << data_length
96
100
  data_to_send << data
97
- return data_to_send
101
+ return data_to_send, extra
98
102
  end
99
103
 
100
104
  protected
@@ -200,7 +204,7 @@ module OpenC3
200
204
  return :STOP if packet_data == :STOP
201
205
 
202
206
  @reduction_state = :START
203
- return packet_data
207
+ return packet_data, @extra
204
208
  end
205
209
 
206
210
  raise "Error should never reach end of method #{@reduction_state}"
@@ -29,6 +29,7 @@ module OpenC3
29
29
  class Protocol
30
30
  attr_accessor :interface
31
31
  attr_accessor :allow_empty_data
32
+ attr_accessor :extra
32
33
 
33
34
  # @param allow_empty_data [true/false/nil] Whether or not this protocol will allow an empty string
34
35
  # to be passed down to later Protocols (instead of returning :STOP). Can be true, false, or nil, where
@@ -40,6 +41,7 @@ module OpenC3
40
41
  end
41
42
 
42
43
  def reset
44
+ @extra = nil
43
45
  end
44
46
 
45
47
  def connect_reset
@@ -51,7 +53,7 @@ module OpenC3
51
53
  end
52
54
 
53
55
  # Ensure we have some data in case this is the only protocol
54
- def read_data(data)
56
+ def read_data(data, extra = nil)
55
57
  if data.length <= 0
56
58
  if @allow_empty_data.nil?
57
59
  if @interface and @interface.read_protocols[-1] == self
@@ -63,7 +65,7 @@ module OpenC3
63
65
  return :STOP
64
66
  end
65
67
  end
66
- data
68
+ return data, extra
67
69
  end
68
70
 
69
71
  def read_packet(packet)
@@ -74,12 +76,12 @@ module OpenC3
74
76
  return packet
75
77
  end
76
78
 
77
- def write_data(data)
78
- return data
79
+ def write_data(data, extra = nil)
80
+ return data, extra
79
81
  end
80
82
 
81
- def post_write_interface(packet, data)
82
- return packet, data
83
+ def post_write_interface(packet, data, extra = nil)
84
+ return packet, data, extra
83
85
  end
84
86
 
85
87
  def protocol_cmd(cmd_name, *cmd_args)
@@ -55,7 +55,7 @@ module OpenC3
55
55
  allow_empty_data = nil)
56
56
 
57
57
  @start_char = ConfigParser.handle_nil(start_char)
58
- @start_char = [Integer(end_char)].pack('C') if @start_char
58
+ @start_char = [Integer(start_char)].pack('C') if @start_char
59
59
  @end_char = [Integer(end_char)].pack('C')
60
60
  @esc_char = [Integer(esc_char)].pack('C')
61
61
  @esc_end_char = [Integer(esc_end_char)].pack('C')
@@ -89,9 +89,9 @@ module OpenC3
89
89
  )
90
90
  end
91
91
 
92
- def read_data(data)
93
- data = super(data)
94
- return data if data.length <= 0 or Symbol === data
92
+ def read_data(data, extra = nil)
93
+ data, extra = super(data, extra)
94
+ return data, extra if data.length <= 0 or Symbol === data
95
95
 
96
96
  if @read_strip_characters
97
97
  if @start_char
@@ -104,10 +104,10 @@ module OpenC3
104
104
  data = data.gsub(@replace_end, @end_char).gsub(@replace_esc, @esc_char)
105
105
  end
106
106
 
107
- return data
107
+ return data, extra
108
108
  end
109
109
 
110
- def write_data(data)
110
+ def write_data(data, extra = nil)
111
111
  # Intentionally not calling super()
112
112
 
113
113
  if @write_enable_escaping
@@ -120,7 +120,7 @@ module OpenC3
120
120
 
121
121
  data << @end_char
122
122
 
123
- return data
123
+ return data, extra
124
124
  end
125
125
 
126
126
  def reduce_to_single_packet
@@ -140,7 +140,7 @@ module OpenC3
140
140
  packet_data = @data[0..(@read_termination_characters.length - 1)]
141
141
  end
142
142
  @data.replace(@data[(index + @read_termination_characters.length)..-1])
143
- return packet_data
143
+ return packet_data, @extra
144
144
  else
145
145
  return :STOP
146
146
  end
@@ -17,7 +17,7 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/config/config_parser'
@@ -108,8 +108,8 @@ module OpenC3
108
108
  @write_block_queue << nil # Unblock the write block queue
109
109
  end
110
110
 
111
- def read_data(data)
112
- return super(data) if data.length <= 0
111
+ def read_data(data, extra = nil)
112
+ return super(data, extra) if data.length <= 0
113
113
 
114
114
  # Drop all data until the initial_read_delay is complete.
115
115
  # This gets rid of unused welcome messages,
@@ -119,7 +119,7 @@ module OpenC3
119
119
 
120
120
  @initial_read_delay_needed = false
121
121
  end
122
- super(data)
122
+ return super(data, extra)
123
123
  end
124
124
 
125
125
  def read_packet(packet)
@@ -165,7 +165,6 @@ module OpenC3
165
165
  result_packet.write(response_item_names[i], value)
166
166
  rescue => error
167
167
  handle_error("#{@interface ? @interface.name : ""}: Could not write value #{value} due to #{error.message}")
168
- break
169
168
  end
170
169
  end
171
170
 
@@ -230,7 +229,7 @@ module OpenC3
230
229
  return raw_packet
231
230
  end
232
231
 
233
- def post_write_interface(packet, data)
232
+ def post_write_interface(packet, data, extra = nil)
234
233
  if @response_template && @response_packet
235
234
  if @response_timeout
236
235
  response_timeout_time = Time.now + @response_timeout
@@ -253,7 +252,7 @@ module OpenC3
253
252
  @response_target_name = nil
254
253
  @response_packets.clear
255
254
  end
256
- return super(packet, data)
255
+ return super(packet, data, extra)
257
256
  end
258
257
 
259
258
  def handle_error(msg)