openc3 5.14.0 → 5.14.2
Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0eaf09072832c752cd1c0ae08160f9a5ef5bb24e585f10ee8be31d22c54ce2e7
|
4
|
+
data.tar.gz: 17fbccdaf92dd9c6e7fae704ca4bacadef88b026c5023d7dbb69583a19f6fe3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92e1bfa1bbd283c4e94d49627ea8bfe6be9423ff88bc1a5453af778fb10dc3cefd78b2cef6b553fa6d1aa6f21559e70413e5343ec546b93841c62c124a3840a1
|
7
|
+
data.tar.gz: ac243f0b29ee7cccd5c809c5625a084cb54a3920b283402ddc7da8ce4178816d9ce75d44cb8af8154438a846ff116dec41b27cd5623ef5ded506c0c2d320e590
|
data/bin/openc3cli
CHANGED
@@ -50,9 +50,9 @@ $redis_url = "redis://#{ENV['OPENC3_REDIS_HOSTNAME']}:#{ENV['OPENC3_REDIS_PORT']
|
|
50
50
|
# Build the OpenStruct and OptionParser here as constants so we can use in methods
|
51
51
|
MIGRATE_OPTIONS = OpenStruct.new
|
52
52
|
MIGRATE_OPTIONS.all = false
|
53
|
-
MIGRATE_PARSER = OptionParser.new do |
|
54
|
-
|
55
|
-
|
53
|
+
MIGRATE_PARSER = OptionParser.new do |opts|
|
54
|
+
opts.banner = "cli migrate PLUGIN [TGT1...] # Create a OpenC3 plugin from existing COSMOS 4 targets"
|
55
|
+
opts.on("-a", "--all", " Move all COSMOS 4 targets into a single OpenC3 plugin") do
|
56
56
|
MIGRATE_OPTIONS.all = true
|
57
57
|
end
|
58
58
|
end
|
@@ -67,7 +67,7 @@ def print_usage
|
|
67
67
|
puts " cli validate /PATH/FILENAME.gem SCOPE variables.txt # Validate a COSMOS plugin gem file"
|
68
68
|
puts " cli load /PATH/FILENAME.gem SCOPE variables.txt # Loads a COSMOS plugin gem file"
|
69
69
|
puts " cli generate TYPE OPTIONS # Generate various COSMOS entities"
|
70
|
-
puts " OPTIONS
|
70
|
+
puts " OPTIONS: --ruby or --python to specify the language in the generated code"
|
71
71
|
puts " #{MIGRATE_PARSER}"
|
72
72
|
puts " cli bridge CONFIG_FILENAME # Run COSMOS host bridge"
|
73
73
|
puts " cli bridgegem gem_name variable1=value1 variable2=value2 # Runs bridge using gem bridge.txt"
|
@@ -208,31 +208,31 @@ end
|
|
208
208
|
|
209
209
|
def xtce_converter(args)
|
210
210
|
options = {}
|
211
|
-
option_parser = OptionParser.new do |
|
212
|
-
|
211
|
+
option_parser = OptionParser.new do |opts|
|
212
|
+
opts.banner = "Usage: xtce_converter [options] --import input_xtce_filename --output output_dir\n"+
|
213
213
|
" xtce_converter [options] --plugin /PATH/FILENAME.gem --output output_dir --variables variables.txt"
|
214
|
-
|
215
|
-
|
216
|
-
puts
|
214
|
+
opts.separator("")
|
215
|
+
opts.on("-h", "--help", "Show this message") do
|
216
|
+
puts opts
|
217
217
|
exit
|
218
218
|
end
|
219
|
-
|
219
|
+
opts.on("-i VALUE", "--import VALUE", "Import the specified .xtce file") do |arg|
|
220
220
|
options[:import] = arg
|
221
221
|
end
|
222
|
-
|
222
|
+
opts.on("-o", "--output DIRECTORY", "Create files in the directory") do |arg|
|
223
223
|
options[:output] = arg
|
224
224
|
end
|
225
|
-
|
225
|
+
opts.on("-p", "--plugin PLUGIN", "Export .xtce file(s) from the plugin") do |arg|
|
226
226
|
options[:plugin] = arg
|
227
227
|
end
|
228
|
-
|
228
|
+
opts.on("-v", "--variables", "Optional variables file to pass to the plugin") do |arg|
|
229
229
|
options[:variables] = arg
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
233
233
|
begin
|
234
234
|
option_parser.parse!(args)
|
235
|
-
rescue
|
235
|
+
rescue
|
236
236
|
abort(option_parser.to_s)
|
237
237
|
end
|
238
238
|
|
@@ -641,7 +641,11 @@ if not ARGV[0].nil? # argument(s) given
|
|
641
641
|
IRB.start
|
642
642
|
|
643
643
|
when 'rake'
|
644
|
-
|
644
|
+
if File.exist?('Rakefile')
|
645
|
+
puts `rake #{ARGV[1..-1].join(' ')}`
|
646
|
+
else
|
647
|
+
puts "No Rakefile found! Only run 'rake' in the presense of a Rakefile which is typically at the root of your COSMOS project."
|
648
|
+
end
|
645
649
|
|
646
650
|
when 'validate'
|
647
651
|
validate_plugin(ARGV[1], scope: ARGV[2], variables_file: ARGV[3])
|
data/bin/pipinstall
ADDED
@@ -13,7 +13,8 @@ LANGUAGE:
|
|
13
13
|
since: 5.11.1
|
14
14
|
REQUIRE:
|
15
15
|
summary: Requires a Ruby file
|
16
|
-
description: Ruby files
|
16
|
+
description: List the Ruby files required to explicitly declare dependencies.
|
17
|
+
This is now completely optional.
|
17
18
|
example: REQUIRE limits_response.rb
|
18
19
|
parameters:
|
19
20
|
- name: Filename
|
@@ -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
|
@@ -143,7 +143,7 @@ module OpenC3
|
|
143
143
|
end
|
144
144
|
|
145
145
|
# @param url [String] The url to link to in error messages
|
146
|
-
def initialize(url = "https
|
146
|
+
def initialize(url = "https://docs.openc3.com/docs")
|
147
147
|
@url = url
|
148
148
|
end
|
149
149
|
|
@@ -199,7 +199,7 @@ module OpenC3
|
|
199
199
|
remove_quotes = true,
|
200
200
|
run_erb = true,
|
201
201
|
variables = {},
|
202
|
-
&
|
202
|
+
&)
|
203
203
|
raise Error.new(self, "Configuration file #{filename} does not exist.") unless filename && File.exist?(filename)
|
204
204
|
|
205
205
|
@filename = filename
|
@@ -219,7 +219,7 @@ module OpenC3
|
|
219
219
|
remove_quotes,
|
220
220
|
size,
|
221
221
|
PARSING_REGEX,
|
222
|
-
&
|
222
|
+
&)
|
223
223
|
ensure
|
224
224
|
file.close unless file.closed?
|
225
225
|
end
|
@@ -267,7 +267,7 @@ module OpenC3
|
|
267
267
|
end
|
268
268
|
end
|
269
269
|
|
270
|
-
# Converts a String containing '', 'NIL' or '
|
270
|
+
# Converts a String containing '', 'NIL', 'NULL', or 'NONE' to nil Ruby primitive.
|
271
271
|
# All other arguments are simply returned.
|
272
272
|
#
|
273
273
|
# @param value [Object]
|
@@ -275,7 +275,7 @@ module OpenC3
|
|
275
275
|
def self.handle_nil(value)
|
276
276
|
if String === value
|
277
277
|
case value.upcase
|
278
|
-
when '', 'NIL', 'NULL'
|
278
|
+
when '', 'NIL', 'NULL', 'NONE'
|
279
279
|
return nil
|
280
280
|
end
|
281
281
|
end
|
@@ -421,12 +421,12 @@ module OpenC3
|
|
421
421
|
if type == 'MIN'
|
422
422
|
value = -2**(bit_size - 1)
|
423
423
|
else # 'MAX'
|
424
|
-
value = 2**(bit_size - 1) - 1
|
424
|
+
value = (2**(bit_size - 1)) - 1
|
425
425
|
end
|
426
426
|
when :UINT
|
427
427
|
# Default is 0 for 'MIN'
|
428
428
|
if type == 'MAX'
|
429
|
-
value = 2**bit_size - 1
|
429
|
+
value = (2**bit_size) - 1
|
430
430
|
end
|
431
431
|
when :FLOAT
|
432
432
|
case bit_size
|
@@ -536,8 +536,8 @@ module OpenC3
|
|
536
536
|
if yield_non_keyword_lines
|
537
537
|
begin
|
538
538
|
yield(@keyword, @parameters)
|
539
|
-
rescue =>
|
540
|
-
errors <<
|
539
|
+
rescue => e
|
540
|
+
errors << e
|
541
541
|
end
|
542
542
|
end
|
543
543
|
@line = ''
|
@@ -569,8 +569,8 @@ module OpenC3
|
|
569
569
|
|
570
570
|
begin
|
571
571
|
yield(@keyword, @parameters)
|
572
|
-
rescue =>
|
573
|
-
errors <<
|
572
|
+
rescue => e
|
573
|
+
errors << e
|
574
574
|
end
|
575
575
|
@line = ''
|
576
576
|
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 2024, 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
|
module OpenC3
|
@@ -46,7 +46,7 @@ module OpenC3
|
|
46
46
|
# conversion.
|
47
47
|
# @param buffer [String] The packet buffer
|
48
48
|
# @return The converted value
|
49
|
-
def call(
|
49
|
+
def call(_value, _packet, _buffer)
|
50
50
|
raise "call method must be defined by subclass"
|
51
51
|
end
|
52
52
|
|
@@ -61,7 +61,7 @@ module OpenC3
|
|
61
61
|
" #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename}\n"
|
62
62
|
end
|
63
63
|
|
64
|
-
def as_json(*
|
64
|
+
def as_json(*_a)
|
65
65
|
result = {}
|
66
66
|
result['class'] = self.class.name.to_s
|
67
67
|
result['converted_type'] = @converted_type if @converted_type
|
@@ -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
|
@@ -205,8 +205,8 @@ module OpenC3
|
|
205
205
|
else
|
206
206
|
cmd(cmd_string)
|
207
207
|
end
|
208
|
-
rescue Exception =>
|
209
|
-
Logger.error("Error sending periodic cmd(#{cmd_string}):\n#{
|
208
|
+
rescue Exception => e
|
209
|
+
Logger.error("Error sending periodic cmd(#{cmd_string}):\n#{e.formatted}")
|
210
210
|
end
|
211
211
|
end
|
212
212
|
end
|
@@ -238,7 +238,7 @@ module OpenC3
|
|
238
238
|
raise "read_interface not defined by Interface"
|
239
239
|
end
|
240
240
|
|
241
|
-
def write_interface(
|
241
|
+
def write_interface(_data, _extra = nil)
|
242
242
|
raise "write_interface not defined by Interface"
|
243
243
|
end
|
244
244
|
|
@@ -305,10 +305,10 @@ module OpenC3
|
|
305
305
|
Logger.warn("#{@name}: Interface unexpectedly requested disconnect") unless packet
|
306
306
|
return packet
|
307
307
|
end
|
308
|
-
rescue Exception =>
|
308
|
+
rescue Exception => e
|
309
309
|
Logger.error("#{@name}: Error reading from interface")
|
310
310
|
disconnect()
|
311
|
-
raise
|
311
|
+
raise e
|
312
312
|
end
|
313
313
|
|
314
314
|
# Method to send a packet on the interface.
|
@@ -395,16 +395,16 @@ module OpenC3
|
|
395
395
|
else
|
396
396
|
@write_mutex.synchronize { yield }
|
397
397
|
end
|
398
|
-
rescue WriteRejectError =>
|
399
|
-
Logger.error("#{@name}: Write rejected by interface: #{
|
400
|
-
raise
|
401
|
-
rescue Exception =>
|
398
|
+
rescue WriteRejectError => e
|
399
|
+
Logger.error("#{@name}: Write rejected by interface: #{e.message}")
|
400
|
+
raise e
|
401
|
+
rescue Exception => e
|
402
402
|
Logger.error("#{@name}: Error writing to interface")
|
403
403
|
disconnect()
|
404
|
-
raise
|
404
|
+
raise e
|
405
405
|
end
|
406
406
|
|
407
|
-
def as_json(*
|
407
|
+
def as_json(*_a)
|
408
408
|
config = {}
|
409
409
|
config['name'] = @name
|
410
410
|
config['state'] = @state
|
@@ -528,7 +528,7 @@ module OpenC3
|
|
528
528
|
# method is called. Subclasses must implement this method.
|
529
529
|
#
|
530
530
|
# @return [String] Raw packet data
|
531
|
-
def read_interface_base(data,
|
531
|
+
def read_interface_base(data, _extra = nil)
|
532
532
|
@read_raw_data_time = Time.now
|
533
533
|
@read_raw_data = data.clone
|
534
534
|
@bytes_read += data.length
|
@@ -541,7 +541,7 @@ module OpenC3
|
|
541
541
|
#
|
542
542
|
# @param data [String] Raw packet data
|
543
543
|
# @return [String] The exact data written
|
544
|
-
def write_interface_base(data,
|
544
|
+
def write_interface_base(data, _extra = nil)
|
545
545
|
@written_raw_data_time = Time.now
|
546
546
|
@written_raw_data = data.clone
|
547
547
|
@bytes_written += data.length
|
@@ -567,9 +567,16 @@ module OpenC3
|
|
567
567
|
return protocol
|
568
568
|
end
|
569
569
|
|
570
|
-
def interface_cmd(cmd_name, *
|
571
|
-
|
572
|
-
|
570
|
+
def interface_cmd(cmd_name, *_cmd_args)
|
571
|
+
case cmd_name
|
572
|
+
when 'clear_counters'
|
573
|
+
@write_queue_size = 0
|
574
|
+
@read_queue_size = 0
|
575
|
+
@bytes_written = 0
|
576
|
+
@bytes_read = 0
|
577
|
+
@write_count = 0
|
578
|
+
@read_count = 0
|
579
|
+
end
|
573
580
|
end
|
574
581
|
|
575
582
|
def protocol_cmd(cmd_name, *cmd_args, read_write: :READ_WRITE, index: -1)
|
@@ -584,7 +591,7 @@ module OpenC3
|
|
584
591
|
write_protocols = @write_protocols.reverse
|
585
592
|
read_index = 0
|
586
593
|
write_index = 0
|
587
|
-
@protocol_info.each do |
|
594
|
+
@protocol_info.each do |_protocol_class, _protocol_args, protocol_read_write|
|
588
595
|
case protocol_read_write
|
589
596
|
when :READ
|
590
597
|
protocols << read_protocols[read_index]
|
@@ -45,6 +45,7 @@ module OpenC3
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def run
|
48
|
+
setup_microservice_topic()
|
48
49
|
while true
|
49
50
|
break if @cancel_thread
|
50
51
|
|
@@ -52,8 +53,9 @@ module OpenC3
|
|
52
53
|
OpenC3.in_span("read_topics") do
|
53
54
|
Topic.read_topics(@topics) do |topic, msg_id, msg_hash, redis|
|
54
55
|
break if @cancel_thread
|
55
|
-
|
56
|
-
|
56
|
+
if topic == @microservice_topic
|
57
|
+
microservice_cmd(topic, msg_id, msg_hash, redis)
|
58
|
+
elsif topic =~ /__DECOMINTERFACE/
|
57
59
|
if msg_hash.key?('inject_tlm')
|
58
60
|
handle_inject_tlm(msg_hash['inject_tlm'])
|
59
61
|
next
|
@@ -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
|
@@ -52,9 +52,9 @@ module OpenC3
|
|
52
52
|
def start
|
53
53
|
@thread = Thread.new do
|
54
54
|
run()
|
55
|
-
rescue Exception =>
|
56
|
-
@logger.error "#{@interface.name}: Command handler thread died: #{
|
57
|
-
raise
|
55
|
+
rescue Exception => e
|
56
|
+
@logger.error "#{@interface.name}: Command handler thread died: #{e.formatted}"
|
57
|
+
raise e
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -67,7 +67,7 @@ module OpenC3
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def run
|
70
|
-
InterfaceTopic.receive_commands(@interface, scope: @scope) do |topic, msg_id, msg_hash,
|
70
|
+
InterfaceTopic.receive_commands(@interface, scope: @scope) do |topic, msg_id, msg_hash, _redis|
|
71
71
|
OpenC3.with_context(msg_hash) do
|
72
72
|
msgid_seconds_from_epoch = msg_id.split('-')[0].to_i / 1000.0
|
73
73
|
delta = Time.now.to_f - msgid_seconds_from_epoch
|
@@ -126,6 +126,7 @@ module OpenC3
|
|
126
126
|
begin
|
127
127
|
@logger.info "#{@interface.name}: interface_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
128
128
|
@interface.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
129
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
129
130
|
rescue => e
|
130
131
|
@logger.error "#{@interface.name}: interface_cmd: #{e.formatted}"
|
131
132
|
next e.message
|
@@ -137,6 +138,7 @@ module OpenC3
|
|
137
138
|
begin
|
138
139
|
@logger.info "#{@interface.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
139
140
|
@interface.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
141
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
140
142
|
rescue => e
|
141
143
|
@logger.error "#{@interface.name}: protocol_cmd: #{e.formatted}"
|
142
144
|
next e.message
|
@@ -241,9 +243,9 @@ module OpenC3
|
|
241
243
|
def start
|
242
244
|
@thread = Thread.new do
|
243
245
|
run()
|
244
|
-
rescue Exception =>
|
245
|
-
@logger.error "#{@router.name}: Telemetry handler thread died: #{
|
246
|
-
raise
|
246
|
+
rescue Exception => e
|
247
|
+
@logger.error "#{@router.name}: Telemetry handler thread died: #{e.formatted}"
|
248
|
+
raise e
|
247
249
|
end
|
248
250
|
end
|
249
251
|
|
@@ -256,7 +258,7 @@ module OpenC3
|
|
256
258
|
end
|
257
259
|
|
258
260
|
def run
|
259
|
-
RouterTopic.receive_telemetry(@router, scope: @scope) do |topic, msg_id, msg_hash,
|
261
|
+
RouterTopic.receive_telemetry(@router, scope: @scope) do |topic, msg_id, msg_hash, _redis|
|
260
262
|
msgid_seconds_from_epoch = msg_id.split('-')[0].to_i / 1000.0
|
261
263
|
delta = Time.now.to_f - msgid_seconds_from_epoch
|
262
264
|
@metric.set(name: 'router_topic_delta_seconds', value: delta, type: 'gauge', unit: 'seconds', help: 'Delta time between data written to stream and router tlm start') if @metric
|
@@ -296,6 +298,7 @@ module OpenC3
|
|
296
298
|
begin
|
297
299
|
@logger.info "#{@router.name}: router_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
298
300
|
@router.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
301
|
+
RouterStatusModel.set(@router.as_json(:allow_nan => true), scope: @scope)
|
299
302
|
rescue => e
|
300
303
|
@logger.error "#{@router.name}: router_cmd: #{e.formatted}"
|
301
304
|
next e.message
|
@@ -307,6 +310,7 @@ module OpenC3
|
|
307
310
|
begin
|
308
311
|
@logger.info "#{@router.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
309
312
|
@router.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
313
|
+
RouterStatusModel.set(@router.as_json(:allow_nan => true), scope: @scope)
|
310
314
|
rescue => e
|
311
315
|
@logger.error "#{@router.name}: protoco_cmd: #{e.formatted}"
|
312
316
|
next e.message
|
@@ -434,9 +438,9 @@ module OpenC3
|
|
434
438
|
end
|
435
439
|
@interface # Return the interface/router since we may have recreated it
|
436
440
|
# Need to rescue Exception so we cover LoadError
|
437
|
-
rescue Exception =>
|
438
|
-
@logger.error("Attempting connection failed with params #{params} due to #{
|
439
|
-
if SignalException ===
|
441
|
+
rescue Exception => e
|
442
|
+
@logger.error("Attempting connection failed with params #{params} due to #{e.message}")
|
443
|
+
if SignalException === e
|
440
444
|
@logger.info "#{@interface.name}: Closing from signal"
|
441
445
|
@cancel_thread = true
|
442
446
|
end
|
@@ -463,8 +467,8 @@ module OpenC3
|
|
463
467
|
# We need to make sure connect is not called after stop() has been called
|
464
468
|
connect() unless @cancel_thread
|
465
469
|
end
|
466
|
-
rescue Exception =>
|
467
|
-
handle_connection_failed(
|
470
|
+
rescue Exception => e
|
471
|
+
handle_connection_failed(e)
|
468
472
|
break if @cancel_thread
|
469
473
|
end
|
470
474
|
when 'CONNECTED'
|
@@ -484,8 +488,8 @@ module OpenC3
|
|
484
488
|
handle_connection_lost()
|
485
489
|
break if @cancel_thread
|
486
490
|
end
|
487
|
-
rescue Exception =>
|
488
|
-
handle_connection_lost(
|
491
|
+
rescue Exception => e
|
492
|
+
handle_connection_lost(e)
|
489
493
|
break if @cancel_thread
|
490
494
|
end
|
491
495
|
else
|
@@ -494,10 +498,10 @@ module OpenC3
|
|
494
498
|
end
|
495
499
|
end
|
496
500
|
end
|
497
|
-
rescue Exception =>
|
498
|
-
unless SystemExit ===
|
499
|
-
@logger.error "#{@interface.name}: Packet reading thread died: #{
|
500
|
-
OpenC3.handle_fatal_exception(
|
501
|
+
rescue Exception => e
|
502
|
+
unless SystemExit === e or SignalException === e
|
503
|
+
@logger.error "#{@interface.name}: Packet reading thread died: #{e.formatted}"
|
504
|
+
OpenC3.handle_fatal_exception(e)
|
501
505
|
end
|
502
506
|
# Try to do clean disconnect because we're going down
|
503
507
|
disconnect(false)
|
@@ -615,13 +619,13 @@ module OpenC3
|
|
615
619
|
@logger.info "#{@interface.name}: Connecting ..."
|
616
620
|
begin
|
617
621
|
@interface.connect
|
618
|
-
rescue Exception =>
|
622
|
+
rescue Exception => e
|
619
623
|
begin
|
620
624
|
@interface.disconnect # Ensure disconnect is called at least once on a partial connect
|
621
625
|
rescue Exception
|
622
626
|
# We want to report any connect errors, not disconnect in this case
|
623
627
|
end
|
624
|
-
raise
|
628
|
+
raise e
|
625
629
|
end
|
626
630
|
@interface.state = 'CONNECTED'
|
627
631
|
if @interface_or_router == 'INTERFACE'
|
@@ -685,7 +689,7 @@ module OpenC3
|
|
685
689
|
end
|
686
690
|
end
|
687
691
|
|
688
|
-
def shutdown(
|
692
|
+
def shutdown(_sig = nil)
|
689
693
|
@logger.info "#{@interface ? @interface.name : @name}: shutdown requested"
|
690
694
|
stop()
|
691
695
|
super()
|
@@ -62,12 +62,17 @@ module OpenC3
|
|
62
62
|
|
63
63
|
def run
|
64
64
|
setup_plws()
|
65
|
+
setup_microservice_topic()
|
65
66
|
while true
|
66
67
|
break if @cancel_thread
|
67
68
|
|
68
69
|
Topic.read_topics(@topics) do |topic, msg_id, msg_hash, redis|
|
69
70
|
break if @cancel_thread
|
70
|
-
|
71
|
+
if topic == @microservice_topic
|
72
|
+
microservice_cmd(topic, msg_id, msg_hash, redis)
|
73
|
+
else
|
74
|
+
log_data(topic, msg_id, msg_hash, redis)
|
75
|
+
end
|
71
76
|
@count += 1
|
72
77
|
@metric.set(name: 'log_total', value: @count, type: 'counter')
|
73
78
|
end
|
@@ -116,6 +116,7 @@ module OpenC3
|
|
116
116
|
end
|
117
117
|
@logger.info("Microservice initialized with config:\n#{@config}")
|
118
118
|
@topics ||= []
|
119
|
+
@microservice_topic = "MICROSERVICE__#{@name}"
|
119
120
|
|
120
121
|
# Get configuration for any targets
|
121
122
|
@target_names = @config["target_names"]
|
@@ -210,5 +211,32 @@ module OpenC3
|
|
210
211
|
@logger.info("Shutting down microservice complete: #{@name}")
|
211
212
|
@shutdown_complete = true
|
212
213
|
end
|
214
|
+
|
215
|
+
def setup_microservice_topic
|
216
|
+
@topics.append(@microservice_topic)
|
217
|
+
Thread.current[:topic_offsets] ||= {}
|
218
|
+
topic_offsets = Thread.current[:topic_offsets]
|
219
|
+
topic_offsets[@microservice_topic] = "0-0" # Always get all available
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns if the command was handled
|
223
|
+
def microservice_cmd(topic, msg_id, msg_hash, redis)
|
224
|
+
command = msg_hash['command']
|
225
|
+
case command
|
226
|
+
when 'ADD_TOPICS'
|
227
|
+
topics = JSON.parse(msg_hash['topics'])
|
228
|
+
if topics and Array === topics
|
229
|
+
topics.each do |new_topic|
|
230
|
+
@topics << new_topic unless @topics.include?(new_topic)
|
231
|
+
end
|
232
|
+
else
|
233
|
+
raise "Invalid topics given to microservice_cmd: #{topics}"
|
234
|
+
end
|
235
|
+
Topic.trim_topic(topic, msg_id)
|
236
|
+
return true
|
237
|
+
end
|
238
|
+
Topic.trim_topic(topic, msg_id)
|
239
|
+
return false
|
240
|
+
end
|
213
241
|
end
|
214
242
|
end
|
@@ -43,6 +43,7 @@ module OpenC3
|
|
43
43
|
attr_accessor :secrets
|
44
44
|
attr_accessor :prefix
|
45
45
|
attr_accessor :disable_erb
|
46
|
+
attr_accessor :ignore_changes
|
46
47
|
|
47
48
|
# NOTE: The following three class methods are used by the ModelController
|
48
49
|
# and are reimplemented to enable various Model class methods to work
|
@@ -103,6 +104,7 @@ module OpenC3
|
|
103
104
|
secrets: [],
|
104
105
|
prefix: nil,
|
105
106
|
disable_erb: nil,
|
107
|
+
ignore_changes: nil,
|
106
108
|
scope:
|
107
109
|
)
|
108
110
|
parts = name.split("__")
|
@@ -128,6 +130,7 @@ module OpenC3
|
|
128
130
|
@secrets = secrets
|
129
131
|
@prefix = prefix
|
130
132
|
@disable_erb = disable_erb
|
133
|
+
@ignore_changes = ignore_changes
|
131
134
|
@bucket = Bucket.getClient()
|
132
135
|
end
|
133
136
|
|
@@ -149,7 +152,8 @@ module OpenC3
|
|
149
152
|
'needs_dependencies' => @needs_dependencies,
|
150
153
|
'secrets' => @secrets.as_json(*a),
|
151
154
|
'prefix' => @prefix,
|
152
|
-
'disable_erb' => @disable_erb
|
155
|
+
'disable_erb' => @disable_erb,
|
156
|
+
'ignore_changes' => @ignore_changes
|
153
157
|
}
|
154
158
|
end
|
155
159
|
|
@@ -183,13 +183,17 @@ module OpenC3
|
|
183
183
|
if File.exist?(File.join(gem_path, 'requirements.txt'))
|
184
184
|
begin
|
185
185
|
pypi_url = get_setting('pypi_url', scope: scope)
|
186
|
-
rescue
|
187
|
-
|
188
|
-
|
189
|
-
pypi_url
|
186
|
+
rescue => e
|
187
|
+
Logger.error("Failed to retrieve pypi_url: #{e.formatted}")
|
188
|
+
ensure
|
189
|
+
if pypi_url.nil?
|
190
|
+
# If Redis isn't running try the ENV, then simply pypi.org/simple
|
191
|
+
pypi_url = ENV['PYPI_URL']
|
192
|
+
pypi_url ||= 'https://pypi.org/simple'
|
193
|
+
end
|
190
194
|
end
|
191
|
-
Logger.info "Installing python packages from requirements.txt"
|
192
|
-
puts
|
195
|
+
Logger.info "Installing python packages from requirements.txt with pypi_url=#{pypi_url}"
|
196
|
+
puts `/openc3/bin/pipinstall --user -i #{pypi_url} -r #{File.join(gem_path, 'requirements.txt')}`
|
193
197
|
needs_dependencies = true
|
194
198
|
end
|
195
199
|
|
@@ -342,7 +346,7 @@ module OpenC3
|
|
342
346
|
raise message
|
343
347
|
end
|
344
348
|
rescue Exception => error
|
345
|
-
Logger.error("Error undeploying plugin model #{@name} in scope #{@scope} due to: #{error}")
|
349
|
+
Logger.error("Error undeploying plugin model #{@name} in scope #{@scope} due to: #{error.formatted}")
|
346
350
|
ensure
|
347
351
|
# Double check everything is gone
|
348
352
|
found = []
|