openc3 5.17.1 → 5.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -4
  3. data/bin/cstol_converter +14 -14
  4. data/bin/openc3cli +190 -8
  5. data/data/config/_interfaces.yaml +5 -5
  6. data/data/config/command_modifiers.yaml +59 -0
  7. data/data/config/interface_modifiers.yaml +19 -9
  8. data/data/config/item_modifiers.yaml +34 -26
  9. data/data/config/microservice.yaml +4 -1
  10. data/data/config/param_item_modifiers.yaml +17 -1
  11. data/data/config/parameter_modifiers.yaml +30 -13
  12. data/data/config/plugins.yaml +9 -5
  13. data/data/config/screen.yaml +9 -9
  14. data/data/config/table_manager.yaml +2 -2
  15. data/data/config/telemetry_modifiers.yaml +9 -4
  16. data/data/config/tool.yaml +4 -1
  17. data/data/config/widgets.yaml +44 -17
  18. data/ext/openc3/ext/config_parser/config_parser.c +1 -1
  19. data/ext/openc3/ext/packet/packet.c +7 -1
  20. data/ext/openc3/ext/platform/platform.c +3 -3
  21. data/ext/openc3/ext/structure/structure.c +56 -76
  22. data/lib/openc3/accessors/accessor.rb +1 -0
  23. data/lib/openc3/accessors/binary_accessor.rb +174 -15
  24. data/lib/openc3/accessors/form_accessor.rb +2 -2
  25. data/lib/openc3/accessors/http_accessor.rb +1 -1
  26. data/lib/openc3/accessors/json_accessor.rb +6 -4
  27. data/lib/openc3/accessors/template_accessor.rb +6 -9
  28. data/lib/openc3/accessors/xml_accessor.rb +1 -1
  29. data/lib/openc3/api/cmd_api.rb +72 -44
  30. data/lib/openc3/api/config_api.rb +10 -10
  31. data/lib/openc3/api/interface_api.rb +28 -21
  32. data/lib/openc3/api/limits_api.rb +30 -30
  33. data/lib/openc3/api/metrics_api.rb +3 -3
  34. data/lib/openc3/api/offline_access_api.rb +5 -5
  35. data/lib/openc3/api/router_api.rb +25 -19
  36. data/lib/openc3/api/settings_api.rb +10 -10
  37. data/lib/openc3/api/stash_api.rb +10 -10
  38. data/lib/openc3/api/target_api.rb +10 -10
  39. data/lib/openc3/api/tlm_api.rb +44 -44
  40. data/lib/openc3/config/config_parser.rb +1 -1
  41. data/lib/openc3/conversions/bit_reverse_conversion.rb +60 -0
  42. data/lib/openc3/conversions/ip_read_conversion.rb +59 -0
  43. data/lib/openc3/conversions/ip_write_conversion.rb +61 -0
  44. data/lib/openc3/conversions/object_read_conversion.rb +88 -0
  45. data/lib/openc3/conversions/object_write_conversion.rb +38 -0
  46. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +7 -7
  47. data/lib/openc3/conversions.rb +6 -1
  48. data/lib/openc3/core_ext/array.rb +5 -5
  49. data/lib/openc3/core_ext/exception.rb +9 -2
  50. data/lib/openc3/core_ext/string.rb +2 -2
  51. data/lib/openc3/interfaces/http_server_interface.rb +1 -0
  52. data/lib/openc3/interfaces/interface.rb +1 -1
  53. data/lib/openc3/interfaces/linc_interface.rb +3 -3
  54. data/lib/openc3/io/json_api.rb +11 -6
  55. data/lib/openc3/io/json_drb.rb +19 -21
  56. data/lib/openc3/io/json_rpc.rb +15 -14
  57. data/lib/openc3/logs/buffered_packet_log_writer.rb +3 -3
  58. data/lib/openc3/logs/log_writer.rb +7 -8
  59. data/lib/openc3/logs/packet_log_writer.rb +7 -7
  60. data/lib/openc3/logs/text_log_writer.rb +4 -4
  61. data/lib/openc3/microservices/decom_microservice.rb +19 -4
  62. data/lib/openc3/microservices/interface_microservice.rb +41 -3
  63. data/lib/openc3/microservices/microservice.rb +11 -11
  64. data/lib/openc3/microservices/reaction_microservice.rb +2 -2
  65. data/lib/openc3/microservices/scope_cleanup_microservice.rb +1 -1
  66. data/lib/openc3/microservices/timeline_microservice.rb +70 -45
  67. data/lib/openc3/microservices/trigger_group_microservice.rb +3 -3
  68. data/lib/openc3/migrations/20240915000000_activity_uuid.rb +28 -0
  69. data/lib/openc3/models/activity_model.rb +124 -92
  70. data/lib/openc3/models/auth_model.rb +31 -2
  71. data/lib/openc3/models/cvt_model.rb +11 -5
  72. data/lib/openc3/models/gem_model.rb +8 -8
  73. data/lib/openc3/models/plugin_model.rb +3 -3
  74. data/lib/openc3/models/reducer_model.rb +2 -2
  75. data/lib/openc3/models/scope_model.rb +45 -14
  76. data/lib/openc3/models/sorted_model.rb +5 -5
  77. data/lib/openc3/models/target_model.rb +7 -4
  78. data/lib/openc3/models/tool_config_model.rb +1 -1
  79. data/lib/openc3/models/tool_model.rb +4 -4
  80. data/lib/openc3/models/widget_model.rb +11 -5
  81. data/lib/openc3/operators/microservice_operator.rb +2 -2
  82. data/lib/openc3/operators/operator.rb +14 -12
  83. data/lib/openc3/packets/command_validator.rb +48 -0
  84. data/lib/openc3/packets/commands.rb +6 -14
  85. data/lib/openc3/packets/packet.rb +49 -16
  86. data/lib/openc3/packets/packet_config.rb +47 -25
  87. data/lib/openc3/packets/packet_item.rb +5 -0
  88. data/lib/openc3/packets/parsers/packet_parser.rb +3 -3
  89. data/lib/openc3/packets/structure.rb +87 -15
  90. data/lib/openc3/packets/structure_item.rb +76 -53
  91. data/lib/openc3/packets/telemetry.rb +6 -27
  92. data/lib/openc3/script/api_shared.rb +7 -5
  93. data/lib/openc3/script/calendar.rb +2 -2
  94. data/lib/openc3/script/commands.rb +6 -4
  95. data/lib/openc3/script/extract.rb +5 -3
  96. data/lib/openc3/script/metadata.rb +2 -2
  97. data/lib/openc3/script/suite.rb +17 -17
  98. data/lib/openc3/script/web_socket_api.rb +11 -0
  99. data/lib/openc3/streams/serial_stream.rb +2 -3
  100. data/lib/openc3/streams/stream.rb +2 -2
  101. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +10 -10
  102. data/lib/openc3/tools/table_manager/table_manager_core.rb +11 -11
  103. data/lib/openc3/tools/table_manager/table_parser.rb +2 -3
  104. data/lib/openc3/topics/command_decom_topic.rb +2 -1
  105. data/lib/openc3/topics/command_topic.rb +3 -3
  106. data/lib/openc3/topics/decom_interface_topic.rb +4 -3
  107. data/lib/openc3/topics/system_events_topic.rb +40 -0
  108. data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
  109. data/lib/openc3/utilities/authentication.rb +2 -1
  110. data/lib/openc3/utilities/authorization.rb +4 -3
  111. data/lib/openc3/utilities/cli_generator.rb +15 -8
  112. data/lib/openc3/utilities/cosmos_rails_formatter.rb +60 -0
  113. data/lib/openc3/utilities/crc.rb +6 -6
  114. data/lib/openc3/utilities/local_mode.rb +2 -1
  115. data/lib/openc3/utilities/logger.rb +44 -34
  116. data/lib/openc3/utilities/metric.rb +1 -2
  117. data/lib/openc3/utilities/quaternion.rb +18 -18
  118. data/lib/openc3/utilities/target_file.rb +4 -4
  119. data/lib/openc3/version.rb +6 -6
  120. data/lib/openc3/win32/win32_main.rb +2 -2
  121. data/templates/tool_angular/package.json +22 -22
  122. data/templates/tool_react/package.json +13 -13
  123. data/templates/tool_svelte/package.json +14 -14
  124. data/templates/tool_svelte/src/services/openc3-api.js +17 -17
  125. data/templates/tool_vue/package.json +13 -13
  126. data/templates/widget/package.json +11 -12
  127. data/templates/widget/src/Widget.vue +0 -1
  128. metadata +25 -2
@@ -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,9 @@ 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
+ # NOTE: When adding new keywords to this method, make sure to update script/commands.rb
456
+ def _cmd_implementation(method_name, *args, range_check:, hazardous_check:, raw:, timeout: nil, log_message: nil, manual: false, validate: true,
457
+ scope: $openc3_scope, token: $openc3_token, **kwargs)
453
458
  extract_string_kwargs_to_args(args, kwargs)
454
459
  unless [nil, true, false].include?(log_message)
455
460
  raise "Invalid log_message parameter: #{log_message}. Must be true or false."
@@ -480,7 +485,24 @@ module OpenC3
480
485
  target_name = target_name.upcase
481
486
  cmd_name = cmd_name.upcase
482
487
  cmd_params = cmd_params.transform_keys(&:upcase)
483
- authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, scope: scope, token: token)
488
+ user = authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, manual: manual, scope: scope, token: token)
489
+ if user.nil?
490
+ user = {}
491
+ user['username'] = ENV['OPENC3_MICROSERVICE_NAME']
492
+
493
+ # Get the caller stack trace to determine the point in the code where the command was called
494
+ # This code works but ultimately we didn't want to overload 'username' and take a performance hit
495
+ # caller.each do |frame|
496
+ # # Look for the following line in the stack trace which indicates custom code
497
+ # # /tmp/d20240827-62-8e57pf/targets/INST/lib/example_limits_response.rb:31:in `call'
498
+ # if frame.include?("/targets/#{target_name}")
499
+ # user = {}
500
+ # # username is the name of the custom code file
501
+ # user['username'] = frame.split("/targets/")[-1].split(':')[0]
502
+ # break
503
+ # end
504
+ # end
505
+ end
484
506
  packet = TargetModel.packet(target_name, cmd_name, type: :CMD, scope: scope)
485
507
  if packet['disabled']
486
508
  error = DisabledError.new
@@ -489,29 +511,35 @@ module OpenC3
489
511
  raise error
490
512
  end
491
513
 
492
- command = {
493
- 'target_name' => target_name,
494
- 'cmd_name' => cmd_name,
495
- 'cmd_params' => cmd_params,
496
- 'range_check' => range_check.to_s,
497
- 'hazardous_check' => hazardous_check.to_s,
498
- 'raw' => raw.to_s
499
- }
500
514
  if log_message.nil? # This means the default was used, no argument was passed
501
515
  log_message = true # Default is true
502
516
  # If the packet has the DISABLE_MESSAGES keyword then no messages by default
503
517
  log_message = false if packet["messages_disabled"]
504
518
  # Check if any of the parameters have DISABLE_MESSAGES
505
519
  cmd_params.each do |key, value|
506
- item = packet['items'].find { |item| item['name'] == key.to_s }
520
+ item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
507
521
  if item && item['states'] && item['states'][value] && item['states'][value]["messages_disabled"]
508
522
  log_message = false
509
523
  end
510
524
  end
511
525
  end
526
+ cmd_string = _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet)
512
527
  if log_message
513
- Logger.info(_build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet), scope: scope)
528
+ Logger.info(cmd_string, scope: scope)
514
529
  end
530
+
531
+ username = user && user['username'] ? user['username'] : 'anonymous'
532
+ command = {
533
+ 'target_name' => target_name,
534
+ 'cmd_name' => cmd_name,
535
+ 'cmd_params' => cmd_params,
536
+ 'range_check' => range_check.to_s,
537
+ 'hazardous_check' => hazardous_check.to_s,
538
+ 'raw' => raw.to_s,
539
+ 'cmd_string' => cmd_string,
540
+ 'username' => username,
541
+ 'validate' => validate.to_s
542
+ }
515
543
  CommandTopic.send_command(command, timeout: timeout, scope: scope)
516
544
  end
517
545
 
@@ -525,7 +553,7 @@ module OpenC3
525
553
  cmd_params.each do |key, value|
526
554
  next if Packet::RESERVED_ITEM_NAMES.include?(key)
527
555
 
528
- item = packet['items'].find { |item| item['name'] == key.to_s }
556
+ item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
529
557
 
530
558
  begin
531
559
  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
@@ -47,8 +47,8 @@ module OpenC3
47
47
  # [[target name, packet name, item name, item limits state], ...]
48
48
  #
49
49
  # @return [Array<Array<String, String, String, String>>]
50
- def get_out_of_limits(scope: $openc3_scope, token: $openc3_token)
51
- authorize(permission: 'tlm', scope: scope, token: token)
50
+ def get_out_of_limits(manual: false, scope: $openc3_scope, token: $openc3_token)
51
+ authorize(permission: 'tlm', manual: manual, scope: scope, token: token)
52
52
  LimitsEventTopic.out_of_limits(scope: scope)
53
53
  end
54
54
 
@@ -59,7 +59,7 @@ module OpenC3
59
59
  # @param ignored_items [Array<Array<String, String, String|nil>>] Array of [TGT, PKT, ITEM] strings
60
60
  # to ignore when determining overall state. Note, ITEM can be nil to indicate to ignore entire packet.
61
61
  # @return [String] The overall limits state for the system, one of 'GREEN', 'YELLOW', 'RED'
62
- def get_overall_limits_state(ignored_items = nil, scope: $openc3_scope, token: $openc3_token)
62
+ def get_overall_limits_state(ignored_items = nil, manual: false, scope: $openc3_scope, token: $openc3_token)
63
63
  # We only need to check out of limits items so call get_out_of_limits() which authorizes
64
64
  out_of_limits = get_out_of_limits(scope: scope, token: token)
65
65
  overall = 'GREEN'
@@ -107,10 +107,10 @@ module OpenC3
107
107
  # Favor the first syntax where possible as it is more succinct.
108
108
  #
109
109
  # @param args [String|Array<String>] See the description for calling style
110
- # @return [Boolean] Whether limits are enable for the itme
111
- def limits_enabled?(*args, scope: $openc3_scope, token: $openc3_token)
110
+ # @return [Boolean] Whether limits are enable for the item
111
+ def limits_enabled?(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
112
112
  target_name, packet_name, item_name = _tlm_process_args(args, 'limits_enabled?', scope: scope)
113
- authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
113
+ authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
114
114
  return TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)['limits']['enabled'] ? true : false
115
115
  end
116
116
  alias limits_enabled limits_enabled?
@@ -124,9 +124,9 @@ module OpenC3
124
124
  # Favor the first syntax where possible as it is more succinct.
125
125
  #
126
126
  # @param args [String|Array<String>] See the description for calling style
127
- def enable_limits(*args, scope: $openc3_scope, token: $openc3_token)
127
+ def enable_limits(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
128
128
  target_name, packet_name, item_name = _tlm_process_args(args, 'enable_limits', scope: scope)
129
- authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
129
+ authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
130
130
  packet = TargetModel.packet(target_name, packet_name, scope: scope)
131
131
  found_item = nil
132
132
  packet['items'].each do |item|
@@ -157,9 +157,9 @@ module OpenC3
157
157
  # Favor the first syntax where possible as it is more succinct.
158
158
  #
159
159
  # @param args [String|Array<String>] See the description for calling style
160
- def disable_limits(*args, scope: $openc3_scope, token: $openc3_token)
160
+ def disable_limits(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
161
161
  target_name, packet_name, item_name = _tlm_process_args(args, 'disable_limits', scope: scope)
162
- authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
162
+ authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
163
163
  packet = TargetModel.packet(target_name, packet_name, scope: scope)
164
164
  found_item = nil
165
165
  packet['items'].each do |item|
@@ -190,8 +190,8 @@ module OpenC3
190
190
  # 'TVAC' => [-25, -10, 50, 55] }
191
191
  #
192
192
  # @return [Hash{String => Array<Number, Number, Number, Number, Number, Number>}]
193
- def get_limits(target_name, packet_name, item_name, cache_timeout: nil, scope: $openc3_scope, token: $openc3_token)
194
- authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
193
+ def get_limits(target_name, packet_name, item_name, cache_timeout: nil, manual: false, scope: $openc3_scope, token: $openc3_token)
194
+ authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
195
195
  limits = {}
196
196
  item = _get_item(target_name, packet_name, item_name, cache_timeout: cache_timeout, scope: scope)
197
197
  item['limits'].each do |key, vals|
@@ -207,8 +207,8 @@ module OpenC3
207
207
  # is created to avoid overriding existing limits.
208
208
  def set_limits(target_name, packet_name, item_name, red_low, yellow_low, yellow_high, red_high,
209
209
  green_low = nil, green_high = nil, limits_set = 'CUSTOM', persistence = nil, enabled = true,
210
- scope: $openc3_scope, token: $openc3_token)
211
- authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
210
+ manual: false, scope: $openc3_scope, token: $openc3_token)
211
+ authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
212
212
  if (red_low > yellow_low) || (yellow_low >= yellow_high) || (yellow_high > red_high)
213
213
  raise "Invalid limits specified. Ensure yellow limits are within red limits."
214
214
  end
@@ -259,38 +259,38 @@ module OpenC3
259
259
  # Returns all limits_groups and their members
260
260
  # @since 5.0.0 Returns hash with values
261
261
  # @return [Hash{String => Array<Array<String, String, String>>]
262
- def get_limits_groups(scope: $openc3_scope, token: $openc3_token)
263
- authorize(permission: 'tlm', scope: scope, token: token)
262
+ def get_limits_groups(manual: false, scope: $openc3_scope, token: $openc3_token)
263
+ authorize(permission: 'tlm', manual: manual, scope: scope, token: token)
264
264
  TargetModel.limits_groups(scope: scope)
265
265
  end
266
266
 
267
267
  # Enables limits for all the items in the group
268
268
  #
269
269
  # @param group_name [String] Name of the group to enable
270
- def enable_limits_group(group_name, scope: $openc3_scope, token: $openc3_token)
271
- _limits_group(group_name, action: :enable, scope: scope, token: token)
270
+ def enable_limits_group(group_name, manual: false, scope: $openc3_scope, token: $openc3_token)
271
+ _limits_group(group_name, action: :enable, manual: manual, scope: scope, token: token)
272
272
  end
273
273
 
274
274
  # Disables limits for all the items in the group
275
275
  #
276
276
  # @param group_name [String] Name of the group to disable
277
- def disable_limits_group(group_name, scope: $openc3_scope, token: $openc3_token)
278
- _limits_group(group_name, action: :disable, scope: scope, token: token)
277
+ def disable_limits_group(group_name, manual: false, scope: $openc3_scope, token: $openc3_token)
278
+ _limits_group(group_name, action: :disable, manual: manual, scope: scope, token: token)
279
279
  end
280
280
 
281
281
  # Returns all defined limits sets
282
282
  #
283
283
  # @return [Array<String>] All defined limits sets
284
- def get_limits_sets(scope: $openc3_scope, token: $openc3_token)
285
- authorize(permission: 'tlm', scope: scope, token: token)
284
+ def get_limits_sets(manual: false, scope: $openc3_scope, token: $openc3_token)
285
+ authorize(permission: 'tlm', manual: manual, scope: scope, token: token)
286
286
  LimitsEventTopic.sets(scope: scope).keys
287
287
  end
288
288
 
289
289
  # Changes the active limits set that applies to all telemetry
290
290
  #
291
291
  # @param limits_set [String] The name of the limits set
292
- def set_limits_set(limits_set, scope: $openc3_scope, token: $openc3_token)
293
- authorize(permission: 'tlm_set', scope: scope, token: token)
292
+ def set_limits_set(limits_set, manual: false, scope: $openc3_scope, token: $openc3_token)
293
+ authorize(permission: 'tlm_set', manual: manual, scope: scope, token: token)
294
294
  message = "Setting Limits Set: #{limits_set}"
295
295
  Logger.info(message, scope: scope)
296
296
  LimitsEventTopic.write({ type: :LIMITS_SET, set: limits_set.to_s,
@@ -300,8 +300,8 @@ module OpenC3
300
300
  # Returns the active limits set that applies to all telemetry
301
301
  #
302
302
  # @return [String] The current limits set
303
- def get_limits_set(scope: $openc3_scope, token: $openc3_token)
304
- authorize(permission: 'tlm', scope: scope, token: token)
303
+ def get_limits_set(manual: false, scope: $openc3_scope, token: $openc3_token)
304
+ authorize(permission: 'tlm', manual: manual, scope: scope, token: token)
305
305
  LimitsEventTopic.current_set(scope: scope)
306
306
  end
307
307
 
@@ -313,8 +313,8 @@ module OpenC3
313
313
  # @param count [Integer] The total number of events returned. Default is 100.
314
314
  # @return [Hash, Integer] Event hash followed by the offset. The offset can
315
315
  # be used in subsequent calls to return events from where the last call left off.
316
- def get_limits_events(offset = nil, count: 100, scope: $openc3_scope, token: $openc3_token)
317
- authorize(permission: 'tlm', scope: scope, token: token)
316
+ def get_limits_events(offset = nil, count: 100, manual: false, scope: $openc3_scope, token: $openc3_token)
317
+ authorize(permission: 'tlm', manual: manual, scope: scope, token: token)
318
318
  LimitsEventTopic.read(offset, count: count, scope: scope)
319
319
  end
320
320
 
@@ -323,8 +323,8 @@ module OpenC3
323
323
  ###########################################################################
324
324
 
325
325
  # Enables or disables a limits group
326
- def _limits_group(group_name, action:, scope:, token:)
327
- authorize(permission: 'tlm_set', scope: scope, token: token)
326
+ def _limits_group(group_name, action:, manual:, scope:, token:)
327
+ authorize(permission: 'tlm_set', manual: manual, scope: scope, token: token)
328
328
  group_name.upcase!
329
329
  group = get_limits_groups(scope: scope, token: token)[group_name]
330
330
  raise "LIMITS_GROUP #{group_name} undefined. Ensure your telemetry definition contains the line: LIMITS_GROUP #{group_name}" unless group
@@ -66,15 +66,15 @@ module OpenC3
66
66
  SUM_METRICS['text_log_total'] = 0
67
67
  SUM_METRICS['text_log_error_total'] = 0
68
68
 
69
- def get_metrics(scope: $openc3_scope, token: $openc3_token)
70
- authorize(permission: 'system', scope: scope, token: token)
69
+ def get_metrics(manual: false, scope: $openc3_scope, token: $openc3_token)
70
+ authorize(permission: 'system', manual: manual, scope: scope, token: token)
71
71
 
72
72
  sum_metrics = SUM_METRICS.dup
73
73
  duration_metrics = DURATION_METRICS.dup
74
74
  delay_metrics = DELAY_METRICS.dup
75
75
 
76
76
  metrics = MetricModel.all(scope: scope)
77
- metrics.each do |microservice_name, metrics|
77
+ metrics.each do |_microservice_name, metrics|
78
78
  next unless metrics and metrics['values']
79
79
  metrics['values'].each do |metric_name, data|
80
80
  value = data['value']