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,206 @@
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/interfaces/protocols/burst_protocol'
21
+
22
+ module OpenC3
23
+ # Delineates packets using the OpenC3 preidentification system
24
+ class PreidentifiedProtocol < BurstProtocol
25
+ COSMOS4_STORED_FLAG_MASK = 0x80
26
+ COSMOS4_EXTRA_FLAG_MASK = 0x40
27
+
28
+ # @param sync_pattern (see BurstProtocol#initialize)
29
+ # @param max_length [Integer] The maximum allowed value of the length field
30
+ # @param allow_empty_data [true/false/nil] See Protocol#initialize
31
+ def initialize(sync_pattern = nil, max_length = nil, mode = 4, allow_empty_data = nil)
32
+ super(0, sync_pattern, false, allow_empty_data)
33
+ @max_length = ConfigParser.handle_nil(max_length)
34
+ @max_length = Integer(@max_length) if @max_length
35
+ @mode = Integer(mode)
36
+ end
37
+
38
+ def reset
39
+ super()
40
+ @reduction_state = :START
41
+ end
42
+
43
+ def read_packet(packet)
44
+ packet.received_time = @read_received_time
45
+ packet.target_name = @read_target_name
46
+ packet.packet_name = @read_packet_name
47
+ if @mode == 4 # COSMOS4.3+ Protocol
48
+ packet.stored = @read_stored
49
+ packet.extra = @read_extra
50
+ end
51
+ return packet
52
+ end
53
+
54
+ def write_packet(packet)
55
+ received_time = packet.received_time
56
+ received_time = Time.now unless received_time
57
+ @write_time_seconds = [received_time.tv_sec].pack('N') # UINT32
58
+ @write_time_microseconds = [received_time.tv_usec].pack('N') # UINT32
59
+ @write_target_name = packet.target_name
60
+ @write_target_name = 'UNKNOWN' unless @write_target_name
61
+ @write_packet_name = packet.packet_name
62
+ @write_packet_name = 'UNKNOWN' unless @write_packet_name
63
+ if @mode == 4 # COSMOS4.3+ Protocol
64
+ @write_flags = 0
65
+ @write_flags |= COSMOS4_STORED_FLAG_MASK if packet.stored
66
+ @write_extra = nil
67
+ if packet.extra
68
+ @write_flags |= COSMOS4_EXTRA_FLAG_MASK
69
+ @write_extra = packet.extra.as_json(:allow_nan => true).to_json(:allow_nan => true)
70
+ end
71
+ end
72
+ return packet
73
+ end
74
+
75
+ def write_data(data)
76
+ data_length = [data.length].pack('N') # UINT32
77
+ data_to_send = ''
78
+ data_to_send << @sync_pattern if @sync_pattern
79
+ if @mode == 4 # COSMOS4.3+ Protocol
80
+ data_to_send << @write_flags
81
+ if @write_extra
82
+ data_to_send << [@write_extra.length].pack('N')
83
+ data_to_send << @write_extra
84
+ end
85
+ end
86
+ data_to_send << @write_time_seconds
87
+ data_to_send << @write_time_microseconds
88
+ data_to_send << @write_target_name.length
89
+ data_to_send << @write_target_name
90
+ data_to_send << @write_packet_name.length
91
+ data_to_send << @write_packet_name
92
+ data_to_send << data_length
93
+ data_to_send << data
94
+ return data_to_send
95
+ end
96
+
97
+ protected
98
+
99
+ def read_length_field_followed_by_string(length_num_bytes)
100
+ # Read bytes for string length
101
+ return :STOP if @data.length < length_num_bytes
102
+
103
+ string_length = @data[0..(length_num_bytes - 1)]
104
+
105
+ case length_num_bytes
106
+ when 1
107
+ string_length = string_length.unpack('C')[0] # UINT8
108
+ when 2
109
+ string_length = string_length.unpack('n')[0] # UINT16
110
+ when 4
111
+ string_length = string_length.unpack('N')[0] # UINT32
112
+ raise "Length value received larger than max_length: #{string_length} > #{@max_length}" if @max_length and string_length > @max_length
113
+ else
114
+ raise "Unsupported length given to read_length_field_followed_by_string: #{length_num_bytes}"
115
+ end
116
+
117
+ # Read String
118
+ return :STOP if @data.length < (string_length + length_num_bytes)
119
+
120
+ next_index = string_length + length_num_bytes
121
+ string = @data[length_num_bytes..(next_index - 1)]
122
+
123
+ # Remove data from current_data
124
+ @data.replace(@data[next_index..-1])
125
+
126
+ return string
127
+ end
128
+
129
+ def reduce_to_single_packet
130
+ # Discard sync pattern if present
131
+ if @sync_pattern
132
+ if @reduction_state == :START
133
+ return :STOP if @data.length < @sync_pattern.length
134
+
135
+ @data.replace(@data[(@sync_pattern.length)..-1])
136
+ @reduction_state = :SYNC_REMOVED
137
+ end
138
+ elsif @reduction_state == :START
139
+ @reduction_state = :SYNC_REMOVED
140
+ end
141
+
142
+ if @reduction_state == :SYNC_REMOVED and @mode == 4
143
+ # Read and remove flags
144
+ return :STOP if @data.length < 1
145
+
146
+ flags = @data[0].unpack('C')[0] # byte
147
+ @data.replace(@data[1..-1])
148
+ @read_stored = false
149
+ @read_stored = true if (flags & COSMOS4_STORED_FLAG_MASK) != 0
150
+ @read_extra = nil
151
+ if (flags & COSMOS4_EXTRA_FLAG_MASK) != 0
152
+ @reduction_state = :NEED_EXTRA
153
+ else
154
+ @reduction_state = :FLAGS_REMOVED
155
+ end
156
+ end
157
+
158
+ if @reduction_state == :NEED_EXTRA
159
+ # Read and remove extra
160
+ @read_extra = read_length_field_followed_by_string(4)
161
+ return :STOP if @read_extra == :STOP
162
+
163
+ @read_extra = JSON.parse(@read_extra, :allow_nan => true, :create_additions => true)
164
+ @reduction_state = :FLAGS_REMOVED
165
+ end
166
+
167
+ if @reduction_state == :FLAGS_REMOVED or (@reduction_state == :SYNC_REMOVED and @mode != 4)
168
+ # Read and remove packet received time
169
+ return :STOP if @data.length < 8
170
+
171
+ time_seconds = @data[0..3].unpack('N')[0] # UINT32
172
+ time_microseconds = @data[4..7].unpack('N')[0] # UINT32
173
+ @read_received_time = Time.at(time_seconds, time_microseconds).sys
174
+ @data.replace(@data[8..-1])
175
+ @reduction_state = :TIME_REMOVED
176
+ end
177
+
178
+ if @reduction_state == :TIME_REMOVED
179
+ # Read and remove the target name
180
+ @read_target_name = read_length_field_followed_by_string(1)
181
+ return :STOP if @read_target_name == :STOP
182
+
183
+ @reduction_state = :TARGET_NAME_REMOVED
184
+ end
185
+
186
+ if @reduction_state == :TARGET_NAME_REMOVED
187
+ # Read and remove the packet name
188
+ @read_packet_name = read_length_field_followed_by_string(1)
189
+ return :STOP if @read_packet_name == :STOP
190
+
191
+ @reduction_state = :PACKET_NAME_REMOVED
192
+ end
193
+
194
+ if @reduction_state == :PACKET_NAME_REMOVED
195
+ # Read packet data and return
196
+ packet_data = read_length_field_followed_by_string(4)
197
+ return :STOP if packet_data == :STOP
198
+
199
+ @reduction_state = :START
200
+ return packet_data
201
+ end
202
+
203
+ raise "Error should never reach end of method #{@reduction_state}"
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+
16
+ # Modified by OpenC3, Inc.
17
+ # All changes Copyright 2022, OpenC3, Inc.
18
+ # All Rights Reserved
19
+
20
+ require 'openc3/config/config_parser'
21
+ require 'thread'
22
+
23
+ module OpenC3
24
+ # Base class for all OpenC3 protocols which defines a framework which must be
25
+ # implemented by a subclass.
26
+ class Protocol
27
+ attr_accessor :interface
28
+ attr_accessor :allow_empty_data
29
+
30
+ # @param allow_empty_data [true/false/nil] Whether or not this protocol will allow an empty string
31
+ # to be passed down to later Protocols (instead of returning :STOP). Can be true, false, or nil, where
32
+ # nil is interpreted as true unless the Protocol is the last Protocol of the chain.
33
+ def initialize(allow_empty_data = nil)
34
+ @interface = nil
35
+ @allow_empty_data = ConfigParser.handle_true_false_nil(allow_empty_data)
36
+ reset()
37
+ end
38
+
39
+ def reset
40
+ end
41
+
42
+ def connect_reset
43
+ reset()
44
+ end
45
+
46
+ def disconnect_reset
47
+ reset()
48
+ end
49
+
50
+ # Ensure we have some data in case this is the only protocol
51
+ def read_data(data)
52
+ if data.length <= 0
53
+ if @allow_empty_data.nil?
54
+ if @interface and @interface.read_protocols[-1] == self
55
+ # Last read interface in chain with auto @allow_empty_data
56
+ return :STOP
57
+ end
58
+ elsif !@allow_empty_data
59
+ # Don't @allow_empty_data means STOP
60
+ return :STOP
61
+ end
62
+ end
63
+ data
64
+ end
65
+
66
+ def read_packet(packet)
67
+ return packet
68
+ end
69
+
70
+ def write_packet(packet)
71
+ return packet
72
+ end
73
+
74
+ def write_data(data)
75
+ return data
76
+ end
77
+
78
+ def post_write_interface(packet, data)
79
+ return packet, data
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,261 @@
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/interfaces/protocols/terminated_protocol'
22
+ require 'thread' # For Queue
23
+ require 'timeout' # For Timeout::Error
24
+
25
+ module OpenC3
26
+ # Protocol which delineates packets using delimiter characters. Designed for
27
+ # text based protocols which expect a command and send a response. The
28
+ # protocol handles sending the command and capturing the response.
29
+ class TemplateProtocol < TerminatedProtocol
30
+ # @param write_termination_characters (see TerminatedProtocol#initialize)
31
+ # @param read_termination_characters (see TerminatedProtocol#initialize)
32
+ # @param ignore_lines [Integer] Number of newline terminated reads to
33
+ # ignore when processing the response
34
+ # @param initial_read_delay [Integer] Initial delay when connecting before
35
+ # trying to read
36
+ # @param response_lines [Integer] Number of newline terminated lines which
37
+ # comprise the response
38
+ # @param strip_read_termination (see TerminatedProtocol#initialize)
39
+ # @param discard_leading_bytes (see TerminatedProtocol#initialize)
40
+ # @param sync_pattern (see TerminatedProtocol#initialize)
41
+ # @param fill_fields (see TerminatedProtocol#initialize)
42
+ # @param response_timeout [Float] Number of seconds to wait before timing out
43
+ # when waiting for a response
44
+ # @param response_polling_period [Float] Number of seconds to wait between polling
45
+ # for a response
46
+ # @param raise_exceptions [String] Whether to raise exceptions when errors
47
+ # occur in the protocol like unexpected responses or response timeouts.
48
+ # @param allow_empty_data [true/false/nil] See Protocol#initialize
49
+ def initialize(
50
+ write_termination_characters,
51
+ read_termination_characters,
52
+ ignore_lines = 0,
53
+ initial_read_delay = nil,
54
+ response_lines = 1,
55
+ strip_read_termination = true,
56
+ discard_leading_bytes = 0,
57
+ sync_pattern = nil,
58
+ fill_fields = false,
59
+ response_timeout = 5.0,
60
+ response_polling_period = 0.02,
61
+ raise_exceptions = false,
62
+ allow_empty_data = nil
63
+ )
64
+ super(
65
+ write_termination_characters,
66
+ read_termination_characters,
67
+ strip_read_termination,
68
+ discard_leading_bytes,
69
+ sync_pattern,
70
+ fill_fields,
71
+ allow_empty_data)
72
+ @response_template = nil
73
+ @response_packet = nil
74
+ @response_target_name = nil
75
+ @response_packets = []
76
+ @write_block_queue = Queue.new
77
+ @ignore_lines = ignore_lines.to_i
78
+ @response_lines = response_lines.to_i
79
+ @initial_read_delay = ConfigParser.handle_nil(initial_read_delay)
80
+ @initial_read_delay = @initial_read_delay.to_f if @initial_read_delay
81
+ @response_timeout = ConfigParser.handle_nil(response_timeout)
82
+ @response_timeout = @response_timeout.to_f if @response_timeout
83
+ @response_polling_period = response_polling_period.to_f
84
+ @connect_complete_time = nil
85
+ @raise_exceptions = ConfigParser.handle_true_false(raise_exceptions)
86
+ end
87
+
88
+ def reset
89
+ super()
90
+ @initial_read_delay_needed = true
91
+ end
92
+
93
+ def connect_reset
94
+ super()
95
+ begin
96
+ @write_block_queue.pop(true) while @write_block_queue.length > 0
97
+ rescue
98
+ end
99
+
100
+ @connect_complete_time = Time.now + @initial_read_delay if @initial_read_delay
101
+ end
102
+
103
+ def disconnect_reset
104
+ super()
105
+ @write_block_queue << nil # Unblock the write block queue
106
+ end
107
+
108
+ def read_data(data)
109
+ return super(data) if data.length <= 0
110
+
111
+ # Drop all data until the initial_read_delay is complete.
112
+ # This gets rid of unused welcome messages,
113
+ # prompts, and other junk on initial connections
114
+ if @initial_read_delay and @initial_read_delay_needed and @connect_complete_time
115
+ return :STOP if Time.now < @connect_complete_time
116
+
117
+ @initial_read_delay_needed = false
118
+ end
119
+ super(data)
120
+ end
121
+
122
+ def read_packet(packet)
123
+ if @response_template && @response_packet
124
+ # If lines make it this far they are part of a response
125
+ @response_packets << packet
126
+ return :STOP if @response_packets.length < (@ignore_lines + @response_lines)
127
+
128
+ @ignore_lines.times do
129
+ @response_packets.shift
130
+ end
131
+ response_string = ''
132
+ @response_lines.times do
133
+ response = @response_packets.shift
134
+ response_string << response.buffer
135
+ end
136
+
137
+ # Grab the response packet specified in the command
138
+ result_packet = System.telemetry.packet(@response_target_name, @response_packet).clone
139
+ result_packet.received_time = nil
140
+ result_packet.id_items.each do |item|
141
+ result_packet.write_item(item, item.id_value, :RAW)
142
+ end
143
+
144
+ # Convert the response template into a Regexp
145
+ response_item_names = []
146
+ response_template = @response_template.clone
147
+ response_template_items = @response_template.scan(/<.*?>/)
148
+
149
+ response_template_items.each do |item|
150
+ response_item_names << item[1..-2]
151
+ response_template.gsub!(item, "(.*)")
152
+ end
153
+ response_regexp = Regexp.new(response_template)
154
+
155
+ # Scan the response for the variables in brackets <VARIABLE>
156
+ # Write the packet value with each of the values received
157
+ response_values = response_string.scan(response_regexp)[0]
158
+ if !response_values || (response_values.length != response_item_names.length)
159
+ handle_error("#{@interface ? @interface.name : ""}: Unexpected response: #{response_string}")
160
+ else
161
+ response_values.each_with_index do |value, i|
162
+ result_packet.write(response_item_names[i], value)
163
+ rescue => error
164
+ handle_error("#{@interface ? @interface.name : ""}: Could not write value #{value} due to #{error.message}")
165
+ break
166
+ end
167
+ end
168
+
169
+ @response_packets.clear
170
+
171
+ # Release the write
172
+ if @response_template && @response_packet
173
+ @write_block_queue << nil
174
+ end
175
+
176
+ return result_packet
177
+ else
178
+ return packet
179
+ end
180
+ end
181
+
182
+ def write_packet(packet)
183
+ # Make sure we are past the initial data dropping period
184
+ if @initial_read_delay and @initial_read_delay_needed and @connect_complete_time and Time.now < @connect_complete_time
185
+ delay_needed = @connect_complete_time - Time.now
186
+ sleep(delay_needed) if delay_needed > 0
187
+ end
188
+
189
+ # First grab the response template and response packet (if there is one)
190
+ begin
191
+ @response_template = packet.read("RSP_TEMPLATE").strip
192
+ @response_packet = packet.read("RSP_PACKET").strip
193
+ @response_target_name = packet.target_name
194
+ # If the template or packet are empty set them to nil. This allows for
195
+ # the user to remove the RSP_TEMPLATE and RSP_PACKET values and avoid
196
+ # any response timeouts
197
+ if @response_template.empty? || @response_packet.empty?
198
+ @response_template = nil
199
+ @response_packet = nil
200
+ @response_target_name = nil
201
+ end
202
+ rescue
203
+ # If there is no response template we set to nil
204
+ @response_template = nil
205
+ @response_packet = nil
206
+ @response_target_name = nil
207
+ end
208
+
209
+ # Grab the command template because that is all we eventually send
210
+ @template = packet.read("CMD_TEMPLATE")
211
+ # Create a new packet to populate with the template
212
+ raw_packet = Packet.new(nil, nil)
213
+ raw_packet.buffer = @template
214
+ raw_packet = super(raw_packet)
215
+ return raw_packet if Symbol === raw_packet
216
+
217
+ data = raw_packet.buffer(false)
218
+ # Scan the template for variables in brackets <VARIABLE>
219
+ # Read these values from the packet and substitute them in the template
220
+ # and in the @response_packet name
221
+ @template.scan(/<(.*?)>/).each do |variable|
222
+ value = packet.read(variable[0], :RAW).to_s
223
+ data.gsub!("<#{variable[0]}>", value)
224
+ @response_packet.gsub!("<#{variable[0]}>", value) if @response_packet
225
+ end
226
+
227
+ return raw_packet
228
+ end
229
+
230
+ def post_write_interface(packet, data)
231
+ if @response_template && @response_packet
232
+ if @response_timeout
233
+ response_timeout_time = Time.now + @response_timeout
234
+ else
235
+ response_timeout_time = nil
236
+ end
237
+
238
+ # Block the write until the response is received
239
+ begin
240
+ @write_block_queue.pop(true)
241
+ rescue
242
+ sleep(@response_polling_period)
243
+ retry if !response_timeout_time
244
+ retry if response_timeout_time and Time.now < response_timeout_time
245
+ handle_error("#{@interface ? @interface.name : ""}: Timeout waiting for response")
246
+ end
247
+
248
+ @response_template = nil
249
+ @response_packet = nil
250
+ @response_target_name = nil
251
+ @response_packets.clear
252
+ end
253
+ return super(packet, data)
254
+ end
255
+
256
+ def handle_error(msg)
257
+ Logger.error(msg)
258
+ raise msg if @raise_exceptions
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,93 @@
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/interfaces/protocols/burst_protocol'
22
+
23
+ module OpenC3
24
+ # Protocol which delineates packets using termination characters at
25
+ # the end of the data.
26
+ class TerminatedProtocol < BurstProtocol
27
+ # @param write_termination_characters [String] The characters to write
28
+ # after writing the Packet buffer. Must be given as a
29
+ # hexadecimal string such as '0xABCD'.
30
+ # @param read_termination_characters [String] The characters at the end of
31
+ # the data which delineate the end of a Packet. Must be given as a
32
+ # hexadecimal string such as '0xABCD'.
33
+ # @param strip_read_termination [Boolean] Whether to remove the
34
+ # read_termination_characters before turning the data into a
35
+ # Packet.
36
+ # @param discard_leading_bytes (see BurstProtocol#initialize)
37
+ # @param sync_pattern (see BurstProtocol#initialize)
38
+ # @param fill_fields (see BurstProtocol#initialize)
39
+ # @param allow_empty_data [true/false/nil] See Protocol#initialize
40
+ def initialize(
41
+ write_termination_characters,
42
+ read_termination_characters,
43
+ strip_read_termination = true,
44
+ discard_leading_bytes = 0,
45
+ sync_pattern = nil,
46
+ fill_fields = false,
47
+ allow_empty_data = nil
48
+ )
49
+ @write_termination_characters = write_termination_characters.hex_to_byte_string
50
+ @read_termination_characters = read_termination_characters.hex_to_byte_string
51
+ @strip_read_termination = ConfigParser.handle_true_false(strip_read_termination)
52
+
53
+ super(discard_leading_bytes, sync_pattern, fill_fields, allow_empty_data)
54
+ end
55
+
56
+ def write_data(data)
57
+ raise "Packet contains termination characters!" if data.index(@write_termination_characters)
58
+
59
+ data = super(data)
60
+ @write_termination_characters.each_byte do |byte|
61
+ data << byte
62
+ end
63
+ return data
64
+ end
65
+
66
+ protected
67
+
68
+ def reduce_to_single_packet
69
+ index = @data.index(@read_termination_characters)
70
+
71
+ # Reduce to packet data and setup current_data for next packet
72
+ if index
73
+ if index > 0
74
+ if @strip_read_termination
75
+ packet_data = @data[0..(index - 1)]
76
+ else
77
+ packet_data = @data[0..(index + @read_termination_characters.length - 1)]
78
+ end
79
+ else # @data begins with the termination characters
80
+ if @strip_read_termination
81
+ packet_data = ''
82
+ else # Keep everything
83
+ packet_data = @data[0..(@read_termination_characters.length - 1)]
84
+ end
85
+ end
86
+ @data.replace(@data[(index + @read_termination_characters.length)..-1])
87
+ return packet_data
88
+ else
89
+ return :STOP
90
+ end
91
+ end
92
+ end
93
+ end