openc3 5.4.1 → 5.4.3.pre.beta0

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.

@@ -1,323 +0,0 @@
1
- # encoding: ascii-8bit
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/config/config_parser'
24
-
25
- module OpenC3
26
- # Reads an ascii file that defines the configuration settings used to
27
- # configure the Command/Telemetry Server.
28
- class CmdTlmServerConfig
29
- # @return [Hash<String, Interface>] Interfaces hash
30
- attr_accessor :interfaces
31
- # @return [Hash<String, Interface>] Routers hash
32
- attr_accessor :routers
33
- # @return [Hash<String, PacketLogWriterPair>] Packet log writer hash. Each
34
- # pair encapsulates a command and telemetry log writer.
35
- attr_accessor :packet_log_writer_pairs
36
- # @return [Array<BackgroundTask>] Array of background tasks
37
- attr_accessor :background_tasks
38
- # @return [String] Command and Telemetry Server title
39
- attr_accessor :title
40
- # @return [Boolean] Flag indicating if meta data should be collected
41
- attr_accessor :metadata
42
-
43
- # Create a default pair of packet log writers and parses the
44
- # configuration file.
45
- #
46
- # @param filename [String] The name of the configuration file to parse
47
- def initialize(filename, system_config)
48
- @system_config = system_config
49
- @interfaces = {}
50
- @routers = {}
51
- @packet_log_writer_pairs = {}
52
- # cmd_log_writer = System.default_packet_log_writer.new(:CMD, *System.default_packet_log_writer_params)
53
- # tlm_log_writer = System.default_packet_log_writer.new(:TLM, *System.default_packet_log_writer_params)
54
- # @packet_log_writer_pairs['DEFAULT'] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
55
- @background_tasks = []
56
- @title = nil
57
- @metadata = false
58
- process_file(filename)
59
- end
60
-
61
- protected
62
-
63
- def get_target_interface_name(target_name)
64
- @interfaces.each do |interface_name, interface|
65
- return interface_name if interface.target_names.include?(target_name)
66
- end
67
- nil
68
- end
69
-
70
- def setup_interface_or_router
71
- current_interface_or_router = OpenStruct.new
72
- current_interface_or_router.interfaces = []
73
- current_interface_or_router.routers = []
74
- current_interface_or_router.target_names = []
75
- current_interface_or_router
76
- end
77
-
78
- # Processes a file and adds in the configuration defined in the file
79
- #
80
- # @param filename [String] The name of the configuration file to parse
81
- # @param recursive [Boolean] Whether process_file is being called
82
- # recursively
83
- def process_file(filename, recursive = false)
84
- current_interface_or_router = nil
85
- current_type = nil
86
- current_interface_log_added = false
87
-
88
- Logger.info "Processing CmdTlmServer configuration in file: #{File.expand_path(filename)}"
89
-
90
- parser = ConfigParser.new("https://openc3.com/docs/v5")
91
- parser.parse_file(filename) do |keyword, params|
92
- case keyword
93
- when 'TITLE'
94
- raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
95
-
96
- parser.verify_num_parameters(1, 1, "#{keyword} <Title Text>")
97
- @title = params[0]
98
-
99
- when 'PACKET_LOG_WRITER'
100
- # usage = "PACKET_LOG_WRITER <Name> <Filename> <Specific Parameters>"
101
- # parser.verify_num_parameters(2, nil, usage)
102
- # packet_log_writer_name = params[0].upcase
103
- # packet_log_writer_class = OpenC3.require_class(params[1])
104
-
105
- # # Verify not overridding a packet log writer that is already associated with an interface
106
- # packet_log_writer_pair = @packet_log_writer_pairs[packet_log_writer_name]
107
- # if packet_log_writer_pair
108
- # @interfaces.each do |interface_name, interface|
109
- # if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
110
- # raise parser.error("Redefining Packet Log Writer #{packet_log_writer_name} not allowed after it is associated with an interface")
111
- # end
112
- # end
113
- # end
114
-
115
- # if params[2]
116
- # cmd_log_writer = packet_log_writer_class.new(:CMD, *params[2..-1])
117
- # tlm_log_writer = packet_log_writer_class.new(:TLM, *params[2..-1])
118
- # @packet_log_writer_pairs[packet_log_writer_name] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
119
- # else
120
- # cmd_log_writer = packet_log_writer_class.new(:CMD)
121
- # tlm_log_writer = packet_log_writer_class.new(:TLM)
122
- # @packet_log_writer_pairs[packet_log_writer_name] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
123
- # end
124
-
125
- when 'AUTO_INTERFACE_TARGETS'
126
- raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
127
-
128
- usage = "#{keyword}"
129
- parser.verify_num_parameters(0, 0, usage)
130
- @system_config.targets.each do |target_name, target|
131
- target_filename = File.join(target.dir, 'cmd_tlm_server.txt')
132
- if File.exist?(target_filename)
133
- # Skip this target if it's already been assigned an interface
134
- next if get_target_interface_name(target.name)
135
- raise parser.error("Cannot use #{keyword} with target name substitutions: #{target.name} != #{target.original_name}") if target.name != target.original_name
136
-
137
- process_file(target_filename, true)
138
- end
139
- end
140
-
141
- when 'INTERFACE_TARGET'
142
- raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
143
-
144
- usage = "#{keyword} <Target Name> <Config File (defaults to cmd_tlm_server.txt)>"
145
- parser.verify_num_parameters(1, 2, usage)
146
- target = @system_config.targets[params[0].upcase]
147
- raise parser.error("Unknown target: #{params[0].upcase}") unless target
148
-
149
- interface_name = get_target_interface_name(target.name)
150
- raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
151
-
152
- target_filename = params[1]
153
- target_filename = 'cmd_tlm_server.txt' unless target_filename
154
- target_filename = File.join(target.dir, target_filename)
155
- if File.exist?(target_filename)
156
- process_file(target_filename, true)
157
- else
158
- raise parser.error("#{target_filename} does not exist")
159
- end
160
-
161
- when 'INTERFACE'
162
- usage = "INTERFACE <Name> <Filename> <Specific Parameters>"
163
- parser.verify_num_parameters(2, nil, usage)
164
- interface_name = params[0].upcase
165
- raise parser.error("Interface '#{interface_name}' defined twice") if @interfaces[interface_name]
166
-
167
- # interface_class = OpenC3.require_class(params[1])
168
- # if params[2]
169
- # current_interface_or_router = interface_class.new(*params[2..-1])
170
- # else
171
- # current_interface_or_router = interface_class.new
172
- # end
173
- current_interface_or_router = setup_interface_or_router()
174
- current_type = :INTERFACE
175
- current_interface_log_added = false
176
- # current_interface_or_router.packet_log_writer_pairs << @packet_log_writer_pairs['DEFAULT']
177
- current_interface_or_router.name = interface_name
178
- current_interface_or_router.config_params = params[1..-1]
179
- @interfaces[interface_name] = current_interface_or_router
180
-
181
- when 'LOG', 'LOG_STORED', 'DONT_LOG', 'TARGET'
182
- raise parser.error("No current interface for #{keyword}") unless current_interface_or_router and current_type == :INTERFACE
183
-
184
- case keyword
185
-
186
- when 'LOG'
187
- parser.verify_num_parameters(1, 1, "#{keyword} <Packet Log Writer Name>")
188
- # packet_log_writer_pair = @packet_log_writer_pairs[params[0].upcase]
189
- # raise parser.error("Unknown packet log writer: #{params[0].upcase}") unless packet_log_writer_pair
190
- # current_interface_or_router.packet_log_writer_pairs.delete(@packet_log_writer_pairs['DEFAULT']) unless current_interface_log_added
191
- current_interface_log_added = true
192
- # current_interface_or_router.packet_log_writer_pairs << packet_log_writer_pair unless current_interface_or_router.packet_log_writer_pairs.include?(packet_log_writer_pair)
193
-
194
- when 'LOG_STORED'
195
- parser.verify_num_parameters(1, 1, "#{keyword} <Packet Log Writer Name>")
196
- # packet_log_writer_pair = @packet_log_writer_pairs[params[0].upcase]
197
- # raise parser.error("Unknown packet log writer: #{params[0].upcase}") unless packet_log_writer_pair
198
- # current_interface_or_router.stored_packet_log_writer_pairs << packet_log_writer_pair unless current_interface_or_router.stored_packet_log_writer_pairs.include?(packet_log_writer_pair)
199
-
200
- when 'DONT_LOG'
201
- parser.verify_num_parameters(0, 0, "#{keyword}")
202
- # current_interface_or_router.packet_log_writer_pairs = []
203
-
204
- when 'TARGET'
205
- parser.verify_num_parameters(1, 1, "#{keyword} <Target Name>")
206
- target_name = params[0].upcase
207
- target = @system_config.targets[target_name]
208
- if target
209
- interface_name = get_target_interface_name(target.name)
210
- raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
211
-
212
- target.interface = current_interface_or_router
213
- current_interface_or_router.target_names << target_name
214
- else
215
- raise parser.error("Unknown target #{target_name} mapped to interface #{current_interface_or_router.name}")
216
- end
217
-
218
- end # end case keyword for all keywords that require a current interface
219
-
220
- when 'DONT_CONNECT', 'DONT_RECONNECT', 'RECONNECT_DELAY', 'DISABLE_DISCONNECT', 'LOG_RAW', 'OPTION', 'PROTOCOL'
221
- raise parser.error("No current interface or router for #{keyword}") unless current_interface_or_router
222
-
223
- case keyword
224
-
225
- when 'DONT_CONNECT'
226
- parser.verify_num_parameters(0, 0, "#{keyword}")
227
- current_interface_or_router.connect_on_startup = false
228
-
229
- when 'DONT_RECONNECT'
230
- parser.verify_num_parameters(0, 0, "#{keyword}")
231
- current_interface_or_router.auto_reconnect = false
232
-
233
- when 'RECONNECT_DELAY'
234
- parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
235
- current_interface_or_router.reconnect_delay = Float(params[0])
236
-
237
- when 'DISABLE_DISCONNECT'
238
- parser.verify_num_parameters(0, 0, "#{keyword}")
239
- current_interface_or_router.disable_disconnect = true
240
-
241
- when 'LOG_RAW',
242
- parser.verify_num_parameters(0, nil, "#{keyword} <Raw Logger Class File (optional)> <Raw Logger Parameters (optional)>")
243
- # current_interface_or_router.raw_logger_pair = RawLoggerPair.new(current_interface_or_router.name, params)
244
- # current_interface_or_router.start_raw_logging
245
-
246
- when 'OPTION'
247
- parser.verify_num_parameters(2, nil, "#{keyword} <Option Name> <Option Value 1> <Option Value 2 (optional)> <etc>")
248
- # current_interface_or_router.set_option(params[0], params[1..-1])
249
-
250
- when 'PROTOCOL'
251
- usage = "#{keyword} <READ WRITE READ_WRITE> <protocol filename or classname> <Protocol specific parameters>"
252
- parser.verify_num_parameters(2, nil, usage)
253
- unless %w(READ WRITE READ_WRITE).include? params[0].upcase
254
- raise parser.error("Invalid protocol type: #{params[0]}", usage)
255
- end
256
-
257
- begin
258
- # klass = OpenC3.require_class(params[1])
259
- # current_interface_or_router.add_protocol(klass, params[2..-1], params[0].upcase.intern)
260
- rescue LoadError, StandardError => error
261
- raise parser.error(error.message, usage)
262
- end
263
-
264
- end # end case keyword for all keywords that require a current interface or router
265
-
266
- when 'ROUTER'
267
- usage = "ROUTER <Name> <Filename> <Specific Parameters>"
268
- parser.verify_num_parameters(2, nil, usage)
269
- router_name = params[0].upcase
270
- raise parser.error("Router '#{router_name}' defined twice") if @routers[router_name]
271
-
272
- # router_class = OpenC3.require_class(params[1])
273
- # if params[2]
274
- # current_interface_or_router = router_class.new(*params[2..-1])
275
- # else
276
- # current_interface_or_router = router_class.new
277
- # end
278
- current_interface_or_router = setup_interface_or_router()
279
- current_type = :ROUTER
280
- current_interface_or_router.name = router_name
281
- @routers[router_name] = current_interface_or_router
282
-
283
- when 'ROUTE'
284
- raise parser.error("No current router for #{keyword}") unless current_interface_or_router and current_type == :ROUTER
285
-
286
- usage = "ROUTE <Interface Name>"
287
- parser.verify_num_parameters(1, 1, usage)
288
- interface_name = params[0].upcase
289
- interface = @interfaces[interface_name]
290
- raise parser.error("Unknown interface #{interface_name} mapped to router #{current_interface_or_router.name}") unless interface
291
-
292
- unless current_interface_or_router.interfaces.include? interface
293
- current_interface_or_router.interfaces << interface
294
- interface.routers << current_interface_or_router
295
- end
296
-
297
- when 'BACKGROUND_TASK'
298
- usage = "#{keyword} <Filename> <Specific Parameters>"
299
- parser.verify_num_parameters(1, nil, usage)
300
- # background_task = OpenC3.require_class(params[0])
301
- if params[1]
302
- @background_tasks << params
303
- else
304
- @background_tasks << params
305
- end
306
-
307
- when 'STOPPED'
308
- parser.verify_num_parameters(0, 0, "#{keyword}")
309
- raise parser.error("No BACKGROUND_TASK defined") if @background_tasks.empty?
310
- # @background_tasks[-1].stopped = true
311
-
312
- when 'COLLECT_METADATA'
313
- parser.verify_num_parameters(0, 0, "#{keyword}")
314
- @metadata = true
315
-
316
- else
317
- # blank lines will have a nil keyword and should not raise an exception
318
- raise parser.error("Unknown keyword: #{keyword}") unless keyword.nil?
319
- end # case
320
- end # loop
321
- end
322
- end
323
- end