openc3 5.14.0 → 5.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/openc3cli +19 -15
- data/bin/pipinstall +9 -0
- data/data/config/target_config.yaml +2 -1
- data/lib/openc3/config/config_parser.rb +12 -12
- data/lib/openc3/conversions/conversion.rb +4 -4
- data/lib/openc3/interfaces/interface.rb +25 -18
- data/lib/openc3/microservices/decom_microservice.rb +4 -2
- data/lib/openc3/microservices/interface_microservice.rb +27 -23
- data/lib/openc3/microservices/log_microservice.rb +6 -1
- data/lib/openc3/microservices/microservice.rb +28 -0
- data/lib/openc3/models/microservice_model.rb +5 -1
- data/lib/openc3/models/plugin_model.rb +11 -7
- data/lib/openc3/models/target_model.rb +36 -4
- data/lib/openc3/operators/microservice_operator.rb +23 -21
- data/lib/openc3/packets/commands.rb +4 -0
- data/lib/openc3/packets/limits_response.rb +1 -1
- data/lib/openc3/packets/packet_config.rb +78 -31
- data/lib/openc3/packets/packet_item.rb +3 -2
- data/lib/openc3/packets/packet_item_limits.rb +2 -1
- data/lib/openc3/packets/parsers/limits_response_parser.rb +21 -10
- data/lib/openc3/packets/parsers/processor_parser.rb +19 -10
- data/lib/openc3/packets/telemetry.rb +4 -0
- data/lib/openc3/system/system.rb +31 -1
- data/lib/openc3/system/system_config.rb +9 -10
- data/lib/openc3/system/target.rb +6 -6
- data/lib/openc3/utilities/cli_generator.rb +18 -3
- data/lib/openc3/utilities/python_proxy.rb +52 -0
- data/lib/openc3/version.rb +5 -5
- data/templates/conversion/conversion.py +1 -1
- data/templates/conversion/conversion.rb +1 -1
- data/templates/limits_response/response.py +2 -2
- data/templates/limits_response/response.rb +2 -2
- data/templates/microservice/microservices/TEMPLATE/microservice.py +6 -3
- data/templates/target/targets/TARGET/lib/target.py +2 -2
- data/templates/target/targets/TARGET/target.txt +2 -0
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_svelte/src/services/config-parser.js +5 -6
- data/templates/tool_svelte/src/services/openc3-api.js +9 -1
- data/templates/tool_vue/package.json +2 -2
- data/templates/widget/package.json +2 -2
- metadata +4 -2
@@ -869,6 +869,42 @@ module OpenC3
|
|
869
869
|
)
|
870
870
|
end
|
871
871
|
end
|
872
|
+
|
873
|
+
# Inform microservices of new topics
|
874
|
+
# Need to tell loggers to log, and decom to decom
|
875
|
+
# We do this for no downtime
|
876
|
+
raw_topics = []
|
877
|
+
decom_topics = []
|
878
|
+
packets.each do |packet|
|
879
|
+
if cmd_or_tlm == :TELEMETRY
|
880
|
+
raw_topics << "#{@scope}__TELEMETRY__{#{@name}}__#{packet.packet_name.upcase}"
|
881
|
+
decom_topics << "#{@scope}__DECOM__{#{@name}}__#{packet.packet_name.upcase}"
|
882
|
+
else
|
883
|
+
raw_topics << "#{@scope}__COMMAND__{#{@name}}__#{packet.packet_name.upcase}"
|
884
|
+
decom_topics << "#{@scope}__DECOMCMD__{#{@name}}__#{packet.packet_name.upcase}"
|
885
|
+
end
|
886
|
+
end
|
887
|
+
if cmd_or_tlm == :TELEMETRY
|
888
|
+
Topic.write_topic("MICROSERVICE__#{@scope}__PACKETLOG__#{@name}", {'command' => 'ADD_TOPICS', 'topics' => raw_topics.as_json.to_json})
|
889
|
+
add_topics_to_microservice("#{@scope}__PACKETLOG__#{@name}", raw_topics)
|
890
|
+
Topic.write_topic("MICROSERVICE__#{@scope}__DECOMLOG__#{@name}", {'command' => 'ADD_TOPICS', 'topics' => decom_topics.as_json.to_json})
|
891
|
+
add_topics_to_microservice("#{@scope}__DECOMLOG__#{@name}", decom_topics)
|
892
|
+
Topic.write_topic("MICROSERVICE__#{@scope}__DECOM__#{@name}", {'command' => 'ADD_TOPICS', 'topics' => raw_topics.as_json.to_json})
|
893
|
+
add_topics_to_microservice("#{@scope}__DECOM__#{@name}", raw_topics)
|
894
|
+
else
|
895
|
+
Topic.write_topic("MICROSERVICE__#{@scope}__COMMANDLOG__#{@name}", {'command' => 'ADD_TOPICS', 'topics' => raw_topics.as_json.to_json})
|
896
|
+
add_topics_to_microservice("#{@scope}__COMMANDLOG__#{@name}", raw_topics)
|
897
|
+
Topic.write_topic("MICROSERVICE__#{@scope}__DECOMCMDLOG__#{@name}", {'command' => 'ADD_TOPICS', 'topics' => decom_topics.as_json.to_json})
|
898
|
+
add_topics_to_microservice("#{@scope}__DECOMCMDLOG__#{@name}", decom_topics)
|
899
|
+
end
|
900
|
+
end
|
901
|
+
|
902
|
+
def add_topics_to_microservice(microservice_name, topics)
|
903
|
+
model = MicroserviceModel.get_model(name: microservice_name, scope: @scope)
|
904
|
+
model.topics.concat(topics)
|
905
|
+
model.topics.uniq!
|
906
|
+
model.ignore_changes = true # Don't restart the microservice right now
|
907
|
+
model.update
|
872
908
|
end
|
873
909
|
|
874
910
|
def deploy_commmandlog_microservice(gem_path, variables, topics, instance = nil, parent = nil)
|
@@ -1109,7 +1145,6 @@ module OpenC3
|
|
1109
1145
|
decom_command_topic_list = []
|
1110
1146
|
packet_topic_list = []
|
1111
1147
|
decom_topic_list = []
|
1112
|
-
reduced_topic_list = []
|
1113
1148
|
begin
|
1114
1149
|
system.commands.packets(@name).each do |packet_name, packet|
|
1115
1150
|
command_topic_list << "#{@scope}__COMMAND__{#{@name}}__#{packet_name}"
|
@@ -1122,9 +1157,6 @@ module OpenC3
|
|
1122
1157
|
system.telemetry.packets(@name).each do |packet_name, packet|
|
1123
1158
|
packet_topic_list << "#{@scope}__TELEMETRY__{#{@name}}__#{packet_name}"
|
1124
1159
|
decom_topic_list << "#{@scope}__DECOM__{#{@name}}__#{packet_name}"
|
1125
|
-
reduced_topic_list << "#{@scope}__REDUCED_MINUTE__{#{@name}}__#{packet_name}"
|
1126
|
-
reduced_topic_list << "#{@scope}__REDUCED_HOUR__{#{@name}}__#{packet_name}"
|
1127
|
-
reduced_topic_list << "#{@scope}__REDUCED_DAY__{#{@name}}__#{packet_name}"
|
1128
1160
|
end
|
1129
1161
|
rescue
|
1130
1162
|
# No telemetry packets for this target
|
@@ -98,28 +98,30 @@ module OpenC3
|
|
98
98
|
previous_parent = @previous_microservices[microservice_name]['parent']
|
99
99
|
if @previous_microservices[microservice_name] != microservice_config
|
100
100
|
# CHANGED
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
if parent
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
#
|
117
|
-
|
118
|
-
|
101
|
+
if not microservice_config['ignore_changes']
|
102
|
+
scope = microservice_name.split("__")[0]
|
103
|
+
Logger.info("Changed microservice detected: #{microservice_name}\nWas: #{@previous_microservices[microservice_name]}\nIs: #{microservice_config}", scope: scope)
|
104
|
+
if parent or previous_parent
|
105
|
+
if parent == previous_parent
|
106
|
+
# Same Parent - Respawn parent
|
107
|
+
@changed_microservices[parent] = @microservices[parent] if @microservices[parent] and @previous_microservices[parent]
|
108
|
+
elsif parent and previous_parent
|
109
|
+
# Parent changed - Respawn both parents
|
110
|
+
@changed_microservices[parent] = @microservices[parent] if @microservices[parent] and @previous_microservices[parent]
|
111
|
+
@changed_microservices[previous_parent] = @microservices[previous_parent] if @microservices[previous_parent] and @previous_microservices[previous_parent]
|
112
|
+
elsif parent
|
113
|
+
# Moved under a parent - Respawn parent and kill standalone
|
114
|
+
@changed_microservices[parent] = @microservices[parent] if @microservices[parent] and @previous_microservices[parent]
|
115
|
+
@removed_microservices[microservice_name] = microservice_config
|
116
|
+
else # previous_parent
|
117
|
+
# Moved to standalone - Respawn previous parent and make new
|
118
|
+
@changed_microservices[previous_parent] = @microservices[previous_parent] if @microservices[previous_parent] and @previous_microservices[previous_parent]
|
119
|
+
@new_microservices[microservice_name] = microservice_config
|
120
|
+
end
|
121
|
+
else
|
122
|
+
# Respawn regular microservice
|
123
|
+
@changed_microservices[microservice_name] = microservice_config
|
119
124
|
end
|
120
|
-
else
|
121
|
-
# Respawn regular microservice
|
122
|
-
@changed_microservices[microservice_name] = microservice_config
|
123
125
|
end
|
124
126
|
end
|
125
127
|
else
|
@@ -303,6 +303,10 @@ module OpenC3
|
|
303
303
|
@config.commands
|
304
304
|
end
|
305
305
|
|
306
|
+
def dynamic_add_packet(packet, affect_ids: false)
|
307
|
+
@config.dynamic_add_packet(packet, :COMMAND, affect_ids: affect_ids)
|
308
|
+
end
|
309
|
+
|
306
310
|
protected
|
307
311
|
|
308
312
|
def set_parameters(command, params, range_checking)
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
# This file implements a class to handle responses to limits state changes.
|
@@ -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
|
@@ -31,6 +31,7 @@ require 'openc3/packets/parsers/format_string_parser'
|
|
31
31
|
require 'openc3/packets/parsers/processor_parser'
|
32
32
|
require 'openc3/packets/parsers/xtce_parser'
|
33
33
|
require 'openc3/packets/parsers/xtce_converter'
|
34
|
+
require 'openc3/utilities/python_proxy'
|
34
35
|
require 'openc3/conversions'
|
35
36
|
require 'openc3/processors'
|
36
37
|
require 'nokogiri'
|
@@ -82,6 +83,9 @@ module OpenC3
|
|
82
83
|
# defined by that identification. Telemetry version
|
83
84
|
attr_reader :tlm_id_value_hash
|
84
85
|
|
86
|
+
# @return [String] Language of current target (ruby or python)
|
87
|
+
attr_reader :language
|
88
|
+
|
85
89
|
COMMAND = "Command"
|
86
90
|
TELEMETRY = "Telemetry"
|
87
91
|
|
@@ -117,7 +121,7 @@ module OpenC3
|
|
117
121
|
# @param filename [String] The name of the configuration file
|
118
122
|
# @param process_target_name [String] The target name. Pass nil when parsing
|
119
123
|
# an xtce file to automatically determine the target name.
|
120
|
-
def process_file(filename, process_target_name)
|
124
|
+
def process_file(filename, process_target_name, language = 'ruby')
|
121
125
|
# Handle .xtce files
|
122
126
|
extension = File.extname(filename).to_s.downcase
|
123
127
|
if extension == ".xtce" or extension == ".xml"
|
@@ -128,13 +132,14 @@ module OpenC3
|
|
128
132
|
# Partial files are included into another file and thus aren't directly processed
|
129
133
|
return if File.basename(filename)[0] == '_' # Partials start with underscore
|
130
134
|
|
135
|
+
@language = language
|
131
136
|
@converted_type = nil
|
132
137
|
@converted_bit_size = nil
|
133
138
|
@proc_text = ''
|
134
139
|
@building_generic_conversion = false
|
135
140
|
|
136
141
|
process_target_name = process_target_name.upcase
|
137
|
-
parser = ConfigParser.new("https://openc3.com/docs
|
142
|
+
parser = ConfigParser.new("https://docs.openc3.com/docs")
|
138
143
|
parser.instance_variable_set(:@target_name, process_target_name)
|
139
144
|
parser.parse_file(filename) do |keyword, params|
|
140
145
|
if @building_generic_conversion
|
@@ -258,7 +263,7 @@ module OpenC3
|
|
258
263
|
rescue
|
259
264
|
# Doesn't exist
|
260
265
|
end
|
261
|
-
packets.each do |
|
266
|
+
packets.each do |_packet_name, packet|
|
262
267
|
File.open(filename, 'a') do |file|
|
263
268
|
file.puts packet.to_config(:TELEMETRY)
|
264
269
|
file.puts ""
|
@@ -276,7 +281,7 @@ module OpenC3
|
|
276
281
|
rescue
|
277
282
|
# Doesn't exist
|
278
283
|
end
|
279
|
-
packets.each do |
|
284
|
+
packets.each do |_packet_name, packet|
|
280
285
|
File.open(filename, 'a') do |file|
|
281
286
|
file.puts packet.to_config(:COMMAND)
|
282
287
|
file.puts ""
|
@@ -315,30 +320,60 @@ module OpenC3
|
|
315
320
|
hash = @cmd_id_value_hash[@current_packet.target_name]
|
316
321
|
hash = {} unless hash
|
317
322
|
@cmd_id_value_hash[@current_packet.target_name] = hash
|
318
|
-
update_id_value_hash(hash)
|
323
|
+
update_id_value_hash(@current_packet, hash)
|
319
324
|
else
|
320
325
|
@telemetry[@current_packet.target_name][@current_packet.packet_name] = @current_packet
|
321
326
|
hash = @tlm_id_value_hash[@current_packet.target_name]
|
322
327
|
hash = {} unless hash
|
323
328
|
@tlm_id_value_hash[@current_packet.target_name] = hash
|
324
|
-
update_id_value_hash(hash)
|
329
|
+
update_id_value_hash(@current_packet, hash)
|
325
330
|
end
|
326
331
|
@current_packet = nil
|
327
332
|
@current_item = nil
|
328
333
|
end
|
329
334
|
end
|
330
335
|
|
336
|
+
def dynamic_add_packet(packet, cmd_or_tlm = :TELEMETRY, affect_ids: false)
|
337
|
+
if cmd_or_tlm == :COMMAND
|
338
|
+
@commands[packet.target_name][packet.packet_name] = packet
|
339
|
+
|
340
|
+
if affect_ids
|
341
|
+
hash = @cmd_id_value_hash[packet.target_name]
|
342
|
+
hash = {} unless hash
|
343
|
+
@cmd_id_value_hash[packet.target_name] = hash
|
344
|
+
update_id_value_hash(packet, hash)
|
345
|
+
end
|
346
|
+
else
|
347
|
+
@telemetry[packet.target_name][packet.packet_name] = packet
|
348
|
+
|
349
|
+
# Update latest_data lookup for telemetry
|
350
|
+
packet.sorted_items.each do |item|
|
351
|
+
target_latest_data = @latest_data[packet.target_name]
|
352
|
+
target_latest_data[item.name] ||= []
|
353
|
+
latest_data_packets = target_latest_data[item.name]
|
354
|
+
latest_data_packets << packet unless latest_data_packets.include?(packet)
|
355
|
+
end
|
356
|
+
|
357
|
+
if affect_ids
|
358
|
+
hash = @tlm_id_value_hash[packet.target_name]
|
359
|
+
hash = {} unless hash
|
360
|
+
@tlm_id_value_hash[packet.target_name] = hash
|
361
|
+
update_id_value_hash(packet, hash)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
331
366
|
protected
|
332
367
|
|
333
|
-
def update_id_value_hash(hash)
|
334
|
-
if
|
368
|
+
def update_id_value_hash(packet, hash)
|
369
|
+
if packet.id_items.length > 0
|
335
370
|
key = []
|
336
|
-
|
371
|
+
packet.id_items.each do |item|
|
337
372
|
key << item.id_value
|
338
373
|
end
|
339
|
-
hash[key] =
|
374
|
+
hash[key] = packet
|
340
375
|
else
|
341
|
-
hash['CATCHALL'.freeze] =
|
376
|
+
hash['CATCHALL'.freeze] = packet
|
342
377
|
end
|
343
378
|
end
|
344
379
|
|
@@ -394,7 +429,7 @@ module OpenC3
|
|
394
429
|
|
395
430
|
# Define a processor class that will be called once when a packet is received
|
396
431
|
when 'PROCESSOR'
|
397
|
-
ProcessorParser.parse(parser, @current_packet, @current_cmd_or_tlm)
|
432
|
+
ProcessorParser.parse(parser, @current_packet, @current_cmd_or_tlm, @language)
|
398
433
|
|
399
434
|
when 'DISABLE_MESSAGES'
|
400
435
|
usage = "#{keyword}"
|
@@ -433,18 +468,27 @@ module OpenC3
|
|
433
468
|
parser.verify_num_parameters(0, 0, usage)
|
434
469
|
@current_packet.hidden = true
|
435
470
|
@current_packet.disabled = true
|
471
|
+
|
436
472
|
when 'ACCESSOR'
|
437
473
|
usage = "#{keyword} <Accessor class name>"
|
438
474
|
parser.verify_num_parameters(1, nil, usage)
|
439
475
|
begin
|
440
|
-
|
441
|
-
|
442
|
-
|
476
|
+
if @language == 'ruby'
|
477
|
+
klass = OpenC3.require_class(params[0])
|
478
|
+
if params.length > 1
|
479
|
+
@current_packet.accessor = klass.new(@current_packet, *params[1..-1])
|
480
|
+
else
|
481
|
+
@current_packet.accessor = klass.new(@current_packet)
|
482
|
+
end
|
443
483
|
else
|
444
|
-
|
484
|
+
if params.length > 1
|
485
|
+
@current_packet.accessor = PythonProxy.new('Accessor', params[0], @current_packet, *params[1..-1])
|
486
|
+
else
|
487
|
+
@current_packet.accessor = PythonProxy.new('Accessor', params[0], @current_packet)
|
488
|
+
end
|
445
489
|
end
|
446
|
-
rescue Exception =>
|
447
|
-
raise parser.error(
|
490
|
+
rescue Exception => e
|
491
|
+
raise parser.error(e)
|
448
492
|
end
|
449
493
|
|
450
494
|
when 'TEMPLATE'
|
@@ -458,8 +502,8 @@ module OpenC3
|
|
458
502
|
|
459
503
|
begin
|
460
504
|
@current_packet.template = parser.read_file(params[0])
|
461
|
-
rescue Exception =>
|
462
|
-
raise parser.error(
|
505
|
+
rescue Exception => e
|
506
|
+
raise parser.error(e)
|
463
507
|
end
|
464
508
|
|
465
509
|
when 'RESPONSE'
|
@@ -500,16 +544,19 @@ module OpenC3
|
|
500
544
|
usage = "#{keyword} <conversion class filename> <custom parameters> ..."
|
501
545
|
parser.verify_num_parameters(1, nil, usage)
|
502
546
|
begin
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
547
|
+
if @language == 'ruby'
|
548
|
+
klass = OpenC3.require_class(params[0])
|
549
|
+
conversion = klass.new(*params[1..(params.length - 1)])
|
550
|
+
@current_item.public_send("#{keyword.downcase}=".to_sym, conversion)
|
551
|
+
if klass != ProcessorConversion and (conversion.converted_type.nil? or conversion.converted_bit_size.nil?)
|
552
|
+
msg = "Read Conversion #{params[0]} on item #{@current_item.name} does not specify converted type or bit size"
|
553
|
+
@warnings << msg
|
554
|
+
Logger.instance.warn @warnings[-1]
|
555
|
+
end
|
556
|
+
else
|
557
|
+
conversion = PythonProxy.new('Conversion', params[0], *params[1..(params.length - 1)])
|
558
|
+
@current_item.public_send("#{keyword.downcase}=".to_sym, conversion)
|
510
559
|
end
|
511
|
-
rescue Exception => err
|
512
|
-
raise parser.error(err)
|
513
560
|
end
|
514
561
|
|
515
562
|
# Apply a polynomial conversion to the current item
|
@@ -570,7 +617,7 @@ module OpenC3
|
|
570
617
|
# Define a response class that will be called when the limits state of the
|
571
618
|
# current item changes.
|
572
619
|
when 'LIMITS_RESPONSE'
|
573
|
-
LimitsResponseParser.parse(parser, @current_item, @current_cmd_or_tlm)
|
620
|
+
LimitsResponseParser.parse(parser, @current_item, @current_cmd_or_tlm, @language)
|
574
621
|
|
575
622
|
# Define a printf style formatting string for the current telemetry item
|
576
623
|
when 'FORMAT_STRING'
|
@@ -23,6 +23,7 @@
|
|
23
23
|
require 'openc3/packets/structure_item'
|
24
24
|
require 'openc3/packets/packet_item_limits'
|
25
25
|
require 'openc3/conversions/conversion'
|
26
|
+
require 'openc3/utilities/python_proxy'
|
26
27
|
require 'openc3/io/json_rpc' # Includes needed as_json code
|
27
28
|
|
28
29
|
module OpenC3
|
@@ -129,7 +130,7 @@ module OpenC3
|
|
129
130
|
|
130
131
|
def read_conversion=(read_conversion)
|
131
132
|
if read_conversion
|
132
|
-
raise ArgumentError, "#{@name}: read_conversion must be a OpenC3::Conversion but is a #{read_conversion.class}" unless OpenC3::Conversion === read_conversion
|
133
|
+
raise ArgumentError, "#{@name}: read_conversion must be a OpenC3::Conversion but is a #{read_conversion.class}" unless OpenC3::Conversion === read_conversion or OpenC3::PythonProxy === read_conversion
|
133
134
|
|
134
135
|
@read_conversion = read_conversion.clone
|
135
136
|
else
|
@@ -139,7 +140,7 @@ module OpenC3
|
|
139
140
|
|
140
141
|
def write_conversion=(write_conversion)
|
141
142
|
if write_conversion
|
142
|
-
raise ArgumentError, "#{@name}: write_conversion must be a OpenC3::Conversion but is a #{write_conversion.class}" unless OpenC3::Conversion === write_conversion
|
143
|
+
raise ArgumentError, "#{@name}: write_conversion must be a OpenC3::Conversion but is a #{write_conversion.class}" unless OpenC3::Conversion === write_conversion or OpenC3::PythonProxy === write_conversion
|
143
144
|
|
144
145
|
@write_conversion = write_conversion.clone
|
145
146
|
else
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/packets/limits_response'
|
24
|
+
require 'openc3/utilities/python_proxy'
|
24
25
|
|
25
26
|
module OpenC3
|
26
27
|
# Maintains knowledge of limits for a PacketItem
|
@@ -96,7 +97,7 @@ module OpenC3
|
|
96
97
|
|
97
98
|
def response=(response)
|
98
99
|
if response
|
99
|
-
raise ArgumentError, "response must be a OpenC3::LimitsResponse but is a #{response.class}" unless OpenC3::LimitsResponse === response
|
100
|
+
raise ArgumentError, "response must be a OpenC3::LimitsResponse but is a #{response.class}" unless OpenC3::LimitsResponse === response or OpenC3::PythonProxy === response
|
100
101
|
|
101
102
|
@response = response.clone
|
102
103
|
else
|
@@ -14,26 +14,29 @@
|
|
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
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
|
+
require 'openc3/utilities/python_proxy'
|
24
|
+
|
23
25
|
module OpenC3
|
24
26
|
class LimitsResponseParser
|
25
27
|
# @param parser [ConfigParser] Configuration parser
|
26
28
|
# @param item [Packet] The current item
|
27
29
|
# @param cmd_or_tlm [String] Whether this is a command or telemetry packet
|
28
|
-
def self.parse(parser, item, cmd_or_tlm)
|
29
|
-
parser = LimitsResponseParser.new(parser)
|
30
|
+
def self.parse(parser, item, cmd_or_tlm, language = 'ruby')
|
31
|
+
parser = LimitsResponseParser.new(parser, language)
|
30
32
|
parser.verify_parameters(cmd_or_tlm)
|
31
33
|
parser.create_limits_response(item)
|
32
34
|
end
|
33
35
|
|
34
36
|
# @param parser [ConfigParser] Configuration parser
|
35
|
-
def initialize(parser)
|
37
|
+
def initialize(parser, language = 'ruby')
|
36
38
|
@parser = parser
|
39
|
+
@language = language
|
37
40
|
end
|
38
41
|
|
39
42
|
# @param cmd_or_tlm [String] Whether this is a command or telemetry packet
|
@@ -48,15 +51,23 @@ module OpenC3
|
|
48
51
|
|
49
52
|
# @param item [PacketItem] The item the limits response should be added to
|
50
53
|
def create_limits_response(item)
|
51
|
-
|
54
|
+
if @language == 'ruby'
|
55
|
+
klass = OpenC3.require_class(@parser.parameters[0])
|
52
56
|
|
53
|
-
|
54
|
-
|
57
|
+
if @parser.parameters[1]
|
58
|
+
item.limits.response = klass.new(*@parser.parameters[1..(@parser.parameters.length - 1)])
|
59
|
+
else
|
60
|
+
item.limits.response = klass.new
|
61
|
+
end
|
55
62
|
else
|
56
|
-
|
63
|
+
if @parser.parameters[1]
|
64
|
+
item.limits.response = PythonProxy.new('LimitsResponse', @parser.parameters[0], *@parser.parameters[1..(@parser.parameters.length - 1)])
|
65
|
+
else
|
66
|
+
item.limits.response = PythonProxy.new('LimitsResponse', @parser.parameters[0], [])
|
67
|
+
end
|
57
68
|
end
|
58
|
-
rescue Exception =>
|
59
|
-
raise @parser.error(
|
69
|
+
rescue Exception => e
|
70
|
+
raise @parser.error(e, @usage)
|
60
71
|
end
|
61
72
|
end
|
62
73
|
end
|
@@ -21,21 +21,23 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/processors'
|
24
|
+
require 'openc3/utilities/python_proxy'
|
24
25
|
|
25
26
|
module OpenC3
|
26
27
|
class ProcessorParser
|
27
28
|
# @param parser [ConfigParser] Configuration parser
|
28
29
|
# @param packet [Packet] The current packet
|
29
30
|
# @param cmd_or_tlm [String] Whether this is a command or telemetry packet
|
30
|
-
def self.parse(parser, packet, cmd_or_tlm)
|
31
|
-
parser = ProcessorParser.new(parser)
|
31
|
+
def self.parse(parser, packet, cmd_or_tlm, language = 'ruby')
|
32
|
+
parser = ProcessorParser.new(parser, language)
|
32
33
|
parser.verify_parameters(cmd_or_tlm)
|
33
34
|
parser.create_processor(packet)
|
34
35
|
end
|
35
36
|
|
36
37
|
# @param parser [ConfigParser] Configuration parser
|
37
|
-
def initialize(parser)
|
38
|
+
def initialize(parser, language = 'ruby')
|
38
39
|
@parser = parser
|
40
|
+
@language = language
|
39
41
|
end
|
40
42
|
|
41
43
|
# @param cmd_or_tlm [String] Whether this is a command or telemetry packet
|
@@ -50,16 +52,23 @@ module OpenC3
|
|
50
52
|
|
51
53
|
# @param packet [Packet] The packet the processor should be added to
|
52
54
|
def create_processor(packet)
|
53
|
-
|
54
|
-
|
55
|
+
if @language == 'ruby'
|
56
|
+
# require should be performed in target.txt
|
57
|
+
klass = OpenC3.require_class(@parser.parameters[1])
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
if @parser.parameters[2]
|
60
|
+
processor = klass.new(*@parser.parameters[2..(@parser.parameters.length - 1)])
|
61
|
+
else
|
62
|
+
processor = klass.new
|
63
|
+
end
|
64
|
+
raise ArgumentError, "processor must be a OpenC3::Processor but is a #{processor.class}" unless OpenC3::Processor === processor
|
58
65
|
else
|
59
|
-
|
66
|
+
if @parser.parameters[2]
|
67
|
+
processor = PythonProxy.new('Processor', @parser.parameters[1], *@parser.parameters[2..(@parser.parameters.length - 1)])
|
68
|
+
else
|
69
|
+
processor = PythonProxy.new('Processor', @parser.parameters[1], [])
|
70
|
+
end
|
60
71
|
end
|
61
|
-
raise ArgumentError, "processor must be a OpenC3::Processor but is a #{processor.class}" unless OpenC3::Processor === processor
|
62
|
-
|
63
72
|
processor.name = get_processor_name()
|
64
73
|
packet.processors[processor.name] = processor
|
65
74
|
rescue Exception => err
|
data/lib/openc3/system/system.rb
CHANGED
@@ -60,6 +60,9 @@ module OpenC3
|
|
60
60
|
# The current limits set
|
61
61
|
@@limits_set = nil
|
62
62
|
|
63
|
+
# Callbacks to call once @@instance is created
|
64
|
+
@@post_instance_callbacks = []
|
65
|
+
|
63
66
|
# @return [Symbol] The current limits_set of the system returned from Redis
|
64
67
|
def self.limits_set
|
65
68
|
unless @@limits_set
|
@@ -72,6 +75,14 @@ module OpenC3
|
|
72
75
|
@@limits_set = value.to_s.intern
|
73
76
|
end
|
74
77
|
|
78
|
+
def self.add_post_instance_callback(callback)
|
79
|
+
if @@instance
|
80
|
+
callback.call()
|
81
|
+
else
|
82
|
+
@@post_instance_callbacks << callback
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
75
86
|
def self.setup_targets(target_names, base_dir, scope:)
|
76
87
|
# Nothing to do if there are no targets
|
77
88
|
return if target_names.nil? or target_names.length == 0
|
@@ -121,11 +132,30 @@ module OpenC3
|
|
121
132
|
raise "System.instance parameters are required on first call" unless target_names and target_config_dir
|
122
133
|
|
123
134
|
@@instance_mutex.synchronize do
|
135
|
+
return @@instance if @@instance
|
124
136
|
@@instance ||= self.new(target_names, target_config_dir)
|
137
|
+
@@post_instance_callbacks.each do |callback|
|
138
|
+
callback.call
|
139
|
+
end
|
125
140
|
return @@instance
|
126
141
|
end
|
127
142
|
end
|
128
143
|
|
144
|
+
# Dynamically add packets to the system instance
|
145
|
+
#
|
146
|
+
# @param dynamic_packets [Array of packets]
|
147
|
+
# @param cmd_or_tlm [Symbol] :COMMAND or :TELEMETRY
|
148
|
+
# @param affect_ids [Boolean] Whether to affect packet id lookup or not
|
149
|
+
def self.dynamic_update(dynamic_packets, cmd_or_tlm = :TELEMETRY, affect_ids: false)
|
150
|
+
dynamic_packets.each do |packet|
|
151
|
+
if cmd_or_tlm == :TELEMETRY
|
152
|
+
@@instance.telemetry.dynamic_add_packet(packet, affect_ids: affect_ids)
|
153
|
+
else
|
154
|
+
@@instance.commands.dynamic_add_packet(packet, affect_ids: affect_ids)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
129
159
|
# Create a new System object.
|
130
160
|
#
|
131
161
|
# @param target_names [Array of target names]
|
@@ -149,7 +179,7 @@ module OpenC3
|
|
149
179
|
@targets[target.name] = target
|
150
180
|
errors = [] # Store all errors processing the cmd_tlm files
|
151
181
|
target.cmd_tlm_files.each do |cmd_tlm_file|
|
152
|
-
@packet_config.process_file(cmd_tlm_file, target.name)
|
182
|
+
@packet_config.process_file(cmd_tlm_file, target.name, target.language)
|
153
183
|
rescue Exception => error
|
154
184
|
errors << "Error processing #{cmd_tlm_file}:\n#{error.message}"
|
155
185
|
end
|