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,487 @@
|
|
|
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/packets/packet_config'
|
|
21
|
+
require 'openc3/ext/telemetry' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
|
|
22
|
+
|
|
23
|
+
module OpenC3
|
|
24
|
+
# Telemetry uses PacketConfig to parse the command and telemetry
|
|
25
|
+
# configuration files. It contains all the knowledge of which telemetry packets
|
|
26
|
+
# exist in the system and how to access them. This class is the API layer
|
|
27
|
+
# which other classes use to access telemetry.
|
|
28
|
+
#
|
|
29
|
+
# This should not be confused with the Api module which implements the JSON
|
|
30
|
+
# API that is used by tools when accessing the Server. The Api module always
|
|
31
|
+
# provides Ruby primatives where the Telemetry class can return actual
|
|
32
|
+
# Packet or PacketItem objects. While there are some overlapping methods between
|
|
33
|
+
# the two, these are separate interfaces into the system.
|
|
34
|
+
class Telemetry
|
|
35
|
+
attr_accessor :config
|
|
36
|
+
|
|
37
|
+
LATEST_PACKET_NAME = 'LATEST'.freeze
|
|
38
|
+
|
|
39
|
+
# @param config [PacketConfig] Packet configuration to use to access the
|
|
40
|
+
# telemetry
|
|
41
|
+
def initialize(config)
|
|
42
|
+
@config = config
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# (see PacketConfig#warnings)
|
|
46
|
+
def warnings
|
|
47
|
+
return @config.warnings
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Array<String>] The telemetry target names (excluding UNKNOWN)
|
|
51
|
+
def target_names
|
|
52
|
+
result = @config.telemetry.keys.sort
|
|
53
|
+
result.delete('UNKNOWN'.freeze)
|
|
54
|
+
return result
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
|
|
58
|
+
# @param target_name [String] The target name
|
|
59
|
+
# @return [Hash<packet_name=>Packet>] Hash of the telemetry packets for the given
|
|
60
|
+
# target name keyed by the packet name
|
|
61
|
+
def packets(target_name)
|
|
62
|
+
upcase_target_name = target_name.to_s.upcase
|
|
63
|
+
target_packets = @config.telemetry[upcase_target_name]
|
|
64
|
+
raise "Telemetry target '#{upcase_target_name}' does not exist" unless target_packets
|
|
65
|
+
|
|
66
|
+
target_packets
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @param target_name [String] The target name
|
|
70
|
+
# @param packet_name [String] The packet name. Must be a defined packet name
|
|
71
|
+
# and not 'LATEST'.
|
|
72
|
+
# @return [Packet] The telemetry packet for the given target and packet name
|
|
73
|
+
def packet(target_name, packet_name)
|
|
74
|
+
target_packets = packets(target_name)
|
|
75
|
+
upcase_packet_name = packet_name.to_s.upcase
|
|
76
|
+
packet = target_packets[upcase_packet_name]
|
|
77
|
+
unless packet
|
|
78
|
+
upcase_target_name = target_name.to_s.upcase
|
|
79
|
+
raise "Telemetry packet '#{upcase_target_name} #{upcase_packet_name}' does not exist"
|
|
80
|
+
end
|
|
81
|
+
packet
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @param target_name (see #packet)
|
|
85
|
+
# @param packet_name [String] The packet name. 'LATEST' can also be given
|
|
86
|
+
# to specify the last received (or defined if no packets have been
|
|
87
|
+
# received) packet within the given target that contains the
|
|
88
|
+
# item_name.
|
|
89
|
+
# @param item_name [String] The item name
|
|
90
|
+
# @return [Packet, PacketItem] The packet and the packet item
|
|
91
|
+
def packet_and_item(target_name, packet_name, item_name)
|
|
92
|
+
upcase_packet_name = packet_name.to_s.upcase
|
|
93
|
+
if upcase_packet_name == "LATEST".freeze
|
|
94
|
+
return_packet = newest_packet(target_name, item_name)
|
|
95
|
+
else
|
|
96
|
+
return_packet = packet(target_name, packet_name)
|
|
97
|
+
end
|
|
98
|
+
item = return_packet.get_item(item_name)
|
|
99
|
+
return [return_packet, item]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Return a telemetry value from a packet.
|
|
103
|
+
#
|
|
104
|
+
# @param target_name (see #packet_and_item)
|
|
105
|
+
# @param packet_name (see #packet_and_item)
|
|
106
|
+
# @param item_name (see #packet_and_item)
|
|
107
|
+
# @param value_type [Symbol] How to convert the item before returning.
|
|
108
|
+
# Must be one of {Packet::VALUE_TYPES}
|
|
109
|
+
# @return The value. :FORMATTED and :WITH_UNITS values are always returned
|
|
110
|
+
# as Strings. :RAW values will match their data_type. :CONVERTED values
|
|
111
|
+
# can be any type.
|
|
112
|
+
def value(target_name, packet_name, item_name, value_type = :CONVERTED)
|
|
113
|
+
packet, _ = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
|
|
114
|
+
return packet.read(item_name, value_type)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Reads the specified list of items and returns their values and limits
|
|
118
|
+
# state.
|
|
119
|
+
#
|
|
120
|
+
# @param item_array [Array<Array(String String String)>] An array
|
|
121
|
+
# consisting of [target name, packet name, item name]
|
|
122
|
+
# @param value_types [Symbol|Array<Symbol>] How to convert the items before
|
|
123
|
+
# returning. A single symbol of {Packet::VALUE_TYPES}
|
|
124
|
+
# can be passed which will convert all items the same way. Or
|
|
125
|
+
# an array of symbols can be passed to control how each item is
|
|
126
|
+
# converted.
|
|
127
|
+
# @return [Array, Array, Array] The first array contains the item values and the
|
|
128
|
+
# second their limits state, and the third their limits settings which includes
|
|
129
|
+
# the red, yellow, and green (if given) limits values.
|
|
130
|
+
def values_and_limits_states(item_array, value_types = :CONVERTED)
|
|
131
|
+
items = []
|
|
132
|
+
|
|
133
|
+
# Verify item_array is a nested array
|
|
134
|
+
raise(ArgumentError, "item_array must be a nested array consisting of [[tgt,pkt,item],[tgt,pkt,item],...]") unless Array === item_array[0]
|
|
135
|
+
|
|
136
|
+
states = []
|
|
137
|
+
settings = []
|
|
138
|
+
limits_set = System.limits_set
|
|
139
|
+
|
|
140
|
+
raise(ArgumentError, "Passed #{item_array.length} items but only #{value_types.length} value types") if (Array === value_types) and item_array.length != value_types.length
|
|
141
|
+
|
|
142
|
+
value_type = value_types.intern unless Array === value_types
|
|
143
|
+
item_array.length.times do |index|
|
|
144
|
+
entry = item_array[index]
|
|
145
|
+
target_name = entry[0]
|
|
146
|
+
packet_name = entry[1]
|
|
147
|
+
item_name = entry[2]
|
|
148
|
+
value_type = value_types[index].intern if Array === value_types
|
|
149
|
+
|
|
150
|
+
packet, item = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
|
|
151
|
+
items << packet.read(item_name, value_type)
|
|
152
|
+
limits = item.limits
|
|
153
|
+
states << limits.state
|
|
154
|
+
limits_values = limits.values
|
|
155
|
+
if limits_values
|
|
156
|
+
limits_settings = limits_values[limits_set]
|
|
157
|
+
else
|
|
158
|
+
limits_settings = nil
|
|
159
|
+
end
|
|
160
|
+
settings << limits_settings
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
return [items, states, settings]
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @param target_name (see #packet)
|
|
168
|
+
# @param packet_name (see #packet)
|
|
169
|
+
# @return [Array<PacketItem>] The telemetry items for the given target and packet name
|
|
170
|
+
def items(target_name, packet_name)
|
|
171
|
+
return packet(target_name, packet_name).sorted_items
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @param target_name (see #packet)
|
|
175
|
+
# @param packet_name (see #packet) The packet name. LATEST is supported.
|
|
176
|
+
# @return [Array<PacketItem>] The telemetry item names for the given target and packet name
|
|
177
|
+
def item_names(target_name, packet_name)
|
|
178
|
+
if LATEST_PACKET_NAME.casecmp(packet_name).zero?
|
|
179
|
+
target_upcase = target_name.to_s.upcase
|
|
180
|
+
target_latest_data = @config.latest_data[target_upcase]
|
|
181
|
+
raise "Telemetry Target '#{target_upcase}' does not exist" unless target_latest_data
|
|
182
|
+
|
|
183
|
+
item_names = target_latest_data.keys
|
|
184
|
+
else
|
|
185
|
+
tlm_packet = packet(target_name, packet_name)
|
|
186
|
+
item_names = []
|
|
187
|
+
tlm_packet.sorted_items.each { |item| item_names << item.name }
|
|
188
|
+
end
|
|
189
|
+
item_names
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Set a telemetry value in a packet.
|
|
193
|
+
#
|
|
194
|
+
# @param target_name (see #packet_and_item)
|
|
195
|
+
# @param packet_name (see #packet_and_item)
|
|
196
|
+
# @param item_name (see #packet_and_item)
|
|
197
|
+
# @param value The value to set in the packet
|
|
198
|
+
# @param value_type (see #tlm)
|
|
199
|
+
def set_value(target_name, packet_name, item_name, value, value_type = :CONVERTED)
|
|
200
|
+
packet, _ = packet_and_item(target_name, packet_name, item_name)
|
|
201
|
+
packet.write(item_name, value, value_type)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# @param target_name (see #packet_and_item)
|
|
205
|
+
# @param item_name (see #packet_and_item)
|
|
206
|
+
# @return [Array<Packet>] The latest (most recently arrived) packets with
|
|
207
|
+
# the specified target and item.
|
|
208
|
+
def latest_packets(target_name, item_name)
|
|
209
|
+
target_upcase = target_name.to_s.upcase
|
|
210
|
+
item_upcase = item_name.to_s.upcase
|
|
211
|
+
target_latest_data = @config.latest_data[target_upcase]
|
|
212
|
+
raise "Telemetry target '#{target_upcase}' does not exist" unless target_latest_data
|
|
213
|
+
|
|
214
|
+
packets = @config.latest_data[target_upcase][item_upcase]
|
|
215
|
+
raise "Telemetry item '#{target_upcase} #{LATEST_PACKET_NAME} #{item_upcase}' does not exist" unless packets
|
|
216
|
+
|
|
217
|
+
return packets
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @param target_name (see #packet_and_item)
|
|
221
|
+
# @param item_name (see #packet_and_item)
|
|
222
|
+
# @return [Packet] The packet with the most recent timestamp that contains
|
|
223
|
+
# the specified target and item.
|
|
224
|
+
def newest_packet(target_name, item_name)
|
|
225
|
+
# Handle LATEST_PACKET_NAME - Lookup packets for this target/item
|
|
226
|
+
packets = latest_packets(target_name, item_name)
|
|
227
|
+
|
|
228
|
+
# Find packet with newest timestamp
|
|
229
|
+
newest_packet = nil
|
|
230
|
+
newest_received_time = nil
|
|
231
|
+
packets.each do |packet|
|
|
232
|
+
received_time = packet.received_time
|
|
233
|
+
if newest_received_time
|
|
234
|
+
# See if the received time from this packet is newer.
|
|
235
|
+
# Having the >= makes this method return the last defined packet
|
|
236
|
+
# whether the timestamps are both nil or both equal.
|
|
237
|
+
if received_time and received_time >= newest_received_time
|
|
238
|
+
newest_packet = packet
|
|
239
|
+
newest_received_time = newest_packet.received_time
|
|
240
|
+
end
|
|
241
|
+
else
|
|
242
|
+
# No received time yet so take this packet
|
|
243
|
+
newest_packet = packet
|
|
244
|
+
newest_received_time = newest_packet.received_time
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
return newest_packet
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Identifies an unknown buffer of data as a defined packet and sets the
|
|
251
|
+
# packet's data to the given buffer. Identifying a packet uses the fields
|
|
252
|
+
# marked as ID_ITEM to identify if the buffer passed represents the
|
|
253
|
+
# packet defined. Incorrectly sized buffers are still processed but an
|
|
254
|
+
# error is logged.
|
|
255
|
+
#
|
|
256
|
+
# Note: This affects all subsequent requests for the packet (for example
|
|
257
|
+
# using packet) which is why the method is marked with a bang!
|
|
258
|
+
#
|
|
259
|
+
# @param packet_data [String] The binary packet data buffer
|
|
260
|
+
# @param target_names [Array<String>] List of target names to limit the search. The
|
|
261
|
+
# default value of nil means to search all known targets.
|
|
262
|
+
# @return [Packet] The identified packet with its data set to the given
|
|
263
|
+
# packet_data buffer. Returns nil if no packet could be identified.
|
|
264
|
+
def identify!(packet_data, target_names = nil)
|
|
265
|
+
identified_packet = identify(packet_data, target_names)
|
|
266
|
+
identified_packet.buffer = packet_data if identified_packet
|
|
267
|
+
return identified_packet
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Finds a packet from the Current Value Table that matches the given data
|
|
271
|
+
# and returns it. Does not fill the packets buffer. Use identify! to update the CVT.
|
|
272
|
+
#
|
|
273
|
+
# @param packet_data [String] The binary packet data buffer
|
|
274
|
+
# @param target_names [Array<String>] List of target names to limit the search. The
|
|
275
|
+
# default value of nil means to search all known targets.
|
|
276
|
+
# @return [Packet] The identified packet, Returns nil if no packet could be identified.
|
|
277
|
+
def identify(packet_data, target_names = nil)
|
|
278
|
+
target_names = target_names() unless target_names
|
|
279
|
+
|
|
280
|
+
target_names.each do |target_name|
|
|
281
|
+
target_name = target_name.to_s.upcase
|
|
282
|
+
|
|
283
|
+
target_packets = nil
|
|
284
|
+
begin
|
|
285
|
+
target_packets = packets(target_name)
|
|
286
|
+
# puts target_packets.length
|
|
287
|
+
rescue RuntimeError
|
|
288
|
+
# No telemetry for this target
|
|
289
|
+
next
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
target = System.targets[target_name]
|
|
293
|
+
if target and target.tlm_unique_id_mode
|
|
294
|
+
# Iterate through the packets and see if any represent the buffer
|
|
295
|
+
target_packets.each do |packet_name, packet|
|
|
296
|
+
return packet if packet.identify?(packet_data)
|
|
297
|
+
end
|
|
298
|
+
else
|
|
299
|
+
# Do a hash lookup to quickly identify the packet
|
|
300
|
+
if target_packets.length > 0
|
|
301
|
+
packet = target_packets.first[1]
|
|
302
|
+
key = packet.read_id_values(packet_data)
|
|
303
|
+
hash = @config.tlm_id_value_hash[target_name]
|
|
304
|
+
identified_packet = hash[key]
|
|
305
|
+
identified_packet = hash['CATCHALL'.freeze] unless identified_packet
|
|
306
|
+
return identified_packet if identified_packet
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
return nil
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def identify_and_define_packet(packet, target_names = nil)
|
|
315
|
+
if !packet.identified?
|
|
316
|
+
identified_packet = identify(packet.buffer(false), target_names)
|
|
317
|
+
return nil unless identified_packet
|
|
318
|
+
|
|
319
|
+
identified_packet = identified_packet.clone
|
|
320
|
+
identified_packet.buffer = packet.buffer
|
|
321
|
+
identified_packet.received_time = packet.received_time
|
|
322
|
+
identified_packet.stored = packet.stored
|
|
323
|
+
identified_packet.extra = packet.extra
|
|
324
|
+
return identified_packet
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
if !packet.defined?
|
|
328
|
+
begin
|
|
329
|
+
identified_packet = self.packet(packet.target_name, packet.packet_name)
|
|
330
|
+
rescue RuntimeError
|
|
331
|
+
return nil
|
|
332
|
+
end
|
|
333
|
+
identified_packet = identified_packet.clone
|
|
334
|
+
identified_packet.buffer = packet.buffer
|
|
335
|
+
identified_packet.received_time = packet.received_time
|
|
336
|
+
identified_packet.stored = packet.stored
|
|
337
|
+
identified_packet.extra = packet.extra
|
|
338
|
+
return identified_packet
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
return packet
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Updates the specified packet with the given packet data. Raises an error
|
|
345
|
+
# if the packet could not be found.
|
|
346
|
+
#
|
|
347
|
+
# Note: This affects all subsequent requests for the packet which is why
|
|
348
|
+
# the method is marked with a bang!
|
|
349
|
+
#
|
|
350
|
+
# @param target_name (see #packet)
|
|
351
|
+
# @param packet_name (see #packet)
|
|
352
|
+
# @param packet_data (see #identify_tlm!)
|
|
353
|
+
# @return [Packet] The packet with its data set to the given packet_data
|
|
354
|
+
# buffer.
|
|
355
|
+
def update!(target_name, packet_name, packet_data)
|
|
356
|
+
identified_packet = packet(target_name, packet_name)
|
|
357
|
+
identified_packet.buffer = packet_data
|
|
358
|
+
return identified_packet
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Assigns a limits change callback to all telemetry packets
|
|
362
|
+
#
|
|
363
|
+
# @param limits_change_callback
|
|
364
|
+
def limits_change_callback=(limits_change_callback)
|
|
365
|
+
@config.telemetry.each do |target_name, packets|
|
|
366
|
+
packets.each do |packet_name, packet|
|
|
367
|
+
packet.limits_change_callback = limits_change_callback
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Iterates through all the telemetry packets and marks them stale if they
|
|
373
|
+
# haven't been received for over the System.staleness_seconds value.
|
|
374
|
+
#
|
|
375
|
+
# @return [Array(Packet)] Array of the stale packets
|
|
376
|
+
def check_stale
|
|
377
|
+
stale = []
|
|
378
|
+
time = Time.now.sys
|
|
379
|
+
@config.telemetry.each do |target_name, target_packets|
|
|
380
|
+
target_packets.each do |packet_name, packet|
|
|
381
|
+
if packet.received_time and (!packet.stale) and (time - packet.received_time > System.staleness_seconds)
|
|
382
|
+
packet.set_stale
|
|
383
|
+
stale << packet
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
stale
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# @param with_limits_only [Boolean] Return only the stale packets
|
|
391
|
+
# that have limits items and thus affect the overall limits
|
|
392
|
+
# state of the system
|
|
393
|
+
# @param target [String] Target name or nil for all targets
|
|
394
|
+
# @return [Array(Packet)] Array of the stale packets
|
|
395
|
+
def stale(with_limits_only = false, target = nil)
|
|
396
|
+
if target && !target_names.include?(target)
|
|
397
|
+
raise "Telemetry target '#{target.upcase}' does not exist"
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
stale = []
|
|
401
|
+
@config.telemetry.each do |target_name, target_packets|
|
|
402
|
+
next if target && target != target_name
|
|
403
|
+
next if target_name == 'UNKNOWN'
|
|
404
|
+
|
|
405
|
+
target_packets.each do |packet_name, packet|
|
|
406
|
+
if packet.stale
|
|
407
|
+
next if with_limits_only && packet.limits_items.empty?
|
|
408
|
+
|
|
409
|
+
stale << packet
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
stale
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
# Clears the received_count value on every packet in every target
|
|
417
|
+
def clear_counters
|
|
418
|
+
@config.telemetry.each do |target_name, target_packets|
|
|
419
|
+
target_packets.each do |packet_name, packet|
|
|
420
|
+
packet.received_count = 0
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
# Resets metadata on every packet in every target
|
|
426
|
+
def reset
|
|
427
|
+
@config.telemetry.each do |target_name, target_packets|
|
|
428
|
+
target_packets.each do |packet_name, packet|
|
|
429
|
+
packet.reset
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
# Returns the first non-hidden packet
|
|
435
|
+
def first_non_hidden
|
|
436
|
+
@config.telemetry.each do |target_name, target_packets|
|
|
437
|
+
next if target_name == 'UNKNOWN'
|
|
438
|
+
|
|
439
|
+
target_packets.each do |packet_name, packet|
|
|
440
|
+
return packet unless packet.hidden
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
nil
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Returns an array with a "TARGET_NAME PACKET_NAME ITEM_NAME" string for every item in the system
|
|
447
|
+
def all_item_strings(include_hidden = false, splash = nil)
|
|
448
|
+
strings = []
|
|
449
|
+
tnames = target_names()
|
|
450
|
+
total = tnames.length.to_f
|
|
451
|
+
tnames.each_with_index do |target_name, index|
|
|
452
|
+
if splash
|
|
453
|
+
splash.message = "Processing #{target_name} telemetry"
|
|
454
|
+
splash.progress = index / total
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
# Note: System only has declared target structures but telemetry may have more
|
|
458
|
+
system_target = System.targets[target_name]
|
|
459
|
+
if system_target
|
|
460
|
+
ignored_items = system_target.ignored_items
|
|
461
|
+
else
|
|
462
|
+
ignored_items = []
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
packets(target_name).each do |packet_name, packet|
|
|
466
|
+
# We don't audit against hidden or disabled packets
|
|
467
|
+
next if !include_hidden and (packet.hidden || packet.disabled)
|
|
468
|
+
|
|
469
|
+
packet.items.each_key do |item_name|
|
|
470
|
+
# Skip ignored items
|
|
471
|
+
next if !include_hidden and ignored_items.include? item_name
|
|
472
|
+
|
|
473
|
+
strings << "#{target_name} #{packet_name} #{item_name}"
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
strings
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# @return [Hash{String=>Hash{String=>Packet}}] Hash of all the telemetry
|
|
481
|
+
# packets keyed by the target name. The value is another hash keyed by the
|
|
482
|
+
# packet name returning the packet.
|
|
483
|
+
def all
|
|
484
|
+
@config.telemetry
|
|
485
|
+
end
|
|
486
|
+
end # class Telemetry
|
|
487
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
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 Processor
|
|
22
|
+
# @return [Symbol] The value type for the processor
|
|
23
|
+
attr_reader :value_type
|
|
24
|
+
|
|
25
|
+
# @return [String] The processor name
|
|
26
|
+
attr_reader :name
|
|
27
|
+
|
|
28
|
+
# @return [Hash] The results of the most recent execution of the processor
|
|
29
|
+
attr_accessor :results
|
|
30
|
+
|
|
31
|
+
# Create a new Processor
|
|
32
|
+
# @param value_type [Symbol or String] the value type to process
|
|
33
|
+
def initialize(value_type = :CONVERTED)
|
|
34
|
+
@name = self.class.to_s.upcase
|
|
35
|
+
value_type = value_type.to_s.upcase.intern
|
|
36
|
+
@value_type = value_type
|
|
37
|
+
raise ArgumentError, "value_type must be RAW, CONVERTED, FORMATTED, or WITH_UNITS. Is #{@value_type}" unless Packet::VALUE_TYPES.include?(@value_type)
|
|
38
|
+
|
|
39
|
+
@results = {}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def name=(name)
|
|
43
|
+
@name = name.to_s.upcase
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Perform processing on the packet.
|
|
47
|
+
#
|
|
48
|
+
# @param packet [Packet] The packet which contains the value. This can
|
|
49
|
+
# be useful to reach into the packet and use other values in the
|
|
50
|
+
# conversion.
|
|
51
|
+
# @param buffer [String] The packet buffer
|
|
52
|
+
# @return The processed result
|
|
53
|
+
def call(packet, buffer)
|
|
54
|
+
raise "call method must be defined by subclass"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @return [String] The processor class
|
|
58
|
+
def to_s
|
|
59
|
+
self.class.to_s.split('::')[-1]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Reset any state
|
|
63
|
+
def reset
|
|
64
|
+
# By default do nothing
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Make a light weight clone of this processor. This only creates a new hash of results
|
|
68
|
+
#
|
|
69
|
+
# @return [Processor] A copy of the processor with a new hash of results
|
|
70
|
+
def clone
|
|
71
|
+
processor = super()
|
|
72
|
+
processor.results = processor.results.clone
|
|
73
|
+
processor
|
|
74
|
+
end
|
|
75
|
+
alias dup clone
|
|
76
|
+
|
|
77
|
+
# Convert to configuration file string
|
|
78
|
+
def to_config
|
|
79
|
+
" PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@value_type}\n"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def as_json(*a)
|
|
83
|
+
{ 'name' => @name, 'class' => self.class.name, 'params' => [@value_type.to_s] }
|
|
84
|
+
end
|
|
85
|
+
end # class Processor
|
|
86
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
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/processors/processor'
|
|
21
|
+
|
|
22
|
+
module OpenC3
|
|
23
|
+
class StatisticsProcessor < Processor
|
|
24
|
+
# @return [Array] The set of samples stored by the processor
|
|
25
|
+
attr_accessor :samples
|
|
26
|
+
|
|
27
|
+
# @param item_name [String] The name of the item to gather statistics on
|
|
28
|
+
# @param samples_to_average [Integer] The number of samples to store for calculations
|
|
29
|
+
# @param value_type #See Processor::initialize
|
|
30
|
+
def initialize(item_name, samples_to_average, value_type = :CONVERTED)
|
|
31
|
+
super(value_type)
|
|
32
|
+
@item_name = item_name.to_s.upcase
|
|
33
|
+
@samples_to_average = Integer(samples_to_average)
|
|
34
|
+
reset()
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Run statistics on the item
|
|
38
|
+
#
|
|
39
|
+
# See Processor#call
|
|
40
|
+
def call(packet, buffer)
|
|
41
|
+
value = packet.read(@item_name, @value_type, buffer)
|
|
42
|
+
# Don't process NaN or Infinite values
|
|
43
|
+
return if value.to_f.nan? || value.to_f.infinite?
|
|
44
|
+
|
|
45
|
+
@samples << value
|
|
46
|
+
@samples = @samples[-@samples_to_average..-1] if @samples.length > @samples_to_average
|
|
47
|
+
mean, stddev = Math.stddev_sample(@samples)
|
|
48
|
+
@results[:MAX] = @samples.max
|
|
49
|
+
@results[:MIN] = @samples.min
|
|
50
|
+
@results[:MEAN] = mean
|
|
51
|
+
@results[:STDDEV] = stddev
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Reset any state
|
|
55
|
+
def reset
|
|
56
|
+
@samples = []
|
|
57
|
+
@results[:MAX] = nil
|
|
58
|
+
@results[:MIN] = nil
|
|
59
|
+
@results[:MEAN] = nil
|
|
60
|
+
@results[:STDDEV] = nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Make a light weight clone of this processor. This only creates a new hash of results
|
|
64
|
+
#
|
|
65
|
+
# @return [Processor] A copy of the processor with a new hash of results
|
|
66
|
+
def clone
|
|
67
|
+
processor = super()
|
|
68
|
+
processor.samples = processor.samples.clone
|
|
69
|
+
processor
|
|
70
|
+
end
|
|
71
|
+
alias dup clone
|
|
72
|
+
|
|
73
|
+
# Convert to configuration file string
|
|
74
|
+
def to_config
|
|
75
|
+
" PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@item_name} #{@samples_to_average} #{@value_type}\n"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def as_json(*a)
|
|
79
|
+
{ 'name' => @name, 'class' => self.class.name, 'params' => [@item_name, @samples_to_average, @value_type.to_s] }
|
|
80
|
+
end
|
|
81
|
+
end # class StatisticsProcessor
|
|
82
|
+
end
|