openc3 5.0.6
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 +7 -0
- data/Gemfile +18 -0
- data/Guardfile +35 -0
- data/LICENSE.txt +727 -0
- data/README.md +37 -0
- data/Rakefile +131 -0
- data/bin/cstol_converter +1178 -0
- data/bin/openc3cli +531 -0
- data/bin/rubysloc +139 -0
- data/data/config/_array_params.yaml +23 -0
- data/data/config/_id_items.yaml +24 -0
- data/data/config/_id_params.yaml +58 -0
- data/data/config/_interfaces.yaml +214 -0
- data/data/config/_interfaces.yaml.err +1017 -0
- data/data/config/_items.yaml +20 -0
- data/data/config/_params.yaml +60 -0
- data/data/config/cmd_tlm_server.yaml +136 -0
- data/data/config/command.yaml +44 -0
- data/data/config/command_modifiers.yaml +160 -0
- data/data/config/command_telemetry.yaml +3 -0
- data/data/config/interface_modifiers.yaml +104 -0
- data/data/config/item_modifiers.yaml +221 -0
- data/data/config/microservice.yaml +78 -0
- data/data/config/param_item_modifiers.yaml +52 -0
- data/data/config/parameter_modifiers.yaml +200 -0
- data/data/config/plugins.yaml +80 -0
- data/data/config/protocols.yaml +290 -0
- data/data/config/screen.yaml +147 -0
- data/data/config/table_manager.yaml +89 -0
- data/data/config/table_parameter_modifiers.yaml +9 -0
- data/data/config/target.yaml +142 -0
- data/data/config/target_config.yaml +94 -0
- data/data/config/telemetry.yaml +87 -0
- data/data/config/telemetry_modifiers.yaml +159 -0
- data/data/config/tool.yaml +63 -0
- data/data/config/unknown.yaml +3 -0
- data/data/config/widgets.yaml +1505 -0
- data/ext/mkrf_conf.rb +49 -0
- data/ext/openc3/ext/array/array.c +122 -0
- data/ext/openc3/ext/array/extconf.rb +13 -0
- data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
- data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
- data/ext/openc3/ext/config_parser/config_parser.c +280 -0
- data/ext/openc3/ext/config_parser/extconf.rb +13 -0
- data/ext/openc3/ext/crc/crc.c +351 -0
- data/ext/openc3/ext/crc/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
- data/ext/openc3/ext/packet/extconf.rb +13 -0
- data/ext/openc3/ext/packet/packet.c +318 -0
- data/ext/openc3/ext/platform/extconf.rb +13 -0
- data/ext/openc3/ext/platform/platform.c +134 -0
- data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
- data/ext/openc3/ext/string/extconf.rb +13 -0
- data/ext/openc3/ext/string/string.c +63 -0
- data/ext/openc3/ext/structure/structure.c +1719 -0
- data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
- data/ext/openc3/ext/telemetry/extconf.rb +13 -0
- data/ext/openc3/ext/telemetry/telemetry.c +336 -0
- data/lib/cosmos.rb +20 -0
- data/lib/cosmosc2.rb +20 -0
- data/lib/openc3/api/api.rb +39 -0
- data/lib/openc3/api/authorized_api.rb +30 -0
- data/lib/openc3/api/cmd_api.rb +451 -0
- data/lib/openc3/api/config_api.rb +58 -0
- data/lib/openc3/api/interface_api.rb +117 -0
- data/lib/openc3/api/limits_api.rb +375 -0
- data/lib/openc3/api/router_api.rb +117 -0
- data/lib/openc3/api/settings_api.rb +70 -0
- data/lib/openc3/api/target_api.rb +78 -0
- data/lib/openc3/api/tlm_api.rb +455 -0
- data/lib/openc3/bridge/bridge.rb +54 -0
- data/lib/openc3/bridge/bridge_config.rb +167 -0
- data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
- data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
- data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
- data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
- data/lib/openc3/config/config_parser.rb +549 -0
- data/lib/openc3/config/meta_config_parser.rb +74 -0
- data/lib/openc3/conversions/conversion.rb +70 -0
- data/lib/openc3/conversions/generic_conversion.rb +83 -0
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
- data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
- data/lib/openc3/conversions/processor_conversion.rb +70 -0
- data/lib/openc3/conversions/received_count_conversion.rb +38 -0
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
- data/lib/openc3/conversions.rb +34 -0
- data/lib/openc3/core_ext/array.rb +416 -0
- data/lib/openc3/core_ext/binding.rb +29 -0
- data/lib/openc3/core_ext/class.rb +72 -0
- data/lib/openc3/core_ext/exception.rb +61 -0
- data/lib/openc3/core_ext/file.rb +83 -0
- data/lib/openc3/core_ext/hash.rb +37 -0
- data/lib/openc3/core_ext/io.rb +134 -0
- data/lib/openc3/core_ext/kernel.rb +42 -0
- data/lib/openc3/core_ext/math.rb +128 -0
- data/lib/openc3/core_ext/matrix.rb +156 -0
- data/lib/openc3/core_ext/objectspace.rb +36 -0
- data/lib/openc3/core_ext/openc3_io.rb +57 -0
- data/lib/openc3/core_ext/range.rb +27 -0
- data/lib/openc3/core_ext/socket.rb +38 -0
- data/lib/openc3/core_ext/string.rb +389 -0
- data/lib/openc3/core_ext/stringio.rb +33 -0
- data/lib/openc3/core_ext/time.rb +508 -0
- data/lib/openc3/core_ext.rb +36 -0
- data/lib/openc3/interfaces/interface.rb +498 -0
- data/lib/openc3/interfaces/linc_interface.rb +475 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
- data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
- data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
- data/lib/openc3/interfaces/serial_interface.rb +94 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
- data/lib/openc3/interfaces/stream_interface.rb +81 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
- data/lib/openc3/interfaces/udp_interface.rb +169 -0
- data/lib/openc3/interfaces.rb +44 -0
- data/lib/openc3/io/buffered_file.rb +109 -0
- data/lib/openc3/io/io_multiplexer.rb +80 -0
- data/lib/openc3/io/json_api_object.rb +208 -0
- data/lib/openc3/io/json_drb.rb +335 -0
- data/lib/openc3/io/json_drb_object.rb +114 -0
- data/lib/openc3/io/json_drb_rack.rb +84 -0
- data/lib/openc3/io/json_rpc.rb +420 -0
- data/lib/openc3/io/openc3_snmp.rb +58 -0
- data/lib/openc3/io/posix_serial_driver.rb +156 -0
- data/lib/openc3/io/raw_logger.rb +167 -0
- data/lib/openc3/io/raw_logger_pair.rb +77 -0
- data/lib/openc3/io/serial_driver.rb +105 -0
- data/lib/openc3/io/stderr.rb +43 -0
- data/lib/openc3/io/stdout.rb +43 -0
- data/lib/openc3/io/udp_sockets.rb +194 -0
- data/lib/openc3/io/win32_serial_driver.rb +196 -0
- data/lib/openc3/logs/log_writer.rb +302 -0
- data/lib/openc3/logs/packet_log_constants.rb +62 -0
- data/lib/openc3/logs/packet_log_reader.rb +345 -0
- data/lib/openc3/logs/packet_log_writer.rb +299 -0
- data/lib/openc3/logs/text_log_writer.rb +68 -0
- data/lib/openc3/logs.rb +25 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
- data/lib/openc3/microservices/decom_microservice.rb +136 -0
- data/lib/openc3/microservices/interface_microservice.rb +532 -0
- data/lib/openc3/microservices/log_microservice.rb +108 -0
- data/lib/openc3/microservices/microservice.rb +204 -0
- data/lib/openc3/microservices/plugin_microservice.rb +43 -0
- data/lib/openc3/microservices/reaction_microservice.rb +541 -0
- data/lib/openc3/microservices/reducer_microservice.rb +313 -0
- data/lib/openc3/microservices/router_microservice.rb +44 -0
- data/lib/openc3/microservices/text_log_microservice.rb +84 -0
- data/lib/openc3/microservices/timeline_microservice.rb +363 -0
- data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
- data/lib/openc3/models/activity_model.rb +319 -0
- data/lib/openc3/models/auth_model.rb +65 -0
- data/lib/openc3/models/cvt_model.rb +185 -0
- data/lib/openc3/models/environment_model.rb +58 -0
- data/lib/openc3/models/gem_model.rb +137 -0
- data/lib/openc3/models/info_model.rb +31 -0
- data/lib/openc3/models/interface_model.rb +281 -0
- data/lib/openc3/models/interface_status_model.rb +117 -0
- data/lib/openc3/models/metadata_model.rb +139 -0
- data/lib/openc3/models/metric_model.rb +59 -0
- data/lib/openc3/models/microservice_model.rb +206 -0
- data/lib/openc3/models/microservice_status_model.rb +74 -0
- data/lib/openc3/models/model.rb +204 -0
- data/lib/openc3/models/note_model.rb +122 -0
- data/lib/openc3/models/notification_model.rb +40 -0
- data/lib/openc3/models/ping_model.rb +35 -0
- data/lib/openc3/models/plugin_model.rb +292 -0
- data/lib/openc3/models/process_status_model.rb +76 -0
- data/lib/openc3/models/reaction_model.rb +322 -0
- data/lib/openc3/models/reducer_model.rb +65 -0
- data/lib/openc3/models/router_model.rb +35 -0
- data/lib/openc3/models/router_status_model.rb +27 -0
- data/lib/openc3/models/scope_model.rb +153 -0
- data/lib/openc3/models/settings_model.rb +55 -0
- data/lib/openc3/models/sorted_model.rb +167 -0
- data/lib/openc3/models/target_model.rb +759 -0
- data/lib/openc3/models/timeline_model.rb +154 -0
- data/lib/openc3/models/tool_config_model.rb +38 -0
- data/lib/openc3/models/tool_model.rb +262 -0
- data/lib/openc3/models/trigger_group_model.rb +186 -0
- data/lib/openc3/models/trigger_model.rb +330 -0
- data/lib/openc3/models/widget_model.rb +138 -0
- data/lib/openc3/operators/microservice_operator.rb +128 -0
- data/lib/openc3/operators/operator.rb +277 -0
- data/lib/openc3/packets/binary_accessor.rb +1207 -0
- data/lib/openc3/packets/commands.rb +373 -0
- data/lib/openc3/packets/json_packet.rb +134 -0
- data/lib/openc3/packets/limits.rb +271 -0
- data/lib/openc3/packets/limits_response.rb +53 -0
- data/lib/openc3/packets/packet.rb +1168 -0
- data/lib/openc3/packets/packet_config.rb +625 -0
- data/lib/openc3/packets/packet_item.rb +586 -0
- data/lib/openc3/packets/packet_item_limits.rb +162 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
- data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
- data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
- data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
- data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
- data/lib/openc3/packets/parsers/state_parser.rb +127 -0
- data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
- data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
- data/lib/openc3/packets/structure.rb +553 -0
- data/lib/openc3/packets/structure_item.rb +365 -0
- data/lib/openc3/packets/telemetry.rb +487 -0
- data/lib/openc3/processors/processor.rb +86 -0
- data/lib/openc3/processors/statistics_processor.rb +82 -0
- data/lib/openc3/processors/watermark_processor.rb +58 -0
- data/lib/openc3/processors.rb +24 -0
- data/lib/openc3/script/api_shared.rb +828 -0
- data/lib/openc3/script/calendar.rb +89 -0
- data/lib/openc3/script/commands.rb +227 -0
- data/lib/openc3/script/exceptions.rb +29 -0
- data/lib/openc3/script/extract.rb +161 -0
- data/lib/openc3/script/limits.rb +60 -0
- data/lib/openc3/script/script.rb +299 -0
- data/lib/openc3/script/script_runner.rb +238 -0
- data/lib/openc3/script/storage.rb +146 -0
- data/lib/openc3/script/suite.rb +542 -0
- data/lib/openc3/script/suite_results.rb +196 -0
- data/lib/openc3/script/suite_runner.rb +217 -0
- data/lib/openc3/script.rb +21 -0
- data/lib/openc3/streams/serial_stream.rb +167 -0
- data/lib/openc3/streams/stream.rb +63 -0
- data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
- data/lib/openc3/system/system.rb +127 -0
- data/lib/openc3/system/system_config.rb +411 -0
- data/lib/openc3/system/target.rb +269 -0
- data/lib/openc3/system.rb +24 -0
- data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
- data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
- data/lib/openc3/tools/table_manager/table.rb +77 -0
- data/lib/openc3/tools/table_manager/table_config.rb +273 -0
- data/lib/openc3/tools/table_manager/table_item.rb +90 -0
- data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
- data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
- data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
- data/lib/openc3/tools/test_runner/test.rb +67 -0
- data/lib/openc3/top_level.rb +595 -0
- data/lib/openc3/topics/autonomic_topic.rb +52 -0
- data/lib/openc3/topics/calendar_topic.rb +44 -0
- data/lib/openc3/topics/command_decom_topic.rb +76 -0
- data/lib/openc3/topics/command_topic.rb +83 -0
- data/lib/openc3/topics/config_topic.rb +68 -0
- data/lib/openc3/topics/interface_topic.rb +73 -0
- data/lib/openc3/topics/limits_event_topic.rb +109 -0
- data/lib/openc3/topics/notifications_topic.rb +28 -0
- data/lib/openc3/topics/router_topic.rb +85 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
- data/lib/openc3/topics/telemetry_topic.rb +36 -0
- data/lib/openc3/topics/timeline_topic.rb +45 -0
- data/lib/openc3/topics/topic.rb +53 -0
- data/lib/openc3/utilities/authentication.rb +141 -0
- data/lib/openc3/utilities/authorization.rb +51 -0
- data/lib/openc3/utilities/crc.rb +278 -0
- data/lib/openc3/utilities/csv.rb +153 -0
- data/lib/openc3/utilities/logger.rb +187 -0
- data/lib/openc3/utilities/message_log.rb +91 -0
- data/lib/openc3/utilities/metric.rb +141 -0
- data/lib/openc3/utilities/process_manager.rb +139 -0
- data/lib/openc3/utilities/quaternion.rb +257 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
- data/lib/openc3/utilities/s3.rb +202 -0
- data/lib/openc3/utilities/s3_autoload.rb +9 -0
- data/lib/openc3/utilities/s3_file_cache.rb +274 -0
- data/lib/openc3/utilities/simulated_target.rb +117 -0
- data/lib/openc3/utilities/sleeper.rb +51 -0
- data/lib/openc3/utilities/store.rb +23 -0
- data/lib/openc3/utilities/store_autoload.rb +237 -0
- data/lib/openc3/utilities/zip.rb +21 -0
- data/lib/openc3/utilities.rb +35 -0
- data/lib/openc3/version.rb +14 -0
- data/lib/openc3/win32/excel.rb +132 -0
- data/lib/openc3/win32/win32.rb +402 -0
- data/lib/openc3/win32/win32_main.rb +333 -0
- data/lib/openc3.rb +49 -0
- data/tasks/gemfile_stats.rake +113 -0
- data/tasks/spec.rake +30 -0
- data/templates/plugin-template/README.md +15 -0
- data/templates/plugin-template/Rakefile +12 -0
- data/templates/plugin-template/plugin.gemspec +23 -0
- data/templates/plugin-template/plugin.txt +9 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
- data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
- data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
- data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
- data/templates/plugin-template/targets/TARGET/target.txt +5 -0
- metadata +849 -0
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
require 'openc3/config/config_parser'
|
|
21
|
+
require 'openc3/packets/packet_config'
|
|
22
|
+
require 'openc3/packets/commands'
|
|
23
|
+
require 'openc3/packets/telemetry'
|
|
24
|
+
require 'openc3/packets/limits'
|
|
25
|
+
require 'openc3/system/target'
|
|
26
|
+
require 'openc3/logs'
|
|
27
|
+
require 'fileutils'
|
|
28
|
+
require 'openc3/utilities/zip'
|
|
29
|
+
require 'bundler'
|
|
30
|
+
require 'thread'
|
|
31
|
+
|
|
32
|
+
module OpenC3
|
|
33
|
+
# System is the primary entry point into the OpenC3 framework. It captures
|
|
34
|
+
# system wide configuration items such as the available ports and paths to
|
|
35
|
+
# various files used by the system. The #commands, #telemetry, and #limits
|
|
36
|
+
# class variables are the primary access points for applications. The
|
|
37
|
+
# #targets variable provides access to all the targets defined by the system.
|
|
38
|
+
# Its primary responsibily is to load the system configuration file and
|
|
39
|
+
# create all the Target instances. It also saves and restores configurations
|
|
40
|
+
# using a hashing checksum over the entire configuration to detect changes.
|
|
41
|
+
class SystemConfig
|
|
42
|
+
# @return [String] Base path of the configuration
|
|
43
|
+
attr_reader :userpath
|
|
44
|
+
# @return [Boolean] Whether to use sound for alerts
|
|
45
|
+
attr_reader :sound
|
|
46
|
+
# @return [Boolean] Whether to use DNS to lookup IP addresses or not
|
|
47
|
+
attr_reader :use_dns
|
|
48
|
+
# @return [Hash<String,Target>] Hash of all the known targets
|
|
49
|
+
attr_reader :targets
|
|
50
|
+
# @return [Integer] The number of seconds before a telemetry packet is considered stale
|
|
51
|
+
attr_reader :staleness_seconds
|
|
52
|
+
# @return [Boolean] Whether to use UTC or local times
|
|
53
|
+
attr_reader :use_utc
|
|
54
|
+
# @return [Hash<String,String>] Hash of the text/color to use for the classificaiton banner
|
|
55
|
+
attr_reader :classificiation_banner
|
|
56
|
+
|
|
57
|
+
# @param filename [String] Full path to the system configuration file to
|
|
58
|
+
# read.
|
|
59
|
+
def initialize(filename)
|
|
60
|
+
reset_variables(filename)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Resets the System's internal state to defaults.
|
|
64
|
+
#
|
|
65
|
+
# @param filename [String] Path to system.txt config file to process. Defaults to config/system/system.txt
|
|
66
|
+
def reset_variables(filename)
|
|
67
|
+
@targets = {}
|
|
68
|
+
@config = nil
|
|
69
|
+
@commands = nil
|
|
70
|
+
@telemetry = nil
|
|
71
|
+
@limits = nil
|
|
72
|
+
@sound = false
|
|
73
|
+
@use_dns = false
|
|
74
|
+
@staleness_seconds = 30
|
|
75
|
+
@use_utc = false
|
|
76
|
+
@meta_init_filename = nil
|
|
77
|
+
@userpath = File.expand_path(File.join(File.dirname(filename), '..', '..'))
|
|
78
|
+
process_file(filename, File.join(@userpath, 'config', 'targets'))
|
|
79
|
+
@initial_filename = filename
|
|
80
|
+
@initial_config = nil
|
|
81
|
+
@config_blacklist = {}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Process the system.txt configuration file
|
|
85
|
+
#
|
|
86
|
+
# @param filename [String] The configuration file
|
|
87
|
+
# @param targets_config_dir [String] The configuration directory to
|
|
88
|
+
# search for the target command and telemetry files.
|
|
89
|
+
def process_file(filename, targets_config_dir)
|
|
90
|
+
parser = ConfigParser.new("https://openc3.com/docs/v5")
|
|
91
|
+
|
|
92
|
+
# First pass - Everything except targets
|
|
93
|
+
parser.parse_file(filename) do |keyword, parameters|
|
|
94
|
+
case keyword
|
|
95
|
+
when 'AUTO_DECLARE_TARGETS', 'DECLARE_TARGET', 'DECLARE_GEM_TARGET', 'DECLARE_GEM_MULTI_TARGET'
|
|
96
|
+
# Will be handled by second pass
|
|
97
|
+
|
|
98
|
+
when 'PORT', 'LISTEN_HOST', 'CONNECT_HOST', 'PATH', 'DEFAULT_PACKET_LOG_WRITER', 'DEFAULT_PACKET_LOG_READER',
|
|
99
|
+
'ALLOW_ACCESS', 'ADD_HASH_FILE', 'ADD_MD5_FILE', 'HASHING_ALGORITHM'
|
|
100
|
+
# Not used by OpenC3 5
|
|
101
|
+
|
|
102
|
+
when 'ENABLE_SOUND'
|
|
103
|
+
usage = "#{keyword}"
|
|
104
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
105
|
+
@sound = true
|
|
106
|
+
|
|
107
|
+
when 'DISABLE_DNS'
|
|
108
|
+
usage = "#{keyword}"
|
|
109
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
110
|
+
@use_dns = false
|
|
111
|
+
|
|
112
|
+
when 'ENABLE_DNS'
|
|
113
|
+
usage = "#{keyword}"
|
|
114
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
115
|
+
@use_dns = true
|
|
116
|
+
|
|
117
|
+
when 'STALENESS_SECONDS'
|
|
118
|
+
parser.verify_num_parameters(1, 1, "#{keyword} <Value in Seconds>")
|
|
119
|
+
@staleness_seconds = Integer(parameters[0])
|
|
120
|
+
|
|
121
|
+
when 'META_INIT'
|
|
122
|
+
parser.verify_num_parameters(1, 1, "#{keyword} <Filename>")
|
|
123
|
+
@meta_init_filename = ConfigParser.handle_nil(parameters[0])
|
|
124
|
+
|
|
125
|
+
when 'TIME_ZONE_UTC'
|
|
126
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
127
|
+
@use_utc = true
|
|
128
|
+
|
|
129
|
+
when 'CLASSIFICATION'
|
|
130
|
+
parser.verify_num_parameters(2, 4, "#{keyword} <Display_Text> <Color Name|Red> <Green> <Blue>")
|
|
131
|
+
# Determine if the OpenC3 color already exists, otherwise create a new one
|
|
132
|
+
if OpenC3.constants.include? parameters[1].upcase.to_sym
|
|
133
|
+
# We were given a named color that already exists in OpenC3
|
|
134
|
+
color = parameters[1].upcase
|
|
135
|
+
else
|
|
136
|
+
if parameters.length < 4
|
|
137
|
+
# We were given a named color, but it didn't exist in OpenC3 already
|
|
138
|
+
color = OpenC3.getColor(parameters[1].upcase)
|
|
139
|
+
else
|
|
140
|
+
# We were given RGB values
|
|
141
|
+
color = OpenC3.getColor(parameters[1], parameters[2], parameters[3])
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
@classificiation_banner = { 'display_text' => parameters[0],
|
|
146
|
+
'color' => color }
|
|
147
|
+
|
|
148
|
+
else
|
|
149
|
+
# blank lines will have a nil keyword and should not raise an exception
|
|
150
|
+
raise parser.error("Unknown keyword '#{keyword}'") if keyword
|
|
151
|
+
end # case keyword
|
|
152
|
+
end # parser.parse_file
|
|
153
|
+
|
|
154
|
+
# Explicitly set up time to use UTC or local
|
|
155
|
+
if @use_utc
|
|
156
|
+
Time.use_utc()
|
|
157
|
+
else
|
|
158
|
+
Time.use_local()
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Second pass - Process targets
|
|
162
|
+
process_targets(parser, filename, targets_config_dir)
|
|
163
|
+
end # def process_file
|
|
164
|
+
|
|
165
|
+
# Parse the system.txt configuration file looking for keywords associated
|
|
166
|
+
# with targets and create all the Target instances in the system.
|
|
167
|
+
#
|
|
168
|
+
# @param parser [ConfigParser] Parser created by process_file
|
|
169
|
+
# @param filename (see #process_file)
|
|
170
|
+
# @param targets_config_dir (see #process_file)
|
|
171
|
+
def process_targets(parser, filename, targets_config_dir)
|
|
172
|
+
parser.parse_file(filename) do |keyword, parameters|
|
|
173
|
+
case keyword
|
|
174
|
+
when 'AUTO_DECLARE_TARGETS'
|
|
175
|
+
usage = "#{keyword}"
|
|
176
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
177
|
+
path = File.join(@userpath, 'config', 'targets')
|
|
178
|
+
unless File.exist? path
|
|
179
|
+
raise parser.error("#{path} must exist", usage)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
dirs = []
|
|
183
|
+
configuration_dir = File.join(@userpath, 'config', 'targets')
|
|
184
|
+
Dir.foreach(configuration_dir) { |dir_filename| dirs << dir_filename }
|
|
185
|
+
dirs.sort!
|
|
186
|
+
dirs.each do |dir_filename|
|
|
187
|
+
if dir_filename[0] != '.'
|
|
188
|
+
if dir_filename == dir_filename.upcase
|
|
189
|
+
# If any of the targets original directory name matches the
|
|
190
|
+
# current directory then it must have been already processed by
|
|
191
|
+
# DECLARE_TARGET so we skip it.
|
|
192
|
+
next if @targets.select { |name, target| target.original_name == dir_filename }.length > 0
|
|
193
|
+
next if dir_filename == 'SYSTEM'
|
|
194
|
+
|
|
195
|
+
target = Target.new(dir_filename, nil, targets_config_dir)
|
|
196
|
+
@targets[target.name] = target
|
|
197
|
+
else
|
|
198
|
+
raise parser.error("Target folder must be uppercase: '#{dir_filename}'")
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
auto_detect_gem_based_targets()
|
|
203
|
+
|
|
204
|
+
when 'DECLARE_TARGET'
|
|
205
|
+
usage = "#{keyword} <TARGET NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
|
|
206
|
+
parser.verify_num_parameters(1, 3, usage)
|
|
207
|
+
target_name = parameters[0].to_s.upcase
|
|
208
|
+
|
|
209
|
+
if targets_config_dir
|
|
210
|
+
folder_name = File.join(targets_config_dir, target_name)
|
|
211
|
+
else
|
|
212
|
+
folder_name = File.join(@userpath, 'config', 'targets', target_name)
|
|
213
|
+
end
|
|
214
|
+
unless Dir.exist?(folder_name)
|
|
215
|
+
raise parser.error("Target folder must exist '#{folder_name}'.")
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
substitute_name = nil
|
|
219
|
+
substitute_name = ConfigParser.handle_nil(parameters[1])
|
|
220
|
+
if substitute_name
|
|
221
|
+
substitute_name = substitute_name.to_s.upcase
|
|
222
|
+
original_name = target_name
|
|
223
|
+
target_name = substitute_name
|
|
224
|
+
else
|
|
225
|
+
original_name = nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[2]))
|
|
229
|
+
@targets[target.name] = target
|
|
230
|
+
|
|
231
|
+
when 'DECLARE_GEM_TARGET'
|
|
232
|
+
usage = "#{keyword} <GEM NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
|
|
233
|
+
parser.verify_num_parameters(1, 3, usage)
|
|
234
|
+
# Remove 'openc3' from the gem name 'openc3-power-supply'
|
|
235
|
+
target_name = parameters[0].split('-')[1..-1].join('-').to_s.upcase
|
|
236
|
+
gem_dir = Gem::Specification.find_by_name(parameters[0]).gem_dir
|
|
237
|
+
substitute_name = nil
|
|
238
|
+
substitute_name = ConfigParser.handle_nil(parameters[1])
|
|
239
|
+
if substitute_name
|
|
240
|
+
substitute_name = substitute_name.to_s.upcase
|
|
241
|
+
original_name = target_name
|
|
242
|
+
target_name = substitute_name
|
|
243
|
+
else
|
|
244
|
+
original_name = nil
|
|
245
|
+
end
|
|
246
|
+
target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[2]), gem_dir)
|
|
247
|
+
@targets[target.name] = target
|
|
248
|
+
|
|
249
|
+
when 'DECLARE_GEM_MULTI_TARGET'
|
|
250
|
+
usage = "#{keyword} <GEM NAME> <TARGET NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
|
|
251
|
+
parser.verify_num_parameters(2, 4, usage)
|
|
252
|
+
target_name = parameters[1].to_s.upcase
|
|
253
|
+
gem_dir = Gem::Specification.find_by_name(parameters[0]).gem_dir
|
|
254
|
+
gem_dir = File.join(gem_dir, target_name)
|
|
255
|
+
substitute_name = nil
|
|
256
|
+
substitute_name = ConfigParser.handle_nil(parameters[2])
|
|
257
|
+
if substitute_name
|
|
258
|
+
substitute_name = substitute_name.to_s.upcase
|
|
259
|
+
original_name = target_name
|
|
260
|
+
target_name = substitute_name
|
|
261
|
+
else
|
|
262
|
+
original_name = nil
|
|
263
|
+
end
|
|
264
|
+
target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[3]), gem_dir)
|
|
265
|
+
@targets[target.name] = target
|
|
266
|
+
|
|
267
|
+
end # case keyword
|
|
268
|
+
end # parser.parse_file
|
|
269
|
+
|
|
270
|
+
# Make sure SYSTEM target is always present and added last
|
|
271
|
+
unless @targets.key?('SYSTEM')
|
|
272
|
+
target = Target.new('SYSTEM', nil, targets_config_dir)
|
|
273
|
+
@targets[target.name] = target
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
protected
|
|
278
|
+
|
|
279
|
+
def unzip(zip_file_name)
|
|
280
|
+
zip_dir = File.join(@paths['TMP'], File.basename(zip_file_name, ".*"))
|
|
281
|
+
# Only unzip if we have to. We assume the unzipped directory structure is
|
|
282
|
+
# intact. If not they'll get a popop with the errors encountered when
|
|
283
|
+
# loading the configuration.
|
|
284
|
+
unless File.exist? zip_dir
|
|
285
|
+
Zip::File.open(zip_file_name) do |zip_file|
|
|
286
|
+
zip_file.each do |entry|
|
|
287
|
+
path = File.join(@paths['TMP'], entry.name)
|
|
288
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
289
|
+
zip_file.extract(entry, path) unless File.exist?(path)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
zip_dir
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# A helper method to make the zip writing recursion work
|
|
297
|
+
def write_zip_entries(base_dir, entries, zip_path, io)
|
|
298
|
+
io.add(zip_path, base_dir) # Add the directory whether it has entries or not
|
|
299
|
+
entries.each do |e|
|
|
300
|
+
zip_file_path = File.join(zip_path, e)
|
|
301
|
+
disk_file_path = File.join(base_dir, e)
|
|
302
|
+
if File.directory? disk_file_path
|
|
303
|
+
recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
|
304
|
+
else
|
|
305
|
+
put_into_archive(disk_file_path, io, zip_file_path)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
|
311
|
+
io.add(zip_file_path, disk_file_path)
|
|
312
|
+
entries = Dir.entries(disk_file_path) - %w(. ..)
|
|
313
|
+
write_zip_entries(disk_file_path, entries, zip_file_path, io)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def put_into_archive(disk_file_path, io, zip_file_path)
|
|
317
|
+
io.get_output_stream(zip_file_path) do |f|
|
|
318
|
+
data = nil
|
|
319
|
+
File.open(disk_file_path, 'rb') do |file|
|
|
320
|
+
data = file.read
|
|
321
|
+
end
|
|
322
|
+
f.write(data)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def auto_detect_gem_based_targets
|
|
327
|
+
Bundler.load.specs.each do |spec|
|
|
328
|
+
spec_name_split = spec.name.split('-')
|
|
329
|
+
if spec_name_split.length > 1 && (spec_name_split[0] == 'openc3')
|
|
330
|
+
# search for multiple targets packaged in a single gem
|
|
331
|
+
dirs = []
|
|
332
|
+
Dir.foreach(spec.gem_dir) { |dir_filename| dirs << dir_filename }
|
|
333
|
+
dirs.sort!
|
|
334
|
+
dirs.each do |dir_filename|
|
|
335
|
+
if dir_filename == "."
|
|
336
|
+
# check the base directory
|
|
337
|
+
curr_dir = spec.gem_dir
|
|
338
|
+
target_name = spec_name_split[1..-1].join('-').to_s.upcase
|
|
339
|
+
else
|
|
340
|
+
# check for targets in other directories 1 level deep
|
|
341
|
+
next if dir_filename[0] == '.' # skip dot directories and ".."
|
|
342
|
+
next if dir_filename != dir_filename.upcase # skip non uppercase directories
|
|
343
|
+
|
|
344
|
+
curr_dir = File.join(spec.gem_dir, dir_filename)
|
|
345
|
+
target_name = dir_filename
|
|
346
|
+
end
|
|
347
|
+
# check for the cmd_tlm directory - if it has it, then we have found a target
|
|
348
|
+
if File.directory?(File.join(curr_dir, 'cmd_tlm'))
|
|
349
|
+
# If any of the targets original directory name matches the
|
|
350
|
+
# current directory then it must have been already processed by
|
|
351
|
+
# DECLARE_TARGET so we skip it.
|
|
352
|
+
next if @targets.select { |name, target| target.original_name == target_name }.length > 0
|
|
353
|
+
|
|
354
|
+
target = Target.new(target_name, nil, nil, nil, spec.gem_dir)
|
|
355
|
+
@targets[target.name] = target
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
rescue Bundler::GemfileNotFound
|
|
361
|
+
# No Gemfile - so no gem based targets
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def save_configuration
|
|
365
|
+
configuration = find_configuration(@config.name)
|
|
366
|
+
configuration = File.join(@paths['SAVED_CONFIG'], File.build_timestamped_filename([@config.name], '.zip')) unless configuration
|
|
367
|
+
unless File.exist?(configuration)
|
|
368
|
+
configuration_tmp = File.join(@paths['SAVED_CONFIG'], File.build_timestamped_filename(['tmp_' + @config.name], '.zip.tmp'))
|
|
369
|
+
begin
|
|
370
|
+
Zip.continue_on_exists_proc = true
|
|
371
|
+
Zip::File.open(configuration_tmp, Zip::File::CREATE) do |zipfile|
|
|
372
|
+
zip_file_path = File.basename(configuration, ".zip")
|
|
373
|
+
zipfile.mkdir zip_file_path
|
|
374
|
+
|
|
375
|
+
# Copy target files into archive
|
|
376
|
+
zip_targets = []
|
|
377
|
+
@targets.each do |target_name, target|
|
|
378
|
+
entries = Dir.entries(target.dir) - %w(. ..)
|
|
379
|
+
zip_target = File.join(zip_file_path, target.original_name)
|
|
380
|
+
# Check the stored list of targets. We can't ask the zip file
|
|
381
|
+
# itself because it's in progress and hasn't been saved
|
|
382
|
+
unless zip_targets.include?(zip_target)
|
|
383
|
+
write_zip_entries(target.dir, entries, zip_target, zipfile)
|
|
384
|
+
zip_targets << zip_target
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Create custom system.txt file
|
|
389
|
+
zipfile.get_output_stream(File.join(zip_file_path, 'system.txt')) do |file|
|
|
390
|
+
@targets.each do |target_name, target|
|
|
391
|
+
target_filename = File.basename(target.filename)
|
|
392
|
+
target_filename = nil unless File.exist?(target.filename)
|
|
393
|
+
# Create a newline character since Zip opens files in binary mode
|
|
394
|
+
newline = Kernel.is_windows? ? "\r\n" : "\n"
|
|
395
|
+
if target.substitute
|
|
396
|
+
file.write "DECLARE_TARGET #{target.original_name} #{target.name} #{target_filename}#{newline}"
|
|
397
|
+
else
|
|
398
|
+
file.write "DECLARE_TARGET #{target.name} nil #{target_filename}#{newline}"
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
File.rename(configuration_tmp, configuration)
|
|
404
|
+
File.chmod(0444, configuration) # Mark readonly
|
|
405
|
+
rescue Exception => error
|
|
406
|
+
Logger.error "Problem saving configuration to #{configuration}: #{error.class}:#{error.message}\n#{error.backtrace.join("\n")}\n"
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
@@ -0,0 +1,269 @@
|
|
|
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
|
+
require 'openc3/config/config_parser'
|
|
21
|
+
require 'pathname'
|
|
22
|
+
|
|
23
|
+
module OpenC3
|
|
24
|
+
# Target encapsulates the information about a OpenC3 target. Targets are
|
|
25
|
+
# accessed through interfaces and have command and telemetry definition files
|
|
26
|
+
# which define their access.
|
|
27
|
+
class Target
|
|
28
|
+
# @return [String] Name of the target. This can be overridden when
|
|
29
|
+
# the system processes the target.
|
|
30
|
+
attr_reader :name
|
|
31
|
+
|
|
32
|
+
# @return [Array<String>] List of filenames that must be required by Ruby
|
|
33
|
+
# before parsing the command and telemetry definitions for this target
|
|
34
|
+
attr_reader :requires
|
|
35
|
+
|
|
36
|
+
# @return [Array<String>] List of parameters that should be ignored. Tools
|
|
37
|
+
# which access this target should not display or manipulate these
|
|
38
|
+
# parameters.
|
|
39
|
+
attr_reader :ignored_parameters
|
|
40
|
+
|
|
41
|
+
# @return [Array<String>] List of items that should be ignored. Tools
|
|
42
|
+
# which access this target should not display or manipulate these
|
|
43
|
+
# items.
|
|
44
|
+
attr_reader :ignored_items
|
|
45
|
+
|
|
46
|
+
# @return [Array<String>] List of configuration files which define the
|
|
47
|
+
# commands and telemetry for this target
|
|
48
|
+
attr_reader :cmd_tlm_files
|
|
49
|
+
|
|
50
|
+
# @return [String] Target filename for this target
|
|
51
|
+
attr_reader :filename
|
|
52
|
+
|
|
53
|
+
# @return [String] The directory which contains this target
|
|
54
|
+
attr_reader :dir
|
|
55
|
+
|
|
56
|
+
# @return [Interface] The interface used to access the target
|
|
57
|
+
attr_accessor :interface
|
|
58
|
+
|
|
59
|
+
# @return [Integer] The number of command packets send to this target
|
|
60
|
+
attr_accessor :cmd_cnt
|
|
61
|
+
|
|
62
|
+
# @return [Integer] The number of telemetry packets received from this target
|
|
63
|
+
attr_accessor :tlm_cnt
|
|
64
|
+
|
|
65
|
+
# @return [Boolean] Indicates if all command packets identify using different fields
|
|
66
|
+
attr_accessor :cmd_unique_id_mode
|
|
67
|
+
|
|
68
|
+
# @return [Boolean] Indicates if telemetry packets identify using different fields
|
|
69
|
+
attr_accessor :tlm_unique_id_mode
|
|
70
|
+
|
|
71
|
+
# @return [String] Id of the target configuration
|
|
72
|
+
attr_accessor :id
|
|
73
|
+
|
|
74
|
+
# Creates a new target by processing the target.txt file in the directory
|
|
75
|
+
# given by the path joined with the target_name. Records all the command
|
|
76
|
+
# and telemetry definition files found in the targets cmd_tlm directory.
|
|
77
|
+
# System uses this list and processes them using PacketConfig.
|
|
78
|
+
#
|
|
79
|
+
# @param target_name [String] The name of the target.
|
|
80
|
+
# @param path [String] Path to the target directory
|
|
81
|
+
# @param gem_path [String] Path to the gem file or nil if there is no gem
|
|
82
|
+
def initialize(target_name, path, gem_path = nil)
|
|
83
|
+
@requires = []
|
|
84
|
+
@ignored_parameters = []
|
|
85
|
+
@ignored_items = []
|
|
86
|
+
@cmd_tlm_files = []
|
|
87
|
+
# @auto_screen_substitute = false
|
|
88
|
+
@interface = nil
|
|
89
|
+
@routers = []
|
|
90
|
+
@cmd_cnt = 0
|
|
91
|
+
@tlm_cnt = 0
|
|
92
|
+
@cmd_unique_id_mode = false
|
|
93
|
+
@tlm_unique_id_mode = false
|
|
94
|
+
@name = target_name.clone.upcase.freeze
|
|
95
|
+
get_target_dir(path, gem_path)
|
|
96
|
+
process_target_config_file()
|
|
97
|
+
|
|
98
|
+
# If target.txt didn't specify specific cmd/tlm files then add everything
|
|
99
|
+
if @cmd_tlm_files.empty?
|
|
100
|
+
@cmd_tlm_files = add_all_cmd_tlm()
|
|
101
|
+
else
|
|
102
|
+
add_cmd_tlm_partials()
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Parses the target configuration file
|
|
107
|
+
#
|
|
108
|
+
# @param filename [String] The target configuration file to parse
|
|
109
|
+
def process_file(filename)
|
|
110
|
+
Logger.instance.info "Processing target definition in file '#{filename}'"
|
|
111
|
+
parser = ConfigParser.new("https://openc3.com/docs/v5/target")
|
|
112
|
+
parser.parse_file(filename) do |keyword, parameters|
|
|
113
|
+
case keyword
|
|
114
|
+
when 'REQUIRE'
|
|
115
|
+
usage = "#{keyword} <FILENAME>"
|
|
116
|
+
parser.verify_num_parameters(1, 1, usage)
|
|
117
|
+
filename = File.join(@dir, 'lib', parameters[0])
|
|
118
|
+
begin
|
|
119
|
+
# Require absolute path to file in target lib folder. Prevents name
|
|
120
|
+
# conflicts at the require step
|
|
121
|
+
OpenC3.disable_warnings do
|
|
122
|
+
OpenC3.require_file(filename, false)
|
|
123
|
+
end
|
|
124
|
+
rescue LoadError
|
|
125
|
+
begin
|
|
126
|
+
# If we couldn't load at the target/lib level check everywhere
|
|
127
|
+
OpenC3.disable_warnings do
|
|
128
|
+
filename = parameters[0]
|
|
129
|
+
OpenC3.require_file(parameters[0])
|
|
130
|
+
end
|
|
131
|
+
rescue Exception => err
|
|
132
|
+
raise parser.error(err.message)
|
|
133
|
+
end
|
|
134
|
+
rescue Exception => err
|
|
135
|
+
raise parser.error(err.message)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# This code resolves any relative paths to absolute before putting into the @requires array
|
|
139
|
+
unless Pathname.new(filename).absolute?
|
|
140
|
+
$:.each do |search_path|
|
|
141
|
+
test_filename = File.join(search_path, filename).gsub("\\", "/")
|
|
142
|
+
if File.exist?(test_filename)
|
|
143
|
+
filename = test_filename
|
|
144
|
+
break
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
@requires << filename
|
|
150
|
+
|
|
151
|
+
when 'IGNORE_PARAMETER', 'IGNORE_ITEM'
|
|
152
|
+
usage = "#{keyword} <#{keyword.split('_')[1]} NAME>"
|
|
153
|
+
parser.verify_num_parameters(1, 1, usage)
|
|
154
|
+
@ignored_parameters << parameters[0].upcase if keyword.include?("PARAMETER")
|
|
155
|
+
@ignored_items << parameters[0].upcase if keyword.include?("ITEM")
|
|
156
|
+
|
|
157
|
+
when 'COMMANDS', 'TELEMETRY'
|
|
158
|
+
usage = "#{keyword} <FILENAME>"
|
|
159
|
+
parser.verify_num_parameters(1, 1, usage)
|
|
160
|
+
filename = File.join(@dir, 'cmd_tlm', parameters[0])
|
|
161
|
+
raise parser.error("#{filename} not found") unless File.exist?(filename)
|
|
162
|
+
|
|
163
|
+
@cmd_tlm_files << filename
|
|
164
|
+
|
|
165
|
+
# when 'AUTO_SCREEN_SUBSTITUTE'
|
|
166
|
+
# usage = "#{keyword}"
|
|
167
|
+
# parser.verify_num_parameters(0, 0, usage)
|
|
168
|
+
# @auto_screen_substitute = true
|
|
169
|
+
|
|
170
|
+
when 'CMD_UNIQUE_ID_MODE'
|
|
171
|
+
usage = "#{keyword}"
|
|
172
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
173
|
+
@cmd_unique_id_mode = true
|
|
174
|
+
|
|
175
|
+
when 'TLM_UNIQUE_ID_MODE'
|
|
176
|
+
usage = "#{keyword}"
|
|
177
|
+
parser.verify_num_parameters(0, 0, usage)
|
|
178
|
+
@tlm_unique_id_mode = true
|
|
179
|
+
|
|
180
|
+
else
|
|
181
|
+
# blank lines will have a nil keyword and should not raise an exception
|
|
182
|
+
raise parser.error("Unknown keyword '#{keyword}'") if keyword
|
|
183
|
+
end # case keyword
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def as_json(*a)
|
|
188
|
+
config = {}
|
|
189
|
+
config['name'] = @name
|
|
190
|
+
config['requires'] = @requires
|
|
191
|
+
config['ignored_parameters'] = @ignored_parameters
|
|
192
|
+
config['ignored_items'] = @ignored_items
|
|
193
|
+
# config['auto_screen_substitute'] = true if @auto_screen_substitute
|
|
194
|
+
config['cmd_tlm_files'] = @cmd_tlm_files
|
|
195
|
+
# config['filename'] = @filename
|
|
196
|
+
# config['interface'] = @interface.name if @interface
|
|
197
|
+
# config['dir'] = @dir
|
|
198
|
+
# config['cmd_cnt'] = @cmd_cnt
|
|
199
|
+
# config['tlm_cnt'] = @tlm_cnt
|
|
200
|
+
config['cmd_unique_id_mode'] = true if @cmd_unique_id_mode
|
|
201
|
+
config['tlm_unique_id_mode'] = true if @tlm_unique_id_mode
|
|
202
|
+
config['id'] = @id
|
|
203
|
+
config
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
protected
|
|
207
|
+
|
|
208
|
+
# Get the target directory and add the target's lib folder to the
|
|
209
|
+
# search path if it exists
|
|
210
|
+
def get_target_dir(path, gem_path)
|
|
211
|
+
if gem_path
|
|
212
|
+
@dir = gem_path
|
|
213
|
+
else
|
|
214
|
+
@dir = File.join(path, @name)
|
|
215
|
+
end
|
|
216
|
+
@dir.gsub!("\\", '/')
|
|
217
|
+
lib_dir = File.join(@dir, 'lib')
|
|
218
|
+
OpenC3.add_to_search_path(lib_dir, false) if File.exist?(lib_dir)
|
|
219
|
+
proc_dir = File.join(@dir, 'procedures')
|
|
220
|
+
OpenC3.add_to_search_path(proc_dir, false) if File.exist?(proc_dir)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Process the target's configuration file if it exists
|
|
224
|
+
def process_target_config_file
|
|
225
|
+
@filename = File.join(@dir, 'target.txt')
|
|
226
|
+
if File.exist?(filename)
|
|
227
|
+
process_file(filename)
|
|
228
|
+
else
|
|
229
|
+
@filename = nil
|
|
230
|
+
end
|
|
231
|
+
id_filename = File.join(@dir, 'target_id.txt')
|
|
232
|
+
if File.exist?(id_filename)
|
|
233
|
+
File.open(id_filename, 'rb') { |file| @id = file.read.strip }
|
|
234
|
+
else
|
|
235
|
+
@id = nil
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Automatically add all command and telemetry definitions to the list
|
|
240
|
+
def add_all_cmd_tlm
|
|
241
|
+
cmd_tlm_files = []
|
|
242
|
+
if Dir.exist?(File.join(@dir, 'cmd_tlm'))
|
|
243
|
+
# Grab All *.txt files in the cmd_tlm folder and subfolders
|
|
244
|
+
Dir[File.join(@dir, 'cmd_tlm', '**', '*.txt')].each do |filename|
|
|
245
|
+
cmd_tlm_files << filename
|
|
246
|
+
end
|
|
247
|
+
# Grab All *.xtce files in the cmd_tlm folder and subfolders
|
|
248
|
+
Dir[File.join(@dir, 'cmd_tlm', '**', '*.xtce')].each do |filename|
|
|
249
|
+
cmd_tlm_files << filename
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
cmd_tlm_files.sort!
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Make sure all partials are included in the cmd_tlm list for the hashing sum calculation
|
|
256
|
+
def add_cmd_tlm_partials
|
|
257
|
+
partial_files = []
|
|
258
|
+
if Dir.exist?(File.join(@dir, 'cmd_tlm'))
|
|
259
|
+
# Grab all _*.txt files in the cmd_tlm folder and subfolders
|
|
260
|
+
Dir[File.join(@dir, 'cmd_tlm', '**', '_*.txt')].each do |filename|
|
|
261
|
+
partial_files << filename
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
partial_files.sort!
|
|
265
|
+
@cmd_tlm_files.concat(partial_files)
|
|
266
|
+
@cmd_tlm_files.uniq!
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|