openc3 6.10.4 → 7.0.0.pre.rc2
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 +4 -4
- data/Gemfile +2 -1
- data/Guardfile +4 -9
- data/LICENSE.md +85 -0
- data/README.md +8 -8
- data/Rakefile +3 -9
- data/bin/cstol_converter +3 -8
- data/bin/openc3cli +64 -35
- data/data/config/command_modifiers.yaml +18 -1
- data/data/config/interface_modifiers.yaml +0 -2
- data/data/config/plugins.yaml +14 -18
- data/data/config/screen.yaml +1 -1
- data/data/config/target.yaml +26 -79
- data/data/config/telemetry_modifiers.yaml +15 -0
- data/data/config/widgets.yaml +32 -32
- data/ext/openc3/ext/array/array.c +4 -9
- data/ext/openc3/ext/buffered_file/buffered_file.c +4 -9
- data/ext/openc3/ext/burst_protocol/burst_protocol.c +3 -8
- data/ext/openc3/ext/config_parser/config_parser.c +2 -7
- data/ext/openc3/ext/crc/crc.c +3 -8
- data/ext/openc3/ext/openc3_io/openc3_io.c +4 -9
- data/ext/openc3/ext/packet/packet.c +7 -9
- data/ext/openc3/ext/platform/platform.c +3 -8
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +16 -12
- data/ext/openc3/ext/string/string.c +4 -9
- data/ext/openc3/ext/structure/structure.c +5 -9
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +4 -9
- data/ext/openc3/ext/telemetry/telemetry.c +8 -12
- data/lib/cosmos.rb +4 -9
- data/lib/cosmosc2.rb +4 -9
- data/lib/openc3/accessors/accessor.rb +10 -13
- data/lib/openc3/accessors/binary_accessor.rb +18 -17
- data/lib/openc3/accessors/cbor_accessor.rb +3 -8
- data/lib/openc3/accessors/form_accessor.rb +4 -9
- data/lib/openc3/accessors/html_accessor.rb +3 -8
- data/lib/openc3/accessors/http_accessor.rb +4 -9
- data/lib/openc3/accessors/json_accessor.rb +4 -9
- data/lib/openc3/accessors/template_accessor.rb +4 -9
- data/lib/openc3/accessors/xml_accessor.rb +4 -9
- data/lib/openc3/accessors.rb +3 -8
- data/lib/openc3/api/README.md +1 -1
- data/lib/openc3/api/api.rb +3 -8
- data/lib/openc3/api/authorized_api.rb +4 -9
- data/lib/openc3/api/cmd_api.rb +3 -8
- data/lib/openc3/api/config_api.rb +3 -8
- data/lib/openc3/api/interface_api.rb +4 -9
- data/lib/openc3/api/limits_api.rb +3 -8
- data/lib/openc3/api/metrics_api.rb +2 -19
- data/lib/openc3/api/offline_access_api.rb +2 -7
- data/lib/openc3/api/router_api.rb +5 -10
- data/lib/openc3/api/settings_api.rb +3 -8
- data/lib/openc3/api/stash_api.rb +2 -7
- data/lib/openc3/api/target_api.rb +3 -8
- data/lib/openc3/api/tlm_api.rb +15 -38
- data/lib/openc3/bridge/bridge.rb +3 -8
- data/lib/openc3/bridge/bridge_config.rb +5 -10
- data/lib/openc3/bridge/bridge_interface_thread.rb +4 -9
- data/lib/openc3/bridge/bridge_router_thread.rb +4 -9
- data/lib/openc3/ccsds/ccsds_packet.rb +4 -9
- data/lib/openc3/ccsds/ccsds_parser.rb +3 -8
- data/lib/openc3/config/config_parser.rb +3 -8
- data/lib/openc3/config/meta_config_parser.rb +3 -8
- data/lib/openc3/conversions/bit_reverse_conversion.rb +3 -8
- data/lib/openc3/conversions/conversion.rb +3 -8
- data/lib/openc3/conversions/generic_conversion.rb +3 -8
- data/lib/openc3/conversions/ip_read_conversion.rb +3 -8
- data/lib/openc3/conversions/ip_write_conversion.rb +3 -8
- data/lib/openc3/conversions/object_read_conversion.rb +3 -8
- data/lib/openc3/conversions/object_write_conversion.rb +3 -8
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +4 -9
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +4 -9
- data/lib/openc3/conversions/polynomial_conversion.rb +6 -8
- data/lib/openc3/conversions/processor_conversion.rb +3 -8
- data/lib/openc3/conversions/received_count_conversion.rb +4 -9
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +4 -9
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +4 -9
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +6 -8
- data/lib/openc3/conversions/unix_time_conversion.rb +3 -8
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +3 -8
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +3 -8
- data/lib/openc3/conversions.rb +3 -8
- data/lib/openc3/core_ext/array.rb +3 -8
- data/lib/openc3/core_ext/binding.rb +4 -9
- data/lib/openc3/core_ext/class.rb +4 -9
- data/lib/openc3/core_ext/exception.rb +3 -8
- data/lib/openc3/core_ext/file.rb +4 -9
- data/lib/openc3/core_ext/io.rb +4 -9
- data/lib/openc3/core_ext/kernel.rb +3 -8
- data/lib/openc3/core_ext/math.rb +4 -9
- data/lib/openc3/core_ext/matrix.rb +4 -9
- data/lib/openc3/core_ext/objectspace.rb +4 -9
- data/lib/openc3/core_ext/openc3_io.rb +4 -9
- data/lib/openc3/core_ext/range.rb +4 -9
- data/lib/openc3/core_ext/socket.rb +4 -9
- data/lib/openc3/core_ext/string.rb +3 -8
- data/lib/openc3/core_ext/stringio.rb +4 -9
- data/lib/openc3/core_ext/tempfile.rb +4 -9
- data/lib/openc3/core_ext/time.rb +3 -8
- data/lib/openc3/core_ext.rb +3 -8
- data/lib/openc3/interfaces/file_interface.rb +3 -8
- data/lib/openc3/interfaces/http_client_interface.rb +3 -8
- data/lib/openc3/interfaces/http_server_interface.rb +3 -8
- data/lib/openc3/interfaces/interface.rb +3 -8
- data/lib/openc3/interfaces/mqtt_interface.rb +3 -8
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +3 -8
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/cobs_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/length_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/slip_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/template_protocol.rb +3 -8
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +3 -8
- data/lib/openc3/interfaces/serial_interface.rb +3 -8
- data/lib/openc3/interfaces/simulated_target_interface.rb +3 -8
- data/lib/openc3/interfaces/stream_interface.rb +3 -8
- data/lib/openc3/interfaces/tcpip_client_interface.rb +3 -8
- data/lib/openc3/interfaces/tcpip_server_interface.rb +3 -8
- data/lib/openc3/interfaces/udp_interface.rb +3 -8
- data/lib/openc3/interfaces.rb +3 -8
- data/lib/openc3/io/buffered_file.rb +4 -9
- data/lib/openc3/io/io_multiplexer.rb +4 -9
- data/lib/openc3/io/json_api.rb +3 -8
- data/lib/openc3/io/json_api_object.rb +4 -9
- data/lib/openc3/io/json_drb.rb +3 -8
- data/lib/openc3/io/json_drb_object.rb +4 -9
- data/lib/openc3/io/json_drb_rack.rb +4 -9
- data/lib/openc3/io/json_rpc.rb +3 -8
- data/lib/openc3/io/posix_serial_driver.rb +3 -8
- data/lib/openc3/io/serial_driver.rb +3 -8
- data/lib/openc3/io/stderr.rb +4 -9
- data/lib/openc3/io/stdout.rb +4 -9
- data/lib/openc3/io/udp_sockets.rb +3 -8
- data/lib/openc3/io/win32_serial_driver.rb +4 -9
- data/lib/openc3/logs/buffered_packet_log_reader.rb +3 -8
- data/lib/openc3/logs/buffered_packet_log_writer.rb +3 -8
- data/lib/openc3/logs/log_writer.rb +3 -8
- data/lib/openc3/logs/packet_log_constants.rb +3 -8
- data/lib/openc3/logs/packet_log_reader.rb +3 -8
- data/lib/openc3/logs/packet_log_writer.rb +3 -8
- data/lib/openc3/logs/stream_log.rb +3 -8
- data/lib/openc3/logs/stream_log_pair.rb +3 -8
- data/lib/openc3/logs/text_log_writer.rb +3 -8
- data/lib/openc3/logs.rb +3 -8
- data/lib/openc3/microservices/cleanup_microservice.rb +4 -14
- data/lib/openc3/microservices/decom_microservice.rb +3 -8
- data/lib/openc3/microservices/interface_decom_common.rb +3 -8
- data/lib/openc3/microservices/interface_microservice.rb +5 -9
- data/lib/openc3/microservices/log_microservice.rb +3 -8
- data/lib/openc3/microservices/microservice.rb +24 -12
- data/lib/openc3/microservices/multi_microservice.rb +2 -7
- data/lib/openc3/microservices/periodic_microservice.rb +3 -8
- data/lib/openc3/microservices/plugin_microservice.rb +3 -8
- data/lib/openc3/microservices/queue_microservice.rb +3 -8
- data/lib/openc3/microservices/router_microservice.rb +3 -8
- data/lib/openc3/microservices/scope_cleanup_microservice.rb +3 -8
- data/lib/openc3/microservices/text_log_microservice.rb +3 -8
- data/lib/openc3/migrations/20251213120000_reinstall_plugins.rb +45 -0
- data/lib/openc3/migrations/20260204000000_remove_decom_reducer.rb +60 -0
- data/lib/openc3/models/activity_model.rb +4 -8
- data/lib/openc3/models/auth_model.rb +57 -38
- data/lib/openc3/models/cvt_model.rb +203 -62
- data/lib/openc3/models/environment_model.rb +4 -9
- data/lib/openc3/models/gem_model.rb +3 -8
- data/lib/openc3/models/info_model.rb +4 -9
- data/lib/openc3/models/interface_model.rb +6 -10
- data/lib/openc3/models/interface_status_model.rb +4 -9
- data/lib/openc3/models/metadata_model.rb +3 -8
- data/lib/openc3/models/metric_model.rb +3 -8
- data/lib/openc3/models/microservice_model.rb +24 -10
- data/lib/openc3/models/microservice_status_model.rb +3 -8
- data/lib/openc3/models/migration_model.rb +3 -8
- data/lib/openc3/models/model.rb +3 -8
- data/lib/openc3/models/news_model.rb +3 -8
- data/lib/openc3/models/note_model.rb +3 -8
- data/lib/openc3/models/offline_access_model.rb +3 -8
- data/lib/openc3/models/ping_model.rb +4 -9
- data/lib/openc3/models/plugin_model.rb +14 -9
- data/lib/openc3/models/plugin_store_model.rb +21 -17
- data/lib/openc3/models/process_status_model.rb +4 -9
- data/lib/openc3/models/python_package_model.rb +3 -8
- data/lib/openc3/models/queue_model.rb +3 -8
- data/lib/openc3/models/reaction_model.rb +9 -10
- data/lib/openc3/models/router_model.rb +4 -9
- data/lib/openc3/models/router_status_model.rb +4 -9
- data/lib/openc3/models/scope_model.rb +4 -9
- data/lib/openc3/models/script_engine_model.rb +3 -8
- data/lib/openc3/models/script_status_model.rb +3 -8
- data/lib/openc3/models/secret_model.rb +3 -8
- data/lib/openc3/models/setting_model.rb +3 -8
- data/lib/openc3/models/sorted_model.rb +3 -8
- data/lib/openc3/models/stash_model.rb +3 -8
- data/lib/openc3/models/target_model.rb +99 -229
- data/lib/openc3/models/timeline_model.rb +3 -8
- data/lib/openc3/models/tool_config_model.rb +3 -8
- data/lib/openc3/models/tool_model.rb +10 -10
- data/lib/openc3/models/trigger_group_model.rb +3 -8
- data/lib/openc3/models/trigger_model.rb +3 -8
- data/lib/openc3/models/widget_model.rb +3 -8
- data/lib/openc3/operators/microservice_operator.rb +7 -8
- data/lib/openc3/operators/operator.rb +3 -8
- data/lib/openc3/packets/command_validator.rb +3 -8
- data/lib/openc3/packets/commands.rb +32 -14
- data/lib/openc3/packets/json_packet.rb +7 -19
- data/lib/openc3/packets/limits.rb +3 -8
- data/lib/openc3/packets/limits_response.rb +3 -8
- data/lib/openc3/packets/packet.rb +38 -32
- data/lib/openc3/packets/packet_config.rb +23 -13
- data/lib/openc3/packets/packet_item.rb +3 -8
- data/lib/openc3/packets/packet_item_limits.rb +3 -8
- data/lib/openc3/packets/parsers/format_string_parser.rb +3 -8
- data/lib/openc3/packets/parsers/limits_parser.rb +3 -8
- data/lib/openc3/packets/parsers/limits_response_parser.rb +3 -8
- data/lib/openc3/packets/parsers/packet_item_parser.rb +7 -8
- data/lib/openc3/packets/parsers/packet_parser.rb +3 -8
- data/lib/openc3/packets/parsers/processor_parser.rb +3 -8
- data/lib/openc3/packets/parsers/state_parser.rb +3 -8
- data/lib/openc3/packets/parsers/xtce_converter.rb +12 -9
- data/lib/openc3/packets/parsers/xtce_parser.rb +3 -8
- data/lib/openc3/packets/structure.rb +14 -11
- data/lib/openc3/packets/structure_item.rb +4 -9
- data/lib/openc3/packets/telemetry.rb +7 -11
- data/lib/openc3/processors/processor.rb +5 -10
- data/lib/openc3/processors/statistics_processor.rb +4 -9
- data/lib/openc3/processors/watermark_processor.rb +4 -9
- data/lib/openc3/processors.rb +4 -9
- data/lib/openc3/script/api_shared.rb +8 -37
- data/lib/openc3/script/autonomic.rb +3 -8
- data/lib/openc3/script/calendar.rb +3 -8
- data/lib/openc3/script/commands.rb +3 -8
- data/lib/openc3/script/critical_cmd.rb +3 -8
- data/lib/openc3/script/exceptions.rb +4 -9
- data/lib/openc3/script/extract.rb +3 -8
- data/lib/openc3/script/limits.rb +3 -8
- data/lib/openc3/script/metadata.rb +3 -8
- data/lib/openc3/script/packages.rb +3 -8
- data/lib/openc3/script/plugins.rb +3 -8
- data/lib/openc3/script/queue.rb +3 -8
- data/lib/openc3/script/screen.rb +7 -8
- data/lib/openc3/script/script.rb +3 -8
- data/lib/openc3/script/script_runner.rb +3 -8
- data/lib/openc3/script/storage.rb +6 -10
- data/lib/openc3/script/suite.rb +3 -8
- data/lib/openc3/script/suite_results.rb +3 -8
- data/lib/openc3/script/suite_runner.rb +3 -8
- data/lib/openc3/script/tables.rb +3 -8
- data/lib/openc3/script/telemetry.rb +3 -8
- data/lib/openc3/script/web_socket_api.rb +8 -13
- data/lib/openc3/script.rb +4 -9
- data/lib/openc3/script_engines/script_engine.rb +3 -8
- data/lib/openc3/streams/mqtt_stream.rb +3 -8
- data/lib/openc3/streams/serial_stream.rb +3 -8
- data/lib/openc3/streams/stream.rb +3 -8
- data/lib/openc3/streams/tcpip_client_stream.rb +3 -8
- data/lib/openc3/streams/tcpip_socket_stream.rb +3 -8
- data/lib/openc3/streams/web_socket_client_stream.rb +3 -8
- data/lib/openc3/system/system.rb +3 -8
- data/lib/openc3/system/target.rb +3 -8
- data/lib/openc3/system.rb +3 -8
- data/lib/openc3/tools/cmd_tlm_server/api.rb +4 -9
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +3 -8
- data/lib/openc3/tools/table_manager/table.rb +3 -8
- data/lib/openc3/tools/table_manager/table_config.rb +3 -8
- data/lib/openc3/tools/table_manager/table_item.rb +4 -9
- data/lib/openc3/tools/table_manager/table_item_parser.rb +3 -8
- data/lib/openc3/tools/table_manager/table_manager_core.rb +3 -8
- data/lib/openc3/tools/table_manager/table_parser.rb +3 -8
- data/lib/openc3/tools/test_runner/test.rb +4 -9
- data/lib/openc3/top_level.rb +3 -8
- data/lib/openc3/topics/autonomic_topic.rb +4 -9
- data/lib/openc3/topics/calendar_topic.rb +4 -9
- data/lib/openc3/topics/command_decom_topic.rb +14 -17
- data/lib/openc3/topics/command_topic.rb +14 -10
- data/lib/openc3/topics/config_topic.rb +3 -8
- data/lib/openc3/topics/decom_interface_topic.rb +3 -8
- data/lib/openc3/topics/interface_topic.rb +3 -8
- data/lib/openc3/topics/limits_event_topic.rb +3 -8
- data/lib/openc3/topics/notebook_topic.rb +32 -0
- data/lib/openc3/topics/queue_topic.rb +3 -8
- data/lib/openc3/topics/router_topic.rb +3 -8
- data/lib/openc3/topics/system_events_topic.rb +3 -8
- data/lib/openc3/topics/telemetry_decom_topic.rb +12 -12
- data/lib/openc3/topics/telemetry_topic.rb +3 -8
- data/lib/openc3/topics/timeline_topic.rb +4 -9
- data/lib/openc3/topics/topic.rb +3 -8
- data/lib/openc3/utilities/authentication.rb +29 -10
- data/lib/openc3/utilities/authorization.rb +4 -9
- data/lib/openc3/utilities/aws_bucket.rb +126 -16
- data/lib/openc3/utilities/bucket.rb +9 -9
- data/lib/openc3/utilities/bucket_file_cache.rb +3 -13
- data/lib/openc3/utilities/bucket_require.rb +3 -8
- data/lib/openc3/utilities/bucket_utilities.rb +3 -10
- data/lib/openc3/utilities/cli_generator.rb +11 -16
- data/lib/openc3/utilities/cmd_log.rb +3 -8
- data/lib/openc3/utilities/crc.rb +3 -8
- data/lib/openc3/utilities/csv.rb +4 -9
- data/lib/openc3/utilities/local_bucket.rb +5 -10
- data/lib/openc3/utilities/local_mode.rb +14 -18
- data/lib/openc3/utilities/logger.rb +3 -8
- data/lib/openc3/utilities/message_log.rb +3 -8
- data/lib/openc3/utilities/metric.rb +3 -8
- data/lib/openc3/utilities/migration.rb +3 -8
- data/lib/openc3/utilities/open_telemetry.rb +3 -8
- data/lib/openc3/utilities/process_manager.rb +3 -8
- data/lib/openc3/utilities/python_proxy.rb +3 -8
- data/lib/openc3/utilities/quaternion.rb +3 -8
- data/lib/openc3/utilities/questdb_client.rb +210 -0
- data/lib/openc3/utilities/redis_secrets.rb +3 -8
- data/lib/openc3/utilities/ruby_lex_utils.rb +3 -8
- data/lib/openc3/utilities/running_script.rb +13 -11
- data/lib/openc3/utilities/s3_autoload.rb +9 -2
- data/lib/openc3/utilities/secrets.rb +8 -9
- data/lib/openc3/utilities/simulated_target.rb +4 -9
- data/lib/openc3/utilities/sleeper.rb +3 -8
- data/lib/openc3/utilities/store.rb +4 -9
- data/lib/openc3/utilities/store_autoload.rb +7 -14
- data/lib/openc3/utilities/store_queued.rb +6 -9
- data/lib/openc3/utilities/target_file.rb +3 -8
- data/lib/openc3/utilities/thread_manager.rb +3 -8
- data/lib/openc3/utilities/throttle.rb +3 -8
- data/lib/openc3/utilities/zip.rb +4 -9
- data/lib/openc3/utilities.rb +4 -9
- data/lib/openc3/version.rb +8 -8
- data/lib/openc3/win32/excel.rb +4 -9
- data/lib/openc3/win32/win32.rb +4 -9
- data/lib/openc3/win32/win32_main.rb +3 -8
- data/lib/openc3.rb +3 -12
- data/tasks/gemfile_stats.rake +4 -9
- data/tasks/spec.rake +4 -9
- data/templates/plugin/README.md +2 -2
- data/templates/plugin/plugin.gemspec +1 -1
- data/templates/tool_angular/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/tool_vue/vite.config.js +2 -1
- data/templates/widget/package.json +3 -3
- data/templates/widget/vite.config.js +1 -1
- metadata +49 -26
- data/LICENSE.txt +0 -729
- data/bin/rubysloc +0 -142
- data/ext/openc3/ext/reducer_microservice/extconf.rb +0 -13
- data/ext/openc3/ext/reducer_microservice/reducer_microservice.c +0 -165
- data/lib/openc3/microservices/reducer_microservice.rb +0 -640
- data/lib/openc3/models/reducer_model.rb +0 -72
- data/lib/openc3/topics/telemetry_reduced_topics.rb +0 -80
- /data/templates/plugin/{LICENSE.txt → LICENSE.md} +0 -0
- /data/templates/widget/{LICENSE.txt → LICENSE.md} +0 -0
|
@@ -3,100 +3,119 @@
|
|
|
3
3
|
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
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
6
|
# This program is distributed in the hope that it will be useful,
|
|
12
7
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
#
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
15
10
|
|
|
16
11
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
12
|
+
# All changes Copyright 2026, OpenC3, Inc.
|
|
18
13
|
# All Rights Reserved
|
|
19
14
|
#
|
|
20
15
|
# This file may also be used under the terms of a commercial license
|
|
21
16
|
# if purchased from OpenC3, Inc.
|
|
22
17
|
|
|
23
|
-
require '
|
|
18
|
+
require 'argon2'
|
|
24
19
|
require 'securerandom'
|
|
25
20
|
require 'openc3/utilities/store'
|
|
26
21
|
|
|
27
22
|
module OpenC3
|
|
28
23
|
class AuthModel
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
ARGON2_PROFILE = ENV["OPENC3_ARGON2_PROFILE"]&.to_sym || :rfc_9106_low_memory
|
|
25
|
+
|
|
26
|
+
# Redis keys
|
|
27
|
+
PRIMARY_KEY = 'OPENC3__TOKEN' # for argon2 password hash
|
|
28
|
+
SESSIONS_KEY = 'OPENC3__SESSIONS' # for hash containing session tokens
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
# The length of time in minutes to keep redis values in memory
|
|
31
|
+
PW_HASH_CACHE_TIMEOUT = 5
|
|
33
32
|
SESSION_CACHE_TIMEOUT = 5
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
|
|
34
|
+
# Cached argon2 password hash
|
|
35
|
+
@@pw_hash_cache = nil
|
|
36
|
+
@@pw_hash_cache_time = nil
|
|
37
|
+
|
|
38
|
+
# Cached session tokens
|
|
36
39
|
@@session_cache = nil
|
|
37
40
|
@@session_cache_time = nil
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
MIN_PASSWORD_LENGTH = 8
|
|
40
43
|
|
|
41
44
|
def self.set?(key = PRIMARY_KEY)
|
|
42
45
|
Store.exists(key) == 1
|
|
43
46
|
end
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
# Checks whether the provided token is a valid user password, service password, or session token.
|
|
49
|
+
# @param token [String] the plaintext password or session token to check (required)
|
|
50
|
+
# @param no_password [Boolean] enforces use of a session token or service password (default: true)
|
|
51
|
+
# @param service_only [Boolean] enforces use of a service password (default: false)
|
|
52
|
+
# @return [Boolean] whether the provided password/token is valid
|
|
53
|
+
def self.verify(token, no_password: true, service_only: false)
|
|
46
54
|
# Handle a service password - Generally only used by ScriptRunner
|
|
47
55
|
# TODO: Replace this with temporary service tokens
|
|
48
56
|
service_password = ENV['OPENC3_SERVICE_PASSWORD']
|
|
49
57
|
return true if service_password and service_password == token
|
|
50
58
|
|
|
51
|
-
return
|
|
59
|
+
return false if service_only
|
|
60
|
+
|
|
61
|
+
return verify_no_service(token, no_password: no_password)
|
|
52
62
|
end
|
|
53
63
|
|
|
54
|
-
|
|
64
|
+
# Checks whether the provided token is a valid user password or session token.
|
|
65
|
+
# @param token [String] the plaintext password or session token to check (required)
|
|
66
|
+
# @param no_password [Boolean] enforces use of a session token (default: true)
|
|
67
|
+
# @return [Boolean] whether the provided password/token is valid
|
|
68
|
+
def self.verify_no_service(token, no_password: true)
|
|
55
69
|
return false if token.nil? or token.empty?
|
|
56
70
|
|
|
71
|
+
# Check cached session tokens and password hash
|
|
57
72
|
time = Time.now
|
|
58
73
|
return true if @@session_cache and (time - @@session_cache_time) < SESSION_CACHE_TIMEOUT and @@session_cache[token]
|
|
59
|
-
|
|
60
|
-
|
|
74
|
+
unless no_password
|
|
75
|
+
return true if @@pw_hash_cache and (time - @@pw_hash_cache_time) < PW_HASH_CACHE_TIMEOUT and Argon2::Password.verify_password(token, @@pw_hash_cache)
|
|
76
|
+
end
|
|
61
77
|
|
|
62
|
-
# Check
|
|
78
|
+
# Check stored session tokens
|
|
63
79
|
@@session_cache = Store.hgetall(SESSIONS_KEY)
|
|
64
80
|
@@session_cache_time = time
|
|
65
81
|
return true if @@session_cache[token]
|
|
66
82
|
|
|
67
|
-
|
|
68
|
-
@@token_cache = Store.get(PRIMARY_KEY)
|
|
69
|
-
@@token_cache_time = time
|
|
70
|
-
return true if @@token_cache == token_hash
|
|
83
|
+
return false if no_password
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
# Check stored password hash
|
|
86
|
+
pw_hash = Store.get(PRIMARY_KEY)
|
|
87
|
+
raise "invalid password hash" unless pw_hash.start_with?("$argon2") # Catch users who didn't run the migration utility when upgrading to COSMOS 7
|
|
88
|
+
@@pw_hash_cache = pw_hash
|
|
89
|
+
@@pw_hash_cache_time = time
|
|
90
|
+
return Argon2::Password.verify_password(token, @@pw_hash_cache)
|
|
73
91
|
end
|
|
74
92
|
|
|
75
|
-
def self.set(
|
|
76
|
-
raise "
|
|
77
|
-
raise "
|
|
93
|
+
def self.set(password, old_password, key = PRIMARY_KEY)
|
|
94
|
+
raise "password must not be nil or empty" if password.nil? or password.empty?
|
|
95
|
+
raise "password must be at least 8 characters" if password.length < MIN_PASSWORD_LENGTH
|
|
78
96
|
|
|
79
97
|
if set?(key)
|
|
80
|
-
raise "
|
|
81
|
-
raise "
|
|
98
|
+
raise "old_password must not be nil or empty" if old_password.nil? or old_password.empty?
|
|
99
|
+
raise "old_password incorrect" unless verify_no_service(old_password, no_password: false)
|
|
82
100
|
end
|
|
83
|
-
|
|
101
|
+
pw_hash = Argon2::Password.create(password, profile: ARGON2_PROFILE)
|
|
102
|
+
Store.set(key, pw_hash)
|
|
103
|
+
@@pw_hash_cache = nil
|
|
104
|
+
@@pw_hash_cache_time = nil
|
|
84
105
|
end
|
|
85
106
|
|
|
107
|
+
# Creates a new session token. DO NOT CALL BEFORE VERIFYING.
|
|
86
108
|
def self.generate_session
|
|
87
109
|
token = SecureRandom.urlsafe_base64(nil, false)
|
|
88
110
|
Store.hset(SESSIONS_KEY, token, Time.now.iso8601)
|
|
89
111
|
return token
|
|
90
112
|
end
|
|
91
113
|
|
|
114
|
+
# Terminates every session.
|
|
92
115
|
def self.logout
|
|
93
116
|
Store.del(SESSIONS_KEY)
|
|
94
|
-
@@
|
|
95
|
-
@@
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def self.hash(token)
|
|
99
|
-
Digest::SHA2.hexdigest token
|
|
117
|
+
@@session_cache = nil
|
|
118
|
+
@@session_cache_time = nil
|
|
100
119
|
end
|
|
101
120
|
end
|
|
102
121
|
end
|
|
@@ -3,27 +3,24 @@
|
|
|
3
3
|
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
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
6
|
# This program is distributed in the hope that it will be useful,
|
|
12
7
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
#
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
15
10
|
|
|
16
11
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
12
|
+
# All changes Copyright 2026, OpenC3, Inc.
|
|
18
13
|
# All Rights Reserved
|
|
19
14
|
#
|
|
20
15
|
# This file may also be used under the terms of a commercial license
|
|
21
16
|
# if purchased from OpenC3, Inc.
|
|
22
17
|
|
|
23
18
|
require 'pg'
|
|
19
|
+
require 'set'
|
|
24
20
|
require 'thread'
|
|
25
21
|
require 'openc3/utilities/store'
|
|
26
22
|
require 'openc3/utilities/store_queued'
|
|
23
|
+
require 'openc3/utilities/questdb_client'
|
|
27
24
|
require 'openc3/models/target_model'
|
|
28
25
|
|
|
29
26
|
module OpenC3
|
|
@@ -33,7 +30,7 @@ module OpenC3
|
|
|
33
30
|
@@conn = nil
|
|
34
31
|
@@conn_mutex = Mutex.new
|
|
35
32
|
|
|
36
|
-
VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED
|
|
33
|
+
VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED]
|
|
37
34
|
def self.build_json_from_packet(packet)
|
|
38
35
|
packet.decom
|
|
39
36
|
end
|
|
@@ -59,6 +56,20 @@ module OpenC3
|
|
|
59
56
|
end
|
|
60
57
|
end
|
|
61
58
|
|
|
59
|
+
# Set the current value table with pre-serialized JSON (avoids double as_json call)
|
|
60
|
+
# @param packet_json [String] Pre-serialized JSON string
|
|
61
|
+
# @param hash [Hash] The JSON-safe hash (already had as_json called)
|
|
62
|
+
def self.set_json(packet_json, hash, target_name:, packet_name:, queued: false, scope: $openc3_scope)
|
|
63
|
+
key = "#{scope}__tlm__#{target_name}"
|
|
64
|
+
tgt_pkt_key = key + "__#{packet_name}"
|
|
65
|
+
@@packet_cache[tgt_pkt_key] = [Time.now, hash]
|
|
66
|
+
if queued
|
|
67
|
+
StoreQueued.hset(key, packet_name, packet_json)
|
|
68
|
+
else
|
|
69
|
+
Store.hset(key, packet_name, packet_json)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
62
73
|
# Get the hash for packet in the CVT
|
|
63
74
|
# Note: Does not apply overrides
|
|
64
75
|
def self.get(target_name:, packet_name:, cache_timeout: nil, scope: $openc3_scope)
|
|
@@ -80,16 +91,13 @@ module OpenC3
|
|
|
80
91
|
def self.set_item(target_name, packet_name, item_name, value, type:, queued: false, scope: $openc3_scope)
|
|
81
92
|
hash = get(target_name: target_name, packet_name: packet_name, cache_timeout: nil, scope: scope)
|
|
82
93
|
case type
|
|
83
|
-
when :WITH_UNITS
|
|
84
|
-
hash["#{item_name}__U"] = value.to_s # WITH_UNITS should always be a string
|
|
85
|
-
when :FORMATTED
|
|
94
|
+
when :FORMATTED, :WITH_UNITS
|
|
86
95
|
hash["#{item_name}__F"] = value.to_s # FORMATTED should always be a string
|
|
87
96
|
when :CONVERTED
|
|
88
97
|
hash["#{item_name}__C"] = value
|
|
89
98
|
when :RAW
|
|
90
99
|
hash[item_name] = value
|
|
91
100
|
when :ALL
|
|
92
|
-
hash["#{item_name}__U"] = value.to_s # WITH_UNITS should always be a string
|
|
93
101
|
hash["#{item_name}__F"] = value.to_s # FORMATTED should always be a string
|
|
94
102
|
hash["#{item_name}__C"] = value
|
|
95
103
|
hash[item_name] = value
|
|
@@ -121,39 +129,135 @@ module OpenC3
|
|
|
121
129
|
end
|
|
122
130
|
end
|
|
123
131
|
|
|
124
|
-
def self.tsdb_lookup(items, start_time:, end_time: nil)
|
|
132
|
+
def self.tsdb_lookup(items, start_time:, end_time: nil, scope: $openc3_scope)
|
|
125
133
|
tables = {}
|
|
126
134
|
names = []
|
|
127
135
|
nil_count = 0
|
|
136
|
+
# Cache packet definitions to avoid repeated lookups
|
|
137
|
+
packet_cache = {}
|
|
138
|
+
# Map column names to item type info for decoding
|
|
139
|
+
item_types = {}
|
|
140
|
+
# Track calculated timestamp items: { position => { source:, format:, table_index: } }
|
|
141
|
+
calculated_items = {}
|
|
142
|
+
# Track which timestamp columns we need per table
|
|
143
|
+
needed_timestamps = {} # { table_index => Set of column names }
|
|
144
|
+
current_position = 0
|
|
145
|
+
|
|
146
|
+
# Stored timestamp items that need conversion from timestamp_ns to float seconds
|
|
147
|
+
stored_timestamp_items = Set.new(['PACKET_TIMESECONDS', 'RECEIVED_TIMESECONDS'])
|
|
148
|
+
# Track stored timestamp items: { position => { column:, table_index: } }
|
|
149
|
+
stored_timestamp_positions = {}
|
|
150
|
+
|
|
128
151
|
items.each do |item|
|
|
129
|
-
target_name, packet_name,
|
|
152
|
+
target_name, packet_name, orig_item_name, value_type, limits = item
|
|
130
153
|
# They will all be nil when item is a nil value
|
|
131
154
|
# A nil value indicates a value that does not exist as returned by get_tlm_available
|
|
132
|
-
if
|
|
133
|
-
# We know
|
|
134
|
-
names << "
|
|
155
|
+
if orig_item_name.nil?
|
|
156
|
+
# We know PACKET_TIMESECONDS always exists so we can use it to fill in the nil value
|
|
157
|
+
names << "PACKET_TIMESECONDS as __nil#{nil_count}"
|
|
135
158
|
nil_count += 1
|
|
159
|
+
current_position += 1
|
|
136
160
|
next
|
|
137
161
|
end
|
|
138
|
-
|
|
139
|
-
table_name = "#{target_name}__#{packet_name}".gsub(/[?,'"\/:\)\(\+\*\%~]/, '_')
|
|
162
|
+
table_name = QuestDBClient.sanitize_table_name(target_name, packet_name, scope: scope)
|
|
140
163
|
tables[table_name] = 1
|
|
141
164
|
index = tables.find_index {|k,v| k == table_name }
|
|
142
|
-
|
|
143
|
-
#
|
|
144
|
-
|
|
165
|
+
|
|
166
|
+
# Check if this is a stored timestamp item (PACKET_TIMESECONDS or RECEIVED_TIMESECONDS)
|
|
167
|
+
# These are stored as timestamp_ns columns and need conversion to float seconds on read
|
|
168
|
+
if stored_timestamp_items.include?(orig_item_name)
|
|
169
|
+
col_name = "T#{index}.#{orig_item_name}"
|
|
170
|
+
names << "\"#{col_name}\""
|
|
171
|
+
stored_timestamp_positions[current_position] = { column: col_name, table_index: index }
|
|
172
|
+
current_position += 1
|
|
173
|
+
next
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Check if this is a calculated timestamp item (PACKET_TIMEFORMATTED or RECEIVED_TIMEFORMATTED)
|
|
177
|
+
if QuestDBClient::TIMESTAMP_ITEMS.key?(orig_item_name)
|
|
178
|
+
ts_info = QuestDBClient::TIMESTAMP_ITEMS[orig_item_name]
|
|
179
|
+
calculated_items[current_position] = {
|
|
180
|
+
source: ts_info[:source],
|
|
181
|
+
format: ts_info[:format],
|
|
182
|
+
table_index: index
|
|
183
|
+
}
|
|
184
|
+
# Track that we need this timestamp column for this table
|
|
185
|
+
needed_timestamps[index] ||= Set.new
|
|
186
|
+
needed_timestamps[index] << ts_info[:source]
|
|
187
|
+
current_position += 1
|
|
188
|
+
next
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
safe_item_name = QuestDBClient.sanitize_column_name(orig_item_name)
|
|
192
|
+
|
|
193
|
+
# Look up item type info from packet definition
|
|
194
|
+
cache_key = [target_name, packet_name]
|
|
195
|
+
unless packet_cache.key?(cache_key)
|
|
196
|
+
begin
|
|
197
|
+
packet_cache[cache_key] = TargetModel.packet(target_name, packet_name, scope: scope)
|
|
198
|
+
rescue RuntimeError
|
|
199
|
+
packet_cache[cache_key] = nil
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
packet_def = packet_cache[cache_key]
|
|
204
|
+
item_def = nil
|
|
205
|
+
if packet_def
|
|
206
|
+
packet_def['items']&.each do |pkt_item|
|
|
207
|
+
if pkt_item['name'] == orig_item_name
|
|
208
|
+
item_def = pkt_item
|
|
209
|
+
break
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
145
214
|
case value_type
|
|
146
|
-
when 'WITH_UNITS'
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
215
|
+
when 'FORMATTED', 'WITH_UNITS'
|
|
216
|
+
col_name = "T#{index}.#{safe_item_name}__F"
|
|
217
|
+
names << "\"#{col_name}\""
|
|
218
|
+
# Formatted values are always strings, no special decoding needed
|
|
219
|
+
item_types[col_name] = { 'data_type' => 'STRING', 'array_size' => nil }
|
|
150
220
|
when 'CONVERTED'
|
|
151
|
-
|
|
221
|
+
col_name = "T#{index}.#{safe_item_name}__C"
|
|
222
|
+
names << "\"#{col_name}\""
|
|
223
|
+
# Converted values may have different types based on read_conversion
|
|
224
|
+
if item_def
|
|
225
|
+
rc = item_def['read_conversion']
|
|
226
|
+
if rc && rc['converted_type']
|
|
227
|
+
item_types[col_name] = { 'data_type' => rc['converted_type'], 'array_size' => item_def['array_size'] }
|
|
228
|
+
elsif item_def['states']
|
|
229
|
+
# State values are strings
|
|
230
|
+
item_types[col_name] = { 'data_type' => 'STRING', 'array_size' => nil }
|
|
231
|
+
else
|
|
232
|
+
item_types[col_name] = { 'data_type' => item_def['data_type'], 'array_size' => item_def['array_size'] }
|
|
233
|
+
end
|
|
234
|
+
else
|
|
235
|
+
item_types[col_name] = { 'data_type' => nil, 'array_size' => nil }
|
|
236
|
+
end
|
|
152
237
|
else
|
|
153
|
-
|
|
238
|
+
col_name = "T#{index}.#{safe_item_name}"
|
|
239
|
+
names << "\"#{col_name}\""
|
|
240
|
+
if item_def
|
|
241
|
+
item_types[col_name] = { 'data_type' => item_def['data_type'], 'array_size' => item_def['array_size'] }
|
|
242
|
+
else
|
|
243
|
+
item_types[col_name] = { 'data_type' => nil, 'array_size' => nil }
|
|
244
|
+
end
|
|
154
245
|
end
|
|
246
|
+
current_position += 1
|
|
155
247
|
if limits
|
|
156
|
-
names << "\"T#{index}.#{
|
|
248
|
+
names << "\"T#{index}.#{safe_item_name}__L\""
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Add needed timestamp columns to the SELECT
|
|
253
|
+
# Track which column alias maps to which timestamp source for result processing
|
|
254
|
+
# Note: We use underscores in the alias name to avoid needing quotes, which QuestDB includes in returned field names
|
|
255
|
+
timestamp_columns = {} # { "T0___ts_timestamp" => { table_index: 0, source: 'timestamp' } }
|
|
256
|
+
needed_timestamps.each do |table_index, ts_columns|
|
|
257
|
+
ts_columns.each do |ts_col|
|
|
258
|
+
alias_name = "T#{table_index}___ts_#{ts_col}"
|
|
259
|
+
names << "T#{table_index}.#{ts_col} as #{alias_name}"
|
|
260
|
+
timestamp_columns[alias_name] = { table_index: table_index, source: ts_col }
|
|
157
261
|
end
|
|
158
262
|
end
|
|
159
263
|
|
|
@@ -167,9 +271,9 @@ module OpenC3
|
|
|
167
271
|
end
|
|
168
272
|
end
|
|
169
273
|
if start_time && !end_time
|
|
170
|
-
query += "WHERE T0.
|
|
274
|
+
query += "WHERE T0.PACKET_TIMESECONDS < '#{start_time}' LIMIT -1"
|
|
171
275
|
elsif start_time && end_time
|
|
172
|
-
query += "WHERE T0.
|
|
276
|
+
query += "WHERE T0.PACKET_TIMESECONDS >= '#{start_time}' AND T0.PACKET_TIMESECONDS < '#{end_time}'"
|
|
173
277
|
end
|
|
174
278
|
|
|
175
279
|
retry_count = 0
|
|
@@ -195,20 +299,70 @@ module OpenC3
|
|
|
195
299
|
# Build up a results set that is an array of arrays
|
|
196
300
|
# Each nested array is a set of 2 items: [value, limits state]
|
|
197
301
|
# If the item does not have limits the limits state is nil
|
|
198
|
-
result.each_with_index do |tuples,
|
|
199
|
-
data[
|
|
302
|
+
result.each_with_index do |tuples, row_num|
|
|
303
|
+
data[row_num] ||= []
|
|
200
304
|
row_index = 0
|
|
305
|
+
# Store timestamp values for this row: { "T0.PACKET_TIMESECONDS" => Time, ... }
|
|
306
|
+
row_timestamps = {}
|
|
201
307
|
tuples.each do |tuple|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
data[
|
|
308
|
+
col_name = tuple[0]
|
|
309
|
+
col_value = tuple[1]
|
|
310
|
+
if col_name.include?("__L")
|
|
311
|
+
data[row_num][row_index - 1][1] = col_value
|
|
312
|
+
elsif col_name =~ /^__nil/
|
|
313
|
+
data[row_num][row_index] = [nil, nil]
|
|
314
|
+
row_index += 1
|
|
315
|
+
elsif col_name =~ /^T(\d+)___ts_(.+)$/
|
|
316
|
+
# This is a timestamp column for calculated items (TIMEFORMATTED)
|
|
317
|
+
table_idx = $1.to_i
|
|
318
|
+
ts_source = $2
|
|
319
|
+
row_timestamps["T#{table_idx}.#{ts_source}"] = col_value
|
|
320
|
+
elsif col_name.end_with?('.PACKET_TIMESECONDS', '.RECEIVED_TIMESECONDS') || col_name == 'PACKET_TIMESECONDS' || col_name == 'RECEIVED_TIMESECONDS'
|
|
321
|
+
# Stored timestamp column - convert from datetime to float seconds
|
|
322
|
+
ts_utc = QuestDBClient.pg_timestamp_to_utc(col_value)
|
|
323
|
+
seconds_value = QuestDBClient.format_timestamp(ts_utc, :seconds)
|
|
324
|
+
data[row_num][row_index] = [seconds_value, nil]
|
|
206
325
|
row_index += 1
|
|
326
|
+
# Also store for calculated items (TIMEFORMATTED) that may need this
|
|
327
|
+
# Normalize key to T{index}.{col} format for consistency
|
|
328
|
+
if col_name.include?('.')
|
|
329
|
+
row_timestamps[col_name] = col_value
|
|
330
|
+
else
|
|
331
|
+
row_timestamps["T0.#{col_name}"] = col_value
|
|
332
|
+
end
|
|
207
333
|
else
|
|
208
|
-
|
|
334
|
+
# Decode value using item type info
|
|
335
|
+
# QuestDB may return column names without table alias prefix
|
|
336
|
+
# Try both the raw column name and prefixed versions
|
|
337
|
+
type_info = item_types[col_name]
|
|
338
|
+
unless type_info
|
|
339
|
+
tables.length.times do |i|
|
|
340
|
+
prefixed_name = "T#{i}.#{col_name}"
|
|
341
|
+
type_info = item_types[prefixed_name]
|
|
342
|
+
break if type_info
|
|
343
|
+
end
|
|
344
|
+
type_info ||= {}
|
|
345
|
+
end
|
|
346
|
+
decoded_value = QuestDBClient.decode_value(
|
|
347
|
+
col_value,
|
|
348
|
+
data_type: type_info['data_type'],
|
|
349
|
+
array_size: type_info['array_size']
|
|
350
|
+
)
|
|
351
|
+
data[row_num][row_index] = [decoded_value, nil]
|
|
209
352
|
row_index += 1
|
|
210
353
|
end
|
|
211
354
|
end
|
|
355
|
+
|
|
356
|
+
# Insert calculated timestamp items at their positions
|
|
357
|
+
# Insert in ascending order so positions remain valid after each insert
|
|
358
|
+
calculated_items.keys.sort.each do |position|
|
|
359
|
+
calc_info = calculated_items[position]
|
|
360
|
+
ts_key = "T#{calc_info[:table_index]}.#{calc_info[:source]}"
|
|
361
|
+
ts_value = row_timestamps[ts_key]
|
|
362
|
+
ts_utc = QuestDBClient.pg_timestamp_to_utc(ts_value)
|
|
363
|
+
calculated_value = QuestDBClient.format_timestamp(ts_utc, calc_info[:format])
|
|
364
|
+
data[row_num].insert(position, [calculated_value, nil])
|
|
365
|
+
end
|
|
212
366
|
end
|
|
213
367
|
# If we only have one row then we return a single array
|
|
214
368
|
if result.ntuples == 1
|
|
@@ -222,10 +376,10 @@ module OpenC3
|
|
|
222
376
|
retry_count += 1
|
|
223
377
|
if retry_count > 4
|
|
224
378
|
# After the 5th retry just raise the error
|
|
225
|
-
raise "Error querying
|
|
379
|
+
raise "Error querying TSDB: #{e.message}"
|
|
226
380
|
end
|
|
227
|
-
Logger.warn("
|
|
228
|
-
Logger.warn("
|
|
381
|
+
Logger.warn("TSDB: Retrying due to error: #{e.message}")
|
|
382
|
+
Logger.warn("TSDB: Last query: #{query}") # Log the last query for debugging
|
|
229
383
|
@@conn_mutex.synchronize do
|
|
230
384
|
if @@conn and !@@conn.finished?
|
|
231
385
|
@@conn.finish()
|
|
@@ -252,7 +406,7 @@ module OpenC3
|
|
|
252
406
|
# If a start_time is passed we're doing a QuestDB lookup and directly return the results
|
|
253
407
|
# TODO: This currently does NOT support the override values
|
|
254
408
|
if start_time
|
|
255
|
-
return tsdb_lookup(items, start_time: start_time, end_time: end_time)
|
|
409
|
+
return tsdb_lookup(items, start_time: start_time, end_time: end_time, scope: scope)
|
|
256
410
|
end
|
|
257
411
|
|
|
258
412
|
# First generate a lookup hash of all the items represented so we can query the CVT
|
|
@@ -318,9 +472,7 @@ module OpenC3
|
|
|
318
472
|
item_name, value_type_key = key.split('__')
|
|
319
473
|
item['item_name'] = item_name
|
|
320
474
|
case value_type_key
|
|
321
|
-
when 'U'
|
|
322
|
-
item['value_type'] = 'WITH_UNITS'
|
|
323
|
-
when 'F'
|
|
475
|
+
when 'F', 'U'
|
|
324
476
|
item['value_type'] = 'FORMATTED'
|
|
325
477
|
when 'C'
|
|
326
478
|
item['value_type'] = 'CONVERTED'
|
|
@@ -346,15 +498,12 @@ module OpenC3
|
|
|
346
498
|
hash[item_name] = value
|
|
347
499
|
hash["#{item_name}__C"] = value
|
|
348
500
|
hash["#{item_name}__F"] = value.to_s
|
|
349
|
-
hash["#{item_name}__U"] = value.to_s
|
|
350
501
|
when :RAW
|
|
351
502
|
hash[item_name] = value
|
|
352
503
|
when :CONVERTED
|
|
353
504
|
hash["#{item_name}__C"] = value
|
|
354
|
-
when :FORMATTED
|
|
505
|
+
when :FORMATTED, :WITH_UNITS
|
|
355
506
|
hash["#{item_name}__F"] = value.to_s # Always a String
|
|
356
|
-
when :WITH_UNITS
|
|
357
|
-
hash["#{item_name}__U"] = value.to_s # Always a String
|
|
358
507
|
else
|
|
359
508
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
|
360
509
|
end
|
|
@@ -374,15 +523,12 @@ module OpenC3
|
|
|
374
523
|
hash.delete(item_name)
|
|
375
524
|
hash.delete("#{item_name}__C")
|
|
376
525
|
hash.delete("#{item_name}__F")
|
|
377
|
-
hash.delete("#{item_name}__U")
|
|
378
526
|
when :RAW
|
|
379
527
|
hash.delete(item_name)
|
|
380
528
|
when :CONVERTED
|
|
381
529
|
hash.delete("#{item_name}__C")
|
|
382
|
-
when :FORMATTED
|
|
530
|
+
when :FORMATTED, :WITH_UNITS
|
|
383
531
|
hash.delete("#{item_name}__F")
|
|
384
|
-
when :WITH_UNITS
|
|
385
|
-
hash.delete("#{item_name}__U")
|
|
386
532
|
else
|
|
387
533
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
|
388
534
|
end
|
|
@@ -424,10 +570,7 @@ module OpenC3
|
|
|
424
570
|
override_key = item_name
|
|
425
571
|
types = []
|
|
426
572
|
case type
|
|
427
|
-
when :WITH_UNITS
|
|
428
|
-
types = ["#{item_name}__U", "#{item_name}__F", "#{item_name}__C", item_name]
|
|
429
|
-
override_key = "#{item_name}__U"
|
|
430
|
-
when :FORMATTED
|
|
573
|
+
when :FORMATTED, :WITH_UNITS
|
|
431
574
|
types = ["#{item_name}__F", "#{item_name}__C", item_name]
|
|
432
575
|
override_key = "#{item_name}__F"
|
|
433
576
|
when :CONVERTED
|
|
@@ -477,16 +620,14 @@ module OpenC3
|
|
|
477
620
|
end
|
|
478
621
|
|
|
479
622
|
# We build lookup keys by including all the less formatted types to gracefully degrade lookups
|
|
480
|
-
# This allows the user to specify
|
|
623
|
+
# This allows the user to specify FORMATTED and if there is no conversions it will simply return the RAW value
|
|
481
624
|
case value_type.to_s
|
|
482
625
|
when 'RAW'
|
|
483
626
|
keys = [item_name]
|
|
484
627
|
when 'CONVERTED'
|
|
485
628
|
keys = ["#{item_name}__C", item_name]
|
|
486
|
-
when 'FORMATTED'
|
|
629
|
+
when 'FORMATTED', 'WITH_UNITS'
|
|
487
630
|
keys = ["#{item_name}__F", "#{item_name}__C", item_name]
|
|
488
|
-
when 'WITH_UNITS'
|
|
489
|
-
keys = ["#{item_name}__U", "#{item_name}__F", "#{item_name}__C", item_name]
|
|
490
631
|
else
|
|
491
632
|
raise "Unknown value type '#{value_type}'"
|
|
492
633
|
end
|
|
@@ -3,21 +3,16 @@
|
|
|
3
3
|
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
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
6
|
# This program is distributed in the hope that it will be useful,
|
|
12
7
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
#
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
15
10
|
|
|
16
11
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
12
|
+
# All changes Copyright 2026, OpenC3, Inc.
|
|
18
13
|
# All Rights Reserved
|
|
19
14
|
#
|
|
20
|
-
# This file may also be used under the terms of a commercial license
|
|
15
|
+
# This file may also be used under the terms of a commercial license
|
|
21
16
|
# if purchased from OpenC3, Inc.
|
|
22
17
|
|
|
23
18
|
require 'openc3/models/model'
|
|
@@ -3,18 +3,13 @@
|
|
|
3
3
|
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
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
6
|
# This program is distributed in the hope that it will be useful,
|
|
12
7
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
#
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
15
10
|
|
|
16
11
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
12
|
+
# All changes Copyright 2026, OpenC3, Inc.
|
|
18
13
|
# All Rights Reserved
|
|
19
14
|
#
|
|
20
15
|
# This file may also be used under the terms of a commercial license
|
|
@@ -3,21 +3,16 @@
|
|
|
3
3
|
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
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
6
|
# This program is distributed in the hope that it will be useful,
|
|
12
7
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
#
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
15
10
|
|
|
16
11
|
# Modified by OpenC3, Inc.
|
|
17
|
-
# All changes Copyright
|
|
12
|
+
# All changes Copyright 2026, OpenC3, Inc.
|
|
18
13
|
# All Rights Reserved
|
|
19
14
|
#
|
|
20
|
-
# This file may also be used under the terms of a commercial license
|
|
15
|
+
# This file may also be used under the terms of a commercial license
|
|
21
16
|
# if purchased from OpenC3, Inc.
|
|
22
17
|
|
|
23
18
|
require 'openc3/utilities/store'
|