openc3 5.1.1 → 5.2.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.
- checksums.yaml +4 -4
- data/bin/openc3cli +48 -9
- data/data/config/interface_modifiers.yaml +14 -0
- data/data/config/parameter_modifiers.yaml +5 -3
- data/data/config/screen.yaml +12 -8
- data/data/config/target.yaml +33 -0
- data/ext/openc3/ext/config_parser/config_parser.c +66 -63
- data/ext/openc3/ext/packet/packet.c +1 -4
- data/lib/openc3/api/README.md +5 -0
- data/lib/openc3/api/api.rb +3 -1
- data/lib/openc3/api/cmd_api.rb +43 -112
- data/lib/openc3/api/interface_api.rb +3 -3
- data/lib/openc3/api/offline_access_api.rb +78 -0
- data/lib/openc3/api/settings_api.rb +3 -1
- data/lib/openc3/api/stash_api.rb +63 -0
- data/lib/openc3/api/target_api.rb +4 -5
- data/lib/openc3/config/config_parser.rb +47 -47
- data/lib/openc3/interfaces/interface.rb +11 -1
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +30 -16
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +8 -2
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +2 -2
- data/lib/openc3/interfaces/protocols/override_protocol.rb +2 -2
- data/lib/openc3/interfaces/tcpip_server_interface.rb +3 -1
- data/lib/openc3/io/json_api_object.rb +30 -9
- data/lib/openc3/io/json_drb.rb +6 -1
- data/lib/openc3/io/json_drb_object.rb +18 -9
- data/lib/openc3/io/json_rpc.rb +5 -3
- data/lib/openc3/logs/buffered_packet_log_writer.rb +1 -1
- data/lib/openc3/logs/log_writer.rb +8 -2
- data/lib/openc3/microservices/cleanup_microservice.rb +3 -3
- data/lib/openc3/microservices/decom_microservice.rb +8 -8
- data/lib/openc3/microservices/interface_microservice.rb +86 -71
- data/lib/openc3/microservices/log_microservice.rb +5 -3
- data/lib/openc3/microservices/microservice.rb +18 -14
- data/lib/openc3/microservices/multi_microservice.rb +62 -0
- data/lib/openc3/microservices/periodic_microservice.rb +58 -0
- data/lib/openc3/microservices/reaction_microservice.rb +61 -47
- data/lib/openc3/microservices/reducer_microservice.rb +64 -40
- data/lib/openc3/microservices/router_microservice.rb +4 -4
- data/lib/openc3/microservices/text_log_microservice.rb +2 -2
- data/lib/openc3/microservices/timeline_microservice.rb +44 -30
- data/lib/openc3/microservices/trigger_group_microservice.rb +39 -36
- data/lib/openc3/migrations/20221202214600_add_target_names.rb +30 -0
- data/lib/openc3/migrations/20221210174900_convert_to_multi.rb +65 -0
- data/lib/openc3/models/cvt_model.rb +1 -1
- data/lib/openc3/models/gem_model.rb +24 -20
- data/lib/openc3/models/interface_model.rb +69 -35
- data/lib/openc3/models/metadata_model.rb +1 -1
- data/lib/openc3/models/microservice_model.rb +7 -24
- data/lib/openc3/models/migration_model.rb +52 -0
- data/lib/openc3/models/model.rb +2 -7
- data/lib/openc3/models/note_model.rb +1 -1
- data/lib/openc3/models/offline_access_model.rb +55 -0
- data/lib/openc3/models/plugin_model.rb +12 -3
- data/lib/openc3/models/reaction_model.rb +6 -2
- data/lib/openc3/models/scope_model.rb +89 -13
- data/lib/openc3/models/settings_model.rb +1 -1
- data/lib/openc3/models/stash_model.rb +53 -0
- data/lib/openc3/models/target_model.rb +301 -130
- data/lib/openc3/models/tool_model.rb +1 -12
- data/lib/openc3/models/widget_model.rb +1 -6
- data/lib/openc3/operators/microservice_operator.rb +45 -6
- data/lib/openc3/operators/operator.rb +27 -5
- data/lib/openc3/packets/commands.rb +1 -25
- data/lib/openc3/packets/limits.rb +0 -75
- data/lib/openc3/packets/packet.rb +0 -28
- data/lib/openc3/packets/packet_item.rb +23 -0
- data/lib/openc3/packets/packet_item_limits.rb +2 -2
- data/lib/openc3/packets/parsers/state_parser.rb +10 -6
- data/lib/openc3/packets/telemetry.rb +1 -45
- data/lib/openc3/script/commands.rb +41 -71
- data/lib/openc3/script/extract.rb +15 -1
- data/lib/openc3/script/{calendar.rb → metadata.rb} +42 -17
- data/lib/openc3/script/script.rb +13 -5
- data/lib/openc3/script/storage.rb +3 -1
- data/lib/openc3/system/system.rb +19 -17
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +4 -4
- data/lib/openc3/top_level.rb +3 -3
- data/lib/openc3/topics/command_decom_topic.rb +2 -2
- data/lib/openc3/topics/command_topic.rb +7 -6
- data/lib/openc3/topics/interface_topic.rb +2 -2
- data/lib/openc3/topics/router_topic.rb +1 -1
- data/lib/openc3/topics/telemetry_topic.rb +2 -1
- data/lib/openc3/utilities/authentication.rb +35 -14
- data/lib/openc3/utilities/aws_bucket.rb +4 -3
- data/lib/openc3/utilities/bucket.rb +4 -2
- data/lib/openc3/utilities/bucket_file_cache.rb +3 -8
- data/lib/openc3/utilities/bucket_utilities.rb +77 -15
- data/lib/openc3/utilities/local_mode.rb +12 -9
- data/lib/openc3/utilities/logger.rb +17 -9
- data/lib/openc3/utilities/message_log.rb +6 -5
- data/lib/openc3/utilities/migration.rb +22 -0
- data/lib/openc3/utilities/store_autoload.rb +7 -5
- data/lib/openc3/utilities/target_file.rb +9 -7
- data/lib/openc3/version.rb +6 -6
- data/lib/openc3.rb +2 -1
- metadata +14 -3
data/lib/openc3/api/cmd_api.rb
CHANGED
|
@@ -17,12 +17,13 @@
|
|
|
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/models/target_model'
|
|
24
24
|
require 'openc3/topics/command_topic'
|
|
25
25
|
require 'openc3/topics/interface_topic'
|
|
26
|
+
require 'openc3/script/extract'
|
|
26
27
|
|
|
27
28
|
module OpenC3
|
|
28
29
|
module Api
|
|
@@ -49,134 +50,48 @@ module OpenC3
|
|
|
49
50
|
'get_cmd_cnts',
|
|
50
51
|
])
|
|
51
52
|
|
|
52
|
-
#
|
|
53
|
+
# The following methods send a command packet to a target. The 'raw' version of the equivalent
|
|
54
|
+
# command methods do not perform command parameter conversions.
|
|
53
55
|
#
|
|
54
56
|
# Accepts two different calling styles:
|
|
55
57
|
# cmd("TGT CMD with PARAM1 val, PARAM2 val")
|
|
56
58
|
# cmd('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
57
59
|
#
|
|
58
60
|
# Favor the first syntax where possible as it is more succinct.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def
|
|
63
|
-
args
|
|
64
|
-
cmd_implementation(true, true, false, 'cmd', *args, scope: scope, token: token)
|
|
61
|
+
def cmd(*args, **kwargs)
|
|
62
|
+
cmd_implementation('cmd', *args, range_check: true, hazardous_check: true, raw: false, **kwargs)
|
|
63
|
+
end
|
|
64
|
+
def cmd_raw(*args, **kwargs)
|
|
65
|
+
cmd_implementation('cmd_raw', *args, range_check: true, hazardous_check: true, raw: true, **kwargs)
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
# Send a command packet to a target without performing any value range
|
|
68
69
|
# checks on the parameters. Useful for testing to allow sending command
|
|
69
70
|
# parameters outside the allowable range as defined in the configuration.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
76
|
-
#
|
|
77
|
-
# @param (see #cmd)
|
|
78
|
-
# @return (see #cmd)
|
|
79
|
-
def cmd_no_range_check(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
80
|
-
args << kwargs unless kwargs.empty?
|
|
81
|
-
cmd_implementation(false, true, false, 'cmd_no_range_check', *args, scope: scope, token: token)
|
|
71
|
+
def cmd_no_range_check(*args, **kwargs)
|
|
72
|
+
cmd_implementation('cmd_no_range_check', *args, range_check: false, hazardous_check: true, raw: false, **kwargs)
|
|
73
|
+
end
|
|
74
|
+
def cmd_raw_no_range_check(*args, **kwargs)
|
|
75
|
+
cmd_implementation('cmd_raw_no_range_check', *args, range_check: false, hazardous_check: true, raw: true, **kwargs)
|
|
82
76
|
end
|
|
83
77
|
|
|
84
78
|
# Send a command packet to a target without performing any hazardous checks
|
|
85
79
|
# both on the command itself and its parameters. Useful in scripts to
|
|
86
80
|
# prevent popping up warnings to the user.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# cmd_no_hazardous_check("TGT CMD with PARAM1 val, PARAM2 val")
|
|
90
|
-
# cmd_no_hazardous_check('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
91
|
-
#
|
|
92
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
93
|
-
#
|
|
94
|
-
# @param (see #cmd)
|
|
95
|
-
# @return (see #cmd)
|
|
96
|
-
def cmd_no_hazardous_check(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
97
|
-
args << kwargs unless kwargs.empty?
|
|
98
|
-
cmd_implementation(true, false, false, 'cmd_no_hazardous_check', *args, scope: scope, token: token)
|
|
81
|
+
def cmd_no_hazardous_check(*args, **kwargs)
|
|
82
|
+
cmd_implementation('cmd_no_hazardous_check', *args, range_check: true, hazardous_check: false, raw: false, **kwargs)
|
|
99
83
|
end
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
# checks or hazardous checks both on the command itself and its parameters.
|
|
103
|
-
#
|
|
104
|
-
# Accepts two different calling styles:
|
|
105
|
-
# cmd_no_checks("TGT CMD with PARAM1 val, PARAM2 val")
|
|
106
|
-
# cmd_no_checks('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
107
|
-
#
|
|
108
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
109
|
-
#
|
|
110
|
-
# @param (see #cmd)
|
|
111
|
-
# @return (see #cmd)
|
|
112
|
-
def cmd_no_checks(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
113
|
-
args << kwargs unless kwargs.empty?
|
|
114
|
-
cmd_implementation(false, false, false, 'cmd_no_checks', *args, scope: scope, token: token)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Send a command packet to a target without running conversions.
|
|
118
|
-
#
|
|
119
|
-
# Accepts two different calling styles:
|
|
120
|
-
# cmd_raw("TGT CMD with PARAM1 val, PARAM2 val")
|
|
121
|
-
# cmd_raw('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
122
|
-
#
|
|
123
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
124
|
-
#
|
|
125
|
-
# @param args [String|Array<String>] See the description for calling style
|
|
126
|
-
# @return [Array<String, String, Hash>] target_name, command_name, parameters
|
|
127
|
-
def cmd_raw(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
128
|
-
args << kwargs unless kwargs.empty?
|
|
129
|
-
cmd_implementation(true, true, true, 'cmd_raw', *args, scope: scope, token: token)
|
|
84
|
+
def cmd_raw_no_hazardous_check(*args, **kwargs)
|
|
85
|
+
cmd_implementation('cmd_raw_no_hazardous_check', *args, range_check: true, hazardous_check: false, raw: true, **kwargs)
|
|
130
86
|
end
|
|
131
87
|
|
|
132
88
|
# Send a command packet to a target without performing any value range
|
|
133
|
-
# checks on the parameters or running conversions. Useful for testing to allow sending command
|
|
134
|
-
# parameters outside the allowable range as defined in the configuration.
|
|
135
|
-
#
|
|
136
|
-
# Accepts two different calling styles:
|
|
137
|
-
# cmd_raw_no_range_check("TGT CMD with PARAM1 val, PARAM2 val")
|
|
138
|
-
# cmd_raw_no_range_check('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
139
|
-
#
|
|
140
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
141
|
-
#
|
|
142
|
-
# @param (see #cmd)
|
|
143
|
-
# @return (see #cmd)
|
|
144
|
-
def cmd_raw_no_range_check(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
145
|
-
args << kwargs unless kwargs.empty?
|
|
146
|
-
cmd_implementation(false, true, true, 'cmd_raw_no_range_check', *args, scope: scope, token: token)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Send a command packet to a target without running conversions or performing any hazardous checks
|
|
150
|
-
# both on the command itself and its parameters. Useful in scripts to
|
|
151
|
-
# prevent popping up warnings to the user.
|
|
152
|
-
#
|
|
153
|
-
# Accepts two different calling styles:
|
|
154
|
-
# cmd_raw_no_hazardous_check("TGT CMD with PARAM1 val, PARAM2 val")
|
|
155
|
-
# cmd_raw_no_hazardous_check('TGT','CMD','PARAM1'=>val,'PARAM2'=>val)
|
|
156
|
-
#
|
|
157
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
158
|
-
#
|
|
159
|
-
# @param (see #cmd)
|
|
160
|
-
# @return (see #cmd)
|
|
161
|
-
def cmd_raw_no_hazardous_check(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
162
|
-
args << kwargs unless kwargs.empty?
|
|
163
|
-
cmd_implementation(true, false, true, 'cmd_raw_no_hazardous_check', *args, scope: scope, token: token)
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Send a command packet to a target without running conversions or performing any value range
|
|
167
89
|
# checks or hazardous checks both on the command itself and its parameters.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
# Favor the first syntax where possible as it is more succinct.
|
|
174
|
-
#
|
|
175
|
-
# @param (see #cmd)
|
|
176
|
-
# @return (see #cmd)
|
|
177
|
-
def cmd_raw_no_checks(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
178
|
-
args << kwargs unless kwargs.empty?
|
|
179
|
-
cmd_implementation(false, false, true, 'cmd_raw_no_checks', *args, scope: scope, token: token)
|
|
90
|
+
def cmd_no_checks(*args, **kwargs)
|
|
91
|
+
cmd_implementation('cmd_no_checks', *args, range_check: false, hazardous_check: false, raw: false, **kwargs)
|
|
92
|
+
end
|
|
93
|
+
def cmd_raw_no_checks(*args, **kwargs)
|
|
94
|
+
cmd_implementation('cmd_raw_no_checks', *args, range_check: false, hazardous_check: false, raw: true, **kwargs)
|
|
180
95
|
end
|
|
181
96
|
|
|
182
97
|
# Send a raw binary string to the specified interface.
|
|
@@ -258,7 +173,7 @@ module OpenC3
|
|
|
258
173
|
# @param args [String|Array<String>] See the description for calling style
|
|
259
174
|
# @return [Boolean] Whether the command is hazardous
|
|
260
175
|
def get_cmd_hazardous(*args, scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
261
|
-
args
|
|
176
|
+
extract_string_kwargs_to_args(args, kwargs)
|
|
262
177
|
case args.length
|
|
263
178
|
when 1
|
|
264
179
|
target_name, command_name, params = extract_fields_from_cmd_text(args[0], scope: scope)
|
|
@@ -375,7 +290,10 @@ module OpenC3
|
|
|
375
290
|
# PRIVATE implementation details
|
|
376
291
|
###########################################################################
|
|
377
292
|
|
|
378
|
-
def cmd_implementation(
|
|
293
|
+
def cmd_implementation(method_name, *args, range_check:, hazardous_check:, raw:, timeout: nil,
|
|
294
|
+
scope: $openc3_scope, token: $openc3_token, **kwargs)
|
|
295
|
+
extract_string_kwargs_to_args(args, kwargs)
|
|
296
|
+
|
|
379
297
|
case args.length
|
|
380
298
|
when 1
|
|
381
299
|
target_name, cmd_name, cmd_params = extract_fields_from_cmd_text(args[0], scope: scope)
|
|
@@ -402,8 +320,21 @@ module OpenC3
|
|
|
402
320
|
'hazardous_check' => hazardous_check.to_s,
|
|
403
321
|
'raw' => raw.to_s
|
|
404
322
|
}
|
|
405
|
-
|
|
406
|
-
|
|
323
|
+
log_cmd = true
|
|
324
|
+
if packet["messages_disabled"]
|
|
325
|
+
log_cmd = false
|
|
326
|
+
else
|
|
327
|
+
cmd_params.each do |key, value|
|
|
328
|
+
item = packet['items'].find { |item| item['name'] == key.to_s }
|
|
329
|
+
if item['states'] && item['states'][value] && item['states'][value]["messages_disabled"]
|
|
330
|
+
log_cmd = false
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
if log_cmd
|
|
335
|
+
Logger.info(build_cmd_output_string(target_name, cmd_name, cmd_params, packet, raw), scope: scope)
|
|
336
|
+
end
|
|
337
|
+
CommandTopic.send_command(command, timeout: timeout, scope: scope)
|
|
407
338
|
end
|
|
408
339
|
|
|
409
340
|
def build_cmd_output_string(target_name, cmd_name, cmd_params, packet, raw)
|
|
@@ -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/models/interface_model'
|
|
@@ -125,7 +125,7 @@ module OpenC3
|
|
|
125
125
|
#
|
|
126
126
|
# @param target_name [String/Array] The name of the target(s)
|
|
127
127
|
# @param interface_name (see #connect_interface)
|
|
128
|
-
def map_target_to_interface(target_name, interface_name, scope: $openc3_scope, token: $openc3_token)
|
|
128
|
+
def map_target_to_interface(target_name, interface_name, cmd_only: false, tlm_only: false, unmap_old: true, scope: $openc3_scope, token: $openc3_token)
|
|
129
129
|
authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
|
|
130
130
|
new_interface = InterfaceModel.get_model(name: interface_name, scope: scope)
|
|
131
131
|
if Array === target_name
|
|
@@ -134,7 +134,7 @@ module OpenC3
|
|
|
134
134
|
target_names = [target_name]
|
|
135
135
|
end
|
|
136
136
|
target_names.each do |name|
|
|
137
|
-
new_interface.map_target(name)
|
|
137
|
+
new_interface.map_target(name, cmd_only: cmd_only, tlm_only: tlm_only, unmap_old: unmap_old)
|
|
138
138
|
Logger.info("Target #{name} mapped to Interface #{interface_name}", scope: scope)
|
|
139
139
|
end
|
|
140
140
|
nil
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
require 'openc3/models/offline_access_model'
|
|
20
|
+
require 'openc3/utilities/authentication'
|
|
21
|
+
|
|
22
|
+
module OpenC3
|
|
23
|
+
module Api
|
|
24
|
+
WHITELIST ||= []
|
|
25
|
+
WHITELIST.concat([
|
|
26
|
+
'offline_access_needed',
|
|
27
|
+
'set_offline_access'
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
def offline_access_needed(scope: $openc3_scope, token: $openc3_token)
|
|
31
|
+
authorize(permission: 'system', scope: scope, token: token)
|
|
32
|
+
begin
|
|
33
|
+
authorize(permission: 'script_run', scope: scope, token: token)
|
|
34
|
+
rescue
|
|
35
|
+
# Not needed if can't run scripts
|
|
36
|
+
return false
|
|
37
|
+
end
|
|
38
|
+
info = user_info(token)
|
|
39
|
+
if info['roles'].to_s.include?("offline_access")
|
|
40
|
+
username = info['username']
|
|
41
|
+
if username and username != ''
|
|
42
|
+
model = OfflineAccessModel.get_model(name: username, scope: scope)
|
|
43
|
+
if model and model.offline_access_token
|
|
44
|
+
auth = OpenC3KeycloakAuthentication.new(ENV['OPENC3_KEYCLOAK_URL'])
|
|
45
|
+
valid_token = auth.get_token_from_refresh_token(model.offline_access_token)
|
|
46
|
+
if valid_token
|
|
47
|
+
return false
|
|
48
|
+
else
|
|
49
|
+
model.offline_access_token = nil
|
|
50
|
+
model.update
|
|
51
|
+
return true
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
return true
|
|
55
|
+
else
|
|
56
|
+
return false
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def set_offline_access(offline_access_token, scope: $openc3_scope, token: $openc3_token)
|
|
64
|
+
authorize(permission: 'script_run', scope: scope, token: token)
|
|
65
|
+
info = user_info(token)
|
|
66
|
+
username = info['username']
|
|
67
|
+
raise "Invalid username" if not username or username == ''
|
|
68
|
+
model = OfflineAccessModel.get_model(name: username, scope: scope)
|
|
69
|
+
if model
|
|
70
|
+
model.offline_access_token = offline_access_token
|
|
71
|
+
model.update
|
|
72
|
+
else
|
|
73
|
+
model = OfflineAccessModel.new(name: username, offline_access_token: offline_access_token, scope: scope)
|
|
74
|
+
model.create
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -17,9 +17,11 @@
|
|
|
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
|
+
require 'openc3/models/settings_model'
|
|
24
|
+
|
|
23
25
|
module OpenC3
|
|
24
26
|
module Api
|
|
25
27
|
WHITELIST ||= []
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
require 'openc3/models/stash_model'
|
|
20
|
+
|
|
21
|
+
module OpenC3
|
|
22
|
+
module Api
|
|
23
|
+
WHITELIST ||= []
|
|
24
|
+
WHITELIST.concat([
|
|
25
|
+
'stash_set',
|
|
26
|
+
'stash_get',
|
|
27
|
+
'stash_all',
|
|
28
|
+
'stash_keys',
|
|
29
|
+
'stash_delete'
|
|
30
|
+
])
|
|
31
|
+
|
|
32
|
+
def stash_set(key, value, scope: $openc3_scope, token: $openc3_token)
|
|
33
|
+
authorize(permission: 'script_run', scope: scope, token: token)
|
|
34
|
+
StashModel.set( {name: key, value: JSON.generate(value.as_json(:allow_nan => true)) }, scope: scope)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def stash_get(key, scope: $openc3_scope, token: $openc3_token)
|
|
38
|
+
authorize(permission: 'script_view', scope: scope, token: token)
|
|
39
|
+
result = StashModel.get(name: key, scope: scope)
|
|
40
|
+
if result
|
|
41
|
+
JSON.parse(result['value'], :allow_nan => true, :create_additions => true)
|
|
42
|
+
else
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def stash_all(scope: $openc3_scope, token: $openc3_token)
|
|
48
|
+
authorize(permission: 'script_view', scope: scope, token: token)
|
|
49
|
+
StashModel.all(scope: scope).transform_values { |hash| JSON.parse(hash["value"], :allow_nan => true, :create_additions => true) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def stash_keys(scope: $openc3_scope, token: $openc3_token)
|
|
53
|
+
authorize(permission: 'script_view', scope: scope, token: token)
|
|
54
|
+
StashModel.names(scope: scope)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def stash_delete(key, scope: $openc3_scope, token: $openc3_token)
|
|
58
|
+
authorize(permission: 'script_run', scope: scope, token: token)
|
|
59
|
+
model = StashModel.get_model(name: key, scope: scope)
|
|
60
|
+
model.destroy if model
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -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/models/target_model'
|
|
@@ -66,14 +66,13 @@ module OpenC3
|
|
|
66
66
|
packets.each do |packet|
|
|
67
67
|
tlm_cnt += Topic.get_cnt("#{scope}__TELEMETRY__{#{target_name}}__#{packet['packet_name']}")
|
|
68
68
|
end
|
|
69
|
-
|
|
69
|
+
interface_names = []
|
|
70
70
|
InterfaceModel.all(scope: scope).each do |name, interface|
|
|
71
71
|
if interface['target_names'].include? target_name
|
|
72
|
-
|
|
73
|
-
break
|
|
72
|
+
interface_names << interface['name']
|
|
74
73
|
end
|
|
75
74
|
end
|
|
76
|
-
info << [target_name,
|
|
75
|
+
info << [target_name, interface_names.join(","), cmd_cnt, tlm_cnt]
|
|
77
76
|
end
|
|
78
77
|
info
|
|
79
78
|
end
|
|
@@ -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/top_level'
|
|
@@ -449,12 +449,11 @@ module OpenC3
|
|
|
449
449
|
if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
|
|
450
450
|
# Iterates over each line of the io object and yields the keyword and parameters
|
|
451
451
|
def parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx)
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
string_concat = false
|
|
454
453
|
@line_number = 0
|
|
455
454
|
@keyword = nil
|
|
456
455
|
@parameters = []
|
|
457
|
-
@line =
|
|
456
|
+
@line = ''
|
|
458
457
|
|
|
459
458
|
while true
|
|
460
459
|
@line_number += 1
|
|
@@ -470,37 +469,57 @@ module OpenC3
|
|
|
470
469
|
end
|
|
471
470
|
|
|
472
471
|
line.strip!
|
|
473
|
-
|
|
474
|
-
|
|
472
|
+
# Ensure the line length is not 0
|
|
473
|
+
next if line.length == 0
|
|
475
474
|
|
|
476
|
-
if
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
@line = line
|
|
481
|
-
if (first_item.length == 0) || (first_item[0] == '#')
|
|
482
|
-
@keyword = nil
|
|
483
|
-
else
|
|
484
|
-
@keyword = first_item.upcase
|
|
475
|
+
if string_concat
|
|
476
|
+
# Skip comment lines after a string concatenation
|
|
477
|
+
if (line[0] == '#')
|
|
478
|
+
next
|
|
485
479
|
end
|
|
486
|
-
|
|
480
|
+
# Remove the opening quote if we're continuing the line
|
|
481
|
+
line = line[1..-1]
|
|
487
482
|
end
|
|
488
483
|
|
|
489
|
-
#
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
484
|
+
# Check for string continuation
|
|
485
|
+
case line[-1]
|
|
486
|
+
when '+', '\\' # String concatenation
|
|
487
|
+
newline = line[-1] == '+'
|
|
488
|
+
# Trim off the concat character plus any spaces, e.g. "line" \
|
|
489
|
+
trim = line[0..-2].strip()
|
|
490
|
+
# Now trim off the last quote so it will flow into the next line
|
|
491
|
+
@line += trim[0..-2]
|
|
492
|
+
@line += "\n" if newline
|
|
493
|
+
string_concat = true
|
|
494
|
+
next
|
|
495
|
+
when '&' # Line continuation
|
|
496
|
+
@line += line[0..-2]
|
|
494
497
|
next
|
|
498
|
+
else
|
|
499
|
+
@line += line
|
|
500
|
+
end
|
|
501
|
+
string_concat = false
|
|
502
|
+
|
|
503
|
+
data = @line.scan(rx)
|
|
504
|
+
first_item = ''
|
|
505
|
+
if data.length > 0
|
|
506
|
+
first_item += data[0]
|
|
495
507
|
end
|
|
496
508
|
|
|
497
|
-
if
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
509
|
+
if (first_item.length == 0) || (first_item[0] == '#')
|
|
510
|
+
@keyword = nil
|
|
511
|
+
else
|
|
512
|
+
@keyword = first_item.upcase
|
|
513
|
+
end
|
|
514
|
+
@parameters = []
|
|
515
|
+
|
|
516
|
+
# Ignore lines without keywords: comments and blank lines
|
|
517
|
+
if @keyword.nil?
|
|
518
|
+
if yield_non_keyword_lines
|
|
519
|
+
yield(@keyword, @parameters)
|
|
502
520
|
end
|
|
503
|
-
|
|
521
|
+
@line = ''
|
|
522
|
+
next
|
|
504
523
|
end
|
|
505
524
|
|
|
506
525
|
length = data.length
|
|
@@ -518,13 +537,6 @@ module OpenC3
|
|
|
518
537
|
end
|
|
519
538
|
end
|
|
520
539
|
|
|
521
|
-
# If the string is simply '&' and its the last string then its a line continuation so break the loop
|
|
522
|
-
if (string.length == 1) && (string[0] == '&') && (index == (length - 1))
|
|
523
|
-
line_continuation = true
|
|
524
|
-
next
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
line_continuation = false
|
|
528
540
|
if remove_quotes
|
|
529
541
|
@parameters << string.remove_quotes
|
|
530
542
|
else
|
|
@@ -533,20 +545,8 @@ module OpenC3
|
|
|
533
545
|
end
|
|
534
546
|
end
|
|
535
547
|
|
|
536
|
-
# If we detected a line continuation while going through all the
|
|
537
|
-
# strings on the line then we strip off the continuation character and
|
|
538
|
-
# return to the top of the loop to continue processing the line.
|
|
539
|
-
if line_continuation
|
|
540
|
-
# Strip the continuation character
|
|
541
|
-
if @line.length >= 1
|
|
542
|
-
@line = @line[0..-2]
|
|
543
|
-
else
|
|
544
|
-
@line = ""
|
|
545
|
-
end
|
|
546
|
-
next
|
|
547
|
-
end
|
|
548
|
-
|
|
549
548
|
yield(@keyword, @parameters)
|
|
549
|
+
@line = ''
|
|
550
550
|
end
|
|
551
551
|
|
|
552
552
|
@@progress_callback.call(1.0) if @@progress_callback
|
|
@@ -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/api/api'
|
|
@@ -38,6 +38,12 @@ module OpenC3
|
|
|
38
38
|
# @return [Array<String>] Array of target names associated with this interface
|
|
39
39
|
attr_accessor :target_names
|
|
40
40
|
|
|
41
|
+
# @return [Array<String>] Array of cmd target names associated with this interface
|
|
42
|
+
attr_accessor :cmd_target_names
|
|
43
|
+
|
|
44
|
+
# @return [Array<String>] Array of tlm target names associated with this interface
|
|
45
|
+
attr_accessor :tlm_target_names
|
|
46
|
+
|
|
41
47
|
# @return [Boolean] Flag indicating if the interface should be connected
|
|
42
48
|
# to on startup
|
|
43
49
|
attr_accessor :connect_on_startup
|
|
@@ -133,6 +139,8 @@ module OpenC3
|
|
|
133
139
|
@name = self.class.to_s.split("::")[-1] # Remove namespacing if present
|
|
134
140
|
@state = 'DISCONNECTED'
|
|
135
141
|
@target_names = []
|
|
142
|
+
@cmd_target_names = []
|
|
143
|
+
@tlm_target_names = []
|
|
136
144
|
@connect_on_startup = true
|
|
137
145
|
@auto_reconnect = true
|
|
138
146
|
@reconnect_delay = 5.0
|
|
@@ -381,6 +389,8 @@ module OpenC3
|
|
|
381
389
|
def copy_to(other_interface)
|
|
382
390
|
other_interface.name = self.name.clone
|
|
383
391
|
other_interface.target_names = self.target_names.clone
|
|
392
|
+
other_interface.cmd_target_names = self.cmd_target_names.clone
|
|
393
|
+
other_interface.tlm_target_names = self.tlm_target_names.clone
|
|
384
394
|
other_interface.connect_on_startup = self.connect_on_startup
|
|
385
395
|
other_interface.auto_reconnect = self.auto_reconnect
|
|
386
396
|
other_interface.reconnect_delay = self.reconnect_delay
|
|
@@ -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'
|
|
@@ -55,30 +55,44 @@ module OpenC3
|
|
|
55
55
|
# creating a Packet. It can discard a set number of bytes at the beginning
|
|
56
56
|
# before creating the Packet.
|
|
57
57
|
#
|
|
58
|
+
# Note: On the first call to this from any interface read(), data will contain a blank
|
|
59
|
+
# string. Blank string is an opportunity for protocols to return any queued up packets.
|
|
60
|
+
# If they have no queued up packets, they should pass the blank string down to chained
|
|
61
|
+
# protocols giving them the same opportunity.
|
|
62
|
+
#
|
|
58
63
|
# @return [String|nil] Data for a packet consisting of the bytes read
|
|
59
64
|
def read_data(data)
|
|
60
65
|
@data << data
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
while true
|
|
68
|
+
control = handle_sync_pattern()
|
|
69
|
+
return control if control and data.length > 0 # Only return here if not blank string test
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
# Reduce the data to a single packet
|
|
72
|
+
packet_data = reduce_to_single_packet()
|
|
73
|
+
if packet_data == :RESYNC
|
|
74
|
+
@sync_state = :SEARCHING
|
|
75
|
+
next if data.length > 0 # Only immediately resync if not blank string test
|
|
76
|
+
end
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
# Potentially allow blank string to be sent to other protocols if no packet is ready in this one
|
|
79
|
+
if Symbol === packet_data
|
|
80
|
+
if (data.length <= 0) and packet_data != :DISCONNECT
|
|
81
|
+
# On blank string test, return blank string (unless we had a packet or need disconnect)
|
|
82
|
+
# The base class handles the special case of returning STOP if on the last protocol in the
|
|
83
|
+
# chain
|
|
84
|
+
return super(data)
|
|
85
|
+
else
|
|
86
|
+
return packet_data # Return any control code if not on blank string test
|
|
87
|
+
end
|
|
74
88
|
end
|
|
75
|
-
end
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
@sync_state = :SEARCHING
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
# Discard leading bytes if necessary
|
|
93
|
+
packet_data.replace(packet_data[@discard_leading_bytes..-1]) if @discard_leading_bytes > 0
|
|
94
|
+
return packet_data
|
|
95
|
+
end
|
|
82
96
|
end
|
|
83
97
|
|
|
84
98
|
# Called to perform modifications on a command packet before it is sent
|