openc3 5.12.0 → 5.14.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.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/bin/openc3cli +21 -18
- data/data/config/command_modifiers.yaml +53 -1
- data/data/config/graph_settings.yaml +1 -1
- data/data/config/item_modifiers.yaml +1 -2
- data/data/config/parameter_modifiers.yaml +13 -14
- data/data/config/screen.yaml +1 -2
- data/data/config/target_config.yaml +2 -6
- data/lib/openc3/accessors/accessor.rb +42 -29
- data/lib/openc3/accessors/binary_accessor.rb +11 -1
- data/lib/openc3/accessors/form_accessor.rb +11 -1
- data/lib/openc3/accessors/http_accessor.rb +38 -0
- data/lib/openc3/accessors/json_accessor.rb +15 -3
- data/lib/openc3/accessors/template_accessor.rb +150 -0
- data/lib/openc3/accessors/xml_accessor.rb +11 -1
- data/lib/openc3/accessors.rb +1 -0
- data/lib/openc3/api/cmd_api.rb +99 -35
- data/lib/openc3/api/limits_api.rb +3 -3
- data/lib/openc3/api/tlm_api.rb +70 -31
- data/lib/openc3/interfaces/interface.rb +9 -7
- data/lib/openc3/interfaces/mqtt_interface.rb +11 -9
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +78 -0
- data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +116 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +5 -0
- data/lib/openc3/interfaces.rb +1 -1
- data/lib/openc3/logs/packet_log_reader.rb +2 -2
- data/lib/openc3/logs/text_log_writer.rb +3 -2
- data/lib/openc3/microservices/decom_microservice.rb +1 -0
- data/lib/openc3/microservices/interface_microservice.rb +10 -1
- data/lib/openc3/microservices/trigger_group_microservice.rb +2 -1
- data/lib/openc3/models/cvt_model.rb +16 -12
- data/lib/openc3/models/gem_model.rb +20 -3
- data/lib/openc3/models/microservice_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +43 -5
- data/lib/openc3/models/target_model.rb +69 -8
- data/lib/openc3/packets/json_packet.rb +46 -15
- data/lib/openc3/packets/packet.rb +92 -4
- data/lib/openc3/packets/packet_config.rb +27 -2
- data/lib/openc3/packets/parsers/xtce_parser.rb +5 -1
- data/lib/openc3/script/api_shared.rb +42 -31
- data/lib/openc3/script/commands.rb +18 -12
- data/lib/openc3/script/limits.rb +1 -1
- data/lib/openc3/script/script.rb +6 -12
- data/lib/openc3/script/storage.rb +4 -4
- data/lib/openc3/script/web_socket_api.rb +2 -2
- data/lib/openc3/streams/mqtt_stream.rb +109 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +19 -0
- data/lib/openc3/system/system.rb +13 -1
- data/lib/openc3/utilities/cli_generator.rb +48 -21
- data/lib/openc3/utilities/local_mode.rb +3 -3
- data/lib/openc3/utilities/logger.rb +17 -16
- data/lib/openc3/utilities/process_manager.rb +1 -1
- data/lib/openc3/utilities/store_queued.rb +126 -0
- data/lib/openc3/version.rb +5 -5
- data/templates/conversion/conversion.py +28 -0
- data/templates/conversion/conversion.rb +1 -18
- data/templates/limits_response/response.py +37 -0
- data/templates/limits_response/response.rb +0 -17
- data/templates/microservice/microservices/TEMPLATE/microservice.py +54 -0
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +0 -7
- data/templates/plugin/.gitignore +1 -0
- data/templates/plugin/plugin.gemspec +2 -2
- data/templates/target/targets/TARGET/lib/target.py +9 -0
- data/templates/target/targets/TARGET/procedures/procedure.py +3 -0
- data/templates/target/targets/TARGET/public/README.txt +1 -0
- data/templates/tool_angular/package.json +21 -20
- data/templates/tool_angular/yarn.lock +2287 -3171
- data/templates/tool_react/package.json +15 -15
- data/templates/tool_react/yarn.lock +716 -789
- data/templates/tool_svelte/package.json +16 -15
- data/templates/tool_svelte/src/services/openc3-api.js +17 -22
- data/templates/tool_svelte/yarn.lock +715 -620
- data/templates/tool_vue/package.json +16 -15
- data/templates/tool_vue/yarn.lock +149 -69
- data/templates/widget/package.json +15 -14
- data/templates/widget/yarn.lock +132 -63
- metadata +160 -148
- data/lib/openc3/io/openc3_snmp.rb +0 -61
@@ -69,7 +69,7 @@ module OpenC3
|
|
69
69
|
method += ", #{orig_kwargs}" unless orig_kwargs.empty?
|
70
70
|
method += ")"
|
71
71
|
rescue Exception => error
|
72
|
-
|
72
|
+
puts "CHECK: #{method} raised #{error.class}:#{error.message}"
|
73
73
|
else
|
74
74
|
raise(CheckError, "#{method} should have raised an exception but did not.")
|
75
75
|
end
|
@@ -107,10 +107,10 @@ module OpenC3
|
|
107
107
|
end
|
108
108
|
|
109
109
|
if all_checks_ok
|
110
|
-
|
110
|
+
puts message
|
111
111
|
else
|
112
112
|
if $disconnect
|
113
|
-
|
113
|
+
puts "ERROR: #{message}"
|
114
114
|
else
|
115
115
|
raise CheckError, message
|
116
116
|
end
|
@@ -120,11 +120,11 @@ module OpenC3
|
|
120
120
|
check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}"
|
121
121
|
range_str = "range #{range.first} to #{range.last} with value == #{value}"
|
122
122
|
if range.include?(value)
|
123
|
-
|
123
|
+
puts "#{check_str} was within #{range_str}"
|
124
124
|
else
|
125
125
|
message = "#{check_str} failed to be within #{range_str}"
|
126
126
|
if $disconnect
|
127
|
-
|
127
|
+
puts "ERROR: #{message}"
|
128
128
|
else
|
129
129
|
raise CheckError, message
|
130
130
|
end
|
@@ -142,11 +142,11 @@ module OpenC3
|
|
142
142
|
def check_expression(exp_to_eval, context = nil, scope: $openc3_scope, token: $openc3_token)
|
143
143
|
success = _openc3_script_wait_implementation_expression(exp_to_eval, 0, DEFAULT_TLM_POLLING_RATE, context, scope: scope, token: token)
|
144
144
|
if success
|
145
|
-
|
145
|
+
puts "CHECK: #{exp_to_eval} is TRUE"
|
146
146
|
else
|
147
147
|
message = "CHECK: #{exp_to_eval} is FALSE"
|
148
148
|
if $disconnect
|
149
|
-
|
149
|
+
puts "ERROR: #{message}"
|
150
150
|
else
|
151
151
|
raise CheckError, message
|
152
152
|
end
|
@@ -171,7 +171,7 @@ module OpenC3
|
|
171
171
|
start_time = Time.now.sys
|
172
172
|
openc3_script_sleep()
|
173
173
|
time_diff = Time.now.sys - start_time
|
174
|
-
|
174
|
+
puts "WAIT: Indefinite for actual time of #{time_diff} seconds" unless quiet
|
175
175
|
|
176
176
|
# wait(5) # absolute wait time
|
177
177
|
when 1
|
@@ -179,7 +179,7 @@ module OpenC3
|
|
179
179
|
start_time = Time.now.sys
|
180
180
|
openc3_script_sleep(args[0])
|
181
181
|
time_diff = Time.now.sys - start_time
|
182
|
-
|
182
|
+
puts "WAIT: #{args[0]} seconds with actual time of #{time_diff} seconds" unless quiet
|
183
183
|
else
|
184
184
|
raise "Non-numeric wait time specified"
|
185
185
|
end
|
@@ -254,9 +254,9 @@ module OpenC3
|
|
254
254
|
end
|
255
255
|
|
256
256
|
if success
|
257
|
-
|
257
|
+
puts message unless quiet
|
258
258
|
else
|
259
|
-
|
259
|
+
puts "WARN: #{message}" unless quiet
|
260
260
|
end
|
261
261
|
else
|
262
262
|
success, value = _openc3_script_wait_implementation_tolerance(target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate, scope: scope, token: token)
|
@@ -265,9 +265,9 @@ module OpenC3
|
|
265
265
|
wait_str = "WAIT: #{_upcase(target_name, packet_name, item_name)}"
|
266
266
|
range_str = "range #{range.first} to #{range.last} with value == #{value} after waiting #{time} seconds"
|
267
267
|
if success
|
268
|
-
|
268
|
+
puts "#{wait_str} was within #{range_str}" unless quiet
|
269
269
|
else
|
270
|
-
|
270
|
+
puts "WARN: #{wait_str} failed to be within #{range_str}" unless quiet
|
271
271
|
end
|
272
272
|
end
|
273
273
|
time
|
@@ -284,9 +284,9 @@ module OpenC3
|
|
284
284
|
success = _openc3_script_wait_implementation_expression(exp_to_eval, timeout, polling_rate, context, scope: scope, token: token)
|
285
285
|
time_diff = Time.now.sys - start_time
|
286
286
|
if success
|
287
|
-
|
287
|
+
puts "WAIT: #{exp_to_eval} is TRUE after waiting #{time_diff} seconds" unless quiet
|
288
288
|
else
|
289
|
-
|
289
|
+
puts "WARN: WAIT: #{exp_to_eval} is FALSE after waiting #{time_diff} seconds" unless quiet
|
290
290
|
end
|
291
291
|
time_diff
|
292
292
|
end
|
@@ -312,11 +312,11 @@ module OpenC3
|
|
312
312
|
end
|
313
313
|
with_value_str = "with value == #{value} after waiting #{time_diff} seconds"
|
314
314
|
if success
|
315
|
-
|
315
|
+
puts "#{check_str} success #{with_value_str}"
|
316
316
|
else
|
317
317
|
message = "#{check_str} failed #{with_value_str}"
|
318
318
|
if $disconnect
|
319
|
-
|
319
|
+
puts "ERROR: #{message}"
|
320
320
|
else
|
321
321
|
raise CheckError, message
|
322
322
|
end
|
@@ -363,10 +363,10 @@ module OpenC3
|
|
363
363
|
end
|
364
364
|
|
365
365
|
if success
|
366
|
-
|
366
|
+
puts message
|
367
367
|
else
|
368
368
|
if $disconnect
|
369
|
-
|
369
|
+
puts "ERROR: #{message}"
|
370
370
|
else
|
371
371
|
raise CheckError, message
|
372
372
|
end
|
@@ -378,11 +378,11 @@ module OpenC3
|
|
378
378
|
check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}"
|
379
379
|
range_str = "range #{range.first} to #{range.last} with value == #{value} after waiting #{time_diff} seconds"
|
380
380
|
if success
|
381
|
-
|
381
|
+
puts "#{check_str} was within #{range_str}"
|
382
382
|
else
|
383
383
|
message = "#{check_str} failed to be within #{range_str}"
|
384
384
|
if $disconnect
|
385
|
-
|
385
|
+
puts "ERROR: #{message}"
|
386
386
|
else
|
387
387
|
raise CheckError, message
|
388
388
|
end
|
@@ -409,11 +409,11 @@ module OpenC3
|
|
409
409
|
context, scope: scope, token: token, &block)
|
410
410
|
time_diff = Time.now.sys - start_time
|
411
411
|
if success
|
412
|
-
|
412
|
+
puts "CHECK: #{exp_to_eval} is TRUE after waiting #{time_diff} seconds"
|
413
413
|
else
|
414
414
|
message = "CHECK: #{exp_to_eval} is FALSE after waiting #{time_diff} seconds"
|
415
415
|
if $disconnect
|
416
|
-
|
416
|
+
puts "ERROR: #{message}"
|
417
417
|
else
|
418
418
|
raise CheckError, message
|
419
419
|
end
|
@@ -525,6 +525,17 @@ module OpenC3
|
|
525
525
|
# Private implementation details
|
526
526
|
###########################################################################
|
527
527
|
|
528
|
+
# This must be here for custom microservices that might block.
|
529
|
+
# Overriden by running_script.rb for script sleep
|
530
|
+
def openc3_script_sleep(sleep_time = nil)
|
531
|
+
if sleep_time
|
532
|
+
sleep(sleep_time)
|
533
|
+
else
|
534
|
+
prompt("Press any key to continue...")
|
535
|
+
end
|
536
|
+
return false
|
537
|
+
end
|
538
|
+
|
528
539
|
# Creates a string with the parameters upcased
|
529
540
|
def _upcase(target_name, packet_name, item_name)
|
530
541
|
"#{target_name.upcase} #{packet_name.upcase} #{item_name.upcase}"
|
@@ -540,7 +551,7 @@ module OpenC3
|
|
540
551
|
if comparison_to_eval
|
541
552
|
_check_eval(target_name, packet_name, item_name, comparison_to_eval, value)
|
542
553
|
else
|
543
|
-
|
554
|
+
puts "CHECK: #{_upcase(target_name, packet_name, item_name)} == #{value}"
|
544
555
|
end
|
545
556
|
end
|
546
557
|
|
@@ -621,17 +632,17 @@ module OpenC3
|
|
621
632
|
value = 0 unless value
|
622
633
|
time_diff = Time.now.sys - start_time
|
623
634
|
if success
|
624
|
-
|
635
|
+
puts "#{type}: #{target_name.upcase} #{packet_name.upcase} received #{value - initial_count} times after waiting #{time_diff} seconds" unless quiet
|
625
636
|
else
|
626
637
|
message = "#{type}: #{target_name.upcase} #{packet_name.upcase} expected to be received #{num_packets} times but only received #{value - initial_count} times after waiting #{time_diff} seconds"
|
627
638
|
if check
|
628
639
|
if $disconnect
|
629
|
-
|
640
|
+
puts "ERROR: #{message}"
|
630
641
|
else
|
631
642
|
raise CheckError, message
|
632
643
|
end
|
633
644
|
else
|
634
|
-
|
645
|
+
puts "WARN: #{message}" unless quiet
|
635
646
|
end
|
636
647
|
end
|
637
648
|
time_diff
|
@@ -645,9 +656,9 @@ module OpenC3
|
|
645
656
|
wait_str = "WAIT: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
|
646
657
|
value_str = "with value == #{value} after waiting #{time_diff} seconds"
|
647
658
|
if success
|
648
|
-
|
659
|
+
puts "#{wait_str} success #{value_str}" unless quiet
|
649
660
|
else
|
650
|
-
|
661
|
+
puts "WARN: #{wait_str} failed #{value_str}" unless quiet
|
651
662
|
end
|
652
663
|
end
|
653
664
|
|
@@ -873,11 +884,11 @@ module OpenC3
|
|
873
884
|
value_str = value.is_a?(String) ? "'#{value}'" : value
|
874
885
|
with_value = "with value == #{value_str}"
|
875
886
|
if eval(string)
|
876
|
-
|
887
|
+
puts "#{check_str} success #{with_value}"
|
877
888
|
else
|
878
889
|
message = "#{check_str} failed #{with_value}"
|
879
890
|
if $disconnect
|
880
|
-
|
891
|
+
puts "ERROR: #{message}"
|
881
892
|
else
|
882
893
|
raise CheckError, message
|
883
894
|
end
|
@@ -69,12 +69,12 @@ module OpenC3
|
|
69
69
|
# NOTE: This is a helper method and should not be called directly
|
70
70
|
def _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
71
71
|
if no_range
|
72
|
-
|
72
|
+
puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring range checks"
|
73
73
|
end
|
74
74
|
if no_hazardous
|
75
|
-
|
75
|
+
puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring hazardous warnings"
|
76
76
|
end
|
77
|
-
|
77
|
+
puts _cmd_string(target_name, cmd_name, cmd_params, raw)
|
78
78
|
end
|
79
79
|
|
80
80
|
def _cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: $openc3_scope)
|
@@ -95,7 +95,7 @@ module OpenC3
|
|
95
95
|
end
|
96
96
|
|
97
97
|
# Get the command and validate the parameters
|
98
|
-
command = $api_server.
|
98
|
+
command = $api_server.get_cmd(target_name, cmd_name, scope: scope)
|
99
99
|
cmd_params.each do |param_name, param_value|
|
100
100
|
param = command['items'].find { |item| item['name'] == param_name }
|
101
101
|
unless param
|
@@ -108,7 +108,7 @@ module OpenC3
|
|
108
108
|
# Send the command and log the results
|
109
109
|
# This method signature has to include the keyword params present in cmd_api.rb cmd_implementation()
|
110
110
|
# NOTE: This is a helper method and should not be called directly
|
111
|
-
def _cmd(cmd, cmd_no_hazardous, *args, scope: $openc3_scope, token: $openc3_token,
|
111
|
+
def _cmd(cmd, cmd_no_hazardous, *args, timeout: nil, log_message: nil, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
112
112
|
extract_string_kwargs_to_args(args, kwargs)
|
113
113
|
raw = cmd.include?('raw')
|
114
114
|
no_range = cmd.include?('no_range') || cmd.include?('no_checks')
|
@@ -118,14 +118,18 @@ module OpenC3
|
|
118
118
|
_cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: scope)
|
119
119
|
else
|
120
120
|
begin
|
121
|
-
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args, scope: scope, token: token
|
122
|
-
|
121
|
+
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args, timeout: timeout, log_message: log_message, scope: scope, token: token)
|
122
|
+
if log_message.nil? or log_message
|
123
|
+
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
124
|
+
end
|
123
125
|
rescue HazardousError => e
|
124
126
|
# This opens a prompt at which point they can cancel and stop the script
|
125
127
|
# or say Yes and send the command. Thus we don't care about the return value.
|
126
128
|
prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
|
127
|
-
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, scope: scope, token: token
|
128
|
-
|
129
|
+
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, scope: scope, token: token)
|
130
|
+
if log_message.nil? or log_message
|
131
|
+
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
132
|
+
end
|
129
133
|
end
|
130
134
|
end
|
131
135
|
end
|
@@ -171,12 +175,14 @@ module OpenC3
|
|
171
175
|
# Builds a command binary
|
172
176
|
#
|
173
177
|
# Accepts two different calling styles:
|
174
|
-
#
|
175
|
-
#
|
176
|
-
def
|
178
|
+
# build_cmd("TGT CMD with PARAM1 val, PARAM2 val")
|
179
|
+
# build_cmd('TGT','CMD',{'PARAM1'=>val,'PARAM2'=>val})
|
180
|
+
def build_cmd(*args, range_check: true, raw: false, scope: $openc3_scope, **kwargs)
|
177
181
|
extract_string_kwargs_to_args(args, kwargs)
|
178
182
|
$api_server.build_command(*args)
|
179
183
|
end
|
184
|
+
# build_command is DEPRECATED
|
185
|
+
alias build_command build_cmd
|
180
186
|
|
181
187
|
# Returns whether the specified command is hazardous
|
182
188
|
#
|
data/lib/openc3/script/limits.rb
CHANGED
@@ -29,7 +29,7 @@ module OpenC3
|
|
29
29
|
define_method(method_name) do |*args, **kw_args, &block|
|
30
30
|
kw_args[:scope] = $openc3_scope unless kw_args[:scope]
|
31
31
|
if $disconnect
|
32
|
-
|
32
|
+
puts "DISCONNECT: #{method_name}(#{args}) ignored"
|
33
33
|
else
|
34
34
|
$api_server.public_send(method_name, *args, **kw_args, &block)
|
35
35
|
end
|
data/lib/openc3/script/script.rb
CHANGED
@@ -93,17 +93,8 @@ module OpenC3
|
|
93
93
|
$script_runner_api_server = nil
|
94
94
|
end
|
95
95
|
|
96
|
-
# This isn't part of the public API because users should use wait()
|
97
|
-
def openc3_script_sleep(sleep_time = nil)
|
98
|
-
if sleep_time
|
99
|
-
sleep(sleep_time)
|
100
|
-
else
|
101
|
-
prompt("Press any key to continue...")
|
102
|
-
end
|
103
|
-
return false
|
104
|
-
end
|
105
|
-
|
106
96
|
# Internal method used in scripts when encountering a hazardous command
|
97
|
+
# Not part of public APIs but must be implemented here
|
107
98
|
def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
|
108
99
|
loop do
|
109
100
|
message = "Warning: Command #{target_name} #{cmd_name} is Hazardous. "
|
@@ -140,6 +131,7 @@ module OpenC3
|
|
140
131
|
default = ''
|
141
132
|
if blank_or_default != true && blank_or_default != false
|
142
133
|
question << " (default = #{blank_or_default})"
|
134
|
+
default = blank_or_default.to_s
|
143
135
|
allow_blank = true
|
144
136
|
else
|
145
137
|
allow_blank = blank_or_default
|
@@ -150,7 +142,9 @@ module OpenC3
|
|
150
142
|
answer.chomp!
|
151
143
|
break if allow_blank
|
152
144
|
end
|
153
|
-
|
145
|
+
if answer.empty? and !default.empty?
|
146
|
+
answer = default
|
147
|
+
end
|
154
148
|
return answer
|
155
149
|
end
|
156
150
|
|
@@ -162,7 +156,7 @@ module OpenC3
|
|
162
156
|
|
163
157
|
def message_box(string, *buttons, **options)
|
164
158
|
print "#{string} (#{buttons.join(", ")}): "
|
165
|
-
print "Details: #{details}\n" if details
|
159
|
+
print "Details: #{details}\n" if options['details']
|
166
160
|
gets.chomp
|
167
161
|
end
|
168
162
|
|
@@ -37,7 +37,7 @@ module OpenC3
|
|
37
37
|
# Only delete from the targets_modified
|
38
38
|
delete_path = "#{scope}/targets_modified/#{path}"
|
39
39
|
endpoint = "/openc3-api/storage/delete/#{delete_path}"
|
40
|
-
|
40
|
+
puts "Deleting #{delete_path}"
|
41
41
|
# Pass the name of the ENV variable name where we pull the actual bucket name
|
42
42
|
response = $api_server.request('delete', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
|
43
43
|
if response.nil? || response.status != 200
|
@@ -65,7 +65,7 @@ module OpenC3
|
|
65
65
|
|
66
66
|
endpoint = "/openc3-api/storage/upload/#{upload_path}"
|
67
67
|
result = _get_presigned_request(endpoint, scope: scope)
|
68
|
-
|
68
|
+
puts "Writing #{upload_path}"
|
69
69
|
|
70
70
|
# Try to put the file
|
71
71
|
begin
|
@@ -104,7 +104,7 @@ module OpenC3
|
|
104
104
|
if part == "targets_modified" and ENV['OPENC3_LOCAL_MODE']
|
105
105
|
local_file = OpenC3::LocalMode.open_local_file(path, scope: scope)
|
106
106
|
if local_file
|
107
|
-
|
107
|
+
puts "Reading local #{scope}/#{part}/#{path}"
|
108
108
|
file = Tempfile.new('target', binmode: true)
|
109
109
|
file.filename = path
|
110
110
|
file.write(local_file.read)
|
@@ -138,7 +138,7 @@ module OpenC3
|
|
138
138
|
|
139
139
|
endpoint = "/openc3-api/storage/download/#{scope}/#{path}"
|
140
140
|
result = _get_presigned_request(endpoint, scope: scope)
|
141
|
-
|
141
|
+
puts "Reading #{scope}/#{path}"
|
142
142
|
|
143
143
|
# Try to get the file
|
144
144
|
uri = _get_uri(result['url'])
|
@@ -217,14 +217,14 @@ module OpenC3
|
|
217
217
|
|
218
218
|
# Log Messages WebSocket
|
219
219
|
class MessagesWebSocketApi < CmdTlmWebSocketApi
|
220
|
-
def initialize(history_count: 0, start_time: nil, end_time: nil,
|
220
|
+
def initialize(history_count: 0, start_time: nil, end_time: nil, level: nil, types: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
|
221
221
|
@identifier = {
|
222
222
|
channel: "MessagesChannel",
|
223
223
|
history_count: history_count
|
224
224
|
}
|
225
225
|
@identifier['start_time'] = start_time if start_time
|
226
226
|
@identifier['end_time'] = end_time if end_time
|
227
|
-
@identifier['
|
227
|
+
@identifier['level'] = level if level
|
228
228
|
@identifier['types'] = types if types
|
229
229
|
super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
|
230
230
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 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/interfaces/mqtt_interface' # For MQTT patches
|
20
|
+
require 'openc3/streams/stream'
|
21
|
+
require 'openc3/config/config_parser'
|
22
|
+
|
23
|
+
module OpenC3
|
24
|
+
class MqttStream < Stream
|
25
|
+
attr_reader :hostname
|
26
|
+
attr_reader :port
|
27
|
+
attr_reader :ssl
|
28
|
+
attr_reader :write_topic
|
29
|
+
attr_reader :read_topic
|
30
|
+
attr_accessor :username
|
31
|
+
attr_accessor :password
|
32
|
+
attr_accessor :cert
|
33
|
+
attr_accessor :key
|
34
|
+
attr_accessor :ca_file
|
35
|
+
|
36
|
+
def initialize(hostname, port = 1883, ssl = false, write_topic = nil, read_topic = nil)
|
37
|
+
super()
|
38
|
+
|
39
|
+
@hostname = hostname
|
40
|
+
@port = Integer(port)
|
41
|
+
@ssl = ConfigParser.handle_true_false(ssl)
|
42
|
+
@write_topic = ConfigParser.handle_nil(write_topic)
|
43
|
+
@read_topic = ConfigParser.handle_nil(read_topic)
|
44
|
+
@connected = false
|
45
|
+
|
46
|
+
@username = nil
|
47
|
+
@password = nil
|
48
|
+
@cert = nil
|
49
|
+
@key = nil
|
50
|
+
@ca_file = nil
|
51
|
+
|
52
|
+
# Mutex on write is needed to protect from commands coming in from more
|
53
|
+
# than one tool
|
54
|
+
@write_mutex = Mutex.new
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [String] Returns a binary string of data from the read_topic
|
58
|
+
def read
|
59
|
+
raise "Attempt to read from write only stream" unless @read_topic
|
60
|
+
|
61
|
+
# No read mutex is needed because reads happen serially
|
62
|
+
_, data = @client.get
|
63
|
+
if data.nil? or data.length <= 0
|
64
|
+
Logger.info "MqttStream: read returned nil" if data.nil?
|
65
|
+
Logger.info "MqttStream: read returned 0 bytes" if not data.nil? and data.length <= 0
|
66
|
+
return nil
|
67
|
+
end
|
68
|
+
|
69
|
+
return data
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param data [String] A binary string of data to write to the write_topic
|
73
|
+
def write(data)
|
74
|
+
raise "Attempt to write to read only stream" unless @write_topic
|
75
|
+
|
76
|
+
@write_mutex.synchronize do
|
77
|
+
@client.publish(@write_topic, data)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Connect the stream
|
82
|
+
def connect
|
83
|
+
@client = MQTT::Client.new
|
84
|
+
@client.host = @hostname
|
85
|
+
@client.port = @port
|
86
|
+
@client.ssl = @ssl
|
87
|
+
@client.username = @username if @username
|
88
|
+
@client.password = @password if @password
|
89
|
+
@client.cert = @cert if @cert
|
90
|
+
@client.key = @key if @key
|
91
|
+
@client.ca_file = @ca_file.path if @ca_file
|
92
|
+
@client.connect
|
93
|
+
@client.subscribe(@read_topic) if @read_topic
|
94
|
+
@connected = true
|
95
|
+
end
|
96
|
+
|
97
|
+
def connected?
|
98
|
+
@connected
|
99
|
+
end
|
100
|
+
|
101
|
+
def disconnect
|
102
|
+
if @connected
|
103
|
+
@client.disconnect
|
104
|
+
@client = nil
|
105
|
+
@connected = false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -160,5 +160,24 @@ module OpenC3
|
|
160
160
|
@pipe_writer.write('.')
|
161
161
|
@connected = false
|
162
162
|
end
|
163
|
+
|
164
|
+
def set_option(option_name, option_values)
|
165
|
+
option_name_upcase = option_name.upcase
|
166
|
+
|
167
|
+
case option_name_upcase
|
168
|
+
when 'KEEPALIVE'
|
169
|
+
@write_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
170
|
+
@read_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
171
|
+
when 'KEEPCNT'
|
172
|
+
@write_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT, Integer(option_values[0]))
|
173
|
+
@read_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT, Integer(option_values[0]))
|
174
|
+
when 'KEEPIDLE'
|
175
|
+
@write_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE, Integer(option_values[0]))
|
176
|
+
@read_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE, Integer(option_values[0]))
|
177
|
+
when 'KEEPINTVL'
|
178
|
+
@write_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL, Integer(option_values[0]))
|
179
|
+
@read_socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL, Integer(option_values[0]))
|
180
|
+
end
|
181
|
+
end
|
163
182
|
end
|
164
183
|
end
|
data/lib/openc3/system/system.rb
CHANGED
@@ -92,6 +92,18 @@ module OpenC3
|
|
92
92
|
zip_file.extract(entry, path) unless File.exist?(path)
|
93
93
|
end
|
94
94
|
end
|
95
|
+
|
96
|
+
# Now add any modifications in targets_modified/TARGET/cmd_tlm
|
97
|
+
# This adds support for remembering dynamically created packets
|
98
|
+
# target.txt must be configured to either use all files in cmd_tlm folder (default)
|
99
|
+
# or have a predetermined empty file like dynamic_tlm.txt
|
100
|
+
bucket_path = "#{scope}/targets_modified/#{target_name}/cmd_tlm"
|
101
|
+
dirs, files = bucket.list_files(bucket: ENV['OPENC3_CONFIG_BUCKET'], path: bucket_path)
|
102
|
+
files.each do |file|
|
103
|
+
bucket_key = File.join(bucket_path, file['name'])
|
104
|
+
local_path = "#{base_dir}/targets/#{target_name}/cmd_tlm/#{file['name']}"
|
105
|
+
bucket.get_object(bucket: ENV['OPENC3_CONFIG_BUCKET'], key: bucket_key, path: local_path)
|
106
|
+
end
|
95
107
|
end
|
96
108
|
|
97
109
|
# Build System from targets
|
@@ -119,7 +131,7 @@ module OpenC3
|
|
119
131
|
# @param target_names [Array of target names]
|
120
132
|
# @param target_config_dir Directory where target config folders are
|
121
133
|
def initialize(target_names, target_config_dir)
|
122
|
-
OpenC3.add_to_search_path(target_config_dir, true)
|
134
|
+
OpenC3.add_to_search_path(target_config_dir, true) if target_config_dir
|
123
135
|
@targets = {}
|
124
136
|
@packet_config = PacketConfig.new
|
125
137
|
@commands = Commands.new(@packet_config)
|