openc3 6.5.1 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/config/param_item_modifiers.yaml +3 -0
- data/lib/openc3/api/cmd_api.rb +5 -45
- data/lib/openc3/microservices/interface_microservice.rb +2 -0
- data/lib/openc3/packets/commands.rb +7 -49
- data/lib/openc3/packets/packet.rb +66 -1
- data/lib/openc3/packets/packet_config.rb +10 -2
- data/lib/openc3/packets/packet_item.rb +10 -1
- data/lib/openc3/script/commands.rb +38 -25
- data/lib/openc3/tools/table_manager/table_config.rb +3 -3
- data/lib/openc3/top_level.rb +2 -6
- data/lib/openc3/topics/command_topic.rb +12 -15
- data/lib/openc3/utilities/cmd_log.rb +70 -0
- data/lib/openc3/version.rb +6 -6
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/widget/package.json +2 -2
- metadata +2 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d08bcc3b92811101e2096aa443b5459835d0396aba80b1067c8147388ec050e6
|
4
|
+
data.tar.gz: 2820795b23e3da0530d0306ee2665d69bb5ad86f494609ced199f985929c56f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 181ce42f3c55f78ee8e6adf3cc7145326974c8239a82478b501def91314169cacb62a9e53c4d0d760e0b0125a1b77e437127f7992d7e4fe42838035640b87dbe
|
7
|
+
data.tar.gz: 957334977c15e7d8e3fe49d14bec6c2e11c7cba09bbaea70cefe3f85a408255f1e7f2620b642c6f7a137d6ff9bdc1b4b49007fca58a9c6c5f9562b81daa0263e
|
data/lib/openc3/api/cmd_api.rb
CHANGED
@@ -30,9 +30,11 @@ require 'openc3/topics/command_decom_topic'
|
|
30
30
|
require 'openc3/topics/decom_interface_topic'
|
31
31
|
require 'openc3/topics/interface_topic'
|
32
32
|
require 'openc3/script/extract'
|
33
|
+
require 'openc3/utilities/cmd_log'
|
33
34
|
|
34
35
|
module OpenC3
|
35
36
|
module Api
|
37
|
+
include OpenC3::CmdLog
|
36
38
|
WHITELIST ||= []
|
37
39
|
WHITELIST.concat([
|
38
40
|
'cmd',
|
@@ -500,6 +502,7 @@ module OpenC3
|
|
500
502
|
# end
|
501
503
|
# end
|
502
504
|
end
|
505
|
+
|
503
506
|
packet = TargetModel.packet(target_name, cmd_name, type: :CMD, scope: scope)
|
504
507
|
if packet['disabled']
|
505
508
|
error = DisabledError.new
|
@@ -507,7 +510,6 @@ module OpenC3
|
|
507
510
|
error.cmd_name = cmd_name
|
508
511
|
raise error
|
509
512
|
end
|
510
|
-
|
511
513
|
if log_message.nil? # This means the default was used, no argument was passed
|
512
514
|
log_message = true # Default is true
|
513
515
|
# If the packet has the DISABLE_MESSAGES keyword then no messages by default
|
@@ -520,7 +522,6 @@ module OpenC3
|
|
520
522
|
end
|
521
523
|
end
|
522
524
|
end
|
523
|
-
|
524
525
|
cmd_string = _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet)
|
525
526
|
username = user && user['username'] ? user['username'] : 'anonymous'
|
526
527
|
command = {
|
@@ -535,52 +536,11 @@ module OpenC3
|
|
535
536
|
'validate' => validate.to_s,
|
536
537
|
'manual' => manual.to_s,
|
537
538
|
'log_message' => log_message.to_s,
|
539
|
+
'obfuscated_items' => packet['obfuscated_items'].to_s
|
538
540
|
}
|
539
541
|
CommandTopic.send_command(command, timeout: timeout, scope: scope)
|
542
|
+
return command
|
540
543
|
end
|
541
544
|
|
542
|
-
def _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet)
|
543
|
-
output_string = "#{method_name}(\""
|
544
|
-
output_string << (target_name + ' ' + cmd_name)
|
545
|
-
if cmd_params.nil? or cmd_params.empty?
|
546
|
-
output_string << '")'
|
547
|
-
else
|
548
|
-
params = []
|
549
|
-
cmd_params.each do |key, value|
|
550
|
-
next if Packet::RESERVED_ITEM_NAMES.include?(key)
|
551
|
-
|
552
|
-
item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
|
553
|
-
|
554
|
-
begin
|
555
|
-
item_type = item['data_type'].intern
|
556
|
-
rescue
|
557
|
-
item_type = nil
|
558
|
-
end
|
559
|
-
|
560
|
-
if value.is_a?(String)
|
561
|
-
value = value.dup
|
562
|
-
if item_type == :BLOCK or item_type == :STRING
|
563
|
-
if !value.is_printable?
|
564
|
-
value = "0x" + value.simple_formatted
|
565
|
-
else
|
566
|
-
value = value.inspect
|
567
|
-
end
|
568
|
-
else
|
569
|
-
value = value.convert_to_value.to_s
|
570
|
-
end
|
571
|
-
if value.length > 256
|
572
|
-
value = value[0..255] + "...'"
|
573
|
-
end
|
574
|
-
value.tr!('"', "'")
|
575
|
-
elsif value.is_a?(Array)
|
576
|
-
value = "[#{value.join(", ")}]"
|
577
|
-
end
|
578
|
-
params << "#{key} #{value}"
|
579
|
-
end
|
580
|
-
params = params.join(", ")
|
581
|
-
output_string << (' with ' + params + '")')
|
582
|
-
end
|
583
|
-
return output_string
|
584
|
-
end
|
585
545
|
end
|
586
546
|
end
|
@@ -24,6 +24,7 @@
|
|
24
24
|
# See https://github.com/OpenC3/cosmos/pull/1963
|
25
25
|
|
26
26
|
require 'openc3/packets/packet_config'
|
27
|
+
require 'openc3/utilities/cmd_log'
|
27
28
|
|
28
29
|
module OpenC3
|
29
30
|
# Commands uses PacketConfig to parse the command and telemetry
|
@@ -37,6 +38,7 @@ module OpenC3
|
|
37
38
|
# Packet or PacketItem objects. While there are some overlapping methods between
|
38
39
|
# the two, these are separate interfaces into the system.
|
39
40
|
class Commands
|
41
|
+
include OpenC3::CmdLog
|
40
42
|
attr_accessor :config
|
41
43
|
|
42
44
|
LATEST_PACKET_NAME = 'LATEST'.freeze
|
@@ -203,60 +205,16 @@ module OpenC3
|
|
203
205
|
raw = false
|
204
206
|
end
|
205
207
|
items.delete_if { |item_name, _item_value| ignored_parameters.include?(item_name) }
|
206
|
-
return build_cmd_output_string(packet.target_name, packet.packet_name, items, raw)
|
208
|
+
return build_cmd_output_string(packet.target_name, packet.packet_name, items, raw, packet)
|
207
209
|
end
|
208
210
|
|
209
|
-
def build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false)
|
210
|
-
|
211
|
-
output_string = 'cmd_raw("'
|
212
|
-
else
|
213
|
-
output_string = 'cmd("'
|
214
|
-
end
|
211
|
+
def build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false, packet)
|
212
|
+
method_name = raw ? "cmd_raw" : "cmd"
|
215
213
|
target_name = 'UNKNOWN' unless target_name
|
216
214
|
cmd_name = 'UNKNOWN' unless cmd_name
|
217
|
-
|
218
|
-
if cmd_params.nil? or cmd_params.empty?
|
219
|
-
output_string << '")'
|
220
|
-
else
|
221
|
-
begin
|
222
|
-
command_items = packet(target_name, cmd_name).items
|
223
|
-
rescue
|
224
|
-
end
|
225
|
-
|
226
|
-
params = []
|
227
|
-
cmd_params.each do |key, value|
|
228
|
-
next if Packet::RESERVED_ITEM_NAMES.include?(key)
|
229
|
-
|
230
|
-
begin
|
231
|
-
item_type = command_items[key].data_type
|
232
|
-
rescue
|
233
|
-
item_type = nil
|
234
|
-
end
|
215
|
+
packet_hash = packet ? packet.as_json : {}
|
235
216
|
|
236
|
-
|
237
|
-
value = value.dup
|
238
|
-
if item_type == :BLOCK or item_type == :STRING
|
239
|
-
if !value.is_printable?
|
240
|
-
value = "0x" + value.simple_formatted
|
241
|
-
else
|
242
|
-
value = value.inspect
|
243
|
-
end
|
244
|
-
else
|
245
|
-
value = value.convert_to_value.to_s
|
246
|
-
end
|
247
|
-
if value.length > 256
|
248
|
-
value = value[0..255] + "...'"
|
249
|
-
end
|
250
|
-
value.tr!('"', "'")
|
251
|
-
elsif value.is_a?(Array)
|
252
|
-
value = "[#{value.join(", ")}]"
|
253
|
-
end
|
254
|
-
params << "#{key} #{value}"
|
255
|
-
end
|
256
|
-
params = params.join(", ")
|
257
|
-
output_string << (' with ' + params + '")')
|
258
|
-
end
|
259
|
-
return output_string
|
217
|
+
_build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet_hash)
|
260
218
|
end
|
261
219
|
|
262
220
|
# Returns whether the given command is hazardous. Commands are hazardous
|
@@ -156,6 +156,7 @@ module OpenC3
|
|
156
156
|
@virtual = false
|
157
157
|
@restricted = false
|
158
158
|
@validator = nil
|
159
|
+
@obfuscated_items = []
|
159
160
|
end
|
160
161
|
|
161
162
|
# Sets the target name this packet is associated with. Unidentified packets
|
@@ -556,6 +557,7 @@ module OpenC3
|
|
556
557
|
item = super(item)
|
557
558
|
update_id_items(item)
|
558
559
|
update_limits_items_cache(item)
|
560
|
+
update_obfuscated_items_cache(item)
|
559
561
|
item
|
560
562
|
end
|
561
563
|
|
@@ -905,6 +907,7 @@ module OpenC3
|
|
905
907
|
@short_buffer_allowed = false
|
906
908
|
@id_items = nil
|
907
909
|
@limits_items = nil
|
910
|
+
@obfuscated_items = []
|
908
911
|
new_items = {}
|
909
912
|
new_sorted_items = []
|
910
913
|
@items.each do |name, item|
|
@@ -957,6 +960,21 @@ module OpenC3
|
|
957
960
|
end
|
958
961
|
end
|
959
962
|
|
963
|
+
# Add an item to the obfuscate items cache if necessary.
|
964
|
+
# You MUST call this after adding obfuscation to an item
|
965
|
+
# This is an optimization so we don't have to iterate through all the items when
|
966
|
+
# checking for obfuscation.
|
967
|
+
def update_obfuscated_items_cache(item)
|
968
|
+
if item.obfuscate
|
969
|
+
@obfuscated_items ||= []
|
970
|
+
@obfuscated_items_hash ||= {}
|
971
|
+
unless @obfuscated_items_hash[item]
|
972
|
+
@obfuscated_items << item
|
973
|
+
@obfuscated_items_hash[item] = true
|
974
|
+
end
|
975
|
+
end
|
976
|
+
end
|
977
|
+
|
960
978
|
# Return an array of arrays indicating all items in the packet that are out of limits
|
961
979
|
# [[target name, packet name, item name, item limits state], ...]
|
962
980
|
#
|
@@ -1158,6 +1176,7 @@ module OpenC3
|
|
1158
1176
|
config['validator'] = @validator.class.to_s if @validator
|
1159
1177
|
config['template'] = Base64.encode64(@template) if @template
|
1160
1178
|
config['config_name'] = self.config_name
|
1179
|
+
config['obfuscated_items'] = @obfuscated_items&.map(&:name) || []
|
1161
1180
|
|
1162
1181
|
if @processors
|
1163
1182
|
processors = []
|
@@ -1287,6 +1306,52 @@ module OpenC3
|
|
1287
1306
|
end
|
1288
1307
|
end
|
1289
1308
|
|
1309
|
+
def obfuscate()
|
1310
|
+
return unless @buffer
|
1311
|
+
return unless @obfuscated_items
|
1312
|
+
|
1313
|
+
@obfuscated_items.each do |item|
|
1314
|
+
next if item.data_type == :DERIVED
|
1315
|
+
|
1316
|
+
begin
|
1317
|
+
current_value = read(item.name, :RAW)
|
1318
|
+
|
1319
|
+
case current_value
|
1320
|
+
when Array
|
1321
|
+
# For arrays, create a new array of zeros with the same size
|
1322
|
+
case item.data_type
|
1323
|
+
when :INT, :UINT
|
1324
|
+
obfuscated_value = Array.new(current_value.size, 0)
|
1325
|
+
when :FLOAT
|
1326
|
+
obfuscated_value = Array.new(current_value.size, 0.0)
|
1327
|
+
when :STRING, :BLOCK
|
1328
|
+
obfuscated_value = Array.new(current_value.size) { |i|
|
1329
|
+
"\x00" * current_value[i].length if current_value[i]
|
1330
|
+
}
|
1331
|
+
else
|
1332
|
+
obfuscated_value = Array.new(current_value.size, 0)
|
1333
|
+
end
|
1334
|
+
when String
|
1335
|
+
# For strings/blocks, create null bytes of the same length
|
1336
|
+
obfuscated_value = "\x00" * current_value.length
|
1337
|
+
else
|
1338
|
+
case item.data_type
|
1339
|
+
when :INT, :UINT
|
1340
|
+
obfuscated_value = 0
|
1341
|
+
when :FLOAT
|
1342
|
+
obfuscated_value = 0.0
|
1343
|
+
else
|
1344
|
+
obfuscated_value = 0
|
1345
|
+
end
|
1346
|
+
end
|
1347
|
+
write(item.name, obfuscated_value, :RAW)
|
1348
|
+
rescue => e
|
1349
|
+
Logger.instance.error "#{item.name} obfuscation failed with error: #{e.message}"
|
1350
|
+
next
|
1351
|
+
end
|
1352
|
+
end
|
1353
|
+
end
|
1354
|
+
|
1290
1355
|
protected
|
1291
1356
|
|
1292
1357
|
def handle_limits_states(item, value)
|
@@ -1404,4 +1469,4 @@ module OpenC3
|
|
1404
1469
|
item
|
1405
1470
|
end
|
1406
1471
|
end
|
1407
|
-
end
|
1472
|
+
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -234,7 +234,8 @@ module OpenC3
|
|
234
234
|
'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION',\
|
235
235
|
'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED',\
|
236
236
|
'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',\
|
237
|
-
'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP', 'KEY', 'VARIABLE_BIT_SIZE'
|
237
|
+
'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP', 'KEY', 'VARIABLE_BIT_SIZE',\
|
238
|
+
'OBFUSCATE'
|
238
239
|
raise parser.error("No current item for #{keyword}") unless @current_item
|
239
240
|
|
240
241
|
process_current_item(parser, keyword, params)
|
@@ -692,6 +693,13 @@ module OpenC3
|
|
692
693
|
@current_item.units_full = params[0]
|
693
694
|
@current_item.units = params[1]
|
694
695
|
|
696
|
+
# Obfuscate the parameter in logs
|
697
|
+
when 'OBFUSCATE'
|
698
|
+
usage = "OBFUSCATE"
|
699
|
+
parser.verify_num_parameters(0, 0, usage)
|
700
|
+
@current_item.obfuscate = true
|
701
|
+
@current_packet.update_obfuscated_items_cache(@current_item)
|
702
|
+
|
695
703
|
# Update the description for the current telemetry item
|
696
704
|
when 'DESCRIPTION'
|
697
705
|
usage = "DESCRIPTION <DESCRIPTION>"
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -93,6 +93,9 @@ module OpenC3
|
|
93
93
|
# @return [PacketItemLimits] All information regarding limits for this PacketItem
|
94
94
|
attr_reader :limits
|
95
95
|
|
96
|
+
# @return [Boolean] Whether the parameter must be obfuscated from logs or not
|
97
|
+
attr_accessor :obfuscate
|
98
|
+
|
96
99
|
# (see StructureItem#initialize)
|
97
100
|
# It also initializes the attributes of the PacketItem.
|
98
101
|
def initialize(name, bit_offset, bit_size, data_type, endianness, array_size = nil, overflow = :ERROR)
|
@@ -109,6 +112,7 @@ module OpenC3
|
|
109
112
|
@range = nil
|
110
113
|
@required = false
|
111
114
|
@hazardous = nil
|
115
|
+
@obfuscate = false
|
112
116
|
@messages_disabled = nil
|
113
117
|
@state_colors = nil
|
114
118
|
@limits = PacketItemLimits.new
|
@@ -314,6 +318,7 @@ module OpenC3
|
|
314
318
|
item.state_colors = self.state_colors.clone if self.state_colors
|
315
319
|
item.limits = self.limits.clone if self.limits
|
316
320
|
item.meta = self.meta.clone if @meta
|
321
|
+
item.obfuscate = self.obfuscate.clone if @obfuscate
|
317
322
|
item
|
318
323
|
end
|
319
324
|
alias dup clone
|
@@ -345,6 +350,7 @@ module OpenC3
|
|
345
350
|
hash['limits'] = self.limits.to_hash
|
346
351
|
hash['meta'] = nil
|
347
352
|
hash['meta'] = @meta if @meta
|
353
|
+
hash['obfuscate'] = self.obfuscate
|
348
354
|
hash
|
349
355
|
end
|
350
356
|
|
@@ -404,6 +410,7 @@ module OpenC3
|
|
404
410
|
config << " FORMAT_STRING #{self.format_string.to_s.quote_if_necessary}\n" if self.format_string
|
405
411
|
config << " UNITS #{self.units_full.to_s.quote_if_necessary} #{self.units.to_s.quote_if_necessary}\n" if self.units
|
406
412
|
config << " OVERFLOW #{self.overflow}\n" if self.overflow != :ERROR
|
413
|
+
config << " OBFUSCATE\n" if self.obfuscate
|
407
414
|
|
408
415
|
if @states
|
409
416
|
@states.each do |state_name, state_value|
|
@@ -512,6 +519,7 @@ module OpenC3
|
|
512
519
|
|
513
520
|
config['meta'] = @meta if @meta
|
514
521
|
config['variable_bit_size'] = @variable_bit_size if @variable_bit_size
|
522
|
+
config['obfuscate'] = self.obfuscate
|
515
523
|
config
|
516
524
|
end
|
517
525
|
|
@@ -573,6 +581,7 @@ module OpenC3
|
|
573
581
|
item.limits.values = values if values.length > 0
|
574
582
|
end
|
575
583
|
item.meta = hash['meta']
|
584
|
+
item.obfuscate = hash['obfuscate']
|
576
585
|
item.variable_bit_size = hash['variable_bit_size']
|
577
586
|
item
|
578
587
|
end
|
@@ -14,12 +14,13 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
|
+
require 'json'
|
23
24
|
require 'openc3/packets/packet'
|
24
25
|
require 'openc3/script/extract'
|
25
26
|
|
@@ -30,7 +31,14 @@ module OpenC3
|
|
30
31
|
private
|
31
32
|
|
32
33
|
# Format the command like it appears in a script
|
33
|
-
def _cmd_string(target_name, cmd_name, cmd_params, raw)
|
34
|
+
def _cmd_string(target_name, cmd_name, cmd_params, raw, obfuscated_items)
|
35
|
+
# Normally obfuscated_items is returned as an Array formatted as a JSON string
|
36
|
+
# because we're hitting the API server, but in the case of a disconnect command, it is an Array
|
37
|
+
if obfuscated_items and obfuscated_items.is_a?(String)
|
38
|
+
obfuscated_items = JSON.parse(obfuscated_items)
|
39
|
+
elsif !obfuscated_items
|
40
|
+
obfuscated_items = []
|
41
|
+
end
|
34
42
|
output_string = $disconnect ? 'DISCONNECT: ' : ''
|
35
43
|
if raw
|
36
44
|
output_string += 'cmd_raw("'
|
@@ -44,18 +52,21 @@ module OpenC3
|
|
44
52
|
params = []
|
45
53
|
cmd_params.each do |key, value|
|
46
54
|
next if Packet::RESERVED_ITEM_NAMES.include?(key)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
55
|
+
if obfuscated_items and obfuscated_items.is_a?(Array) and obfuscated_items.include?(key)
|
56
|
+
params << "#{key} *****"
|
57
|
+
else
|
58
|
+
if value.is_a?(String)
|
59
|
+
if !value.is_printable?
|
60
|
+
value = "BINARY"
|
61
|
+
elsif value.length > 256
|
62
|
+
value = value[0..255] + "...'"
|
63
|
+
end
|
64
|
+
value.tr!('"', "'")
|
65
|
+
elsif value.is_a?(Array)
|
66
|
+
value = "[#{value.join(", ")}]"
|
53
67
|
end
|
54
|
-
|
55
|
-
elsif value.is_a?(Array)
|
56
|
-
value = "[#{value.join(", ")}]"
|
68
|
+
params << "#{key} #{value}"
|
57
69
|
end
|
58
|
-
params << "#{key} #{value}"
|
59
70
|
end
|
60
71
|
params = params.join(", ")
|
61
72
|
output_string += ' with ' + params + '")'
|
@@ -65,14 +76,14 @@ module OpenC3
|
|
65
76
|
|
66
77
|
# Log any warnings about disabling checks and log the command itself
|
67
78
|
# NOTE: This is a helper method and should not be called directly
|
68
|
-
def _log_cmd(
|
79
|
+
def _log_cmd(cmd, raw, no_range, no_hazardous)
|
69
80
|
if no_range
|
70
|
-
puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring range checks"
|
81
|
+
puts "WARN: Command #{cmd['target_name']} #{cmd['cmd_name']} being sent ignoring range checks"
|
71
82
|
end
|
72
83
|
if no_hazardous
|
73
|
-
puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring hazardous warnings"
|
84
|
+
puts "WARN: Command #{cmd['target_name']} #{cmd['cmd_name']} being sent ignoring hazardous warnings"
|
74
85
|
end
|
75
|
-
puts _cmd_string(target_name, cmd_name, cmd_params, raw)
|
86
|
+
puts _cmd_string(cmd['target_name'], cmd['cmd_name'], cmd['cmd_params'], raw, cmd['obfuscated_items'])
|
76
87
|
end
|
77
88
|
|
78
89
|
def _cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: $openc3_scope)
|
@@ -94,14 +105,17 @@ module OpenC3
|
|
94
105
|
|
95
106
|
# Get the command and validate the parameters
|
96
107
|
command = $api_server.get_cmd(target_name, cmd_name, scope: scope)
|
108
|
+
# This returns a packet hash instead of the command hash so add missing fields
|
109
|
+
command['cmd_name'] = cmd_name
|
110
|
+
command['cmd_params'] = cmd_params
|
97
111
|
cmd_params.each do |param_name, _param_value|
|
98
112
|
param = command['items'].find { |item| item['name'] == param_name }
|
99
113
|
unless param
|
100
114
|
raise "Packet item '#{target_name} #{cmd_name} #{param_name}' does not exist"
|
101
115
|
end
|
102
116
|
end
|
103
|
-
_log_cmd(
|
104
|
-
|
117
|
+
_log_cmd(command, raw, no_range, no_hazardous)
|
118
|
+
end
|
105
119
|
|
106
120
|
# Send the command and log the results
|
107
121
|
# This method signature has to include the keyword params present in cmd_api.rb _cmd_implementation()
|
@@ -113,30 +127,29 @@ module OpenC3
|
|
113
127
|
raw = cmd.include?('raw')
|
114
128
|
no_range = cmd.include?('no_range') || cmd.include?('no_checks')
|
115
129
|
no_hazardous = cmd.include?('no_hazardous') || cmd.include?('no_checks')
|
116
|
-
|
117
130
|
if $disconnect
|
118
131
|
_cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: scope)
|
119
132
|
else
|
120
133
|
begin
|
121
134
|
begin
|
122
|
-
|
135
|
+
command = $api_server.method_missing(cmd, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
|
123
136
|
if log_message.nil? or log_message
|
124
|
-
_log_cmd(
|
137
|
+
_log_cmd(command, raw, no_range, no_hazardous)
|
125
138
|
end
|
126
139
|
rescue HazardousError => e
|
127
140
|
# This opens a prompt at which point they can cancel and stop the script
|
128
141
|
# or say Yes and send the command. Thus we don't care about the return value.
|
129
142
|
prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
|
130
|
-
|
143
|
+
command = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
|
131
144
|
if log_message.nil? or log_message
|
132
|
-
_log_cmd(
|
145
|
+
_log_cmd(command, raw, no_range, no_hazardous)
|
133
146
|
end
|
134
147
|
end
|
135
148
|
rescue CriticalCmdError => e
|
136
149
|
# This should not return until the critical command has been approved
|
137
|
-
prompt_for_critical_cmd(e.uuid, e.username, e.target_name, e.cmd_name, e.cmd_params, e.cmd_string)
|
150
|
+
prompt_for_critical_cmd(e.uuid, e.command['username'], e.command['target_name'], e.command['cmd_name'], e.command['cmd_params'], e.command['cmd_string'])
|
138
151
|
if log_message.nil? or log_message
|
139
|
-
_log_cmd(e.
|
152
|
+
_log_cmd(e.command, raw, no_range, no_hazardous)
|
140
153
|
end
|
141
154
|
end
|
142
155
|
end
|
@@ -14,10 +14,10 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# 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'
|
@@ -169,7 +169,7 @@ module OpenC3
|
|
169
169
|
'GENERIC_WRITE_CONVERSION_START', 'REQUIRED', 'LIMITS',
|
170
170
|
'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',
|
171
171
|
'HIDDEN', 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE',
|
172
|
-
'OVERFLOW', 'UNEDITABLE'
|
172
|
+
'OVERFLOW', 'UNEDITABLE', 'OBFUSCATE'
|
173
173
|
unless @current_item
|
174
174
|
raise parser.error("No current item for #{keyword}")
|
175
175
|
end
|
data/lib/openc3/top_level.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -51,11 +51,7 @@ end
|
|
51
51
|
|
52
52
|
class CriticalCmdError < StandardError
|
53
53
|
attr_accessor :uuid
|
54
|
-
attr_accessor :
|
55
|
-
attr_accessor :target_name
|
56
|
-
attr_accessor :cmd_name
|
57
|
-
attr_accessor :cmd_params
|
58
|
-
attr_accessor :cmd_string
|
54
|
+
attr_accessor :command
|
59
55
|
end
|
60
56
|
|
61
57
|
# If a disabled command is sent through the {OpenC3::Api} this error is raised.
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2025, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -41,7 +41,7 @@ module OpenC3
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# @param command [Hash] Command hash structure read to be written to a topic
|
44
|
-
def self.send_command(command, timeout: COMMAND_ACK_TIMEOUT_S, scope:)
|
44
|
+
def self.send_command(command, timeout: COMMAND_ACK_TIMEOUT_S, scope:, obfuscated_items: [])
|
45
45
|
timeout = COMMAND_ACK_TIMEOUT_S unless timeout
|
46
46
|
ack_topic = "{#{scope}__ACKCMD}TARGET__#{command['target_name']}"
|
47
47
|
Topic.update_topic_offsets([ack_topic])
|
@@ -50,17 +50,18 @@ module OpenC3
|
|
50
50
|
command['cmd_params'] = JSON.generate(command['cmd_params'].as_json(:allow_nan => true))
|
51
51
|
OpenC3.inject_context(command)
|
52
52
|
cmd_id = Topic.write_topic("{#{scope}__CMD}TARGET__#{command['target_name']}", command, '*', 100)
|
53
|
+
command["cmd_params"] = cmd_params # Restore the original cmd_params Hash
|
53
54
|
time = Time.now
|
54
55
|
while (Time.now - time) < timeout
|
55
56
|
Topic.read_topics([ack_topic]) do |_topic, _msg_id, msg_hash, _redis|
|
56
57
|
if msg_hash["id"] == cmd_id
|
57
58
|
if msg_hash["result"] == "SUCCESS"
|
58
|
-
return
|
59
|
+
return command
|
59
60
|
# Check for HazardousError which is a special case
|
60
61
|
elsif msg_hash["result"].include?("HazardousError")
|
61
|
-
raise_hazardous_error(msg_hash, command
|
62
|
+
raise_hazardous_error(msg_hash, command)
|
62
63
|
elsif msg_hash["result"].include?("CriticalCmdError")
|
63
|
-
raise_critical_cmd_error(msg_hash, command
|
64
|
+
raise_critical_cmd_error(msg_hash, command)
|
64
65
|
else
|
65
66
|
raise msg_hash["result"]
|
66
67
|
end
|
@@ -74,14 +75,14 @@ module OpenC3
|
|
74
75
|
# PRIVATE implementation details
|
75
76
|
###########################################################################
|
76
77
|
|
77
|
-
def self.raise_hazardous_error(msg_hash,
|
78
|
+
def self.raise_hazardous_error(msg_hash, command)
|
78
79
|
_, description, formatted = msg_hash["result"].split("\n")
|
79
80
|
# Create and populate a new HazardousError and raise it up
|
80
81
|
# The _cmd method in script/commands.rb rescues this and calls prompt_for_hazardous
|
81
82
|
error = HazardousError.new
|
82
|
-
error.target_name = target_name
|
83
|
-
error.cmd_name = cmd_name
|
84
|
-
error.cmd_params = cmd_params
|
83
|
+
error.target_name = command["target_name"]
|
84
|
+
error.cmd_name = command["cmd_name"]
|
85
|
+
error.cmd_params = command["cmd_params"]
|
85
86
|
error.hazardous_description = description
|
86
87
|
error.formatted = formatted
|
87
88
|
|
@@ -89,17 +90,13 @@ module OpenC3
|
|
89
90
|
raise error
|
90
91
|
end
|
91
92
|
|
92
|
-
def self.raise_critical_cmd_error(msg_hash,
|
93
|
+
def self.raise_critical_cmd_error(msg_hash, command)
|
93
94
|
_, uuid = msg_hash["result"].split("\n")
|
94
95
|
# Create and populate a new CriticalCmdError and raise it up
|
95
96
|
# The _cmd method in script/commands.rb rescues this and calls prompt_for_critical_cmd
|
96
97
|
error = CriticalCmdError.new
|
97
98
|
error.uuid = uuid
|
98
|
-
error.
|
99
|
-
error.target_name = target_name
|
100
|
-
error.cmd_name = cmd_name
|
101
|
-
error.cmd_params = cmd_params
|
102
|
-
error.cmd_string = cmd_string
|
99
|
+
error.command = command
|
103
100
|
raise error
|
104
101
|
end
|
105
102
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2025 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
require 'openc3/packets/packet'
|
20
|
+
|
21
|
+
module OpenC3
|
22
|
+
module CmdLog
|
23
|
+
def _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet)
|
24
|
+
output_string = "#{method_name}(\""
|
25
|
+
output_string << (target_name + ' ' + cmd_name)
|
26
|
+
if cmd_params.nil? or cmd_params.empty?
|
27
|
+
output_string << '")'
|
28
|
+
else
|
29
|
+
params = []
|
30
|
+
cmd_params.each do |key, value|
|
31
|
+
next if Packet::RESERVED_ITEM_NAMES.include?(key)
|
32
|
+
|
33
|
+
item = packet['items'].find { |find_item| find_item['name'] == key.to_s }
|
34
|
+
begin
|
35
|
+
item_type = item['data_type'].intern
|
36
|
+
rescue
|
37
|
+
item_type = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
if (item and item['obfuscate'])
|
41
|
+
params << "#{key} *****"
|
42
|
+
else
|
43
|
+
if value.is_a?(String)
|
44
|
+
value = value.dup
|
45
|
+
if item_type == :BLOCK or item_type == :STRING
|
46
|
+
if !value.is_printable?
|
47
|
+
value = "0x" + value.simple_formatted
|
48
|
+
else
|
49
|
+
value = value.inspect
|
50
|
+
end
|
51
|
+
else
|
52
|
+
value = value.convert_to_value.to_s
|
53
|
+
end
|
54
|
+
if value.length > 256
|
55
|
+
value = value[0..255] + "...'"
|
56
|
+
end
|
57
|
+
value.tr!('"', "'")
|
58
|
+
elsif value.is_a?(Array)
|
59
|
+
value = "[#{value.join(", ")}]"
|
60
|
+
end
|
61
|
+
params << "#{key} #{value}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
params = params.join(", ")
|
65
|
+
output_string << (' with ' + params + '")')
|
66
|
+
end
|
67
|
+
return output_string
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/openc3/version.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
OPENC3_VERSION = '6.
|
3
|
+
OPENC3_VERSION = '6.6.0'
|
4
4
|
module OpenC3
|
5
5
|
module Version
|
6
6
|
MAJOR = '6'
|
7
|
-
MINOR = '
|
8
|
-
PATCH = '
|
7
|
+
MINOR = '6'
|
8
|
+
PATCH = '0'
|
9
9
|
OTHER = ''
|
10
|
-
BUILD = '
|
10
|
+
BUILD = 'ceee2aabacbdfe57fe8b5de3580358db2ae3a19a'
|
11
11
|
end
|
12
|
-
VERSION = '6.
|
13
|
-
GEM_VERSION = '6.
|
12
|
+
VERSION = '6.6.0'
|
13
|
+
GEM_VERSION = '6.6.0'
|
14
14
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "<%= tool_name %>",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.6.0",
|
4
4
|
"scripts": {
|
5
5
|
"ng": "ng",
|
6
6
|
"start": "ng serve",
|
@@ -23,7 +23,7 @@
|
|
23
23
|
"@angular/platform-browser-dynamic": "^18.2.6",
|
24
24
|
"@angular/router": "^18.2.6",
|
25
25
|
"@astrouxds/astro-web-components": "^7.24.0",
|
26
|
-
"@openc3/js-common": "6.
|
26
|
+
"@openc3/js-common": "6.6.0",
|
27
27
|
"rxjs": "~7.8.0",
|
28
28
|
"single-spa": "^5.9.5",
|
29
29
|
"single-spa-angular": "^9.2.0",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "<%= tool_name %>",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.6.0",
|
4
4
|
"private": true,
|
5
5
|
"type": "module",
|
6
6
|
"scripts": {
|
@@ -11,8 +11,8 @@
|
|
11
11
|
},
|
12
12
|
"dependencies": {
|
13
13
|
"@astrouxds/astro-web-components": "^7.24.0",
|
14
|
-
"@openc3/js-common": "6.
|
15
|
-
"@openc3/vue-common": "6.
|
14
|
+
"@openc3/js-common": "6.6.0",
|
15
|
+
"@openc3/vue-common": "6.6.0",
|
16
16
|
"axios": "^1.7.7",
|
17
17
|
"date-fns": "^4.1.0",
|
18
18
|
"lodash": "^4.17.21",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "<%= widget_name %>",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.6.0",
|
4
4
|
"private": true,
|
5
5
|
"type": "module",
|
6
6
|
"scripts": {
|
@@ -8,7 +8,7 @@
|
|
8
8
|
},
|
9
9
|
"dependencies": {
|
10
10
|
"@astrouxds/astro-web-components": "^7.24.0",
|
11
|
-
"@openc3/vue-common": "6.
|
11
|
+
"@openc3/vue-common": "6.6.0",
|
12
12
|
"vuetify": "^3.7.1"
|
13
13
|
},
|
14
14
|
"devDependencies": {
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openc3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Melton
|
@@ -766,20 +766,6 @@ dependencies:
|
|
766
766
|
- - "~>"
|
767
767
|
- !ruby/object:Gem::Version
|
768
768
|
version: '2.1'
|
769
|
-
- !ruby/object:Gem::Dependency
|
770
|
-
name: simplecov_json_formatter
|
771
|
-
requirement: !ruby/object:Gem::Requirement
|
772
|
-
requirements:
|
773
|
-
- - "~>"
|
774
|
-
- !ruby/object:Gem::Version
|
775
|
-
version: '0.1'
|
776
|
-
type: :development
|
777
|
-
prerelease: false
|
778
|
-
version_requirements: !ruby/object:Gem::Requirement
|
779
|
-
requirements:
|
780
|
-
- - "~>"
|
781
|
-
- !ruby/object:Gem::Version
|
782
|
-
version: '0.1'
|
783
769
|
description: |2
|
784
770
|
OpenC3 provides all the functionality needed to send
|
785
771
|
commands to and receive data from one or more embedded systems
|
@@ -1156,6 +1142,7 @@ files:
|
|
1156
1142
|
- lib/openc3/utilities/bucket_require.rb
|
1157
1143
|
- lib/openc3/utilities/bucket_utilities.rb
|
1158
1144
|
- lib/openc3/utilities/cli_generator.rb
|
1145
|
+
- lib/openc3/utilities/cmd_log.rb
|
1159
1146
|
- lib/openc3/utilities/cosmos_rails_formatter.rb
|
1160
1147
|
- lib/openc3/utilities/crc.rb
|
1161
1148
|
- lib/openc3/utilities/csv.rb
|