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,196 @@
|
|
|
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
|
+
module OpenC3
|
|
21
|
+
class SuiteResults
|
|
22
|
+
attr_accessor :metadata
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@report = nil
|
|
26
|
+
@context = nil
|
|
27
|
+
@start_time = nil
|
|
28
|
+
@stop_time = nil
|
|
29
|
+
@results = nil
|
|
30
|
+
@settings = nil
|
|
31
|
+
@metadata = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def start(test_type, test_suite_class, test_class = nil, test_case = nil, settings = nil)
|
|
35
|
+
@results = []
|
|
36
|
+
@start_time = Time.now.sys
|
|
37
|
+
@settings = settings
|
|
38
|
+
@report = []
|
|
39
|
+
|
|
40
|
+
if test_case
|
|
41
|
+
# Executing a single test case
|
|
42
|
+
@context = "#{test_suite_class.name}:#{test_class.name}:#{test_case} #{test_type}"
|
|
43
|
+
elsif test_class
|
|
44
|
+
# Executing an entire test
|
|
45
|
+
@context = "#{test_suite_class.name}:#{test_class.name} #{test_type}"
|
|
46
|
+
else
|
|
47
|
+
# Executing a test suite
|
|
48
|
+
@context = "#{test_suite_class.name} #{test_type}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
header()
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# process_result can handle an array of OpenC3TestResult objects
|
|
55
|
+
# or a single OpenC3TestResult object
|
|
56
|
+
def process_result(results)
|
|
57
|
+
openc3_lib = Regexp.new(File.join(OpenC3::PATH, 'lib'))
|
|
58
|
+
# If we were passed an array we concat it to the results global
|
|
59
|
+
if results.is_a? Array
|
|
60
|
+
@results.concat(results)
|
|
61
|
+
# A single result is appended and then turned into an array
|
|
62
|
+
else
|
|
63
|
+
@results << results
|
|
64
|
+
results = [results]
|
|
65
|
+
end
|
|
66
|
+
# Process all the results (may be just one)
|
|
67
|
+
results.each do |result|
|
|
68
|
+
self.puts("#{result.group}:#{result.script}:#{result.result}")
|
|
69
|
+
if result.message
|
|
70
|
+
result.message.each_line do |line|
|
|
71
|
+
if /[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F-\xFF]/.match?(line)
|
|
72
|
+
line.chomp!
|
|
73
|
+
line = line.inspect.remove_quotes
|
|
74
|
+
end
|
|
75
|
+
@report << ' ' + line.strip
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
if result.exceptions
|
|
79
|
+
@report << " Exceptions:"
|
|
80
|
+
result.exceptions.each_with_index do |error, index|
|
|
81
|
+
error.formatted().each_line do |line|
|
|
82
|
+
next if /in run_text/.match?(line)
|
|
83
|
+
next if /running_script.rb/.match?(line)
|
|
84
|
+
next if line&.match?(openc3_lib)
|
|
85
|
+
|
|
86
|
+
if /[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F-\xFF]/.match?(line)
|
|
87
|
+
line.chomp!
|
|
88
|
+
line = line.inspect.remove_quotes
|
|
89
|
+
end
|
|
90
|
+
@report << ' ' + line.strip
|
|
91
|
+
end
|
|
92
|
+
@report << '' if index != (result.exceptions.length - 1)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def complete
|
|
99
|
+
@stop_time = Time.now.sys
|
|
100
|
+
footer()
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def report
|
|
104
|
+
@report.join("\n")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def header
|
|
108
|
+
@report << "--- Test Report ---"
|
|
109
|
+
# @report << ''
|
|
110
|
+
# if @metadata
|
|
111
|
+
# begin
|
|
112
|
+
# items = get_tlm_packet('SYSTEM', 'META')
|
|
113
|
+
# @report << ''
|
|
114
|
+
# @report << "Metadata:"
|
|
115
|
+
# items.each do |item_name, item_value, _|
|
|
116
|
+
# next if SetTlmDialog::IGNORED_ITEMS.include?(item_name)
|
|
117
|
+
# @report << "#{item_name} = #{item_value}"
|
|
118
|
+
# end
|
|
119
|
+
# rescue DRb::DRbConnError
|
|
120
|
+
# # Oh well
|
|
121
|
+
# end
|
|
122
|
+
# end
|
|
123
|
+
if @settings
|
|
124
|
+
@report << ''
|
|
125
|
+
@report << "Settings:"
|
|
126
|
+
@settings.each { |setting_name, setting_value| @report << "#{setting_name} = #{setting_value}" }
|
|
127
|
+
end
|
|
128
|
+
@report << ''
|
|
129
|
+
@report << "Results:"
|
|
130
|
+
self.puts "Executing #{@context}"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def footer
|
|
134
|
+
self.puts "Completed #{@context}"
|
|
135
|
+
|
|
136
|
+
@report << ''
|
|
137
|
+
@report << "--- Test Summary ---"
|
|
138
|
+
@report << ''
|
|
139
|
+
|
|
140
|
+
pass_count = 0
|
|
141
|
+
skip_count = 0
|
|
142
|
+
fail_count = 0
|
|
143
|
+
stopped = false
|
|
144
|
+
@results.each do |result|
|
|
145
|
+
if result.result == :PASS
|
|
146
|
+
pass_count += 1
|
|
147
|
+
elsif result.result == :SKIP
|
|
148
|
+
skip_count += 1
|
|
149
|
+
elsif result.result == :FAIL
|
|
150
|
+
fail_count += 1
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if result.stopped
|
|
154
|
+
stopped = true
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
run_time = Time.format_seconds(@stop_time - @start_time)
|
|
158
|
+
run_time << " (#{@stop_time - @start_time} seconds)" if @stop_time - @start_time > 60
|
|
159
|
+
@report << "Run Time: #{run_time}"
|
|
160
|
+
@report << "Total Tests: #{@results.length}"
|
|
161
|
+
@report << "Pass: #{pass_count}"
|
|
162
|
+
@report << "Skip: #{skip_count}"
|
|
163
|
+
@report << "Fail: #{fail_count}"
|
|
164
|
+
@report << ''
|
|
165
|
+
if stopped
|
|
166
|
+
@report << '*** Test was stopped prematurely ***'
|
|
167
|
+
@report << ''
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def write(string)
|
|
172
|
+
@report << Time.now.sys.formatted + ': ' + string
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def puts(string)
|
|
176
|
+
@report << Time.now.sys.formatted + ': ' + string
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# def collect_metadata(parent = nil)
|
|
180
|
+
# success = true
|
|
181
|
+
# if @metadata
|
|
182
|
+
# Qt.execute_in_main_thread(true) do
|
|
183
|
+
# begin
|
|
184
|
+
# success = SetTlmDialog.execute(parent, 'Enter Test Metadata', 'Start Test', 'Cancel Test', 'SYSTEM', 'META')
|
|
185
|
+
# rescue DRb::DRbConnError
|
|
186
|
+
# success = false
|
|
187
|
+
# Qt::MessageBox.critical(parent, 'Error', 'Error Connecting to Command and Telemetry Server')
|
|
188
|
+
# rescue Exception => err
|
|
189
|
+
# OpenC3.handle_fatal_exception(err)
|
|
190
|
+
# end
|
|
191
|
+
# end
|
|
192
|
+
# end
|
|
193
|
+
# success
|
|
194
|
+
# end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,217 @@
|
|
|
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/script/suite'
|
|
21
|
+
require 'openc3/script/suite_results'
|
|
22
|
+
require 'openc3/tools/test_runner/test'
|
|
23
|
+
|
|
24
|
+
module OpenC3
|
|
25
|
+
# Placeholder for all Groups discovered without assigned Suites
|
|
26
|
+
class UnassignedSuite < Suite
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class SuiteRunner
|
|
30
|
+
@@suites = []
|
|
31
|
+
@@settings = {}
|
|
32
|
+
@@suite_results = nil
|
|
33
|
+
|
|
34
|
+
def self.settings
|
|
35
|
+
@@settings
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.settings=(settings)
|
|
39
|
+
@@settings = settings
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.suite_results
|
|
43
|
+
@@suite_results
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.execute(result_string, suite_class, group_class = nil, script = nil)
|
|
47
|
+
@@suite_results = SuiteResults.new
|
|
48
|
+
@@suites.each do |suite|
|
|
49
|
+
if suite.class == suite_class
|
|
50
|
+
@@suite_results.start(result_string, suite_class, group_class, script, @@settings)
|
|
51
|
+
loop do
|
|
52
|
+
yield(suite)
|
|
53
|
+
break if not @@settings['Loop'] or (ScriptStatus.instance.fail_count > 0 and @@settings['Break Loop On Error'])
|
|
54
|
+
end
|
|
55
|
+
break
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.start(suite_class, group_class = nil, script = nil)
|
|
61
|
+
result = []
|
|
62
|
+
execute('', suite_class, group_class, script) do |suite|
|
|
63
|
+
if script
|
|
64
|
+
result = suite.run_script(group_class, script)
|
|
65
|
+
@@suite_results.process_result(result)
|
|
66
|
+
raise StopScript if (result.exceptions and Group.abort_on_exception) or result.stopped
|
|
67
|
+
elsif group_class
|
|
68
|
+
suite.run_group(group_class) { |current_result| @@suite_results.process_result(current_result); raise StopScript if current_result.stopped }
|
|
69
|
+
else
|
|
70
|
+
suite.run { |current_result| @@suite_results.process_result(current_result); raise StopScript if current_result.stopped }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.setup(suite_class, group_class = nil)
|
|
76
|
+
execute('Manual Setup', suite_class, group_class) do |suite|
|
|
77
|
+
if group_class
|
|
78
|
+
result = suite.run_group_setup(group_class)
|
|
79
|
+
else
|
|
80
|
+
result = suite.run_setup
|
|
81
|
+
end
|
|
82
|
+
if result
|
|
83
|
+
@@suite_results.process_result(result)
|
|
84
|
+
raise StopScript if result.stopped
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.teardown(suite_class, group_class = nil)
|
|
90
|
+
execute('Manual Teardown', suite_class, group_class) do |suite|
|
|
91
|
+
if group_class
|
|
92
|
+
result = suite.run_group_teardown(group_class)
|
|
93
|
+
else
|
|
94
|
+
result = suite.run_teardown
|
|
95
|
+
end
|
|
96
|
+
if result
|
|
97
|
+
@@suite_results.process_result(result)
|
|
98
|
+
raise StopScript if result.stopped
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Convert the OpenStruct structure to a simple hash
|
|
104
|
+
# TODO: Maybe just use hashes right from the beginning?
|
|
105
|
+
def self.open_struct_to_hash(object)
|
|
106
|
+
hash = object.to_h
|
|
107
|
+
hash.each do |key1, val1|
|
|
108
|
+
if val1.is_a?(Hash)
|
|
109
|
+
val1.each do |key2, val2|
|
|
110
|
+
if val2.is_a?(OpenStruct)
|
|
111
|
+
hash[key1][key2] = val2.to_h
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
hash
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Build list of Suites and Groups
|
|
120
|
+
def self.build_suites
|
|
121
|
+
@@suites = []
|
|
122
|
+
# @@suites = @@suites.select { |my_suite| my_suite.name == 'CustomSuite' }
|
|
123
|
+
suites = {}
|
|
124
|
+
groups = []
|
|
125
|
+
ObjectSpace.each_object(Class) do |object|
|
|
126
|
+
# If we inherit from Suite but aren't the deprecated TestSuite
|
|
127
|
+
if object < Suite && object != TestSuite
|
|
128
|
+
# Ensure they didn't override name for some reason
|
|
129
|
+
if object.instance_methods(false).include?(:name)
|
|
130
|
+
raise FatalError.new("#{object} redefined the 'name' method. Delete the 'name' method and try again.")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# ObjectSpace.each_object appears to yield objects in the reverse
|
|
134
|
+
# order that they were parsed by the interpreter so push each
|
|
135
|
+
# Suite object to the front of the array to order as encountered
|
|
136
|
+
@@suites.unshift(object.new)
|
|
137
|
+
end
|
|
138
|
+
# If we inherit from Group but aren't the deprecated Test
|
|
139
|
+
if object < Group && object != Test
|
|
140
|
+
# Ensure they didn't override self.name for some reason
|
|
141
|
+
if object.methods(false).include?(:name)
|
|
142
|
+
raise FatalError.new("#{object} redefined the 'self.name' method. Delete the 'self.name' method and try again.")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
groups << object
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
# Raise error if no suites or groups
|
|
149
|
+
if @@suites.empty? || groups.empty?
|
|
150
|
+
return "No Suite or no Group classes found"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Create Suite for unassigned Groups
|
|
154
|
+
@@suites.each do |suite|
|
|
155
|
+
groups_to_delete = []
|
|
156
|
+
groups.each { |group| groups_to_delete << group if suite.scripts[group] }
|
|
157
|
+
groups_to_delete.each { |group| groups.delete(group) }
|
|
158
|
+
end
|
|
159
|
+
if groups.empty?
|
|
160
|
+
@@suites = @@suites.select { |suite| suite.class != UnassignedSuite }
|
|
161
|
+
else
|
|
162
|
+
unassigned_suite = @@suites.select { |suite| suite.class == UnassignedSuite }[0]
|
|
163
|
+
groups.each { |group| unassigned_suite.add_group(group) }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
@@suites.each do |suite|
|
|
167
|
+
cur_suite = OpenStruct.new(:setup => false, :teardown => false, :groups => {})
|
|
168
|
+
cur_suite.setup = true if suite.class.method_defined?(:setup)
|
|
169
|
+
cur_suite.teardown = true if suite.class.method_defined?(:teardown)
|
|
170
|
+
|
|
171
|
+
suite.plans.each do |type, group_class, script|
|
|
172
|
+
case type
|
|
173
|
+
when :GROUP
|
|
174
|
+
cur_suite.groups[group_class.name] ||=
|
|
175
|
+
OpenStruct.new(:setup => false, :teardown => false, :scripts => [])
|
|
176
|
+
cur_suite.groups[group_class.name].scripts.concat(group_class.scripts)
|
|
177
|
+
cur_suite.groups[group_class.name].scripts.uniq!
|
|
178
|
+
cur_suite.groups[group_class.name].setup = true if group_class.method_defined?(:setup)
|
|
179
|
+
cur_suite.groups[group_class.name].teardown = true if group_class.method_defined?(:teardown)
|
|
180
|
+
when :SCRIPT
|
|
181
|
+
cur_suite.groups[group_class.name] ||=
|
|
182
|
+
OpenStruct.new(:setup => false, :teardown => false, :scripts => [])
|
|
183
|
+
# Explicitly check for this method and raise an error if it does not exist
|
|
184
|
+
if group_class.method_defined?(script.intern)
|
|
185
|
+
cur_suite.groups[group_class.name].scripts << script
|
|
186
|
+
cur_suite.groups[group_class.name].scripts.uniq!
|
|
187
|
+
else
|
|
188
|
+
raise "#{group_class} does not have a #{script} method defined."
|
|
189
|
+
end
|
|
190
|
+
cur_suite.groups[group_class.name].setup = true if group_class.method_defined?(:setup)
|
|
191
|
+
cur_suite.groups[group_class.name].teardown = true if group_class.method_defined?(:teardown)
|
|
192
|
+
when :GROUP_SETUP
|
|
193
|
+
cur_suite.groups[group_class.name] ||=
|
|
194
|
+
OpenStruct.new(:setup => false, :teardown => false, :scripts => [])
|
|
195
|
+
# Explicitly check for the setup method and raise an error if it does not exist
|
|
196
|
+
if group_class.method_defined?(:setup)
|
|
197
|
+
cur_suite.groups[group_class.name].setup = true
|
|
198
|
+
else
|
|
199
|
+
raise "#{group_class} does not have a setup method defined."
|
|
200
|
+
end
|
|
201
|
+
when :GROUP_TEARDOWN
|
|
202
|
+
cur_suite.groups[group_class.name] ||=
|
|
203
|
+
OpenStruct.new(:setup => false, :teardown => false, :scripts => [])
|
|
204
|
+
# Explicitly check for the teardown method and raise an error if it does not exist
|
|
205
|
+
if group_class.method_defined?(:teardown)
|
|
206
|
+
cur_suite.groups[group_class.name].teardown = true
|
|
207
|
+
else
|
|
208
|
+
raise "#{group_class} does not have a teardown method defined."
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
suites[suite.name.split('::')[-1]] = open_struct_to_hash(cur_suite) unless suite.name == 'CustomSuite'
|
|
213
|
+
end
|
|
214
|
+
return suites
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
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/script/script'
|
|
21
|
+
include OpenC3::Script
|
|
@@ -0,0 +1,167 @@
|
|
|
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 'thread' # For Mutex
|
|
21
|
+
require 'openc3/streams/stream'
|
|
22
|
+
require 'openc3/config/config_parser'
|
|
23
|
+
require 'openc3/io/serial_driver'
|
|
24
|
+
|
|
25
|
+
module OpenC3
|
|
26
|
+
# Stream that reads and writes to serial ports by using {SerialDriver}.
|
|
27
|
+
class SerialStream < Stream
|
|
28
|
+
# @param write_port_name [String] The name of the serial port to write.
|
|
29
|
+
# Pass nil if the stream is to be read only. On Windows the port name
|
|
30
|
+
# is typically 'COMX' where X can be any port number. On UNIX the port
|
|
31
|
+
# name is typically a device such as '/dev/ttyS0'.
|
|
32
|
+
# @param read_port_name [String] The name of the serial port to read.
|
|
33
|
+
# Pass nil if the stream is to be read only. On Windows the port name
|
|
34
|
+
# is typically 'COMX' where X can be any port number. On UNIX the port
|
|
35
|
+
# name is typically a device such as '/dev/ttyS0'.
|
|
36
|
+
# @param baud_rate [Integer] The serial port baud rate
|
|
37
|
+
# @param parity [Symbol] Must be :NONE, :EVEN, or :ODD
|
|
38
|
+
# @param stop_bits [Integer] Number of stop bits. Must be 1 or 2.
|
|
39
|
+
# @param write_timeout [Integer] Number of seconds to wait for the write to
|
|
40
|
+
# complete. Pass nil to create no timeout. The {SerialDriver} will
|
|
41
|
+
# continously try to send the data until it has been sent or an error
|
|
42
|
+
# occurs.
|
|
43
|
+
# @param read_timeout [Integer] Number of seconds to wait for the read to
|
|
44
|
+
# complete. Pass nil to create no timeout. The {SerialDriver} will
|
|
45
|
+
# continously try to read data until it has received data or an error
|
|
46
|
+
# occurs.
|
|
47
|
+
# @param flow_control [Symbol] Currently supported :NONE and :RTSCTS (default :NONE)
|
|
48
|
+
# @param data_bits [Integer] Number of data bits (default 8)
|
|
49
|
+
def initialize(write_port_name,
|
|
50
|
+
read_port_name,
|
|
51
|
+
baud_rate,
|
|
52
|
+
parity,
|
|
53
|
+
stop_bits,
|
|
54
|
+
write_timeout,
|
|
55
|
+
read_timeout,
|
|
56
|
+
flow_control = :NONE,
|
|
57
|
+
data_bits = 8)
|
|
58
|
+
super()
|
|
59
|
+
|
|
60
|
+
# The SerialDriver class will validate the parameters
|
|
61
|
+
@write_port_name = ConfigParser.handle_nil(write_port_name)
|
|
62
|
+
@read_port_name = ConfigParser.handle_nil(read_port_name)
|
|
63
|
+
@baud_rate = Integer(baud_rate)
|
|
64
|
+
@parity = parity
|
|
65
|
+
@stop_bits = stop_bits.to_i
|
|
66
|
+
@write_timeout = ConfigParser.handle_nil(write_timeout)
|
|
67
|
+
@write_timeout = @write_timeout.to_f if @write_timeout
|
|
68
|
+
@read_timeout = ConfigParser.handle_nil(read_timeout)
|
|
69
|
+
@read_timeout = @read_timeout.to_f if @read_timeout
|
|
70
|
+
@flow_control = flow_control.to_s.intern
|
|
71
|
+
@data_bits = data_bits.to_i
|
|
72
|
+
|
|
73
|
+
if @write_port_name
|
|
74
|
+
@write_serial_port = SerialDriver.new(@write_port_name,
|
|
75
|
+
@baud_rate,
|
|
76
|
+
@parity,
|
|
77
|
+
@stop_bits,
|
|
78
|
+
@write_timeout,
|
|
79
|
+
@read_timeout,
|
|
80
|
+
@flow_control,
|
|
81
|
+
@data_bits)
|
|
82
|
+
else
|
|
83
|
+
@write_serial_port = nil
|
|
84
|
+
end
|
|
85
|
+
if @read_port_name
|
|
86
|
+
if @read_port_name == @write_port_name
|
|
87
|
+
@read_serial_port = @write_serial_port
|
|
88
|
+
else
|
|
89
|
+
@read_serial_port = SerialDriver.new(@read_port_name,
|
|
90
|
+
@baud_rate,
|
|
91
|
+
@parity,
|
|
92
|
+
@stop_bits,
|
|
93
|
+
@write_timeout,
|
|
94
|
+
@read_timeout,
|
|
95
|
+
@flow_control,
|
|
96
|
+
@data_bits)
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
@read_serial_port = nil
|
|
100
|
+
end
|
|
101
|
+
if @read_serial_port.nil? && @write_serial_port.nil?
|
|
102
|
+
raise "Either a write port or read port must be given"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# We 'connect' when we create the stream
|
|
106
|
+
@connected = true
|
|
107
|
+
|
|
108
|
+
# Mutex on write is needed to protect from commands coming in from more
|
|
109
|
+
# than one tool
|
|
110
|
+
@write_mutex = Mutex.new
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @return [String] Returns a binary string of data from the serial port
|
|
114
|
+
def read
|
|
115
|
+
raise "Attempt to read from write only stream" unless @read_serial_port
|
|
116
|
+
|
|
117
|
+
# No read mutex is needed because reads happen serially
|
|
118
|
+
@read_serial_port.read
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @return [String] Returns a binary string of data from the serial port without blocking
|
|
122
|
+
def read_nonblock
|
|
123
|
+
raise "Attempt to read from write only stream" unless @read_serial_port
|
|
124
|
+
|
|
125
|
+
# No read mutex is needed because reads happen serially
|
|
126
|
+
@read_serial_port.read_nonblock
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @param data [String] A binary string of data to write to the serial port
|
|
130
|
+
def write(data)
|
|
131
|
+
raise "Attempt to write to read only stream" unless @write_serial_port
|
|
132
|
+
|
|
133
|
+
@write_mutex.synchronize do
|
|
134
|
+
@write_serial_port.write(data)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Connect the stream
|
|
139
|
+
def connect
|
|
140
|
+
# N/A - Serial streams 'connect' on creation
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @return [Boolean] Whether the serial stream is connected to the serial
|
|
144
|
+
# port
|
|
145
|
+
def connected?
|
|
146
|
+
@connected
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Disconnect by closing the serial ports
|
|
150
|
+
def disconnect
|
|
151
|
+
if @connected
|
|
152
|
+
begin
|
|
153
|
+
@write_serial_port.close if @write_serial_port && !@write_serial_port.closed?
|
|
154
|
+
rescue IOError
|
|
155
|
+
# Ignore
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
begin
|
|
159
|
+
@read_serial_port.close if @read_serial_port && !@read_serial_port.closed?
|
|
160
|
+
rescue IOError
|
|
161
|
+
# Ignore
|
|
162
|
+
end
|
|
163
|
+
@connected = false
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end # class SerialStream
|
|
167
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
module OpenC3
|
|
21
|
+
# Class that implments the following methods: read, write(data),
|
|
22
|
+
# connect, connected? and disconnect. Streams are simply data sources which
|
|
23
|
+
# {Protocol} classes read and write to. This separation of concerns
|
|
24
|
+
# allows Streams to simply focus on getting and sending raw data while the
|
|
25
|
+
# higher level processing occurs in {Protocol}.
|
|
26
|
+
class Stream
|
|
27
|
+
# Expected to return any amount of data on success, or a blank string on
|
|
28
|
+
# closed/EOF, and may raise Timeout::Error, or other errors
|
|
29
|
+
def read
|
|
30
|
+
raise "read not defined by Stream"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Expected to always return immediately with data if available or an empty string.
|
|
34
|
+
# Should not raise errors
|
|
35
|
+
def read_nonblock
|
|
36
|
+
raise "read_nonblock not defined by Stream"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Expected to write complete set of data. May raise Timeout::Error
|
|
40
|
+
# or other errors.
|
|
41
|
+
#
|
|
42
|
+
# @param data [String] Binary data to write to the stream
|
|
43
|
+
def write(data)
|
|
44
|
+
raise "write not defined by Stream"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Connects the stream
|
|
48
|
+
def connect
|
|
49
|
+
raise "connect not defined by Stream"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Boolean] true if connected or false otherwise
|
|
53
|
+
def connected?
|
|
54
|
+
raise "connected? not defined by Stream"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Disconnects the stream
|
|
58
|
+
# Note that streams are not designed to be reconnected and must be recreated
|
|
59
|
+
def disconnect
|
|
60
|
+
raise "disconnect not defined by Stream"
|
|
61
|
+
end
|
|
62
|
+
end # class Stream
|
|
63
|
+
end
|