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,24 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+
16
+ # Modified by OpenC3, Inc.
17
+ # All changes Copyright 2022, OpenC3, Inc.
18
+ # All Rights Reserved
19
+
20
+ module OpenC3
21
+ autoload(:Target, "openc3/system/target.rb")
22
+ autoload(:System, "openc3/system/system.rb")
23
+ autoload(:SystemConfig, "openc3/system/system_config.rb")
24
+ end
@@ -0,0 +1,20 @@
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/api/api'
@@ -0,0 +1,320 @@
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
+
22
+ module OpenC3
23
+ # Reads an ascii file that defines the configuration settings used to
24
+ # configure the Command/Telemetry Server.
25
+ class CmdTlmServerConfig
26
+ # @return [Hash<String, Interface>] Interfaces hash
27
+ attr_accessor :interfaces
28
+ # @return [Hash<String, Interface>] Routers hash
29
+ attr_accessor :routers
30
+ # @return [Hash<String, PacketLogWriterPair>] Packet log writer hash. Each
31
+ # pair encapsulates a command and telemetry log writer.
32
+ attr_accessor :packet_log_writer_pairs
33
+ # @return [Array<BackgroundTask>] Array of background tasks
34
+ attr_accessor :background_tasks
35
+ # @return [String] Command and Telemetry Server title
36
+ attr_accessor :title
37
+ # @return [Boolean] Flag indicating if meta data should be collected
38
+ attr_accessor :metadata
39
+
40
+ # Create a default pair of packet log writers and parses the
41
+ # configuration file.
42
+ #
43
+ # @param filename [String] The name of the configuration file to parse
44
+ def initialize(filename, system_config)
45
+ @system_config = system_config
46
+ @interfaces = {}
47
+ @routers = {}
48
+ @packet_log_writer_pairs = {}
49
+ # cmd_log_writer = System.default_packet_log_writer.new(:CMD, *System.default_packet_log_writer_params)
50
+ # tlm_log_writer = System.default_packet_log_writer.new(:TLM, *System.default_packet_log_writer_params)
51
+ # @packet_log_writer_pairs['DEFAULT'] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
52
+ @background_tasks = []
53
+ @title = nil
54
+ @metadata = false
55
+ process_file(filename)
56
+ end
57
+
58
+ protected
59
+
60
+ def get_target_interface_name(target_name)
61
+ @interfaces.each do |interface_name, interface|
62
+ return interface_name if interface.target_names.include?(target_name)
63
+ end
64
+ nil
65
+ end
66
+
67
+ def setup_interface_or_router
68
+ current_interface_or_router = OpenStruct.new
69
+ current_interface_or_router.interfaces = []
70
+ current_interface_or_router.routers = []
71
+ current_interface_or_router.target_names = []
72
+ current_interface_or_router
73
+ end
74
+
75
+ # Processes a file and adds in the configuration defined in the file
76
+ #
77
+ # @param filename [String] The name of the configuration file to parse
78
+ # @param recursive [Boolean] Whether process_file is being called
79
+ # recursively
80
+ def process_file(filename, recursive = false)
81
+ current_interface_or_router = nil
82
+ current_type = nil
83
+ current_interface_log_added = false
84
+
85
+ Logger.info "Processing CmdTlmServer configuration in file: #{File.expand_path(filename)}"
86
+
87
+ parser = ConfigParser.new("https://openc3.com/docs/v5")
88
+ parser.parse_file(filename) do |keyword, params|
89
+ case keyword
90
+ when 'TITLE'
91
+ raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
92
+
93
+ parser.verify_num_parameters(1, 1, "#{keyword} <Title Text>")
94
+ @title = params[0]
95
+
96
+ when 'PACKET_LOG_WRITER'
97
+ # usage = "PACKET_LOG_WRITER <Name> <Filename> <Specific Parameters>"
98
+ # parser.verify_num_parameters(2, nil, usage)
99
+ # packet_log_writer_name = params[0].upcase
100
+ # packet_log_writer_class = OpenC3.require_class(params[1])
101
+
102
+ # # Verify not overridding a packet log writer that is already associated with an interface
103
+ # packet_log_writer_pair = @packet_log_writer_pairs[packet_log_writer_name]
104
+ # if packet_log_writer_pair
105
+ # @interfaces.each do |interface_name, interface|
106
+ # if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
107
+ # raise parser.error("Redefining Packet Log Writer #{packet_log_writer_name} not allowed after it is associated with an interface")
108
+ # end
109
+ # end
110
+ # end
111
+
112
+ # if params[2]
113
+ # cmd_log_writer = packet_log_writer_class.new(:CMD, *params[2..-1])
114
+ # tlm_log_writer = packet_log_writer_class.new(:TLM, *params[2..-1])
115
+ # @packet_log_writer_pairs[packet_log_writer_name] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
116
+ # else
117
+ # cmd_log_writer = packet_log_writer_class.new(:CMD)
118
+ # tlm_log_writer = packet_log_writer_class.new(:TLM)
119
+ # @packet_log_writer_pairs[packet_log_writer_name] = PacketLogWriterPair.new(cmd_log_writer, tlm_log_writer)
120
+ # end
121
+
122
+ when 'AUTO_INTERFACE_TARGETS'
123
+ raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
124
+
125
+ usage = "#{keyword}"
126
+ parser.verify_num_parameters(0, 0, usage)
127
+ @system_config.targets.each do |target_name, target|
128
+ target_filename = File.join(target.dir, 'cmd_tlm_server.txt')
129
+ if File.exist?(target_filename)
130
+ # Skip this target if it's already been assigned an interface
131
+ next if get_target_interface_name(target.name)
132
+ raise parser.error("Cannot use #{keyword} with target name substitutions: #{target.name} != #{target.original_name}") if target.name != target.original_name
133
+
134
+ process_file(target_filename, true)
135
+ end
136
+ end
137
+
138
+ when 'INTERFACE_TARGET'
139
+ raise parser.error("#{keyword} not allowed in target #{filename}") if recursive
140
+
141
+ usage = "#{keyword} <Target Name> <Config File (defaults to cmd_tlm_server.txt)>"
142
+ parser.verify_num_parameters(1, 2, usage)
143
+ target = @system_config.targets[params[0].upcase]
144
+ raise parser.error("Unknown target: #{params[0].upcase}") unless target
145
+
146
+ interface_name = get_target_interface_name(target.name)
147
+ raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
148
+
149
+ target_filename = params[1]
150
+ target_filename = 'cmd_tlm_server.txt' unless target_filename
151
+ target_filename = File.join(target.dir, target_filename)
152
+ if File.exist?(target_filename)
153
+ process_file(target_filename, true)
154
+ else
155
+ raise parser.error("#{target_filename} does not exist")
156
+ end
157
+
158
+ when 'INTERFACE'
159
+ usage = "INTERFACE <Name> <Filename> <Specific Parameters>"
160
+ parser.verify_num_parameters(2, nil, usage)
161
+ interface_name = params[0].upcase
162
+ raise parser.error("Interface '#{interface_name}' defined twice") if @interfaces[interface_name]
163
+
164
+ # interface_class = OpenC3.require_class(params[1])
165
+ # if params[2]
166
+ # current_interface_or_router = interface_class.new(*params[2..-1])
167
+ # else
168
+ # current_interface_or_router = interface_class.new
169
+ # end
170
+ current_interface_or_router = setup_interface_or_router()
171
+ current_type = :INTERFACE
172
+ current_interface_log_added = false
173
+ # current_interface_or_router.packet_log_writer_pairs << @packet_log_writer_pairs['DEFAULT']
174
+ current_interface_or_router.name = interface_name
175
+ current_interface_or_router.config_params = params[1..-1]
176
+ @interfaces[interface_name] = current_interface_or_router
177
+
178
+ when 'LOG', 'LOG_STORED', 'DONT_LOG', 'TARGET'
179
+ raise parser.error("No current interface for #{keyword}") unless current_interface_or_router and current_type == :INTERFACE
180
+
181
+ case keyword
182
+
183
+ when 'LOG'
184
+ parser.verify_num_parameters(1, 1, "#{keyword} <Packet Log Writer Name>")
185
+ # packet_log_writer_pair = @packet_log_writer_pairs[params[0].upcase]
186
+ # raise parser.error("Unknown packet log writer: #{params[0].upcase}") unless packet_log_writer_pair
187
+ # current_interface_or_router.packet_log_writer_pairs.delete(@packet_log_writer_pairs['DEFAULT']) unless current_interface_log_added
188
+ current_interface_log_added = true
189
+ # current_interface_or_router.packet_log_writer_pairs << packet_log_writer_pair unless current_interface_or_router.packet_log_writer_pairs.include?(packet_log_writer_pair)
190
+
191
+ when 'LOG_STORED'
192
+ parser.verify_num_parameters(1, 1, "#{keyword} <Packet Log Writer Name>")
193
+ # packet_log_writer_pair = @packet_log_writer_pairs[params[0].upcase]
194
+ # raise parser.error("Unknown packet log writer: #{params[0].upcase}") unless packet_log_writer_pair
195
+ # current_interface_or_router.stored_packet_log_writer_pairs << packet_log_writer_pair unless current_interface_or_router.stored_packet_log_writer_pairs.include?(packet_log_writer_pair)
196
+
197
+ when 'DONT_LOG'
198
+ parser.verify_num_parameters(0, 0, "#{keyword}")
199
+ # current_interface_or_router.packet_log_writer_pairs = []
200
+
201
+ when 'TARGET'
202
+ parser.verify_num_parameters(1, 1, "#{keyword} <Target Name>")
203
+ target_name = params[0].upcase
204
+ target = @system_config.targets[target_name]
205
+ if target
206
+ interface_name = get_target_interface_name(target.name)
207
+ raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
208
+
209
+ target.interface = current_interface_or_router
210
+ current_interface_or_router.target_names << target_name
211
+ else
212
+ raise parser.error("Unknown target #{target_name} mapped to interface #{current_interface_or_router.name}")
213
+ end
214
+
215
+ end # end case keyword for all keywords that require a current interface
216
+
217
+ when 'DONT_CONNECT', 'DONT_RECONNECT', 'RECONNECT_DELAY', 'DISABLE_DISCONNECT', 'LOG_RAW', 'OPTION', 'PROTOCOL'
218
+ raise parser.error("No current interface or router for #{keyword}") unless current_interface_or_router
219
+
220
+ case keyword
221
+
222
+ when 'DONT_CONNECT'
223
+ parser.verify_num_parameters(0, 0, "#{keyword}")
224
+ current_interface_or_router.connect_on_startup = false
225
+
226
+ when 'DONT_RECONNECT'
227
+ parser.verify_num_parameters(0, 0, "#{keyword}")
228
+ current_interface_or_router.auto_reconnect = false
229
+
230
+ when 'RECONNECT_DELAY'
231
+ parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
232
+ current_interface_or_router.reconnect_delay = Float(params[0])
233
+
234
+ when 'DISABLE_DISCONNECT'
235
+ parser.verify_num_parameters(0, 0, "#{keyword}")
236
+ current_interface_or_router.disable_disconnect = true
237
+
238
+ when 'LOG_RAW',
239
+ parser.verify_num_parameters(0, nil, "#{keyword} <Raw Logger Class File (optional)> <Raw Logger Parameters (optional)>")
240
+ # current_interface_or_router.raw_logger_pair = RawLoggerPair.new(current_interface_or_router.name, params)
241
+ # current_interface_or_router.start_raw_logging
242
+
243
+ when 'OPTION'
244
+ parser.verify_num_parameters(2, nil, "#{keyword} <Option Name> <Option Value 1> <Option Value 2 (optional)> <etc>")
245
+ # current_interface_or_router.set_option(params[0], params[1..-1])
246
+
247
+ when 'PROTOCOL'
248
+ usage = "#{keyword} <READ WRITE READ_WRITE> <protocol filename or classname> <Protocol specific parameters>"
249
+ parser.verify_num_parameters(2, nil, usage)
250
+ unless %w(READ WRITE READ_WRITE).include? params[0].upcase
251
+ raise parser.error("Invalid protocol type: #{params[0]}", usage)
252
+ end
253
+
254
+ begin
255
+ # klass = OpenC3.require_class(params[1])
256
+ # current_interface_or_router.add_protocol(klass, params[2..-1], params[0].upcase.intern)
257
+ rescue LoadError, StandardError => error
258
+ raise parser.error(error.message, usage)
259
+ end
260
+
261
+ end # end case keyword for all keywords that require a current interface or router
262
+
263
+ when 'ROUTER'
264
+ usage = "ROUTER <Name> <Filename> <Specific Parameters>"
265
+ parser.verify_num_parameters(2, nil, usage)
266
+ router_name = params[0].upcase
267
+ raise parser.error("Router '#{router_name}' defined twice") if @routers[router_name]
268
+
269
+ # router_class = OpenC3.require_class(params[1])
270
+ # if params[2]
271
+ # current_interface_or_router = router_class.new(*params[2..-1])
272
+ # else
273
+ # current_interface_or_router = router_class.new
274
+ # end
275
+ current_interface_or_router = setup_interface_or_router()
276
+ current_type = :ROUTER
277
+ current_interface_or_router.name = router_name
278
+ @routers[router_name] = current_interface_or_router
279
+
280
+ when 'ROUTE'
281
+ raise parser.error("No current router for #{keyword}") unless current_interface_or_router and current_type == :ROUTER
282
+
283
+ usage = "ROUTE <Interface Name>"
284
+ parser.verify_num_parameters(1, 1, usage)
285
+ interface_name = params[0].upcase
286
+ interface = @interfaces[interface_name]
287
+ raise parser.error("Unknown interface #{interface_name} mapped to router #{current_interface_or_router.name}") unless interface
288
+
289
+ unless current_interface_or_router.interfaces.include? interface
290
+ current_interface_or_router.interfaces << interface
291
+ interface.routers << current_interface_or_router
292
+ end
293
+
294
+ when 'BACKGROUND_TASK'
295
+ usage = "#{keyword} <Filename> <Specific Parameters>"
296
+ parser.verify_num_parameters(1, nil, usage)
297
+ # background_task = OpenC3.require_class(params[0])
298
+ if params[1]
299
+ @background_tasks << params
300
+ else
301
+ @background_tasks << params
302
+ end
303
+
304
+ when 'STOPPED'
305
+ parser.verify_num_parameters(0, 0, "#{keyword}")
306
+ raise parser.error("No BACKGROUND_TASK defined") if @background_tasks.empty?
307
+ # @background_tasks[-1].stopped = true
308
+
309
+ when 'COLLECT_METADATA'
310
+ parser.verify_num_parameters(0, 0, "#{keyword}")
311
+ @metadata = true
312
+
313
+ else
314
+ # blank lines will have a nil keyword and should not raise an exception
315
+ raise parser.error("Unknown keyword: #{keyword}") unless keyword.nil?
316
+ end # case
317
+ end # loop
318
+ end
319
+ end
320
+ end
@@ -0,0 +1,294 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+
16
+ # Modified by OpenC3, Inc.
17
+ # All changes Copyright 2022, OpenC3, Inc.
18
+ # All Rights Reserved
19
+
20
+ module OpenC3
21
+ # Encapsulates an {Interface} in a Ruby thread. When the thread is started by
22
+ # the {#start} method, it loops trying to connect. It then continously reads
23
+ # from the interface while handling the packets it receives.
24
+ class InterfaceThread
25
+ # The number of bytes to print when an UNKNOWN packet is received
26
+ UNKNOWN_BYTES_TO_PRINT = 36
27
+
28
+ # @return [#call()] Callback which is called if the #{Interface#connect}
29
+ # method succeeds
30
+ attr_accessor :connection_success_callback
31
+ # @return [#call(Exception)] Callback which is called if the
32
+ # {Interface#connect} method throws an exception.
33
+ attr_accessor :connection_failed_callback
34
+ # @return [#call(Exception|nil)] Callback which is called if the
35
+ # interface connection is lost.
36
+ attr_accessor :connection_lost_callback
37
+ # @return [#call(Packet)] Callback which is called when a packet has been
38
+ # received from the interface and identified.
39
+ attr_accessor :identified_packet_callback
40
+ # @return [#call(Exception)] Callback which is called if the
41
+ # InterfaceThread dies for any reason.
42
+ attr_accessor :fatal_exception_callback
43
+
44
+ # @param interface [Interface] The interface to create a thread for
45
+ def initialize(interface)
46
+ @interface = interface
47
+ @connection_success_callback = nil
48
+ @connection_failed_callback = nil
49
+ @connection_lost_callback = nil
50
+ @identified_packet_callback = nil
51
+ @fatal_exception_callback = nil
52
+ @thread = nil
53
+ @thread_sleeper = Sleeper.new
54
+ @connection_failed_messages = []
55
+ @connection_lost_messages = []
56
+ @mutex = Mutex.new
57
+ end
58
+
59
+ # Create and start the Ruby thread that will encapsulate the interface.
60
+ # Creates a while loop that waits for {Interface#connect} to succeed. Then
61
+ # calls {Interface#read} and handles all the incoming packets.
62
+ def start
63
+ @thread_sleeper = Sleeper.new
64
+ @thread = Thread.new do
65
+ @cancel_thread = false
66
+ begin
67
+ if @interface.read_allowed?
68
+ Logger.info "Starting packet reading for #{@interface.name}"
69
+ else
70
+ Logger.info "Starting connection maintenance for #{@interface.name}"
71
+ end
72
+ while true
73
+ break if @cancel_thread
74
+
75
+ unless @interface.connected?
76
+ begin
77
+ @mutex.synchronize do
78
+ # We need to make sure connect is not called after stop() has been called
79
+ connect() unless @cancel_thread
80
+ end
81
+ break if @cancel_thread
82
+ rescue Exception => connect_error
83
+ handle_connection_failed(connect_error)
84
+ if @cancel_thread
85
+ break
86
+ else
87
+ next
88
+ end
89
+ end
90
+ end
91
+
92
+ if @interface.read_allowed?
93
+ begin
94
+ packet = @interface.read
95
+ unless packet
96
+ Logger.info "Clean disconnect from #{@interface.name} (returned nil)"
97
+ handle_connection_lost(nil)
98
+ if @cancel_thread
99
+ break
100
+ else
101
+ next
102
+ end
103
+ end
104
+ packet.received_time = Time.now.sys unless packet.received_time
105
+ rescue Exception => err
106
+ handle_connection_lost(err)
107
+ if @cancel_thread
108
+ break
109
+ else
110
+ next
111
+ end
112
+ end
113
+
114
+ handle_packet(packet)
115
+ else
116
+ @thread_sleeper.sleep(1)
117
+ handle_connection_lost(nil) if !@interface.connected?
118
+ end
119
+ end # loop
120
+ rescue Exception => error
121
+ if @fatal_exception_callback
122
+ @fatal_exception_callback.call(error)
123
+ else
124
+ Logger.error "Packet reading thread unexpectedly died for #{@interface.name}"
125
+ OpenC3.handle_fatal_exception(error)
126
+ end
127
+ end
128
+ Logger.info "Stopped packet reading for #{@interface.name}"
129
+ end # Thread.new
130
+ end # def start
131
+
132
+ # Disconnect from the interface and stop the thread
133
+ def stop
134
+ @mutex.synchronize do
135
+ # Need to make sure that @cancel_thread is set and the interface disconnected within
136
+ # mutex to ensure that connect() is not called when we want to stop()
137
+ @cancel_thread = true
138
+ @thread_sleeper.cancel
139
+ @interface.disconnect
140
+ end
141
+ OpenC3.kill_thread(self, @thread) if @thread and @thread != Thread.current
142
+ end
143
+
144
+ def graceful_kill
145
+ # Just to avoid warning
146
+ end
147
+
148
+ protected
149
+
150
+ def handle_packet(packet)
151
+ if packet.stored
152
+ # Stored telemetry does not update the current value table
153
+ identified_packet = System.telemetry.identify_and_define_packet(packet, @interface.target_names)
154
+ else
155
+ # Identify and update packet
156
+ if packet.identified?
157
+ begin
158
+ # Preidentifed packet - place it into the current value table
159
+ identified_packet = System.telemetry.update!(packet.target_name,
160
+ packet.packet_name,
161
+ packet.buffer)
162
+ rescue RuntimeError
163
+ # Packet identified but we don't know about it
164
+ # Clear packet_name and target_name and try to identify
165
+ Logger.warn "Received unknown identified telemetry: #{packet.target_name} #{packet.packet_name}"
166
+ packet.target_name = nil
167
+ packet.packet_name = nil
168
+ identified_packet = System.telemetry.identify!(packet.buffer,
169
+ @interface.target_names)
170
+ end
171
+ else
172
+ # Packet needs to be identified
173
+ identified_packet = System.telemetry.identify!(packet.buffer,
174
+ @interface.target_names)
175
+ end
176
+ end
177
+
178
+ if identified_packet
179
+ identified_packet.received_time = packet.received_time
180
+ identified_packet.stored = packet.stored
181
+ identified_packet.extra = packet.extra
182
+ packet = identified_packet
183
+ else
184
+ unknown_packet = System.telemetry.update!('UNKNOWN', 'UNKNOWN', packet.buffer)
185
+ unknown_packet.received_time = packet.received_time
186
+ unknown_packet.stored = packet.stored
187
+ unknown_packet.extra = packet.extra
188
+ packet = unknown_packet
189
+ data_length = packet.length
190
+ string = "#{@interface.name} - Unknown #{data_length} byte packet starting: "
191
+ num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, data_length].min
192
+ data_to_print = packet.buffer(false)[0..(num_bytes_to_print - 1)]
193
+ data_to_print.each_byte do |byte|
194
+ string << sprintf("%02X", byte)
195
+ end
196
+ Logger.error string
197
+ end
198
+
199
+ target = System.targets[packet.target_name]
200
+ target.tlm_cnt += 1 if target
201
+ packet.received_count += 1
202
+ @identified_packet_callback.call(packet) if @identified_packet_callback
203
+
204
+ # Write to routers
205
+ @interface.routers.each do |router|
206
+ router.write(packet) if router.write_allowed? and router.connected?
207
+ rescue => err
208
+ Logger.error "Problem writing to router #{router.name} - #{err.class}:#{err.message}"
209
+ end
210
+
211
+ # Write to packet log writers
212
+ if packet.stored and !@interface.stored_packet_log_writer_pairs.empty?
213
+ @interface.stored_packet_log_writer_pairs.each do |packet_log_writer_pair|
214
+ packet_log_writer_pair.tlm_log_writer.write(packet)
215
+ end
216
+ else
217
+ @interface.packet_log_writer_pairs.each do |packet_log_writer_pair|
218
+ # Write errors are handled by the log writer
219
+ packet_log_writer_pair.tlm_log_writer.write(packet)
220
+ end
221
+ end
222
+ end
223
+
224
+ def handle_connection_failed(connect_error)
225
+ if @connection_failed_callback
226
+ @connection_failed_callback.call(connect_error)
227
+ else
228
+ Logger.error "#{@interface.name} Connection Failed: #{connect_error.formatted(false, false)}"
229
+ case connect_error
230
+ when Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ENOTSOCK, Errno::EHOSTUNREACH, IOError
231
+ # Do not write an exception file for these extremely common cases
232
+ else
233
+ if RuntimeError === connect_error and (connect_error.message =~ /canceled/ or connect_error.message =~ /timeout/)
234
+ # Do not write an exception file for these extremely common cases
235
+ else
236
+ Logger.error connect_error.formatted
237
+ unless @connection_failed_messages.include?(connect_error.message)
238
+ OpenC3.write_exception_file(connect_error)
239
+ @connection_failed_messages << connect_error.message
240
+ end
241
+ end
242
+ end
243
+ end
244
+ disconnect()
245
+ end
246
+
247
+ def handle_connection_lost(err)
248
+ if @connection_lost_callback
249
+ @connection_lost_callback.call(err)
250
+ else
251
+ if err
252
+ Logger.info "Connection Lost for #{@interface.name}: #{err.formatted(false, false)}"
253
+ case err
254
+ when Errno::ECONNABORTED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EBADF, Errno::ENOTSOCK, IOError
255
+ # Do not write an exception file for these extremely common cases
256
+ else
257
+ Logger.error err.formatted
258
+ unless @connection_lost_messages.include?(err.message)
259
+ OpenC3.write_exception_file(err)
260
+ @connection_lost_messages << err.message
261
+ end
262
+ end
263
+ else
264
+ Logger.info "Connection Lost for #{@interface.name}"
265
+ end
266
+ end
267
+ disconnect()
268
+ end
269
+
270
+ def connect
271
+ Logger.info "Connecting to #{@interface.name}..."
272
+ @interface.connect
273
+ if @connection_success_callback
274
+ @connection_success_callback.call
275
+ else
276
+ Logger.info "#{@interface.name} Connection Success"
277
+ end
278
+ end
279
+
280
+ def disconnect
281
+ @interface.disconnect
282
+
283
+ # If the interface is set to auto_reconnect then delay so the thread
284
+ # can come back around and allow the interface a chance to reconnect.
285
+ if @interface.auto_reconnect
286
+ if !@cancel_thread
287
+ @thread_sleeper.sleep(@interface.reconnect_delay)
288
+ end
289
+ else
290
+ stop()
291
+ end
292
+ end
293
+ end # class InterfaceThread
294
+ end