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,549 @@
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/top_level'
21
+ require 'openc3/ext/config_parser' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
22
+ require 'erb'
23
+
24
+ module OpenC3
25
+ # Reads OpenC3 style configuration data which consists of keywords followed
26
+ # by 0 or more comma delimited parameters. Parameters with spaces must be
27
+ # enclosed in quotes. Quotes should also be used to indicate a parameter is a
28
+ # string. Keywords are case-insensitive and will be returned in uppercase.
29
+ class ConfigParser
30
+ # @return [String] The current keyword being parsed
31
+ attr_accessor :keyword
32
+
33
+ # @return [Array<String>] The parameters found after the keyword
34
+ attr_accessor :parameters
35
+
36
+ # @return [String] The name of the configuration file being parsed. This
37
+ # will be an empty string if the parse_string class method is used.
38
+ attr_accessor :filename
39
+
40
+ # @return [String] The current line being parsed. This is the raw string
41
+ # which is useful when printing errors.
42
+ attr_accessor :line
43
+
44
+ # @return [Integer] The current line number being parsed.
45
+ # This will still be populated when using parse_string because lines
46
+ # still must be delimited by newline characters.
47
+ attr_accessor :line_number
48
+
49
+ # @return [String] The default URL to use in errors. The URL can still be
50
+ # overridden by directly passing it to the error method.
51
+ attr_accessor :url
52
+
53
+ # @see message_callback=
54
+ @@message_callback = nil
55
+
56
+ # @param message_callback [#call(String)] Callback method called with a
57
+ # String when various parsing events occur.
58
+ def self.message_callback=(message_callback)
59
+ @@message_callback = message_callback
60
+ end
61
+
62
+ # @see progress_callback=
63
+ @@progress_callback = nil
64
+
65
+ # @param progress_callback [#call(Float)] Callback method called with a
66
+ # Float (0.0 to 100.0) based on the amount of the io param that has
67
+ # currently been processed.
68
+ def self.progress_callback=(progress_callback)
69
+ @@progress_callback = progress_callback
70
+ end
71
+
72
+ # Holds the current splash screen
73
+ @@splash = nil
74
+
75
+ # @param splash [Splash::SplashDialogBox] Set the splash dialog box which
76
+ # will be updated with messages and progress.
77
+ def self.splash=(splash)
78
+ if splash
79
+ @@splash = splash
80
+ @@progress_callback = splash.progress_callback
81
+ @@message_callback = splash.message_callback
82
+ else
83
+ @@splash = nil
84
+ @@progress_callback = nil
85
+ @@message_callback = nil
86
+ end
87
+ end
88
+
89
+ # Returns the current splash screen if present
90
+ def self.splash
91
+ @@splash
92
+ end
93
+
94
+ # Regular expression used to break up an individual line into a keyword and
95
+ # comma delimited parameters. Handles parameters in single or double quotes.
96
+ PARSING_REGEX = %r{ (?:"(?:[^\\"]|\\.)*") | (?:'(?:[^\\']|\\.)*') | \S+ }x # "
97
+
98
+ # Error which gets raised by ConfigParser in #verify_num_parameters. This
99
+ # is also the error that classes using ConfigParser should raise when they
100
+ # encounter a configuration error.
101
+ class Error < StandardError
102
+ attr_reader :keyword, :parameters, :filename, :line, :line_number
103
+
104
+ # @return [String] The usage string representing how this keyword should
105
+ # be formatted.
106
+ attr_reader :usage
107
+
108
+ # @return [String] URL which points to usage documentation on the OpenC3
109
+ # Wiki.
110
+ attr_reader :url
111
+
112
+ # Create an Error with the specified Config data
113
+ #
114
+ # @param config_parser [ConfigParser] Instance of ConfigParser so Error
115
+ # has access to the ConfigParser attributes
116
+ # @param message [String] The error message which gets passed to the
117
+ # StandardError constructor
118
+ # @param usage [String] The usage string representing how this keyword should
119
+ # be formatted.
120
+ # @param url [String] URL which should point to usage information. By
121
+ # default this gets constructed to point to the generic configuration
122
+ # Guide on the OpenC3 Wiki.
123
+ def initialize(config_parser, message = "Configuration Error", usage = "", url = "")
124
+ if Error == message
125
+ super(message.message)
126
+ elsif Exception == message
127
+ super("#{message.class}:#{message.message}")
128
+ else
129
+ super(message)
130
+ end
131
+ @keyword = config_parser.keyword
132
+ @parameters = config_parser.parameters
133
+ @filename = config_parser.filename
134
+ @line = config_parser.line
135
+ @line_number = config_parser.line_number
136
+ @usage = usage
137
+ @url = url
138
+ end
139
+ end
140
+
141
+ # @param url [String] The url to link to in error messages
142
+ def initialize(url = "https:/openc3.com/docs/v5")
143
+ @url = url
144
+ end
145
+
146
+ # Creates an Error
147
+ #
148
+ # @param message [String] The string to set the Exception message to
149
+ # @param usage [String] The usage message
150
+ # @param url [String] Where to get help about this error
151
+ # @return [Error] The constructed error
152
+ def error(message, usage = "", url = @url)
153
+ return Error.new(self, message, usage, url)
154
+ end
155
+
156
+ # Called by the ERB template to render a partial
157
+ def render(template_name, options = {})
158
+ raise Error.new(self, "Partial name '#{template_name}' must begin with an underscore.") if File.basename(template_name)[0] != '_'
159
+
160
+ b = binding
161
+ if options[:locals]
162
+ options[:locals].each { |key, value| b.local_variable_set(key, value) }
163
+ end
164
+ # Assume the file is there. If not we raise a pretty obvious error
165
+ if File.expand_path(template_name) == template_name # absolute path
166
+ path = template_name
167
+ else # relative to the current @filename
168
+ path = File.join(File.dirname(@filename), template_name)
169
+ end
170
+ OpenC3.set_working_dir(File.dirname(path)) do
171
+ return ERB.new(File.read(path), trim_mode: "-").result(b)
172
+ end
173
+ end
174
+
175
+ # Processes a file and yields |config| to the given block
176
+ #
177
+ # @param filename [String] The full name and path of the configuration file
178
+ # @param yield_non_keyword_lines [Boolean] Whether to yield all lines including blank
179
+ # lines or comment lines.
180
+ # @param remove_quotes [Boolean] Whether to remove beginning and ending single
181
+ # or double quote characters from parameters.
182
+ # @param run_erb [Boolean] Whether or not to run ERB on the file
183
+ # @param variables [Hash] variables to pash to ERB context
184
+ # @param block [Block] The block to yield to
185
+ # @yieldparam keyword [String] The keyword in the current parsed line
186
+ # @yieldparam parameters [Array<String>] The parameters in the current parsed line
187
+ def parse_file(filename,
188
+ yield_non_keyword_lines = false,
189
+ remove_quotes = true,
190
+ run_erb = true,
191
+ variables = {},
192
+ &block)
193
+ raise Error.new(self, "Configuration file #{filename} does not exist.") unless filename && File.exist?(filename)
194
+
195
+ @filename = filename
196
+
197
+ # Create a temp file where we write the ERB parsed output
198
+ file = create_parsed_output_file(filename, run_erb, variables)
199
+ size = file.stat.size.to_f
200
+
201
+ # Callbacks for beginning of parsing
202
+ @@message_callback.call("Parsing #{size} bytes of #{filename}") if @@message_callback
203
+ @@progress_callback.call(0.0) if @@progress_callback
204
+
205
+ begin
206
+ # Loop through each line of the data
207
+ parse_loop(file,
208
+ yield_non_keyword_lines,
209
+ remove_quotes,
210
+ size,
211
+ PARSING_REGEX,
212
+ &block)
213
+ rescue Exception => e # Catch EVERYTHING so we can re-raise with additional info
214
+ raise e, "#{e}\n\nParsed output in #{file.path}", e.backtrace
215
+ ensure
216
+ file.close unless file.closed?
217
+ end
218
+ end
219
+
220
+ # Verifies the parameters in the config parameter have the specified
221
+ # number of parameter and raises an Error if not.
222
+ #
223
+ # @param [Integer] min_num_params The minimum number of parameters
224
+ # @param [Integer] max_num_params The maximum number of parameters. Pass
225
+ # nil to indicate there is no maximum number of parameters.
226
+ def verify_num_parameters(min_num_params, max_num_params, usage = "")
227
+ # This syntax works with 0 because each doesn't return any values
228
+ # for a backwards range
229
+ (1..min_num_params).each do |index|
230
+ # If the parameter is nil (0 based) then we have a problem
231
+ if @parameters[index - 1].nil?
232
+ raise Error.new(self, "Not enough parameters for #{@keyword}.", usage, @url)
233
+ end
234
+ end
235
+ # If they pass nil for max_params we don't check for a maximum number
236
+ if max_num_params && !@parameters[max_num_params].nil?
237
+ raise Error.new(self, "Too many parameters for #{@keyword}.", usage, @url)
238
+ end
239
+ end
240
+
241
+ # Verifies the indicated parameter in the config doesn't start or end
242
+ # with an underscore, doesn't contain a double underscore, doesn't contain
243
+ # spaces and doesn't start with a close bracket.
244
+ #
245
+ # @param [Integer] index The index of the parameter to check
246
+ def verify_parameter_naming(index, usage = "")
247
+ param = @parameters[index - 1]
248
+ if param.end_with? '_'
249
+ raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot end with an underscore ('_').", usage, @url)
250
+ end
251
+ if param.include? '__'
252
+ raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot contain a double underscore ('__').", usage, @url)
253
+ end
254
+ if param.include? ' '
255
+ raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot contain a space (' ').", usage, @url)
256
+ end
257
+ if param.start_with?('}')
258
+ raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot start with a close bracket ('}').", usage, @url)
259
+ end
260
+ end
261
+
262
+ # Converts a String containing '', 'NIL' or 'NULL' to nil Ruby primitive.
263
+ # All other arguments are simply returned.
264
+ #
265
+ # @param value [Object]
266
+ # @return [nil|Object]
267
+ def self.handle_nil(value)
268
+ if String === value
269
+ case value.upcase
270
+ when '', 'NIL', 'NULL'
271
+ return nil
272
+ end
273
+ end
274
+ return value
275
+ end
276
+
277
+ # Converts a String containing 'TRUE' or 'FALSE' to true or false Ruby
278
+ # primitive. All other values are simply returned.
279
+ #
280
+ # @param value [Object]
281
+ # @return [true|false|Object]
282
+ def self.handle_true_false(value)
283
+ if String === value
284
+ case value.upcase
285
+ when 'TRUE'
286
+ return true
287
+ when 'FALSE'
288
+ return false
289
+ end
290
+ end
291
+ return value
292
+ end
293
+
294
+ # Converts a String containing '', 'NIL', 'NULL', 'TRUE' or 'FALSE' to nil,
295
+ # true or false Ruby primitives. All other values are simply returned.
296
+ #
297
+ # @param value [Object]
298
+ # @return [true|false|nil|Object]
299
+ def self.handle_true_false_nil(value)
300
+ if String === value
301
+ case value.upcase
302
+ when 'TRUE'
303
+ return true
304
+ when 'FALSE'
305
+ return false
306
+ when '', 'NIL', 'NULL'
307
+ return nil
308
+ end
309
+ end
310
+ return value
311
+ end
312
+
313
+ # Converts a string representing a defined constant into its value. The
314
+ # defined constants are the minimum and maximum values for all the
315
+ # allowable data types. [MIN/MAX]_[U]INT[8/16/32] and
316
+ # [MIN/MAX]_FLOAT[32/64]. Thus MIN_UINT8, MAX_INT32, and MIN_FLOAT64 are
317
+ # all allowable values. Any other strings raise ArgumentError but all other
318
+ # types are simply returned.
319
+ #
320
+ # @param value [Object] Can be anything
321
+ # @return [Numeric] The converted value. Either a Fixnum or Float.
322
+ def self.handle_defined_constants(value, data_type = nil, bit_size = nil)
323
+ if value.class == String
324
+ case value.upcase
325
+ when 'MIN', 'MAX'
326
+ return self.calculate_range_value(value.upcase, data_type, bit_size)
327
+ when 'MIN_INT8'
328
+ return -128
329
+ when 'MAX_INT8'
330
+ return 127
331
+ when 'MIN_INT16'
332
+ return -32768
333
+ when 'MAX_INT16'
334
+ return 32767
335
+ when 'MIN_INT32'
336
+ return -2147483648
337
+ when 'MAX_INT32'
338
+ return 2147483647
339
+ when 'MIN_INT64'
340
+ return -9223372036854775808
341
+ when 'MAX_INT64'
342
+ return 9223372036854775807
343
+ when 'MIN_UINT8', 'MIN_UINT16', 'MIN_UINT32', 'MIN_UINT64'
344
+ return 0
345
+ when 'MAX_UINT8'
346
+ return 255
347
+ when 'MAX_UINT16'
348
+ return 65535
349
+ when 'MAX_UINT32'
350
+ return 4294967295
351
+ when 'MAX_UINT64'
352
+ return 18446744073709551615
353
+ when 'MIN_FLOAT64'
354
+ return -Float::MAX
355
+ when 'MAX_FLOAT64'
356
+ return Float::MAX
357
+ when 'MIN_FLOAT32'
358
+ return -3.402823e38
359
+ when 'MAX_FLOAT32'
360
+ return 3.402823e38
361
+ when 'POS_INFINITY'
362
+ return Float::INFINITY
363
+ when 'NEG_INFINITY'
364
+ return -Float::INFINITY
365
+ else
366
+ raise ArgumentError, "Could not convert constant: #{value}"
367
+ end
368
+ end
369
+ return value
370
+ end
371
+
372
+ protected
373
+
374
+ # Writes the ERB parsed results
375
+ def create_parsed_output_file(filename, run_erb, variables)
376
+ begin
377
+ output = nil
378
+ if run_erb
379
+ OpenC3.set_working_dir(File.dirname(filename)) do
380
+ output = ERB.new(File.read(filename), trim_mode: "-").result(binding.set_variables(variables))
381
+ end
382
+ else
383
+ output = File.read(filename)
384
+ end
385
+ rescue => e
386
+ # The first line of the backtrace indicates the line where the ERB
387
+ # parse failed. Grab the line number for the error message.
388
+ match = /:(.*):/.match(e.backtrace[0])
389
+ line_number = match.captures[0] if match
390
+ raise e, "ERB error at #{filename}:#{line_number}\n#{e}", e.backtrace
391
+ end
392
+ # Make a copy of the filename since we're calling slice! which modifies it directly
393
+ copy = filename.dup
394
+ config_index = copy.index('config')
395
+ if config_index
396
+ copy = copy[config_index..-1]
397
+ elsif copy.include?(':') # Check for Windows drive letter
398
+ copy = copy.split(':')[1]
399
+ end
400
+ parsed_filename = File.join(Dir.tmpdir, 'openc3', 'tmp', copy)
401
+ FileUtils.mkdir_p(File.dirname(parsed_filename)) # Create the path
402
+ file = File.open(parsed_filename, 'w+')
403
+ file.puts output
404
+ file.rewind # Rewind so the file is ready to read
405
+ file
406
+ end
407
+
408
+ def self.calculate_range_value(type, data_type, bit_size)
409
+ value = 0 # Default for UINT minimum
410
+
411
+ case data_type
412
+ when :INT
413
+ if type == 'MIN'
414
+ value = -2**(bit_size - 1)
415
+ else # 'MAX'
416
+ value = 2**(bit_size - 1) - 1
417
+ end
418
+ when :UINT
419
+ # Default is 0 for 'MIN'
420
+ if type == 'MAX'
421
+ value = 2**bit_size - 1
422
+ end
423
+ when :FLOAT
424
+ case bit_size
425
+ when 32
426
+ value = 3.402823e38
427
+ value *= -1 if type == 'MIN'
428
+ when 64
429
+ value = Float::MAX
430
+ value *= -1 if type == 'MIN'
431
+ else
432
+ raise ArgumentError, "Invalid bit size #{bit_size} for FLOAT type."
433
+ end
434
+ else
435
+ raise ArgumentError, "Invalid data type #{data_type} when calculating range."
436
+ end
437
+ value
438
+ end
439
+
440
+ if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
441
+ # Iterates over each line of the io object and yields the keyword and parameters
442
+ def parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx)
443
+ line_continuation = false
444
+
445
+ @line_number = 0
446
+ @keyword = nil
447
+ @parameters = []
448
+ @line = nil
449
+
450
+ while true
451
+ @line_number += 1
452
+
453
+ if @@progress_callback && ((@line_number % 10) == 0)
454
+ @@progress_callback.call(io.pos / size) if size > 0.0
455
+ end
456
+
457
+ begin
458
+ line = io.readline
459
+ rescue Exception
460
+ break
461
+ end
462
+
463
+ line.strip!
464
+ data = line.scan(rx)
465
+ first_item = data[0].to_s
466
+
467
+ if line_continuation
468
+ @line << line
469
+ # Carry over keyword and parameters
470
+ else
471
+ @line = line
472
+ if (first_item.length == 0) || (first_item[0] == '#')
473
+ @keyword = nil
474
+ else
475
+ @keyword = first_item.upcase
476
+ end
477
+ @parameters = []
478
+ end
479
+
480
+ # Ignore comments and blank lines
481
+ if @keyword.nil?
482
+ if (yield_non_keyword_lines) && (!line_continuation)
483
+ yield(@keyword, @parameters)
484
+ end
485
+ next
486
+ end
487
+
488
+ if line_continuation
489
+ if remove_quotes
490
+ @parameters << first_item.remove_quotes
491
+ else
492
+ @parameters << first_item
493
+ end
494
+ line_continuation = false
495
+ end
496
+
497
+ length = data.length
498
+ if length > 1
499
+ (1..(length - 1)).each do |index|
500
+ string = data[index]
501
+
502
+ # Don't process trailing comments such as:
503
+ # KEYWORD PARAM #This is a comment
504
+ # But still process Ruby string interpolations such as:
505
+ # KEYWORD PARAM #{var}
506
+ if (string.length > 0) && (string[0] == '#')
507
+ if !((string.length > 1) && (string[1] == '{'))
508
+ break
509
+ end
510
+ end
511
+
512
+ # If the string is simply '&' and its the last string then its a line continuation so break the loop
513
+ if (string.length == 1) && (string[0] == '&') && (index == (length - 1))
514
+ line_continuation = true
515
+ next
516
+ end
517
+
518
+ line_continuation = false
519
+ if remove_quotes
520
+ @parameters << string.remove_quotes
521
+ else
522
+ @parameters << string
523
+ end
524
+ end
525
+ end
526
+
527
+ # If we detected a line continuation while going through all the
528
+ # strings on the line then we strip off the continuation character and
529
+ # return to the top of the loop to continue processing the line.
530
+ if line_continuation
531
+ # Strip the continuation character
532
+ if @line.length >= 1
533
+ @line = @line[0..-2]
534
+ else
535
+ @line = ""
536
+ end
537
+ next
538
+ end
539
+
540
+ yield(@keyword, @parameters)
541
+ end
542
+
543
+ @@progress_callback.call(1.0) if @@progress_callback
544
+
545
+ return nil
546
+ end
547
+ end
548
+ end
549
+ end
@@ -0,0 +1,74 @@
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 'erb'
21
+ require 'psych'
22
+ require 'tempfile'
23
+ require 'openc3/top_level'
24
+
25
+ class Array
26
+ def to_meta_config_yaml(indentation = 0)
27
+ Psych.dump(self).split("\n")[1..-1].join("\n#{' ' * indentation}")
28
+ end
29
+ end
30
+
31
+ class Hash
32
+ def to_meta_config_yaml(indentation = 0)
33
+ Psych.dump(self).split("\n")[1..-1].join("\n#{' ' * indentation}")
34
+ end
35
+ end
36
+
37
+ module OpenC3
38
+ # Reads YAML formatted files describing a configuration file
39
+ class MetaConfigParser
40
+ @basedir = ''
41
+ def self.load(filename)
42
+ data = nil
43
+ if File.exist?(filename)
44
+ path = filename
45
+ @basedir = File.dirname(filename)
46
+ else
47
+ path = File.join(@basedir, filename)
48
+ end
49
+ tf = Tempfile.new("temp.yaml")
50
+
51
+ output = nil
52
+ OpenC3.set_working_dir(File.dirname(path)) do
53
+ output = ERB.new(File.read(path), trim_mode: "-").result(binding)
54
+ end
55
+ tf.write(output)
56
+ tf.close
57
+ begin
58
+ data = Psych.safe_load(File.read(tf.path), aliases: true)
59
+ rescue => error
60
+ error_file = "#{filename}.err"
61
+ File.open(error_file, 'w') { |file| file.puts output }
62
+ raise error.exception("#{error.message}\n\nParsed output written to #{File.expand_path(error_file)}\n")
63
+ end
64
+ tf.unlink
65
+ data
66
+ end
67
+
68
+ def self.dump(object, filename)
69
+ File.open(filename, 'w') do |file|
70
+ file.write Psych.dump(object)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,70 @@
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
+ # Performs a general conversion via the implementation of the call method
22
+ class Conversion
23
+ # @return [Symbol] The converted data type. Must be one of
24
+ # {OpenC3::StructureItem#data_type}
25
+ attr_reader :converted_type
26
+ # @return [Integer] The size in bits of the converted value
27
+ attr_reader :converted_bit_size
28
+ # @return [Integer] The size in bits of the converted array value
29
+ attr_reader :converted_array_size
30
+
31
+ # Create a new conversion
32
+ def initialize
33
+ @converted_type = nil
34
+ @converted_bit_size = nil
35
+ @converted_array_size = nil
36
+ end
37
+
38
+ # Perform the conversion on the value.
39
+ #
40
+ # @param value [Object] The value to convert
41
+ # @param packet [Packet] The packet which contains the value. This can
42
+ # be useful to reach into the packet and use other values in the
43
+ # conversion.
44
+ # @param buffer [String] The packet buffer
45
+ # @return The converted value
46
+ def call(value, packet, buffer)
47
+ raise "call method must be defined by subclass"
48
+ end
49
+
50
+ # @return [String] The conversion class
51
+ def to_s
52
+ self.class.to_s.split('::')[-1]
53
+ end
54
+
55
+ # @param read_or_write [String] Either 'READ' or 'WRITE'
56
+ # @return [String] Config fragment for this conversion
57
+ def to_config(read_or_write)
58
+ " #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename}\n"
59
+ end
60
+
61
+ def as_json(*a)
62
+ result = {}
63
+ result['class'] = self.class.name.to_s
64
+ result['converted_type'] = @converted_type if @converted_type
65
+ result['converted_bit_size'] = @converted_bit_size if @converted_bit_size
66
+ result['converted_array_size'] = @converted_array_size if @converted_array_size
67
+ result
68
+ end
69
+ end
70
+ end