openc3 5.19.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +0 -7
- data/bin/openc3cli +12 -120
- data/bin/pipinstall +5 -3
- data/data/config/command_modifiers.yaml +17 -1
- data/data/config/interface_modifiers.yaml +21 -4
- data/data/config/item_modifiers.yaml +1 -1
- data/data/config/microservice.yaml +15 -2
- data/data/config/param_item_modifiers.yaml +1 -1
- data/data/config/parameter_modifiers.yaml +1 -1
- data/data/config/table_manager.yaml +2 -2
- data/data/config/target.yaml +11 -0
- data/data/config/telemetry_modifiers.yaml +17 -1
- data/data/config/tool.yaml +12 -0
- data/data/config/widgets.yaml +41 -17
- data/ext/openc3/ext/packet/packet.c +3 -0
- data/lib/openc3/accessors/form_accessor.rb +4 -3
- data/lib/openc3/accessors/html_accessor.rb +3 -3
- data/lib/openc3/accessors/http_accessor.rb +13 -13
- data/lib/openc3/accessors/xml_accessor.rb +16 -4
- data/lib/openc3/api/cmd_api.rb +4 -5
- data/lib/openc3/api/limits_api.rb +3 -3
- data/lib/openc3/api/target_api.rb +0 -30
- data/lib/openc3/api/tlm_api.rb +2 -1
- data/lib/openc3/bridge/bridge_config.rb +1 -2
- data/lib/openc3/ccsds/ccsds_parser.rb +12 -8
- data/lib/openc3/config/config_parser.rb +10 -3
- data/lib/openc3/conversions/bit_reverse_conversion.rb +1 -0
- data/lib/openc3/conversions/conversion.rb +5 -1
- data/lib/openc3/conversions/generic_conversion.rb +3 -8
- data/lib/openc3/conversions/object_read_conversion.rb +1 -8
- data/lib/openc3/conversions/polynomial_conversion.rb +3 -8
- data/lib/openc3/conversions/processor_conversion.rb +13 -11
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +3 -11
- data/lib/openc3/conversions/unix_time_conversion.rb +4 -7
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +4 -3
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +4 -3
- data/lib/openc3/core_ext/array.rb +0 -16
- data/lib/openc3/core_ext.rb +0 -1
- data/lib/openc3/interfaces/file_interface.rb +198 -0
- data/lib/openc3/interfaces/http_client_interface.rb +71 -39
- data/lib/openc3/interfaces/http_server_interface.rb +1 -9
- data/lib/openc3/interfaces/interface.rb +3 -2
- data/lib/openc3/interfaces/mqtt_interface.rb +32 -15
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +19 -4
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -0
- data/lib/openc3/interfaces/serial_interface.rb +1 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +1 -2
- data/lib/openc3/interfaces/udp_interface.rb +5 -3
- data/lib/openc3/interfaces.rb +2 -4
- data/lib/openc3/io/json_drb.rb +5 -0
- data/lib/openc3/io/json_rpc.rb +10 -9
- data/lib/openc3/io/udp_sockets.rb +7 -5
- data/lib/openc3/microservices/decom_microservice.rb +24 -7
- data/lib/openc3/microservices/interface_microservice.rb +65 -7
- data/lib/openc3/microservices/microservice.rb +1 -2
- data/lib/openc3/microservices/multi_microservice.rb +3 -3
- data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +31 -0
- data/lib/openc3/migrations/20241208080001_no_trigger_group.rb +46 -0
- data/lib/openc3/models/activity_model.rb +7 -3
- data/lib/openc3/models/cvt_model.rb +7 -1
- data/lib/openc3/models/interface_model.rb +9 -3
- data/lib/openc3/models/microservice_model.rb +8 -1
- data/lib/openc3/models/model.rb +1 -0
- data/lib/openc3/models/plugin_model.rb +11 -6
- data/lib/openc3/models/python_package_model.rb +10 -3
- data/lib/openc3/models/reaction_model.rb +14 -10
- data/lib/openc3/models/scope_model.rb +87 -25
- data/lib/openc3/models/target_model.rb +17 -1
- data/lib/openc3/models/timeline_model.rb +17 -5
- data/lib/openc3/models/tool_model.rb +15 -3
- data/lib/openc3/models/trigger_group_model.rb +6 -3
- data/lib/openc3/operators/microservice_operator.rb +10 -3
- data/lib/openc3/packets/commands.rb +17 -6
- data/lib/openc3/packets/limits.rb +0 -12
- data/lib/openc3/packets/packet.rb +10 -1
- data/lib/openc3/packets/packet_config.rb +34 -1
- data/lib/openc3/packets/packet_item.rb +30 -32
- data/lib/openc3/packets/structure_item.rb +2 -2
- data/lib/openc3/script/calendar.rb +1 -6
- data/lib/openc3/script/commands.rb +19 -13
- data/lib/openc3/script/critical_cmd.rb +91 -0
- data/lib/openc3/script/screen.rb +2 -2
- data/lib/openc3/script/script.rb +17 -10
- data/lib/openc3/script/web_socket_api.rb +5 -5
- data/lib/openc3/streams/mqtt_stream.rb +41 -33
- data/lib/openc3/streams/serial_stream.rb +27 -27
- data/lib/openc3/streams/stream.rb +17 -17
- data/lib/openc3/streams/tcpip_client_stream.rb +1 -1
- data/lib/openc3/streams/tcpip_socket_stream.rb +19 -19
- data/lib/openc3/system/system.rb +1 -1
- data/lib/openc3/system.rb +2 -3
- data/lib/openc3/tools/table_manager/table.rb +2 -2
- data/lib/openc3/tools/table_manager/table_parser.rb +1 -1
- data/lib/openc3/top_level.rb +9 -5
- data/lib/openc3/topics/command_decom_topic.rb +0 -7
- data/lib/openc3/topics/command_topic.rb +16 -0
- data/lib/openc3/topics/interface_topic.rb +2 -0
- data/lib/openc3/utilities/authentication.rb +7 -3
- data/lib/openc3/utilities/bucket_utilities.rb +1 -1
- data/lib/openc3/utilities/cli_generator.rb +0 -1
- data/lib/openc3/utilities/logger.rb +1 -0
- data/lib/openc3/utilities/store_queued.rb +1 -0
- data/lib/openc3/version.rb +6 -6
- data/templates/conversion/conversion.rb +2 -0
- data/templates/plugin/README.md +1 -1
- data/templates/target/targets/TARGET/lib/target.rb +1 -1
- data/templates/tool_angular/package.json +9 -9
- data/templates/tool_angular/src/app/app.component.html +4 -13
- data/templates/tool_angular/src/app/app.component.scss +5 -13
- data/templates/tool_angular/src/app/app.component.ts +5 -4
- data/templates/tool_angular/src/app/custom-overlay-container.ts +2 -2
- data/templates/tool_angular/src/app/openc3-api.d.ts +1 -1
- data/templates/tool_angular/src/main.single-spa.ts +1 -1
- data/templates/tool_react/package.json +1 -0
- data/templates/tool_react/src/root.component.js +1 -1
- data/templates/tool_svelte/build/smui.css +1 -1
- data/templates/tool_svelte/package.json +11 -9
- data/templates/tool_svelte/rollup.config.js +2 -0
- data/templates/tool_svelte/src/App.svelte +2 -2
- data/templates/tool_vue/eslint.config.mjs +68 -0
- data/templates/tool_vue/jsconfig.json +1 -1
- data/templates/tool_vue/package.json +26 -43
- data/templates/tool_vue/src/App.vue +3 -5
- data/templates/tool_vue/src/main.js +12 -23
- data/templates/tool_vue/src/router.js +19 -18
- data/templates/tool_vue/src/tools/tool_name/tool_name.vue +2 -2
- data/templates/tool_vue/vite.config.js +52 -0
- data/templates/widget/package.json +19 -26
- data/templates/widget/src/Widget.vue +13 -15
- data/templates/widget/vite.config.js +26 -0
- metadata +25 -39
- data/lib/openc3/core_ext/hash.rb +0 -40
- data/lib/openc3/core_ext/httpclient.rb +0 -11
- data/lib/openc3/interfaces/linc_interface.rb +0 -480
- data/lib/openc3/interfaces/protocols/override_protocol.rb +0 -4
- data/lib/openc3/microservices/reaction_microservice.rb +0 -607
- data/lib/openc3/microservices/timeline_microservice.rb +0 -400
- data/lib/openc3/microservices/trigger_group_microservice.rb +0 -698
- data/lib/openc3/migrations/20230615000000_autonomic.rb +0 -86
- data/lib/openc3/migrations/20240915000000_activity_uuid.rb +0 -28
- data/lib/openc3/system/system_config.rb +0 -413
- data/templates/tool_svelte/src/services/api.js +0 -92
- data/templates/tool_svelte/src/services/axios.js +0 -85
- data/templates/tool_svelte/src/services/cable.js +0 -65
- data/templates/tool_svelte/src/services/config-parser.js +0 -198
- data/templates/tool_svelte/src/services/openc3-api.js +0 -606
- data/templates/tool_vue/.eslintrc.js +0 -43
- data/templates/tool_vue/babel.config.json +0 -11
- data/templates/tool_vue/vue.config.js +0 -38
- data/templates/widget/.eslintrc.js +0 -43
- data/templates/widget/babel.config.json +0 -11
- data/templates/widget/vue.config.js +0 -28
- /data/templates/tool_vue/{.prettierrc.js → .prettierrc.cjs} +0 -0
- /data/templates/widget/{.prettierrc.js → .prettierrc.cjs} +0 -0
@@ -64,9 +64,9 @@ module OpenC3
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
attr_reader :name, :scope, :updated_at
|
67
|
+
attr_reader :name, :scope, :shard, :updated_at
|
68
68
|
|
69
|
-
def initialize(name:, scope:, updated_at: nil)
|
69
|
+
def initialize(name:, scope:, shard: 0, updated_at: nil)
|
70
70
|
unless name.is_a?(String)
|
71
71
|
raise TriggerGroupInputError.new "invalid group name: '#{name}'"
|
72
72
|
end
|
@@ -75,6 +75,7 @@ module OpenC3
|
|
75
75
|
end
|
76
76
|
super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope)
|
77
77
|
@microservice_name = "#{scope}__TRIGGER_GROUP__#{name}"
|
78
|
+
@shard = shard.to_i # to_i to handle nil
|
78
79
|
@updated_at = updated_at
|
79
80
|
end
|
80
81
|
|
@@ -93,6 +94,7 @@ module OpenC3
|
|
93
94
|
return {
|
94
95
|
'name' => @name,
|
95
96
|
'scope' => @scope,
|
97
|
+
'shard' => @shard,
|
96
98
|
'updated_at' => @updated_at,
|
97
99
|
}
|
98
100
|
end
|
@@ -122,11 +124,12 @@ module OpenC3
|
|
122
124
|
name: @microservice_name,
|
123
125
|
folder_name: nil,
|
124
126
|
cmd: ['ruby', "trigger_group_microservice.rb", @microservice_name],
|
125
|
-
work_dir: '/openc3/lib/openc3/microservices',
|
127
|
+
work_dir: '/openc3-enterprise/lib/openc3-enterprise/microservices',
|
126
128
|
options: [],
|
127
129
|
topics: topics,
|
128
130
|
target_names: [],
|
129
131
|
plugin: nil,
|
132
|
+
shard: @shard,
|
130
133
|
scope: @scope
|
131
134
|
)
|
132
135
|
microservice.create
|
@@ -42,6 +42,8 @@ module OpenC3
|
|
42
42
|
@new_microservices = {}
|
43
43
|
@changed_microservices = {}
|
44
44
|
@removed_microservices = {}
|
45
|
+
@shard = ENV['OPENC3_SHARD'] || 0
|
46
|
+
@shard = @shard.to_i
|
45
47
|
end
|
46
48
|
|
47
49
|
def convert_microservice_to_process_definition(microservice_name, microservice_config)
|
@@ -65,10 +67,9 @@ module OpenC3
|
|
65
67
|
secrets.each do |type, secret_name, env_name_or_path, secret_store|
|
66
68
|
secret_value = @secrets.get(secret_name, secret_store: secret_store, scope: scope)
|
67
69
|
if secret_value
|
68
|
-
|
69
|
-
when 'ENV'
|
70
|
+
if type == 'ENV'
|
70
71
|
env[env_name_or_path] = secret_value
|
71
|
-
|
72
|
+
elsif type == 'FILE'
|
72
73
|
FileUtils.mkdir_p(File.dirname(env_name_or_path))
|
73
74
|
File.open(env_name_or_path, 'wb') do |file|
|
74
75
|
file.write(secret_value)
|
@@ -88,6 +89,12 @@ module OpenC3
|
|
88
89
|
# Get all the microservice configuration
|
89
90
|
@microservices = MicroserviceModel.all
|
90
91
|
|
92
|
+
# Filter to just this shard
|
93
|
+
@microservices = @microservices.select do |microservice_name, microservice_config|
|
94
|
+
microservice_shard = microservice_config['shard'] || 0
|
95
|
+
microservice_shard == @shard
|
96
|
+
end
|
97
|
+
|
91
98
|
# Detect new and changed microservices
|
92
99
|
@new_microservices = {}
|
93
100
|
@changed_microservices = {}
|
@@ -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 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
|
@@ -308,12 +308,23 @@ module OpenC3
|
|
308
308
|
item = command.get_item(item_upcase)
|
309
309
|
range_check_value = value
|
310
310
|
|
311
|
-
# Convert from state to value if possible
|
312
|
-
if item.states and item.states[value.to_s.upcase]
|
313
|
-
range_check_value = item.states[value.to_s.upcase]
|
314
|
-
end
|
315
|
-
|
316
311
|
if range_checking
|
312
|
+
if item.states
|
313
|
+
if item.states[value.to_s.upcase]
|
314
|
+
range_check_value = item.states[value.to_s.upcase]
|
315
|
+
else
|
316
|
+
unless item.states.values.include?(value)
|
317
|
+
if command.raw
|
318
|
+
# Raw commands report missing value maps
|
319
|
+
raise "Command parameter '#{command.target_name} #{command.packet_name} #{item_upcase}' = #{value.to_s.upcase} not one of #{item.states.values.join(', ')}"
|
320
|
+
else
|
321
|
+
# Normal commands report missing state maps
|
322
|
+
raise "Command parameter '#{command.target_name} #{command.packet_name} #{item_upcase}' = #{value.to_s.upcase} not one of #{item.states.keys.join(', ')}"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
317
328
|
range = item.range
|
318
329
|
if range
|
319
330
|
# Perform Range Check on command parameter
|
@@ -50,18 +50,6 @@ module OpenC3
|
|
50
50
|
return @config.limits_sets
|
51
51
|
end
|
52
52
|
|
53
|
-
# (see OpenC3::Packet#out_of_limits)
|
54
|
-
def out_of_limits
|
55
|
-
items = []
|
56
|
-
@config.telemetry.each do |target_name, target_packets|
|
57
|
-
target_packets.each do |packet_name, packet|
|
58
|
-
new_items = packet.out_of_limits
|
59
|
-
items.concat(new_items)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
return items
|
63
|
-
end
|
64
|
-
|
65
53
|
# @return [Hash(String, Array)] The defined limits groups
|
66
54
|
def groups
|
67
55
|
return @config.limits_groups
|
@@ -110,6 +110,9 @@ module OpenC3
|
|
110
110
|
# @return [Boolean] If this packet should be used for identification
|
111
111
|
attr_reader :virtual
|
112
112
|
|
113
|
+
# @return [Boolean] If this packet is marked as restricted use
|
114
|
+
attr_accessor :restricted
|
115
|
+
|
113
116
|
# Valid format types
|
114
117
|
VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED, :WITH_UNITS]
|
115
118
|
|
@@ -151,6 +154,7 @@ module OpenC3
|
|
151
154
|
@packet_time = nil
|
152
155
|
@ignore_overlap = false
|
153
156
|
@virtual = false
|
157
|
+
@restricted = false
|
154
158
|
@validator = nil
|
155
159
|
end
|
156
160
|
|
@@ -752,7 +756,7 @@ module OpenC3
|
|
752
756
|
super(item, value, :RAW, buffer)
|
753
757
|
rescue ArgumentError => e
|
754
758
|
if item.states and String === value and e.message =~ /invalid value for/
|
755
|
-
raise "Unknown state #{value} for #{item.name}"
|
759
|
+
raise "Unknown state #{value} for #{item.name}, must be one of #{item.states.keys.join(', ')}"
|
756
760
|
else
|
757
761
|
raise e
|
758
762
|
end
|
@@ -1085,6 +1089,9 @@ module OpenC3
|
|
1085
1089
|
elsif @hidden
|
1086
1090
|
config << " HIDDEN\n"
|
1087
1091
|
end
|
1092
|
+
if @restricted
|
1093
|
+
config << " RESTRICTED\n"
|
1094
|
+
end
|
1088
1095
|
|
1089
1096
|
if @processors
|
1090
1097
|
@processors.each do |_processor_name, processor|
|
@@ -1145,6 +1152,7 @@ module OpenC3
|
|
1145
1152
|
config['disabled'] = true if @disabled
|
1146
1153
|
config['hidden'] = true if @hidden
|
1147
1154
|
config['virtual'] = true if @virtual
|
1155
|
+
config['restricted'] = true if @restricted
|
1148
1156
|
config['accessor'] = @accessor.class.to_s
|
1149
1157
|
config['accessor_args'] = @accessor.args
|
1150
1158
|
config['validator'] = @validator.class.to_s if @validator
|
@@ -1201,6 +1209,7 @@ module OpenC3
|
|
1201
1209
|
packet.disabled = hash['disabled']
|
1202
1210
|
packet.hidden = hash['hidden']
|
1203
1211
|
packet.virtual = hash['virtual']
|
1212
|
+
packet.restricted = hash['restricted']
|
1204
1213
|
if hash['accessor']
|
1205
1214
|
begin
|
1206
1215
|
accessor = OpenC3::const_get(hash['accessor'])
|
@@ -34,9 +34,11 @@ require 'openc3/packets/parsers/xtce_converter'
|
|
34
34
|
require 'openc3/utilities/python_proxy'
|
35
35
|
require 'openc3/conversions'
|
36
36
|
require 'openc3/processors'
|
37
|
+
require 'openc3/accessors'
|
37
38
|
require 'nokogiri'
|
38
39
|
require 'ostruct'
|
39
40
|
require 'fileutils'
|
41
|
+
require 'tempfile'
|
40
42
|
|
41
43
|
module OpenC3
|
42
44
|
# Reads a command or telemetry configuration file and builds a hash of packets.
|
@@ -219,7 +221,7 @@ module OpenC3
|
|
219
221
|
'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
|
220
222
|
'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
|
221
223
|
'APPEND_ARRAY_PARAMETER', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META',\
|
222
|
-
'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'VIRTUAL', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE',\
|
224
|
+
'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'VIRTUAL', 'RESTRICTED', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE',\
|
223
225
|
'RESPONSE', 'ERROR_RESPONSE', 'SCREEN', 'RELATED_ITEM', 'IGNORE_OVERLAP', 'VALIDATOR'
|
224
226
|
raise parser.error("No current packet for #{keyword}") unless @current_packet
|
225
227
|
|
@@ -367,6 +369,32 @@ module OpenC3
|
|
367
369
|
end
|
368
370
|
end
|
369
371
|
|
372
|
+
# This method provides way to quickly test packet configs
|
373
|
+
#
|
374
|
+
# require 'openc3/packets/packet_config'
|
375
|
+
#
|
376
|
+
# config = <<END
|
377
|
+
# ...
|
378
|
+
# END
|
379
|
+
#
|
380
|
+
# pc = PacketConfig.from_config(config, "MYTARGET")
|
381
|
+
# c = pc.commands['CMDADCS']['SET_POINTING_CMD']
|
382
|
+
# c.restore_defaults()
|
383
|
+
# c.write("MYITEM", 5)
|
384
|
+
# puts c.buffer.formatted
|
385
|
+
def self.from_config(config, process_target_name, language = 'ruby')
|
386
|
+
pc = self.new
|
387
|
+
tf = Tempfile.new("pc.txt")
|
388
|
+
tf.write(config)
|
389
|
+
tf.close
|
390
|
+
begin
|
391
|
+
pc.process_file(tf.path, process_target_name, language)
|
392
|
+
ensure
|
393
|
+
tf.unlink
|
394
|
+
end
|
395
|
+
return pc
|
396
|
+
end
|
397
|
+
|
370
398
|
protected
|
371
399
|
|
372
400
|
def update_id_value_hash(packet, hash)
|
@@ -480,6 +508,11 @@ module OpenC3
|
|
480
508
|
@current_packet.disabled = true
|
481
509
|
@current_packet.virtual = true
|
482
510
|
|
511
|
+
when 'RESTRICTED'
|
512
|
+
usage = "#{keyword}"
|
513
|
+
parser.verify_num_parameters(0, 0, usage)
|
514
|
+
@current_packet.restricted = true
|
515
|
+
|
483
516
|
when 'ACCESSOR', 'VALIDATOR'
|
484
517
|
usage = "#{keyword} <Class name> <Optional parameters> ..."
|
485
518
|
parser.verify_num_parameters(1, nil, usage)
|
@@ -112,8 +112,6 @@ module OpenC3
|
|
112
112
|
@messages_disabled = nil
|
113
113
|
@state_colors = nil
|
114
114
|
@limits = PacketItemLimits.new
|
115
|
-
@persistence_setting = 1
|
116
|
-
@persistence_count = 0
|
117
115
|
@meta = nil
|
118
116
|
end
|
119
117
|
|
@@ -426,15 +424,13 @@ module OpenC3
|
|
426
424
|
config << self.read_conversion.to_config(:READ) if self.read_conversion
|
427
425
|
config << self.write_conversion.to_config(:WRITE) if self.write_conversion
|
428
426
|
|
429
|
-
if self.limits
|
430
|
-
|
431
|
-
self.limits.
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
config << "\n"
|
437
|
-
end
|
427
|
+
if self.limits.values
|
428
|
+
self.limits.values.each do |limits_set, limits_values|
|
429
|
+
config << " LIMITS #{limits_set} #{self.limits.persistence_setting} #{self.limits.enabled ? 'ENABLED' : 'DISABLED'} #{limits_values[0]} #{limits_values[1]} #{limits_values[2]} #{limits_values[3]}"
|
430
|
+
if limits_values[4] && limits_values[5]
|
431
|
+
config << " #{limits_values[4]} #{limits_values[5]}\n"
|
432
|
+
else
|
433
|
+
config << "\n"
|
438
434
|
end
|
439
435
|
end
|
440
436
|
config << self.limits.response.to_config if self.limits.response
|
@@ -489,31 +485,33 @@ module OpenC3
|
|
489
485
|
config['read_conversion'] = self.read_conversion.as_json(*a) if self.read_conversion
|
490
486
|
config['write_conversion'] = self.write_conversion.as_json(*a) if self.write_conversion
|
491
487
|
|
492
|
-
|
493
|
-
|
494
|
-
config['limits']['enabled'] = true
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
488
|
+
config['limits'] ||= {}
|
489
|
+
if self.limits.enabled
|
490
|
+
config['limits']['enabled'] = true
|
491
|
+
elsif self.limits.values || (self.state_colors && self.state_colors.length > 0)
|
492
|
+
# Only set to false if there are limits or state colors
|
493
|
+
# to avoid items without limits acting like they can be enabled
|
494
|
+
config['limits']['enabled'] = false
|
495
|
+
end
|
496
|
+
if self.limits.values
|
497
|
+
# Only set these if there are limits.values because persistence_setting has a default
|
498
|
+
# and we don't want keys on the 'limits' hash if there aren't any limits
|
499
|
+
config['limits']['persistence_setting'] = self.limits.persistence_setting if self.limits.persistence_setting
|
500
|
+
config['limits']['response'] = self.limits.response.to_s if self.limits.response
|
501
|
+
self.limits.values.each do |limits_set, limits_values|
|
502
|
+
limits = {}
|
503
|
+
limits['red_low'] = limits_values[0]
|
504
|
+
limits['yellow_low'] = limits_values[1]
|
505
|
+
limits['yellow_high'] = limits_values[2]
|
506
|
+
limits['red_high'] = limits_values[3]
|
507
|
+
limits['green_low'] = limits_values[4] if limits_values[4]
|
508
|
+
limits['green_high'] = limits_values[5] if limits_values[5]
|
509
|
+
config['limits'][limits_set] = limits
|
509
510
|
end
|
510
|
-
config['limits_response'] = self.limits.response.as_json(*a) if self.limits.response
|
511
511
|
end
|
512
512
|
|
513
513
|
config['meta'] = @meta if @meta
|
514
|
-
if @variable_bit_size
|
515
|
-
config['variable_bit_size'] = @variable_bit_size
|
516
|
-
end
|
514
|
+
config['variable_bit_size'] = @variable_bit_size if @variable_bit_size
|
517
515
|
config
|
518
516
|
end
|
519
517
|
|
@@ -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 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
|
@@ -141,7 +141,7 @@ module OpenC3
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def key=(key)
|
144
|
-
raise ArgumentError, "key must be a String but is a #{
|
144
|
+
raise ArgumentError, "key must be a String but is a #{key.class}" unless String === key
|
145
145
|
raise ArgumentError, "key must contain at least one character" if key.empty?
|
146
146
|
|
147
147
|
@key = key
|
@@ -98,12 +98,7 @@ module OpenC3
|
|
98
98
|
result = JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
99
99
|
raise "#{error_message} due to #{result['message']}"
|
100
100
|
end
|
101
|
-
|
102
|
-
if response.body.nil? or response.body.empty?
|
103
|
-
return nil
|
104
|
-
else
|
105
|
-
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
106
|
-
end
|
101
|
+
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
107
102
|
end
|
108
103
|
end
|
109
104
|
end
|
@@ -46,12 +46,10 @@ module OpenC3
|
|
46
46
|
next if Packet::RESERVED_ITEM_NAMES.include?(key)
|
47
47
|
|
48
48
|
if value.is_a?(String)
|
49
|
-
value = value.convert_to_value.to_s
|
50
|
-
if value.length > 256
|
51
|
-
value = value[0..255] + "...'"
|
52
|
-
end
|
53
49
|
if !value.is_printable?
|
54
50
|
value = "BINARY"
|
51
|
+
elsif value.length > 256
|
52
|
+
value = value[0..255] + "...'"
|
55
53
|
end
|
56
54
|
value.tr!('"', "'")
|
57
55
|
elsif value.is_a?(Array)
|
@@ -120,17 +118,25 @@ module OpenC3
|
|
120
118
|
_cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: scope)
|
121
119
|
else
|
122
120
|
begin
|
123
|
-
|
124
|
-
|
125
|
-
|
121
|
+
begin
|
122
|
+
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
|
123
|
+
if log_message.nil? or log_message
|
124
|
+
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
125
|
+
end
|
126
|
+
rescue HazardousError => e
|
127
|
+
# This opens a prompt at which point they can cancel and stop the script
|
128
|
+
# or say Yes and send the command. Thus we don't care about the return value.
|
129
|
+
prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
|
130
|
+
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
|
131
|
+
if log_message.nil? or log_message
|
132
|
+
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
133
|
+
end
|
126
134
|
end
|
127
|
-
rescue
|
128
|
-
# This
|
129
|
-
|
130
|
-
prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
|
131
|
-
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
|
135
|
+
rescue CriticalCmdError => e
|
136
|
+
# 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)
|
132
138
|
if log_message.nil? or log_message
|
133
|
-
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
139
|
+
_log_cmd(e.target_name, e.cmd_name, e.cmd_params, raw, no_range, no_hazardous)
|
134
140
|
end
|
135
141
|
end
|
136
142
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2024 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
|
+
module OpenC3
|
20
|
+
module Script
|
21
|
+
private
|
22
|
+
|
23
|
+
def critical_cmd_status(uuid, scope: $openc3_scope)
|
24
|
+
begin
|
25
|
+
endpoint = "/openc3-api/criticalcmd/status/#{uuid}"
|
26
|
+
response = $api_server.request('get', endpoint, scope: scope)
|
27
|
+
if response.nil? || response.status != 200
|
28
|
+
raise "Unexpected response to critical_cmd_status: #{response.inspect}"
|
29
|
+
end
|
30
|
+
result = JSON.parse(response.body)
|
31
|
+
return result['status']
|
32
|
+
rescue => error
|
33
|
+
raise "critical_cmd_status failed due to #{error.formatted}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def critical_cmd_approve(uuid, scope: $openc3_scope)
|
38
|
+
begin
|
39
|
+
endpoint = "/openc3-api/criticalcmd/approve/#{uuid}"
|
40
|
+
response = $api_server.request('post', endpoint, :json => true, scope: scope)
|
41
|
+
if response.nil? || response.status != 200
|
42
|
+
if response
|
43
|
+
parsed = JSON.parse(response.body)
|
44
|
+
raise "critical_cmd_approve error: #{parsed['error']}"
|
45
|
+
else
|
46
|
+
raise "critical_cmd_approve failed"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return
|
50
|
+
rescue => error
|
51
|
+
raise "critical_cmd_approve failed due to #{error.formatted}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def critical_cmd_reject(uuid, scope: $openc3_scope)
|
56
|
+
begin
|
57
|
+
endpoint = "/openc3-api/criticalcmd/reject/#{uuid}"
|
58
|
+
response = $api_server.request('post', endpoint, :json => true, scope: scope)
|
59
|
+
if response.nil? || response.status != 200
|
60
|
+
if response
|
61
|
+
parsed = JSON.parse(response.body)
|
62
|
+
raise "critical_cmd_reject error: #{parsed['error']}"
|
63
|
+
else
|
64
|
+
raise "critical_cmd_reject failed"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return
|
68
|
+
rescue => error
|
69
|
+
raise "critical_cmd_reject failed due to #{error.formatted}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def critical_cmd_can_approve(uuid, scope: $openc3_scope)
|
74
|
+
begin
|
75
|
+
endpoint = "/openc3-api/criticalcmd/canapprove/#{uuid}"
|
76
|
+
response = $api_server.request('get', endpoint, scope: scope)
|
77
|
+
if response.nil? || response.status != 200
|
78
|
+
raise "Unexpected response to critical_cmd_can_approve: #{response.inspect}"
|
79
|
+
end
|
80
|
+
result = JSON.parse(response.body)
|
81
|
+
if result['status'] == 'ok'
|
82
|
+
return true
|
83
|
+
else
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
rescue => error
|
87
|
+
raise "critical_cmd_can_approve failed due to #{error.formatted}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/openc3/script/screen.rb
CHANGED
@@ -70,7 +70,7 @@ module OpenC3
|
|
70
70
|
response = $api_server.request('post', endpoint, :data => data, :json => true, scope: scope)
|
71
71
|
if response.nil? || response.status != 200
|
72
72
|
if response
|
73
|
-
parsed = JSON.parse(response)
|
73
|
+
parsed = JSON.parse(response.body)
|
74
74
|
raise "create_screen error: #{parsed['error']}"
|
75
75
|
else
|
76
76
|
raise "create_screen failed"
|
@@ -88,7 +88,7 @@ module OpenC3
|
|
88
88
|
response = $api_server.request('delete', endpoint, scope: scope)
|
89
89
|
if response.nil? || response.status != 200
|
90
90
|
if response
|
91
|
-
parsed = JSON.parse(response)
|
91
|
+
parsed = JSON.parse(response.body)
|
92
92
|
raise "delete_screen error: #{parsed['error']}"
|
93
93
|
else
|
94
94
|
raise "delete_screen failed"
|
data/lib/openc3/script/script.rb
CHANGED
@@ -36,6 +36,7 @@ require 'openc3/script/storage'
|
|
36
36
|
require 'openc3/script/web_socket_api'
|
37
37
|
require 'openc3/script/packages'
|
38
38
|
require 'openc3/script/plugins'
|
39
|
+
require 'openc3/script/critical_cmd'
|
39
40
|
require 'openc3/utilities/authentication'
|
40
41
|
|
41
42
|
$api_server = nil
|
@@ -108,6 +109,22 @@ module OpenC3
|
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
112
|
+
def prompt_for_critical_cmd(uuid, _username, _target_name, _cmd_name, _cmd_params, cmd_string)
|
113
|
+
puts "Waiting for critical command approval:"
|
114
|
+
puts " #{cmd_string}"
|
115
|
+
puts " UUID: #{uuid}"
|
116
|
+
loop do
|
117
|
+
status = critical_cmd_status(uuid)
|
118
|
+
if status == 'APPROVED'
|
119
|
+
return
|
120
|
+
elsif status == 'REJECTED'
|
121
|
+
raise "Critical command rejected"
|
122
|
+
end
|
123
|
+
# Else still waiting
|
124
|
+
wait(0.1)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
111
128
|
###########################################################################
|
112
129
|
# START PUBLIC API
|
113
130
|
###########################################################################
|
@@ -116,16 +133,6 @@ module OpenC3
|
|
116
133
|
$disconnect = true
|
117
134
|
end
|
118
135
|
|
119
|
-
# DEPRECATED
|
120
|
-
def play_wav_file(wav_filename)
|
121
|
-
# NOOP
|
122
|
-
end
|
123
|
-
|
124
|
-
# DEPRECATED
|
125
|
-
def status_bar(message)
|
126
|
-
# NOOP
|
127
|
-
end
|
128
|
-
|
129
136
|
def ask_string(question, blank_or_default = false, password = false)
|
130
137
|
answer = ''
|
131
138
|
default = ''
|
@@ -126,7 +126,7 @@ module OpenC3
|
|
126
126
|
# Connect to the websocket with authorization in query params
|
127
127
|
def connect
|
128
128
|
disconnect()
|
129
|
-
final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.token}"
|
129
|
+
final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.token(include_bearer: false)}"
|
130
130
|
@stream = WebSocketClientStream.new(final_url, @write_timeout, @read_timeout, @connect_timeout)
|
131
131
|
@stream.headers = {
|
132
132
|
'Sec-WebSocket-Protocol' => 'actioncable-v1-json, actioncable-unsupported',
|
@@ -240,7 +240,7 @@ module OpenC3
|
|
240
240
|
end
|
241
241
|
end
|
242
242
|
|
243
|
-
# Autonomic Events WebSocket
|
243
|
+
# Autonomic Events WebSocket (Enterprise Only)
|
244
244
|
class AutonomicEventsWebSocketApi < CmdTlmWebSocketApi
|
245
245
|
def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
|
246
246
|
@identifier = {
|
@@ -251,7 +251,7 @@ module OpenC3
|
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
254
|
-
# Calendar Events WebSocket
|
254
|
+
# Calendar Events WebSocket (Enterprise Only)
|
255
255
|
class CalendarEventsWebSocketApi < CmdTlmWebSocketApi
|
256
256
|
def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
|
257
257
|
@identifier = {
|
@@ -355,7 +355,7 @@ module OpenC3
|
|
355
355
|
data_hash['items'] = items if items
|
356
356
|
data_hash['packets'] = packets if packets
|
357
357
|
data_hash['scope'] = scope
|
358
|
-
data_hash['token'] = @authentication.token
|
358
|
+
data_hash['token'] = @authentication.token(include_bearer: false)
|
359
359
|
write_action(data_hash)
|
360
360
|
end
|
361
361
|
|
@@ -384,7 +384,7 @@ module OpenC3
|
|
384
384
|
data_hash['items'] = items if items
|
385
385
|
data_hash['packets'] = packets if packets
|
386
386
|
data_hash['scope'] = scope
|
387
|
-
data_hash['token'] = @authentication.token
|
387
|
+
data_hash['token'] = @authentication.token(include_bearer: false)
|
388
388
|
write_action(data_hash)
|
389
389
|
end
|
390
390
|
|