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,202 @@
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
+ autoload(:Aws, 'openc3/utilities/s3_autoload.rb')
21
+ require 'openc3/models/reducer_model'
22
+
23
+ module OpenC3
24
+ class S3Utilities
25
+ def self.list_files_before_time(bucket, prefix, time)
26
+ rubys3_client = Aws::S3::Client.new
27
+ oldest_list = []
28
+ total_size = 0
29
+
30
+ # Return nothing if bucket doesn't exist (it won't at the very beginning)
31
+ begin
32
+ rubys3_client.head_bucket(bucket: bucket)
33
+ rescue Aws::S3::Errors::NotFound
34
+ return total_size, oldest_list
35
+ end
36
+
37
+ # Get List of Packet Names - Assumes prefix gets us to a folder of packet names
38
+ token = nil
39
+ folder_list = []
40
+ while true
41
+ resp = rubys3_client.list_objects_v2({
42
+ bucket: bucket,
43
+ max_keys: 1000,
44
+ prefix: prefix,
45
+ delimiter: '/',
46
+ continuation_token: token
47
+ })
48
+
49
+ resp.common_prefixes.each do |item|
50
+ folder_list << item.prefix
51
+ end
52
+ break unless resp.is_truncated
53
+ token = resp.next_continuation_token
54
+ end
55
+
56
+ # Go through each folder and keep files that end before time
57
+ folder_list.each do |folder|
58
+ token = nil
59
+ next_folder = false
60
+ while true
61
+ resp = rubys3_client.list_objects_v2({
62
+ bucket: bucket,
63
+ max_keys: 1000,
64
+ prefix: folder,
65
+ continuation_token: token
66
+ })
67
+ resp.contents.each do |item|
68
+ t = item.key.split('__')[1]
69
+ file_end_time = Time.utc(t[0..3], t[4..5], t[6..7], t[8..9], t[10..11], t[12..13])
70
+ if file_end_time < time
71
+ oldest_list << item
72
+ total_size += item.size
73
+ else
74
+ next_folder = true
75
+ break
76
+ end
77
+ end
78
+ break if !resp.is_truncated or next_folder
79
+
80
+ token = resp.next_continuation_token
81
+ end
82
+ end
83
+ return total_size, oldest_list
84
+ end
85
+
86
+ def self.get_total_size_and_oldest_list(bucket, prefix, max_list_length = 10000)
87
+ rubys3_client = Aws::S3::Client.new
88
+ oldest_list = []
89
+ total_size = 0
90
+
91
+ # Return nothing if bucket doesn't exist (it won't at the very beginning)
92
+ begin
93
+ rubys3_client.head_bucket(bucket: bucket)
94
+ rescue Aws::S3::Errors::NotFound
95
+ return total_size, oldest_list
96
+ end
97
+
98
+ # Get List of Files from S3
99
+ token = nil
100
+ while true
101
+ resp = rubys3_client.list_objects_v2({
102
+ bucket: bucket,
103
+ max_keys: 1000,
104
+ prefix: prefix,
105
+ continuation_token: token
106
+ })
107
+ resp.contents.each do |item|
108
+ total_size += item.size
109
+ end
110
+ oldest_list.concat(resp.contents)
111
+ oldest_list.sort! { |a, b| File.basename(a.key) <=> File.basename(b.key) }
112
+ oldest_list = oldest_list[0..(max_list_length - 1)]
113
+ break unless resp.is_truncated
114
+
115
+ token = resp.next_continuation_token
116
+ end
117
+ return total_size, oldest_list
118
+ end
119
+
120
+ def self.move_log_file_to_s3(filename, s3_key, metadata: {})
121
+ Thread.new do
122
+ rubys3_client = Aws::S3::Client.new
123
+
124
+ # Ensure logs bucket exists
125
+ begin
126
+ rubys3_client.head_bucket(bucket: 'logs')
127
+ rescue Aws::S3::Errors::NotFound
128
+ rubys3_client.create_bucket(bucket: 'logs')
129
+ end
130
+
131
+ # Write to S3 Bucket
132
+ File.open(filename, 'rb') do |read_file|
133
+ rubys3_client.put_object(bucket: 'logs', key: s3_key, body: read_file, metadata: metadata)
134
+ end
135
+ Logger.debug "logs/#{s3_key} written to S3"
136
+ ReducerModel.add_file(s3_key) # Record the new file for data reduction
137
+
138
+ File.delete(filename)
139
+ rescue => err
140
+ Logger.error("Error saving log file to bucket: #{filename}\n#{err.formatted}")
141
+ end
142
+ end
143
+
144
+ def self.ensure_public_bucket(bucket_name)
145
+ rubys3_client = Aws::S3::Client.new
146
+ begin
147
+ rubys3_client.head_bucket(bucket: bucket_name)
148
+ rescue Aws::S3::Errors::NotFound
149
+ rubys3_client.create_bucket(bucket: bucket_name)
150
+
151
+ policy = <<~EOL
152
+ {
153
+ "Version": "2012-10-17",
154
+ "Statement": [
155
+ {
156
+ "Action": [
157
+ "s3:GetBucketLocation",
158
+ "s3:ListBucket"
159
+ ],
160
+ "Effect": "Allow",
161
+ "Principal": {
162
+ "AWS": [
163
+ "*"
164
+ ]
165
+ },
166
+ "Resource": [
167
+ "arn:aws:s3:::#{bucket_name}"
168
+ ],
169
+ "Sid": ""
170
+ },
171
+ {
172
+ "Action": [
173
+ "s3:GetObject"
174
+ ],
175
+ "Effect": "Allow",
176
+ "Principal": {
177
+ "AWS": [
178
+ "*"
179
+ ]
180
+ },
181
+ "Resource": [
182
+ "arn:aws:s3:::#{bucket_name}/*"
183
+ ],
184
+ "Sid": ""
185
+ }
186
+ ]
187
+ }
188
+ EOL
189
+
190
+ rubys3_client.put_bucket_policy({ bucket: bucket_name, policy: policy })
191
+ end
192
+ end
193
+
194
+ def self.get_cache_control(filename)
195
+ # Allow caching for files that have a filename versioning strategy
196
+ has_version_number = /(-|_|\.)\d+(-|_|\.)\d+(-|_|\.)\d+\./.match(@filename)
197
+ has_content_hash = /\.[a-f0-9]{20}\./.match(@filename)
198
+ return nil if has_version_number or has_content_hash
199
+ return 'no-cache'
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,9 @@
1
+ require 'aws-sdk-s3'
2
+
3
+ Aws.config.update(
4
+ endpoint: ENV['OPENC3_S3_URL'] || (ENV['OPENC3_DEVEL'] ? 'http://127.0.0.1:9000' : 'http://openc3-minio:9000'),
5
+ access_key_id: ENV['OPENC3_MINIO_USERNAME'],
6
+ secret_access_key: ENV['OPENC3_MINIO_PASSWORD'],
7
+ force_path_style: true,
8
+ region: 'us-east-1'
9
+ )
@@ -0,0 +1,274 @@
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 'fileutils'
21
+ require 'tmpdir'
22
+ require 'openc3'
23
+ require 'openc3/utilities/s3'
24
+
25
+ class S3File
26
+ attr_reader :s3_path
27
+ attr_reader :local_path
28
+ attr_reader :reservation_count
29
+ attr_reader :size
30
+ attr_reader :error
31
+ attr_accessor :priority
32
+
33
+ def initialize(s3_path, size = 0, priority = 0)
34
+ @rubys3_client = Aws::S3::Client.new
35
+ begin
36
+ @rubys3_client.head_bucket(bucket: 'logs')
37
+ rescue Aws::S3::Errors::NotFound
38
+ @rubys3_client.create_bucket(bucket: 'logs')
39
+ end
40
+
41
+ @s3_path = s3_path
42
+ @local_path = nil
43
+ @reservation_count = 0
44
+ @size = size
45
+ @priority = priority
46
+ @error = nil
47
+ @mutex = Mutex.new
48
+ end
49
+
50
+ def retrieve
51
+ local_path = "#{S3FileCache.instance.cache_dir}/#{File.basename(@s3_path)}"
52
+ OpenC3::Logger.debug "Retrieving #{@s3_path} from logs bucket"
53
+ @rubys3_client.get_object(bucket: "logs", key: @s3_path, response_target: local_path)
54
+ if File.exist?(local_path)
55
+ @size = File.size(local_path)
56
+ @local_path = local_path
57
+ end
58
+ rescue => err
59
+ @error = err
60
+ OpenC3::Logger.error "Failed to retrieve #{@s3_path}\n#{err.formatted}"
61
+ raise err
62
+ end
63
+
64
+ def reserve
65
+ @mutex.synchronize do
66
+ @reservation_count += 1
67
+ end
68
+ end
69
+
70
+ def unreserve
71
+ @mutex.synchronize do
72
+ @reservation_count -= 1
73
+ delete() if @reservation_count <= 0
74
+ end
75
+ end
76
+
77
+ # private
78
+
79
+ def delete
80
+ if @local_path and File.exist?(local_path)
81
+ File.delete(@local_path)
82
+ @local_path = nil
83
+ end
84
+ end
85
+ end
86
+
87
+ class S3FileCollection
88
+ def initialize
89
+ @array = []
90
+ @mutex = Mutex.new
91
+ end
92
+
93
+ def add(s3_path, size, priority)
94
+ @mutex.synchronize do
95
+ @array.each do |file|
96
+ if file.s3_path == s3_path
97
+ file.priority = priority if priority < file.priority
98
+ @array.sort! {|a,b| a.priority <=> b.priority}
99
+ return file
100
+ end
101
+ end
102
+ file = S3File.new(s3_path, size, priority)
103
+ @array << file
104
+ @array.sort! {|a,b| a.priority <=> b.priority}
105
+ return file
106
+ end
107
+ end
108
+
109
+ def length
110
+ @array.length
111
+ end
112
+
113
+ def get(local_path)
114
+ @mutex.synchronize do
115
+ @array.each do |file|
116
+ return file if file.local_path == local_path
117
+ end
118
+ end
119
+ return nil
120
+ end
121
+
122
+ def get_next_to_retrieve
123
+ @mutex.synchronize do
124
+ @array.each do |file|
125
+ return file unless file.local_path
126
+ end
127
+ end
128
+ return nil
129
+ end
130
+
131
+ def current_disk_usage
132
+ @mutex.synchronize do
133
+ total_size = 0
134
+ @array.each do |file|
135
+ total_size += file.size if file.local_path
136
+ end
137
+ return total_size
138
+ end
139
+ end
140
+ end
141
+
142
+ class S3FileCache
143
+ MAX_DISK_USAGE = 20_000_000_000 # 20 GB
144
+ TIMESTAMP_FORMAT = "%Y%m%d%H%M%S%N" # TODO: get from different class?
145
+
146
+ attr_reader :cache_dir
147
+
148
+ @@instance = nil
149
+ @@mutex = Mutex.new
150
+
151
+ def self.instance
152
+ return @@instance if @@instance
153
+ @@mutex.synchronize do
154
+ @@instance ||= S3FileCache.new
155
+ end
156
+ @@instance
157
+ end
158
+
159
+ def initialize(name = 'default', max_disk_usage = MAX_DISK_USAGE)
160
+ @max_disk_usage = max_disk_usage
161
+
162
+ @rubys3_client = Aws::S3::Client.new
163
+ begin
164
+ @rubys3_client.head_bucket(bucket: 'logs')
165
+ rescue Aws::S3::Errors::NotFound
166
+ @rubys3_client.create_bucket(bucket: 'logs')
167
+ end
168
+
169
+ # Create local file cache location
170
+ @cache_dir = Dir.mktmpdir
171
+ FileUtils.mkdir_p(@cache_dir)
172
+ at_exit do
173
+ FileUtils.remove_dir(@cache_dir, true)
174
+ end
175
+
176
+ @cached_files = S3FileCollection.new
177
+
178
+ @thread = Thread.new do
179
+ while true
180
+ file = @cached_files.get_next_to_retrieve
181
+ # OpenC3::Logger.debug "Next file: #{file}"
182
+ if file and (file.size + @cached_files.current_disk_usage()) <= @max_disk_usage
183
+ begin
184
+ file.retrieve
185
+ rescue
186
+ # Will be automatically retried
187
+ end
188
+ else
189
+ sleep(1)
190
+ end
191
+ end
192
+ rescue => err
193
+ OpenC3::Logger.error "S3FileCache thread unexpectedly died\n#{err.formatted}"
194
+ end
195
+ end
196
+
197
+ def reserve_file(cmd_or_tlm, target_name, packet_name, start_time_nsec, end_time_nsec, type = :DECOM, timeout = 60, scope:)
198
+ # OpenC3::Logger.debug "reserve_file #{cmd_or_tlm}:#{target_name}:#{packet_name} start:#{start_time_nsec / 1_000_000_000} end:#{end_time_nsec / 1_000_000_000} type:#{type} timeout:#{timeout}"
199
+ # Get List of Files from S3
200
+ total_resp = []
201
+ token = nil
202
+ dates = []
203
+ cur_date = Time.at(start_time_nsec / Time::NSEC_PER_SECOND).beginning_of_day
204
+ end_date = Time.at(end_time_nsec / Time::NSEC_PER_SECOND).beginning_of_day
205
+ cur_date -= 1.day # start looking in the folder for the day before because log files can span across midnight
206
+ while cur_date <= end_date
207
+ dates << cur_date.strftime("%Y%m%d")
208
+ cur_date += 1.day
209
+ end
210
+ prefixes = []
211
+ dates.each do |date|
212
+ while true
213
+ prefixes << "#{scope}/#{type.to_s.downcase}_logs/#{cmd_or_tlm.to_s.downcase}/#{target_name}/#{packet_name}/#{date}"
214
+ resp = @rubys3_client.list_objects_v2({
215
+ bucket: "logs",
216
+ max_keys: 1000,
217
+ prefix: prefixes[-1],
218
+ continuation_token: token
219
+ })
220
+ total_resp.concat(resp.contents)
221
+ break unless resp.is_truncated
222
+ token = resp.next_continuation_token
223
+ end
224
+ end
225
+
226
+ # Add to needed files
227
+ files = []
228
+ total_resp.each_with_index do |item, index|
229
+ s3_path = item.key
230
+ if file_in_time_range(s3_path, start_time_nsec, end_time_nsec)
231
+ file = @cached_files.add(s3_path, item.size, index)
232
+ files << file
233
+ end
234
+ end
235
+
236
+ # Wait for first file retrieval
237
+ if files.length > 0
238
+ wait_start = Time.now
239
+ file = files[0]
240
+ file.reserve
241
+ while (Time.now - wait_start) < timeout
242
+ return file.local_path if file.local_path
243
+ sleep(1)
244
+ end
245
+ # Remove reservations if we timeout
246
+ file.unreserve
247
+ else
248
+ OpenC3::Logger.info "No files found for #{prefixes}"
249
+ end
250
+
251
+ return nil
252
+ end
253
+
254
+ def unreserve_file(filename)
255
+ @@mutex.synchronize do
256
+ file = @cached_files.get(filename)
257
+ file.unreserve if file
258
+ end
259
+ end
260
+
261
+ # private
262
+
263
+ def file_in_time_range(s3_path, start_time_nsec, end_time_nsec)
264
+ basename = File.basename(s3_path)
265
+ file_start_timestamp, file_end_timestamp, other = basename.split("__")
266
+ file_start_time_nsec = DateTime.strptime(file_start_timestamp, TIMESTAMP_FORMAT).to_f * Time::NSEC_PER_SECOND
267
+ file_end_time_nsec = DateTime.strptime(file_end_timestamp, TIMESTAMP_FORMAT).to_f * Time::NSEC_PER_SECOND
268
+ if (start_time_nsec < file_end_time_nsec) and (end_time_nsec >= file_start_time_nsec)
269
+ return true
270
+ else
271
+ return false
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,117 @@
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/packets/packet'
21
+ require 'openc3/packets/structure'
22
+ require 'openc3/system/system'
23
+
24
+ module OpenC3
25
+ class Packet < Structure
26
+ attr_accessor :packet_rate
27
+ end
28
+
29
+ # Base class for all virtual OpenC3 targets which must be implemented by
30
+ # a subclass. Provides a framework and helper methods to implement a
31
+ # virtual target which can cycle telemetry values and emit telemetry
32
+ # packets.
33
+ class SimulatedTarget
34
+ attr_accessor :tlm_packets
35
+
36
+ def initialize(target_name)
37
+ @tlm_packets = {}
38
+
39
+ # Generate copy of telemetry packets for this target
40
+ System.telemetry.packets(target_name).each do |name, packet|
41
+ @tlm_packets[name] = packet.clone
42
+ @tlm_packets[name].enable_method_missing
43
+ end
44
+
45
+ # Set id values
46
+ @tlm_packets.each do |name, packet|
47
+ ids = packet.id_items
48
+ ids.each do |id|
49
+ packet.public_send((id.name + '=').to_sym, id.id_value)
50
+ end
51
+ end
52
+
53
+ @current_cycle_delta = {}
54
+ end
55
+
56
+ def set_rates
57
+ raise "Error: set_rates must be implemented by subclass"
58
+ end
59
+
60
+ def write(packet)
61
+ raise "Error: write must be implemented by subclass"
62
+ end
63
+
64
+ def read(count_100hz, time)
65
+ raise "Error: read must be implemented by subclass"
66
+ end
67
+
68
+ def tick_period_seconds
69
+ return 0.01 # Override this method to optimize
70
+ end
71
+
72
+ def tick_increment
73
+ return 1 # Override this method to optimize
74
+ end
75
+
76
+ protected
77
+
78
+ def set_rate(packet_name, rate)
79
+ packet = @tlm_packets[packet_name.upcase]
80
+ packet.packet_rate = rate if packet
81
+ end
82
+
83
+ def get_pending_packets(count_100hz)
84
+ pending_packets = []
85
+
86
+ # Determine if packets are due to be sent and add to pending
87
+ @tlm_packets.each do |name, packet|
88
+ if packet.packet_rate
89
+ if (count_100hz % packet.packet_rate) == 0
90
+ pending_packets << packet
91
+ end
92
+ end
93
+ end
94
+
95
+ pending_packets
96
+ end
97
+
98
+ def cycle_tlm_item(packet, item_name, min, max, first_delta)
99
+ packet_name = packet.packet_name
100
+ @current_cycle_delta[packet_name] ||= {}
101
+ @current_cycle_delta[packet_name][item_name] ||= first_delta
102
+
103
+ current_delta = @current_cycle_delta[packet_name][item_name]
104
+ current_value = packet.read(item_name)
105
+ updated_value = current_value + current_delta
106
+ if updated_value < min
107
+ updated_value = min
108
+ @current_cycle_delta[packet_name][item_name] = -current_delta
109
+ elsif updated_value > max
110
+ updated_value = max
111
+ @current_cycle_delta[packet_name][item_name] = -current_delta
112
+ end
113
+ packet.write(item_name, updated_value)
114
+ updated_value
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,51 @@
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
+ # Allows for a breakable sleep implementation using the self-pipe trick
22
+ # See http://www.sitepoint.com/the-self-pipe-trick-explained/
23
+ class Sleeper
24
+ def initialize
25
+ @pipe_reader, @pipe_writer = IO.pipe
26
+ @readers = [@pipe_reader]
27
+ @canceled = false
28
+ end
29
+
30
+ # Breakable version of sleep
31
+ # @param seconds Number of seconds to sleep
32
+ # @return true if the sleep was broken by someone calling cancel
33
+ # otherwise returns false
34
+ def sleep(seconds)
35
+ read_ready, _ = IO.select(@readers, nil, nil, seconds)
36
+ if read_ready && read_ready.include?(@pipe_reader)
37
+ return true
38
+ else
39
+ return false
40
+ end
41
+ end
42
+
43
+ # Break sleeping - Once canceled a sleeper cannot be used again
44
+ def cancel
45
+ if !@canceled
46
+ @canceled = true
47
+ @pipe_writer.write('.')
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
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
+ autoload(:Store, "openc3/utilities/store_autoload.rb")
22
+ autoload(:EphemeralStore, "openc3/utilities/store_autoload.rb")
23
+ end