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,313 @@
|
|
|
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/microservices/microservice'
|
|
21
|
+
require 'openc3/topics/topic'
|
|
22
|
+
require 'openc3/packets/json_packet'
|
|
23
|
+
require 'openc3/utilities/s3_file_cache'
|
|
24
|
+
require 'openc3/models/reducer_model'
|
|
25
|
+
require 'rufus-scheduler'
|
|
26
|
+
|
|
27
|
+
module OpenC3
|
|
28
|
+
class ReducerMicroservice < Microservice
|
|
29
|
+
MINUTE_METRIC = 'reducer_minute_duration'
|
|
30
|
+
HOUR_METRIC = 'reducer_hour_duration'
|
|
31
|
+
DAY_METRIC = 'reducer_day_duration'
|
|
32
|
+
|
|
33
|
+
# How long to wait for any currently running jobs to complete before killing them
|
|
34
|
+
SHUTDOWN_DELAY_SECS = 5
|
|
35
|
+
MINUTE_ENTRY_SECS = 60
|
|
36
|
+
MINUTE_FILE_SECS = 3600
|
|
37
|
+
HOUR_ENTRY_SECS = 3600
|
|
38
|
+
HOUR_FILE_SECS = 3600 * 24
|
|
39
|
+
DAY_ENTRY_SECS = 3600 * 24
|
|
40
|
+
DAY_FILE_SECS = 3600 * 24 * 30
|
|
41
|
+
|
|
42
|
+
# @param name [String] Microservice name formatted as <SCOPE>__REDUCER__<TARGET>
|
|
43
|
+
# where <SCOPE> and <TARGET> are variables representing the scope name and target name
|
|
44
|
+
def initialize(name)
|
|
45
|
+
super(name, is_plugin: false)
|
|
46
|
+
@target_name = name.split('__')[-1]
|
|
47
|
+
@packet_logs = {}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def run
|
|
51
|
+
# Note it takes several seconds to create the scheduler
|
|
52
|
+
@scheduler = Rufus::Scheduler.new
|
|
53
|
+
# Run every minute
|
|
54
|
+
@scheduler.cron '* * * * *', first: :now do
|
|
55
|
+
reduce_minute
|
|
56
|
+
end
|
|
57
|
+
# Run every 15 minutes
|
|
58
|
+
@scheduler.cron '*/15 * * * *', first: :now do
|
|
59
|
+
reduce_hour
|
|
60
|
+
end
|
|
61
|
+
# Run hourly at minute 5 to allow the hour reducer to finish
|
|
62
|
+
@scheduler.cron '5 * * * *', first: :now do
|
|
63
|
+
reduce_day
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Let the current thread join the scheduler thread and
|
|
67
|
+
# block until shutdown is called
|
|
68
|
+
@scheduler.join
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def shutdown
|
|
72
|
+
@scheduler.shutdown(wait: SHUTDOWN_DELAY_SECS) if @scheduler
|
|
73
|
+
|
|
74
|
+
# Make sure all the existing logs are properly closed down
|
|
75
|
+
@packet_logs.each do |name, log|
|
|
76
|
+
log.shutdown
|
|
77
|
+
end
|
|
78
|
+
super()
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def metric(name)
|
|
82
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
83
|
+
yield
|
|
84
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
85
|
+
@metric.add_sample(
|
|
86
|
+
name: name,
|
|
87
|
+
value: elapsed,
|
|
88
|
+
labels: {
|
|
89
|
+
'target' => @target_name,
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def reduce_minute
|
|
95
|
+
metric(MINUTE_METRIC) do
|
|
96
|
+
ReducerModel
|
|
97
|
+
.all_files(type: :DECOM, target: @target_name, scope: @scope)
|
|
98
|
+
.each do |file|
|
|
99
|
+
process_file(file, 'minute', MINUTE_ENTRY_SECS, MINUTE_FILE_SECS)
|
|
100
|
+
ReducerModel.rm_file(file)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def reduce_hour
|
|
106
|
+
metric(HOUR_METRIC) do
|
|
107
|
+
ReducerModel
|
|
108
|
+
.all_files(type: :MINUTE, target: @target_name, scope: @scope)
|
|
109
|
+
.each do |file|
|
|
110
|
+
process_file(file, 'hour', HOUR_ENTRY_SECS, HOUR_FILE_SECS)
|
|
111
|
+
ReducerModel.rm_file(file)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def reduce_day
|
|
117
|
+
metric(DAY_METRIC) do
|
|
118
|
+
ReducerModel
|
|
119
|
+
.all_files(type: :HOUR, target: @target_name, scope: @scope)
|
|
120
|
+
.each do |file|
|
|
121
|
+
process_file(file, 'day', DAY_ENTRY_SECS, DAY_FILE_SECS)
|
|
122
|
+
ReducerModel.rm_file(file)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def process_file(filename, type, entry_seconds, file_seconds)
|
|
128
|
+
file = S3File.new(filename)
|
|
129
|
+
file.retrieve
|
|
130
|
+
|
|
131
|
+
# Determine if we already have a PacketLogWriter created
|
|
132
|
+
start_time, end_time, scope, target_name, packet_name, _ =
|
|
133
|
+
filename.split('__')
|
|
134
|
+
if @target_name != target_name
|
|
135
|
+
raise "Target name in file #{filename} does not match microservice target name #{@target_name}"
|
|
136
|
+
end
|
|
137
|
+
plw = @packet_logs["#{scope}__#{target_name}__#{packet_name}__#{type}"]
|
|
138
|
+
unless plw
|
|
139
|
+
# Create a new PacketLogWriter for this reduced data
|
|
140
|
+
# e.g. DEFAULT/reduced_minute_logs/tlm/INST/HEALTH_STATUS/20220101/
|
|
141
|
+
# 20220101204857274290500__20220101205857276524900__DEFAULT__INST__HEALTH_STATUS__reduced__minute.bin
|
|
142
|
+
remote_log_directory = "#{scope}/reduced_#{type}_logs/tlm/#{target_name}/#{packet_name}"
|
|
143
|
+
rt_label = "#{scope}__#{target_name}__#{packet_name}__reduced__#{type}"
|
|
144
|
+
plw = PacketLogWriter.new(remote_log_directory, rt_label)
|
|
145
|
+
@packet_logs["#{scope}__#{target_name}__#{packet_name}__#{type}"] = plw
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
reduced = {}
|
|
149
|
+
data_keys = nil
|
|
150
|
+
entry_time = nil
|
|
151
|
+
current_time = nil
|
|
152
|
+
previous_time = nil
|
|
153
|
+
plr = OpenC3::PacketLogReader.new
|
|
154
|
+
plr.each(file.local_path) do |packet|
|
|
155
|
+
# Ignore anything except numbers like STRING or BLOCK items
|
|
156
|
+
data = packet.read_all(:RAW).select { |key, value| value.is_a?(Numeric) }
|
|
157
|
+
converted_data = packet.read_all(:CONVERTED).select { |key, value| value.is_a?(Numeric) }
|
|
158
|
+
# Merge in the converted data which overwrites the raw
|
|
159
|
+
data.merge!(converted_data)
|
|
160
|
+
|
|
161
|
+
previous_time = current_time
|
|
162
|
+
current_time = packet.packet_time.to_f
|
|
163
|
+
entry_time ||= current_time
|
|
164
|
+
data_keys ||= data.keys
|
|
165
|
+
|
|
166
|
+
# Determine if we've rolled over a entry boundary
|
|
167
|
+
# We have to use current % entry_seconds < previous % entry_seconds because
|
|
168
|
+
# we don't know the data rates. We also have to check for current - previous >= entry_seconds
|
|
169
|
+
# in case the data rate is so slow we don't have multiple samples per entry
|
|
170
|
+
if previous_time &&
|
|
171
|
+
(
|
|
172
|
+
(current_time % entry_seconds < previous_time % entry_seconds) ||
|
|
173
|
+
(current_time - previous_time >= entry_seconds)
|
|
174
|
+
)
|
|
175
|
+
Logger.debug("Reducer: Roll over entry boundary cur_time:#{current_time}")
|
|
176
|
+
|
|
177
|
+
reduce(type, data_keys, reduced)
|
|
178
|
+
plw.write(
|
|
179
|
+
:JSON_PACKET,
|
|
180
|
+
:TLM,
|
|
181
|
+
target_name,
|
|
182
|
+
packet_name,
|
|
183
|
+
entry_time * Time::NSEC_PER_SECOND,
|
|
184
|
+
false,
|
|
185
|
+
JSON.generate(reduced.as_json(:allow_nan => true)),
|
|
186
|
+
)
|
|
187
|
+
# Reset all our sample variables
|
|
188
|
+
entry_time = current_time
|
|
189
|
+
reduced = {}
|
|
190
|
+
|
|
191
|
+
# Check to see if we should start a new log file
|
|
192
|
+
# We compare the current entry_time to see if it will push us over
|
|
193
|
+
if plw.first_time &&
|
|
194
|
+
(entry_time - plw.first_time.to_f) >= file_seconds
|
|
195
|
+
Logger.debug("Reducer: (1) start new file! old filename: #{plw.filename}")
|
|
196
|
+
plw.start_new_file # Automatically closes the current file
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Update statistics for this packet's values
|
|
201
|
+
data.each do |key, value|
|
|
202
|
+
if type == 'minute'
|
|
203
|
+
reduced["#{key}__VALS"] ||= []
|
|
204
|
+
reduced["#{key}__VALS"] << value
|
|
205
|
+
reduced["#{key}_MIN"] ||= value
|
|
206
|
+
reduced["#{key}_MIN"] = value if value < reduced["#{key}_MIN"]
|
|
207
|
+
reduced["#{key}_MAX"] ||= value
|
|
208
|
+
reduced["#{key}_MAX"] = value if value > reduced["#{key}_MAX"]
|
|
209
|
+
else
|
|
210
|
+
reduced[key] ||= value
|
|
211
|
+
reduced[key] = value if key.match(/_MIN$/) && value < reduced[key]
|
|
212
|
+
reduced[key] = value if key.match(/_MAX$/) && value > reduced[key]
|
|
213
|
+
if key.match(/_AVG$/)
|
|
214
|
+
reduced["#{key}__VALS"] ||= []
|
|
215
|
+
reduced["#{key}__VALS"] << value
|
|
216
|
+
end
|
|
217
|
+
if key.match(/_STDDEV$/)
|
|
218
|
+
reduced["#{key}__VALS"] ||= []
|
|
219
|
+
reduced["#{key}__VALS"] << value
|
|
220
|
+
end
|
|
221
|
+
if key.match(/_SAMPLES$/)
|
|
222
|
+
reduced["#{key}__VALS"] ||= []
|
|
223
|
+
reduced["#{key}__VALS"] << value
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
file.delete # Remove the local copy
|
|
229
|
+
|
|
230
|
+
# See if this last entry should go in a new file
|
|
231
|
+
if plw.first_time &&
|
|
232
|
+
(entry_time - plw.first_time.to_f) >= file_seconds
|
|
233
|
+
Logger.debug("Reducer: (2) start new file! old filename: #{plw.filename}")
|
|
234
|
+
plw.start_new_file # Automatically closes the current file
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Write out the final data now that the file is done
|
|
238
|
+
reduce(type, data_keys, reduced)
|
|
239
|
+
plw.write(
|
|
240
|
+
:JSON_PACKET,
|
|
241
|
+
:TLM,
|
|
242
|
+
target_name,
|
|
243
|
+
packet_name,
|
|
244
|
+
entry_time * Time::NSEC_PER_SECOND,
|
|
245
|
+
false,
|
|
246
|
+
JSON.generate(reduced.as_json(:allow_nan => true)),
|
|
247
|
+
)
|
|
248
|
+
true
|
|
249
|
+
rescue => e
|
|
250
|
+
if file.local_path and File.exist?(file.local_path)
|
|
251
|
+
Logger.error("Reducer Error: #{filename}:#{File.size(file.local_path)} bytes: \n#{e.formatted}")
|
|
252
|
+
else
|
|
253
|
+
Logger.error("Reducer Error: #{filename}:(Not Retrieved): \n#{e.formatted}")
|
|
254
|
+
end
|
|
255
|
+
false
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def reduce(type, data_keys, reduced)
|
|
259
|
+
# We've collected all the values so calculate the AVG and STDDEV
|
|
260
|
+
if type == 'minute'
|
|
261
|
+
data_keys.each do |key|
|
|
262
|
+
reduced["#{key}_SAMPLES"] = reduced["#{key}__VALS"].length
|
|
263
|
+
reduced["#{key}_AVG"], reduced["#{key}_STDDEV"] =
|
|
264
|
+
Math.stddev_population(reduced["#{key}__VALS"])
|
|
265
|
+
|
|
266
|
+
# Remove the raw values as they're only used for AVG / STDDEV calculation
|
|
267
|
+
reduced.delete("#{key}__VALS")
|
|
268
|
+
end
|
|
269
|
+
else
|
|
270
|
+
# Sort so we calculate the average first, then samples, then stddev
|
|
271
|
+
data_keys.sort.each do |key|
|
|
272
|
+
base_name = key.split('_')[0..-2].join('_')
|
|
273
|
+
case key
|
|
274
|
+
when /_AVG$/
|
|
275
|
+
weighted_sum = 0
|
|
276
|
+
samples = reduced["#{base_name}_SAMPLES__VALS"]
|
|
277
|
+
reduced["#{key}__VALS"].each_with_index do |val, i|
|
|
278
|
+
weighted_sum += (val * samples[i])
|
|
279
|
+
end
|
|
280
|
+
reduced[key] = weighted_sum / samples.sum
|
|
281
|
+
when /_SAMPLES$/
|
|
282
|
+
reduced[key] = reduced["#{base_name}_SAMPLES__VALS"].sum
|
|
283
|
+
when /_STDDEV$/
|
|
284
|
+
# Do the STDDEV calc last so we can use the previously calculated AVG
|
|
285
|
+
# See https://math.stackexchange.com/questions/1547141/aggregating-standard-deviation-to-a-summary-point
|
|
286
|
+
samples = reduced["#{base_name}_SAMPLES__VALS"]
|
|
287
|
+
avg = reduced["#{base_name}_AVG__VALS"]
|
|
288
|
+
s2 = 0
|
|
289
|
+
reduced["#{key}__VALS"].each_with_index do |val, i|
|
|
290
|
+
# puts "i:#{i} val:#{val} samples[i]:#{samples[i]} avg[i]:#{avg[i]}"
|
|
291
|
+
s2 += (samples[i] * avg[i]**2 + val**2)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Note: For very large numbers with very small deviations this sqrt can fail.
|
|
295
|
+
# If so then just set the stddev to 0.
|
|
296
|
+
begin
|
|
297
|
+
reduced[key] =
|
|
298
|
+
Math.sqrt(s2 / samples.sum - reduced["#{base_name}_AVG"])
|
|
299
|
+
rescue Exception
|
|
300
|
+
reduced[key] = 0.0
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
data_keys.each do |key|
|
|
305
|
+
# Remove the raw values as they're only used for AVG / STDDEV calculation
|
|
306
|
+
reduced.delete("#{key}__VALS")
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
OpenC3::ReducerMicroservice.run if __FILE__ == $0
|
|
@@ -0,0 +1,44 @@
|
|
|
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/microservices/interface_microservice'
|
|
21
|
+
|
|
22
|
+
module OpenC3
|
|
23
|
+
class RouterMicroservice < InterfaceMicroservice
|
|
24
|
+
def handle_packet(packet)
|
|
25
|
+
@count += 1
|
|
26
|
+
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
|
27
|
+
if !packet.identified?
|
|
28
|
+
# Need to identify so we can find the target
|
|
29
|
+
identified_packet = System.commands.identify(packet.buffer(false), @target_names)
|
|
30
|
+
packet = identified_packet if identified_packet
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
begin
|
|
34
|
+
RouterTopic.route_command(packet, @target_names, scope: @scope)
|
|
35
|
+
@count += 1
|
|
36
|
+
rescue Exception => err
|
|
37
|
+
@error = err
|
|
38
|
+
Logger.error "Error routing command from #{@interface.name}\n#{err.formatted}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
OpenC3::RouterMicroservice.run if __FILE__ == $0
|
|
@@ -0,0 +1,84 @@
|
|
|
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/microservices/microservice'
|
|
21
|
+
require 'openc3/topics/topic'
|
|
22
|
+
|
|
23
|
+
module OpenC3
|
|
24
|
+
class TextLogMicroservice < Microservice
|
|
25
|
+
def initialize(name)
|
|
26
|
+
super(name)
|
|
27
|
+
@config['options'].each do |option|
|
|
28
|
+
case option[0].upcase
|
|
29
|
+
when 'CYCLE_TIME' # Maximum time between log files
|
|
30
|
+
@cycle_time = option[1].to_i
|
|
31
|
+
when 'CYCLE_SIZE' # Maximum size of a log file
|
|
32
|
+
@cycle_size = option[1].to_i
|
|
33
|
+
else
|
|
34
|
+
Logger.error("Unknown option passed to microservice #{@name}: #{option}")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# These settings limit the log file to 10 minutes or 50MB of data, whichever comes first
|
|
39
|
+
@cycle_time = 600 unless @cycle_time # 10 minutes
|
|
40
|
+
@cycle_size = 50_000_000 unless @cycle_size # ~50 MB
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def run
|
|
44
|
+
tlws = setup_tlws
|
|
45
|
+
while true
|
|
46
|
+
break if @cancel_thread
|
|
47
|
+
|
|
48
|
+
Topic.read_topics(@topics) do |topic, msg_id, msg_hash, redis|
|
|
49
|
+
break if @cancel_thread
|
|
50
|
+
|
|
51
|
+
log_data(tlws, topic, msg_id, msg_hash, redis)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def setup_tlws
|
|
57
|
+
tlws = {}
|
|
58
|
+
@topics.each do |topic|
|
|
59
|
+
topic_split = topic.gsub(/{|}/, '').split("__") # Remove the redis hashtag curly braces
|
|
60
|
+
scope = topic_split[0]
|
|
61
|
+
log_name = topic_split[1]
|
|
62
|
+
remote_log_directory = "#{scope}/text_logs/#{log_name}"
|
|
63
|
+
tlws[topic] = TextLogWriter.new(remote_log_directory, true, @cycle_time, @cycle_size, redis_topic: topic)
|
|
64
|
+
end
|
|
65
|
+
return tlws
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def log_data(tlws, topic, msg_id, msg_hash, redis)
|
|
69
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
70
|
+
keys = msg_hash.keys
|
|
71
|
+
keys.delete("time")
|
|
72
|
+
entry = keys.reduce("") { |data, key| data + "#{key}: #{msg_hash[key]}\t" }
|
|
73
|
+
tlws[topic].write(msg_hash["time"].to_i, entry, msg_id)
|
|
74
|
+
@count += 1
|
|
75
|
+
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
76
|
+
@metric.add_sample(name: "log_duration_seconds", value: diff, labels: {})
|
|
77
|
+
rescue => err
|
|
78
|
+
@error = err
|
|
79
|
+
Logger.error("#{@name} error: #{err.formatted}")
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
OpenC3::TextLogMicroservice.run if __FILE__ == $0
|