openc3 5.17.0 → 5.18.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.

Potentially problematic release.


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

Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +1 -1
  3. data/data/config/_interfaces.yaml +4 -4
  4. data/data/config/command_modifiers.yaml +4 -0
  5. data/data/config/interface_modifiers.yaml +18 -8
  6. data/data/config/item_modifiers.yaml +34 -26
  7. data/data/config/microservice.yaml +4 -1
  8. data/data/config/param_item_modifiers.yaml +16 -0
  9. data/data/config/parameter_modifiers.yaml +29 -12
  10. data/data/config/plugins.yaml +3 -3
  11. data/data/config/screen.yaml +7 -7
  12. data/data/config/telemetry_modifiers.yaml +9 -4
  13. data/data/config/widgets.yaml +41 -14
  14. data/ext/openc3/ext/packet/packet.c +6 -0
  15. data/lib/openc3/accessors/accessor.rb +1 -0
  16. data/lib/openc3/accessors/binary_accessor.rb +170 -11
  17. data/lib/openc3/api/cmd_api.rb +39 -35
  18. data/lib/openc3/api/config_api.rb +10 -10
  19. data/lib/openc3/api/interface_api.rb +28 -21
  20. data/lib/openc3/api/limits_api.rb +29 -29
  21. data/lib/openc3/api/metrics_api.rb +3 -3
  22. data/lib/openc3/api/offline_access_api.rb +5 -5
  23. data/lib/openc3/api/router_api.rb +25 -19
  24. data/lib/openc3/api/settings_api.rb +10 -10
  25. data/lib/openc3/api/stash_api.rb +10 -10
  26. data/lib/openc3/api/target_api.rb +10 -10
  27. data/lib/openc3/api/tlm_api.rb +44 -44
  28. data/lib/openc3/conversions/bit_reverse_conversion.rb +60 -0
  29. data/lib/openc3/conversions/ip_read_conversion.rb +59 -0
  30. data/lib/openc3/conversions/ip_write_conversion.rb +61 -0
  31. data/lib/openc3/conversions/object_read_conversion.rb +88 -0
  32. data/lib/openc3/conversions/object_write_conversion.rb +38 -0
  33. data/lib/openc3/conversions.rb +6 -1
  34. data/lib/openc3/io/json_drb.rb +19 -21
  35. data/lib/openc3/io/json_rpc.rb +14 -13
  36. data/lib/openc3/microservices/microservice.rb +11 -11
  37. data/lib/openc3/microservices/scope_cleanup_microservice.rb +1 -1
  38. data/lib/openc3/microservices/timeline_microservice.rb +76 -51
  39. data/lib/openc3/models/activity_model.rb +25 -21
  40. data/lib/openc3/models/scope_model.rb +44 -13
  41. data/lib/openc3/models/sorted_model.rb +1 -1
  42. data/lib/openc3/models/target_model.rb +4 -1
  43. data/lib/openc3/operators/microservice_operator.rb +2 -2
  44. data/lib/openc3/operators/operator.rb +9 -9
  45. data/lib/openc3/packets/packet.rb +18 -1
  46. data/lib/openc3/packets/packet_config.rb +37 -16
  47. data/lib/openc3/packets/packet_item.rb +5 -0
  48. data/lib/openc3/packets/structure.rb +67 -3
  49. data/lib/openc3/packets/structure_item.rb +49 -12
  50. data/lib/openc3/script/calendar.rb +2 -2
  51. data/lib/openc3/script/extract.rb +5 -3
  52. data/lib/openc3/script/web_socket_api.rb +11 -0
  53. data/lib/openc3/topics/decom_interface_topic.rb +2 -1
  54. data/lib/openc3/topics/system_events_topic.rb +40 -0
  55. data/lib/openc3/utilities/authentication.rb +2 -1
  56. data/lib/openc3/utilities/authorization.rb +2 -2
  57. data/lib/openc3/version.rb +5 -5
  58. data/templates/tool_angular/package.json +5 -5
  59. data/templates/tool_react/package.json +8 -8
  60. data/templates/tool_svelte/package.json +10 -10
  61. data/templates/tool_vue/package.json +10 -10
  62. data/templates/widget/package.json +10 -10
  63. data/templates/widget/src/Widget.vue +0 -1
  64. metadata +22 -2
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -85,8 +85,6 @@ module OpenC3
85
85
  # Valid overflow types
86
86
  OVERFLOW_TYPES = [:TRUNCATE, :SATURATE, :ERROR, :ERROR_ALLOW_HEX]
87
87
 
88
- protected
89
-
90
88
  # Determines the endianness of the host running this code
91
89
  #
92
90
  # This method is protected to force the use of the constant
@@ -108,13 +106,175 @@ module OpenC3
108
106
  raise ArgumentError, "#{buffer.length} byte buffer insufficient to #{read_write} #{data_type} at bit_offset #{given_bit_offset} with bit_size #{given_bit_size}"
109
107
  end
110
108
 
111
- public
112
-
113
109
  # Store the host endianness so that it only has to be determined once
114
110
  HOST_ENDIANNESS = get_host_endianness()
115
111
  # Valid endianess
116
112
  ENDIANNESS = [:BIG_ENDIAN, :LITTLE_ENDIAN]
117
113
 
114
+ def handle_read_variable_bit_size(item, _buffer)
115
+ length_value = @packet.read(item.variable_bit_size['length_item_name'], :CONVERTED)
116
+ if item.array_size
117
+ item.array_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
118
+ else
119
+ if item.data_type == :INT or item.data_type == :UINT
120
+ # QUIC encoding is currently assumed for individual variable sized integers
121
+ # see https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc
122
+ case length_value
123
+ when 0
124
+ item.bit_size = 6
125
+ when 1
126
+ item.bit_size = 14
127
+ when 2
128
+ item.bit_size = 30
129
+ else
130
+ item.bit_size = 62
131
+ end
132
+ else
133
+ item.bit_size = (length_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
134
+ end
135
+ end
136
+ end
137
+
138
+ def read_item(item, buffer)
139
+ return nil if item.data_type == :DERIVED
140
+ handle_read_variable_bit_size(item, buffer) if item.variable_bit_size
141
+ self.class.read_item(item, buffer)
142
+ end
143
+
144
+ def handle_write_variable_bit_size(item, value, buffer)
145
+ # Update length field to new size
146
+ if (item.data_type == :INT or item.data_type == :UINT) and not item.original_array_size
147
+ # QUIC encoding is currently assumed for individual variable sized integers
148
+ # see https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc
149
+
150
+ # Calculate current bit size so we can preserve bytes after the item
151
+ length_item_value = @packet.read(item.variable_bit_size['length_item_name'], :CONVERTED)
152
+ case length_item_value
153
+ when 0
154
+ current_bit_size = 6
155
+ when 1
156
+ current_bit_size = 14
157
+ when 2
158
+ current_bit_size = 30
159
+ when 3
160
+ current_bit_size = 62
161
+ else
162
+ raise "Value #{item.variable_bit_size['length_item_name']} has unknown QUIC bit size encoding: #{length_item_value}"
163
+ end
164
+
165
+ if item.data_type == :UINT
166
+ if value <= 63
167
+ # Length = 0, value up to 6-bits
168
+ new_bit_size = 6
169
+ item.bit_size = new_bit_size
170
+ @packet.write(item.variable_bit_size['length_item_name'], 0)
171
+ elsif value <= 16383
172
+ # Length = 1, value up to 14-bits
173
+ new_bit_size = 14
174
+ item.bit_size = new_bit_size
175
+ @packet.write(item.variable_bit_size['length_item_name'], 1)
176
+ elsif value <= 1073741823
177
+ # Length = 2, value up to 30-bits
178
+ new_bit_size = 30
179
+ item.bit_size = new_bit_size
180
+ @packet.write(item.variable_bit_size['length_item_name'], 2)
181
+ else
182
+ # Length = 3, value up to 62-bits
183
+ new_bit_size = 62
184
+ item.bit_size = new_bit_size
185
+ @packet.write(item.variable_bit_size['length_item_name'], 3)
186
+ end
187
+ else
188
+ if value <= 31 and value >= -32
189
+ # Length = 0, value up to 6-bits
190
+ new_bit_size = 6
191
+ item.bit_size = new_bit_size
192
+ @packet.write(item.variable_bit_size['length_item_name'], 0)
193
+ elsif value <= 8191 and value >= -8192
194
+ # Length = 1, value up to 14-bits
195
+ new_bit_size = 14
196
+ item.bit_size = new_bit_size
197
+ @packet.write(item.variable_bit_size['length_item_name'], 1)
198
+ elsif value <= 536870911 and value >= -536870912
199
+ # Length = 2, value up to 30-bits
200
+ new_bit_size = 30
201
+ item.bit_size = new_bit_size
202
+ @packet.write(item.variable_bit_size['length_item_name'], 2)
203
+ else
204
+ # Length = 3, value up to 62-bits
205
+ new_bit_size = 62
206
+ item.bit_size = new_bit_size
207
+ @packet.write(item.variable_bit_size['length_item_name'], 3)
208
+ end
209
+ end
210
+
211
+ # Later items need their bit_offset adjusted by the change in this item
212
+ adjustment = new_bit_size - current_bit_size
213
+ bytes = (adjustment / 8)
214
+ item_offset = item.bit_offset / 8
215
+ if bytes > 0
216
+ original_length = buffer.length
217
+ # Add extra bytes because we're adjusting larger
218
+ buffer << ("\000" * bytes)
219
+ # We added bytes to the end so now we have to shift the buffer over
220
+ # NOTE: buffer[offset, length]
221
+ # We copy to the shifted offset location with the remaining buffer length
222
+ buffer[item_offset + bytes, buffer.length - (item_offset + bytes)] =
223
+ # We copy from the original offset location with the original length minus the offset
224
+ buffer[item_offset, original_length - item_offset]
225
+ elsif bytes < 0
226
+ # Remove extra bytes because we're adjusting smaller
227
+ buffer[item_offset + 1, -bytes] = ''
228
+ end
229
+ # Probably not possible to get this condition because we don't allow 0 sized floats
230
+ # but check for it just to cover all the possible data_types
231
+ elsif item.data_type == :FLOAT
232
+ raise "Variable bit size not currently supported for FLOAT data type"
233
+ else
234
+ # STRING, BLOCK, or array types
235
+
236
+ # Calculate current bit size so we can preserve bytes after the item
237
+ length_item_value = @packet.read(item.variable_bit_size['length_item_name'], :CONVERTED)
238
+ current_bit_size = (length_item_value * item.variable_bit_size['length_bits_per_count']) + item.variable_bit_size['length_value_bit_offset']
239
+
240
+ # Calculate bits after this item
241
+ bits_with_item = item.bit_offset + current_bit_size
242
+ bits_after_item = (buffer.length * 8) - bits_with_item
243
+ if item.original_array_size
244
+ item.array_size = -bits_after_item
245
+ else
246
+ item.bit_size = -bits_after_item
247
+ end
248
+
249
+ new_bit_size = value.length * 8
250
+ length_value = (new_bit_size - item.variable_bit_size['length_value_bit_offset']) / item.variable_bit_size['length_bits_per_count']
251
+ @packet.write(item.variable_bit_size['length_item_name'], length_value)
252
+
253
+ # Later items need their bit_offset adjusted by the change in this item
254
+ adjustment = new_bit_size - current_bit_size
255
+ end
256
+
257
+ # Recalculate bit offsets after this item
258
+ if adjustment != 0 and item.bit_offset >= 0
259
+ @packet.sorted_items.each do |sitem|
260
+ if sitem.data_type == :DERIVED or sitem.bit_offset < item.bit_offset
261
+ # Skip items before this item and derived items and items with negative bit offsets
262
+ next
263
+ end
264
+ if sitem != item
265
+ sitem.bit_offset += adjustment
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+ def write_item(item, value, buffer)
272
+ return nil if item.data_type == :DERIVED
273
+ handle_write_variable_bit_size(item, value, buffer) if item.variable_bit_size
274
+ self.class.write_item(item, value, buffer)
275
+ end
276
+
277
+ # Note: do not use directly - use instance read_item
118
278
  def self.read_item(item, buffer)
119
279
  return nil if item.data_type == :DERIVED
120
280
  if item.array_size
@@ -124,6 +284,7 @@ module OpenC3
124
284
  end
125
285
  end
126
286
 
287
+ # Note: do not use directly - use instance write_item
127
288
  def self.write_item(item, value, buffer)
128
289
  return nil if item.data_type == :DERIVED
129
290
  if item.array_size
@@ -388,7 +549,7 @@ module OpenC3
388
549
  # String was completely empty
389
550
  if end_bytes > 0
390
551
  # Preserve bytes at end of buffer
391
- buffer << "\000" * value.length
552
+ buffer << ("\000" * value.length)
392
553
  buffer[lower_bound + value.length, end_bytes] = buffer[lower_bound, end_bytes]
393
554
  end
394
555
  elsif bit_size == 0
@@ -400,7 +561,7 @@ module OpenC3
400
561
  elsif (upper_bound > old_upper_bound) && (end_bytes > 0)
401
562
  # Preserve bytes at end of buffer
402
563
  diff = upper_bound - old_upper_bound
403
- buffer << "\000" * diff
564
+ buffer << ("\000" * diff)
404
565
  buffer[upper_bound + 1, end_bytes] = buffer[old_upper_bound + 1, end_bytes]
405
566
  end
406
567
  else # given_bit_size > 0
@@ -587,7 +748,6 @@ module OpenC3
587
748
  return value
588
749
  end
589
750
 
590
- protected
591
751
 
592
752
  # Check the bit size and bit offset for problems. Recalulate the bit offset
593
753
  # and return back through the passed in pointer.
@@ -705,7 +865,6 @@ module OpenC3
705
865
  (bit_size == 8) || (bit_size == 16) || (bit_size == 32) || (bit_size == 64)
706
866
  end
707
867
 
708
- public
709
868
 
710
869
  end
711
870
 
@@ -948,7 +1107,7 @@ module OpenC3
948
1107
  # Grow buffer and preserve bytes at end of buffer if necesssary
949
1108
  buffer_length = buffer.length
950
1109
  diff = upper_bound - old_upper_bound
951
- buffer << ZERO_STRING * diff
1110
+ buffer << (ZERO_STRING * diff)
952
1111
  if end_bytes > 0
953
1112
  buffer[(upper_bound + 1)..(buffer.length - 1)] = buffer[(old_upper_bound + 1)..(buffer_length - 1)]
954
1113
  end
@@ -975,7 +1134,7 @@ module OpenC3
975
1134
  end
976
1135
 
977
1136
  # Ensure the buffer has enough room
978
- if bit_offset + num_writes * bit_size > buffer.length * 8
1137
+ if bit_offset + (num_writes * bit_size) > buffer.length * 8
979
1138
  raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size)
980
1139
  end
981
1140
 
@@ -20,6 +20,7 @@
20
20
  # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
+ require 'openc3/api/interface_api'
23
24
  require 'openc3/models/target_model'
24
25
  require 'openc3/topics/command_topic'
25
26
  require 'openc3/topics/command_decom_topic'
@@ -107,7 +108,7 @@ module OpenC3
107
108
  # Build a command binary
108
109
  #
109
110
  # @since 5.8.0
110
- def build_cmd(*args, range_check: true, raw: false, scope: $openc3_scope, token: $openc3_token, **kwargs)
111
+ def build_cmd(*args, range_check: true, raw: false, manual: false, scope: $openc3_scope, token: $openc3_token, **kwargs)
111
112
  extract_string_kwargs_to_args(args, kwargs)
112
113
  case args.length
113
114
  when 1
@@ -127,31 +128,31 @@ module OpenC3
127
128
  target_name = target_name.upcase
128
129
  cmd_name = cmd_name.upcase
129
130
  cmd_params = cmd_params.transform_keys(&:upcase)
130
- authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
131
+ authorize(permission: 'cmd_info', target_name: target_name, manual: manual, scope: scope, token: token)
131
132
  DecomInterfaceTopic.build_cmd(target_name, cmd_name, cmd_params, range_check, raw, scope: scope)
132
133
  end
133
134
  # build_command is DEPRECATED
134
135
  alias build_command build_cmd
135
136
 
136
137
  # Helper method for disable_cmd / enable_cmd
137
- def _get_and_set_cmd(method, *args, scope: $openc3_scope, token: $openc3_token)
138
+ def _get_and_set_cmd(method, *args, manual:, scope:, token:)
138
139
  target_name, command_name = _extract_target_command_names(method, *args)
139
- authorize(permission: 'admin', target_name: target_name, packet_name: command_name, scope: scope, token: token)
140
+ authorize(permission: 'admin', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
140
141
  command = yield TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
141
142
  TargetModel.set_packet(target_name, command_name, command, type: :CMD, scope: scope)
142
143
  end
143
144
 
144
145
  # @since 5.15.1
145
- def enable_cmd(*args, scope: $openc3_scope, token: $openc3_token)
146
- _get_and_set_cmd('enable_cmd', *args, scope: scope, token: token) do |command|
146
+ def enable_cmd(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
147
+ _get_and_set_cmd('enable_cmd', *args, manual: manual, scope: scope, token: token) do |command|
147
148
  command['disabled'] = false
148
149
  command
149
150
  end
150
151
  end
151
152
 
152
153
  # @since 5.15.1
153
- def disable_cmd(*args, scope: $openc3_scope, token: $openc3_token)
154
- _get_and_set_cmd('disable_cmd', *args, scope: scope, token: token) do |command|
154
+ def disable_cmd(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
155
+ _get_and_set_cmd('disable_cmd', *args, manual: manual, scope: scope, token: token) do |command|
155
156
  command['disabled'] = true
156
157
  command
157
158
  end
@@ -161,10 +162,13 @@ module OpenC3
161
162
  #
162
163
  # @param interface_name [String] The interface to send the raw binary
163
164
  # @param data [String] The raw binary data
164
- def send_raw(interface_name, data, scope: $openc3_scope, token: $openc3_token)
165
+ def send_raw(interface_name, data, manual: false, scope: $openc3_scope, token: $openc3_token)
165
166
  interface_name = interface_name.upcase
166
- authorize(permission: 'cmd_raw', interface_name: interface_name, scope: scope, token: token)
167
- get_interface(interface_name, scope: scope, token: token) # Check to make sure the interface exists
167
+ interface = get_interface(interface_name, scope: scope, token: token)
168
+ # Verify we have command authority on all the targets mapped to this interface
169
+ interface['cmd_target_names'].each do |target_name|
170
+ authorize(permission: 'cmd_raw', interface_name: interface_name, target_name: target_name, manual: manual, scope: scope, token: token)
171
+ end
168
172
  InterfaceTopic.write_raw(interface_name, data, scope: scope)
169
173
  end
170
174
 
@@ -173,9 +177,9 @@ module OpenC3
173
177
  # @param target_name [String] Target name of the command
174
178
  # @param command_name [String] Packet name of the command
175
179
  # @return [Hash] command hash with last command buffer
176
- def get_cmd_buffer(*args, scope: $openc3_scope, token: $openc3_token)
180
+ def get_cmd_buffer(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
177
181
  target_name, command_name = _extract_target_command_names('get_cmd_buffer', *args)
178
- authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
182
+ authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
179
183
  TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
180
184
  topic = "#{scope}__COMMAND__{#{target_name}}__#{command_name}"
181
185
  msg_id, msg_hash = Topic.get_newest_message(topic)
@@ -191,9 +195,9 @@ module OpenC3
191
195
  # @since 5.0.0
192
196
  # @param target_name [String] Name of the target
193
197
  # @return [Array<Hash>] Array of all commands as a hash
194
- def get_all_cmds(target_name, scope: $openc3_scope, token: $openc3_token)
198
+ def get_all_cmds(target_name, manual: false, scope: $openc3_scope, token: $openc3_token)
195
199
  target_name = target_name.upcase
196
- authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
200
+ authorize(permission: 'cmd_info', target_name: target_name, manual: manual, scope: scope, token: token)
197
201
  TargetModel.packets(target_name, type: :CMD, scope: scope)
198
202
  end
199
203
  # get_all_commands is DEPRECATED
@@ -204,7 +208,7 @@ module OpenC3
204
208
  # @since 5.0.6
205
209
  # @param target_name [String] Name of the target
206
210
  # @return [Array<String>] Array of all command packet names
207
- def get_all_cmd_names(target_name, hidden: false, scope: $openc3_scope, token: $openc3_token)
211
+ def get_all_cmd_names(target_name, hidden: false, manual: false, scope: $openc3_scope, token: $openc3_token)
208
212
  begin
209
213
  packets = get_all_cmds(target_name, scope: scope, token: token)
210
214
  rescue RuntimeError
@@ -227,9 +231,9 @@ module OpenC3
227
231
  #
228
232
  # @since 5.0.0
229
233
  # @return [Hash] Command as a hash
230
- def get_cmd(*args, scope: $openc3_scope, token: $openc3_token)
234
+ def get_cmd(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
231
235
  target_name, command_name = _extract_target_command_names('get_cmd', *args)
232
- authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
236
+ authorize(permission: 'cmd_info', target_name: target_name, manual: manual, scope: scope, token: token)
233
237
  TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
234
238
  end
235
239
  # get_command is DEPRECATED
@@ -242,9 +246,9 @@ module OpenC3
242
246
  # @param command_name [String] Name of the packet
243
247
  # @param parameter_name [String] Name of the parameter
244
248
  # @return [Hash] Command parameter as a hash
245
- def get_param(*args, scope: $openc3_scope, token: $openc3_token)
249
+ def get_param(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
246
250
  target_name, command_name, parameter_name = _extract_target_command_parameter_names('get_param', *args)
247
- authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
251
+ authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
248
252
  TargetModel.packet_item(target_name, command_name, parameter_name, type: :CMD, scope: scope)
249
253
  end
250
254
  # get_parameter is DEPRECATED
@@ -258,7 +262,7 @@ module OpenC3
258
262
  #
259
263
  # @param args [String|Array<String>] See the description for calling style
260
264
  # @return [Boolean] Whether the command is hazardous
261
- def get_cmd_hazardous(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
265
+ def get_cmd_hazardous(*args, manual: false, scope: $openc3_scope, token: $openc3_token, **kwargs)
262
266
  extract_string_kwargs_to_args(args, kwargs)
263
267
  case args.length
264
268
  when 1
@@ -279,7 +283,7 @@ module OpenC3
279
283
  command_name = command_name.upcase
280
284
  parameters = parameters.transform_keys(&:upcase)
281
285
 
282
- authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
286
+ authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
283
287
  packet = TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
284
288
  return true if packet['hazardous']
285
289
 
@@ -307,7 +311,7 @@ module OpenC3
307
311
  # get_cmd_value("TGT PKT ITEM", type: :RAW)
308
312
  # get_cmd_value("TGT", "PKT", "ITEM", type: :RAW)
309
313
  # get_cmd_value("TGT", "PKT", "ITEM", :RAW) # DEPRECATED
310
- def get_cmd_value(*args, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
314
+ def get_cmd_value(*args, type: :CONVERTED, manual: false, scope: $openc3_scope, token: $openc3_token)
311
315
  target_name = nil
312
316
  command_name = nil
313
317
  parameter_name = nil
@@ -330,7 +334,7 @@ module OpenC3
330
334
  if target_name.nil? or command_name.nil? or parameter_name.nil?
331
335
  raise "ERROR: Target name, command name and parameter name required. Usage: get_cmd_value(\"TGT CMD PARAM\") or #{method_name}(\"TGT\", \"CMD\", \"PARAM\")"
332
336
  end
333
- authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
337
+ authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
334
338
  CommandDecomTopic.get_cmd_item(target_name, command_name, parameter_name, type: type, scope: scope)
335
339
  end
336
340
 
@@ -341,8 +345,8 @@ module OpenC3
341
345
  # @param command_name [String] Packet name of the command. If not given then
342
346
  # then most recent time from the given target will be returned.
343
347
  # @return [Array<Target Name, Command Name, Time Seconds, Time Microseconds>]
344
- def get_cmd_time(target_name = nil, command_name = nil, scope: $openc3_scope, token: $openc3_token)
345
- authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
348
+ def get_cmd_time(target_name = nil, command_name = nil, manual: false, scope: $openc3_scope, token: $openc3_token)
349
+ authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
346
350
  if target_name and command_name
347
351
  target_name = target_name.upcase
348
352
  command_name = command_name.upcase
@@ -379,9 +383,9 @@ module OpenC3
379
383
  # @param target_name [String] Target name of the command
380
384
  # @param command_name [String] Packet name of the command
381
385
  # @return [Numeric] Transmit count for the command
382
- def get_cmd_cnt(*args, scope: $openc3_scope, token: $openc3_token)
386
+ def get_cmd_cnt(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
383
387
  target_name, command_name = _extract_target_command_names('get_cmd_cnt', *args)
384
- authorize(permission: 'system', target_name: target_name, packet_name: command_name, scope: scope, token: token)
388
+ authorize(permission: 'system', target_name: target_name, packet_name: command_name, manual: manual, scope: scope, token: token)
385
389
  TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
386
390
  Topic.get_cnt("#{scope}__COMMAND__{#{target_name}}__#{command_name}")
387
391
  end
@@ -390,8 +394,8 @@ module OpenC3
390
394
  #
391
395
  # @param target_commands [Array<Array<String, String>>] Array of arrays containing target_name, packet_name
392
396
  # @return [Numeric] Transmit count for the command
393
- def get_cmd_cnts(target_commands, scope: $openc3_scope, token: $openc3_token)
394
- authorize(permission: 'system', scope: scope, token: token)
397
+ def get_cmd_cnts(target_commands, manual: false, scope: $openc3_scope, token: $openc3_token)
398
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
395
399
  unless target_commands.is_a?(Array) and target_commands[0].is_a?(Array)
396
400
  raise "get_cmd_cnts takes an array of arrays containing target, packet_name, e.g. [['INST', 'COLLECT'], ['INST', 'ABORT']]"
397
401
  end
@@ -448,8 +452,8 @@ module OpenC3
448
452
  return [target_name, command_name, parameter_name]
449
453
  end
450
454
 
451
- def _cmd_implementation(method_name, *args, range_check:, hazardous_check:, raw:, timeout: nil, log_message: nil,
452
- scope: $openc3_scope, token: $openc3_token, **kwargs)
455
+ def _cmd_implementation(method_name, *args, range_check:, hazardous_check:, raw:, timeout: nil, log_message: nil, manual: false,
456
+ scope: $openc3_scope, token: $openc3_token, **kwargs)
453
457
  extract_string_kwargs_to_args(args, kwargs)
454
458
  unless [nil, true, false].include?(log_message)
455
459
  raise "Invalid log_message parameter: #{log_message}. Must be true or false."
@@ -480,7 +484,7 @@ module OpenC3
480
484
  target_name = target_name.upcase
481
485
  cmd_name = cmd_name.upcase
482
486
  cmd_params = cmd_params.transform_keys(&:upcase)
483
- authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, scope: scope, token: token)
487
+ authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, manual: manual, scope: scope, token: token)
484
488
  packet = TargetModel.packet(target_name, cmd_name, type: :CMD, scope: scope)
485
489
  if packet['disabled']
486
490
  error = DisabledError.new
@@ -503,7 +507,7 @@ module OpenC3
503
507
  log_message = false if packet["messages_disabled"]
504
508
  # Check if any of the parameters have DISABLE_MESSAGES
505
509
  cmd_params.each do |key, value|
506
- item = packet['items'].find { |item| item['name'] == key.to_s }
510
+ item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
507
511
  if item && item['states'] && item['states'][value] && item['states'][value]["messages_disabled"]
508
512
  log_message = false
509
513
  end
@@ -525,7 +529,7 @@ module OpenC3
525
529
  cmd_params.each do |key, value|
526
530
  next if Packet::RESERVED_ITEM_NAMES.include?(key)
527
531
 
528
- item = packet['items'].find { |item| item['name'] == key.to_s }
532
+ item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
529
533
 
530
534
  begin
531
535
  item_type = item['data_type'].intern
@@ -33,28 +33,28 @@ module OpenC3
33
33
  'delete_config'
34
34
  ])
35
35
 
36
- def config_tool_names(scope: $openc3_scope, token: $openc3_token)
37
- authorize(permission: 'system', scope: scope, token: token)
36
+ def config_tool_names(manual: false, scope: $openc3_scope, token: $openc3_token)
37
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
38
38
  ToolConfigModel.config_tool_names(scope: scope)
39
39
  end
40
40
 
41
- def list_configs(tool, scope: $openc3_scope, token: $openc3_token)
42
- authorize(permission: 'system', scope: scope, token: token)
41
+ def list_configs(tool, manual: false, scope: $openc3_scope, token: $openc3_token)
42
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
43
43
  ToolConfigModel.list_configs(tool, scope: scope)
44
44
  end
45
45
 
46
- def load_config(tool, name, scope: $openc3_scope, token: $openc3_token)
47
- authorize(permission: 'system', scope: scope, token: token)
46
+ def load_config(tool, name, manual: false, scope: $openc3_scope, token: $openc3_token)
47
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
48
48
  ToolConfigModel.load_config(tool, name, scope: scope)
49
49
  end
50
50
 
51
- def save_config(tool, name, data, scope: $openc3_scope, token: $openc3_token)
52
- authorize(permission: 'system_set', scope: scope, token: token)
51
+ def save_config(tool, name, data, manual: false, scope: $openc3_scope, token: $openc3_token)
52
+ authorize(permission: 'system_set', manual: manual, scope: scope, token: token)
53
53
  ToolConfigModel.save_config(tool, name, data, scope: scope)
54
54
  end
55
55
 
56
- def delete_config(tool, name, scope: $openc3_scope, token: $openc3_token)
57
- authorize(permission: 'system_set', scope: scope, token: token)
56
+ def delete_config(tool, name, manual: false, scope: $openc3_scope, token: $openc3_token)
57
+ authorize(permission: 'system_set', manual: manual, scope: scope, token: token)
58
58
  ToolConfigModel.delete_config(tool, name, scope: scope)
59
59
  end
60
60
  end
@@ -45,8 +45,8 @@ module OpenC3
45
45
  # @since 5.0.0
46
46
  # @param interface_name [String] Interface name
47
47
  # @return [Hash] Hash of all the interface information
48
- def get_interface(interface_name, scope: $openc3_scope, token: $openc3_token)
49
- authorize(permission: 'system', interface_name: interface_name, scope: scope, token: token)
48
+ def get_interface(interface_name, manual: false, scope: $openc3_scope, token: $openc3_token)
49
+ authorize(permission: 'system', interface_name: interface_name, manual: manual, scope: scope, token: token)
50
50
  interface = InterfaceModel.get(name: interface_name, scope: scope)
51
51
  raise "Interface '#{interface_name}' does not exist" unless interface
52
52
 
@@ -54,8 +54,8 @@ module OpenC3
54
54
  end
55
55
 
56
56
  # @return [Array<String>] All the interface names
57
- def get_interface_names(scope: $openc3_scope, token: $openc3_token)
58
- authorize(permission: 'system', scope: scope, token: token)
57
+ def get_interface_names(manual: false, scope: $openc3_scope, token: $openc3_token)
58
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
59
59
  InterfaceModel.names(scope: scope)
60
60
  end
61
61
 
@@ -63,24 +63,27 @@ module OpenC3
63
63
  #
64
64
  # @param interface_name [String] The name of the interface
65
65
  # @param interface_params [Array] Optional parameters to pass to the interface
66
- def connect_interface(interface_name, *interface_params, scope: $openc3_scope, token: $openc3_token)
67
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
66
+ def connect_interface(interface_name, *interface_params, manual: false, scope: $openc3_scope, token: $openc3_token)
67
+ # TODO: Check if they have command authority for the targets mapped to this interface
68
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
68
69
  InterfaceTopic.connect_interface(interface_name, *interface_params, scope: scope)
69
70
  end
70
71
 
71
72
  # Disconnects from an interface and kills its telemetry gathering thread
72
73
  #
73
74
  # @param interface_name [String] The name of the interface
74
- def disconnect_interface(interface_name, scope: $openc3_scope, token: $openc3_token)
75
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
75
+ def disconnect_interface(interface_name, manual: false, scope: $openc3_scope, token: $openc3_token)
76
+ # TODO: Check if they have command authority for the targets mapped to this interface
77
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
76
78
  InterfaceTopic.disconnect_interface(interface_name, scope: scope)
77
79
  end
78
80
 
79
81
  # Starts raw logging for an interface
80
82
  #
81
83
  # @param interface_name [String] The name of the interface
82
- def start_raw_logging_interface(interface_name = 'ALL', scope: $openc3_scope, token: $openc3_token)
83
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
84
+ def start_raw_logging_interface(interface_name = 'ALL', manual: false, scope: $openc3_scope, token: $openc3_token)
85
+ # TODO: Check if they have command authority for the targets mapped to this interface
86
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
84
87
  if interface_name == 'ALL'
85
88
  get_interface_names().each do |interface_name|
86
89
  InterfaceTopic.start_raw_logging(interface_name, scope: scope)
@@ -93,8 +96,9 @@ module OpenC3
93
96
  # Stop raw logging for an interface
94
97
  #
95
98
  # @param interface_name [String] The name of the interface
96
- def stop_raw_logging_interface(interface_name = 'ALL', scope: $openc3_scope, token: $openc3_token)
97
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
99
+ def stop_raw_logging_interface(interface_name = 'ALL', manual: false, scope: $openc3_scope, token: $openc3_token)
100
+ # TODO: Check if they have command authority for the targets mapped to this interface
101
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
98
102
  if interface_name == 'ALL'
99
103
  get_interface_names().each do |interface_name|
100
104
  InterfaceTopic.stop_raw_logging(interface_name, scope: scope)
@@ -110,10 +114,10 @@ module OpenC3
110
114
  # Numeric, Numeric>>] Array of Arrays containing \[name, state, num clients,
111
115
  # TX queue size, RX queue size, TX bytes, RX bytes, Command count,
112
116
  # Telemetry count] for all interfaces
113
- def get_all_interface_info(scope: $openc3_scope, token: $openc3_token)
114
- authorize(permission: 'system', scope: scope, token: token)
117
+ def get_all_interface_info(manual: false, scope: $openc3_scope, token: $openc3_token)
118
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
115
119
  info = []
116
- InterfaceStatusModel.all(scope: scope).each do |int_name, int|
120
+ InterfaceStatusModel.all(scope: scope).each do |_int_name, int|
117
121
  info << [int['name'], int['state'], int['clients'], int['txsize'], int['rxsize'],
118
122
  int['txbytes'], int['rxbytes'], int['txcnt'], int['rxcnt']]
119
123
  end
@@ -127,8 +131,9 @@ module OpenC3
127
131
  #
128
132
  # @param target_name [String/Array] The name of the target(s)
129
133
  # @param interface_name (see #connect_interface)
130
- def map_target_to_interface(target_name, interface_name, cmd_only: false, tlm_only: false, unmap_old: true, scope: $openc3_scope, token: $openc3_token)
131
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
134
+ def map_target_to_interface(target_name, interface_name, cmd_only: false, tlm_only: false, unmap_old: true, manual: false, scope: $openc3_scope, token: $openc3_token)
135
+ # TODO: Check if they have command authority for the targets mapped to this interface
136
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
132
137
  new_interface = InterfaceModel.get_model(name: interface_name, scope: scope)
133
138
  if Array === target_name
134
139
  target_names = target_name
@@ -142,13 +147,15 @@ module OpenC3
142
147
  nil
143
148
  end
144
149
 
145
- def interface_cmd(interface_name, cmd_name, *cmd_params, scope: $openc3_scope, token: $openc3_token)
146
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
150
+ def interface_cmd(interface_name, cmd_name, *cmd_params, manual: false, scope: $openc3_scope, token: $openc3_token)
151
+ # TODO: Check if they have command authority for the targets mapped to this interface
152
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
147
153
  InterfaceTopic.interface_cmd(interface_name, cmd_name, *cmd_params, scope: scope)
148
154
  end
149
155
 
150
- def interface_protocol_cmd(interface_name, cmd_name, *cmd_params, read_write: :READ_WRITE, index: -1, scope: $openc3_scope, token: $openc3_token)
151
- authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
156
+ def interface_protocol_cmd(interface_name, cmd_name, *cmd_params, read_write: :READ_WRITE, index: -1, manual: false, scope: $openc3_scope, token: $openc3_token)
157
+ # TODO: Check if they have command authority for the targets mapped to this interface
158
+ authorize(permission: 'system_set', interface_name: interface_name, manual: manual, scope: scope, token: token)
152
159
  InterfaceTopic.protocol_cmd(interface_name, cmd_name, *cmd_params, read_write: read_write, index: index, scope: scope)
153
160
  end
154
161
  end