openc3 5.5.0.pre.beta0 → 5.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/openc3cli +58 -74
- data/data/config/_canvas_values.yaml +41 -0
- data/data/config/_graph_params.yaml +25 -0
- data/data/config/graph_settings.yaml +52 -0
- data/data/config/interface_modifiers.yaml +4 -0
- data/data/config/item_modifiers.yaml +1 -1
- data/data/config/microservice.yaml +5 -1
- data/data/config/plugins.yaml +5 -0
- data/data/config/screen.yaml +44 -50
- data/data/config/settings.yaml +144 -0
- data/data/config/widgets.yaml +1744 -1491
- data/lib/openc3/api/cmd_api.rb +43 -17
- data/lib/openc3/api/tlm_api.rb +37 -4
- data/lib/openc3/bridge/bridge.rb +3 -3
- data/lib/openc3/bridge/bridge_config.rb +68 -20
- data/lib/openc3/interfaces/interface.rb +8 -0
- data/lib/openc3/microservices/decom_microservice.rb +0 -3
- data/lib/openc3/microservices/interface_microservice.rb +2 -0
- data/lib/openc3/microservices/reaction_microservice.rb +0 -1
- data/lib/openc3/models/cvt_model.rb +1 -2
- data/lib/openc3/models/interface_model.rb +5 -2
- data/lib/openc3/models/metadata_model.rb +1 -1
- data/lib/openc3/models/microservice_model.rb +7 -6
- data/lib/openc3/models/note_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +17 -8
- data/lib/openc3/models/timeline_model.rb +1 -1
- data/lib/openc3/models/trigger_group_model.rb +1 -1
- data/lib/openc3/operators/microservice_operator.rb +2 -2
- data/lib/openc3/packets/packet_item.rb +1 -1
- data/lib/openc3/script/storage.rb +5 -5
- data/lib/openc3/streams/web_socket_client_stream.rb +0 -1
- data/lib/openc3/tools/table_manager/table_manager_core.rb +1 -2
- data/lib/openc3/utilities/aws_bucket.rb +22 -4
- data/lib/openc3/utilities/bucket_file_cache.rb +3 -2
- data/lib/openc3/utilities/bucket_utilities.rb +1 -1
- data/lib/openc3/utilities/cli_generator.rb +210 -0
- data/lib/openc3/utilities/local_mode.rb +2 -2
- data/lib/openc3/utilities/redis_secrets.rb +4 -4
- data/lib/openc3/utilities/secrets.rb +5 -5
- data/lib/openc3/utilities/target_file.rb +43 -32
- data/lib/openc3/version.rb +6 -6
- data/templates/conversion/conversion.rb +43 -0
- data/templates/limits_response/response.rb +51 -0
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +62 -0
- data/templates/plugin/plugin.txt +1 -0
- data/templates/{plugin-template → target}/targets/TARGET/screens/status.txt +1 -2
- metadata +23 -16
- data/lib/openc3/models/traefik_model.rb +0 -47
- data/templates/plugin-template/plugin.txt +0 -9
- /data/templates/{plugin-template → plugin}/LICENSE.txt +0 -0
- /data/templates/{plugin-template → plugin}/README.md +0 -0
- /data/templates/{plugin-template → plugin}/Rakefile +0 -0
- /data/templates/{plugin-template → plugin}/plugin.gemspec +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/cmd_tlm/cmd.txt +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/cmd_tlm/tlm.txt +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/lib/target.rb +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/procedures/procedure.rb +0 -0
- /data/templates/{plugin-template → target}/targets/TARGET/target.txt +0 -0
data/lib/openc3/api/cmd_api.rb
CHANGED
@@ -99,6 +99,7 @@ module OpenC3
|
|
99
99
|
# @param interface_name [String] The interface to send the raw binary
|
100
100
|
# @param data [String] The raw binary data
|
101
101
|
def send_raw(interface_name, data, scope: $openc3_scope, token: $openc3_token)
|
102
|
+
interface_name = interface_name.upcase
|
102
103
|
authorize(permission: 'cmd_raw', interface_name: interface_name, scope: scope, token: token)
|
103
104
|
get_interface(interface_name, scope: scope, token: token) # Check to make sure the interface exists
|
104
105
|
InterfaceTopic.write_raw(interface_name, data, scope: scope)
|
@@ -110,6 +111,8 @@ module OpenC3
|
|
110
111
|
# @param command_name [String] Packet name of the command
|
111
112
|
# @return [Hash] command hash with last command buffer
|
112
113
|
def get_cmd_buffer(target_name, command_name, scope: $openc3_scope, token: $openc3_token)
|
114
|
+
target_name = target_name.upcase
|
115
|
+
command_name = command_name.upcase
|
113
116
|
authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
114
117
|
TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
|
115
118
|
topic = "#{scope}__COMMAND__{#{target_name}}__#{command_name}"
|
@@ -127,6 +130,7 @@ module OpenC3
|
|
127
130
|
# @param target_name [String] Name of the target
|
128
131
|
# @return [Array<Hash>] Array of all commands as a hash
|
129
132
|
def get_all_commands(target_name, scope: $openc3_scope, token: $openc3_token)
|
133
|
+
target_name = target_name.upcase
|
130
134
|
authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
|
131
135
|
TargetModel.packets(target_name, type: :CMD, scope: scope)
|
132
136
|
end
|
@@ -137,6 +141,7 @@ module OpenC3
|
|
137
141
|
# @param target_name [String] Name of the target
|
138
142
|
# @return [Array<String>] Array of all command packet names
|
139
143
|
def get_all_command_names(target_name, scope: $openc3_scope, token: $openc3_token)
|
144
|
+
target_name = target_name.upcase
|
140
145
|
authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
|
141
146
|
TargetModel.packet_names(target_name, type: :CMD, scope: scope)
|
142
147
|
end
|
@@ -145,23 +150,28 @@ module OpenC3
|
|
145
150
|
#
|
146
151
|
# @since 5.0.0
|
147
152
|
# @param target_name [String] Name of the target
|
148
|
-
# @param
|
153
|
+
# @param command_name [String] Name of the packet
|
149
154
|
# @return [Hash] Command as a hash
|
150
|
-
def get_command(target_name,
|
155
|
+
def get_command(target_name, command_name, scope: $openc3_scope, token: $openc3_token)
|
156
|
+
target_name = target_name.upcase
|
157
|
+
command_name = command_name.upcase
|
151
158
|
authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
|
152
|
-
TargetModel.packet(target_name,
|
159
|
+
TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
|
153
160
|
end
|
154
161
|
|
155
162
|
# Returns a hash of the given command parameter
|
156
163
|
#
|
157
164
|
# @since 5.0.0
|
158
165
|
# @param target_name [String] Name of the target
|
159
|
-
# @param
|
160
|
-
# @param
|
166
|
+
# @param command_name [String] Name of the packet
|
167
|
+
# @param parameter_name [String] Name of the parameter
|
161
168
|
# @return [Hash] Command parameter as a hash
|
162
|
-
def get_parameter(target_name,
|
163
|
-
|
164
|
-
|
169
|
+
def get_parameter(target_name, command_name, parameter_name, scope: $openc3_scope, token: $openc3_token)
|
170
|
+
target_name = target_name.upcase
|
171
|
+
command_name = command_name.upcase
|
172
|
+
parameter_name = parameter_name.upcase
|
173
|
+
authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
174
|
+
TargetModel.packet_item(target_name, command_name, parameter_name, type: :CMD, scope: scope)
|
165
175
|
end
|
166
176
|
|
167
177
|
# Returns whether the specified command is hazardous
|
@@ -176,35 +186,38 @@ module OpenC3
|
|
176
186
|
extract_string_kwargs_to_args(args, kwargs)
|
177
187
|
case args.length
|
178
188
|
when 1
|
179
|
-
target_name, command_name,
|
189
|
+
target_name, command_name, parameters = extract_fields_from_cmd_text(args[0], scope: scope)
|
180
190
|
when 2, 3
|
181
191
|
target_name = args[0]
|
182
192
|
command_name = args[1]
|
183
193
|
if args.length == 2
|
184
|
-
|
194
|
+
parameters = {}
|
185
195
|
else
|
186
|
-
|
196
|
+
parameters = args[2]
|
187
197
|
end
|
188
198
|
else
|
189
199
|
# Invalid number of arguments
|
190
200
|
raise "ERROR: Invalid number of arguments (#{args.length}) passed to get_cmd_hazardous()"
|
191
201
|
end
|
202
|
+
target_name = target_name.upcase
|
203
|
+
command_name = command_name.upcase
|
204
|
+
parameters = parameters.transform_keys(&:upcase)
|
192
205
|
|
193
206
|
authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
194
207
|
packet = TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
|
195
208
|
return true if packet['hazardous']
|
196
209
|
|
197
210
|
packet['items'].each do |item|
|
198
|
-
next unless
|
211
|
+
next unless parameters.keys.include?(item['name']) && item['states']
|
199
212
|
|
200
213
|
# States are an array of the name followed by a hash of 'value' and sometimes 'hazardous'
|
201
214
|
item['states'].each do |name, hash|
|
202
|
-
|
215
|
+
parameter_name = parameters[item['name']]
|
203
216
|
# Remove quotes from string parameters
|
204
|
-
|
217
|
+
parameter_name = parameter_name.gsub('"', '').gsub("'", '') if parameter_name.is_a?(String)
|
205
218
|
# To be hazardous the state must be marked hazardous
|
206
219
|
# Check if either the state name or value matches the param passed
|
207
|
-
if hash['hazardous'] && (name ==
|
220
|
+
if hash['hazardous'] && (name == parameter_name || hash['value'] == parameter_name)
|
208
221
|
return true
|
209
222
|
end
|
210
223
|
end
|
@@ -222,6 +235,9 @@ module OpenC3
|
|
222
235
|
# one of {Packet::VALUE_TYPES}
|
223
236
|
# @return [Varies] value
|
224
237
|
def get_cmd_value(target_name, command_name, parameter_name, value_type = :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
238
|
+
target_name = target_name.upcase
|
239
|
+
command_name = command_name.upcase
|
240
|
+
parameter_name = parameter_name.upcase
|
225
241
|
authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
226
242
|
CommandDecomTopic.get_cmd_item(target_name, command_name, parameter_name, type: value_type, scope: scope)
|
227
243
|
end
|
@@ -236,12 +252,15 @@ module OpenC3
|
|
236
252
|
def get_cmd_time(target_name = nil, command_name = nil, scope: $openc3_scope, token: $openc3_token)
|
237
253
|
authorize(permission: 'cmd_info', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
238
254
|
if target_name and command_name
|
255
|
+
target_name = target_name.upcase
|
256
|
+
command_name = command_name.upcase
|
239
257
|
time = CommandDecomTopic.get_cmd_item(target_name, command_name, 'RECEIVED_TIMESECONDS', type: :CONVERTED, scope: scope)
|
240
258
|
[target_name, command_name, time.to_i, ((time.to_f - time.to_i) * 1_000_000).to_i]
|
241
259
|
else
|
242
260
|
if target_name.nil?
|
243
261
|
targets = TargetModel.names(scope: scope)
|
244
262
|
else
|
263
|
+
target_name = target_name.upcase
|
245
264
|
targets = [target_name]
|
246
265
|
end
|
247
266
|
targets.each do |target_name|
|
@@ -268,6 +287,8 @@ module OpenC3
|
|
268
287
|
# @param command_name [String] Packet name of the command
|
269
288
|
# @return [Numeric] Transmit count for the command
|
270
289
|
def get_cmd_cnt(target_name, command_name, scope: $openc3_scope, token: $openc3_token)
|
290
|
+
target_name = target_name.upcase
|
291
|
+
command_name = command_name.upcase
|
271
292
|
authorize(permission: 'system', target_name: target_name, packet_name: command_name, scope: scope, token: token)
|
272
293
|
TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
|
273
294
|
Topic.get_cnt("#{scope}__COMMAND__{#{target_name}}__#{command_name}")
|
@@ -281,6 +302,8 @@ module OpenC3
|
|
281
302
|
authorize(permission: 'system', scope: scope, token: token)
|
282
303
|
counts = []
|
283
304
|
target_commands.each do |target_name, command_name|
|
305
|
+
target_name = target_name.upcase
|
306
|
+
command_name = command_name.upcase
|
284
307
|
counts << Topic.get_cnt("#{scope}__COMMAND__{#{target_name}}__#{command_name}")
|
285
308
|
end
|
286
309
|
counts
|
@@ -298,8 +321,8 @@ module OpenC3
|
|
298
321
|
when 1
|
299
322
|
target_name, cmd_name, cmd_params = extract_fields_from_cmd_text(args[0], scope: scope)
|
300
323
|
when 2, 3
|
301
|
-
target_name
|
302
|
-
cmd_name
|
324
|
+
target_name = args[0]
|
325
|
+
cmd_name = args[1]
|
303
326
|
if args.length == 2
|
304
327
|
cmd_params = {}
|
305
328
|
else
|
@@ -309,6 +332,9 @@ module OpenC3
|
|
309
332
|
# Invalid number of arguments
|
310
333
|
raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
|
311
334
|
end
|
335
|
+
target_name = target_name.upcase
|
336
|
+
cmd_name = cmd_name.upcase
|
337
|
+
cmd_params = cmd_params.transform_keys(&:upcase)
|
312
338
|
authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, scope: scope, token: token)
|
313
339
|
packet = TargetModel.packet(target_name, cmd_name, type: :CMD, scope: scope)
|
314
340
|
|
data/lib/openc3/api/tlm_api.rb
CHANGED
@@ -120,11 +120,14 @@ module OpenC3
|
|
120
120
|
def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
121
121
|
authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
122
122
|
type = type.to_s.intern
|
123
|
+
target_name = target_name.upcase
|
124
|
+
packet_name = packet_name.upcase
|
123
125
|
unless CvtModel::VALUE_TYPES.include?(type)
|
124
126
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name}"
|
125
127
|
end
|
126
128
|
|
127
129
|
if item_hash
|
130
|
+
item_hash = item_hash.transform_keys(&:upcase)
|
128
131
|
# Check that the items exist ... exceptions are raised if not
|
129
132
|
TargetModel.packet_items(target_name, packet_name, item_hash.keys, scope: scope)
|
130
133
|
else
|
@@ -201,6 +204,8 @@ module OpenC3
|
|
201
204
|
# @param packet_name [String] Name of the packet
|
202
205
|
# @return [Hash] telemetry hash with last telemetry buffer
|
203
206
|
def get_tlm_buffer(target_name, packet_name, scope: $openc3_scope, token: $openc3_token)
|
207
|
+
target_name = target_name.upcase
|
208
|
+
packet_name = packet_name.upcase
|
204
209
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
205
210
|
TargetModel.packet(target_name, packet_name, scope: scope)
|
206
211
|
topic = "#{scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
|
@@ -222,11 +227,13 @@ module OpenC3
|
|
222
227
|
# of [item name, item value, item limits state] where the item limits
|
223
228
|
# state can be one of {OpenC3::Limits::LIMITS_STATES}
|
224
229
|
def get_tlm_packet(target_name, packet_name, stale_time: 30, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
230
|
+
target_name = target_name.upcase
|
231
|
+
packet_name = packet_name.upcase
|
225
232
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
226
233
|
packet = TargetModel.packet(target_name, packet_name, scope: scope)
|
227
234
|
t = _validate_tlm_type(type)
|
228
235
|
raise ArgumentError, "Unknown type '#{type}' for #{target_name} #{packet_name}" if t.nil?
|
229
|
-
items = packet['items'].map { | item | item['name'] }
|
236
|
+
items = packet['items'].map { | item | item['name'].upcase }
|
230
237
|
cvt_items = items.map { | item | "#{target_name}__#{packet_name}__#{item}__#{type}" }
|
231
238
|
current_values = CvtModel.get_tlm_values(cvt_items, stale_time: stale_time, scope: scope)
|
232
239
|
items.zip(current_values).map { | item , values | [item, values[0], values[1]]}
|
@@ -246,13 +253,18 @@ module OpenC3
|
|
246
253
|
if !items.is_a?(Array) || !items[0].is_a?(String)
|
247
254
|
raise ArgumentError, "items must be array of strings: ['TGT__PKT__ITEM__TYPE', ...]"
|
248
255
|
end
|
249
|
-
|
250
256
|
items.each_with_index do |item, index|
|
251
|
-
target_name, packet_name, item_name,
|
257
|
+
target_name, packet_name, item_name, value_type = item.split('__')
|
258
|
+
raise ArgumentError, "items must be formatted as TGT__PKT__ITEM__TYPE" if target_name.nil? || packet_name.nil? || item_name.nil? || value_type.nil?
|
259
|
+
target_name = target_name.upcase
|
260
|
+
packet_name = packet_name.upcase
|
261
|
+
item_name = item_name.upcase
|
262
|
+
value_type = value_type.upcase
|
252
263
|
if packet_name == 'LATEST'
|
253
264
|
_, packet_name, _ = tlm_process_args([target_name, packet_name, item_name], 'get_tlm_values', scope: scope) # Figure out which packet is LATEST
|
254
|
-
items[index] = "#{target_name}__#{packet_name}__#{item_name}__#{item_type}" # Replace LATEST with the real packet name
|
255
265
|
end
|
266
|
+
# Change packet_name in case of LATEST and ensure upcase
|
267
|
+
items[index] = "#{target_name}__#{packet_name}__#{item_name}__#{value_type}"
|
256
268
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
257
269
|
end
|
258
270
|
CvtModel.get_tlm_values(items, stale_time: stale_time, scope: scope)
|
@@ -264,6 +276,7 @@ module OpenC3
|
|
264
276
|
# @param target_name [String] Name of the target
|
265
277
|
# @return [Array<Hash>] Array of all telemetry packet hashes
|
266
278
|
def get_all_telemetry(target_name, scope: $openc3_scope, token: $openc3_token)
|
279
|
+
target_name = target_name.upcase
|
267
280
|
authorize(permission: 'tlm', target_name: target_name, scope: scope, token: token)
|
268
281
|
TargetModel.packets(target_name, type: :TLM, scope: scope)
|
269
282
|
end
|
@@ -274,6 +287,7 @@ module OpenC3
|
|
274
287
|
# @param target_name [String] Name of the target
|
275
288
|
# @return [Array<String>] Array of all telemetry packet names
|
276
289
|
def get_all_telemetry_names(target_name, scope: $openc3_scope, token: $openc3_token)
|
290
|
+
target_name = target_name.upcase
|
277
291
|
authorize(permission: 'cmd_info', target_name: target_name, scope: scope, token: token)
|
278
292
|
TargetModel.packet_names(target_name, type: :TLM, scope: scope)
|
279
293
|
end
|
@@ -285,6 +299,8 @@ module OpenC3
|
|
285
299
|
# @param packet_name [String] Name of the packet
|
286
300
|
# @return [Hash] Telemetry packet hash
|
287
301
|
def get_telemetry(target_name, packet_name, scope: $openc3_scope, token: $openc3_token)
|
302
|
+
target_name = target_name.upcase
|
303
|
+
packet_name = packet_name.upcase
|
288
304
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
289
305
|
TargetModel.packet(target_name, packet_name, scope: scope)
|
290
306
|
end
|
@@ -297,6 +313,9 @@ module OpenC3
|
|
297
313
|
# @param item_name [String] Name of the packet
|
298
314
|
# @return [Hash] Telemetry packet item hash
|
299
315
|
def get_item(target_name, packet_name, item_name, scope: $openc3_scope, token: $openc3_token)
|
316
|
+
target_name = target_name.upcase
|
317
|
+
packet_name = packet_name.upcase
|
318
|
+
item_name = item_name.upcase
|
300
319
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
301
320
|
TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
302
321
|
end
|
@@ -316,6 +335,8 @@ module OpenC3
|
|
316
335
|
|
317
336
|
result = {}
|
318
337
|
packets.each do |target_name, packet_name|
|
338
|
+
target_name = target_name.upcase
|
339
|
+
packet_name = packet_name.upcase
|
319
340
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
320
341
|
topic = "#{scope}__DECOM__{#{target_name}}__#{packet_name}"
|
321
342
|
id, _ = Topic.get_newest_message(topic)
|
@@ -356,6 +377,8 @@ module OpenC3
|
|
356
377
|
# @param packet_name [String] Name of the packet
|
357
378
|
# @return [Numeric] Receive count for the telemetry packet
|
358
379
|
def get_tlm_cnt(target_name, packet_name, scope: $openc3_scope, token: $openc3_token)
|
380
|
+
target_name = target_name.upcase
|
381
|
+
packet_name = packet_name.upcase
|
359
382
|
authorize(permission: 'system', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
360
383
|
TargetModel.packet(target_name, packet_name, scope: scope)
|
361
384
|
Topic.get_cnt("#{scope}__TELEMETRY__{#{target_name}}__#{packet_name}")
|
@@ -369,6 +392,8 @@ module OpenC3
|
|
369
392
|
authorize(permission: 'system', scope: scope, token: token)
|
370
393
|
counts = []
|
371
394
|
target_packets.each do |target_name, packet_name|
|
395
|
+
target_name = target_name.upcase
|
396
|
+
packet_name = packet_name.upcase
|
372
397
|
counts << Topic.get_cnt("#{scope}__TELEMETRY__{#{target_name}}__#{packet_name}")
|
373
398
|
end
|
374
399
|
counts
|
@@ -380,6 +405,8 @@ module OpenC3
|
|
380
405
|
# @param packet_name [String] Packet name
|
381
406
|
# @return [Array<String>] All of the ignored telemetry items for a packet.
|
382
407
|
def get_packet_derived_items(target_name, packet_name, scope: $openc3_scope, token: $openc3_token)
|
408
|
+
target_name = target_name.upcase
|
409
|
+
packet_name = packet_name.upcase
|
383
410
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
384
411
|
packet = TargetModel.packet(target_name, packet_name, scope: scope)
|
385
412
|
return packet['items'].select { |item| item['data_type'] == 'DERIVED' }.map { |item| item['name'] }
|
@@ -413,6 +440,9 @@ module OpenC3
|
|
413
440
|
# Invalid number of arguments
|
414
441
|
raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
|
415
442
|
end
|
443
|
+
target_name = target_name.upcase
|
444
|
+
packet_name = packet_name.upcase
|
445
|
+
item_name = item_name.upcase
|
416
446
|
if packet_name == 'LATEST'
|
417
447
|
latest = -1
|
418
448
|
TargetModel.packets(target_name, scope: scope).each do |packet|
|
@@ -449,6 +479,9 @@ module OpenC3
|
|
449
479
|
# Invalid number of arguments
|
450
480
|
raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
|
451
481
|
end
|
482
|
+
target_name = target_name.upcase
|
483
|
+
packet_name = packet_name.upcase
|
484
|
+
item_name = item_name.upcase
|
452
485
|
# Determine if this item exists, it will raise appropriate errors if not
|
453
486
|
TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
454
487
|
|
data/lib/openc3/bridge/bridge.rb
CHANGED
@@ -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'
|
@@ -27,8 +27,8 @@ require 'openc3/bridge/bridge_router_thread'
|
|
27
27
|
|
28
28
|
module OpenC3
|
29
29
|
class Bridge
|
30
|
-
def initialize(filename)
|
31
|
-
@config = BridgeConfig.new(filename)
|
30
|
+
def initialize(filename, existing_variables = {})
|
31
|
+
@config = BridgeConfig.new(filename, existing_variables)
|
32
32
|
@threads = []
|
33
33
|
|
34
34
|
# Start Interface Threads
|
@@ -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/utilities/logger'
|
@@ -30,28 +30,55 @@ module OpenC3
|
|
30
30
|
# @return [Hash<String, Interface>] Routers hash
|
31
31
|
attr_accessor :routers
|
32
32
|
|
33
|
-
def initialize(filename)
|
33
|
+
def initialize(filename, existing_variables = {})
|
34
34
|
@interfaces = {}
|
35
35
|
@routers = {}
|
36
|
-
process_file(filename)
|
36
|
+
process_file(filename, existing_variables)
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.generate_default(filename)
|
40
40
|
default_config = <<~EOF
|
41
|
-
|
42
|
-
|
43
|
-
# INTERFACE <Interface Name> <Interface File> <Interface Params...>
|
44
|
-
# INTERFACE <Interface Name> serial_interface.rb <Write Port> <Read Port> <Baud Rate> <Parity ODD/EVEN/NONE> <Stop Bits> <Write Timeout> <Read Timeout> <Protocol Name> <Protocol Params>
|
45
|
-
# INTERFACE <Interface Name> serial_interface.rb <Write Port> <Read Port> <Baud Rate> <Parity ODD/EVEN/NONE> <Stop Bits> <Write Timeout> <Read Timeout> BURST <Discard Leading Bytes> <Sync Pattern> <Add Sync On Write>
|
46
|
-
# INTERFACE SERIAL_INT serial_interface.rb /dev/ttyS1 /dev/ttyS1 38400 ODD 1 10.0 nil BURST 4 0xDEADBEEF
|
47
|
-
INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 9600 NONE 1 10.0 nil BURST
|
41
|
+
# Write serial port name
|
42
|
+
VARIABLE write_port_name COM1
|
48
43
|
#{' '}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
# Read serial port name
|
45
|
+
VARIABLE read_port_name COM1
|
46
|
+
#{' '}
|
47
|
+
# Baud Rate
|
48
|
+
VARIABLE baud_rate 115200
|
49
|
+
#{' '}
|
50
|
+
# Parity - NONE, ODD, or EVEN
|
51
|
+
VARIABLE parity NONE
|
52
|
+
#{' '}
|
53
|
+
# Stop bits - 0, 1, or 2
|
54
|
+
VARIABLE stop_bits 1
|
55
|
+
#{' '}
|
56
|
+
# Write Timeout
|
57
|
+
VARIABLE write_timeout 10.0
|
58
|
+
#{' '}
|
59
|
+
# Read Timeout
|
60
|
+
VARIABLE read_timeout nil
|
61
|
+
#{' '}
|
62
|
+
# Flow Control - NONE, or RTSCTS
|
63
|
+
VARIABLE flow_control NONE
|
64
|
+
#{' '}
|
65
|
+
# Data bits per word - Typically 8
|
66
|
+
VARIABLE data_bits 8
|
67
|
+
#{' '}
|
68
|
+
# Port to listen for connections from COSMOS - Plugin must match
|
69
|
+
VARIABLE router_port 2950
|
70
|
+
#{' '}
|
71
|
+
# Port to listen on for connections from COSMOS. Defaults to localhost for security. Will need to be opened
|
72
|
+
# if COSMOS is on another machine.
|
73
|
+
VARIABLE router_listen_address 127.0.0.1
|
74
|
+
#{' '}
|
75
|
+
INTERFACE SERIAL_INT serial_interface.rb <%= write_port_name %> <%= read_port_name %> <%= baud_rate %> <%= parity %> <%= stop_bits %> <%= write_timeout %> <%= read_timeout %>
|
76
|
+
OPTION FLOW_CONTROL <%= flow_control %>
|
77
|
+
OPTION DATA_BITS <%= data_bits %>
|
78
|
+
#{' '}
|
79
|
+
ROUTER SERIAL_ROUTER tcpip_server_interface.rb <%= router_port %> <%= router_port %> 10.0 nil BURST
|
80
|
+
ROUTE SERIAL_INT
|
81
|
+
OPTION LISTEN_ADDRESS <%= router_listen_address %>
|
55
82
|
#{' '}
|
56
83
|
EOF
|
57
84
|
|
@@ -66,18 +93,39 @@ module OpenC3
|
|
66
93
|
# Processes a file and adds in the configuration defined in the file
|
67
94
|
#
|
68
95
|
# @param filename [String] The name of the configuration file to parse
|
69
|
-
|
70
|
-
# recursively
|
71
|
-
def process_file(filename, recursive = false)
|
96
|
+
def process_file(filename, existing_variables = {})
|
72
97
|
current_interface_or_router = nil
|
73
98
|
current_type = nil
|
74
99
|
current_interface_log_added = false
|
75
100
|
|
76
101
|
Logger.info "Processing Bridge configuration in file: #{File.expand_path(filename)}"
|
77
102
|
|
103
|
+
variables = {}
|
78
104
|
parser = ConfigParser.new
|
79
|
-
parser.parse_file(filename
|
105
|
+
parser.parse_file(filename,
|
106
|
+
false,
|
107
|
+
true,
|
108
|
+
false) do |keyword, params|
|
80
109
|
case keyword
|
110
|
+
when 'VARIABLE'
|
111
|
+
usage = "#{keyword} <Variable Name> <Default Value>"
|
112
|
+
parser.verify_num_parameters(2, nil, usage)
|
113
|
+
variable_name = params[0]
|
114
|
+
value = params[1..-1].join(" ")
|
115
|
+
variables[variable_name] = value
|
116
|
+
if existing_variables && existing_variables.key?(variable_name)
|
117
|
+
variables[variable_name] = existing_variables[variable_name]
|
118
|
+
end
|
119
|
+
# Ignore everything else during phase 1
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
parser = ConfigParser.new
|
124
|
+
parser.parse_file(filename, false, true, true, variables) do |keyword, params|
|
125
|
+
case keyword
|
126
|
+
|
127
|
+
when 'VARIABLE'
|
128
|
+
# Ignore during this pass
|
81
129
|
|
82
130
|
when 'INTERFACE'
|
83
131
|
usage = "INTERFACE <Name> <Filename> <Specific Parameters>"
|
@@ -25,6 +25,11 @@ require 'openc3/io/raw_logger_pair'
|
|
25
25
|
require 'openc3/utilities/secrets'
|
26
26
|
|
27
27
|
module OpenC3
|
28
|
+
# Define a class to allow interfaces and protocols to reject commands without
|
29
|
+
# disconnecting the interface
|
30
|
+
class WriteRejectError < StandardError
|
31
|
+
end
|
32
|
+
|
28
33
|
# Defines all the attributes and methods common to all interface classes
|
29
34
|
# used by OpenC3.
|
30
35
|
class Interface
|
@@ -330,6 +335,9 @@ module OpenC3
|
|
330
335
|
else
|
331
336
|
@write_mutex.synchronize { yield }
|
332
337
|
end
|
338
|
+
rescue WriteRejectError => err
|
339
|
+
Logger.error("#{@name}: Write rejected by interface: #{err.message}")
|
340
|
+
raise err
|
333
341
|
rescue Exception => err
|
334
342
|
Logger.error("#{@name}: Error writing to interface")
|
335
343
|
disconnect()
|
@@ -95,7 +95,6 @@ module OpenC3
|
|
95
95
|
# @param log_change [Boolean] Whether to log this limits change event
|
96
96
|
def limits_change_callback(packet, item, old_limits_state, value, log_change)
|
97
97
|
return if @cancel_thread
|
98
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
99
98
|
packet_time = packet.packet_time
|
100
99
|
message = "#{packet.target_name} #{packet.packet_name} #{item.name} = #{value} is #{item.limits.state}"
|
101
100
|
message << " (#{packet.packet_time.sys.formatted})" if packet_time
|
@@ -136,8 +135,6 @@ module OpenC3
|
|
136
135
|
@logger.error e.formatted
|
137
136
|
end
|
138
137
|
end
|
139
|
-
|
140
|
-
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
141
138
|
end
|
142
139
|
end
|
143
140
|
end
|
@@ -264,7 +264,6 @@ module OpenC3
|
|
264
264
|
when 'trigger'
|
265
265
|
process_enabled_trigger(data: data)
|
266
266
|
end
|
267
|
-
current_time = Time.now.to_i
|
268
267
|
rescue StandardError => e
|
269
268
|
@logger.error "ReactionWorker-#{@ident} failed to evaluate kind: #{kind} data: #{data}\n#{e.formatted}"
|
270
269
|
end
|
@@ -240,11 +240,10 @@ module OpenC3
|
|
240
240
|
# return an ordered array of hash with keys
|
241
241
|
def self._parse_item(lookups, overrides, item, scope:)
|
242
242
|
target_name, packet_name, item_name, value_type = item.split('__')
|
243
|
-
raise ArgumentError, "items must be formatted as TGT__PKT__ITEM__TYPE" if target_name.nil? || packet_name.nil? || item_name.nil? || value_type.nil?
|
244
243
|
|
245
244
|
# We build lookup keys by including all the less formatted types to gracefully degrade lookups
|
246
245
|
# This allows the user to specify WITH_UNITS and if there is no conversions it will simply return the RAW value
|
247
|
-
case value_type
|
246
|
+
case value_type
|
248
247
|
when 'RAW'
|
249
248
|
keys = [item_name]
|
250
249
|
when 'CONVERTED'
|
@@ -257,12 +257,15 @@ module OpenC3
|
|
257
257
|
@log_raw = true
|
258
258
|
|
259
259
|
when 'SECRET'
|
260
|
-
parser.verify_num_parameters(3,
|
260
|
+
parser.verify_num_parameters(3, 5, "#{keyword} <Secret Type: ENV or FILE> <Secret Name> <Environment Variable Name or File Path> <Option Name (Optional)> <Secret Store Name (Optional)>")
|
261
261
|
@secrets << parameters[0..2]
|
262
|
-
if parameters[3]
|
262
|
+
if ConfigParser.handle_nil(parameters[3])
|
263
263
|
# Option Name, Secret Name
|
264
264
|
@secret_options << [parameters[3], parameters[1]]
|
265
265
|
end
|
266
|
+
if ConfigParser.handle_nil(parameters[4])
|
267
|
+
@secrets[-1] << parameters[4]
|
268
|
+
end
|
266
269
|
|
267
270
|
else
|
268
271
|
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Interface/Router: #{keyword} #{parameters.join(" ")}")
|
@@ -69,7 +69,7 @@ module OpenC3
|
|
69
69
|
if @color.nil?
|
70
70
|
@color = '#%06x' % (rand * 0xffffff)
|
71
71
|
end
|
72
|
-
unless @color =~ /(#*)([0-
|
72
|
+
unless @color =~ /(#*)([0-9a-fA-F]{6})/
|
73
73
|
raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
|
74
74
|
end
|
75
75
|
@color = "##{@color}" unless @color.start_with?('#')
|
@@ -23,7 +23,6 @@
|
|
23
23
|
require 'openc3/top_level'
|
24
24
|
require 'openc3/models/model'
|
25
25
|
require 'openc3/models/metric_model'
|
26
|
-
require 'openc3/models/traefik_model'
|
27
26
|
require 'openc3/utilities/bucket'
|
28
27
|
|
29
28
|
module OpenC3
|
@@ -163,7 +162,7 @@ module OpenC3
|
|
163
162
|
parser.verify_num_parameters(1, 2, usage)
|
164
163
|
begin
|
165
164
|
@ports << [Integer(parameters[0])]
|
166
|
-
rescue
|
165
|
+
rescue # In case Integer fails
|
167
166
|
raise ConfigParser::Error.new(parser, "Port must be an integer: #{parameters[0]}", usage)
|
168
167
|
end
|
169
168
|
protocol = ConfigParser.handle_nil(parameters[1])
|
@@ -193,8 +192,12 @@ module OpenC3
|
|
193
192
|
parser.verify_num_parameters(1, 1, "#{keyword} <Container Image Name>")
|
194
193
|
@container = parameters[0]
|
195
194
|
when 'SECRET'
|
196
|
-
parser.verify_num_parameters(3,
|
197
|
-
|
195
|
+
parser.verify_num_parameters(3, 4, "#{keyword} <Secret Type: ENV or FILE> <Secret Name> <Environment Variable Name or File Path> <Secret Store Name (Optional)>")
|
196
|
+
if ConfigParser.handle_nil(parameters[3])
|
197
|
+
@secrets << parameters.dup
|
198
|
+
else
|
199
|
+
@secrets << parameters[0..2]
|
200
|
+
end
|
198
201
|
when 'ROUTE_PREFIX'
|
199
202
|
parser.verify_num_parameters(1, 1, "#{keyword} <Route Prefix>")
|
200
203
|
@prefix = parameters[0]
|
@@ -225,7 +228,6 @@ module OpenC3
|
|
225
228
|
end
|
226
229
|
end
|
227
230
|
unless validate_only
|
228
|
-
TraefikModel.register_route(microservice_name: @name, port: @ports[0][0], prefix: @prefix) if @ports[0] and ports[0][0] and @prefix
|
229
231
|
ConfigTopic.write({ kind: 'created', type: 'microservice', name: @name, plugin: @plugin }, scope: @scope)
|
230
232
|
end
|
231
233
|
end
|
@@ -235,7 +237,6 @@ module OpenC3
|
|
235
237
|
@bucket.list_objects(bucket: ENV['OPENC3_CONFIG_BUCKET'], prefix: prefix).each do |object|
|
236
238
|
@bucket.delete_object(bucket: ENV['OPENC3_CONFIG_BUCKET'], key: object.key)
|
237
239
|
end
|
238
|
-
TraefikModel.unregister_route(microservice_name: @name, port: @ports[0][0], prefix: @prefix) if @ports[0] and ports[0][0] and @prefix
|
239
240
|
ConfigTopic.write({ kind: 'deleted', type: 'microservice', name: @name, plugin: @plugin }, scope: @scope)
|
240
241
|
rescue Exception => error
|
241
242
|
Logger.error("Error undeploying microservice model #{@name} in scope #{@scope} due to #{error}")
|
@@ -78,7 +78,7 @@ module OpenC3
|
|
78
78
|
if @color.nil?
|
79
79
|
@color = '#%06x' % (rand * 0xffffff)
|
80
80
|
end
|
81
|
-
unless @color =~ /(#*)([0-
|
81
|
+
unless @color =~ /(#*)([0-9a-fA-F]{6})/
|
82
82
|
raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
|
83
83
|
end
|
84
84
|
@color = "##{@color}" unless @color.start_with?('#')
|