openc3 5.20.0 → 6.0.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 +12 -120
- data/data/config/command_modifiers.yaml +13 -1
- data/data/config/interface_modifiers.yaml +21 -4
- data/data/config/item_modifiers.yaml +1 -1
- data/data/config/microservice.yaml +15 -2
- data/data/config/param_item_modifiers.yaml +1 -1
- data/data/config/parameter_modifiers.yaml +1 -1
- data/data/config/table_manager.yaml +2 -2
- data/data/config/target.yaml +11 -0
- data/data/config/telemetry_modifiers.yaml +17 -1
- data/data/config/tool.yaml +12 -0
- data/data/config/widgets.yaml +13 -17
- data/lib/openc3/accessors/form_accessor.rb +4 -3
- data/lib/openc3/accessors/html_accessor.rb +3 -3
- data/lib/openc3/accessors/http_accessor.rb +13 -13
- data/lib/openc3/accessors/xml_accessor.rb +16 -4
- data/lib/openc3/api/target_api.rb +0 -30
- data/lib/openc3/config/config_parser.rb +6 -3
- data/lib/openc3/core_ext/array.rb +0 -16
- data/lib/openc3/core_ext.rb +0 -1
- data/lib/openc3/interfaces/file_interface.rb +198 -0
- data/lib/openc3/interfaces/http_client_interface.rb +71 -39
- data/lib/openc3/interfaces/http_server_interface.rb +0 -7
- data/lib/openc3/interfaces/interface.rb +2 -0
- data/lib/openc3/interfaces/mqtt_interface.rb +32 -15
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +19 -4
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -0
- data/lib/openc3/interfaces/serial_interface.rb +1 -0
- data/lib/openc3/interfaces.rb +2 -4
- data/lib/openc3/microservices/multi_microservice.rb +3 -3
- data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +31 -0
- data/lib/openc3/migrations/20241208080001_no_trigger_group.rb +46 -0
- data/lib/openc3/models/interface_model.rb +9 -3
- data/lib/openc3/models/microservice_model.rb +8 -1
- data/lib/openc3/models/plugin_model.rb +6 -1
- data/lib/openc3/models/python_package_model.rb +6 -1
- data/lib/openc3/models/reaction_model.rb +14 -10
- data/lib/openc3/models/scope_model.rb +60 -42
- data/lib/openc3/models/target_model.rb +17 -1
- data/lib/openc3/models/timeline_model.rb +17 -5
- data/lib/openc3/models/tool_model.rb +15 -3
- data/lib/openc3/models/trigger_group_model.rb +6 -3
- data/lib/openc3/operators/microservice_operator.rb +8 -0
- data/lib/openc3/packets/commands.rb +17 -6
- data/lib/openc3/packets/limits.rb +0 -12
- data/lib/openc3/packets/packet.rb +1 -1
- data/lib/openc3/packets/packet_item.rb +30 -36
- data/lib/openc3/packets/structure_item.rb +2 -2
- data/lib/openc3/script/script.rb +0 -10
- data/lib/openc3/script/web_socket_api.rb +2 -2
- data/lib/openc3/streams/mqtt_stream.rb +41 -33
- data/lib/openc3/streams/serial_stream.rb +27 -27
- data/lib/openc3/streams/stream.rb +17 -17
- data/lib/openc3/streams/tcpip_client_stream.rb +1 -1
- data/lib/openc3/streams/tcpip_socket_stream.rb +19 -19
- data/lib/openc3/system/system.rb +1 -1
- data/lib/openc3/system.rb +2 -3
- data/lib/openc3/tools/table_manager/table.rb +2 -2
- data/lib/openc3/tools/table_manager/table_parser.rb +1 -1
- data/lib/openc3/top_level.rb +0 -5
- data/lib/openc3/topics/command_decom_topic.rb +0 -7
- data/lib/openc3/utilities/bucket_utilities.rb +1 -1
- data/lib/openc3/utilities/cli_generator.rb +0 -1
- data/lib/openc3/version.rb +6 -6
- data/templates/plugin/README.md +1 -1
- data/templates/target/targets/TARGET/lib/target.rb +1 -1
- data/templates/tool_angular/package.json +8 -8
- data/templates/tool_angular/src/app/app.component.html +4 -13
- data/templates/tool_angular/src/app/app.component.scss +5 -13
- data/templates/tool_angular/src/app/app.component.ts +5 -4
- data/templates/tool_angular/src/app/custom-overlay-container.ts +2 -2
- data/templates/tool_angular/src/app/openc3-api.d.ts +1 -1
- data/templates/tool_angular/src/main.single-spa.ts +1 -1
- data/templates/tool_react/package.json +1 -0
- data/templates/tool_react/src/root.component.js +1 -1
- data/templates/tool_svelte/package.json +11 -9
- data/templates/tool_svelte/rollup.config.js +2 -0
- data/templates/tool_svelte/src/App.svelte +2 -2
- data/templates/tool_vue/eslint.config.mjs +68 -0
- data/templates/tool_vue/jsconfig.json +1 -1
- data/templates/tool_vue/package.json +26 -43
- data/templates/tool_vue/src/App.vue +3 -5
- data/templates/tool_vue/src/main.js +12 -23
- data/templates/tool_vue/src/router.js +19 -18
- data/templates/tool_vue/src/tools/tool_name/tool_name.vue +2 -2
- data/templates/tool_vue/vite.config.js +52 -0
- data/templates/widget/package.json +19 -26
- data/templates/widget/src/Widget.vue +13 -15
- data/templates/widget/vite.config.js +26 -0
- metadata +10 -41
- data/lib/openc3/core_ext/hash.rb +0 -40
- data/lib/openc3/core_ext/httpclient.rb +0 -11
- data/lib/openc3/interfaces/linc_interface.rb +0 -480
- data/lib/openc3/interfaces/protocols/override_protocol.rb +0 -4
- data/lib/openc3/microservices/critical_cmd_microservice.rb +0 -74
- data/lib/openc3/microservices/reaction_microservice.rb +0 -607
- data/lib/openc3/microservices/timeline_microservice.rb +0 -398
- data/lib/openc3/microservices/trigger_group_microservice.rb +0 -698
- data/lib/openc3/migrations/20230615000000_autonomic.rb +0 -86
- data/lib/openc3/migrations/20240915000000_activity_uuid.rb +0 -28
- data/lib/openc3/migrations/20241016000000_scope_critical_cmd.rb +0 -24
- data/lib/openc3/system/system_config.rb +0 -413
- data/templates/tool_svelte/src/services/api.js +0 -92
- data/templates/tool_svelte/src/services/axios.js +0 -85
- data/templates/tool_svelte/src/services/cable.js +0 -65
- data/templates/tool_svelte/src/services/config-parser.js +0 -198
- data/templates/tool_svelte/src/services/openc3-api.js +0 -606
- data/templates/tool_vue/.eslintrc.js +0 -43
- data/templates/tool_vue/babel.config.json +0 -11
- data/templates/tool_vue/vue.config.js +0 -38
- data/templates/widget/.eslintrc.js +0 -43
- data/templates/widget/babel.config.json +0 -11
- data/templates/widget/vue.config.js +0 -28
- /data/templates/tool_vue/{.prettierrc.js → .prettierrc.cjs} +0 -0
- /data/templates/widget/{.prettierrc.js → .prettierrc.cjs} +0 -0
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openc3
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Melton
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2024-
|
|
12
|
+
date: 2024-12-17 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bundler
|
|
@@ -235,20 +235,6 @@ dependencies:
|
|
|
235
235
|
- - "~>"
|
|
236
236
|
- !ruby/object:Gem::Version
|
|
237
237
|
version: '0.9'
|
|
238
|
-
- !ruby/object:Gem::Dependency
|
|
239
|
-
name: httpclient
|
|
240
|
-
requirement: !ruby/object:Gem::Requirement
|
|
241
|
-
requirements:
|
|
242
|
-
- - "~>"
|
|
243
|
-
- !ruby/object:Gem::Version
|
|
244
|
-
version: '2.8'
|
|
245
|
-
type: :runtime
|
|
246
|
-
prerelease: false
|
|
247
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
248
|
-
requirements:
|
|
249
|
-
- - "~>"
|
|
250
|
-
- !ruby/object:Gem::Version
|
|
251
|
-
version: '2.8'
|
|
252
238
|
- !ruby/object:Gem::Dependency
|
|
253
239
|
name: aws-sdk-s3
|
|
254
240
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -925,8 +911,6 @@ files:
|
|
|
925
911
|
- lib/openc3/core_ext/exception.rb
|
|
926
912
|
- lib/openc3/core_ext/faraday.rb
|
|
927
913
|
- lib/openc3/core_ext/file.rb
|
|
928
|
-
- lib/openc3/core_ext/hash.rb
|
|
929
|
-
- lib/openc3/core_ext/httpclient.rb
|
|
930
914
|
- lib/openc3/core_ext/io.rb
|
|
931
915
|
- lib/openc3/core_ext/kernel.rb
|
|
932
916
|
- lib/openc3/core_ext/math.rb
|
|
@@ -941,10 +925,10 @@ files:
|
|
|
941
925
|
- lib/openc3/core_ext/time.rb
|
|
942
926
|
- lib/openc3/ext/.keep
|
|
943
927
|
- lib/openc3/interfaces.rb
|
|
928
|
+
- lib/openc3/interfaces/file_interface.rb
|
|
944
929
|
- lib/openc3/interfaces/http_client_interface.rb
|
|
945
930
|
- lib/openc3/interfaces/http_server_interface.rb
|
|
946
931
|
- lib/openc3/interfaces/interface.rb
|
|
947
|
-
- lib/openc3/interfaces/linc_interface.rb
|
|
948
932
|
- lib/openc3/interfaces/mqtt_interface.rb
|
|
949
933
|
- lib/openc3/interfaces/mqtt_stream_interface.rb
|
|
950
934
|
- lib/openc3/interfaces/protocols/burst_protocol.rb
|
|
@@ -954,7 +938,6 @@ files:
|
|
|
954
938
|
- lib/openc3/interfaces/protocols/fixed_protocol.rb
|
|
955
939
|
- lib/openc3/interfaces/protocols/ignore_packet_protocol.rb
|
|
956
940
|
- lib/openc3/interfaces/protocols/length_protocol.rb
|
|
957
|
-
- lib/openc3/interfaces/protocols/override_protocol.rb
|
|
958
941
|
- lib/openc3/interfaces/protocols/preidentified_protocol.rb
|
|
959
942
|
- lib/openc3/interfaces/protocols/protocol.rb
|
|
960
943
|
- lib/openc3/interfaces/protocols/slip_protocol.rb
|
|
@@ -991,7 +974,6 @@ files:
|
|
|
991
974
|
- lib/openc3/logs/stream_log_pair.rb
|
|
992
975
|
- lib/openc3/logs/text_log_writer.rb
|
|
993
976
|
- lib/openc3/microservices/cleanup_microservice.rb
|
|
994
|
-
- lib/openc3/microservices/critical_cmd_microservice.rb
|
|
995
977
|
- lib/openc3/microservices/decom_microservice.rb
|
|
996
978
|
- lib/openc3/microservices/interface_decom_common.rb
|
|
997
979
|
- lib/openc3/microservices/interface_microservice.rb
|
|
@@ -1000,21 +982,17 @@ files:
|
|
|
1000
982
|
- lib/openc3/microservices/multi_microservice.rb
|
|
1001
983
|
- lib/openc3/microservices/periodic_microservice.rb
|
|
1002
984
|
- lib/openc3/microservices/plugin_microservice.rb
|
|
1003
|
-
- lib/openc3/microservices/reaction_microservice.rb
|
|
1004
985
|
- lib/openc3/microservices/reducer_microservice.rb
|
|
1005
986
|
- lib/openc3/microservices/router_microservice.rb
|
|
1006
987
|
- lib/openc3/microservices/scope_cleanup_microservice.rb
|
|
1007
988
|
- lib/openc3/microservices/text_log_microservice.rb
|
|
1008
|
-
- lib/openc3/microservices/timeline_microservice.rb
|
|
1009
|
-
- lib/openc3/microservices/trigger_group_microservice.rb
|
|
1010
989
|
- lib/openc3/migrations/20220420190000_log_stuff.rb
|
|
1011
990
|
- lib/openc3/migrations/20221202214600_add_target_names.rb
|
|
1012
991
|
- lib/openc3/migrations/20221210174900_convert_to_multi.rb
|
|
1013
|
-
- lib/openc3/migrations/20230615000000_autonomic.rb
|
|
1014
992
|
- lib/openc3/migrations/20230915000002_no_scope_log_messages.rb
|
|
1015
993
|
- lib/openc3/migrations/20231022000000_tlm_viewer_config.rb
|
|
1016
|
-
- lib/openc3/migrations/
|
|
1017
|
-
- lib/openc3/migrations/
|
|
994
|
+
- lib/openc3/migrations/20241208080000_no_critical_cmd.rb
|
|
995
|
+
- lib/openc3/migrations/20241208080001_no_trigger_group.rb
|
|
1018
996
|
- lib/openc3/models/activity_model.rb
|
|
1019
997
|
- lib/openc3/models/auth_model.rb
|
|
1020
998
|
- lib/openc3/models/cvt_model.rb
|
|
@@ -1107,7 +1085,6 @@ files:
|
|
|
1107
1085
|
- lib/openc3/streams/web_socket_client_stream.rb
|
|
1108
1086
|
- lib/openc3/system.rb
|
|
1109
1087
|
- lib/openc3/system/system.rb
|
|
1110
|
-
- lib/openc3/system/system_config.rb
|
|
1111
1088
|
- lib/openc3/system/target.rb
|
|
1112
1089
|
- lib/openc3/tools/cmd_tlm_server/api.rb
|
|
1113
1090
|
- lib/openc3/tools/cmd_tlm_server/interface_thread.rb
|
|
@@ -1244,37 +1221,29 @@ files:
|
|
|
1244
1221
|
- templates/tool_svelte/rollup.config.js
|
|
1245
1222
|
- templates/tool_svelte/src/App.svelte
|
|
1246
1223
|
- templates/tool_svelte/src/App.test.js
|
|
1247
|
-
- templates/tool_svelte/src/services/api.js
|
|
1248
|
-
- templates/tool_svelte/src/services/axios.js
|
|
1249
|
-
- templates/tool_svelte/src/services/cable.js
|
|
1250
|
-
- templates/tool_svelte/src/services/config-parser.js
|
|
1251
|
-
- templates/tool_svelte/src/services/openc3-api.js
|
|
1252
1224
|
- templates/tool_svelte/src/theme/_smui-theme.scss
|
|
1253
1225
|
- templates/tool_svelte/src/tool_name.js
|
|
1254
1226
|
- templates/tool_vue/.browserslistrc
|
|
1255
1227
|
- templates/tool_vue/.env.standalone
|
|
1256
|
-
- templates/tool_vue/.eslintrc.js
|
|
1257
1228
|
- templates/tool_vue/.gitignore
|
|
1258
1229
|
- templates/tool_vue/.nycrc
|
|
1259
|
-
- templates/tool_vue/.prettierrc.
|
|
1260
|
-
- templates/tool_vue/
|
|
1230
|
+
- templates/tool_vue/.prettierrc.cjs
|
|
1231
|
+
- templates/tool_vue/eslint.config.mjs
|
|
1261
1232
|
- templates/tool_vue/jsconfig.json
|
|
1262
1233
|
- templates/tool_vue/package.json
|
|
1263
1234
|
- templates/tool_vue/src/App.vue
|
|
1264
1235
|
- templates/tool_vue/src/main.js
|
|
1265
1236
|
- templates/tool_vue/src/router.js
|
|
1266
1237
|
- templates/tool_vue/src/tools/tool_name/tool_name.vue
|
|
1267
|
-
- templates/tool_vue/
|
|
1238
|
+
- templates/tool_vue/vite.config.js
|
|
1268
1239
|
- templates/widget/.browserslistrc
|
|
1269
|
-
- templates/widget/.eslintrc.js
|
|
1270
1240
|
- templates/widget/.nycrc
|
|
1271
|
-
- templates/widget/.prettierrc.
|
|
1241
|
+
- templates/widget/.prettierrc.cjs
|
|
1272
1242
|
- templates/widget/LICENSE.txt
|
|
1273
1243
|
- templates/widget/Rakefile
|
|
1274
|
-
- templates/widget/babel.config.json
|
|
1275
1244
|
- templates/widget/package.json
|
|
1276
1245
|
- templates/widget/src/Widget.vue
|
|
1277
|
-
- templates/widget/
|
|
1246
|
+
- templates/widget/vite.config.js
|
|
1278
1247
|
homepage: https://github.com/OpenC3/cosmos
|
|
1279
1248
|
licenses:
|
|
1280
1249
|
- AGPL-3.0-only
|
data/lib/openc3/core_ext/hash.rb
DELETED
|
@@ -1,40 +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
|
-
# OpenC3 specific additions to the Ruby Hash class
|
|
24
|
-
class Hash
|
|
25
|
-
# Redefine inspect to only print for small numbers of
|
|
26
|
-
# items. Prevents exceptions taking forever to be raised with
|
|
27
|
-
# large objects. See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/105145
|
|
28
|
-
alias old_inspect inspect
|
|
29
|
-
|
|
30
|
-
# @param max_elements [Integer] The maximum number of elements in the Hash to
|
|
31
|
-
# print out before simply displaying the Hash class and object id
|
|
32
|
-
# @return [String] String representation of the hash
|
|
33
|
-
def inspect(max_elements = 10)
|
|
34
|
-
if self.length <= max_elements
|
|
35
|
-
old_inspect()
|
|
36
|
-
else
|
|
37
|
-
'#<' + self.class.to_s + ':' + self.object_id.to_s + '>'
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
require 'httpclient'
|
|
2
|
-
|
|
3
|
-
class HTTPClient
|
|
4
|
-
alias original_initialize initialize
|
|
5
|
-
|
|
6
|
-
def initialize(*args, &block)
|
|
7
|
-
original_initialize(*args, &block)
|
|
8
|
-
# Force use of the default system CA certs (instead of the 6 year old bundled ones)
|
|
9
|
-
@session_manager&.ssl_config&.set_default_paths
|
|
10
|
-
end
|
|
11
|
-
end
|
|
@@ -1,480 +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/interfaces/tcpip_client_interface'
|
|
24
|
-
require 'uuidtools'
|
|
25
|
-
|
|
26
|
-
module OpenC3
|
|
27
|
-
# TODO: Deprecated ... Will remove in next major version of COSMOS (COSMOS 6)
|
|
28
|
-
|
|
29
|
-
# Interface for connecting to Ball Aerospace LINC Labview targets
|
|
30
|
-
class LincInterface < TcpipClientInterface
|
|
31
|
-
# The maximum number of asynchronous commands we can wait for at a time.
|
|
32
|
-
# We don't ever expect to get close to this but we need to limit it
|
|
33
|
-
# to ensure the Array doesn't grow out of control.
|
|
34
|
-
MAX_CONCURRENT_HANDSHAKES = 1000
|
|
35
|
-
|
|
36
|
-
def initialize(
|
|
37
|
-
hostname,
|
|
38
|
-
port,
|
|
39
|
-
handshake_enabled = true,
|
|
40
|
-
response_timeout = 5.0,
|
|
41
|
-
read_timeout = nil,
|
|
42
|
-
write_timeout = 5.0,
|
|
43
|
-
length_bitoffset = 0,
|
|
44
|
-
length_bitsize = 16,
|
|
45
|
-
length_value_offset = 4,
|
|
46
|
-
fieldname_guid = 'HDR_GUID',
|
|
47
|
-
endianness = 'BIG_ENDIAN',
|
|
48
|
-
fieldname_cmd_length = 'HDR_LENGTH'
|
|
49
|
-
)
|
|
50
|
-
# Initialize Super Class
|
|
51
|
-
super(hostname, port, port, write_timeout, read_timeout, 'LENGTH',
|
|
52
|
-
length_bitoffset, length_bitsize, length_value_offset, 1, endianness, 0, nil, nil)
|
|
53
|
-
|
|
54
|
-
# Configuration Settings
|
|
55
|
-
@handshake_enabled = ConfigParser.handle_true_false(handshake_enabled)
|
|
56
|
-
@handshake_enableds = nil
|
|
57
|
-
@response_timeout = response_timeout.to_f
|
|
58
|
-
@length_value_offset = Integer(length_value_offset)
|
|
59
|
-
@fieldname_guid = ConfigParser.handle_nil(fieldname_guid)
|
|
60
|
-
@fieldname_cmd_length = ConfigParser.handle_nil(fieldname_cmd_length)
|
|
61
|
-
|
|
62
|
-
# Other instance variables
|
|
63
|
-
@ignored_error_codes = {}
|
|
64
|
-
@handshake_cmds = []
|
|
65
|
-
@handshakes_mutex = Mutex.new
|
|
66
|
-
|
|
67
|
-
# Call this once now because the first time is slow
|
|
68
|
-
UUIDTools::UUID.random_create.raw
|
|
69
|
-
end # def initialize
|
|
70
|
-
|
|
71
|
-
def connect
|
|
72
|
-
# Packet definitions need to be retrieved here because @target_names is not filled in until after initialize
|
|
73
|
-
unless @handshake_enableds
|
|
74
|
-
@handshake_enableds = {}
|
|
75
|
-
@target_names.each do |target_name|
|
|
76
|
-
@handshake_enableds[target_name] = @handshake_enabled
|
|
77
|
-
@ignored_error_codes[target_name] = []
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
@handshake_packets = []
|
|
81
|
-
@error_packets = []
|
|
82
|
-
@error_ignore_commands = nil
|
|
83
|
-
@error_handle_commands = nil
|
|
84
|
-
@handshake_enable_commands = nil
|
|
85
|
-
@handshake_disable_commands = nil
|
|
86
|
-
|
|
87
|
-
@target_names.each do |target_name|
|
|
88
|
-
@handshake_packets << System.telemetry.packet(target_name, 'HANDSHAKE')
|
|
89
|
-
@error_packets << System.telemetry.packet(target_name, 'ERROR')
|
|
90
|
-
|
|
91
|
-
# Handle not defining the interface configuration commands (Targets may not want to support this functionality)
|
|
92
|
-
begin
|
|
93
|
-
command = System.commands.packet(target_name, 'OPENC3_ERROR_IGNORE')
|
|
94
|
-
@error_ignore_commands ||= []
|
|
95
|
-
@error_ignore_commands << command
|
|
96
|
-
rescue
|
|
97
|
-
end
|
|
98
|
-
begin
|
|
99
|
-
command = System.commands.packet(target_name, 'OPENC3_ERROR_HANDLE')
|
|
100
|
-
@error_handle_commands ||= []
|
|
101
|
-
@error_handle_commands << command
|
|
102
|
-
rescue
|
|
103
|
-
end
|
|
104
|
-
begin
|
|
105
|
-
command = System.commands.packet(target_name, 'OPENC3_HANDSHAKE_EN')
|
|
106
|
-
@handshake_enable_commands ||= []
|
|
107
|
-
@handshake_enable_commands << command
|
|
108
|
-
rescue
|
|
109
|
-
end
|
|
110
|
-
begin
|
|
111
|
-
command = System.commands.packet(target_name, 'OPENC3_HANDSHAKE_DS')
|
|
112
|
-
@handshake_disable_commands ||= []
|
|
113
|
-
@handshake_disable_commands << command
|
|
114
|
-
rescue
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
@handshakes_mutex.synchronize do
|
|
119
|
-
@handshake_cmds = []
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Actually connect
|
|
123
|
-
super()
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def write(packet)
|
|
127
|
-
return if linc_interface_command(packet)
|
|
128
|
-
raise "Interface not connected" unless connected?()
|
|
129
|
-
|
|
130
|
-
# Add a GUID to the GUID field if its defined
|
|
131
|
-
# A GUID means it's an asynchronous packet type.
|
|
132
|
-
if @fieldname_guid
|
|
133
|
-
guid = get_guid(packet)
|
|
134
|
-
else
|
|
135
|
-
# If @fieldname_guid is not defined (synchronous) we don't care what the
|
|
136
|
-
# GUID is because we're not trying to match it up with anything.
|
|
137
|
-
# As soon as we get a response we free the command.
|
|
138
|
-
guid = 0
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Fix the length field to handle the cases where a variable length packet
|
|
142
|
-
# is defined. OpenC3 does not do this automatically.
|
|
143
|
-
update_length_field(packet) if @fieldname_cmd_length
|
|
144
|
-
|
|
145
|
-
# Always take the mutex (even if we aren't handshaking)
|
|
146
|
-
# We do not want any incoming telemetry to be missed because
|
|
147
|
-
# it could be the handshake to this command.
|
|
148
|
-
@handshakes_mutex.synchronize do
|
|
149
|
-
super(packet) # Send the command
|
|
150
|
-
wait_for_response(packet, guid) if @handshake_enableds[packet.target_name]
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def linc_interface_command(packet)
|
|
155
|
-
if @error_ignore_commands
|
|
156
|
-
@error_ignore_commands.each do |error_ignore_command|
|
|
157
|
-
if error_ignore_command.identify?(packet.buffer(false))
|
|
158
|
-
linc_cmd = error_ignore_command.clone
|
|
159
|
-
linc_cmd.buffer = packet.buffer
|
|
160
|
-
code = linc_cmd.read('CODE')
|
|
161
|
-
@ignored_error_codes[error_ignore_command.target_name] << code unless @ignored_error_codes[error_ignore_command.target_name].include? code
|
|
162
|
-
return true
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
if @error_handle_commands
|
|
168
|
-
@error_handle_commands.each do |error_handle_command|
|
|
169
|
-
if error_handle_command.identify?(packet.buffer(false))
|
|
170
|
-
linc_cmd = error_handle_command.clone
|
|
171
|
-
linc_cmd.buffer = packet.buffer
|
|
172
|
-
code = linc_cmd.read('CODE')
|
|
173
|
-
@ignored_error_codes[error_handle_command.target_name].delete(code) if @ignored_error_codes[error_handle_command.target_name].include? code
|
|
174
|
-
return true
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
if @handshake_enable_commands
|
|
180
|
-
@handshake_enable_commands.each do |handshake_enable_command|
|
|
181
|
-
if handshake_enable_command.identify?(packet.buffer(false))
|
|
182
|
-
@handshake_enabled = true
|
|
183
|
-
@handshake_enableds[handshake_enable_command.target_name] = true
|
|
184
|
-
return true
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
if @handshake_disable_commands
|
|
190
|
-
@handshake_disable_commands.each do |handshake_disable_command|
|
|
191
|
-
if handshake_disable_command.identify?(packet.buffer(false))
|
|
192
|
-
@handshake_enabled = false
|
|
193
|
-
@handshake_enableds[handshake_disable_command.target_name] = false
|
|
194
|
-
return true
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
return false
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def get_guid(packet)
|
|
203
|
-
if not packet.read(@fieldname_guid) =~ /[\x01-\xFF]/
|
|
204
|
-
# The GUID has not been set already (it has all \x00 values), so make a new one.
|
|
205
|
-
# This enables a router GUI to make the GUIDs so it can process handshakes too.
|
|
206
|
-
guid = UUIDTools::UUID.random_create.raw
|
|
207
|
-
packet.write(@fieldname_guid, guid, :RAW)
|
|
208
|
-
else
|
|
209
|
-
guid = packet.read(@fieldname_guid)
|
|
210
|
-
end
|
|
211
|
-
return guid
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def update_length_field(packet)
|
|
215
|
-
length = packet.length - @length_value_offset
|
|
216
|
-
packet.write(@fieldname_cmd_length, length, :RAW)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def wait_for_response(packet, guid)
|
|
220
|
-
# Check the number of commands waiting for handshakes. This is just for sanity
|
|
221
|
-
# If the number of commands waiting for handshakes is very large then it can't be real
|
|
222
|
-
# So raise an error. Something has gone horribly wrong.
|
|
223
|
-
if @handshake_cmds.length > MAX_CONCURRENT_HANDSHAKES
|
|
224
|
-
len = @handshake_cmds.length
|
|
225
|
-
@handshake_cmds = []
|
|
226
|
-
raise "The number of commands waiting for handshakes to #{len}. Clearing all commands!"
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
# Create a handshake command object and add it to the list of commands waiting
|
|
230
|
-
handshake_cmd = LincHandshakeCommand.new(@handshakes_mutex, guid)
|
|
231
|
-
@handshake_cmds.push(handshake_cmd)
|
|
232
|
-
|
|
233
|
-
# wait for that handshake. This releases the mutex so that the telemetry and other commands can start running again.
|
|
234
|
-
timed_out = handshake_cmd.wait_for_handshake(@response_timeout)
|
|
235
|
-
# We now have the mutex again. This interface is blocked for the rest of the command handling,
|
|
236
|
-
# which should be quick because it's just checking variables and logging.
|
|
237
|
-
# We want to hold the mutex during that so that the commands get logged in order of handshake from here.
|
|
238
|
-
|
|
239
|
-
if timed_out
|
|
240
|
-
# Clean this command out of the array of items that require handshakes.
|
|
241
|
-
@handshake_cmds.delete_if { |hsc| hsc == handshake_cmd }
|
|
242
|
-
raise "Timeout waiting for handshake from #{System.commands.format(packet, System.targets[packet.target_name].ignored_parameters)}"
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
process_handshake_results(handshake_cmd)
|
|
246
|
-
rescue Exception => e
|
|
247
|
-
# If anything goes wrong after successfully writing the packet to the LINC target
|
|
248
|
-
# ensure that the packet gets updated in the CVT and logged to the packet log writer.
|
|
249
|
-
# OpenC3 normally only does this if write returns successfully
|
|
250
|
-
if packet.identified?
|
|
251
|
-
command = System.commands.packet(packet.target_name, packet.packet_name)
|
|
252
|
-
else
|
|
253
|
-
command = System.commands.packet('UNKNOWN', 'UNKNOWN')
|
|
254
|
-
end
|
|
255
|
-
command.buffer = packet.buffer
|
|
256
|
-
|
|
257
|
-
@packet_log_writer_pairs.each do |packet_log_writer_pair|
|
|
258
|
-
packet_log_writer_pair.cmd_log_writer.write(packet)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
raise e
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def process_handshake_results(handshake_cmd)
|
|
265
|
-
status = handshake_cmd.handshake.handshake.read('STATUS')
|
|
266
|
-
code = handshake_cmd.handshake.handshake.read('CODE')
|
|
267
|
-
source = handshake_cmd.handshake.error_source
|
|
268
|
-
|
|
269
|
-
# Handle handshake warnings and errors
|
|
270
|
-
if status == "OK" and code != 0
|
|
271
|
-
unless @ignored_error_codes[handshake_cmd.handshake.handshake.target_name].include? code
|
|
272
|
-
Logger.warn "#{@name}: Warning sending command (#{code}): #{source}"
|
|
273
|
-
end
|
|
274
|
-
elsif status == "ERROR"
|
|
275
|
-
unless @ignored_error_codes[handshake_cmd.handshake.handshake.target_name].include? code
|
|
276
|
-
raise "Error sending command (#{code}): #{source}"
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
def read
|
|
282
|
-
packet = super()
|
|
283
|
-
if packet
|
|
284
|
-
@handshake_packets.each do |handshake_packet|
|
|
285
|
-
if handshake_packet.identify?(packet.buffer(false))
|
|
286
|
-
handshake_packet = handshake_packet.clone
|
|
287
|
-
handshake_packet.buffer = packet.buffer
|
|
288
|
-
linc_handshake = LincHandshake.new(handshake_packet, handshake_packet.target_name)
|
|
289
|
-
|
|
290
|
-
# Check for a local handshake
|
|
291
|
-
if handshake_packet.read('origin') == "LCL"
|
|
292
|
-
handle_local_handshake(linc_handshake)
|
|
293
|
-
else
|
|
294
|
-
handle_remote_handshake(linc_handshake) if @handshake_enableds[handshake_packet.target_name]
|
|
295
|
-
end # if handshake_packet.read('origin') == "LCL"
|
|
296
|
-
end # @handshake_packet.identify?(packet.buffer(false))
|
|
297
|
-
end
|
|
298
|
-
end # if packet
|
|
299
|
-
|
|
300
|
-
return packet
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def handle_local_handshake(linc_handshake)
|
|
304
|
-
# Update the current value table for this command
|
|
305
|
-
command = System.commands.packet(linc_handshake.identified_command.target_name, linc_handshake.identified_command.packet_name)
|
|
306
|
-
command.received_time = linc_handshake.identified_command.received_time
|
|
307
|
-
command.buffer = linc_handshake.identified_command.buffer
|
|
308
|
-
command.received_count += 1
|
|
309
|
-
|
|
310
|
-
# Put a log of the command onto the server for the user to see
|
|
311
|
-
Logger.info("#{@name}: External Command: " + System.commands.format(linc_handshake.identified_command, System.targets[linc_handshake.identified_command.target_name].ignored_parameters))
|
|
312
|
-
|
|
313
|
-
# Log the command to the command log(s)
|
|
314
|
-
@packet_log_writer_pairs.each do |packet_log_writer_pair|
|
|
315
|
-
packet_log_writer_pair.cmd_log_writer.write(linc_handshake.identified_command)
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def handle_remote_handshake(linc_handshake)
|
|
320
|
-
# This is a remote packet (sent from here).
|
|
321
|
-
# Add to the array of handshake packet responses
|
|
322
|
-
# The mutex is required by the command task due to the way it
|
|
323
|
-
# first looks up the handshake before removing it.
|
|
324
|
-
@handshakes_mutex.synchronize do
|
|
325
|
-
if @fieldname_guid
|
|
326
|
-
# A GUID means it's an asynchronous packet type.
|
|
327
|
-
# So look at the list of incoming handshakes and pick off (deleting)
|
|
328
|
-
# the handshake from the list if it's for this command.
|
|
329
|
-
#
|
|
330
|
-
# The mutex is required because the telemetry task
|
|
331
|
-
# could enqueue a response between the index lookup and the slice
|
|
332
|
-
# function which would remove the wrong response. FAIL!
|
|
333
|
-
|
|
334
|
-
# Loop through all waiting commands to see if this handshake belongs to them
|
|
335
|
-
this_handshake_guid = linc_handshake.get_cmd_guid(@fieldname_guid)
|
|
336
|
-
handshake_cmd_index = @handshake_cmds.index { |hsc| hsc.get_cmd_guid == this_handshake_guid }
|
|
337
|
-
|
|
338
|
-
# If command was waiting (ie the loop above found one), then remove it from waiters and signal it
|
|
339
|
-
if handshake_cmd_index
|
|
340
|
-
handshake_cmd = @handshake_cmds.slice!(handshake_cmd_index)
|
|
341
|
-
handshake_cmd.got_your_handshake(linc_handshake)
|
|
342
|
-
else
|
|
343
|
-
# No command match found! Either it gave up and timed out or this wasn't originated from here.
|
|
344
|
-
# Ignore this typically. This case here for clarity.
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
else
|
|
348
|
-
# Synchronous version: just pop the array (pull the command off) and send it the handshake
|
|
349
|
-
handshake_cmd = @handshakes_cmds.pop
|
|
350
|
-
handshake_cmd.got_your_handshake(linc_handshake)
|
|
351
|
-
end # of handshaking type check
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
end # class LincInterface
|
|
355
|
-
|
|
356
|
-
# The LincHandshakeCommand class is used only by the LincInterface.
|
|
357
|
-
# It is the command with other required items that is passed to the telemetry
|
|
358
|
-
# thread so it can match it with the handshake.
|
|
359
|
-
class LincHandshakeCommand
|
|
360
|
-
attr_accessor :handshake
|
|
361
|
-
|
|
362
|
-
def initialize(handshakes_mutex, cmd_guid)
|
|
363
|
-
@cmd_guid = cmd_guid
|
|
364
|
-
@handshakes_mutex = handshakes_mutex
|
|
365
|
-
@resource = ConditionVariable.new
|
|
366
|
-
@handshake = nil
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
def wait_for_handshake(response_timeout)
|
|
370
|
-
timed_out = false
|
|
371
|
-
|
|
372
|
-
@resource.wait(@handshakes_mutex, response_timeout)
|
|
373
|
-
if @handshake
|
|
374
|
-
timed_out = false
|
|
375
|
-
else
|
|
376
|
-
Logger.warn "#{@name}: No handshake - must be timeout."
|
|
377
|
-
timed_out = true
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
return timed_out
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def got_your_handshake(handshake)
|
|
384
|
-
@handshake = handshake
|
|
385
|
-
@resource.signal
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
def get_cmd_guid
|
|
389
|
-
return @cmd_guid
|
|
390
|
-
end
|
|
391
|
-
end # class LincHandshakeCommand
|
|
392
|
-
|
|
393
|
-
# The LincHandshake class is used only by the LincInterface. It processes the handshake and
|
|
394
|
-
# helps with finding the information regarding the internal command.
|
|
395
|
-
class LincHandshake
|
|
396
|
-
attr_accessor :handshake
|
|
397
|
-
attr_accessor :identified_command
|
|
398
|
-
attr_accessor :error_source
|
|
399
|
-
|
|
400
|
-
def initialize(handshake, interface_target_name)
|
|
401
|
-
@handshake = handshake
|
|
402
|
-
|
|
403
|
-
# Interpret the command field of the handshake packet
|
|
404
|
-
# Where DATA is defined as:
|
|
405
|
-
# 1 byte target name length
|
|
406
|
-
# X byte target name
|
|
407
|
-
# 1 byte packet name length
|
|
408
|
-
# X byte packet name
|
|
409
|
-
# 4 byte packet data length
|
|
410
|
-
# X byte packet data
|
|
411
|
-
# 4 byte error source length
|
|
412
|
-
# X byte error source
|
|
413
|
-
data = handshake.read('DATA')
|
|
414
|
-
raise "Data field too short for target name length" if data.length == 0
|
|
415
|
-
|
|
416
|
-
# Get target name length
|
|
417
|
-
target_name_length = data[0..0].unpack('C')[0]
|
|
418
|
-
raise "Invalid target name length" if target_name_length == 0
|
|
419
|
-
|
|
420
|
-
data = data[1..-1]
|
|
421
|
-
|
|
422
|
-
# get target name
|
|
423
|
-
raise "Data field too short for target name" if data.length < target_name_length
|
|
424
|
-
|
|
425
|
-
# target_name = data[0..(target_name_length - 1)] # Unused
|
|
426
|
-
data = data[target_name_length..-1]
|
|
427
|
-
|
|
428
|
-
# get packet name length
|
|
429
|
-
raise "Data field too short for packet name length" if data.length == 0
|
|
430
|
-
|
|
431
|
-
packet_name_length = data[0..0].unpack('C')[0]
|
|
432
|
-
raise "Invalid packet name length" if packet_name_length == 0
|
|
433
|
-
|
|
434
|
-
data = data[1..-1]
|
|
435
|
-
|
|
436
|
-
# get packet name
|
|
437
|
-
raise "Data field too short for packet name" if data.length < packet_name_length
|
|
438
|
-
|
|
439
|
-
packet_name = data[0..(packet_name_length - 1)]
|
|
440
|
-
data = data[packet_name_length..-1]
|
|
441
|
-
|
|
442
|
-
# get packet data length
|
|
443
|
-
raise "Data field too short for packet data length" if data.length < 4
|
|
444
|
-
|
|
445
|
-
packet_data_length = data[0..3].unpack('N')[0]
|
|
446
|
-
raise "Invalid data length" if packet_data_length == 0
|
|
447
|
-
|
|
448
|
-
data = data[4..-1]
|
|
449
|
-
|
|
450
|
-
# get packet data
|
|
451
|
-
raise "Data field too short for packet data" if data.length < packet_data_length
|
|
452
|
-
|
|
453
|
-
packet_data = data[0..(packet_data_length - 1)]
|
|
454
|
-
data = data[packet_data_length..-1]
|
|
455
|
-
|
|
456
|
-
# get error source length
|
|
457
|
-
raise "Data field too short for error source length" if data.length < 4
|
|
458
|
-
|
|
459
|
-
error_source_length = data[0..3].unpack('N')[0]
|
|
460
|
-
# note it is OK to have a 0 source length
|
|
461
|
-
data = data[4..-1]
|
|
462
|
-
|
|
463
|
-
# get error source - store on object
|
|
464
|
-
if error_source_length > 0
|
|
465
|
-
@error_source = data[0..(error_source_length - 1)]
|
|
466
|
-
else
|
|
467
|
-
@error_source = ''
|
|
468
|
-
end
|
|
469
|
-
|
|
470
|
-
# make packet - store on object as a defined packet of type command that this handshakes
|
|
471
|
-
@identified_command = System.commands.packet(interface_target_name, packet_name).clone
|
|
472
|
-
@identified_command.buffer = packet_data
|
|
473
|
-
@identified_command.received_time = Time.at(handshake.read('TIME_SECONDS'), handshake.read('TIME_MICROSECONDS')).sys
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def get_cmd_guid(fieldname_guid)
|
|
477
|
-
return @identified_command.read(fieldname_guid)
|
|
478
|
-
end
|
|
479
|
-
end
|
|
480
|
-
end
|