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,487 @@
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_config'
21
+ require 'openc3/ext/telemetry' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
22
+
23
+ module OpenC3
24
+ # Telemetry uses PacketConfig to parse the command and telemetry
25
+ # configuration files. It contains all the knowledge of which telemetry packets
26
+ # exist in the system and how to access them. This class is the API layer
27
+ # which other classes use to access telemetry.
28
+ #
29
+ # This should not be confused with the Api module which implements the JSON
30
+ # API that is used by tools when accessing the Server. The Api module always
31
+ # provides Ruby primatives where the Telemetry class can return actual
32
+ # Packet or PacketItem objects. While there are some overlapping methods between
33
+ # the two, these are separate interfaces into the system.
34
+ class Telemetry
35
+ attr_accessor :config
36
+
37
+ LATEST_PACKET_NAME = 'LATEST'.freeze
38
+
39
+ # @param config [PacketConfig] Packet configuration to use to access the
40
+ # telemetry
41
+ def initialize(config)
42
+ @config = config
43
+ end
44
+
45
+ # (see PacketConfig#warnings)
46
+ def warnings
47
+ return @config.warnings
48
+ end
49
+
50
+ # @return [Array<String>] The telemetry target names (excluding UNKNOWN)
51
+ def target_names
52
+ result = @config.telemetry.keys.sort
53
+ result.delete('UNKNOWN'.freeze)
54
+ return result
55
+ end
56
+
57
+ if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
58
+ # @param target_name [String] The target name
59
+ # @return [Hash<packet_name=>Packet>] Hash of the telemetry packets for the given
60
+ # target name keyed by the packet name
61
+ def packets(target_name)
62
+ upcase_target_name = target_name.to_s.upcase
63
+ target_packets = @config.telemetry[upcase_target_name]
64
+ raise "Telemetry target '#{upcase_target_name}' does not exist" unless target_packets
65
+
66
+ target_packets
67
+ end
68
+
69
+ # @param target_name [String] The target name
70
+ # @param packet_name [String] The packet name. Must be a defined packet name
71
+ # and not 'LATEST'.
72
+ # @return [Packet] The telemetry packet for the given target and packet name
73
+ def packet(target_name, packet_name)
74
+ target_packets = packets(target_name)
75
+ upcase_packet_name = packet_name.to_s.upcase
76
+ packet = target_packets[upcase_packet_name]
77
+ unless packet
78
+ upcase_target_name = target_name.to_s.upcase
79
+ raise "Telemetry packet '#{upcase_target_name} #{upcase_packet_name}' does not exist"
80
+ end
81
+ packet
82
+ end
83
+
84
+ # @param target_name (see #packet)
85
+ # @param packet_name [String] The packet name. 'LATEST' can also be given
86
+ # to specify the last received (or defined if no packets have been
87
+ # received) packet within the given target that contains the
88
+ # item_name.
89
+ # @param item_name [String] The item name
90
+ # @return [Packet, PacketItem] The packet and the packet item
91
+ def packet_and_item(target_name, packet_name, item_name)
92
+ upcase_packet_name = packet_name.to_s.upcase
93
+ if upcase_packet_name == "LATEST".freeze
94
+ return_packet = newest_packet(target_name, item_name)
95
+ else
96
+ return_packet = packet(target_name, packet_name)
97
+ end
98
+ item = return_packet.get_item(item_name)
99
+ return [return_packet, item]
100
+ end
101
+
102
+ # Return a telemetry value from a packet.
103
+ #
104
+ # @param target_name (see #packet_and_item)
105
+ # @param packet_name (see #packet_and_item)
106
+ # @param item_name (see #packet_and_item)
107
+ # @param value_type [Symbol] How to convert the item before returning.
108
+ # Must be one of {Packet::VALUE_TYPES}
109
+ # @return The value. :FORMATTED and :WITH_UNITS values are always returned
110
+ # as Strings. :RAW values will match their data_type. :CONVERTED values
111
+ # can be any type.
112
+ def value(target_name, packet_name, item_name, value_type = :CONVERTED)
113
+ packet, _ = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
114
+ return packet.read(item_name, value_type)
115
+ end
116
+
117
+ # Reads the specified list of items and returns their values and limits
118
+ # state.
119
+ #
120
+ # @param item_array [Array<Array(String String String)>] An array
121
+ # consisting of [target name, packet name, item name]
122
+ # @param value_types [Symbol|Array<Symbol>] How to convert the items before
123
+ # returning. A single symbol of {Packet::VALUE_TYPES}
124
+ # can be passed which will convert all items the same way. Or
125
+ # an array of symbols can be passed to control how each item is
126
+ # converted.
127
+ # @return [Array, Array, Array] The first array contains the item values and the
128
+ # second their limits state, and the third their limits settings which includes
129
+ # the red, yellow, and green (if given) limits values.
130
+ def values_and_limits_states(item_array, value_types = :CONVERTED)
131
+ items = []
132
+
133
+ # Verify item_array is a nested array
134
+ raise(ArgumentError, "item_array must be a nested array consisting of [[tgt,pkt,item],[tgt,pkt,item],...]") unless Array === item_array[0]
135
+
136
+ states = []
137
+ settings = []
138
+ limits_set = System.limits_set
139
+
140
+ raise(ArgumentError, "Passed #{item_array.length} items but only #{value_types.length} value types") if (Array === value_types) and item_array.length != value_types.length
141
+
142
+ value_type = value_types.intern unless Array === value_types
143
+ item_array.length.times do |index|
144
+ entry = item_array[index]
145
+ target_name = entry[0]
146
+ packet_name = entry[1]
147
+ item_name = entry[2]
148
+ value_type = value_types[index].intern if Array === value_types
149
+
150
+ packet, item = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
151
+ items << packet.read(item_name, value_type)
152
+ limits = item.limits
153
+ states << limits.state
154
+ limits_values = limits.values
155
+ if limits_values
156
+ limits_settings = limits_values[limits_set]
157
+ else
158
+ limits_settings = nil
159
+ end
160
+ settings << limits_settings
161
+ end
162
+
163
+ return [items, states, settings]
164
+ end
165
+ end
166
+
167
+ # @param target_name (see #packet)
168
+ # @param packet_name (see #packet)
169
+ # @return [Array<PacketItem>] The telemetry items for the given target and packet name
170
+ def items(target_name, packet_name)
171
+ return packet(target_name, packet_name).sorted_items
172
+ end
173
+
174
+ # @param target_name (see #packet)
175
+ # @param packet_name (see #packet) The packet name. LATEST is supported.
176
+ # @return [Array<PacketItem>] The telemetry item names for the given target and packet name
177
+ def item_names(target_name, packet_name)
178
+ if LATEST_PACKET_NAME.casecmp(packet_name).zero?
179
+ target_upcase = target_name.to_s.upcase
180
+ target_latest_data = @config.latest_data[target_upcase]
181
+ raise "Telemetry Target '#{target_upcase}' does not exist" unless target_latest_data
182
+
183
+ item_names = target_latest_data.keys
184
+ else
185
+ tlm_packet = packet(target_name, packet_name)
186
+ item_names = []
187
+ tlm_packet.sorted_items.each { |item| item_names << item.name }
188
+ end
189
+ item_names
190
+ end
191
+
192
+ # Set a telemetry value in a packet.
193
+ #
194
+ # @param target_name (see #packet_and_item)
195
+ # @param packet_name (see #packet_and_item)
196
+ # @param item_name (see #packet_and_item)
197
+ # @param value The value to set in the packet
198
+ # @param value_type (see #tlm)
199
+ def set_value(target_name, packet_name, item_name, value, value_type = :CONVERTED)
200
+ packet, _ = packet_and_item(target_name, packet_name, item_name)
201
+ packet.write(item_name, value, value_type)
202
+ end
203
+
204
+ # @param target_name (see #packet_and_item)
205
+ # @param item_name (see #packet_and_item)
206
+ # @return [Array<Packet>] The latest (most recently arrived) packets with
207
+ # the specified target and item.
208
+ def latest_packets(target_name, item_name)
209
+ target_upcase = target_name.to_s.upcase
210
+ item_upcase = item_name.to_s.upcase
211
+ target_latest_data = @config.latest_data[target_upcase]
212
+ raise "Telemetry target '#{target_upcase}' does not exist" unless target_latest_data
213
+
214
+ packets = @config.latest_data[target_upcase][item_upcase]
215
+ raise "Telemetry item '#{target_upcase} #{LATEST_PACKET_NAME} #{item_upcase}' does not exist" unless packets
216
+
217
+ return packets
218
+ end
219
+
220
+ # @param target_name (see #packet_and_item)
221
+ # @param item_name (see #packet_and_item)
222
+ # @return [Packet] The packet with the most recent timestamp that contains
223
+ # the specified target and item.
224
+ def newest_packet(target_name, item_name)
225
+ # Handle LATEST_PACKET_NAME - Lookup packets for this target/item
226
+ packets = latest_packets(target_name, item_name)
227
+
228
+ # Find packet with newest timestamp
229
+ newest_packet = nil
230
+ newest_received_time = nil
231
+ packets.each do |packet|
232
+ received_time = packet.received_time
233
+ if newest_received_time
234
+ # See if the received time from this packet is newer.
235
+ # Having the >= makes this method return the last defined packet
236
+ # whether the timestamps are both nil or both equal.
237
+ if received_time and received_time >= newest_received_time
238
+ newest_packet = packet
239
+ newest_received_time = newest_packet.received_time
240
+ end
241
+ else
242
+ # No received time yet so take this packet
243
+ newest_packet = packet
244
+ newest_received_time = newest_packet.received_time
245
+ end
246
+ end
247
+ return newest_packet
248
+ end
249
+
250
+ # Identifies an unknown buffer of data as a defined packet and sets the
251
+ # packet's data to the given buffer. Identifying a packet uses the fields
252
+ # marked as ID_ITEM to identify if the buffer passed represents the
253
+ # packet defined. Incorrectly sized buffers are still processed but an
254
+ # error is logged.
255
+ #
256
+ # Note: This affects all subsequent requests for the packet (for example
257
+ # using packet) which is why the method is marked with a bang!
258
+ #
259
+ # @param packet_data [String] The binary packet data buffer
260
+ # @param target_names [Array<String>] List of target names to limit the search. The
261
+ # default value of nil means to search all known targets.
262
+ # @return [Packet] The identified packet with its data set to the given
263
+ # packet_data buffer. Returns nil if no packet could be identified.
264
+ def identify!(packet_data, target_names = nil)
265
+ identified_packet = identify(packet_data, target_names)
266
+ identified_packet.buffer = packet_data if identified_packet
267
+ return identified_packet
268
+ end
269
+
270
+ # Finds a packet from the Current Value Table that matches the given data
271
+ # and returns it. Does not fill the packets buffer. Use identify! to update the CVT.
272
+ #
273
+ # @param packet_data [String] The binary packet data buffer
274
+ # @param target_names [Array<String>] List of target names to limit the search. The
275
+ # default value of nil means to search all known targets.
276
+ # @return [Packet] The identified packet, Returns nil if no packet could be identified.
277
+ def identify(packet_data, target_names = nil)
278
+ target_names = target_names() unless target_names
279
+
280
+ target_names.each do |target_name|
281
+ target_name = target_name.to_s.upcase
282
+
283
+ target_packets = nil
284
+ begin
285
+ target_packets = packets(target_name)
286
+ # puts target_packets.length
287
+ rescue RuntimeError
288
+ # No telemetry for this target
289
+ next
290
+ end
291
+
292
+ target = System.targets[target_name]
293
+ if target and target.tlm_unique_id_mode
294
+ # Iterate through the packets and see if any represent the buffer
295
+ target_packets.each do |packet_name, packet|
296
+ return packet if packet.identify?(packet_data)
297
+ end
298
+ else
299
+ # Do a hash lookup to quickly identify the packet
300
+ if target_packets.length > 0
301
+ packet = target_packets.first[1]
302
+ key = packet.read_id_values(packet_data)
303
+ hash = @config.tlm_id_value_hash[target_name]
304
+ identified_packet = hash[key]
305
+ identified_packet = hash['CATCHALL'.freeze] unless identified_packet
306
+ return identified_packet if identified_packet
307
+ end
308
+ end
309
+ end
310
+
311
+ return nil
312
+ end
313
+
314
+ def identify_and_define_packet(packet, target_names = nil)
315
+ if !packet.identified?
316
+ identified_packet = identify(packet.buffer(false), target_names)
317
+ return nil unless identified_packet
318
+
319
+ identified_packet = identified_packet.clone
320
+ identified_packet.buffer = packet.buffer
321
+ identified_packet.received_time = packet.received_time
322
+ identified_packet.stored = packet.stored
323
+ identified_packet.extra = packet.extra
324
+ return identified_packet
325
+ end
326
+
327
+ if !packet.defined?
328
+ begin
329
+ identified_packet = self.packet(packet.target_name, packet.packet_name)
330
+ rescue RuntimeError
331
+ return nil
332
+ end
333
+ identified_packet = identified_packet.clone
334
+ identified_packet.buffer = packet.buffer
335
+ identified_packet.received_time = packet.received_time
336
+ identified_packet.stored = packet.stored
337
+ identified_packet.extra = packet.extra
338
+ return identified_packet
339
+ end
340
+
341
+ return packet
342
+ end
343
+
344
+ # Updates the specified packet with the given packet data. Raises an error
345
+ # if the packet could not be found.
346
+ #
347
+ # Note: This affects all subsequent requests for the packet which is why
348
+ # the method is marked with a bang!
349
+ #
350
+ # @param target_name (see #packet)
351
+ # @param packet_name (see #packet)
352
+ # @param packet_data (see #identify_tlm!)
353
+ # @return [Packet] The packet with its data set to the given packet_data
354
+ # buffer.
355
+ def update!(target_name, packet_name, packet_data)
356
+ identified_packet = packet(target_name, packet_name)
357
+ identified_packet.buffer = packet_data
358
+ return identified_packet
359
+ end
360
+
361
+ # Assigns a limits change callback to all telemetry packets
362
+ #
363
+ # @param limits_change_callback
364
+ def limits_change_callback=(limits_change_callback)
365
+ @config.telemetry.each do |target_name, packets|
366
+ packets.each do |packet_name, packet|
367
+ packet.limits_change_callback = limits_change_callback
368
+ end
369
+ end
370
+ end
371
+
372
+ # Iterates through all the telemetry packets and marks them stale if they
373
+ # haven't been received for over the System.staleness_seconds value.
374
+ #
375
+ # @return [Array(Packet)] Array of the stale packets
376
+ def check_stale
377
+ stale = []
378
+ time = Time.now.sys
379
+ @config.telemetry.each do |target_name, target_packets|
380
+ target_packets.each do |packet_name, packet|
381
+ if packet.received_time and (!packet.stale) and (time - packet.received_time > System.staleness_seconds)
382
+ packet.set_stale
383
+ stale << packet
384
+ end
385
+ end
386
+ end
387
+ stale
388
+ end
389
+
390
+ # @param with_limits_only [Boolean] Return only the stale packets
391
+ # that have limits items and thus affect the overall limits
392
+ # state of the system
393
+ # @param target [String] Target name or nil for all targets
394
+ # @return [Array(Packet)] Array of the stale packets
395
+ def stale(with_limits_only = false, target = nil)
396
+ if target && !target_names.include?(target)
397
+ raise "Telemetry target '#{target.upcase}' does not exist"
398
+ end
399
+
400
+ stale = []
401
+ @config.telemetry.each do |target_name, target_packets|
402
+ next if target && target != target_name
403
+ next if target_name == 'UNKNOWN'
404
+
405
+ target_packets.each do |packet_name, packet|
406
+ if packet.stale
407
+ next if with_limits_only && packet.limits_items.empty?
408
+
409
+ stale << packet
410
+ end
411
+ end
412
+ end
413
+ stale
414
+ end
415
+
416
+ # Clears the received_count value on every packet in every target
417
+ def clear_counters
418
+ @config.telemetry.each do |target_name, target_packets|
419
+ target_packets.each do |packet_name, packet|
420
+ packet.received_count = 0
421
+ end
422
+ end
423
+ end
424
+
425
+ # Resets metadata on every packet in every target
426
+ def reset
427
+ @config.telemetry.each do |target_name, target_packets|
428
+ target_packets.each do |packet_name, packet|
429
+ packet.reset
430
+ end
431
+ end
432
+ end
433
+
434
+ # Returns the first non-hidden packet
435
+ def first_non_hidden
436
+ @config.telemetry.each do |target_name, target_packets|
437
+ next if target_name == 'UNKNOWN'
438
+
439
+ target_packets.each do |packet_name, packet|
440
+ return packet unless packet.hidden
441
+ end
442
+ end
443
+ nil
444
+ end
445
+
446
+ # Returns an array with a "TARGET_NAME PACKET_NAME ITEM_NAME" string for every item in the system
447
+ def all_item_strings(include_hidden = false, splash = nil)
448
+ strings = []
449
+ tnames = target_names()
450
+ total = tnames.length.to_f
451
+ tnames.each_with_index do |target_name, index|
452
+ if splash
453
+ splash.message = "Processing #{target_name} telemetry"
454
+ splash.progress = index / total
455
+ end
456
+
457
+ # Note: System only has declared target structures but telemetry may have more
458
+ system_target = System.targets[target_name]
459
+ if system_target
460
+ ignored_items = system_target.ignored_items
461
+ else
462
+ ignored_items = []
463
+ end
464
+
465
+ packets(target_name).each do |packet_name, packet|
466
+ # We don't audit against hidden or disabled packets
467
+ next if !include_hidden and (packet.hidden || packet.disabled)
468
+
469
+ packet.items.each_key do |item_name|
470
+ # Skip ignored items
471
+ next if !include_hidden and ignored_items.include? item_name
472
+
473
+ strings << "#{target_name} #{packet_name} #{item_name}"
474
+ end
475
+ end
476
+ end
477
+ strings
478
+ end
479
+
480
+ # @return [Hash{String=>Hash{String=>Packet}}] Hash of all the telemetry
481
+ # packets keyed by the target name. The value is another hash keyed by the
482
+ # packet name returning the packet.
483
+ def all
484
+ @config.telemetry
485
+ end
486
+ end # class Telemetry
487
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+
16
+ # Modified by OpenC3, Inc.
17
+ # All changes Copyright 2022, OpenC3, Inc.
18
+ # All Rights Reserved
19
+
20
+ module OpenC3
21
+ class Processor
22
+ # @return [Symbol] The value type for the processor
23
+ attr_reader :value_type
24
+
25
+ # @return [String] The processor name
26
+ attr_reader :name
27
+
28
+ # @return [Hash] The results of the most recent execution of the processor
29
+ attr_accessor :results
30
+
31
+ # Create a new Processor
32
+ # @param value_type [Symbol or String] the value type to process
33
+ def initialize(value_type = :CONVERTED)
34
+ @name = self.class.to_s.upcase
35
+ value_type = value_type.to_s.upcase.intern
36
+ @value_type = value_type
37
+ raise ArgumentError, "value_type must be RAW, CONVERTED, FORMATTED, or WITH_UNITS. Is #{@value_type}" unless Packet::VALUE_TYPES.include?(@value_type)
38
+
39
+ @results = {}
40
+ end
41
+
42
+ def name=(name)
43
+ @name = name.to_s.upcase
44
+ end
45
+
46
+ # Perform processing on the packet.
47
+ #
48
+ # @param packet [Packet] The packet which contains the value. This can
49
+ # be useful to reach into the packet and use other values in the
50
+ # conversion.
51
+ # @param buffer [String] The packet buffer
52
+ # @return The processed result
53
+ def call(packet, buffer)
54
+ raise "call method must be defined by subclass"
55
+ end
56
+
57
+ # @return [String] The processor class
58
+ def to_s
59
+ self.class.to_s.split('::')[-1]
60
+ end
61
+
62
+ # Reset any state
63
+ def reset
64
+ # By default do nothing
65
+ end
66
+
67
+ # Make a light weight clone of this processor. This only creates a new hash of results
68
+ #
69
+ # @return [Processor] A copy of the processor with a new hash of results
70
+ def clone
71
+ processor = super()
72
+ processor.results = processor.results.clone
73
+ processor
74
+ end
75
+ alias dup clone
76
+
77
+ # Convert to configuration file string
78
+ def to_config
79
+ " PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@value_type}\n"
80
+ end
81
+
82
+ def as_json(*a)
83
+ { 'name' => @name, 'class' => self.class.name, 'params' => [@value_type.to_s] }
84
+ end
85
+ end # class Processor
86
+ end
@@ -0,0 +1,82 @@
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/processors/processor'
21
+
22
+ module OpenC3
23
+ class StatisticsProcessor < Processor
24
+ # @return [Array] The set of samples stored by the processor
25
+ attr_accessor :samples
26
+
27
+ # @param item_name [String] The name of the item to gather statistics on
28
+ # @param samples_to_average [Integer] The number of samples to store for calculations
29
+ # @param value_type #See Processor::initialize
30
+ def initialize(item_name, samples_to_average, value_type = :CONVERTED)
31
+ super(value_type)
32
+ @item_name = item_name.to_s.upcase
33
+ @samples_to_average = Integer(samples_to_average)
34
+ reset()
35
+ end
36
+
37
+ # Run statistics on the item
38
+ #
39
+ # See Processor#call
40
+ def call(packet, buffer)
41
+ value = packet.read(@item_name, @value_type, buffer)
42
+ # Don't process NaN or Infinite values
43
+ return if value.to_f.nan? || value.to_f.infinite?
44
+
45
+ @samples << value
46
+ @samples = @samples[-@samples_to_average..-1] if @samples.length > @samples_to_average
47
+ mean, stddev = Math.stddev_sample(@samples)
48
+ @results[:MAX] = @samples.max
49
+ @results[:MIN] = @samples.min
50
+ @results[:MEAN] = mean
51
+ @results[:STDDEV] = stddev
52
+ end
53
+
54
+ # Reset any state
55
+ def reset
56
+ @samples = []
57
+ @results[:MAX] = nil
58
+ @results[:MIN] = nil
59
+ @results[:MEAN] = nil
60
+ @results[:STDDEV] = nil
61
+ end
62
+
63
+ # Make a light weight clone of this processor. This only creates a new hash of results
64
+ #
65
+ # @return [Processor] A copy of the processor with a new hash of results
66
+ def clone
67
+ processor = super()
68
+ processor.samples = processor.samples.clone
69
+ processor
70
+ end
71
+ alias dup clone
72
+
73
+ # Convert to configuration file string
74
+ def to_config
75
+ " PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@item_name} #{@samples_to_average} #{@value_type}\n"
76
+ end
77
+
78
+ def as_json(*a)
79
+ { 'name' => @name, 'class' => self.class.name, 'params' => [@item_name, @samples_to_average, @value_type.to_s] }
80
+ end
81
+ end # class StatisticsProcessor
82
+ end