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,154 @@
|
|
|
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/models/model'
|
|
21
|
+
require 'openc3/models/activity_model'
|
|
22
|
+
require 'openc3/models/microservice_model'
|
|
23
|
+
require 'openc3/topics/timeline_topic'
|
|
24
|
+
|
|
25
|
+
module OpenC3
|
|
26
|
+
class TimelineError < StandardError; end
|
|
27
|
+
|
|
28
|
+
class TimelineInputError < TimelineError; end
|
|
29
|
+
|
|
30
|
+
class TimelineModel < Model
|
|
31
|
+
PRIMARY_KEY = 'openc3_timelines'.freeze # MUST be equal to ActivityModel::PRIMARY_KEY without leading __
|
|
32
|
+
KEY = '__TIMELINE__'.freeze
|
|
33
|
+
|
|
34
|
+
# @return [TimelineModel] Return the object with the name at
|
|
35
|
+
def self.get(name:, scope:)
|
|
36
|
+
json = super(PRIMARY_KEY, name: "#{scope}#{KEY}#{name}")
|
|
37
|
+
unless json.nil?
|
|
38
|
+
self.from_json(json, name: name, scope: scope)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Array<Hash>] All the Key, Values stored under the name key
|
|
43
|
+
def self.all
|
|
44
|
+
super(PRIMARY_KEY)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [Array<String>] All the names stored under the name key
|
|
48
|
+
def self.names
|
|
49
|
+
super(PRIMARY_KEY)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Remove the sorted set.
|
|
53
|
+
def self.delete(name:, scope:, force: false)
|
|
54
|
+
key = "#{scope}__#{PRIMARY_KEY}__#{name}"
|
|
55
|
+
z = Store.zcard(key)
|
|
56
|
+
if force == false && z > 0
|
|
57
|
+
raise TimelineError.new "timeline contains activities, must force remove"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Store.multi do |multi|
|
|
61
|
+
multi.del(key)
|
|
62
|
+
multi.hdel(PRIMARY_KEY, "#{scope}#{KEY}#{name}")
|
|
63
|
+
end
|
|
64
|
+
return name
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @return [TimelineModel] Model generated from the passed JSON
|
|
68
|
+
def self.from_json(json, name:, scope:)
|
|
69
|
+
json = JSON.parse(json) if String === json
|
|
70
|
+
raise "json data is nil" if json.nil?
|
|
71
|
+
|
|
72
|
+
json.transform_keys!(&:to_sym)
|
|
73
|
+
self.new(**json, name: name, scope: scope)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def initialize(name:, scope:, updated_at: nil, color: nil)
|
|
77
|
+
if name.nil? || scope.nil?
|
|
78
|
+
raise TimelineInputError.new "name or scope must not be nil"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
super(PRIMARY_KEY, name: "#{scope}#{KEY}#{name}", scope: scope)
|
|
82
|
+
@updated_at = updated_at
|
|
83
|
+
@timeline_name = name
|
|
84
|
+
update_color(color: color)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def update_color(color: nil)
|
|
88
|
+
if color.nil?
|
|
89
|
+
color = '#%06x' % (rand * 0xffffff)
|
|
90
|
+
end
|
|
91
|
+
valid_color = color =~ /(#*)([0-9,a-f,A-f]{6})/
|
|
92
|
+
if valid_color.nil?
|
|
93
|
+
raise RuntimeError.new "invalid color but in hex format. #FF0000"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
unless color.start_with?('#')
|
|
97
|
+
color = "##{color}"
|
|
98
|
+
end
|
|
99
|
+
@color = color
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @return [Hash] generated from the TimelineModel
|
|
103
|
+
def as_json(*a)
|
|
104
|
+
{
|
|
105
|
+
'name' => @timeline_name,
|
|
106
|
+
'color' => @color,
|
|
107
|
+
'scope' => @scope,
|
|
108
|
+
'updated_at' => @updated_at
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @return [] update the redis stream / timeline topic that something has changed
|
|
113
|
+
def notify(kind:)
|
|
114
|
+
notification = {
|
|
115
|
+
'data' => JSON.generate(as_json(:allow_nan => true)),
|
|
116
|
+
'kind' => kind,
|
|
117
|
+
'type' => 'timeline',
|
|
118
|
+
'timeline' => @timeline_name
|
|
119
|
+
}
|
|
120
|
+
begin
|
|
121
|
+
TimelineTopic.write_activity(notification, scope: @scope)
|
|
122
|
+
rescue StandardError => e
|
|
123
|
+
raise TimelineInputError.new "Failed to write to stream: #{notification}, #{e}"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def deploy
|
|
128
|
+
topics = ["#{@scope}__#{PRIMARY_KEY}"]
|
|
129
|
+
TimelineTopic.initialize_streams(topics)
|
|
130
|
+
# Timeline Microservice
|
|
131
|
+
microservice = MicroserviceModel.new(
|
|
132
|
+
name: @name,
|
|
133
|
+
folder_name: nil,
|
|
134
|
+
cmd: ['ruby', 'timeline_microservice.rb', @name],
|
|
135
|
+
work_dir: '/openc3/lib/openc3/microservices',
|
|
136
|
+
options: [],
|
|
137
|
+
topics: topics,
|
|
138
|
+
target_names: [],
|
|
139
|
+
plugin: nil,
|
|
140
|
+
scope: @scope
|
|
141
|
+
)
|
|
142
|
+
microservice.create
|
|
143
|
+
notify(kind: 'created')
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def undeploy
|
|
147
|
+
model = MicroserviceModel.get_model(name: @name, scope: @scope)
|
|
148
|
+
if model
|
|
149
|
+
model.destroy
|
|
150
|
+
notify(kind: 'deleted')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
2
|
+
|
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
|
+
# All Rights Reserved.
|
|
5
|
+
#
|
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
|
7
|
+
# under the terms of the GNU Affero General Public License
|
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
|
10
|
+
#
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU Affero General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# Modified by OpenC3, Inc.
|
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
|
18
|
+
# All Rights Reserved
|
|
19
|
+
|
|
20
|
+
module OpenC3
|
|
21
|
+
class ToolConfigModel
|
|
22
|
+
def self.list_configs(tool, scope: $openc3_scope)
|
|
23
|
+
Store.hkeys("#{scope}__config__#{tool}")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.load_config(tool, name, scope: $openc3_scope)
|
|
27
|
+
Store.hget("#{scope}__config__#{tool}", name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.save_config(tool, name, data, scope: $openc3_scope)
|
|
31
|
+
Store.hset("#{scope}__config__#{tool}", name, data)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.delete_config(tool, name, scope: $openc3_scope)
|
|
35
|
+
Store.hdel("#{scope}__config__#{tool}", name)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,262 @@
|
|
|
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/models/model'
|
|
21
|
+
require 'openc3/models/scope_model'
|
|
22
|
+
require 'openc3/utilities/s3'
|
|
23
|
+
require 'rack'
|
|
24
|
+
|
|
25
|
+
module OpenC3
|
|
26
|
+
class ToolModel < Model
|
|
27
|
+
PRIMARY_KEY = 'openc3_tools'
|
|
28
|
+
|
|
29
|
+
attr_accessor :folder_name
|
|
30
|
+
attr_accessor :icon
|
|
31
|
+
attr_accessor :url
|
|
32
|
+
attr_accessor :inline_url
|
|
33
|
+
attr_accessor :window
|
|
34
|
+
attr_accessor :category
|
|
35
|
+
attr_accessor :shown
|
|
36
|
+
attr_accessor :position
|
|
37
|
+
attr_accessor :needs_dependencies
|
|
38
|
+
|
|
39
|
+
# NOTE: The following three class methods are used by the ModelController
|
|
40
|
+
# and are reimplemented to enable various Model class methods to work
|
|
41
|
+
def self.get(name:, scope: nil)
|
|
42
|
+
super("#{scope}__#{PRIMARY_KEY}", name: name)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.names(scope: nil)
|
|
46
|
+
array = []
|
|
47
|
+
all(scope: scope).each do |name, _tool|
|
|
48
|
+
array << name
|
|
49
|
+
end
|
|
50
|
+
array
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.all(scope: nil)
|
|
54
|
+
ordered_array = []
|
|
55
|
+
tools = unordered_all(scope: scope)
|
|
56
|
+
tools.each do |_name, tool|
|
|
57
|
+
ordered_array << tool
|
|
58
|
+
end
|
|
59
|
+
ordered_array.sort! { |a, b| a['position'] <=> b['position'] }
|
|
60
|
+
ordered_hash = {}
|
|
61
|
+
ordered_array.each do |tool|
|
|
62
|
+
ordered_hash[tool['name']] = tool
|
|
63
|
+
end
|
|
64
|
+
ordered_hash
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.all_scopes
|
|
68
|
+
result = {}
|
|
69
|
+
scopes = OpenC3::ScopeModel.all
|
|
70
|
+
scopes.each do |key, _scope|
|
|
71
|
+
tools = unordered_all(scope: key)
|
|
72
|
+
result.merge!(tools)
|
|
73
|
+
end
|
|
74
|
+
result
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Called by the PluginModel to allow this class to validate it's top-level keyword: "TOOL"
|
|
78
|
+
def self.handle_config(parser, keyword, parameters, plugin: nil, needs_dependencies: false, scope:)
|
|
79
|
+
case keyword
|
|
80
|
+
when 'TOOL'
|
|
81
|
+
parser.verify_num_parameters(2, 2, "TOOL <Folder Name> <Name>")
|
|
82
|
+
return self.new(folder_name: parameters[0], name: parameters[1], plugin: plugin, needs_dependencies: needs_dependencies, scope: scope)
|
|
83
|
+
else
|
|
84
|
+
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Tool: #{keyword} #{parameters.join(" ")}")
|
|
85
|
+
end
|
|
86
|
+
return nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# The ToolsTab.vue calls the ToolsController which uses this method to reorder the tools
|
|
90
|
+
# Position is index in the list starting with 0 = first
|
|
91
|
+
def self.set_position(name:, position:, scope:)
|
|
92
|
+
position = Integer(position)
|
|
93
|
+
next_position = position + 1
|
|
94
|
+
|
|
95
|
+
# Go through all the tools and reorder
|
|
96
|
+
all(scope: scope).each do |_tool_name, tool|
|
|
97
|
+
tool_model = from_json(tool, scope: scope)
|
|
98
|
+
# Update the requested model to the new position
|
|
99
|
+
if tool_model.name == name
|
|
100
|
+
tool_model.position = position
|
|
101
|
+
# Move existing tools down in the order
|
|
102
|
+
elsif position > 0 && position >= tool_model.position
|
|
103
|
+
tool_model.position -= 1
|
|
104
|
+
else # Move existing tools up in the order
|
|
105
|
+
tool_model.position = next_position
|
|
106
|
+
next_position += 1
|
|
107
|
+
end
|
|
108
|
+
tool_model.update
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def initialize(
|
|
113
|
+
name:,
|
|
114
|
+
folder_name: nil,
|
|
115
|
+
icon: '$astro-caution',
|
|
116
|
+
url: nil,
|
|
117
|
+
inline_url: nil,
|
|
118
|
+
window: 'INLINE',
|
|
119
|
+
category: nil,
|
|
120
|
+
shown: true,
|
|
121
|
+
position: nil,
|
|
122
|
+
updated_at: nil,
|
|
123
|
+
plugin: nil,
|
|
124
|
+
needs_dependencies: false,
|
|
125
|
+
scope:
|
|
126
|
+
)
|
|
127
|
+
super("#{scope}__#{PRIMARY_KEY}", name: name, plugin: plugin, updated_at: updated_at, scope: scope)
|
|
128
|
+
@folder_name = folder_name
|
|
129
|
+
@icon = icon
|
|
130
|
+
@url = url
|
|
131
|
+
@inline_url = inline_url
|
|
132
|
+
@window = window.to_s.upcase
|
|
133
|
+
@category = category
|
|
134
|
+
@shown = shown
|
|
135
|
+
@position = position
|
|
136
|
+
|
|
137
|
+
if @shown and @window == 'INLINE'
|
|
138
|
+
@inline_url = 'js/app.js' unless @inline_url
|
|
139
|
+
@url = "/tools/#{folder_name}" unless @url
|
|
140
|
+
end
|
|
141
|
+
@needs_dependencies = needs_dependencies
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def create(update: false, force: false)
|
|
145
|
+
unless @position
|
|
146
|
+
tools = self.class.all(scope: @scope)
|
|
147
|
+
_, tool = tools.max_by { |_tool_name, tool| tool['position'] }
|
|
148
|
+
if tool
|
|
149
|
+
@position = tool['position'] + 1
|
|
150
|
+
else
|
|
151
|
+
@position = 0
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
super(update: update, force: force)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def as_json(*a)
|
|
158
|
+
{
|
|
159
|
+
'name' => @name,
|
|
160
|
+
'folder_name' => @folder_name,
|
|
161
|
+
'icon' => @icon,
|
|
162
|
+
'url' => @url,
|
|
163
|
+
'inline_url' => @inline_url,
|
|
164
|
+
'window' => @window,
|
|
165
|
+
'category' => @category,
|
|
166
|
+
'shown' => @shown,
|
|
167
|
+
'position' => @position,
|
|
168
|
+
'updated_at' => @updated_at,
|
|
169
|
+
'plugin' => @plugin,
|
|
170
|
+
'needs_dependencies' => @needs_dependencies,
|
|
171
|
+
}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def as_config
|
|
175
|
+
result = "TOOL #{@folder_name ? @folder_name : 'nil'} \"#{@name}\"\n"
|
|
176
|
+
result << " URL #{@url}\n" if @url
|
|
177
|
+
result << " INLINE_URL #{@inline_url}\n" if @inline_url
|
|
178
|
+
result << " ICON #{@icon}\n" if @icon
|
|
179
|
+
result << " WINDOW #{@window}\n" unless @window == 'INLINE'
|
|
180
|
+
result << " CATEGORY #{@category}\n" if @category
|
|
181
|
+
result << " SHOWN false\n" unless @shown
|
|
182
|
+
result
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def handle_config(parser, keyword, parameters)
|
|
186
|
+
case keyword
|
|
187
|
+
when 'URL'
|
|
188
|
+
parser.verify_num_parameters(1, 1, "URL <URL>")
|
|
189
|
+
@url = parameters[0]
|
|
190
|
+
when 'INLINE_URL'
|
|
191
|
+
parser.verify_num_parameters(1, 1, "INLINE_URL <URL>")
|
|
192
|
+
@inline_url = parameters[0]
|
|
193
|
+
when 'ICON'
|
|
194
|
+
parser.verify_num_parameters(1, 1, "ICON <ICON Name>")
|
|
195
|
+
@icon = parameters[0]
|
|
196
|
+
when 'WINDOW'
|
|
197
|
+
parser.verify_num_parameters(1, 1, "WINDOW <INLINE | IFRAME | NEW>")
|
|
198
|
+
@window = parameters[0].to_s.upcase
|
|
199
|
+
raise ConfigParser::Error.new(parser, "Invalid WINDOW setting: #{@window}") unless ['INLINE', 'IFRAME', 'NEW'].include?(@window)
|
|
200
|
+
when 'CATEGORY'
|
|
201
|
+
parser.verify_num_parameters(1, 1, "CATEGORY <Category Name>")
|
|
202
|
+
@category = parameters[0].to_s
|
|
203
|
+
when 'SHOWN'
|
|
204
|
+
parser.verify_num_parameters(1, 1, "SHOWN <true/false>")
|
|
205
|
+
@shown = ConfigParser.handle_true_false(parameters[0])
|
|
206
|
+
else
|
|
207
|
+
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Tool: #{keyword} #{parameters.join(" ")}")
|
|
208
|
+
end
|
|
209
|
+
return nil
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def deploy(gem_path, variables, validate_only: false)
|
|
213
|
+
return unless @folder_name
|
|
214
|
+
|
|
215
|
+
# Ensure tools bucket exists
|
|
216
|
+
OpenC3::S3Utilities.ensure_public_bucket('tools') unless validate_only
|
|
217
|
+
|
|
218
|
+
variables["tool_name"] = @name
|
|
219
|
+
start_path = "/tools/#{@folder_name}/"
|
|
220
|
+
Dir.glob(gem_path + start_path + "**/*") do |filename|
|
|
221
|
+
next if filename == '.' or filename == '..' or File.directory?(filename)
|
|
222
|
+
|
|
223
|
+
key = filename.split(gem_path + '/tools/')[-1]
|
|
224
|
+
extension = filename.split('.')[-1]
|
|
225
|
+
content_type = Rack::Mime.mime_type(".#{extension}")
|
|
226
|
+
|
|
227
|
+
# Load tool files
|
|
228
|
+
data = File.read(filename, mode: "rb")
|
|
229
|
+
data = ERB.new(data, trim_mode: "-").result(binding.set_variables(variables)) if data.is_printable?
|
|
230
|
+
unless validate_only
|
|
231
|
+
cache_control = OpenC3::S3Utilities.get_cache_control(filename)
|
|
232
|
+
Aws::S3::Client.new.put_object(bucket: 'tools', content_type: content_type, cache_control: cache_control, key: key, body: data)
|
|
233
|
+
ConfigTopic.write({ kind: 'created', type: 'tool', name: @folder_name, plugin: @plugin }, scope: @scope)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def undeploy
|
|
239
|
+
if @folder_name and @folder_name.to_s.length > 0
|
|
240
|
+
rubys3_client = Aws::S3::Client.new
|
|
241
|
+
prefix = "#{@folder_name}/"
|
|
242
|
+
rubys3_client.list_objects(bucket: 'tools', prefix: prefix).contents.each do |object|
|
|
243
|
+
rubys3_client.delete_object(bucket: 'tools', key: object.key)
|
|
244
|
+
ConfigTopic.write({ kind: 'deleted', type: 'tool', name: @folder_name, plugin: @plugin }, scope: @scope)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
##################################################
|
|
250
|
+
# The following methods are implementation details
|
|
251
|
+
##################################################
|
|
252
|
+
|
|
253
|
+
# Returns the list of tools or the default OpenC3 tool set if no tools have been created
|
|
254
|
+
def self.unordered_all(scope: nil)
|
|
255
|
+
tools = Store.hgetall("#{scope}__#{PRIMARY_KEY}")
|
|
256
|
+
tools.each do |key, value|
|
|
257
|
+
tools[key] = JSON.parse(value, :allow_nan => true, :create_additions => true)
|
|
258
|
+
end
|
|
259
|
+
return tools
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
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/models/model'
|
|
21
|
+
require 'openc3/models/microservice_model'
|
|
22
|
+
require 'openc3/topics/autonomic_topic'
|
|
23
|
+
|
|
24
|
+
module OpenC3
|
|
25
|
+
class TriggerGroupError < StandardError; end
|
|
26
|
+
|
|
27
|
+
class TriggerGroupInputError < TriggerGroupError; end
|
|
28
|
+
|
|
29
|
+
# INPUT:
|
|
30
|
+
# {
|
|
31
|
+
# "name": "FOOBAR",
|
|
32
|
+
# "color": "#000000",
|
|
33
|
+
# }
|
|
34
|
+
class TriggerGroupModel < Model
|
|
35
|
+
PRIMARY_KEY = '__TRIGGER__GROUP'.freeze
|
|
36
|
+
|
|
37
|
+
# @return [GroupModel] Return the object with the name at
|
|
38
|
+
def self.get(name:, scope:)
|
|
39
|
+
json = super("#{scope}#{PRIMARY_KEY}", name: name)
|
|
40
|
+
unless json.nil?
|
|
41
|
+
self.from_json(json, name: name, scope: scope)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Array<Hash>] All the Key, Values stored under the name key
|
|
46
|
+
def self.all(scope:)
|
|
47
|
+
super("#{scope}#{PRIMARY_KEY}")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Array<String>] All the uuids stored under the name key
|
|
51
|
+
def self.names(scope:)
|
|
52
|
+
super("#{scope}#{PRIMARY_KEY}")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Check dependents before delete.
|
|
56
|
+
def self.delete(name:, scope:)
|
|
57
|
+
model = self.get(name: name, scope: scope)
|
|
58
|
+
if model.nil?
|
|
59
|
+
raise TriggerGroupInputError.new "invalid group: #{name} not found"
|
|
60
|
+
end
|
|
61
|
+
triggers = TriggerModel.names(scope: scope, group: name)
|
|
62
|
+
if triggers.empty?
|
|
63
|
+
Store.hdel("#{scope}#{PRIMARY_KEY}", name)
|
|
64
|
+
model.notify(kind: 'deleted')
|
|
65
|
+
else
|
|
66
|
+
raise TriggerGroupError.new "failed to delete #{name} triggers: #{triggers}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
attr_reader :name, :scope, :color, :updated_at
|
|
71
|
+
|
|
72
|
+
def initialize(name:, scope:, color: nil, updated_at: nil)
|
|
73
|
+
if name.nil? || scope.nil?
|
|
74
|
+
raise GroupTriggerInputError.new "name, or scope must not be nil"
|
|
75
|
+
end
|
|
76
|
+
unless name.is_a?(String)
|
|
77
|
+
raise TriggerGroupInputError.new "invalid name: '#{name}'"
|
|
78
|
+
end
|
|
79
|
+
if name.include?('_')
|
|
80
|
+
raise TriggerGroupInputError.new "invalid name: '#{name}' can not include an underscore '_'"
|
|
81
|
+
end
|
|
82
|
+
super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope)
|
|
83
|
+
@microservice_name = "#{scope}__TRIGGER_GROUP__#{name}"
|
|
84
|
+
update_color(color: color)
|
|
85
|
+
@updated_at = updated_at
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def update_color(color: nil)
|
|
89
|
+
if color.nil?
|
|
90
|
+
color = '#%06x' % (rand * 0xffffff)
|
|
91
|
+
end
|
|
92
|
+
valid_color = color =~ /(#*)([0-9,a-f,A-f]{6})/
|
|
93
|
+
if valid_color.nil?
|
|
94
|
+
raise TriggerGroupInputError.new "invalid color must be in hex format. #FF0000"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
unless color.start_with?('#')
|
|
98
|
+
color = "##{color}"
|
|
99
|
+
end
|
|
100
|
+
@color = color
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def create
|
|
104
|
+
unless Store.hget(@primary_key, @name).nil?
|
|
105
|
+
raise TriggerGroupInputError.new "exsisting TriggerGroup found: #{@name}"
|
|
106
|
+
end
|
|
107
|
+
@updated_at = Time.now.to_nsec_from_epoch
|
|
108
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
109
|
+
notify(kind: 'created')
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def update
|
|
113
|
+
@updated_at = Time.now.to_nsec_from_epoch
|
|
114
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
115
|
+
notify(kind: 'updated')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @return [String] generated from the TriggerGroupModel
|
|
119
|
+
def to_s
|
|
120
|
+
return "(TriggerGroupModel :: #{@name})"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# @return [Hash] generated from the TriggerGroupModel
|
|
124
|
+
def as_json(*a)
|
|
125
|
+
return {
|
|
126
|
+
'name' => @name,
|
|
127
|
+
'scope' => @scope,
|
|
128
|
+
'color' => @color,
|
|
129
|
+
'updated_at' => @updated_at,
|
|
130
|
+
}
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# @return [TriggerGroupModel] Model generated from the passed JSON
|
|
134
|
+
def self.from_json(json, name:, scope:)
|
|
135
|
+
json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
|
|
136
|
+
raise "json data is nil" if json.nil?
|
|
137
|
+
|
|
138
|
+
json.transform_keys!(&:to_sym)
|
|
139
|
+
self.new(**json, name: name, scope: scope)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @return [] update the redis stream / trigger topic that something has changed
|
|
143
|
+
def notify(kind:, error: nil)
|
|
144
|
+
data = as_json(:allow_nan => true)
|
|
145
|
+
data['error'] = error unless error.nil?
|
|
146
|
+
notification = {
|
|
147
|
+
'kind' => kind,
|
|
148
|
+
'type' => 'group',
|
|
149
|
+
'data' => JSON.generate(data),
|
|
150
|
+
}
|
|
151
|
+
AutonomicTopic.write_notification(notification, scope: @scope)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def create_microservice(topics:)
|
|
155
|
+
# reaction Microservice
|
|
156
|
+
microservice = MicroserviceModel.new(
|
|
157
|
+
name: @microservice_name,
|
|
158
|
+
folder_name: nil,
|
|
159
|
+
cmd: ['ruby', "trigger_group_microservice.rb", @microservice_name],
|
|
160
|
+
work_dir: '/openc3/lib/openc3/microservices',
|
|
161
|
+
options: [],
|
|
162
|
+
topics: topics,
|
|
163
|
+
target_names: [],
|
|
164
|
+
plugin: nil,
|
|
165
|
+
scope: @scope
|
|
166
|
+
)
|
|
167
|
+
microservice.create
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def deploy
|
|
171
|
+
topics = ["#{@scope}__openc3_autonomic"]
|
|
172
|
+
if MicroserviceModel.get_model(name: @microservice_name, scope: @scope).nil?
|
|
173
|
+
AutonomicTopic.initialize_streams(topics)
|
|
174
|
+
create_microservice(topics: topics)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def undeploy
|
|
179
|
+
if TriggerModel.names(scope: scope, group: name).empty?
|
|
180
|
+
model = MicroserviceModel.get_model(name: @microservice_name, scope: @scope)
|
|
181
|
+
model.destroy if model
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
end
|