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,411 @@
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/config/config_parser'
21
+ require 'openc3/packets/packet_config'
22
+ require 'openc3/packets/commands'
23
+ require 'openc3/packets/telemetry'
24
+ require 'openc3/packets/limits'
25
+ require 'openc3/system/target'
26
+ require 'openc3/logs'
27
+ require 'fileutils'
28
+ require 'openc3/utilities/zip'
29
+ require 'bundler'
30
+ require 'thread'
31
+
32
+ module OpenC3
33
+ # System is the primary entry point into the OpenC3 framework. It captures
34
+ # system wide configuration items such as the available ports and paths to
35
+ # various files used by the system. The #commands, #telemetry, and #limits
36
+ # class variables are the primary access points for applications. The
37
+ # #targets variable provides access to all the targets defined by the system.
38
+ # Its primary responsibily is to load the system configuration file and
39
+ # create all the Target instances. It also saves and restores configurations
40
+ # using a hashing checksum over the entire configuration to detect changes.
41
+ class SystemConfig
42
+ # @return [String] Base path of the configuration
43
+ attr_reader :userpath
44
+ # @return [Boolean] Whether to use sound for alerts
45
+ attr_reader :sound
46
+ # @return [Boolean] Whether to use DNS to lookup IP addresses or not
47
+ attr_reader :use_dns
48
+ # @return [Hash<String,Target>] Hash of all the known targets
49
+ attr_reader :targets
50
+ # @return [Integer] The number of seconds before a telemetry packet is considered stale
51
+ attr_reader :staleness_seconds
52
+ # @return [Boolean] Whether to use UTC or local times
53
+ attr_reader :use_utc
54
+ # @return [Hash<String,String>] Hash of the text/color to use for the classificaiton banner
55
+ attr_reader :classificiation_banner
56
+
57
+ # @param filename [String] Full path to the system configuration file to
58
+ # read.
59
+ def initialize(filename)
60
+ reset_variables(filename)
61
+ end
62
+
63
+ # Resets the System's internal state to defaults.
64
+ #
65
+ # @param filename [String] Path to system.txt config file to process. Defaults to config/system/system.txt
66
+ def reset_variables(filename)
67
+ @targets = {}
68
+ @config = nil
69
+ @commands = nil
70
+ @telemetry = nil
71
+ @limits = nil
72
+ @sound = false
73
+ @use_dns = false
74
+ @staleness_seconds = 30
75
+ @use_utc = false
76
+ @meta_init_filename = nil
77
+ @userpath = File.expand_path(File.join(File.dirname(filename), '..', '..'))
78
+ process_file(filename, File.join(@userpath, 'config', 'targets'))
79
+ @initial_filename = filename
80
+ @initial_config = nil
81
+ @config_blacklist = {}
82
+ end
83
+
84
+ # Process the system.txt configuration file
85
+ #
86
+ # @param filename [String] The configuration file
87
+ # @param targets_config_dir [String] The configuration directory to
88
+ # search for the target command and telemetry files.
89
+ def process_file(filename, targets_config_dir)
90
+ parser = ConfigParser.new("https://openc3.com/docs/v5")
91
+
92
+ # First pass - Everything except targets
93
+ parser.parse_file(filename) do |keyword, parameters|
94
+ case keyword
95
+ when 'AUTO_DECLARE_TARGETS', 'DECLARE_TARGET', 'DECLARE_GEM_TARGET', 'DECLARE_GEM_MULTI_TARGET'
96
+ # Will be handled by second pass
97
+
98
+ when 'PORT', 'LISTEN_HOST', 'CONNECT_HOST', 'PATH', 'DEFAULT_PACKET_LOG_WRITER', 'DEFAULT_PACKET_LOG_READER',
99
+ 'ALLOW_ACCESS', 'ADD_HASH_FILE', 'ADD_MD5_FILE', 'HASHING_ALGORITHM'
100
+ # Not used by OpenC3 5
101
+
102
+ when 'ENABLE_SOUND'
103
+ usage = "#{keyword}"
104
+ parser.verify_num_parameters(0, 0, usage)
105
+ @sound = true
106
+
107
+ when 'DISABLE_DNS'
108
+ usage = "#{keyword}"
109
+ parser.verify_num_parameters(0, 0, usage)
110
+ @use_dns = false
111
+
112
+ when 'ENABLE_DNS'
113
+ usage = "#{keyword}"
114
+ parser.verify_num_parameters(0, 0, usage)
115
+ @use_dns = true
116
+
117
+ when 'STALENESS_SECONDS'
118
+ parser.verify_num_parameters(1, 1, "#{keyword} <Value in Seconds>")
119
+ @staleness_seconds = Integer(parameters[0])
120
+
121
+ when 'META_INIT'
122
+ parser.verify_num_parameters(1, 1, "#{keyword} <Filename>")
123
+ @meta_init_filename = ConfigParser.handle_nil(parameters[0])
124
+
125
+ when 'TIME_ZONE_UTC'
126
+ parser.verify_num_parameters(0, 0, "#{keyword}")
127
+ @use_utc = true
128
+
129
+ when 'CLASSIFICATION'
130
+ parser.verify_num_parameters(2, 4, "#{keyword} <Display_Text> <Color Name|Red> <Green> <Blue>")
131
+ # Determine if the OpenC3 color already exists, otherwise create a new one
132
+ if OpenC3.constants.include? parameters[1].upcase.to_sym
133
+ # We were given a named color that already exists in OpenC3
134
+ color = parameters[1].upcase
135
+ else
136
+ if parameters.length < 4
137
+ # We were given a named color, but it didn't exist in OpenC3 already
138
+ color = OpenC3.getColor(parameters[1].upcase)
139
+ else
140
+ # We were given RGB values
141
+ color = OpenC3.getColor(parameters[1], parameters[2], parameters[3])
142
+ end
143
+ end
144
+
145
+ @classificiation_banner = { 'display_text' => parameters[0],
146
+ 'color' => color }
147
+
148
+ else
149
+ # blank lines will have a nil keyword and should not raise an exception
150
+ raise parser.error("Unknown keyword '#{keyword}'") if keyword
151
+ end # case keyword
152
+ end # parser.parse_file
153
+
154
+ # Explicitly set up time to use UTC or local
155
+ if @use_utc
156
+ Time.use_utc()
157
+ else
158
+ Time.use_local()
159
+ end
160
+
161
+ # Second pass - Process targets
162
+ process_targets(parser, filename, targets_config_dir)
163
+ end # def process_file
164
+
165
+ # Parse the system.txt configuration file looking for keywords associated
166
+ # with targets and create all the Target instances in the system.
167
+ #
168
+ # @param parser [ConfigParser] Parser created by process_file
169
+ # @param filename (see #process_file)
170
+ # @param targets_config_dir (see #process_file)
171
+ def process_targets(parser, filename, targets_config_dir)
172
+ parser.parse_file(filename) do |keyword, parameters|
173
+ case keyword
174
+ when 'AUTO_DECLARE_TARGETS'
175
+ usage = "#{keyword}"
176
+ parser.verify_num_parameters(0, 0, usage)
177
+ path = File.join(@userpath, 'config', 'targets')
178
+ unless File.exist? path
179
+ raise parser.error("#{path} must exist", usage)
180
+ end
181
+
182
+ dirs = []
183
+ configuration_dir = File.join(@userpath, 'config', 'targets')
184
+ Dir.foreach(configuration_dir) { |dir_filename| dirs << dir_filename }
185
+ dirs.sort!
186
+ dirs.each do |dir_filename|
187
+ if dir_filename[0] != '.'
188
+ if dir_filename == dir_filename.upcase
189
+ # If any of the targets original directory name matches the
190
+ # current directory then it must have been already processed by
191
+ # DECLARE_TARGET so we skip it.
192
+ next if @targets.select { |name, target| target.original_name == dir_filename }.length > 0
193
+ next if dir_filename == 'SYSTEM'
194
+
195
+ target = Target.new(dir_filename, nil, targets_config_dir)
196
+ @targets[target.name] = target
197
+ else
198
+ raise parser.error("Target folder must be uppercase: '#{dir_filename}'")
199
+ end
200
+ end
201
+ end
202
+ auto_detect_gem_based_targets()
203
+
204
+ when 'DECLARE_TARGET'
205
+ usage = "#{keyword} <TARGET NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
206
+ parser.verify_num_parameters(1, 3, usage)
207
+ target_name = parameters[0].to_s.upcase
208
+
209
+ if targets_config_dir
210
+ folder_name = File.join(targets_config_dir, target_name)
211
+ else
212
+ folder_name = File.join(@userpath, 'config', 'targets', target_name)
213
+ end
214
+ unless Dir.exist?(folder_name)
215
+ raise parser.error("Target folder must exist '#{folder_name}'.")
216
+ end
217
+
218
+ substitute_name = nil
219
+ substitute_name = ConfigParser.handle_nil(parameters[1])
220
+ if substitute_name
221
+ substitute_name = substitute_name.to_s.upcase
222
+ original_name = target_name
223
+ target_name = substitute_name
224
+ else
225
+ original_name = nil
226
+ end
227
+
228
+ target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[2]))
229
+ @targets[target.name] = target
230
+
231
+ when 'DECLARE_GEM_TARGET'
232
+ usage = "#{keyword} <GEM NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
233
+ parser.verify_num_parameters(1, 3, usage)
234
+ # Remove 'openc3' from the gem name 'openc3-power-supply'
235
+ target_name = parameters[0].split('-')[1..-1].join('-').to_s.upcase
236
+ gem_dir = Gem::Specification.find_by_name(parameters[0]).gem_dir
237
+ substitute_name = nil
238
+ substitute_name = ConfigParser.handle_nil(parameters[1])
239
+ if substitute_name
240
+ substitute_name = substitute_name.to_s.upcase
241
+ original_name = target_name
242
+ target_name = substitute_name
243
+ else
244
+ original_name = nil
245
+ end
246
+ target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[2]), gem_dir)
247
+ @targets[target.name] = target
248
+
249
+ when 'DECLARE_GEM_MULTI_TARGET'
250
+ usage = "#{keyword} <GEM NAME> <TARGET NAME> <SUBSTITUTE TARGET NAME (Optional)> <TARGET FILENAME (Optional - defaults to target.txt)>"
251
+ parser.verify_num_parameters(2, 4, usage)
252
+ target_name = parameters[1].to_s.upcase
253
+ gem_dir = Gem::Specification.find_by_name(parameters[0]).gem_dir
254
+ gem_dir = File.join(gem_dir, target_name)
255
+ substitute_name = nil
256
+ substitute_name = ConfigParser.handle_nil(parameters[2])
257
+ if substitute_name
258
+ substitute_name = substitute_name.to_s.upcase
259
+ original_name = target_name
260
+ target_name = substitute_name
261
+ else
262
+ original_name = nil
263
+ end
264
+ target = Target.new(target_name, original_name, targets_config_dir, ConfigParser.handle_nil(parameters[3]), gem_dir)
265
+ @targets[target.name] = target
266
+
267
+ end # case keyword
268
+ end # parser.parse_file
269
+
270
+ # Make sure SYSTEM target is always present and added last
271
+ unless @targets.key?('SYSTEM')
272
+ target = Target.new('SYSTEM', nil, targets_config_dir)
273
+ @targets[target.name] = target
274
+ end
275
+ end
276
+
277
+ protected
278
+
279
+ def unzip(zip_file_name)
280
+ zip_dir = File.join(@paths['TMP'], File.basename(zip_file_name, ".*"))
281
+ # Only unzip if we have to. We assume the unzipped directory structure is
282
+ # intact. If not they'll get a popop with the errors encountered when
283
+ # loading the configuration.
284
+ unless File.exist? zip_dir
285
+ Zip::File.open(zip_file_name) do |zip_file|
286
+ zip_file.each do |entry|
287
+ path = File.join(@paths['TMP'], entry.name)
288
+ FileUtils.mkdir_p(File.dirname(path))
289
+ zip_file.extract(entry, path) unless File.exist?(path)
290
+ end
291
+ end
292
+ end
293
+ zip_dir
294
+ end
295
+
296
+ # A helper method to make the zip writing recursion work
297
+ def write_zip_entries(base_dir, entries, zip_path, io)
298
+ io.add(zip_path, base_dir) # Add the directory whether it has entries or not
299
+ entries.each do |e|
300
+ zip_file_path = File.join(zip_path, e)
301
+ disk_file_path = File.join(base_dir, e)
302
+ if File.directory? disk_file_path
303
+ recursively_deflate_directory(disk_file_path, io, zip_file_path)
304
+ else
305
+ put_into_archive(disk_file_path, io, zip_file_path)
306
+ end
307
+ end
308
+ end
309
+
310
+ def recursively_deflate_directory(disk_file_path, io, zip_file_path)
311
+ io.add(zip_file_path, disk_file_path)
312
+ entries = Dir.entries(disk_file_path) - %w(. ..)
313
+ write_zip_entries(disk_file_path, entries, zip_file_path, io)
314
+ end
315
+
316
+ def put_into_archive(disk_file_path, io, zip_file_path)
317
+ io.get_output_stream(zip_file_path) do |f|
318
+ data = nil
319
+ File.open(disk_file_path, 'rb') do |file|
320
+ data = file.read
321
+ end
322
+ f.write(data)
323
+ end
324
+ end
325
+
326
+ def auto_detect_gem_based_targets
327
+ Bundler.load.specs.each do |spec|
328
+ spec_name_split = spec.name.split('-')
329
+ if spec_name_split.length > 1 && (spec_name_split[0] == 'openc3')
330
+ # search for multiple targets packaged in a single gem
331
+ dirs = []
332
+ Dir.foreach(spec.gem_dir) { |dir_filename| dirs << dir_filename }
333
+ dirs.sort!
334
+ dirs.each do |dir_filename|
335
+ if dir_filename == "."
336
+ # check the base directory
337
+ curr_dir = spec.gem_dir
338
+ target_name = spec_name_split[1..-1].join('-').to_s.upcase
339
+ else
340
+ # check for targets in other directories 1 level deep
341
+ next if dir_filename[0] == '.' # skip dot directories and ".."
342
+ next if dir_filename != dir_filename.upcase # skip non uppercase directories
343
+
344
+ curr_dir = File.join(spec.gem_dir, dir_filename)
345
+ target_name = dir_filename
346
+ end
347
+ # check for the cmd_tlm directory - if it has it, then we have found a target
348
+ if File.directory?(File.join(curr_dir, 'cmd_tlm'))
349
+ # If any of the targets original directory name matches the
350
+ # current directory then it must have been already processed by
351
+ # DECLARE_TARGET so we skip it.
352
+ next if @targets.select { |name, target| target.original_name == target_name }.length > 0
353
+
354
+ target = Target.new(target_name, nil, nil, nil, spec.gem_dir)
355
+ @targets[target.name] = target
356
+ end
357
+ end
358
+ end
359
+ end
360
+ rescue Bundler::GemfileNotFound
361
+ # No Gemfile - so no gem based targets
362
+ end
363
+
364
+ def save_configuration
365
+ configuration = find_configuration(@config.name)
366
+ configuration = File.join(@paths['SAVED_CONFIG'], File.build_timestamped_filename([@config.name], '.zip')) unless configuration
367
+ unless File.exist?(configuration)
368
+ configuration_tmp = File.join(@paths['SAVED_CONFIG'], File.build_timestamped_filename(['tmp_' + @config.name], '.zip.tmp'))
369
+ begin
370
+ Zip.continue_on_exists_proc = true
371
+ Zip::File.open(configuration_tmp, Zip::File::CREATE) do |zipfile|
372
+ zip_file_path = File.basename(configuration, ".zip")
373
+ zipfile.mkdir zip_file_path
374
+
375
+ # Copy target files into archive
376
+ zip_targets = []
377
+ @targets.each do |target_name, target|
378
+ entries = Dir.entries(target.dir) - %w(. ..)
379
+ zip_target = File.join(zip_file_path, target.original_name)
380
+ # Check the stored list of targets. We can't ask the zip file
381
+ # itself because it's in progress and hasn't been saved
382
+ unless zip_targets.include?(zip_target)
383
+ write_zip_entries(target.dir, entries, zip_target, zipfile)
384
+ zip_targets << zip_target
385
+ end
386
+ end
387
+
388
+ # Create custom system.txt file
389
+ zipfile.get_output_stream(File.join(zip_file_path, 'system.txt')) do |file|
390
+ @targets.each do |target_name, target|
391
+ target_filename = File.basename(target.filename)
392
+ target_filename = nil unless File.exist?(target.filename)
393
+ # Create a newline character since Zip opens files in binary mode
394
+ newline = Kernel.is_windows? ? "\r\n" : "\n"
395
+ if target.substitute
396
+ file.write "DECLARE_TARGET #{target.original_name} #{target.name} #{target_filename}#{newline}"
397
+ else
398
+ file.write "DECLARE_TARGET #{target.name} nil #{target_filename}#{newline}"
399
+ end
400
+ end
401
+ end
402
+ end
403
+ File.rename(configuration_tmp, configuration)
404
+ File.chmod(0444, configuration) # Mark readonly
405
+ rescue Exception => error
406
+ Logger.error "Problem saving configuration to #{configuration}: #{error.class}:#{error.message}\n#{error.backtrace.join("\n")}\n"
407
+ end
408
+ end
409
+ end
410
+ end
411
+ end
@@ -0,0 +1,269 @@
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/config/config_parser'
21
+ require 'pathname'
22
+
23
+ module OpenC3
24
+ # Target encapsulates the information about a OpenC3 target. Targets are
25
+ # accessed through interfaces and have command and telemetry definition files
26
+ # which define their access.
27
+ class Target
28
+ # @return [String] Name of the target. This can be overridden when
29
+ # the system processes the target.
30
+ attr_reader :name
31
+
32
+ # @return [Array<String>] List of filenames that must be required by Ruby
33
+ # before parsing the command and telemetry definitions for this target
34
+ attr_reader :requires
35
+
36
+ # @return [Array<String>] List of parameters that should be ignored. Tools
37
+ # which access this target should not display or manipulate these
38
+ # parameters.
39
+ attr_reader :ignored_parameters
40
+
41
+ # @return [Array<String>] List of items that should be ignored. Tools
42
+ # which access this target should not display or manipulate these
43
+ # items.
44
+ attr_reader :ignored_items
45
+
46
+ # @return [Array<String>] List of configuration files which define the
47
+ # commands and telemetry for this target
48
+ attr_reader :cmd_tlm_files
49
+
50
+ # @return [String] Target filename for this target
51
+ attr_reader :filename
52
+
53
+ # @return [String] The directory which contains this target
54
+ attr_reader :dir
55
+
56
+ # @return [Interface] The interface used to access the target
57
+ attr_accessor :interface
58
+
59
+ # @return [Integer] The number of command packets send to this target
60
+ attr_accessor :cmd_cnt
61
+
62
+ # @return [Integer] The number of telemetry packets received from this target
63
+ attr_accessor :tlm_cnt
64
+
65
+ # @return [Boolean] Indicates if all command packets identify using different fields
66
+ attr_accessor :cmd_unique_id_mode
67
+
68
+ # @return [Boolean] Indicates if telemetry packets identify using different fields
69
+ attr_accessor :tlm_unique_id_mode
70
+
71
+ # @return [String] Id of the target configuration
72
+ attr_accessor :id
73
+
74
+ # Creates a new target by processing the target.txt file in the directory
75
+ # given by the path joined with the target_name. Records all the command
76
+ # and telemetry definition files found in the targets cmd_tlm directory.
77
+ # System uses this list and processes them using PacketConfig.
78
+ #
79
+ # @param target_name [String] The name of the target.
80
+ # @param path [String] Path to the target directory
81
+ # @param gem_path [String] Path to the gem file or nil if there is no gem
82
+ def initialize(target_name, path, gem_path = nil)
83
+ @requires = []
84
+ @ignored_parameters = []
85
+ @ignored_items = []
86
+ @cmd_tlm_files = []
87
+ # @auto_screen_substitute = false
88
+ @interface = nil
89
+ @routers = []
90
+ @cmd_cnt = 0
91
+ @tlm_cnt = 0
92
+ @cmd_unique_id_mode = false
93
+ @tlm_unique_id_mode = false
94
+ @name = target_name.clone.upcase.freeze
95
+ get_target_dir(path, gem_path)
96
+ process_target_config_file()
97
+
98
+ # If target.txt didn't specify specific cmd/tlm files then add everything
99
+ if @cmd_tlm_files.empty?
100
+ @cmd_tlm_files = add_all_cmd_tlm()
101
+ else
102
+ add_cmd_tlm_partials()
103
+ end
104
+ end
105
+
106
+ # Parses the target configuration file
107
+ #
108
+ # @param filename [String] The target configuration file to parse
109
+ def process_file(filename)
110
+ Logger.instance.info "Processing target definition in file '#{filename}'"
111
+ parser = ConfigParser.new("https://openc3.com/docs/v5/target")
112
+ parser.parse_file(filename) do |keyword, parameters|
113
+ case keyword
114
+ when 'REQUIRE'
115
+ usage = "#{keyword} <FILENAME>"
116
+ parser.verify_num_parameters(1, 1, usage)
117
+ filename = File.join(@dir, 'lib', parameters[0])
118
+ begin
119
+ # Require absolute path to file in target lib folder. Prevents name
120
+ # conflicts at the require step
121
+ OpenC3.disable_warnings do
122
+ OpenC3.require_file(filename, false)
123
+ end
124
+ rescue LoadError
125
+ begin
126
+ # If we couldn't load at the target/lib level check everywhere
127
+ OpenC3.disable_warnings do
128
+ filename = parameters[0]
129
+ OpenC3.require_file(parameters[0])
130
+ end
131
+ rescue Exception => err
132
+ raise parser.error(err.message)
133
+ end
134
+ rescue Exception => err
135
+ raise parser.error(err.message)
136
+ end
137
+
138
+ # This code resolves any relative paths to absolute before putting into the @requires array
139
+ unless Pathname.new(filename).absolute?
140
+ $:.each do |search_path|
141
+ test_filename = File.join(search_path, filename).gsub("\\", "/")
142
+ if File.exist?(test_filename)
143
+ filename = test_filename
144
+ break
145
+ end
146
+ end
147
+ end
148
+
149
+ @requires << filename
150
+
151
+ when 'IGNORE_PARAMETER', 'IGNORE_ITEM'
152
+ usage = "#{keyword} <#{keyword.split('_')[1]} NAME>"
153
+ parser.verify_num_parameters(1, 1, usage)
154
+ @ignored_parameters << parameters[0].upcase if keyword.include?("PARAMETER")
155
+ @ignored_items << parameters[0].upcase if keyword.include?("ITEM")
156
+
157
+ when 'COMMANDS', 'TELEMETRY'
158
+ usage = "#{keyword} <FILENAME>"
159
+ parser.verify_num_parameters(1, 1, usage)
160
+ filename = File.join(@dir, 'cmd_tlm', parameters[0])
161
+ raise parser.error("#{filename} not found") unless File.exist?(filename)
162
+
163
+ @cmd_tlm_files << filename
164
+
165
+ # when 'AUTO_SCREEN_SUBSTITUTE'
166
+ # usage = "#{keyword}"
167
+ # parser.verify_num_parameters(0, 0, usage)
168
+ # @auto_screen_substitute = true
169
+
170
+ when 'CMD_UNIQUE_ID_MODE'
171
+ usage = "#{keyword}"
172
+ parser.verify_num_parameters(0, 0, usage)
173
+ @cmd_unique_id_mode = true
174
+
175
+ when 'TLM_UNIQUE_ID_MODE'
176
+ usage = "#{keyword}"
177
+ parser.verify_num_parameters(0, 0, usage)
178
+ @tlm_unique_id_mode = true
179
+
180
+ else
181
+ # blank lines will have a nil keyword and should not raise an exception
182
+ raise parser.error("Unknown keyword '#{keyword}'") if keyword
183
+ end # case keyword
184
+ end
185
+ end
186
+
187
+ def as_json(*a)
188
+ config = {}
189
+ config['name'] = @name
190
+ config['requires'] = @requires
191
+ config['ignored_parameters'] = @ignored_parameters
192
+ config['ignored_items'] = @ignored_items
193
+ # config['auto_screen_substitute'] = true if @auto_screen_substitute
194
+ config['cmd_tlm_files'] = @cmd_tlm_files
195
+ # config['filename'] = @filename
196
+ # config['interface'] = @interface.name if @interface
197
+ # config['dir'] = @dir
198
+ # config['cmd_cnt'] = @cmd_cnt
199
+ # config['tlm_cnt'] = @tlm_cnt
200
+ config['cmd_unique_id_mode'] = true if @cmd_unique_id_mode
201
+ config['tlm_unique_id_mode'] = true if @tlm_unique_id_mode
202
+ config['id'] = @id
203
+ config
204
+ end
205
+
206
+ protected
207
+
208
+ # Get the target directory and add the target's lib folder to the
209
+ # search path if it exists
210
+ def get_target_dir(path, gem_path)
211
+ if gem_path
212
+ @dir = gem_path
213
+ else
214
+ @dir = File.join(path, @name)
215
+ end
216
+ @dir.gsub!("\\", '/')
217
+ lib_dir = File.join(@dir, 'lib')
218
+ OpenC3.add_to_search_path(lib_dir, false) if File.exist?(lib_dir)
219
+ proc_dir = File.join(@dir, 'procedures')
220
+ OpenC3.add_to_search_path(proc_dir, false) if File.exist?(proc_dir)
221
+ end
222
+
223
+ # Process the target's configuration file if it exists
224
+ def process_target_config_file
225
+ @filename = File.join(@dir, 'target.txt')
226
+ if File.exist?(filename)
227
+ process_file(filename)
228
+ else
229
+ @filename = nil
230
+ end
231
+ id_filename = File.join(@dir, 'target_id.txt')
232
+ if File.exist?(id_filename)
233
+ File.open(id_filename, 'rb') { |file| @id = file.read.strip }
234
+ else
235
+ @id = nil
236
+ end
237
+ end
238
+
239
+ # Automatically add all command and telemetry definitions to the list
240
+ def add_all_cmd_tlm
241
+ cmd_tlm_files = []
242
+ if Dir.exist?(File.join(@dir, 'cmd_tlm'))
243
+ # Grab All *.txt files in the cmd_tlm folder and subfolders
244
+ Dir[File.join(@dir, 'cmd_tlm', '**', '*.txt')].each do |filename|
245
+ cmd_tlm_files << filename
246
+ end
247
+ # Grab All *.xtce files in the cmd_tlm folder and subfolders
248
+ Dir[File.join(@dir, 'cmd_tlm', '**', '*.xtce')].each do |filename|
249
+ cmd_tlm_files << filename
250
+ end
251
+ end
252
+ cmd_tlm_files.sort!
253
+ end
254
+
255
+ # Make sure all partials are included in the cmd_tlm list for the hashing sum calculation
256
+ def add_cmd_tlm_partials
257
+ partial_files = []
258
+ if Dir.exist?(File.join(@dir, 'cmd_tlm'))
259
+ # Grab all _*.txt files in the cmd_tlm folder and subfolders
260
+ Dir[File.join(@dir, 'cmd_tlm', '**', '_*.txt')].each do |filename|
261
+ partial_files << filename
262
+ end
263
+ end
264
+ partial_files.sort!
265
+ @cmd_tlm_files.concat(partial_files)
266
+ @cmd_tlm_files.uniq!
267
+ end
268
+ end
269
+ end