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,322 @@
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/trigger_model'
22
+ require 'openc3/models/microservice_model'
23
+ require 'openc3/topics/autonomic_topic'
24
+
25
+ module OpenC3
26
+ class ReactionError < StandardError; end
27
+
28
+ class ReactionInputError < ReactionError; end
29
+
30
+ # {
31
+ # "description": "POSX greater than 200",
32
+ # "snooze": 300,
33
+ # "review": true,
34
+ # "triggers": [
35
+ # {
36
+ # "name": "TV0-1234",
37
+ # "group": "foo",
38
+ # }
39
+ # ],
40
+ # "actions": [
41
+ # {
42
+ # "type": "command",
43
+ # "value": "INST CLEAR",
44
+ # }
45
+ # ]
46
+ # }
47
+ class ReactionModel < Model
48
+ PRIMARY_KEY = '__openc3__reaction'.freeze
49
+ COMMAND_REACTION = 'command'.freeze
50
+ SCRIPT_REACTION = 'script'.freeze
51
+
52
+ def self.create_mini_id
53
+ time = (Time.now.to_f * 10_000_000).to_i
54
+ jitter = rand(10_000_000)
55
+ key = "#{jitter}#{time}".to_i.to_s(36)
56
+ return "RV0-#{key}"
57
+ end
58
+
59
+ # @return [Array<ReactionModel>]
60
+ def self.reactions(scope:)
61
+ reactions = Array.new
62
+ Store.hgetall("#{scope}#{PRIMARY_KEY}").each do |key, value|
63
+ data = JSON.parse(value, :allow_nan => true, :create_additions => true)
64
+ reaction = self.from_json(data, name: data['name'], scope: data['scope'])
65
+ reactions << reaction if reaction.active
66
+ end
67
+ return reactions
68
+ end
69
+
70
+ # @return [ReactionModel] Return the object with the name at
71
+ def self.get(name:, scope:)
72
+ json = super("#{scope}#{PRIMARY_KEY}", name: name)
73
+ unless json.nil?
74
+ self.from_json(json, name: name, scope: scope)
75
+ end
76
+ end
77
+
78
+ # @return [Array<Hash>] All the Key, Values stored under the name key
79
+ def self.all(scope:)
80
+ super("#{scope}#{PRIMARY_KEY}")
81
+ end
82
+
83
+ # @return [Array<String>] All the uuids stored under the name key
84
+ def self.names(scope:)
85
+ super("#{scope}#{PRIMARY_KEY}")
86
+ end
87
+
88
+ # Check dependents before delete.
89
+ def self.delete(name:, scope:, force: false)
90
+ model = self.get(name: name, scope: scope)
91
+ if model.nil?
92
+ raise ReactionInputError.new "failed to find reaction: #{name}"
93
+ end
94
+ model.triggers.each do | trigger |
95
+ trigger_model = TriggerModel.get(name: trigger['name'], group: trigger['group'], scope: scope)
96
+ trigger_model.update_dependents(dependent: name, remove: true)
97
+ trigger_model.update()
98
+ end
99
+ Store.hdel("#{scope}#{PRIMARY_KEY}", name)
100
+ model.notify(kind: 'deleted')
101
+ end
102
+
103
+ #
104
+ def validate_snooze(snooze:)
105
+ unless snooze.is_a?(Integer)
106
+ raise ReactionInputError.new "invalid snooze value: #{snooze}"
107
+ end
108
+ if snooze < 30
109
+ raise ReactionInputError.new "invalid snooze: '#{snooze}' must be greater than 30"
110
+ end
111
+ return snooze
112
+ end
113
+
114
+ #
115
+ def validate_triggers(triggers:)
116
+ unless triggers.is_a?(Array)
117
+ raise ReactionInputError.new "invalid operator: #{operator}"
118
+ end
119
+ trigger_hash = Hash.new()
120
+ triggers.each do | trigger |
121
+ unless trigger.is_a?(Hash)
122
+ raise ReactionInputError.new "invalid trigger object: #{trigger}"
123
+ end
124
+ if trigger['name'].nil? || trigger['group'].nil?
125
+ raise ReactionInputError.new "allowed: #{triggers}"
126
+ end
127
+ trigger_name = trigger['name']
128
+ unless trigger_hash[trigger_name].nil?
129
+ raise ReactionInputError.new "no duplicate triggers allowed: #{triggers}"
130
+ else
131
+ trigger_hash[trigger_name] = 1
132
+ end
133
+ end
134
+ return triggers
135
+ end
136
+
137
+ #
138
+ def validate_actions(actions:)
139
+ unless actions.is_a?(Array)
140
+ raise ReactionInputError.new "invalid actions object: #{actions}"
141
+ end
142
+ actions.each do | action |
143
+ unless action.is_a?(Hash)
144
+ raise ReactionInputError.new "invalid action object: #{action}"
145
+ end
146
+ action_type = action['type']
147
+ if action_type.nil?
148
+ raise ReactionInputError.new "reaction action must contain type: #{action_type}"
149
+ elsif action['value'].nil?
150
+ raise ReactionInputError.new "reaction action: #{action} does not contain 'value'"
151
+ end
152
+ unless [COMMAND_REACTION, SCRIPT_REACTION].include?(action_type)
153
+ raise ReactionInputError.new "reaction action contains invalid type: #{action_type}"
154
+ end
155
+ end
156
+ return actions
157
+ end
158
+
159
+ attr_reader :name, :scope, :description, :snooze, :triggers, :actions, :active, :review, :snoozed_until
160
+
161
+ def initialize(
162
+ name:,
163
+ scope:,
164
+ description:,
165
+ snooze:,
166
+ actions:,
167
+ triggers:,
168
+ active: true,
169
+ review: true,
170
+ snoozed_until: nil,
171
+ updated_at: nil
172
+ )
173
+ if name.nil? || scope.nil? || description.nil? || snooze.nil? || triggers.nil? || actions.nil?
174
+ raise ReactionInputError.new "#{name}, #{scope}, #{description}, #{snooze}, #{triggers}, or #{actions} must not be nil"
175
+ end
176
+ super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope)
177
+ @microservice_name = "#{scope}__OPENC3__REACTION"
178
+ @active = active
179
+ @review = review
180
+ @description = description
181
+ @snoozed_until = snoozed_until
182
+ @snooze = validate_snooze(snooze: snooze)
183
+ @actions = validate_actions(actions: actions)
184
+ @triggers = validate_triggers(triggers: triggers)
185
+ @updated_at = updated_at
186
+ end
187
+
188
+ def verify_triggers
189
+ trigger_models = []
190
+ @triggers.each do | trigger |
191
+ model = TriggerModel.get(name: trigger['name'], group: trigger['group'], scope: @scope)
192
+ if model.nil?
193
+ raise ReactionInputError.new "failed to find trigger: #{trigger}"
194
+ end
195
+ trigger_models << model
196
+ end
197
+ if trigger_models.empty?
198
+ raise ReactionInputError.new "reaction must contain at least one valid trigger: #{@triggers}"
199
+ end
200
+ trigger_models.each do | trigger_model |
201
+ trigger_model.update_dependents(dependent: @name)
202
+ trigger_model.update()
203
+ end
204
+ end
205
+
206
+ def create
207
+ unless Store.hget(@primary_key, @name).nil?
208
+ raise ReactionInputError.new "exsisting Reaction found: #{@name}"
209
+ end
210
+ verify_triggers()
211
+ @updated_at = Time.now.to_nsec_from_epoch
212
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
213
+ notify(kind: 'created')
214
+ end
215
+
216
+ def update
217
+ verify_triggers()
218
+ @updated_at = Time.now.to_nsec_from_epoch
219
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
220
+ notify(kind: 'updated')
221
+ end
222
+
223
+ def activate
224
+ @active = true
225
+ @snoozed_until = nil if @snoozed_until && @snoozed_until < Time.now.to_i
226
+ @updated_at = Time.now.to_nsec_from_epoch
227
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
228
+ notify(kind: 'activated')
229
+ end
230
+
231
+ def deactivate
232
+ @active = false
233
+ @updated_at = Time.now.to_nsec_from_epoch
234
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
235
+ notify(kind: 'deactivated')
236
+ end
237
+
238
+ def sleep
239
+ @snoozed_until = Time.now.to_i + @snooze
240
+ @updated_at = Time.now.to_nsec_from_epoch
241
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
242
+ notify(kind: 'sleep')
243
+ end
244
+
245
+ def awaken
246
+ @snoozed_until = nil
247
+ @updated_at = Time.now.to_nsec_from_epoch
248
+ Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
249
+ notify(kind: 'awaken')
250
+ end
251
+
252
+ # @return [String] generated from the TriggerModel
253
+ def to_s
254
+ return "(ReactionModel :: #{@name} :: #{@active} :: #{@review} :: #{@description} :: #{@snooze} :: #{@snoozed_until})"
255
+ end
256
+
257
+ # @return [Hash] generated from the ReactionModel
258
+ def as_json(*a)
259
+ return {
260
+ 'name' => @name,
261
+ 'scope' => @scope,
262
+ 'active' => @active,
263
+ 'review' => @review,
264
+ 'description' => @description,
265
+ 'snooze' => @snooze,
266
+ 'snoozed_until' => @snoozed_until,
267
+ 'triggers' => @triggers,
268
+ 'actions' => @actions,
269
+ 'updated_at' => @updated_at
270
+ }
271
+ end
272
+
273
+ # @return [ReactionModel] Model generated from the passed JSON
274
+ def self.from_json(json, name:, scope:)
275
+ json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
276
+ raise "json data is nil" if json.nil?
277
+
278
+ json.transform_keys!(&:to_sym)
279
+ self.new(**json, name: name, scope: scope)
280
+ end
281
+
282
+ # @return [] update the redis stream / reaction topic that something has changed
283
+ def notify(kind:)
284
+ notification = {
285
+ 'kind' => kind,
286
+ 'type' => 'reaction',
287
+ 'data' => JSON.generate(as_json(:allow_nan => true)),
288
+ }
289
+ AutonomicTopic.write_notification(notification, scope: @scope)
290
+ end
291
+
292
+ def create_microservice(topics:)
293
+ # reaction Microservice
294
+ microservice = MicroserviceModel.new(
295
+ name: @microservice_name,
296
+ folder_name: nil,
297
+ cmd: ['ruby', 'reaction_microservice.rb', @microservice_name],
298
+ work_dir: '/openc3/lib/openc3/microservices',
299
+ options: [],
300
+ topics: topics,
301
+ target_names: [],
302
+ plugin: nil,
303
+ scope: @scope
304
+ )
305
+ microservice.create
306
+ end
307
+
308
+ def deploy
309
+ topics = ["#{@scope}__openc3_autonomic"]
310
+ if MicroserviceModel.get_model(name: @microservice_name, scope: @scope).nil?
311
+ create_microservice(topics: topics)
312
+ end
313
+ end
314
+
315
+ def undeploy
316
+ if ReactionModel.names(scope: @scope).empty?
317
+ model = MicroserviceModel.get_model(name: @microservice_name, scope: @scope)
318
+ model.destroy if model
319
+ end
320
+ end
321
+ end
322
+ end
@@ -0,0 +1,65 @@
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/utilities/store'
21
+
22
+ module OpenC3
23
+ # Tracks the files which are being stored in S3 for data reduction purposes.
24
+ # Files are stored in a Redis set by spliting their filenames and storing in
25
+ # a set named SCOPE__TARGET__reducer__TYPE, e.g. DEFAULT__INST__reducer__decom
26
+ # Where TYPE can be 'decom', 'minute', or 'hour'. 'day' is not necessary because
27
+ # day is the final reduction state. As files are reduced they are removed from
28
+ # the set. Thus the sets contain the active set of files to be reduced.
29
+ class ReducerModel
30
+ def self.add_file(s3_key)
31
+ # s3_key is formatted like STARTTIME__ENDTIME__SCOPE__TARGET__PACKET__TYPE.bin
32
+ # e.g. 20211229191610578229500__20211229192610563836500__DEFAULT__INST__HEALTH_STATUS__rt__decom.bin
33
+ _, _, scope, target, _ = s3_key.split('__')
34
+ case s3_key
35
+ when /__decom\.bin$/
36
+ Store.sadd("#{scope}__#{target}__reducer__decom", s3_key)
37
+ when /__minute\.bin$/
38
+ Store.sadd("#{scope}__#{target}__reducer__minute", s3_key)
39
+ when /__hour\.bin$/
40
+ Store.sadd("#{scope}__#{target}__reducer__hour", s3_key)
41
+ end
42
+ # No else clause because add_file is called with raw files which are ignored
43
+ end
44
+
45
+ def self.rm_file(s3_key)
46
+ _, _, scope, target, _ = s3_key.split('__')
47
+ case s3_key
48
+ when /__decom\.bin$/
49
+ Store.srem("#{scope}__#{target}__reducer__decom", s3_key)
50
+ when /__minute\.bin$/
51
+ Store.srem("#{scope}__#{target}__reducer__minute", s3_key)
52
+ when /__hour\.bin$/
53
+ Store.srem("#{scope}__#{target}__reducer__hour", s3_key)
54
+ else
55
+ # We should only remove files that were previously in the set
56
+ # Thus if we don't match the s3_key it is an error
57
+ raise "Unknown file #{s3_key}"
58
+ end
59
+ end
60
+
61
+ def self.all_files(type:, target:, scope:)
62
+ Store.smembers("#{scope}__#{target}__reducer__#{type.downcase}").sort
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,35 @@
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/interface_model'
21
+
22
+ module OpenC3
23
+ class RouterModel < InterfaceModel
24
+ # Called by the PluginModel to allow this class to validate it's top-level keyword: "ROUTER"
25
+ def self.handle_config(parser, keyword, parameters, plugin: nil, needs_dependencies: false, scope:)
26
+ case keyword
27
+ when 'ROUTER'
28
+ parser.verify_num_parameters(2, nil, "ROUTER <Name> <Filename> <Specific Parameters>")
29
+ return self.new(name: parameters[0].upcase, config_params: parameters[1..-1], plugin: plugin, needs_dependencies: needs_dependencies, scope: scope)
30
+ else
31
+ raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Router: #{keyword} #{parameters.join(" ")}")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
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/interface_status_model'
21
+
22
+ module OpenC3
23
+ # Stores the status about a router. All of the functionality is handled
24
+ # in the InterfaceStatusModel so we simply inherit it.
25
+ class RouterStatusModel < InterfaceStatusModel
26
+ end
27
+ end
@@ -0,0 +1,153 @@
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/version'
21
+ require 'openc3/models/model'
22
+ require 'openc3/models/microservice_model'
23
+ require 'openc3/models/settings_model'
24
+
25
+ module OpenC3
26
+ class ScopeModel < Model
27
+ PRIMARY_KEY = 'openc3_scopes'
28
+
29
+ # NOTE: The following three class methods are used by the ModelController
30
+ # and are reimplemented to enable various Model class methods to work
31
+ def self.get(name:, scope: nil)
32
+ super(PRIMARY_KEY, name: name)
33
+ end
34
+
35
+ def self.names(scope: nil)
36
+ super(PRIMARY_KEY)
37
+ end
38
+
39
+ def self.all(scope: nil)
40
+ super(PRIMARY_KEY)
41
+ end
42
+
43
+ def initialize(name:, updated_at: nil, scope: nil)
44
+ super(PRIMARY_KEY, name: name, scope: name, updated_at: updated_at)
45
+ end
46
+
47
+ def as_json(*a)
48
+ { 'name' => @name,
49
+ 'updated_at' => @updated_at }
50
+ end
51
+
52
+ def deploy(gem_path, variables)
53
+ seed_database()
54
+
55
+ ConfigTopic.initialize_stream(@scope)
56
+
57
+ # OpenC3 Log Microservice
58
+ microservice_name = "#{@scope}__OPENC3__LOG"
59
+ microservice = MicroserviceModel.new(
60
+ name: microservice_name,
61
+ cmd: ["ruby", "text_log_microservice.rb", microservice_name],
62
+ work_dir: '/openc3/lib/openc3/microservices',
63
+ options: [
64
+ # The following options are optional (600 and 50_000_000 are the defaults)
65
+ # ["CYCLE_TIME", "600"], # Keep at most 10 minutes per log
66
+ # ["CYCLE_SIZE", "50_000_000"] # Keep at most ~50MB per log
67
+ ],
68
+ topics: ["#{@scope}__openc3_log_messages"],
69
+ scope: @scope
70
+ )
71
+ microservice.create
72
+ microservice.deploy(gem_path, variables)
73
+ Logger.info "Configured microservice #{microservice_name}"
74
+
75
+ # Notification Log Microservice
76
+ microservice_name = "#{@scope}__NOTIFICATION__LOG"
77
+ microservice = MicroserviceModel.new(
78
+ name: microservice_name,
79
+ cmd: ["ruby", "text_log_microservice.rb", microservice_name],
80
+ work_dir: '/openc3/lib/openc3/microservices',
81
+ options: [
82
+ # The following options are optional (600 and 50_000_000 are the defaults)
83
+ ["CYCLE_TIME", "3600"], # Keep at most 1 hour per log
84
+ ],
85
+ topics: ["#{@scope}__openc3_notifications"],
86
+ scope: @scope
87
+ )
88
+ microservice.create
89
+ microservice.deploy(gem_path, variables)
90
+ Logger.info "Configured microservice #{microservice_name}"
91
+
92
+ # UNKNOWN CommandLog Microservice
93
+ Topic.initialize_streams(["#{@scope}__COMMAND__{UNKNOWN}__UNKNOWN"])
94
+ microservice_name = "#{@scope}__COMMANDLOG__UNKNOWN"
95
+ microservice = MicroserviceModel.new(
96
+ name: microservice_name,
97
+ cmd: ["ruby", "log_microservice.rb", microservice_name],
98
+ work_dir: '/openc3/lib/openc3/microservices',
99
+ options: [
100
+ ["RAW_OR_DECOM", "RAW"],
101
+ ["CMD_OR_TLM", "CMD"],
102
+ ["CYCLE_TIME", "3600"], # Keep at most 1 hour per log
103
+ ],
104
+ topics: ["#{@scope}__COMMAND__{UNKNOWN}__UNKNOWN"],
105
+ target_names: [],
106
+ scope: @scope
107
+ )
108
+ microservice.create
109
+ microservice.deploy(gem_path, variables)
110
+ Logger.info "Configured microservice #{microservice_name}"
111
+
112
+ # UNKNOWN PacketLog Microservice
113
+ Topic.initialize_streams(["#{@scope}__TELEMETRY__{UNKNOWN}__UNKNOWN"])
114
+ microservice_name = "#{@scope}__PACKETLOG__UNKNOWN"
115
+ microservice = MicroserviceModel.new(
116
+ name: microservice_name,
117
+ cmd: ["ruby", "log_microservice.rb", microservice_name],
118
+ work_dir: '/openc3/lib/openc3/microservices',
119
+ options: [
120
+ ["RAW_OR_DECOM", "RAW"],
121
+ ["CMD_OR_TLM", "TLM"],
122
+ ["CYCLE_TIME", "3600"], # Keep at most 1 hour per log
123
+ ],
124
+ topics: ["#{@scope}__TELEMETRY__{UNKNOWN}__UNKNOWN"],
125
+ target_names: [],
126
+ scope: @scope
127
+ )
128
+ microservice.create
129
+ microservice.deploy(gem_path, variables)
130
+ Logger.info "Configured microservice #{microservice_name}"
131
+ end
132
+
133
+ def undeploy
134
+ model = MicroserviceModel.get_model(name: "#{@scope}__OPENC3__LOG", scope: @scope)
135
+ model.destroy if model
136
+ model = MicroserviceModel.get_model(name: "#{@scope}__NOTIFICATION__LOG", scope: @scope)
137
+ model.destroy if model
138
+ model = MicroserviceModel.get_model(name: "#{@scope}__COMMANDLOG__UNKNOWN", scope: @scope)
139
+ model.destroy if model
140
+ model = MicroserviceModel.get_model(name: "#{@scope}__PACKETLOG__UNKNOWN", scope: @scope)
141
+ model.destroy if model
142
+ end
143
+
144
+ def seed_database
145
+ setting = SettingsModel.get(name: 'source_url')
146
+ SettingsModel.set({ name: 'source_url', data: 'https://github.com/OpenC3/openc3' }, scope: @scope) unless setting
147
+ end
148
+
149
+ def self.limits_set(scope:)
150
+ Store.hget("#{scope}__openc3_system", 'limits_set').intern
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,55 @@
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
+
22
+ module OpenC3
23
+ class SettingsModel < Model
24
+ PRIMARY_KEY = 'openc3__settings'
25
+
26
+ # NOTE: The following three class methods are used by the ModelController
27
+ # and are reimplemented to enable various Model class methods to work
28
+ def self.get(name:, scope: nil)
29
+ super(PRIMARY_KEY, name: name)
30
+ end
31
+
32
+ def self.names(scope: nil)
33
+ super(PRIMARY_KEY)
34
+ end
35
+
36
+ def self.all(scope: nil)
37
+ super(PRIMARY_KEY)
38
+ end
39
+ # END NOTE
40
+
41
+ def initialize(name:, scope: nil, data:)
42
+ super(PRIMARY_KEY, name: name, scope: scope)
43
+ @data = data
44
+ end
45
+
46
+ # @return [Hash] JSON encoding of this model
47
+ def as_json(*a)
48
+ {
49
+ 'name' => @name,
50
+ 'data' => @data.as_json(*a),
51
+ 'updated_at' => @updated_at
52
+ }
53
+ end
54
+ end
55
+ end