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,625 @@
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'
22
+ require 'openc3/packets/parsers/packet_parser'
23
+ require 'openc3/packets/parsers/packet_item_parser'
24
+ require 'openc3/packets/parsers/limits_parser'
25
+ require 'openc3/packets/parsers/limits_response_parser'
26
+ require 'openc3/packets/parsers/state_parser'
27
+ require 'openc3/packets/parsers/format_string_parser'
28
+ require 'openc3/packets/parsers/processor_parser'
29
+ require 'openc3/packets/parsers/xtce_parser'
30
+ require 'openc3/packets/parsers/xtce_converter'
31
+ require 'openc3/conversions'
32
+ require 'openc3/processors'
33
+ require 'nokogiri'
34
+ require 'ostruct'
35
+
36
+ module OpenC3
37
+ # Reads a command or telemetry configuration file and builds a hash of packets.
38
+ class PacketConfig
39
+ # @return [String] The name of this configuration. To be used by higher
40
+ # level classes to store information about the current PacketConfig.
41
+ attr_accessor :name
42
+
43
+ # @return [Hash<String=>Packet>] Hash of all the telemetry packets
44
+ # keyed by the packet name.
45
+ attr_reader :telemetry
46
+
47
+ # @return [Hash<String=>Packet>] Hash of all the command packets
48
+ # keyed by the packet name.
49
+ attr_reader :commands
50
+
51
+ # @return [Hash<String=>Array(String, String, String)>] Hash of all the
52
+ # limits groups keyed by the group name. The value is a three element
53
+ # array consisting of the target_name, packet_name, and item_name.
54
+ attr_reader :limits_groups
55
+
56
+ # @return [Array<Symbol>] The defined limits sets for all items in the
57
+ # packet. This will always include :DEFAULT.
58
+ attr_reader :limits_sets
59
+
60
+ # @return [Array<String>] Array of strings listing all the warnings
61
+ # that were created while parsing the configuration file.
62
+ attr_reader :warnings
63
+
64
+ # @return [Hash<String=>Hash<String=>Array(Packet)>>] Hash of hashes keyed
65
+ # first by the target name and then by the item name. This results in an
66
+ # array of packets containing that target and item. This structure is
67
+ # used to perform lookups when the packet and item are known but the
68
+ # packet is not.
69
+ attr_reader :latest_data
70
+
71
+ # @return [Hash<String>=>Hash<Array>=>Packet] Hash keyed by target name
72
+ # that returns a hash keyed by an array of id values. The id values resolve to the packet
73
+ # defined by that identification. Command version
74
+ attr_reader :cmd_id_value_hash
75
+
76
+ # @return [Hash<String>=>Hash<Array>=>Packet] Hash keyed by target name
77
+ # that returns a hash keyed by an array of id values. The id values resolve to the packet
78
+ # defined by that identification. Telemetry version
79
+ attr_reader :tlm_id_value_hash
80
+
81
+ COMMAND = "Command"
82
+ TELEMETRY = "Telemetry"
83
+
84
+ def initialize
85
+ @name = nil
86
+ @telemetry = {}
87
+ @commands = {}
88
+ @limits_groups = {}
89
+ @limits_sets = [:DEFAULT]
90
+ # Hash of Hashes. First index by target name and then item name.
91
+ # Returns an array of packets with that target and item.
92
+ @latest_data = {}
93
+ @warnings = []
94
+ @cmd_id_value_hash = {}
95
+ @tlm_id_value_hash = {}
96
+
97
+ # Create unknown packets
98
+ @commands['UNKNOWN'] = {}
99
+ @commands['UNKNOWN']['UNKNOWN'] = Packet.new('UNKNOWN', 'UNKNOWN', :BIG_ENDIAN)
100
+ @telemetry['UNKNOWN'] = {}
101
+ @telemetry['UNKNOWN']['UNKNOWN'] = Packet.new('UNKNOWN', 'UNKNOWN', :BIG_ENDIAN)
102
+
103
+ reset_processing_variables()
104
+ end
105
+
106
+ #########################################################################
107
+ # The following methods process a command or telemetry packet config file
108
+ #########################################################################
109
+
110
+ # Processes a OpenC3 configuration file and uses the keywords to build up
111
+ # knowledge of the commands, telemetry, and limits groups.
112
+ #
113
+ # @param filename [String] The name of the configuration file
114
+ # @param process_target_name [String] The target name. Pass nil when parsing
115
+ # an xtce file to automatically determine the target name.
116
+ def process_file(filename, process_target_name)
117
+ # Handle .xtce files
118
+ if File.extname(filename).to_s.downcase == ".xtce"
119
+ XtceParser.process(@commands, @telemetry, @warnings, filename, process_target_name)
120
+ return
121
+ end
122
+
123
+ # Partial files are included into another file and thus aren't directly processed
124
+ return if File.basename(filename)[0] == '_' # Partials start with underscore
125
+
126
+ @converted_type = nil
127
+ @converted_bit_size = nil
128
+ @proc_text = ''
129
+ @building_generic_conversion = false
130
+
131
+ process_target_name = process_target_name.upcase
132
+ parser = ConfigParser.new("https://openc3.com/docs/v5")
133
+ parser.instance_variable_set(:@target_name, process_target_name)
134
+ parser.parse_file(filename) do |keyword, params|
135
+ if @building_generic_conversion
136
+ case keyword
137
+ # Complete a generic conversion
138
+ when 'GENERIC_READ_CONVERSION_END', 'GENERIC_WRITE_CONVERSION_END'
139
+ parser.verify_num_parameters(0, 0, keyword)
140
+ @current_item.read_conversion =
141
+ GenericConversion.new(@proc_text,
142
+ @converted_type,
143
+ @converted_bit_size) if keyword.include? "READ"
144
+ @current_item.write_conversion =
145
+ GenericConversion.new(@proc_text,
146
+ @converted_type,
147
+ @converted_bit_size) if keyword.include? "WRITE"
148
+ @building_generic_conversion = false
149
+ # Add the current config.line to the conversion being built
150
+ else
151
+ @proc_text << parser.line << "\n"
152
+ end # case keyword
153
+
154
+ else # not building generic conversion
155
+
156
+ case keyword
157
+
158
+ # Start a new packet
159
+ when 'COMMAND'
160
+ finish_packet()
161
+ @current_packet = PacketParser.parse_command(parser, process_target_name, @commands, @warnings)
162
+ @current_cmd_or_tlm = COMMAND
163
+
164
+ when 'TELEMETRY'
165
+ finish_packet()
166
+ @current_packet = PacketParser.parse_telemetry(parser, process_target_name, @telemetry, @latest_data, @warnings)
167
+ @current_cmd_or_tlm = TELEMETRY
168
+
169
+ # Select an existing packet for editing
170
+ when 'SELECT_COMMAND', 'SELECT_TELEMETRY'
171
+ usage = "#{keyword} <TARGET NAME> <PACKET NAME>"
172
+ finish_packet()
173
+ parser.verify_num_parameters(2, 2, usage)
174
+ target_name = process_target_name
175
+ target_name = params[0].upcase if target_name == 'SYSTEM'
176
+ packet_name = params[1].upcase
177
+
178
+ @current_packet = nil
179
+ if keyword.include?('COMMAND')
180
+ @current_cmd_or_tlm = COMMAND
181
+ if @commands[target_name]
182
+ @current_packet = @commands[target_name][packet_name]
183
+ end
184
+ else
185
+ @current_cmd_or_tlm = TELEMETRY
186
+ if @telemetry[target_name]
187
+ @current_packet = @telemetry[target_name][packet_name]
188
+ end
189
+ end
190
+ raise parser.error("Packet not found", usage) unless @current_packet
191
+
192
+ # Start the creation of a new limits group
193
+ when 'LIMITS_GROUP'
194
+ usage = "LIMITS_GROUP <GROUP NAME>"
195
+ parser.verify_num_parameters(1, 1, usage)
196
+ @current_limits_group = params[0].to_s.upcase
197
+ @limits_groups[@current_limits_group] = [] unless @limits_groups.include?(@current_limits_group)
198
+
199
+ # Add a telemetry item to the limits group
200
+ when 'LIMITS_GROUP_ITEM'
201
+ usage = "LIMITS_GROUP_ITEM <TARGET NAME> <PACKET NAME> <ITEM NAME>"
202
+ parser.verify_num_parameters(3, 3, usage)
203
+ @limits_groups[@current_limits_group] << [params[0].to_s.upcase, params[1].to_s.upcase, params[2].to_s.upcase] if @current_limits_group
204
+
205
+ #######################################################################
206
+ # All the following keywords must have a current packet defined
207
+ #######################################################################
208
+ when 'SELECT_ITEM', 'SELECT_PARAMETER', 'DELETE_ITEM', 'DELETE_PARAMETER', 'ITEM',\
209
+ 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
210
+ 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
211
+ 'APPEND_ARRAY_PARAMETER', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META',\
212
+ 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
213
+ raise parser.error("No current packet for #{keyword}") unless @current_packet
214
+
215
+ process_current_packet(parser, keyword, params)
216
+
217
+ #######################################################################
218
+ # All the following keywords must have a current item defined
219
+ #######################################################################
220
+ when 'STATE', 'READ_CONVERSION', 'WRITE_CONVERSION', 'POLY_READ_CONVERSION',\
221
+ 'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION',\
222
+ 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED',\
223
+ 'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',\
224
+ 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP'
225
+ raise parser.error("No current item for #{keyword}") unless @current_item
226
+
227
+ process_current_item(parser, keyword, params)
228
+
229
+ else
230
+ # blank config.lines will have a nil keyword and should not raise an exception
231
+ raise parser.error("Unknown keyword '#{keyword}'") if keyword
232
+ end # case keyword
233
+
234
+ end # if building_generic_conversion
235
+ end
236
+
237
+ # Complete the last defined packet
238
+ finish_packet()
239
+ end
240
+
241
+ # Convert the PacketConfig back to OpenC3 configuration files for each target
242
+ def to_config(output_dir)
243
+ FileUtils.mkdir_p(output_dir)
244
+
245
+ @telemetry.each do |target_name, packets|
246
+ next if target_name == 'UNKNOWN'
247
+
248
+ FileUtils.mkdir_p(File.join(output_dir, target_name, 'cmd_tlm'))
249
+ filename = File.join(output_dir, target_name, 'cmd_tlm', target_name.downcase + '_tlm.txt')
250
+ begin
251
+ File.delete(filename)
252
+ rescue
253
+ # Doesn't exist
254
+ end
255
+ packets.each do |packet_name, packet|
256
+ File.open(filename, 'a') do |file|
257
+ file.puts packet.to_config(:TELEMETRY)
258
+ file.puts ""
259
+ end
260
+ end
261
+ end
262
+
263
+ @commands.each do |target_name, packets|
264
+ next if target_name == 'UNKNOWN'
265
+
266
+ FileUtils.mkdir_p(File.join(output_dir, target_name, 'cmd_tlm'))
267
+ filename = File.join(output_dir, target_name, 'cmd_tlm', target_name.downcase + '_cmd.txt')
268
+ begin
269
+ File.delete(filename)
270
+ rescue
271
+ # Doesn't exist
272
+ end
273
+ packets.each do |packet_name, packet|
274
+ File.open(filename, 'a') do |file|
275
+ file.puts packet.to_config(:COMMAND)
276
+ file.puts ""
277
+ end
278
+ end
279
+ end
280
+
281
+ # Put limits groups into SYSTEM target
282
+ if @limits_groups.length > 0
283
+ FileUtils.mkdir_p(File.join(output_dir, 'SYSTEM', 'cmd_tlm'))
284
+ filename = File.join(output_dir, 'SYSTEM', 'cmd_tlm', 'limits_groups.txt')
285
+ File.open(filename, 'w') do |file|
286
+ @limits_groups.each do |limits_group_name, limits_group_items|
287
+ file.puts "LIMITS_GROUP #{limits_group_name.to_s.quote_if_necessary}"
288
+ limits_group_items.each do |target_name, packet_name, item_name|
289
+ file.puts " LIMITS_GROUP_ITEM #{target_name.to_s.quote_if_necessary} #{packet_name.to_s.quote_if_necessary} #{item_name.to_s.quote_if_necessary}"
290
+ end
291
+ file.puts ""
292
+ end
293
+ end
294
+ end
295
+ end # def to_config
296
+
297
+ def to_xtce(output_dir)
298
+ XtceConverter.convert(@commands, @telemetry, output_dir)
299
+ end
300
+
301
+ # Add current packet into hash if it exists
302
+ def finish_packet
303
+ finish_item()
304
+ if @current_packet
305
+ @warnings += @current_packet.check_bit_offsets
306
+ if @current_cmd_or_tlm == COMMAND
307
+ PacketParser.check_item_data_types(@current_packet)
308
+ @commands[@current_packet.target_name][@current_packet.packet_name] = @current_packet
309
+ hash = @cmd_id_value_hash[@current_packet.target_name]
310
+ hash = {} unless hash
311
+ @cmd_id_value_hash[@current_packet.target_name] = hash
312
+ update_id_value_hash(hash)
313
+ else
314
+ @telemetry[@current_packet.target_name][@current_packet.packet_name] = @current_packet
315
+ hash = @tlm_id_value_hash[@current_packet.target_name]
316
+ hash = {} unless hash
317
+ @tlm_id_value_hash[@current_packet.target_name] = hash
318
+ update_id_value_hash(hash)
319
+ end
320
+ @current_packet = nil
321
+ @current_item = nil
322
+ end
323
+ end
324
+
325
+ protected
326
+
327
+ def update_id_value_hash(hash)
328
+ if @current_packet.id_items.length > 0
329
+ key = []
330
+ @current_packet.id_items.each do |item|
331
+ key << item.id_value
332
+ end
333
+ hash[key] = @current_packet
334
+ else
335
+ hash['CATCHALL'.freeze] = @current_packet
336
+ end
337
+ end
338
+
339
+ def reset_processing_variables
340
+ @current_cmd_or_tlm = nil
341
+ @current_packet = nil
342
+ @current_item = nil
343
+ @current_limits_group = nil
344
+ end
345
+
346
+ def process_current_packet(parser, keyword, params)
347
+ case keyword
348
+
349
+ # Select or delete an item in the current packet
350
+ when 'SELECT_PARAMETER', 'SELECT_ITEM', 'DELETE_PARAMETER', 'DELETE_ITEM'
351
+ if (@current_cmd_or_tlm == COMMAND) && (keyword.split('_')[1] == 'ITEM')
352
+ raise parser.error("#{keyword} only applies to telemetry packets")
353
+ end
354
+ if (@current_cmd_or_tlm == TELEMETRY) && (keyword.split('_')[1] == 'PARAMETER')
355
+ raise parser.error("#{keyword} only applies to command packets")
356
+ end
357
+
358
+ usage = "#{keyword} <#{keyword.split('_')[1]} NAME>"
359
+ finish_item()
360
+ parser.verify_num_parameters(1, 1, usage)
361
+ begin
362
+ if keyword.include?("SELECT")
363
+ @current_item = @current_packet.get_item(params[0])
364
+ else # DELETE
365
+ @current_packet.delete_item(params[0])
366
+ end
367
+ rescue # Rescue the default execption to provide a nicer error message
368
+ raise parser.error("#{params[0]} not found in #{@current_cmd_or_tlm.downcase} packet #{@current_packet.target_name} #{@current_packet.packet_name}", usage)
369
+ end
370
+
371
+ # Start a new telemetry item in the current packet
372
+ when 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER',\
373
+ 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER',\
374
+ 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER'
375
+ start_item(parser)
376
+
377
+ # Allow this packet to be received with less data than the defined length
378
+ # without generating a warning.
379
+ when 'ALLOW_SHORT'
380
+ @current_packet.short_buffer_allowed = true
381
+
382
+ # Mark the current command as hazardous
383
+ when 'HAZARDOUS'
384
+ usage = "HAZARDOUS <HAZARDOUS DESCRIPTION (Optional)>"
385
+ parser.verify_num_parameters(0, 1, usage)
386
+ @current_packet.hazardous = true
387
+ @current_packet.hazardous_description = params[0] if params[0]
388
+
389
+ # Define a processor class that will be called once when a packet is received
390
+ when 'PROCESSOR'
391
+ ProcessorParser.parse(parser, @current_packet, @current_cmd_or_tlm)
392
+
393
+ when 'DISABLE_MESSAGES'
394
+ usage = "#{keyword}"
395
+ parser.verify_num_parameters(0, 0, usage)
396
+ @current_packet.messages_disabled = true
397
+
398
+ # Store user defined metadata for the packet or a packet item
399
+ when 'META'
400
+ usage = "META <META NAME> <META VALUES (optional)>"
401
+ parser.verify_num_parameters(1, nil, usage)
402
+ if params.length > 1
403
+ meta_values = params[1..-1]
404
+ else
405
+ meta_values = []
406
+ end
407
+ meta_values.each_with_index do |value, index|
408
+ if String === value
409
+ meta_values[index] = value.to_utf8
410
+ end
411
+ end
412
+ if @current_item
413
+ # Item META
414
+ @current_item.meta[params[0].to_s.upcase] = meta_values
415
+ else
416
+ # Packet META
417
+ @current_packet.meta[params[0].to_s.upcase] = meta_values
418
+ end
419
+
420
+ when 'HIDDEN'
421
+ usage = "#{keyword}"
422
+ parser.verify_num_parameters(0, 0, usage)
423
+ @current_packet.hidden = true
424
+
425
+ when 'DISABLED'
426
+ usage = "#{keyword}"
427
+ parser.verify_num_parameters(0, 0, usage)
428
+ @current_packet.hidden = true
429
+ @current_packet.disabled = true
430
+
431
+ end
432
+ end
433
+
434
+ def process_current_item(parser, keyword, params)
435
+ case keyword
436
+
437
+ # Add a state to the current telemety item
438
+ when 'STATE'
439
+ StateParser.parse(parser, @current_packet, @current_cmd_or_tlm, @current_item, @warnings)
440
+
441
+ # Apply a conversion to the current item after it is read to or
442
+ # written from the packet
443
+ when 'READ_CONVERSION', 'WRITE_CONVERSION'
444
+ usage = "#{keyword} <conversion class filename> <custom parameters> ..."
445
+ parser.verify_num_parameters(1, nil, usage)
446
+ begin
447
+ # require should be performed in target.txt
448
+ klass = params[0].filename_to_class_name.to_class
449
+ raise parser.error("#{params[0].filename_to_class_name} class not found. Did you require the file in target.txt?", usage) unless klass
450
+
451
+ conversion = klass.new(*params[1..(params.length - 1)])
452
+ @current_item.public_send("#{keyword.downcase}=".to_sym, conversion)
453
+ if klass != ProcessorConversion and (conversion.converted_type.nil? or conversion.converted_bit_size.nil?)
454
+ msg = "Read Conversion #{params[0].filename_to_class_name} on item #{@current_item.name} does not specify converted type or bit size"
455
+ @warnings << msg
456
+ Logger.instance.warn @warnings[-1]
457
+ end
458
+ rescue Exception => err
459
+ raise parser.error(err)
460
+ end
461
+
462
+ # Apply a polynomial conversion to the current item
463
+ when 'POLY_READ_CONVERSION', 'POLY_WRITE_CONVERSION'
464
+ usage = "#{keyword} <C0> <C1> <C2> ..."
465
+ parser.verify_num_parameters(1, nil, usage)
466
+ @current_item.read_conversion = PolynomialConversion.new(*params) if keyword.include? "READ"
467
+ @current_item.write_conversion = PolynomialConversion.new(*params) if keyword.include? "WRITE"
468
+
469
+ # Apply a segmented polynomial conversion to the current item
470
+ # after it is read from the telemetry packet
471
+ when 'SEG_POLY_READ_CONVERSION'
472
+ usage = "SEG_POLY_READ_CONVERSION <Lower Bound> <C0> <C1> <C2> ..."
473
+ parser.verify_num_parameters(2, nil, usage)
474
+ if !(@current_item.read_conversion &&
475
+ SegmentedPolynomialConversion === @current_item.read_conversion)
476
+ @current_item.read_conversion = SegmentedPolynomialConversion.new
477
+ end
478
+ @current_item.read_conversion.add_segment(params[0].to_f, *params[1..-1])
479
+
480
+ # Apply a segmented polynomial conversion to the current item
481
+ # before it is written to the telemetry packet
482
+ when 'SEG_POLY_WRITE_CONVERSION'
483
+ usage = "SEG_POLY_WRITE_CONVERSION <Lower Bound> <C0> <C1> <C2> ..."
484
+ parser.verify_num_parameters(2, nil, usage)
485
+ if !(@current_item.write_conversion &&
486
+ SegmentedPolynomialConversion === @current_item.write_conversion)
487
+ @current_item.write_conversion = SegmentedPolynomialConversion.new
488
+ end
489
+ @current_item.write_conversion.add_segment(params[0].to_f, *params[1..-1])
490
+
491
+ # Start the definition of a generic conversion.
492
+ # All config.lines following this config.line are considered part
493
+ # of the conversion until an end of conversion marker is found
494
+ when 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START'
495
+ usage = "#{keyword} <Converted Type (optional)> <Converted Bit Size (optional)>"
496
+ parser.verify_num_parameters(0, 2, usage)
497
+ @proc_text = ''
498
+ @building_generic_conversion = true
499
+ @converted_type = nil
500
+ @converted_bit_size = nil
501
+ if params[0]
502
+ @converted_type = params[0].upcase.intern
503
+ raise parser.error("Invalid converted_type: #{@converted_type}.") unless [:INT, :UINT, :FLOAT, :STRING, :BLOCK].include? @converted_type
504
+ end
505
+ @converted_bit_size = Integer(params[1]) if params[1]
506
+ if @converted_type.nil? or @converted_bit_size.nil?
507
+ msg = "Generic Conversion on item #{@current_item.name} does not specify converted type or bit size"
508
+ @warnings << msg
509
+ Logger.instance.warn @warnings[-1]
510
+ end
511
+
512
+ # Define a set of limits for the current telemetry item
513
+ when 'LIMITS'
514
+ @limits_sets << LimitsParser.parse(parser, @current_packet, @current_cmd_or_tlm, @current_item, @warnings)
515
+ @limits_sets.uniq!
516
+
517
+ # Define a response class that will be called when the limits state of the
518
+ # current item changes.
519
+ when 'LIMITS_RESPONSE'
520
+ LimitsResponseParser.parse(parser, @current_item, @current_cmd_or_tlm)
521
+
522
+ # Define a printf style formatting string for the current telemetry item
523
+ when 'FORMAT_STRING'
524
+ FormatStringParser.parse(parser, @current_item)
525
+
526
+ # Define the units of the current telemetry item
527
+ when 'UNITS'
528
+ usage = "UNITS <FULL UNITS NAME> <ABBREVIATED UNITS NAME>"
529
+ parser.verify_num_parameters(2, 2, usage)
530
+ @current_item.units_full = params[0]
531
+ @current_item.units = params[1]
532
+
533
+ # Update the description for the current telemetry item
534
+ when 'DESCRIPTION'
535
+ usage = "DESCRIPTION <DESCRIPTION>"
536
+ parser.verify_num_parameters(1, 1, usage)
537
+ @current_item.description = params[0]
538
+
539
+ # Mark the current command parameter as required.
540
+ # This means it must be given a value and not just use its default.
541
+ when 'REQUIRED'
542
+ usage = "REQUIRED"
543
+ parser.verify_num_parameters(0, 0, usage)
544
+ if @current_cmd_or_tlm == COMMAND
545
+ @current_item.required = true
546
+ else
547
+ raise parser.error("#{keyword} only applies to command parameters")
548
+ end
549
+
550
+ # Update the mimimum value for the current command parameter
551
+ when 'MINIMUM_VALUE'
552
+ if @current_cmd_or_tlm == TELEMETRY
553
+ raise parser.error("#{keyword} only applies to command parameters")
554
+ end
555
+
556
+ usage = "MINIMUM_VALUE <MINIMUM VALUE>"
557
+ parser.verify_num_parameters(1, 1, usage)
558
+ min = ConfigParser.handle_defined_constants(
559
+ params[0].convert_to_value, @current_item.data_type, @current_item.bit_size
560
+ )
561
+ @current_item.range = Range.new(min, @current_item.range.end)
562
+
563
+ # Update the maximum value for the current command parameter
564
+ when 'MAXIMUM_VALUE'
565
+ if @current_cmd_or_tlm == TELEMETRY
566
+ raise parser.error("#{keyword} only applies to command parameters")
567
+ end
568
+
569
+ usage = "MAXIMUM_VALUE <MAXIMUM VALUE>"
570
+ parser.verify_num_parameters(1, 1, usage)
571
+ max = ConfigParser.handle_defined_constants(
572
+ params[0].convert_to_value, @current_item.data_type, @current_item.bit_size
573
+ )
574
+ @current_item.range = Range.new(@current_item.range.begin, max)
575
+
576
+ # Update the default value for the current command parameter
577
+ when 'DEFAULT_VALUE'
578
+ if @current_cmd_or_tlm == TELEMETRY
579
+ raise parser.error("#{keyword} only applies to command parameters")
580
+ end
581
+
582
+ usage = "DEFAULT_VALUE <DEFAULT VALUE>"
583
+ parser.verify_num_parameters(1, 1, usage)
584
+ if (@current_item.data_type == :STRING) ||
585
+ (@current_item.data_type == :BLOCK)
586
+ @current_item.default = params[0]
587
+ else
588
+ @current_item.default = ConfigParser.handle_defined_constants(
589
+ params[0].convert_to_value, @current_item.data_type, @current_item.bit_size
590
+ )
591
+ end
592
+
593
+ # Update the overflow type for the current command parameter
594
+ when 'OVERFLOW'
595
+ usage = "OVERFLOW <OVERFLOW VALUE - ERROR, ERROR_ALLOW_HEX, TRUNCATE, or SATURATE>"
596
+ parser.verify_num_parameters(1, 1, usage)
597
+ @current_item.overflow = params[0].to_s.upcase.intern
598
+
599
+ when 'OVERLAP'
600
+ parser.verify_num_parameters(0, 0, 'OVERLAP')
601
+ @current_item.overlap = true
602
+
603
+ end
604
+ end
605
+
606
+ def start_item(parser)
607
+ finish_item()
608
+ @current_item = PacketItemParser.parse(parser, @current_packet, @current_cmd_or_tlm, @warnings)
609
+ end
610
+
611
+ # Finish updating packet item
612
+ def finish_item
613
+ if @current_item
614
+ @current_packet.set_item(@current_item)
615
+ if @current_cmd_or_tlm == TELEMETRY
616
+ target_latest_data = @latest_data[@current_packet.target_name]
617
+ target_latest_data[@current_item.name] ||= []
618
+ latest_data_packets = target_latest_data[@current_item.name]
619
+ latest_data_packets << @current_packet unless latest_data_packets.include?(@current_packet)
620
+ end
621
+ @current_item = nil
622
+ end
623
+ end
624
+ end
625
+ end