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,345 @@
|
|
|
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/core_ext/io'
|
|
21
|
+
require 'openc3/packets/packet'
|
|
22
|
+
require 'openc3/packets/json_packet'
|
|
23
|
+
require 'openc3/io/buffered_file'
|
|
24
|
+
require 'openc3/logs/packet_log_constants'
|
|
25
|
+
|
|
26
|
+
module OpenC3
|
|
27
|
+
# Reads a packet log of either commands or telemetry.
|
|
28
|
+
class PacketLogReader
|
|
29
|
+
include PacketLogConstants
|
|
30
|
+
|
|
31
|
+
attr_reader :redis_offset
|
|
32
|
+
|
|
33
|
+
MAX_READ_SIZE = 1000000000
|
|
34
|
+
|
|
35
|
+
# Create a new log file reader
|
|
36
|
+
def initialize
|
|
37
|
+
reset()
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Yields back each packet as it is found in the log file.
|
|
41
|
+
#
|
|
42
|
+
# @param filename [String] The log file to read
|
|
43
|
+
# @param identify_and_define [Boolean] Once the packet has been read from
|
|
44
|
+
# the log file, whether to both identify the packet by setting the target
|
|
45
|
+
# and packet name, and define the packet by populating all the items.
|
|
46
|
+
# @param start_time [Time|nil] Time at which to start returning packets.
|
|
47
|
+
# Packets found with a timestamp before this time are ignored. Pass nil
|
|
48
|
+
# to return all packets.
|
|
49
|
+
# @param end_time [Time|nil] Time at which to stop returning packets.
|
|
50
|
+
# Packets found with a timestamp after this time are ignored. Pass nil
|
|
51
|
+
# to return all packets.
|
|
52
|
+
# @yieldparam packet [Packet]
|
|
53
|
+
# @return [Boolean] Whether we reached the end_time while reading
|
|
54
|
+
def each(filename, identify_and_define = true, start_time = nil, end_time = nil)
|
|
55
|
+
reached_end_time = false
|
|
56
|
+
open(filename)
|
|
57
|
+
|
|
58
|
+
# seek_to_time(start_time) if start_time
|
|
59
|
+
|
|
60
|
+
while true
|
|
61
|
+
packet = read(identify_and_define)
|
|
62
|
+
break unless packet
|
|
63
|
+
|
|
64
|
+
time = packet.packet_time
|
|
65
|
+
if time
|
|
66
|
+
next if start_time and time < start_time
|
|
67
|
+
# If we reach the end_time that means we found all the packets we asked for
|
|
68
|
+
# This can be used by callers to know they are done reading
|
|
69
|
+
if end_time and time > end_time
|
|
70
|
+
reached_end_time = true
|
|
71
|
+
break
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
yield packet
|
|
75
|
+
end
|
|
76
|
+
reached_end_time
|
|
77
|
+
ensure # No implicit return value in the ensure block
|
|
78
|
+
close()
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @param filename [String] The log filename to open
|
|
82
|
+
# @return [Boolean, Exception] Returns true if successfully changed to configuration specified in log,
|
|
83
|
+
# otherwise returns false and potentially an Exception class if an error occurred. If no error occurred
|
|
84
|
+
# false indicates that the requested configuration was simply not found.
|
|
85
|
+
def open(filename)
|
|
86
|
+
close()
|
|
87
|
+
reset()
|
|
88
|
+
@filename = filename
|
|
89
|
+
@file = BufferedFile.open(@filename, 'rb')
|
|
90
|
+
@max_read_size = @file.size
|
|
91
|
+
@max_read_size = MAX_READ_SIZE if @max_read_size > MAX_READ_SIZE
|
|
92
|
+
return read_file_header()
|
|
93
|
+
rescue => err
|
|
94
|
+
close()
|
|
95
|
+
raise err
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Closes the current log file
|
|
99
|
+
def close
|
|
100
|
+
@file.close if @file and !@file.closed?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Read a packet from the log file
|
|
104
|
+
#
|
|
105
|
+
# @param identify_and_define (see #each)
|
|
106
|
+
# @return [Packet]
|
|
107
|
+
def read(identify_and_define = true)
|
|
108
|
+
# Read entry length
|
|
109
|
+
length = @file.read(4)
|
|
110
|
+
return nil if !length or length.length <= 0
|
|
111
|
+
|
|
112
|
+
length = length.unpack('N')[0]
|
|
113
|
+
entry = @file.read(length)
|
|
114
|
+
flags = entry[0..1].unpack('n')[0]
|
|
115
|
+
|
|
116
|
+
cmd_or_tlm = :TLM
|
|
117
|
+
cmd_or_tlm = :CMD if flags & OPENC3_CMD_FLAG_MASK == OPENC3_CMD_FLAG_MASK
|
|
118
|
+
stored = false
|
|
119
|
+
stored = true if flags & OPENC3_STORED_FLAG_MASK == OPENC3_STORED_FLAG_MASK
|
|
120
|
+
id = false
|
|
121
|
+
id = true if flags & OPENC3_ID_FLAG_MASK == OPENC3_ID_FLAG_MASK
|
|
122
|
+
|
|
123
|
+
if flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_JSON_PACKET_ENTRY_TYPE_MASK
|
|
124
|
+
packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
|
|
125
|
+
json_data = entry[12..-1]
|
|
126
|
+
lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
|
|
127
|
+
if cmd_or_tlm != lookup_cmd_or_tlm
|
|
128
|
+
raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
return JsonPacket.new(cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, json_data)
|
|
132
|
+
elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_RAW_PACKET_ENTRY_TYPE_MASK
|
|
133
|
+
packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
|
|
134
|
+
packet_data = entry[12..-1]
|
|
135
|
+
lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
|
|
136
|
+
if cmd_or_tlm != lookup_cmd_or_tlm
|
|
137
|
+
raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
received_time = Time.from_nsec_from_epoch(time_nsec_since_epoch)
|
|
141
|
+
if identify_and_define
|
|
142
|
+
packet = identify_and_define_packet_data(cmd_or_tlm, target_name, packet_name, received_time, packet_data)
|
|
143
|
+
else
|
|
144
|
+
# Build Packet
|
|
145
|
+
packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
|
|
146
|
+
end
|
|
147
|
+
packet.set_received_time_fast(received_time)
|
|
148
|
+
packet.cmd_or_tlm = cmd_or_tlm
|
|
149
|
+
packet.stored = stored
|
|
150
|
+
packet.received_count += 1
|
|
151
|
+
return packet
|
|
152
|
+
elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_TARGET_DECLARATION_ENTRY_TYPE_MASK
|
|
153
|
+
target_name_length = length - OPENC3_PRIMARY_FIXED_SIZE - OPENC3_TARGET_DECLARATION_SECONDARY_FIXED_SIZE
|
|
154
|
+
target_name_length -= OPENC3_ID_FIXED_SIZE if id
|
|
155
|
+
target_name = entry[2..(target_name_length + 1)]
|
|
156
|
+
if id
|
|
157
|
+
id = entry[(target_name_length + 3)..(target_name_length + 34)]
|
|
158
|
+
@target_ids << id
|
|
159
|
+
end
|
|
160
|
+
@target_names << target_name
|
|
161
|
+
return read(identify_and_define)
|
|
162
|
+
elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK
|
|
163
|
+
target_index = entry[2..3].unpack('n')[0]
|
|
164
|
+
target_name = @target_names[target_index]
|
|
165
|
+
packet_name_length = length - OPENC3_PRIMARY_FIXED_SIZE - OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE
|
|
166
|
+
packet_name_length -= OPENC3_ID_FIXED_SIZE if id
|
|
167
|
+
packet_name = entry[4..(packet_name_length + 3)]
|
|
168
|
+
if id
|
|
169
|
+
id = entry[(packet_name_length + 4)..-1]
|
|
170
|
+
@packet_ids << id
|
|
171
|
+
end
|
|
172
|
+
@packets << [cmd_or_tlm, target_name, packet_name, id]
|
|
173
|
+
return read(identify_and_define)
|
|
174
|
+
elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_OFFSET_MARKER_ENTRY_TYPE_MASK
|
|
175
|
+
@redis_offset = entry[2..-1]
|
|
176
|
+
return read(identify_and_define)
|
|
177
|
+
else
|
|
178
|
+
raise "Invalid Entry Flags: #{flags}"
|
|
179
|
+
end
|
|
180
|
+
rescue => err
|
|
181
|
+
close()
|
|
182
|
+
raise err
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# TODO: Currently not used
|
|
186
|
+
# Returns an analysis of the log file by reading all the packets and
|
|
187
|
+
# returning information about each packet. This information maps directly
|
|
188
|
+
# to the parameters need by the {#read_at_offset} method and thus should be
|
|
189
|
+
# called before using {#read_at_offset}.
|
|
190
|
+
#
|
|
191
|
+
# @param filename [String] The filename to analyze
|
|
192
|
+
# @param progress_callback [Proc] Callback that should receive a single
|
|
193
|
+
# floating point parameter which is the percentage done
|
|
194
|
+
# @return [Array<Array<Integer, Integer, String, String, Time, Time>] Array
|
|
195
|
+
# of arrays for each packet found in the log file consisting of:
|
|
196
|
+
# [File position, length, target name, packet name, time formatted,
|
|
197
|
+
# received time].
|
|
198
|
+
# def packet_offsets(filename, progress_callback = nil)
|
|
199
|
+
# open(filename)
|
|
200
|
+
# offsets = []
|
|
201
|
+
# filesize = size().to_f
|
|
202
|
+
|
|
203
|
+
# while true
|
|
204
|
+
# current_pos = @file.pos
|
|
205
|
+
# packet = read(false)
|
|
206
|
+
# break unless packet
|
|
207
|
+
# offsets << current_pos
|
|
208
|
+
# if progress_callback
|
|
209
|
+
# break if progress_callback.call(current_pos / filesize)
|
|
210
|
+
# end
|
|
211
|
+
# end
|
|
212
|
+
|
|
213
|
+
# return offsets
|
|
214
|
+
# ensure
|
|
215
|
+
# close()
|
|
216
|
+
# end
|
|
217
|
+
|
|
218
|
+
# TODO: Currently not used
|
|
219
|
+
# Reads a packet from the opened log file. Should only be used in
|
|
220
|
+
# conjunction with {#packet_offsets}.
|
|
221
|
+
#
|
|
222
|
+
# @param file_offset [Integer] Byte offset into the log file to start
|
|
223
|
+
# reading
|
|
224
|
+
# @param identify_and_define (see #each)
|
|
225
|
+
# @return [Packet]
|
|
226
|
+
# def read_at_offset(file_offset, identify_and_define = true)
|
|
227
|
+
# @file.seek(file_offset, IO::SEEK_SET)
|
|
228
|
+
# return read(identify_and_define)
|
|
229
|
+
# rescue => err
|
|
230
|
+
# close()
|
|
231
|
+
# raise err
|
|
232
|
+
# end
|
|
233
|
+
|
|
234
|
+
# TODO: Currently not used
|
|
235
|
+
# Read the first packet from the log file and reset the file position back
|
|
236
|
+
# to the current position. This allows the client to call read multiple
|
|
237
|
+
# times to return packets, call first, and continue calling read which will
|
|
238
|
+
# return the next packet in the file.
|
|
239
|
+
#
|
|
240
|
+
# @return [Packet]
|
|
241
|
+
# def first
|
|
242
|
+
# original_position = @file.pos
|
|
243
|
+
# @file.seek(0, IO::SEEK_SET)
|
|
244
|
+
# read_file_header()
|
|
245
|
+
# packet = read()
|
|
246
|
+
# raise "No first packet found" unless packet
|
|
247
|
+
# @file.seek(original_position, IO::SEEK_SET)
|
|
248
|
+
# packet.clone
|
|
249
|
+
# rescue => err
|
|
250
|
+
# close()
|
|
251
|
+
# raise err
|
|
252
|
+
# end
|
|
253
|
+
|
|
254
|
+
# TODO: Currently not used
|
|
255
|
+
# Read the last packet from the log file and reset the file position back
|
|
256
|
+
# to the current position. This allows the client to call read multiple
|
|
257
|
+
# times to return packets, call last, and continue calling read which will
|
|
258
|
+
# return the next packet in the file.
|
|
259
|
+
#
|
|
260
|
+
# @return [Packet]
|
|
261
|
+
# def last
|
|
262
|
+
# raise "TODO: Implement me - Need to add end of file entry to support"
|
|
263
|
+
# original_position = @file.pos
|
|
264
|
+
# @file.seek(-1, IO::SEEK_END)
|
|
265
|
+
# packet = search(-1)
|
|
266
|
+
# raise "No last packet found" unless packet
|
|
267
|
+
# @file.seek(original_position, IO::SEEK_SET)
|
|
268
|
+
# packet.clone
|
|
269
|
+
# rescue => err
|
|
270
|
+
# close()
|
|
271
|
+
# raise err
|
|
272
|
+
# end
|
|
273
|
+
|
|
274
|
+
# @return [Integer] The size of the log file being processed
|
|
275
|
+
def size
|
|
276
|
+
@file.stat.size
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# @return [Integer] The current file position in the log file
|
|
280
|
+
def bytes_read
|
|
281
|
+
@file.pos
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
protected
|
|
285
|
+
|
|
286
|
+
def reset
|
|
287
|
+
@file = nil
|
|
288
|
+
@filename = nil
|
|
289
|
+
@max_read_size = MAX_READ_SIZE
|
|
290
|
+
@target_names = []
|
|
291
|
+
@target_ids = []
|
|
292
|
+
@packets = []
|
|
293
|
+
@packet_ids = []
|
|
294
|
+
@redis_offset = nil
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# This is best effort. May return unidentified/undefined packets
|
|
298
|
+
def identify_and_define_packet_data(cmd_or_tlm, target_name, packet_name, received_time, packet_data)
|
|
299
|
+
packet = nil
|
|
300
|
+
unless target_name and packet_name
|
|
301
|
+
if cmd_or_tlm == :CMD
|
|
302
|
+
packet = System.commands.identify(packet_data)
|
|
303
|
+
else
|
|
304
|
+
packet = System.telemetry.identify!(packet_data)
|
|
305
|
+
end
|
|
306
|
+
else
|
|
307
|
+
begin
|
|
308
|
+
if cmd_or_tlm == :CMD
|
|
309
|
+
packet = System.commands.packet(target_name, packet_name)
|
|
310
|
+
else
|
|
311
|
+
packet = System.telemetry.packet(target_name, packet_name)
|
|
312
|
+
end
|
|
313
|
+
packet.buffer = packet_data
|
|
314
|
+
rescue
|
|
315
|
+
# Could not find a definition for this packet
|
|
316
|
+
Logger.instance.error "Unknown packet #{target_name} #{packet_name}"
|
|
317
|
+
packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
packet
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Should return if successfully switched to requested configuration
|
|
324
|
+
def read_file_header
|
|
325
|
+
header = @file.read(OPENC3_HEADER_LENGTH)
|
|
326
|
+
if header and header.length == OPENC3_HEADER_LENGTH
|
|
327
|
+
if header == OPENC3_FILE_HEADER
|
|
328
|
+
# Found OpenC3 5 File Header - That's all we need to do
|
|
329
|
+
elsif header == COSMOS4_FILE_HEADER
|
|
330
|
+
raise "COSMOS 4 log file must be converted to OpenC3 5"
|
|
331
|
+
elsif header == COSMOS2_FILE_HEADER
|
|
332
|
+
raise "COSMOS 2 log file must be converted to OpenC3 5"
|
|
333
|
+
else
|
|
334
|
+
raise "OpenC3 file header not found"
|
|
335
|
+
end
|
|
336
|
+
else
|
|
337
|
+
raise "Failed to read at least #{OPENC3_HEADER_LENGTH} bytes from packet log"
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def seek_to_time(time)
|
|
342
|
+
raise "TODO: Implement me - Use index file or offsets"
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
@@ -0,0 +1,299 @@
|
|
|
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/logs/log_writer'
|
|
21
|
+
require 'openc3/logs/packet_log_constants'
|
|
22
|
+
|
|
23
|
+
module OpenC3
|
|
24
|
+
# Creates a packet log. Can automatically cycle the log based on an elasped
|
|
25
|
+
# time period or when the log file reaches a predefined size.
|
|
26
|
+
class PacketLogWriter < LogWriter
|
|
27
|
+
include PacketLogConstants
|
|
28
|
+
|
|
29
|
+
# @param remote_log_directory [String] The s3 path to store the log files
|
|
30
|
+
# @param label [String] Label to apply to the log filename
|
|
31
|
+
# @param logging_enabled [Boolean] Whether to start with logging enabled
|
|
32
|
+
# @param cycle_time [Integer] The amount of time in seconds before creating
|
|
33
|
+
# a new log file. This can be combined with cycle_size but is better used
|
|
34
|
+
# independently.
|
|
35
|
+
# @param cycle_size [Integer] The size in bytes before creating a new log
|
|
36
|
+
# file. This can be combined with cycle_time but is better used
|
|
37
|
+
# independently.
|
|
38
|
+
# @param cycle_hour [Integer] The time at which to cycle the log. Combined with
|
|
39
|
+
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
|
40
|
+
# will be cycled hourly at the specified cycle_minute.
|
|
41
|
+
# @param cycle_minute [Integer] The time at which to cycle the log. See cycle_hour
|
|
42
|
+
# for more information.
|
|
43
|
+
# @param redis_topic [String] The key of the Redis stream to trim when files are
|
|
44
|
+
# moved to S3
|
|
45
|
+
def initialize(
|
|
46
|
+
remote_log_directory,
|
|
47
|
+
label,
|
|
48
|
+
logging_enabled = true,
|
|
49
|
+
cycle_time = nil,
|
|
50
|
+
cycle_size = 1_000_000_000,
|
|
51
|
+
cycle_hour = nil,
|
|
52
|
+
cycle_minute = nil,
|
|
53
|
+
redis_topic: nil
|
|
54
|
+
)
|
|
55
|
+
super(
|
|
56
|
+
remote_log_directory,
|
|
57
|
+
logging_enabled,
|
|
58
|
+
cycle_time,
|
|
59
|
+
cycle_size,
|
|
60
|
+
cycle_hour,
|
|
61
|
+
cycle_minute,
|
|
62
|
+
redis_topic: redis_topic
|
|
63
|
+
)
|
|
64
|
+
@label = label
|
|
65
|
+
@index_file = nil
|
|
66
|
+
@index_filename = nil
|
|
67
|
+
@cmd_packet_table = {}
|
|
68
|
+
@tlm_packet_table = {}
|
|
69
|
+
@target_dec_entries = []
|
|
70
|
+
@packet_dec_entries = []
|
|
71
|
+
@next_packet_index = 0
|
|
72
|
+
@target_indexes = {}
|
|
73
|
+
@next_target_index = 0
|
|
74
|
+
|
|
75
|
+
# This is an optimization to avoid creating a new entry object
|
|
76
|
+
# each time we create an entry which we do a LOT!
|
|
77
|
+
@index_entry = String.new
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Write a packet to the log file.
|
|
81
|
+
#
|
|
82
|
+
# If no log file currently exists in the filesystem, a new file will be
|
|
83
|
+
# created.
|
|
84
|
+
#
|
|
85
|
+
# @param entry_type [Symbol] Type of entry to write. Must be one of
|
|
86
|
+
# :TARGET_DECLARATION, :PACKET_DECLARATION, :RAW_PACKET, :JSON_PACKET
|
|
87
|
+
# @param cmd_or_tlm [Symbol] One of :CMD or :TLM
|
|
88
|
+
# @param target_name [String] Name of the target
|
|
89
|
+
# @param packet_name [String] Name of the packet
|
|
90
|
+
# @param time_nsec_since_epoch [Integer] 64 bit integer nsecs since EPOCH
|
|
91
|
+
# @param stored [Boolean] Whether this data is stored telemetry
|
|
92
|
+
# @param data [String] Binary string of data
|
|
93
|
+
# @param id [Integer] Target ID
|
|
94
|
+
# @param redis_offset [Integer] The offset of this packet in its Redis stream
|
|
95
|
+
def write(entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id = nil, redis_offset = '0-0')
|
|
96
|
+
return if !@logging_enabled
|
|
97
|
+
|
|
98
|
+
@mutex.synchronize do
|
|
99
|
+
prepare_write(time_nsec_since_epoch, data.length, redis_offset)
|
|
100
|
+
write_entry(entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id) if @file
|
|
101
|
+
end
|
|
102
|
+
rescue => err
|
|
103
|
+
Logger.instance.error "Error writing #{@filename} : #{err.formatted}"
|
|
104
|
+
OpenC3.handle_critical_exception(err)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Starting a new index file is a critical operation so the entire method is
|
|
108
|
+
# wrapped with a rescue and handled with handle_critical_exception
|
|
109
|
+
# Assumes mutex has already been taken
|
|
110
|
+
def start_new_file
|
|
111
|
+
super
|
|
112
|
+
@file.write(OPENC3_FILE_HEADER)
|
|
113
|
+
@file_size += OPENC3_FILE_HEADER.length
|
|
114
|
+
|
|
115
|
+
# Start index log file
|
|
116
|
+
@index_filename = create_unique_filename('.idx'.freeze)
|
|
117
|
+
@index_file = File.new(@index_filename, 'wb')
|
|
118
|
+
@index_file.write(OPENC3_INDEX_HEADER)
|
|
119
|
+
|
|
120
|
+
@cmd_packet_table = {}
|
|
121
|
+
@tlm_packet_table = {}
|
|
122
|
+
@next_packet_index = 0
|
|
123
|
+
@target_indexes = {}
|
|
124
|
+
@target_dec_entries = []
|
|
125
|
+
@packet_dec_entries = []
|
|
126
|
+
Logger.debug "Index Log File Opened : #{@index_filename}"
|
|
127
|
+
rescue => err
|
|
128
|
+
Logger.error "Error starting new log file: #{err.formatted}"
|
|
129
|
+
@logging_enabled = false
|
|
130
|
+
OpenC3.handle_critical_exception(err)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Closing a log file isn't critical so we just log an error
|
|
134
|
+
def close_file(take_mutex = true)
|
|
135
|
+
write_entry(:OFFSET_MARKER, nil, nil, nil, nil, nil, nil, nil) if @file
|
|
136
|
+
super
|
|
137
|
+
|
|
138
|
+
@mutex.lock if take_mutex
|
|
139
|
+
begin
|
|
140
|
+
if @index_file
|
|
141
|
+
begin
|
|
142
|
+
write_index_file_footer()
|
|
143
|
+
@index_file.close unless @index_file.closed?
|
|
144
|
+
Logger.debug "Index Log File Closed : #{@index_filename}"
|
|
145
|
+
date = first_timestamp[0..7] # YYYYMMDD
|
|
146
|
+
s3_key = File.join(@remote_log_directory, date, "#{first_timestamp}__#{last_timestamp}__#{@label}.idx")
|
|
147
|
+
S3Utilities.move_log_file_to_s3(@index_filename, s3_key)
|
|
148
|
+
rescue Exception => err
|
|
149
|
+
Logger.instance.error "Error closing #{@index_filename} : #{err.formatted}"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
@index_file = nil
|
|
153
|
+
@index_filename = nil
|
|
154
|
+
end
|
|
155
|
+
ensure
|
|
156
|
+
@mutex.unlock if take_mutex
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def get_packet_index(cmd_or_tlm, target_name, packet_name)
|
|
161
|
+
if cmd_or_tlm == :CMD
|
|
162
|
+
target_table = @cmd_packet_table[target_name]
|
|
163
|
+
else
|
|
164
|
+
target_table = @tlm_packet_table[target_name]
|
|
165
|
+
end
|
|
166
|
+
if target_table
|
|
167
|
+
packet_index = target_table[packet_name]
|
|
168
|
+
return packet_index if packet_index
|
|
169
|
+
else
|
|
170
|
+
# New packet_table entry needed
|
|
171
|
+
target_table = {}
|
|
172
|
+
if cmd_or_tlm == :CMD
|
|
173
|
+
@cmd_packet_table[target_name] = target_table
|
|
174
|
+
else
|
|
175
|
+
@tlm_packet_table[target_name] = target_table
|
|
176
|
+
end
|
|
177
|
+
id = nil
|
|
178
|
+
target = System.targets[target_name]
|
|
179
|
+
id = target.id if target
|
|
180
|
+
write_entry(:TARGET_DECLARATION, cmd_or_tlm, target_name, packet_name, nil, nil, nil, id)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# New target_table entry needed
|
|
184
|
+
packet_index = @next_packet_index
|
|
185
|
+
if packet_index > OPENC3_MAX_PACKET_INDEX
|
|
186
|
+
raise "Packet Index Overflow"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
target_table[packet_name] = packet_index
|
|
190
|
+
@next_packet_index += 1
|
|
191
|
+
|
|
192
|
+
id = nil
|
|
193
|
+
begin
|
|
194
|
+
if cmd_or_tlm == :CMD
|
|
195
|
+
id = System.commands.packet(target_nam, packet_name).config_name
|
|
196
|
+
else
|
|
197
|
+
id = System.telemetry.packet(target_name, packet_name).config_name
|
|
198
|
+
end
|
|
199
|
+
rescue
|
|
200
|
+
# No packet def
|
|
201
|
+
end
|
|
202
|
+
write_entry(:PACKET_DECLARATION, cmd_or_tlm, target_name, packet_name, nil, nil, nil, id)
|
|
203
|
+
return packet_index
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def write_entry(entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id)
|
|
207
|
+
raise ArgumentError.new("Length of id must be 64, got #{id.length}") if id and id.length != 64 # 64 hex digits, gets packed to 32 bytes with .pack('H*')
|
|
208
|
+
|
|
209
|
+
length = OPENC3_PRIMARY_FIXED_SIZE
|
|
210
|
+
flags = 0
|
|
211
|
+
flags |= OPENC3_STORED_FLAG_MASK if stored
|
|
212
|
+
flags |= OPENC3_ID_FLAG_MASK if id
|
|
213
|
+
case entry_type
|
|
214
|
+
when :TARGET_DECLARATION
|
|
215
|
+
target_index = @next_target_index
|
|
216
|
+
@target_indexes[target_name] = target_index
|
|
217
|
+
@next_target_index += 1
|
|
218
|
+
if target_index > OPENC3_MAX_TARGET_INDEX
|
|
219
|
+
raise "Target Index Overflow"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
flags |= OPENC3_TARGET_DECLARATION_ENTRY_TYPE_MASK
|
|
223
|
+
length += OPENC3_TARGET_DECLARATION_SECONDARY_FIXED_SIZE + target_name.length
|
|
224
|
+
length += OPENC3_ID_FIXED_SIZE if id
|
|
225
|
+
@entry.clear
|
|
226
|
+
@entry << [length, flags].pack(OPENC3_TARGET_DECLARATION_PACK_DIRECTIVE) << target_name
|
|
227
|
+
@entry << [id].pack('H*') if id
|
|
228
|
+
@target_dec_entries << @entry.dup
|
|
229
|
+
when :PACKET_DECLARATION
|
|
230
|
+
target_index = @target_indexes[target_name]
|
|
231
|
+
flags |= OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK
|
|
232
|
+
if cmd_or_tlm == :CMD
|
|
233
|
+
flags |= OPENC3_CMD_FLAG_MASK
|
|
234
|
+
end
|
|
235
|
+
length += OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE + packet_name.length
|
|
236
|
+
length += OPENC3_ID_FIXED_SIZE if id
|
|
237
|
+
@entry.clear
|
|
238
|
+
@entry << [length, flags, target_index].pack(OPENC3_PACKET_DECLARATION_PACK_DIRECTIVE) << packet_name
|
|
239
|
+
@entry << [id].pack('H*') if id
|
|
240
|
+
@packet_dec_entries << @entry.dup
|
|
241
|
+
when :OFFSET_MARKER
|
|
242
|
+
flags |= OPENC3_OFFSET_MARKER_ENTRY_TYPE_MASK
|
|
243
|
+
length += OPENC3_OFFSET_MARKER_SECONDARY_FIXED_SIZE + @last_offset.length
|
|
244
|
+
@entry.clear
|
|
245
|
+
@entry << [length, flags].pack(OPENC3_OFFSET_MARKER_PACK_DIRECTIVE) << @last_offset
|
|
246
|
+
when :RAW_PACKET, :JSON_PACKET
|
|
247
|
+
target_name = 'UNKNOWN'.freeze unless target_name
|
|
248
|
+
packet_name = 'UNKNOWN'.freeze unless packet_name
|
|
249
|
+
packet_index = get_packet_index(cmd_or_tlm, target_name, packet_name)
|
|
250
|
+
if entry_type == :RAW_PACKET
|
|
251
|
+
flags |= OPENC3_RAW_PACKET_ENTRY_TYPE_MASK
|
|
252
|
+
else
|
|
253
|
+
flags |= OPENC3_JSON_PACKET_ENTRY_TYPE_MASK
|
|
254
|
+
end
|
|
255
|
+
if cmd_or_tlm == :CMD
|
|
256
|
+
flags |= OPENC3_CMD_FLAG_MASK
|
|
257
|
+
end
|
|
258
|
+
length += OPENC3_PACKET_SECONDARY_FIXED_SIZE + data.length
|
|
259
|
+
@entry.clear
|
|
260
|
+
@index_entry.clear
|
|
261
|
+
@index_entry << [length, flags, packet_index, time_nsec_since_epoch].pack(OPENC3_PACKET_PACK_DIRECTIVE)
|
|
262
|
+
@entry << @index_entry << data
|
|
263
|
+
@index_entry << [@file_size].pack('Q>')
|
|
264
|
+
@index_file.write(@index_entry)
|
|
265
|
+
@first_time = time_nsec_since_epoch if !@first_time or time_nsec_since_epoch < @first_time
|
|
266
|
+
@last_time = time_nsec_since_epoch if !@last_time or time_nsec_since_epoch > @last_time
|
|
267
|
+
else
|
|
268
|
+
raise "Unknown entry_type: #{entry_type}"
|
|
269
|
+
end
|
|
270
|
+
@file.write(@entry)
|
|
271
|
+
@file_size += @entry.length
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def write_index_file_footer
|
|
275
|
+
footer_length = 4 # Includes length of length field at end
|
|
276
|
+
@index_file.write([@target_dec_entries.length].pack('n'))
|
|
277
|
+
footer_length += 2
|
|
278
|
+
@target_dec_entries.each do |target_dec_entry|
|
|
279
|
+
@index_file.write(target_dec_entry)
|
|
280
|
+
footer_length += target_dec_entry.length
|
|
281
|
+
end
|
|
282
|
+
@index_file.write([@packet_dec_entries.length].pack('n'))
|
|
283
|
+
footer_length += 2
|
|
284
|
+
@packet_dec_entries.each do |packet_dec_entry|
|
|
285
|
+
@index_file.write(packet_dec_entry)
|
|
286
|
+
footer_length += packet_dec_entry.length
|
|
287
|
+
end
|
|
288
|
+
@index_file.write([footer_length].pack('N'))
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def s3_filename
|
|
292
|
+
"#{first_timestamp}__#{last_timestamp}__#{@label}" + extension
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def extension
|
|
296
|
+
'.bin'.freeze
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|