openc3 5.2.0 → 5.4.0

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.

Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +108 -105
  3. data/data/config/interface_modifiers.yaml +22 -4
  4. data/data/config/item_modifiers.yaml +4 -2
  5. data/data/config/microservice.yaml +18 -0
  6. data/data/config/table_manager.yaml +2 -2
  7. data/data/config/tool.yaml +1 -1
  8. data/ext/openc3/ext/config_parser/config_parser.c +17 -2
  9. data/lib/openc3/api/api.rb +1 -0
  10. data/lib/openc3/api/interface_api.rb +12 -0
  11. data/lib/openc3/api/metrics_api.rb +97 -0
  12. data/lib/openc3/api/router_api.rb +14 -2
  13. data/lib/openc3/api/target_api.rb +24 -3
  14. data/lib/openc3/api/tlm_api.rb +5 -4
  15. data/lib/openc3/config/config_parser.rb +29 -4
  16. data/lib/openc3/core_ext/time.rb +6 -1
  17. data/lib/openc3/interfaces/interface.rb +27 -26
  18. data/lib/openc3/interfaces/mqtt_interface.rb +240 -0
  19. data/lib/openc3/interfaces/protocols/override_protocol.rb +2 -61
  20. data/lib/openc3/interfaces/protocols/protocol.rb +6 -1
  21. data/lib/openc3/interfaces/simulated_target_interface.rb +1 -3
  22. data/lib/openc3/interfaces/tcpip_server_interface.rb +0 -11
  23. data/lib/openc3/interfaces.rb +2 -3
  24. data/lib/openc3/logs/buffered_packet_log_reader.rb +2 -2
  25. data/lib/openc3/microservices/cleanup_microservice.rb +17 -1
  26. data/lib/openc3/microservices/decom_microservice.rb +12 -9
  27. data/lib/openc3/microservices/interface_microservice.rb +93 -9
  28. data/lib/openc3/microservices/log_microservice.rb +11 -5
  29. data/lib/openc3/microservices/microservice.rb +10 -9
  30. data/lib/openc3/microservices/periodic_microservice.rb +7 -0
  31. data/lib/openc3/microservices/reaction_microservice.rb +0 -33
  32. data/lib/openc3/microservices/reducer_microservice.rb +14 -10
  33. data/lib/openc3/microservices/text_log_microservice.rb +12 -3
  34. data/lib/openc3/microservices/timeline_microservice.rb +0 -6
  35. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -20
  36. data/lib/openc3/models/cvt_model.rb +103 -47
  37. data/lib/openc3/models/interface_model.rb +23 -0
  38. data/lib/openc3/models/metric_model.rb +53 -6
  39. data/lib/openc3/models/microservice_model.rb +15 -1
  40. data/lib/openc3/models/model.rb +1 -1
  41. data/lib/openc3/models/plugin_model.rb +6 -1
  42. data/lib/openc3/models/secret_model.rb +53 -0
  43. data/lib/openc3/models/target_model.rb +2 -2
  44. data/lib/openc3/models/tool_model.rb +17 -8
  45. data/lib/openc3/operators/microservice_operator.rb +25 -0
  46. data/lib/openc3/operators/operator.rb +5 -1
  47. data/lib/openc3/packets/packet.rb +21 -7
  48. data/lib/openc3/packets/packet_item.rb +3 -2
  49. data/lib/openc3/script/api_shared.rb +18 -2
  50. data/lib/openc3/script/script.rb +8 -0
  51. data/lib/openc3/script/script_runner.rb +1 -2
  52. data/lib/openc3/script/storage.rb +2 -1
  53. data/lib/openc3/script/suite.rb +15 -11
  54. data/lib/openc3/system/system.rb +6 -3
  55. data/lib/openc3/topics/interface_topic.rb +17 -1
  56. data/lib/openc3/topics/router_topic.rb +17 -1
  57. data/lib/openc3/utilities/aws_bucket.rb +20 -3
  58. data/lib/openc3/utilities/bucket.rb +1 -1
  59. data/lib/openc3/utilities/bucket_file_cache.rb +1 -1
  60. data/lib/openc3/utilities/bucket_utilities.rb +1 -1
  61. data/lib/openc3/utilities/local_mode.rb +1 -0
  62. data/lib/openc3/utilities/metric.rb +77 -101
  63. data/lib/openc3/utilities/redis_secrets.rb +46 -0
  64. data/lib/openc3/utilities/s3_autoload.rb +19 -9
  65. data/lib/openc3/utilities/secrets.rb +63 -0
  66. data/lib/openc3/utilities/target_file.rb +3 -1
  67. data/lib/openc3/version.rb +5 -5
  68. data/templates/plugin-template/LICENSE.txt +7 -0
  69. data/templates/plugin-template/README.md +4 -3
  70. data/templates/plugin-template/plugin.gemspec +4 -4
  71. metadata +22 -3
  72. data/data/config/_interfaces.yaml.err +0 -1017
@@ -28,7 +28,8 @@ module OpenC3
28
28
  WHITELIST.concat([
29
29
  'get_target_list',
30
30
  'get_target',
31
- 'get_all_target_info',
31
+ 'get_target_interfaces',
32
+ 'get_all_target_info', # DEPRECATED
32
33
  ])
33
34
 
34
35
  # Returns the list of all target names
@@ -49,9 +50,29 @@ module OpenC3
49
50
  TargetModel.get(name: target_name, scope: scope)
50
51
  end
51
52
 
52
- # Get information about all targets
53
+ # Get all targets and their interfaces
53
54
  #
54
- # @return [Array<Array<String, Numeric, Numeric>] Array of Arrays \[name, interface, cmd_cnt, tlm_cnt]
55
+ # @return [Array<Array<String, String] Array of Arrays \[name, interfaces]
56
+ def get_target_interfaces(scope: $openc3_scope, token: $openc3_token)
57
+ authorize(permission: 'system', scope: scope, token: token)
58
+ info = []
59
+ interfaces = InterfaceModel.all(scope: scope)
60
+ get_target_list(scope: scope, token: token).each do |target_name|
61
+ interface_names = []
62
+ interfaces.each do |name, interface|
63
+ if interface['target_names'].include? target_name
64
+ interface_names << interface['name']
65
+ end
66
+ end
67
+ info << [target_name, interface_names.join(",")]
68
+ end
69
+ info
70
+ end
71
+
72
+ # DEPRECATED: Get information about all targets
73
+ # Warning this call can take a long time with many defined packets
74
+ #
75
+ # @return [Array<Array<String, String, Numeric, Numeric>] Array of Arrays \[name, interface, cmd_cnt, tlm_cnt]
55
76
  def get_all_target_info(scope: $openc3_scope, token: $openc3_token)
56
77
  authorize(permission: 'system', scope: scope, token: token)
57
78
  info = []
@@ -118,7 +118,8 @@ module OpenC3
118
118
  # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
119
119
  def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
120
120
  authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
121
- unless CvtModel::VALUE_TYPES.include?(type.intern)
121
+ type = type.to_s.intern
122
+ unless CvtModel::VALUE_TYPES.include?(type)
122
123
  raise "Unknown type '#{type}' for #{target_name} #{packet_name}"
123
124
  end
124
125
 
@@ -161,8 +162,8 @@ module OpenC3
161
162
  # @param args The args must either be a string followed by a value or
162
163
  # three strings followed by a value (see the calling style in the
163
164
  # description).
164
- # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
165
- def override_tlm(*args, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
165
+ # @param type [Symbol] Telemetry type, :ALL (default), :RAW, :CONVERTED, :FORMATTED, :WITH_UNITS
166
+ def override_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
166
167
  target_name, packet_name, item_name, value = set_tlm_process_args(args, __method__, scope: scope)
167
168
  authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
168
169
  CvtModel.override(target_name, packet_name, item_name, value, type: type.intern, scope: scope)
@@ -179,7 +180,7 @@ module OpenC3
179
180
  #
180
181
  # @param args The args must either be a string or three strings
181
182
  # (see the calling style in the description).
182
- # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
183
+ # @param type [Symbol] Telemetry type, :ALL (default), :RAW, :CONVERTED, :FORMATTED, :WITH_UNITS
183
184
  # Also takes :ALL which means to normalize all telemetry types
184
185
  def normalize_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
185
186
  target_name, packet_name, item_name = tlm_process_args(args, __method__, scope: scope)
@@ -219,8 +219,6 @@ module OpenC3
219
219
  size,
220
220
  PARSING_REGEX,
221
221
  &block)
222
- rescue Exception => e # Catch EVERYTHING so we can re-raise with additional info
223
- raise e, "#{e}\n\nParsed output in #{file.path}", e.backtrace
224
222
  ensure
225
223
  file.close unless file.closed?
226
224
  end
@@ -446,6 +444,22 @@ module OpenC3
446
444
  value
447
445
  end
448
446
 
447
+ def parse_errors(errors)
448
+ return if errors.empty?
449
+ message = ''
450
+ errors.each do |error|
451
+ if error.is_a? OpenC3::ConfigParser::Error
452
+ message += "\n#{File.basename(error.filename)}:#{error.line_number}: #{error.line}"
453
+ message += "\nError: #{error.message}"
454
+ message += "\nUsage: #{error.usage}" unless error.usage.empty?
455
+ else
456
+ message += "\n#{error.message}"
457
+ end
458
+ message += "\n"
459
+ end
460
+ raise message
461
+ end
462
+
449
463
  if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
450
464
  # Iterates over each line of the io object and yields the keyword and parameters
451
465
  def parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx)
@@ -454,6 +468,7 @@ module OpenC3
454
468
  @keyword = nil
455
469
  @parameters = []
456
470
  @line = ''
471
+ errors = []
457
472
 
458
473
  while true
459
474
  @line_number += 1
@@ -516,7 +531,11 @@ module OpenC3
516
531
  # Ignore lines without keywords: comments and blank lines
517
532
  if @keyword.nil?
518
533
  if yield_non_keyword_lines
519
- yield(@keyword, @parameters)
534
+ begin
535
+ yield(@keyword, @parameters)
536
+ rescue => error
537
+ errors << error
538
+ end
520
539
  end
521
540
  @line = ''
522
541
  next
@@ -545,10 +564,16 @@ module OpenC3
545
564
  end
546
565
  end
547
566
 
548
- yield(@keyword, @parameters)
567
+ begin
568
+ yield(@keyword, @parameters)
569
+ rescue => error
570
+ errors << error
571
+ end
549
572
  @line = ''
550
573
  end
551
574
 
575
+ parse_errors(errors)
576
+
552
577
  @@progress_callback.call(1.0) if @@progress_callback
553
578
 
554
579
  return nil
@@ -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
  require 'date'
@@ -58,6 +58,7 @@ class Time
58
58
  MINUTES_PER_HOUR = 60
59
59
  HOURS_PER_DAY = 24
60
60
  NSEC_PER_SECOND = 1_000_000_000
61
+ NSEC_PER_MSEC = 1_000_000
61
62
  USEC_PER_SECOND = USEC_PER_MSEC * MSEC_PER_SECOND
62
63
  MSEC_PER_MINUTE = 60 * MSEC_PER_SECOND
63
64
  MSEC_PER_HOUR = 60 * MSEC_PER_MINUTE
@@ -508,4 +509,8 @@ class Time
508
509
  nanoseconds = nsec_from_epoch % NSEC_PER_SECOND
509
510
  Time.at(seconds, nanoseconds, :nsec)
510
511
  end
512
+
513
+ def to_msec_from_epoch
514
+ (self.tv_sec * MSEC_PER_SECOND) + (self.tv_nsec / NSEC_PER_MSEC)
515
+ end
511
516
  end
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'openc3/api/api'
24
24
  require 'openc3/io/raw_logger_pair'
25
+ require 'openc3/utilities/secrets'
25
26
 
26
27
  module OpenC3
27
28
  # Defines all the attributes and methods common to all interface classes
@@ -112,9 +113,6 @@ module OpenC3
112
113
  # @return [Array<[Protocol Class, Protocol Args, Protocol kind (:READ, :WRITE, :READ_WRITE)>] Info to recreate protocols
113
114
  attr_accessor :protocol_info
114
115
 
115
- # @return [Hash or nil] Hash of overridden telemetry points
116
- attr_accessor :override_tlm
117
-
118
116
  # @return [String] Most recently read raw data
119
117
  attr_accessor :read_raw_data
120
118
 
@@ -134,6 +132,9 @@ module OpenC3
134
132
  # (when used as a BridgeRouter)
135
133
  attr_accessor :interfaces
136
134
 
135
+ # @return [Secrets] Interface secrets manager class
136
+ attr_accessor :secrets
137
+
137
138
  # Initialize default attribute values
138
139
  def initialize
139
140
  @name = self.class.to_s.split("::")[-1] # Remove namespacing if present
@@ -166,13 +167,13 @@ module OpenC3
166
167
  @read_protocols = []
167
168
  @write_protocols = []
168
169
  @protocol_info = []
169
- @override_tlm = nil
170
170
  @read_raw_data = ''
171
171
  @written_raw_data = ''
172
172
  @read_raw_data_time = nil
173
173
  @written_raw_data_time = nil
174
174
  @config_params = []
175
175
  @interfaces = []
176
+ @secrets = Secrets.getClient
176
177
  end
177
178
 
178
179
  # Connects the interface to its target(s). Must be implemented by a
@@ -406,13 +407,13 @@ module OpenC3
406
407
  # num_clients is per interface so don't copy
407
408
  # read_queue_size is the number of packets in the queue so don't copy
408
409
  # write_queue_size is the number of packets in the queue so don't copy
409
- other_interface.options = self.options.clone
410
+ self.options.each do |option_name, option_values|
411
+ other_interface.set_option(option_name, option_values)
412
+ end
410
413
  other_interface.protocol_info = []
411
414
  self.protocol_info.each do |protocol_class, protocol_args, read_write|
412
415
  other_interface.add_protocol(protocol_class, protocol_args, read_write)
413
416
  end
414
- other_interface.override_tlm = nil
415
- other_interface.override_tlm = self.override_tlm.clone if self.override_tlm
416
417
  end
417
418
 
418
419
  # Set an interface or router specific option
@@ -484,28 +485,28 @@ module OpenC3
484
485
  protocol.interface = self
485
486
  end
486
487
 
487
- def _override_tlm(target_name, packet_name, item_name, value)
488
- _override(target_name, packet_name, item_name, value, :CONVERTED)
488
+ def interface_cmd(cmd_name, *cmd_args)
489
+ # Default do nothing - Implemented by subclasses
490
+ return false
489
491
  end
490
492
 
491
- def _override_tlm_raw(target_name, packet_name, item_name, value)
492
- _override(target_name, packet_name, item_name, value, :RAW)
493
- end
494
-
495
- def _normalize_tlm(target_name, packet_name, item_name)
496
- @override_tlm ||= {}
497
- pkt = @override_tlm[target_name]
498
- if pkt
499
- items = @override_tlm[target_name][packet_name]
500
- items.delete(item_name) if items
493
+ def protocol_cmd(cmd_name, *cmd_args, read_write: :READ_WRITE, index: -1)
494
+ read_write = read_write.to_s.upcase.intern
495
+ protocols = nil
496
+ case read_write
497
+ when :READ, :READ_WRITE
498
+ protocols = @read_protocols
499
+ when :WRITE
500
+ protocols = @write_protocols.reverse # Reverse so ordering matches configuration ordering
501
+ else
502
+ raise "Unknown protocol descriptor: #{read_write}. Must be :READ, :WRITE, or :READ_WRITE."
501
503
  end
502
- end
503
-
504
- def _override(target_name, packet_name, item_name, value, type)
505
- @override_tlm ||= {}
506
- @override_tlm[target_name] ||= {}
507
- @override_tlm[target_name][packet_name] ||= {}
508
- @override_tlm[target_name][packet_name][item_name] = [value, type]
504
+ handled = false
505
+ protocols.each_with_index do |protocol, protocol_index|
506
+ result = protocol.protocol_cmd(cmd_name, @cmd_args) if index == protocol_index or index == -1
507
+ handled = true if result
508
+ end
509
+ return handled
509
510
  end
510
511
  end
511
512
  end
@@ -0,0 +1,240 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2022 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
+ # You can quickly setup an unauthenticated MQTT server in Docker with
20
+ # docker run -it -p 1883:1883 eclipse-mosquitto:2.0.15 mosquitto -c /mosquitto-no-auth.conf
21
+
22
+ require 'openc3/interfaces/interface'
23
+ require 'openc3/config/config_parser'
24
+ require 'mqtt'
25
+
26
+ # Patches to the Ruby MQTT library so that it will work reliably with COSMOS
27
+ saved_verbose = $VERBOSE
28
+ $VERBOSE = nil
29
+ module MQTT
30
+ class Client
31
+ def get(topic = nil, options = {})
32
+ if block_given?
33
+ get_packet(topic) do |packet|
34
+ yield(packet.topic, packet.payload) unless packet.retain && options[:omit_retained]
35
+ end
36
+ else
37
+ loop do
38
+ # Wait for one packet to be available
39
+ packet = get_packet(topic)
40
+ return nil unless packet # Patch for COSMOS
41
+ return packet.topic, packet.payload unless packet.retain && options[:omit_retained]
42
+ end
43
+ end
44
+ end
45
+
46
+ def get_packet(topic = nil)
47
+ # Subscribe to a topic, if an argument is given
48
+ subscribe(topic) unless topic.nil?
49
+
50
+ if block_given?
51
+ # Loop forever!
52
+ loop do
53
+ packet = @read_queue.pop
54
+ return nil unless packet # Patch for COSMOS
55
+ yield(packet)
56
+ puback_packet(packet) if packet.qos > 0
57
+ end
58
+ else
59
+ # Wait for one packet to be available
60
+ packet = @read_queue.pop
61
+ return nil unless packet # Patch for COSMOS
62
+ puback_packet(packet) if packet.qos > 0
63
+ return packet
64
+ end
65
+ end
66
+
67
+ def disconnect(send_msg = true)
68
+ # Stop reading packets from the socket first
69
+ @read_thread.kill if @read_thread && @read_thread.alive?
70
+ @read_thread = nil
71
+
72
+ @read_queue << nil # Patch for COSMOS
73
+
74
+ # Close the socket if it is open
75
+ if connected?
76
+ if send_msg
77
+ packet = MQTT::Packet::Disconnect.new
78
+ send_packet(packet)
79
+ end
80
+ @socket.close unless @socket.nil?
81
+ @socket = nil
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+ $VERBOSE = saved_verbose
88
+
89
+ module OpenC3
90
+ # Base class for interfaces that send and receive messages over MQTT
91
+ class MqttInterface < Interface
92
+ # @param hostname [String] MQTT server to connect to
93
+ # @param port [Integer] MQTT port
94
+ # @param ssl [Boolean] Use SSL true/false
95
+ def initialize(hostname, port = 1883, ssl = false)
96
+ super()
97
+ @hostname = hostname
98
+ @port = Integer(port)
99
+ @ssl = ConfigParser.handle_true_false(ssl)
100
+ @username = nil
101
+ @password = nil
102
+ @cert = nil
103
+ @key = nil
104
+ @ca_file = nil
105
+
106
+ @write_topics = []
107
+ @read_topics = []
108
+
109
+ # Build list of packets by topic
110
+ @read_packets_by_topic = {}
111
+ System.telemetry.all.each do |target_name, target_packets|
112
+ target_packets.each do |packet_name, packet|
113
+ topics = packet.meta['TOPIC']
114
+ topics = packet.meta['TOPICS'] unless topics
115
+ if topics
116
+ topics.each do |topic|
117
+ @read_packets_by_topic[topic] = packet
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ # Connects the interface to its target(s)
125
+ def connect
126
+ @write_topics = []
127
+ @read_topics = []
128
+ @client = MQTT::Client.new
129
+ @client.host = @hostname
130
+ @client.port = @port
131
+ @client.ssl = @ssl
132
+ @client.username = @username if @username
133
+ @client.password = @password if @password
134
+ @client.cert = @cert if @cert
135
+ @client.key = @key if @key
136
+ @client.ca_file = @ca_file.path if @ca_file
137
+ @client.connect
138
+ @read_packets_by_topic.each do |topic, _|
139
+ Logger.info "#{@name}: Subscribing to #{topic}"
140
+ @client.subscribe(topic)
141
+ end
142
+ super()
143
+ end
144
+
145
+ # @return [Boolean] Whether the active ports (read and/or write) have
146
+ # created sockets. Since UDP is connectionless, creation of the sockets
147
+ # is used to determine connection.
148
+ def connected?
149
+ if @client
150
+ return @client.connected?
151
+ else
152
+ return false
153
+ end
154
+ end
155
+
156
+ # Disconnects the interface from its target(s)
157
+ def disconnect
158
+ @client.disconnect
159
+ @client = nil
160
+ super()
161
+ end
162
+
163
+ def read
164
+ topic = @read_topics.shift
165
+ packet = super()
166
+ return nil unless packet
167
+ identified_packet = @read_packets_by_topic[topic]
168
+ if identified_packet
169
+ identified_packet = identified_packet.dup
170
+ identified_packet.buffer = packet.buffer
171
+ packet = identified_packet
172
+ end
173
+ packet.received_time = nil
174
+ return packet
175
+ end
176
+
177
+ def write(packet)
178
+ topics = packet.meta['TOPIC']
179
+ topics = packet.meta['TOPICS'] unless topics
180
+ if topics
181
+ topics.each do |topic|
182
+ @write_topics << topic
183
+ super(packet)
184
+ end
185
+ else
186
+ raise "Command packet #{packet.target_name} #{packet.packet_name} requires a META TOPIC or TOPICS"
187
+ end
188
+ end
189
+
190
+ # Reads from the socket if the read_port is defined
191
+ def read_interface
192
+ topic, data = @client.get
193
+ if data.nil? or data.length <= 0
194
+ Logger.info "#{@name}: read returned nil" if data.nil?
195
+ Logger.info "#{@name}: read returned 0 bytes" if not data.nil? and data.length <= 0
196
+ return nil
197
+ end
198
+ @read_topics << topic
199
+ read_interface_base(data)
200
+ return data
201
+ rescue IOError # Disconnected
202
+ return nil
203
+ end
204
+
205
+ # Writes to the socket
206
+ # @param data [String] Raw packet data
207
+ def write_interface(data)
208
+ write_interface_base(data)
209
+ topic = @write_topics.shift
210
+ @client.publish(topic, data)
211
+ data
212
+ end
213
+
214
+ # Supported Options
215
+ # USERNAME - Username for Mqtt Server
216
+ # PASSWORD - Password for Mqtt Server
217
+ # CERT - Public Key for Client Cert Auth
218
+ # KEY - Private Key for Client Cert Auth
219
+ # CA_FILE - Certificate Authority for Client Cert Auth
220
+ # (see Interface#set_option)
221
+ def set_option(option_name, option_values)
222
+ super(option_name, option_values)
223
+ case option_name.upcase
224
+ when 'USERNAME'
225
+ @username = option_values[0]
226
+ when 'PASSWORD'
227
+ @password = option_values[0]
228
+ when 'CERT'
229
+ @cert = option_values[0]
230
+ when 'KEY'
231
+ @key = option_values[0]
232
+ when 'CA_FILE'
233
+ # CA_FILE must be given as a file
234
+ @ca_file = Tempfile.new('ca_file')
235
+ @ca_file.write(option_values[0])
236
+ @ca_file.close
237
+ end
238
+ end
239
+ end
240
+ end
@@ -1,63 +1,4 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2022 Ball Aerospace & Technologies Corp.
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
- # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
18
- # All Rights Reserved
19
- #
20
- # This file may also be used under the terms of a commercial license
21
- # if purchased from OpenC3, Inc.
22
-
23
- require 'openc3/interfaces/protocols/protocol'
24
-
25
- module OpenC3
26
- # Protocol which permanently overrides an item value such that reading the
27
- # item returns the overriden value. Methods are prefixed with underscores
28
- # so the API can include the original name which calls out to these
29
- # methods. Clearing the override requires calling normalize_tlm.
30
- class OverrideProtocol < Protocol
31
- # @param allow_empty_data [true/false/nil] See Protocol#initialize
32
- def initialize(allow_empty_data = nil)
33
- super(allow_empty_data)
34
- end
35
-
36
- # Called to perform modifications on a read packet before it is given to the user
37
- #
38
- # @param packet [Packet] Original packet
39
- # @return [Packet] Potentially modified packet
40
- def read_packet(packet)
41
- if @interface.override_tlm && !@interface.override_tlm.empty?
42
- # Need to make sure packet is identified and defined
43
- target_names = nil
44
- target_names = @interface.tlm_target_names if @interface
45
- identified_packet = System.telemetry.identify_and_define_packet(packet, target_names)
46
- if identified_packet
47
- packet = identified_packet
48
- packets = @interface.override_tlm[packet.target_name]
49
- if packets
50
- items = packets[packet.packet_name]
51
- if items
52
- items.each do |item_name, value|
53
- # This should be safe because we check at the API level it exists
54
- packet.write(item_name, value[0], value[1])
55
- end
56
- end
57
- end
58
- end
59
- end
60
- return packet
61
- end
62
- end
63
- end
3
+ # This class is deprecated and this file exists only to satisfy existing code requiring it
4
+ # TODO: Remove this in a future release
@@ -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
  require 'openc3/config/config_parser'
@@ -81,5 +81,10 @@ module OpenC3
81
81
  def post_write_interface(packet, data)
82
82
  return packet, data
83
83
  end
84
+
85
+ def protocol_cmd(cmd_name, *cmd_args)
86
+ # Default do nothing - Implemented by subclasses
87
+ return false
88
+ end
84
89
  end
85
90
  end
@@ -17,11 +17,10 @@
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
  require 'openc3/interfaces/interface'
24
- require 'openc3/interfaces/protocols/override_protocol'
25
24
 
26
25
  module OpenC3
27
26
  # An interface class that provides simulated telemetry and command responses
@@ -38,7 +37,6 @@ module OpenC3
38
37
  @sim_target = nil
39
38
  @write_raw_allowed = false
40
39
  @raw_logger_pair = nil
41
- add_protocol(OverrideProtocol, [], :READ)
42
40
  end
43
41
 
44
42
  # Initialize the simulated target object and "connect" to the target
@@ -58,8 +58,6 @@ module OpenC3
58
58
  attr_accessor :raw_logger_pair
59
59
  # @return [String] The ip address to bind to. Default to ANY (0.0.0.0)
60
60
  attr_accessor :listen_address
61
- # @return [boolean] Automatically send SYSTEM META on connect - Default false - Can be CMD/TLM
62
- attr_accessor :auto_system_meta
63
61
 
64
62
  # @param write_port [Integer] The server write port. Clients should connect
65
63
  # and expect to receive data from this port.
@@ -114,7 +112,6 @@ module OpenC3
114
112
  @raw_logging_enabled = false
115
113
  @connection_mutex = Mutex.new
116
114
  @listen_address = "0.0.0.0"
117
- @auto_system_meta = false
118
115
 
119
116
  @read_allowed = false unless ConfigParser.handle_nil(read_port)
120
117
  @write_allowed = false unless ConfigParser.handle_nil(write_port)
@@ -282,15 +279,12 @@ module OpenC3
282
279
 
283
280
  # Supported Options
284
281
  # LISTEN_ADDRESS - Ip address of the interface to accept connections on - Default: 0.0.0.0
285
- # AUTO_SYSTEM_META - Automatically send SYSTEM META on connect - Default false
286
282
  # (see Interface#set_option)
287
283
  def set_option(option_name, option_values)
288
284
  super(option_name, option_values)
289
285
  case option_name.upcase
290
286
  when 'LISTEN_ADDRESS'
291
287
  @listen_address = option_values[0]
292
- when 'AUTO_SYSTEM_META'
293
- @auto_system_meta = ConfigParser.handle_true_false(option_values[0])
294
288
  end
295
289
  end
296
290
 
@@ -411,11 +405,6 @@ module OpenC3
411
405
  interface.connect
412
406
 
413
407
  if listen_write
414
- if @auto_system_meta
415
- meta_packet = System.telemetry.packet('SYSTEM', 'META').clone
416
- interface.write(meta_packet)
417
- end
418
-
419
408
  @write_connection_callback.call(interface) if @write_connection_callback
420
409
  @connection_mutex.synchronize do
421
410
  @write_interface_infos << InterfaceInfo.new(interface, hostname, host_ip, port)