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.
Files changed (307) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +18 -0
  3. data/Guardfile +35 -0
  4. data/LICENSE.txt +727 -0
  5. data/README.md +37 -0
  6. data/Rakefile +131 -0
  7. data/bin/cstol_converter +1178 -0
  8. data/bin/openc3cli +531 -0
  9. data/bin/rubysloc +139 -0
  10. data/data/config/_array_params.yaml +23 -0
  11. data/data/config/_id_items.yaml +24 -0
  12. data/data/config/_id_params.yaml +58 -0
  13. data/data/config/_interfaces.yaml +214 -0
  14. data/data/config/_interfaces.yaml.err +1017 -0
  15. data/data/config/_items.yaml +20 -0
  16. data/data/config/_params.yaml +60 -0
  17. data/data/config/cmd_tlm_server.yaml +136 -0
  18. data/data/config/command.yaml +44 -0
  19. data/data/config/command_modifiers.yaml +160 -0
  20. data/data/config/command_telemetry.yaml +3 -0
  21. data/data/config/interface_modifiers.yaml +104 -0
  22. data/data/config/item_modifiers.yaml +221 -0
  23. data/data/config/microservice.yaml +78 -0
  24. data/data/config/param_item_modifiers.yaml +52 -0
  25. data/data/config/parameter_modifiers.yaml +200 -0
  26. data/data/config/plugins.yaml +80 -0
  27. data/data/config/protocols.yaml +290 -0
  28. data/data/config/screen.yaml +147 -0
  29. data/data/config/table_manager.yaml +89 -0
  30. data/data/config/table_parameter_modifiers.yaml +9 -0
  31. data/data/config/target.yaml +142 -0
  32. data/data/config/target_config.yaml +94 -0
  33. data/data/config/telemetry.yaml +87 -0
  34. data/data/config/telemetry_modifiers.yaml +159 -0
  35. data/data/config/tool.yaml +63 -0
  36. data/data/config/unknown.yaml +3 -0
  37. data/data/config/widgets.yaml +1505 -0
  38. data/ext/mkrf_conf.rb +49 -0
  39. data/ext/openc3/ext/array/array.c +122 -0
  40. data/ext/openc3/ext/array/extconf.rb +13 -0
  41. data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
  42. data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
  43. data/ext/openc3/ext/config_parser/config_parser.c +280 -0
  44. data/ext/openc3/ext/config_parser/extconf.rb +13 -0
  45. data/ext/openc3/ext/crc/crc.c +351 -0
  46. data/ext/openc3/ext/crc/extconf.rb +13 -0
  47. data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
  48. data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
  49. data/ext/openc3/ext/packet/extconf.rb +13 -0
  50. data/ext/openc3/ext/packet/packet.c +318 -0
  51. data/ext/openc3/ext/platform/extconf.rb +13 -0
  52. data/ext/openc3/ext/platform/platform.c +134 -0
  53. data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
  54. data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
  55. data/ext/openc3/ext/string/extconf.rb +13 -0
  56. data/ext/openc3/ext/string/string.c +63 -0
  57. data/ext/openc3/ext/structure/structure.c +1719 -0
  58. data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
  59. data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
  60. data/ext/openc3/ext/telemetry/extconf.rb +13 -0
  61. data/ext/openc3/ext/telemetry/telemetry.c +336 -0
  62. data/lib/cosmos.rb +20 -0
  63. data/lib/cosmosc2.rb +20 -0
  64. data/lib/openc3/api/api.rb +39 -0
  65. data/lib/openc3/api/authorized_api.rb +30 -0
  66. data/lib/openc3/api/cmd_api.rb +451 -0
  67. data/lib/openc3/api/config_api.rb +58 -0
  68. data/lib/openc3/api/interface_api.rb +117 -0
  69. data/lib/openc3/api/limits_api.rb +375 -0
  70. data/lib/openc3/api/router_api.rb +117 -0
  71. data/lib/openc3/api/settings_api.rb +70 -0
  72. data/lib/openc3/api/target_api.rb +78 -0
  73. data/lib/openc3/api/tlm_api.rb +455 -0
  74. data/lib/openc3/bridge/bridge.rb +54 -0
  75. data/lib/openc3/bridge/bridge_config.rb +167 -0
  76. data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
  77. data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
  78. data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
  79. data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
  80. data/lib/openc3/config/config_parser.rb +549 -0
  81. data/lib/openc3/config/meta_config_parser.rb +74 -0
  82. data/lib/openc3/conversions/conversion.rb +70 -0
  83. data/lib/openc3/conversions/generic_conversion.rb +83 -0
  84. data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
  85. data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
  86. data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
  87. data/lib/openc3/conversions/processor_conversion.rb +70 -0
  88. data/lib/openc3/conversions/received_count_conversion.rb +38 -0
  89. data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
  90. data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
  91. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
  92. data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
  93. data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
  94. data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
  95. data/lib/openc3/conversions.rb +34 -0
  96. data/lib/openc3/core_ext/array.rb +416 -0
  97. data/lib/openc3/core_ext/binding.rb +29 -0
  98. data/lib/openc3/core_ext/class.rb +72 -0
  99. data/lib/openc3/core_ext/exception.rb +61 -0
  100. data/lib/openc3/core_ext/file.rb +83 -0
  101. data/lib/openc3/core_ext/hash.rb +37 -0
  102. data/lib/openc3/core_ext/io.rb +134 -0
  103. data/lib/openc3/core_ext/kernel.rb +42 -0
  104. data/lib/openc3/core_ext/math.rb +128 -0
  105. data/lib/openc3/core_ext/matrix.rb +156 -0
  106. data/lib/openc3/core_ext/objectspace.rb +36 -0
  107. data/lib/openc3/core_ext/openc3_io.rb +57 -0
  108. data/lib/openc3/core_ext/range.rb +27 -0
  109. data/lib/openc3/core_ext/socket.rb +38 -0
  110. data/lib/openc3/core_ext/string.rb +389 -0
  111. data/lib/openc3/core_ext/stringio.rb +33 -0
  112. data/lib/openc3/core_ext/time.rb +508 -0
  113. data/lib/openc3/core_ext.rb +36 -0
  114. data/lib/openc3/interfaces/interface.rb +498 -0
  115. data/lib/openc3/interfaces/linc_interface.rb +475 -0
  116. data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
  117. data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
  118. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
  119. data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
  120. data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
  121. data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
  122. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
  123. data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
  124. data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
  125. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
  126. data/lib/openc3/interfaces/serial_interface.rb +94 -0
  127. data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
  128. data/lib/openc3/interfaces/stream_interface.rb +81 -0
  129. data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
  130. data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
  131. data/lib/openc3/interfaces/udp_interface.rb +169 -0
  132. data/lib/openc3/interfaces.rb +44 -0
  133. data/lib/openc3/io/buffered_file.rb +109 -0
  134. data/lib/openc3/io/io_multiplexer.rb +80 -0
  135. data/lib/openc3/io/json_api_object.rb +208 -0
  136. data/lib/openc3/io/json_drb.rb +335 -0
  137. data/lib/openc3/io/json_drb_object.rb +114 -0
  138. data/lib/openc3/io/json_drb_rack.rb +84 -0
  139. data/lib/openc3/io/json_rpc.rb +420 -0
  140. data/lib/openc3/io/openc3_snmp.rb +58 -0
  141. data/lib/openc3/io/posix_serial_driver.rb +156 -0
  142. data/lib/openc3/io/raw_logger.rb +167 -0
  143. data/lib/openc3/io/raw_logger_pair.rb +77 -0
  144. data/lib/openc3/io/serial_driver.rb +105 -0
  145. data/lib/openc3/io/stderr.rb +43 -0
  146. data/lib/openc3/io/stdout.rb +43 -0
  147. data/lib/openc3/io/udp_sockets.rb +194 -0
  148. data/lib/openc3/io/win32_serial_driver.rb +196 -0
  149. data/lib/openc3/logs/log_writer.rb +302 -0
  150. data/lib/openc3/logs/packet_log_constants.rb +62 -0
  151. data/lib/openc3/logs/packet_log_reader.rb +345 -0
  152. data/lib/openc3/logs/packet_log_writer.rb +299 -0
  153. data/lib/openc3/logs/text_log_writer.rb +68 -0
  154. data/lib/openc3/logs.rb +25 -0
  155. data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
  156. data/lib/openc3/microservices/decom_microservice.rb +136 -0
  157. data/lib/openc3/microservices/interface_microservice.rb +532 -0
  158. data/lib/openc3/microservices/log_microservice.rb +108 -0
  159. data/lib/openc3/microservices/microservice.rb +204 -0
  160. data/lib/openc3/microservices/plugin_microservice.rb +43 -0
  161. data/lib/openc3/microservices/reaction_microservice.rb +541 -0
  162. data/lib/openc3/microservices/reducer_microservice.rb +313 -0
  163. data/lib/openc3/microservices/router_microservice.rb +44 -0
  164. data/lib/openc3/microservices/text_log_microservice.rb +84 -0
  165. data/lib/openc3/microservices/timeline_microservice.rb +363 -0
  166. data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
  167. data/lib/openc3/models/activity_model.rb +319 -0
  168. data/lib/openc3/models/auth_model.rb +65 -0
  169. data/lib/openc3/models/cvt_model.rb +185 -0
  170. data/lib/openc3/models/environment_model.rb +58 -0
  171. data/lib/openc3/models/gem_model.rb +137 -0
  172. data/lib/openc3/models/info_model.rb +31 -0
  173. data/lib/openc3/models/interface_model.rb +281 -0
  174. data/lib/openc3/models/interface_status_model.rb +117 -0
  175. data/lib/openc3/models/metadata_model.rb +139 -0
  176. data/lib/openc3/models/metric_model.rb +59 -0
  177. data/lib/openc3/models/microservice_model.rb +206 -0
  178. data/lib/openc3/models/microservice_status_model.rb +74 -0
  179. data/lib/openc3/models/model.rb +204 -0
  180. data/lib/openc3/models/note_model.rb +122 -0
  181. data/lib/openc3/models/notification_model.rb +40 -0
  182. data/lib/openc3/models/ping_model.rb +35 -0
  183. data/lib/openc3/models/plugin_model.rb +292 -0
  184. data/lib/openc3/models/process_status_model.rb +76 -0
  185. data/lib/openc3/models/reaction_model.rb +322 -0
  186. data/lib/openc3/models/reducer_model.rb +65 -0
  187. data/lib/openc3/models/router_model.rb +35 -0
  188. data/lib/openc3/models/router_status_model.rb +27 -0
  189. data/lib/openc3/models/scope_model.rb +153 -0
  190. data/lib/openc3/models/settings_model.rb +55 -0
  191. data/lib/openc3/models/sorted_model.rb +167 -0
  192. data/lib/openc3/models/target_model.rb +759 -0
  193. data/lib/openc3/models/timeline_model.rb +154 -0
  194. data/lib/openc3/models/tool_config_model.rb +38 -0
  195. data/lib/openc3/models/tool_model.rb +262 -0
  196. data/lib/openc3/models/trigger_group_model.rb +186 -0
  197. data/lib/openc3/models/trigger_model.rb +330 -0
  198. data/lib/openc3/models/widget_model.rb +138 -0
  199. data/lib/openc3/operators/microservice_operator.rb +128 -0
  200. data/lib/openc3/operators/operator.rb +277 -0
  201. data/lib/openc3/packets/binary_accessor.rb +1207 -0
  202. data/lib/openc3/packets/commands.rb +373 -0
  203. data/lib/openc3/packets/json_packet.rb +134 -0
  204. data/lib/openc3/packets/limits.rb +271 -0
  205. data/lib/openc3/packets/limits_response.rb +53 -0
  206. data/lib/openc3/packets/packet.rb +1168 -0
  207. data/lib/openc3/packets/packet_config.rb +625 -0
  208. data/lib/openc3/packets/packet_item.rb +586 -0
  209. data/lib/openc3/packets/packet_item_limits.rb +162 -0
  210. data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
  211. data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
  212. data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
  213. data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
  214. data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
  215. data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
  216. data/lib/openc3/packets/parsers/state_parser.rb +127 -0
  217. data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
  218. data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
  219. data/lib/openc3/packets/structure.rb +553 -0
  220. data/lib/openc3/packets/structure_item.rb +365 -0
  221. data/lib/openc3/packets/telemetry.rb +487 -0
  222. data/lib/openc3/processors/processor.rb +86 -0
  223. data/lib/openc3/processors/statistics_processor.rb +82 -0
  224. data/lib/openc3/processors/watermark_processor.rb +58 -0
  225. data/lib/openc3/processors.rb +24 -0
  226. data/lib/openc3/script/api_shared.rb +828 -0
  227. data/lib/openc3/script/calendar.rb +89 -0
  228. data/lib/openc3/script/commands.rb +227 -0
  229. data/lib/openc3/script/exceptions.rb +29 -0
  230. data/lib/openc3/script/extract.rb +161 -0
  231. data/lib/openc3/script/limits.rb +60 -0
  232. data/lib/openc3/script/script.rb +299 -0
  233. data/lib/openc3/script/script_runner.rb +238 -0
  234. data/lib/openc3/script/storage.rb +146 -0
  235. data/lib/openc3/script/suite.rb +542 -0
  236. data/lib/openc3/script/suite_results.rb +196 -0
  237. data/lib/openc3/script/suite_runner.rb +217 -0
  238. data/lib/openc3/script.rb +21 -0
  239. data/lib/openc3/streams/serial_stream.rb +167 -0
  240. data/lib/openc3/streams/stream.rb +63 -0
  241. data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
  242. data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
  243. data/lib/openc3/system/system.rb +127 -0
  244. data/lib/openc3/system/system_config.rb +411 -0
  245. data/lib/openc3/system/target.rb +269 -0
  246. data/lib/openc3/system.rb +24 -0
  247. data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
  248. data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
  249. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
  250. data/lib/openc3/tools/table_manager/table.rb +77 -0
  251. data/lib/openc3/tools/table_manager/table_config.rb +273 -0
  252. data/lib/openc3/tools/table_manager/table_item.rb +90 -0
  253. data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
  254. data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
  255. data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
  256. data/lib/openc3/tools/test_runner/test.rb +67 -0
  257. data/lib/openc3/top_level.rb +595 -0
  258. data/lib/openc3/topics/autonomic_topic.rb +52 -0
  259. data/lib/openc3/topics/calendar_topic.rb +44 -0
  260. data/lib/openc3/topics/command_decom_topic.rb +76 -0
  261. data/lib/openc3/topics/command_topic.rb +83 -0
  262. data/lib/openc3/topics/config_topic.rb +68 -0
  263. data/lib/openc3/topics/interface_topic.rb +73 -0
  264. data/lib/openc3/topics/limits_event_topic.rb +109 -0
  265. data/lib/openc3/topics/notifications_topic.rb +28 -0
  266. data/lib/openc3/topics/router_topic.rb +85 -0
  267. data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
  268. data/lib/openc3/topics/telemetry_topic.rb +36 -0
  269. data/lib/openc3/topics/timeline_topic.rb +45 -0
  270. data/lib/openc3/topics/topic.rb +53 -0
  271. data/lib/openc3/utilities/authentication.rb +141 -0
  272. data/lib/openc3/utilities/authorization.rb +51 -0
  273. data/lib/openc3/utilities/crc.rb +278 -0
  274. data/lib/openc3/utilities/csv.rb +153 -0
  275. data/lib/openc3/utilities/logger.rb +187 -0
  276. data/lib/openc3/utilities/message_log.rb +91 -0
  277. data/lib/openc3/utilities/metric.rb +141 -0
  278. data/lib/openc3/utilities/process_manager.rb +139 -0
  279. data/lib/openc3/utilities/quaternion.rb +257 -0
  280. data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
  281. data/lib/openc3/utilities/s3.rb +202 -0
  282. data/lib/openc3/utilities/s3_autoload.rb +9 -0
  283. data/lib/openc3/utilities/s3_file_cache.rb +274 -0
  284. data/lib/openc3/utilities/simulated_target.rb +117 -0
  285. data/lib/openc3/utilities/sleeper.rb +51 -0
  286. data/lib/openc3/utilities/store.rb +23 -0
  287. data/lib/openc3/utilities/store_autoload.rb +237 -0
  288. data/lib/openc3/utilities/zip.rb +21 -0
  289. data/lib/openc3/utilities.rb +35 -0
  290. data/lib/openc3/version.rb +14 -0
  291. data/lib/openc3/win32/excel.rb +132 -0
  292. data/lib/openc3/win32/win32.rb +402 -0
  293. data/lib/openc3/win32/win32_main.rb +333 -0
  294. data/lib/openc3.rb +49 -0
  295. data/tasks/gemfile_stats.rake +113 -0
  296. data/tasks/spec.rake +30 -0
  297. data/templates/plugin-template/README.md +15 -0
  298. data/templates/plugin-template/Rakefile +12 -0
  299. data/templates/plugin-template/plugin.gemspec +23 -0
  300. data/templates/plugin-template/plugin.txt +9 -0
  301. data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
  302. data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
  303. data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
  304. data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
  305. data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
  306. data/templates/plugin-template/targets/TARGET/target.txt +5 -0
  307. 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