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.

Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/bin/openc3cli +21 -18
  4. data/data/config/command_modifiers.yaml +53 -1
  5. data/data/config/graph_settings.yaml +1 -1
  6. data/data/config/item_modifiers.yaml +1 -2
  7. data/data/config/parameter_modifiers.yaml +13 -14
  8. data/data/config/screen.yaml +1 -2
  9. data/data/config/target_config.yaml +2 -6
  10. data/lib/openc3/accessors/accessor.rb +42 -29
  11. data/lib/openc3/accessors/binary_accessor.rb +11 -1
  12. data/lib/openc3/accessors/form_accessor.rb +11 -1
  13. data/lib/openc3/accessors/http_accessor.rb +38 -0
  14. data/lib/openc3/accessors/json_accessor.rb +15 -3
  15. data/lib/openc3/accessors/template_accessor.rb +150 -0
  16. data/lib/openc3/accessors/xml_accessor.rb +11 -1
  17. data/lib/openc3/accessors.rb +1 -0
  18. data/lib/openc3/api/cmd_api.rb +99 -35
  19. data/lib/openc3/api/limits_api.rb +3 -3
  20. data/lib/openc3/api/tlm_api.rb +70 -31
  21. data/lib/openc3/interfaces/interface.rb +9 -7
  22. data/lib/openc3/interfaces/mqtt_interface.rb +11 -9
  23. data/lib/openc3/interfaces/mqtt_stream_interface.rb +78 -0
  24. data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +116 -0
  25. data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -0
  26. data/lib/openc3/interfaces/tcpip_server_interface.rb +5 -0
  27. data/lib/openc3/interfaces.rb +1 -1
  28. data/lib/openc3/logs/packet_log_reader.rb +2 -2
  29. data/lib/openc3/logs/text_log_writer.rb +3 -2
  30. data/lib/openc3/microservices/decom_microservice.rb +1 -0
  31. data/lib/openc3/microservices/interface_microservice.rb +10 -1
  32. data/lib/openc3/microservices/trigger_group_microservice.rb +2 -1
  33. data/lib/openc3/models/cvt_model.rb +16 -12
  34. data/lib/openc3/models/gem_model.rb +20 -3
  35. data/lib/openc3/models/microservice_model.rb +1 -1
  36. data/lib/openc3/models/plugin_model.rb +43 -5
  37. data/lib/openc3/models/target_model.rb +69 -8
  38. data/lib/openc3/packets/json_packet.rb +46 -15
  39. data/lib/openc3/packets/packet.rb +92 -4
  40. data/lib/openc3/packets/packet_config.rb +27 -2
  41. data/lib/openc3/packets/parsers/xtce_parser.rb +5 -1
  42. data/lib/openc3/script/api_shared.rb +42 -31
  43. data/lib/openc3/script/commands.rb +18 -12
  44. data/lib/openc3/script/limits.rb +1 -1
  45. data/lib/openc3/script/script.rb +6 -12
  46. data/lib/openc3/script/storage.rb +4 -4
  47. data/lib/openc3/script/web_socket_api.rb +2 -2
  48. data/lib/openc3/streams/mqtt_stream.rb +109 -0
  49. data/lib/openc3/streams/tcpip_socket_stream.rb +19 -0
  50. data/lib/openc3/system/system.rb +13 -1
  51. data/lib/openc3/utilities/cli_generator.rb +48 -21
  52. data/lib/openc3/utilities/local_mode.rb +3 -3
  53. data/lib/openc3/utilities/logger.rb +17 -16
  54. data/lib/openc3/utilities/process_manager.rb +1 -1
  55. data/lib/openc3/utilities/store_queued.rb +126 -0
  56. data/lib/openc3/version.rb +5 -5
  57. data/templates/conversion/conversion.py +28 -0
  58. data/templates/conversion/conversion.rb +1 -18
  59. data/templates/limits_response/response.py +37 -0
  60. data/templates/limits_response/response.rb +0 -17
  61. data/templates/microservice/microservices/TEMPLATE/microservice.py +54 -0
  62. data/templates/microservice/microservices/TEMPLATE/microservice.rb +0 -7
  63. data/templates/plugin/.gitignore +1 -0
  64. data/templates/plugin/plugin.gemspec +2 -2
  65. data/templates/target/targets/TARGET/lib/target.py +9 -0
  66. data/templates/target/targets/TARGET/procedures/procedure.py +3 -0
  67. data/templates/target/targets/TARGET/public/README.txt +1 -0
  68. data/templates/tool_angular/package.json +21 -20
  69. data/templates/tool_angular/yarn.lock +2287 -3171
  70. data/templates/tool_react/package.json +15 -15
  71. data/templates/tool_react/yarn.lock +716 -789
  72. data/templates/tool_svelte/package.json +16 -15
  73. data/templates/tool_svelte/src/services/openc3-api.js +17 -22
  74. data/templates/tool_svelte/yarn.lock +715 -620
  75. data/templates/tool_vue/package.json +16 -15
  76. data/templates/tool_vue/yarn.lock +149 -69
  77. data/templates/widget/package.json +15 -14
  78. data/templates/widget/yarn.lock +132 -63
  79. metadata +160 -148
  80. 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
- Logger.info "CHECK: #{method} raised #{error.class}:#{error.message}"
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
- Logger.info message
110
+ puts message
111
111
  else
112
112
  if $disconnect
113
- Logger.error message
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
- Logger.info "#{check_str} was within #{range_str}"
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
- Logger.error message
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
- Logger.info "CHECK: #{exp_to_eval} is TRUE"
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
- Logger.error message
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
- Logger.info("WAIT: Indefinite for actual time of #{time_diff} seconds") unless quiet
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
- Logger.info("WAIT: #{args[0]} seconds with actual time of #{time_diff} seconds") unless quiet
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
- Logger.info message unless quiet
257
+ puts message unless quiet
258
258
  else
259
- Logger.warn message unless quiet
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
- Logger.info "#{wait_str} was within #{range_str}" unless quiet
268
+ puts "#{wait_str} was within #{range_str}" unless quiet
269
269
  else
270
- Logger.warn "#{wait_str} failed to be within #{range_str}" unless quiet
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
- Logger.info "WAIT: #{exp_to_eval} is TRUE after waiting #{time_diff} seconds" unless quiet
287
+ puts "WAIT: #{exp_to_eval} is TRUE after waiting #{time_diff} seconds" unless quiet
288
288
  else
289
- Logger.warn "WAIT: #{exp_to_eval} is FALSE after waiting #{time_diff} seconds" unless quiet
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
- Logger.info "#{check_str} success #{with_value_str}"
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
- Logger.error message
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
- Logger.info message
366
+ puts message
367
367
  else
368
368
  if $disconnect
369
- Logger.error message
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
- Logger.info "#{check_str} was within #{range_str}"
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
- Logger.error message
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
- Logger.info "CHECK: #{exp_to_eval} is TRUE after waiting #{time_diff} seconds"
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
- Logger.error message
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
- Logger.info "CHECK: #{_upcase(target_name, packet_name, item_name)} == #{value}"
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
- Logger.info "#{type}: #{target_name.upcase} #{packet_name.upcase} received #{value - initial_count} times after waiting #{time_diff} seconds" unless quiet
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
- Logger.error message
640
+ puts "ERROR: #{message}"
630
641
  else
631
642
  raise CheckError, message
632
643
  end
633
644
  else
634
- Logger.warn message unless quiet
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
- Logger.info "#{wait_str} success #{value_str}" unless quiet
659
+ puts "#{wait_str} success #{value_str}" unless quiet
649
660
  else
650
- Logger.warn "#{wait_str} failed #{value_str}" unless quiet
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
- Logger.info "#{check_str} success #{with_value}"
887
+ puts "#{check_str} success #{with_value}"
877
888
  else
878
889
  message = "#{check_str} failed #{with_value}"
879
890
  if $disconnect
880
- Logger.error message
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
- Logger.warn "Command #{target_name} #{cmd_name} being sent ignoring range checks"
72
+ puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring range checks"
73
73
  end
74
74
  if no_hazardous
75
- Logger.warn "Command #{target_name} #{cmd_name} being sent ignoring hazardous warnings"
75
+ puts "WARN: Command #{target_name} #{cmd_name} being sent ignoring hazardous warnings"
76
76
  end
77
- Logger.info _cmd_string(target_name, cmd_name, cmd_params, raw)
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.get_command(target_name, cmd_name, scope: scope)
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, timeout: nil, **kwargs)
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, timeout: timeout)
122
- _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
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, timeout: timeout)
128
- _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
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
- # build_command("TGT CMD with PARAM1 val, PARAM2 val")
175
- # build_command('TGT','CMD',{'PARAM1'=>val,'PARAM2'=>val})
176
- def build_command(*args, range_check: true, raw: false, scope: $openc3_scope, **kwargs)
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
  #
@@ -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
- Logger.info "DISCONNECT: #{method_name}(#{args}) ignored"
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
@@ -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
- answer = default if answer.empty? and !default.empty?
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
- OpenC3::Logger.info "Deleting #{delete_path}"
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
- OpenC3::Logger.info "Writing #{upload_path}"
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
- OpenC3::Logger.info "Reading local #{scope}/#{part}/#{path}"
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
- OpenC3::Logger.info "Reading #{scope}/#{path}"
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, severity: nil, types: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
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['severity'] = severity if severity
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
@@ -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)