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,313 @@
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/microservices/microservice'
21
+ require 'openc3/topics/topic'
22
+ require 'openc3/packets/json_packet'
23
+ require 'openc3/utilities/s3_file_cache'
24
+ require 'openc3/models/reducer_model'
25
+ require 'rufus-scheduler'
26
+
27
+ module OpenC3
28
+ class ReducerMicroservice < Microservice
29
+ MINUTE_METRIC = 'reducer_minute_duration'
30
+ HOUR_METRIC = 'reducer_hour_duration'
31
+ DAY_METRIC = 'reducer_day_duration'
32
+
33
+ # How long to wait for any currently running jobs to complete before killing them
34
+ SHUTDOWN_DELAY_SECS = 5
35
+ MINUTE_ENTRY_SECS = 60
36
+ MINUTE_FILE_SECS = 3600
37
+ HOUR_ENTRY_SECS = 3600
38
+ HOUR_FILE_SECS = 3600 * 24
39
+ DAY_ENTRY_SECS = 3600 * 24
40
+ DAY_FILE_SECS = 3600 * 24 * 30
41
+
42
+ # @param name [String] Microservice name formatted as <SCOPE>__REDUCER__<TARGET>
43
+ # where <SCOPE> and <TARGET> are variables representing the scope name and target name
44
+ def initialize(name)
45
+ super(name, is_plugin: false)
46
+ @target_name = name.split('__')[-1]
47
+ @packet_logs = {}
48
+ end
49
+
50
+ def run
51
+ # Note it takes several seconds to create the scheduler
52
+ @scheduler = Rufus::Scheduler.new
53
+ # Run every minute
54
+ @scheduler.cron '* * * * *', first: :now do
55
+ reduce_minute
56
+ end
57
+ # Run every 15 minutes
58
+ @scheduler.cron '*/15 * * * *', first: :now do
59
+ reduce_hour
60
+ end
61
+ # Run hourly at minute 5 to allow the hour reducer to finish
62
+ @scheduler.cron '5 * * * *', first: :now do
63
+ reduce_day
64
+ end
65
+
66
+ # Let the current thread join the scheduler thread and
67
+ # block until shutdown is called
68
+ @scheduler.join
69
+ end
70
+
71
+ def shutdown
72
+ @scheduler.shutdown(wait: SHUTDOWN_DELAY_SECS) if @scheduler
73
+
74
+ # Make sure all the existing logs are properly closed down
75
+ @packet_logs.each do |name, log|
76
+ log.shutdown
77
+ end
78
+ super()
79
+ end
80
+
81
+ def metric(name)
82
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
83
+ yield
84
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
85
+ @metric.add_sample(
86
+ name: name,
87
+ value: elapsed,
88
+ labels: {
89
+ 'target' => @target_name,
90
+ },
91
+ )
92
+ end
93
+
94
+ def reduce_minute
95
+ metric(MINUTE_METRIC) do
96
+ ReducerModel
97
+ .all_files(type: :DECOM, target: @target_name, scope: @scope)
98
+ .each do |file|
99
+ process_file(file, 'minute', MINUTE_ENTRY_SECS, MINUTE_FILE_SECS)
100
+ ReducerModel.rm_file(file)
101
+ end
102
+ end
103
+ end
104
+
105
+ def reduce_hour
106
+ metric(HOUR_METRIC) do
107
+ ReducerModel
108
+ .all_files(type: :MINUTE, target: @target_name, scope: @scope)
109
+ .each do |file|
110
+ process_file(file, 'hour', HOUR_ENTRY_SECS, HOUR_FILE_SECS)
111
+ ReducerModel.rm_file(file)
112
+ end
113
+ end
114
+ end
115
+
116
+ def reduce_day
117
+ metric(DAY_METRIC) do
118
+ ReducerModel
119
+ .all_files(type: :HOUR, target: @target_name, scope: @scope)
120
+ .each do |file|
121
+ process_file(file, 'day', DAY_ENTRY_SECS, DAY_FILE_SECS)
122
+ ReducerModel.rm_file(file)
123
+ end
124
+ end
125
+ end
126
+
127
+ def process_file(filename, type, entry_seconds, file_seconds)
128
+ file = S3File.new(filename)
129
+ file.retrieve
130
+
131
+ # Determine if we already have a PacketLogWriter created
132
+ start_time, end_time, scope, target_name, packet_name, _ =
133
+ filename.split('__')
134
+ if @target_name != target_name
135
+ raise "Target name in file #{filename} does not match microservice target name #{@target_name}"
136
+ end
137
+ plw = @packet_logs["#{scope}__#{target_name}__#{packet_name}__#{type}"]
138
+ unless plw
139
+ # Create a new PacketLogWriter for this reduced data
140
+ # e.g. DEFAULT/reduced_minute_logs/tlm/INST/HEALTH_STATUS/20220101/
141
+ # 20220101204857274290500__20220101205857276524900__DEFAULT__INST__HEALTH_STATUS__reduced__minute.bin
142
+ remote_log_directory = "#{scope}/reduced_#{type}_logs/tlm/#{target_name}/#{packet_name}"
143
+ rt_label = "#{scope}__#{target_name}__#{packet_name}__reduced__#{type}"
144
+ plw = PacketLogWriter.new(remote_log_directory, rt_label)
145
+ @packet_logs["#{scope}__#{target_name}__#{packet_name}__#{type}"] = plw
146
+ end
147
+
148
+ reduced = {}
149
+ data_keys = nil
150
+ entry_time = nil
151
+ current_time = nil
152
+ previous_time = nil
153
+ plr = OpenC3::PacketLogReader.new
154
+ plr.each(file.local_path) do |packet|
155
+ # Ignore anything except numbers like STRING or BLOCK items
156
+ data = packet.read_all(:RAW).select { |key, value| value.is_a?(Numeric) }
157
+ converted_data = packet.read_all(:CONVERTED).select { |key, value| value.is_a?(Numeric) }
158
+ # Merge in the converted data which overwrites the raw
159
+ data.merge!(converted_data)
160
+
161
+ previous_time = current_time
162
+ current_time = packet.packet_time.to_f
163
+ entry_time ||= current_time
164
+ data_keys ||= data.keys
165
+
166
+ # Determine if we've rolled over a entry boundary
167
+ # We have to use current % entry_seconds < previous % entry_seconds because
168
+ # we don't know the data rates. We also have to check for current - previous >= entry_seconds
169
+ # in case the data rate is so slow we don't have multiple samples per entry
170
+ if previous_time &&
171
+ (
172
+ (current_time % entry_seconds < previous_time % entry_seconds) ||
173
+ (current_time - previous_time >= entry_seconds)
174
+ )
175
+ Logger.debug("Reducer: Roll over entry boundary cur_time:#{current_time}")
176
+
177
+ reduce(type, data_keys, reduced)
178
+ plw.write(
179
+ :JSON_PACKET,
180
+ :TLM,
181
+ target_name,
182
+ packet_name,
183
+ entry_time * Time::NSEC_PER_SECOND,
184
+ false,
185
+ JSON.generate(reduced.as_json(:allow_nan => true)),
186
+ )
187
+ # Reset all our sample variables
188
+ entry_time = current_time
189
+ reduced = {}
190
+
191
+ # Check to see if we should start a new log file
192
+ # We compare the current entry_time to see if it will push us over
193
+ if plw.first_time &&
194
+ (entry_time - plw.first_time.to_f) >= file_seconds
195
+ Logger.debug("Reducer: (1) start new file! old filename: #{plw.filename}")
196
+ plw.start_new_file # Automatically closes the current file
197
+ end
198
+ end
199
+
200
+ # Update statistics for this packet's values
201
+ data.each do |key, value|
202
+ if type == 'minute'
203
+ reduced["#{key}__VALS"] ||= []
204
+ reduced["#{key}__VALS"] << value
205
+ reduced["#{key}_MIN"] ||= value
206
+ reduced["#{key}_MIN"] = value if value < reduced["#{key}_MIN"]
207
+ reduced["#{key}_MAX"] ||= value
208
+ reduced["#{key}_MAX"] = value if value > reduced["#{key}_MAX"]
209
+ else
210
+ reduced[key] ||= value
211
+ reduced[key] = value if key.match(/_MIN$/) && value < reduced[key]
212
+ reduced[key] = value if key.match(/_MAX$/) && value > reduced[key]
213
+ if key.match(/_AVG$/)
214
+ reduced["#{key}__VALS"] ||= []
215
+ reduced["#{key}__VALS"] << value
216
+ end
217
+ if key.match(/_STDDEV$/)
218
+ reduced["#{key}__VALS"] ||= []
219
+ reduced["#{key}__VALS"] << value
220
+ end
221
+ if key.match(/_SAMPLES$/)
222
+ reduced["#{key}__VALS"] ||= []
223
+ reduced["#{key}__VALS"] << value
224
+ end
225
+ end
226
+ end
227
+ end
228
+ file.delete # Remove the local copy
229
+
230
+ # See if this last entry should go in a new file
231
+ if plw.first_time &&
232
+ (entry_time - plw.first_time.to_f) >= file_seconds
233
+ Logger.debug("Reducer: (2) start new file! old filename: #{plw.filename}")
234
+ plw.start_new_file # Automatically closes the current file
235
+ end
236
+
237
+ # Write out the final data now that the file is done
238
+ reduce(type, data_keys, reduced)
239
+ plw.write(
240
+ :JSON_PACKET,
241
+ :TLM,
242
+ target_name,
243
+ packet_name,
244
+ entry_time * Time::NSEC_PER_SECOND,
245
+ false,
246
+ JSON.generate(reduced.as_json(:allow_nan => true)),
247
+ )
248
+ true
249
+ rescue => e
250
+ if file.local_path and File.exist?(file.local_path)
251
+ Logger.error("Reducer Error: #{filename}:#{File.size(file.local_path)} bytes: \n#{e.formatted}")
252
+ else
253
+ Logger.error("Reducer Error: #{filename}:(Not Retrieved): \n#{e.formatted}")
254
+ end
255
+ false
256
+ end
257
+
258
+ def reduce(type, data_keys, reduced)
259
+ # We've collected all the values so calculate the AVG and STDDEV
260
+ if type == 'minute'
261
+ data_keys.each do |key|
262
+ reduced["#{key}_SAMPLES"] = reduced["#{key}__VALS"].length
263
+ reduced["#{key}_AVG"], reduced["#{key}_STDDEV"] =
264
+ Math.stddev_population(reduced["#{key}__VALS"])
265
+
266
+ # Remove the raw values as they're only used for AVG / STDDEV calculation
267
+ reduced.delete("#{key}__VALS")
268
+ end
269
+ else
270
+ # Sort so we calculate the average first, then samples, then stddev
271
+ data_keys.sort.each do |key|
272
+ base_name = key.split('_')[0..-2].join('_')
273
+ case key
274
+ when /_AVG$/
275
+ weighted_sum = 0
276
+ samples = reduced["#{base_name}_SAMPLES__VALS"]
277
+ reduced["#{key}__VALS"].each_with_index do |val, i|
278
+ weighted_sum += (val * samples[i])
279
+ end
280
+ reduced[key] = weighted_sum / samples.sum
281
+ when /_SAMPLES$/
282
+ reduced[key] = reduced["#{base_name}_SAMPLES__VALS"].sum
283
+ when /_STDDEV$/
284
+ # Do the STDDEV calc last so we can use the previously calculated AVG
285
+ # See https://math.stackexchange.com/questions/1547141/aggregating-standard-deviation-to-a-summary-point
286
+ samples = reduced["#{base_name}_SAMPLES__VALS"]
287
+ avg = reduced["#{base_name}_AVG__VALS"]
288
+ s2 = 0
289
+ reduced["#{key}__VALS"].each_with_index do |val, i|
290
+ # puts "i:#{i} val:#{val} samples[i]:#{samples[i]} avg[i]:#{avg[i]}"
291
+ s2 += (samples[i] * avg[i]**2 + val**2)
292
+ end
293
+
294
+ # Note: For very large numbers with very small deviations this sqrt can fail.
295
+ # If so then just set the stddev to 0.
296
+ begin
297
+ reduced[key] =
298
+ Math.sqrt(s2 / samples.sum - reduced["#{base_name}_AVG"])
299
+ rescue Exception
300
+ reduced[key] = 0.0
301
+ end
302
+ end
303
+ end
304
+ data_keys.each do |key|
305
+ # Remove the raw values as they're only used for AVG / STDDEV calculation
306
+ reduced.delete("#{key}__VALS")
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
312
+
313
+ OpenC3::ReducerMicroservice.run if __FILE__ == $0
@@ -0,0 +1,44 @@
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/microservices/interface_microservice'
21
+
22
+ module OpenC3
23
+ class RouterMicroservice < InterfaceMicroservice
24
+ def handle_packet(packet)
25
+ @count += 1
26
+ RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
27
+ if !packet.identified?
28
+ # Need to identify so we can find the target
29
+ identified_packet = System.commands.identify(packet.buffer(false), @target_names)
30
+ packet = identified_packet if identified_packet
31
+ end
32
+
33
+ begin
34
+ RouterTopic.route_command(packet, @target_names, scope: @scope)
35
+ @count += 1
36
+ rescue Exception => err
37
+ @error = err
38
+ Logger.error "Error routing command from #{@interface.name}\n#{err.formatted}"
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ OpenC3::RouterMicroservice.run if __FILE__ == $0
@@ -0,0 +1,84 @@
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/microservices/microservice'
21
+ require 'openc3/topics/topic'
22
+
23
+ module OpenC3
24
+ class TextLogMicroservice < Microservice
25
+ def initialize(name)
26
+ super(name)
27
+ @config['options'].each do |option|
28
+ case option[0].upcase
29
+ when 'CYCLE_TIME' # Maximum time between log files
30
+ @cycle_time = option[1].to_i
31
+ when 'CYCLE_SIZE' # Maximum size of a log file
32
+ @cycle_size = option[1].to_i
33
+ else
34
+ Logger.error("Unknown option passed to microservice #{@name}: #{option}")
35
+ end
36
+ end
37
+
38
+ # These settings limit the log file to 10 minutes or 50MB of data, whichever comes first
39
+ @cycle_time = 600 unless @cycle_time # 10 minutes
40
+ @cycle_size = 50_000_000 unless @cycle_size # ~50 MB
41
+ end
42
+
43
+ def run
44
+ tlws = setup_tlws
45
+ while true
46
+ break if @cancel_thread
47
+
48
+ Topic.read_topics(@topics) do |topic, msg_id, msg_hash, redis|
49
+ break if @cancel_thread
50
+
51
+ log_data(tlws, topic, msg_id, msg_hash, redis)
52
+ end
53
+ end
54
+ end
55
+
56
+ def setup_tlws
57
+ tlws = {}
58
+ @topics.each do |topic|
59
+ topic_split = topic.gsub(/{|}/, '').split("__") # Remove the redis hashtag curly braces
60
+ scope = topic_split[0]
61
+ log_name = topic_split[1]
62
+ remote_log_directory = "#{scope}/text_logs/#{log_name}"
63
+ tlws[topic] = TextLogWriter.new(remote_log_directory, true, @cycle_time, @cycle_size, redis_topic: topic)
64
+ end
65
+ return tlws
66
+ end
67
+
68
+ def log_data(tlws, topic, msg_id, msg_hash, redis)
69
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
70
+ keys = msg_hash.keys
71
+ keys.delete("time")
72
+ entry = keys.reduce("") { |data, key| data + "#{key}: #{msg_hash[key]}\t" }
73
+ tlws[topic].write(msg_hash["time"].to_i, entry, msg_id)
74
+ @count += 1
75
+ diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
76
+ @metric.add_sample(name: "log_duration_seconds", value: diff, labels: {})
77
+ rescue => err
78
+ @error = err
79
+ Logger.error("#{@name} error: #{err.formatted}")
80
+ end
81
+ end
82
+ end
83
+
84
+ OpenC3::TextLogMicroservice.run if __FILE__ == $0