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,196 @@
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/win32/win32'
21
+ require 'timeout' # For Timeout::Error
22
+
23
+ module OpenC3
24
+ # Serial driver for use on Windows serial ports
25
+ class Win32SerialDriver
26
+ # (see SerialDriver#initialize)
27
+ def initialize(port_name = 'COM1',
28
+ baud_rate = 9600,
29
+ parity = :NONE,
30
+ stop_bits = 1,
31
+ write_timeout = 10.0,
32
+ read_timeout = nil,
33
+ read_polling_period = 0.01,
34
+ read_max_length = 1000,
35
+ flow_control = :NONE,
36
+ data_bits = 8)
37
+
38
+ # Verify Parameters
39
+ port_name = '\\\\.\\' + port_name if /^COM[0-9]{2,3}$/.match?(port_name)
40
+
41
+ raise(ArgumentError, "Invalid baud rate: #{baud_rate}") unless baud_rate.between?(Win32::BAUD_RATES[0], Win32::BAUD_RATES[-1])
42
+ raise(ArgumentError, "Invalid data bits: #{data_bits}") unless [5, 6, 7, 8].include?(data_bits)
43
+ raise(ArgumentError, "Invalid parity: #{parity}") if parity and !SerialDriver::VALID_PARITY.include?(parity)
44
+
45
+ case parity
46
+ when SerialDriver::ODD
47
+ parity = Win32::ODDPARITY
48
+ when SerialDriver::EVEN
49
+ parity = Win32::EVENPARITY
50
+ when SerialDriver::NONE
51
+ parity = Win32::NOPARITY
52
+ end
53
+
54
+ raise(ArgumentError, "Invalid stop bits: #{stop_bits}") unless [1, 2].include?(stop_bits)
55
+
56
+ if stop_bits == 1
57
+ stop_bits = Win32::ONESTOPBIT
58
+ else
59
+ stop_bits = Win32::TWOSTOPBITS
60
+ end
61
+
62
+ @write_timeout = write_timeout
63
+ @read_timeout = read_timeout
64
+ @read_polling_period = read_polling_period
65
+ @read_max_length = read_max_length
66
+
67
+ # Open the Comm Port
68
+ @handle = Win32.create_file(port_name,
69
+ Win32::GENERIC_READ | Win32::GENERIC_WRITE,
70
+ 0,
71
+ Win32::NULL,
72
+ Win32::OPEN_EXISTING,
73
+ Win32::FILE_ATTRIBUTE_NORMAL)
74
+
75
+ @mutex = Mutex.new
76
+
77
+ # Configure the Comm Port - See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx
78
+ dcb = Win32.get_comm_state(@handle)
79
+ dcb.write('BaudRate', baud_rate)
80
+ dcb.write('ByteSize', data_bits)
81
+ dcb.write('Parity', parity)
82
+ dcb.write('StopBits', stop_bits)
83
+ if flow_control == :RTSCTS
84
+ # Monitor CTS
85
+ dcb.write('fOutxCtsFlow', 1)
86
+
87
+ # 0x00 - RTS_CONTROL_DISABLE - Disables the RTS line when the device is opened and leaves it disabled.
88
+ # 0x01 - RTS_CONTROL_ENABLE - Enables the RTS line when the device is opened and leaves it on.
89
+ # 0x02 - RTS_CONTROL_HANDSHAKE - Enables RTS handshaking. The driver raises the RTS line when the "type-ahead" (input) buffer is less than one-half full and lowers the RTS line when the buffer is more than three-quarters full. If handshaking is enabled, it is an error for the application to adjust the line by using the EscapeCommFunction function.
90
+ # 0x03 - RTS_CONTROL_TOGGLE - Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low.
91
+ dcb.write('fRtsControl', 0x03)
92
+ end
93
+ Win32.set_comm_state(@handle, dcb)
94
+
95
+ # Configure Timeouts, the WinAPI structure is COMMTIMEOUTS:
96
+ # DWORD ReadIntervalTimeout;
97
+ # DWORD ReadTotalTimeoutMultiplier;
98
+ # DWORD ReadTotalTimeoutConstant;
99
+ # DWORD WriteTotalTimeoutMultiplier;
100
+ # DWORD WriteTotalTimeoutConstant;
101
+ # 0xFFFFFFFF, 0, 0 specifies that the read operation is to return immediately
102
+ # with the bytes that have already been received, even if no bytes have been received.
103
+ # The WriteTotalTimeoutMultiplier is multiplied by the number of bytes to be written
104
+ # and the WriteTotalTimeoutConstant is added to that total (both are in milliseconds).
105
+ bits_per_symbol = data_bits + 1 # 1 start bit
106
+ case stop_bits
107
+ when Win32::ONESTOPBIT
108
+ bits_per_symbol += 1
109
+ when Win32::TWOSTOPBITS
110
+ bits_per_symbol += 2
111
+ end
112
+ case parity
113
+ when Win32::ODDPARITY, Win32::EVENPARITY
114
+ bits_per_symbol += 1
115
+ end
116
+ delay = (1000.0 / (baud_rate / bits_per_symbol.to_f)).ceil
117
+ Win32.set_comm_timeouts(@handle, 0xFFFFFFFF, 0, 0, delay, 1000)
118
+ end
119
+
120
+ # (see SerialDriver#close)
121
+ def close
122
+ if @handle
123
+ # Close the Comm Port
124
+ Win32.close_handle(@handle)
125
+ @mutex.synchronize do
126
+ @handle = nil
127
+ end
128
+ end
129
+ end
130
+
131
+ # (see SerialDriver#closed?)
132
+ def closed?
133
+ if @handle
134
+ false
135
+ else
136
+ true
137
+ end
138
+ end
139
+
140
+ # (see SerialDriver#write)
141
+ def write(data)
142
+ # Write the data
143
+ time = Time.now.sys
144
+ bytes_to_write = data.length
145
+ while bytes_to_write > 0
146
+ bytes_written = Win32.write_file(@handle, data, data.length)
147
+ raise "Error writing to comm port" if bytes_written <= 0
148
+
149
+ bytes_to_write -= bytes_written
150
+ data = data[bytes_written..-1]
151
+ raise Timeout::Error, "Write Timeout" if @write_timeout and (Time.now.sys - time > @write_timeout) and bytes_to_write > 0
152
+ end
153
+ end
154
+
155
+ # (see SerialDriver#read)
156
+ def read
157
+ data = ''
158
+ sleep_time = 0.0
159
+
160
+ loop do
161
+ loop do
162
+ buffer = nil
163
+ @mutex.synchronize do
164
+ break unless @handle
165
+
166
+ buffer = Win32.read_file(@handle, @read_max_length - data.length)
167
+ end
168
+ break unless buffer
169
+
170
+ data << buffer
171
+ break if buffer.length <= 0 or data.length >= @read_max_length or !@handle
172
+ end
173
+ break if data.length > 0 or !@handle
174
+ if @read_timeout and sleep_time >= @read_timeout
175
+ raise Timeout::Error, "Read Timeout"
176
+ end
177
+
178
+ sleep(@read_polling_period)
179
+ sleep_time += @read_polling_period
180
+ end
181
+
182
+ data
183
+ end
184
+
185
+ # (see SerialDriver#read_nonblock)
186
+ def read_nonblock
187
+ data = ''
188
+ loop do
189
+ buffer = Win32.read_file(@handle, @read_max_length - data.length)
190
+ data << buffer
191
+ break if buffer.length <= 0 or data.length >= @read_max_length
192
+ end
193
+ data
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,302 @@
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 'thread'
21
+ require 'openc3/config/config_parser'
22
+ require 'openc3/topics/topic'
23
+ require 'openc3/utilities/s3'
24
+
25
+ module OpenC3
26
+ # Creates a log. Can automatically cycle the log based on an elasped
27
+ # time period or when the log file reaches a predefined size.
28
+ class LogWriter
29
+ # @return [String] The filename of the packet log
30
+ attr_reader :filename
31
+
32
+ # @return [true/false] Whether logging is enabled
33
+ attr_reader :logging_enabled
34
+
35
+ # @return cycle_time [Integer] The amount of time in seconds before creating
36
+ # a new log file. This can be combined with cycle_size but is better used
37
+ # independently.
38
+ attr_reader :cycle_time
39
+
40
+ # @return cycle_hour [Integer] The time at which to cycle the log. Combined with
41
+ # cycle_minute to cycle the log daily at the specified time. If nil, the log
42
+ # will be cycled hourly at the specified cycle_minute.
43
+ attr_reader :cycle_hour
44
+
45
+ # @return cycle_minute [Integer] The time at which to cycle the log. See cycle_hour
46
+ # for more information.
47
+ attr_reader :cycle_minute
48
+
49
+ # @return [Time] Time that the current log file started
50
+ attr_reader :start_time
51
+
52
+ # @return [Mutex] Instance mutex protecting file
53
+ attr_reader :mutex
54
+
55
+ # The cycle time interval. Cycle times are only checked at this level of
56
+ # granularity.
57
+ CYCLE_TIME_INTERVAL = 10
58
+
59
+ # Mutex protecting class variables
60
+ @@mutex = Mutex.new
61
+
62
+ # Array of instances used to keep track of cycling logs
63
+ @@instances = []
64
+
65
+ # Thread used to cycle logs across all log writers
66
+ @@cycle_thread = nil
67
+
68
+ # Sleeper used to delay cycle thread
69
+ @@cycle_sleeper = nil
70
+
71
+ # @param remote_log_directory [String] The s3 path to store the log files
72
+ # @param logging_enabled [Boolean] Whether to start with logging enabled
73
+ # @param cycle_time [Integer] The amount of time in seconds before creating
74
+ # a new log file. This can be combined with cycle_size but is better used
75
+ # independently.
76
+ # @param cycle_size [Integer] The size in bytes before creating a new log
77
+ # file. This can be combined with cycle_time but is better used
78
+ # independently.
79
+ # @param cycle_hour [Integer] The time at which to cycle the log. Combined with
80
+ # cycle_minute to cycle the log daily at the specified time. If nil, the log
81
+ # will be cycled hourly at the specified cycle_minute.
82
+ # @param cycle_minute [Integer] The time at which to cycle the log. See cycle_hour
83
+ # for more information.
84
+ # @param redis_topic [String] The key of the Redis stream to trim when files are
85
+ # moved to S3
86
+ def initialize(
87
+ remote_log_directory,
88
+ logging_enabled = true,
89
+ cycle_time = nil,
90
+ cycle_size = 1000000000,
91
+ cycle_hour = nil,
92
+ cycle_minute = nil,
93
+ redis_topic: nil
94
+ )
95
+ @remote_log_directory = remote_log_directory
96
+ @logging_enabled = ConfigParser.handle_true_false(logging_enabled)
97
+ @cycle_time = ConfigParser.handle_nil(cycle_time)
98
+ if @cycle_time
99
+ @cycle_time = Integer(@cycle_time)
100
+ raise "cycle_time must be >= #{CYCLE_TIME_INTERVAL}" if @cycle_time < CYCLE_TIME_INTERVAL
101
+ end
102
+ @cycle_size = ConfigParser.handle_nil(cycle_size)
103
+ @cycle_size = Integer(@cycle_size) if @cycle_size
104
+ @cycle_hour = ConfigParser.handle_nil(cycle_hour)
105
+ @cycle_hour = Integer(@cycle_hour) if @cycle_hour
106
+ @cycle_minute = ConfigParser.handle_nil(cycle_minute)
107
+ @cycle_minute = Integer(@cycle_minute) if @cycle_minute
108
+ @mutex = Mutex.new
109
+ @file = nil
110
+ @file_size = 0
111
+ @filename = nil
112
+ @start_time = Time.now.utc
113
+ @first_time = nil
114
+ @last_time = nil
115
+ @cancel_threads = false
116
+ @last_offset = nil
117
+ @previous_file_redis_offset = nil
118
+ @redis_topic = redis_topic
119
+
120
+ # This is an optimization to avoid creating a new entry object
121
+ # each time we create an entry which we do a LOT!
122
+ @entry = String.new
123
+
124
+ if @cycle_time or @cycle_hour or @cycle_minute
125
+ @@mutex.synchronize do
126
+ @@instances << self
127
+
128
+ unless @@cycle_thread
129
+ @@cycle_thread = OpenC3.safe_thread("Log cycle") do
130
+ cycle_thread_body()
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ # Starts a new log file by closing the existing log file. New log files are
138
+ # not created until packets are written by {#write} so this does not
139
+ # immediately create a log file on the filesystem.
140
+ def start
141
+ @mutex.synchronize { close_file(false); @logging_enabled = true }
142
+ end
143
+
144
+ # Stops all logging and closes the current log file.
145
+ def stop
146
+ @mutex.synchronize { @logging_enabled = false; close_file(false) }
147
+ end
148
+
149
+ # Stop all logging, close the current log file, and kill the logging threads.
150
+ def shutdown
151
+ stop()
152
+ @@mutex.synchronize do
153
+ @@instances.delete(self)
154
+ if @@instances.length <= 0
155
+ @@cycle_sleeper.cancel if @@cycle_sleeper
156
+ OpenC3.kill_thread(self, @@cycle_thread) if @@cycle_thread
157
+ @@cycle_thread = nil
158
+ end
159
+ end
160
+ end
161
+
162
+ def graceful_kill
163
+ @cancel_threads = true
164
+ end
165
+
166
+ # implementation details
167
+
168
+ def create_unique_filename(ext = extension)
169
+ # Create a filename that doesn't exist
170
+ attempt = nil
171
+ while true
172
+ filename_parts = [attempt]
173
+ filename_parts.unshift @label if @label
174
+ filename = File.join(Dir.tmpdir, File.build_timestamped_filename([@label, attempt], ext))
175
+ if File.exist?(filename)
176
+ attempt ||= 0
177
+ attempt += 1
178
+ else
179
+ return filename
180
+ end
181
+ end
182
+ end
183
+
184
+ def cycle_thread_body
185
+ @@cycle_sleeper = Sleeper.new
186
+ while true
187
+ start_time = Time.now
188
+ @@mutex.synchronize do
189
+ @@instances.each do |instance|
190
+ # The check against start_time needs to be mutex protected to prevent a packet coming in between the check
191
+ # and closing the file
192
+ instance.mutex.synchronize do
193
+ utc_now = Time.now.utc
194
+ # Logger.debug("start:#{@start_time.to_f} now:#{utc_now.to_f} cycle:#{@cycle_time} new:#{(utc_now - @start_time) > @cycle_time}")
195
+ if instance.logging_enabled and
196
+ (
197
+ # Cycle based on total time logging
198
+ (instance.cycle_time and (utc_now - instance.start_time) > instance.cycle_time) or
199
+
200
+ # Cycle daily at a specific time
201
+ (instance.cycle_hour and instance.cycle_minute and utc_now.hour == instance.cycle_hour and utc_now.min == instance.cycle_minute and instance.start_time.yday != utc_now.yday) or
202
+
203
+ # Cycle hourly at a specific time
204
+ (instance.cycle_minute and not instance.cycle_hour and utc_now.min == instance.cycle_minute and instance.start_time.hour != utc_now.hour)
205
+ )
206
+ instance.close_file(false)
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ # Only check whether to cycle at a set interval
213
+ run_time = Time.now - start_time
214
+ sleep_time = CYCLE_TIME_INTERVAL - run_time
215
+ sleep_time = 0 if sleep_time < 0
216
+ break if @@cycle_sleeper.sleep(sleep_time)
217
+ end
218
+ end
219
+
220
+ # Starting a new log file is a critical operation so the entire method is
221
+ # wrapped with a rescue and handled with handle_critical_exception
222
+ # Assumes mutex has already been taken
223
+ def start_new_file
224
+ close_file(false)
225
+
226
+ # Start log file
227
+ @filename = create_unique_filename()
228
+ @file = File.new(@filename, 'wb')
229
+ @file_size = 0
230
+
231
+ @start_time = Time.now.utc
232
+ @first_time = nil
233
+ @last_time = nil
234
+ Logger.debug "Log File Opened : #{@filename}"
235
+ rescue => err
236
+ Logger.error "Error starting new log file: #{err.formatted}"
237
+ @logging_enabled = false
238
+ OpenC3.handle_critical_exception(err)
239
+ end
240
+
241
+ def prepare_write(time_nsec_since_epoch, data_length, redis_offset)
242
+ # This check includes logging_enabled again because it might have changed since we acquired the mutex
243
+ if @logging_enabled and (!@file or (@cycle_size and (@file_size + data_length) > @cycle_size))
244
+ start_new_file()
245
+ end
246
+ @last_offset = redis_offset # This is needed for the redis offset marker entry at the end of the log file
247
+ end
248
+
249
+ # Closing a log file isn't critical so we just log an error. NOTE: This also trims the Redis stream
250
+ # to keep a full file's worth of data in the stream. This is what prevents continuous stream growth.
251
+ def close_file(take_mutex = true)
252
+ @mutex.lock if take_mutex
253
+ begin
254
+ if @file
255
+ begin
256
+ @file.close unless @file.closed?
257
+ Logger.debug "Log File Closed : #{@filename}"
258
+ date = first_timestamp[0..7] # YYYYMMDD
259
+ s3_key = File.join(@remote_log_directory, date, s3_filename)
260
+ S3Utilities.move_log_file_to_s3(@filename, s3_key)
261
+ # Now that the file is in S3, trim the Redis stream up until the previous file.
262
+ # This keeps one file worth of data in Redis as a safety buffer
263
+ Topic.trim_topic(@redis_topic, @previous_file_redis_offset) if @redis_topic and @previous_file_redis_offset
264
+ @previous_file_redis_offset = @last_offset
265
+ rescue Exception => err
266
+ Logger.instance.error "Error closing #{@filename} : #{err.formatted}"
267
+ end
268
+
269
+ @file = nil
270
+ @file_size = 0
271
+ @filename = nil
272
+ end
273
+ ensure
274
+ @mutex.unlock if take_mutex
275
+ end
276
+ end
277
+
278
+ def s3_filename
279
+ "#{first_timestamp}__#{last_timestamp}" + extension
280
+ end
281
+
282
+ def extension
283
+ '.log'.freeze
284
+ end
285
+
286
+ def first_time
287
+ Time.from_nsec_from_epoch(@first_time)
288
+ end
289
+
290
+ def last_time
291
+ Time.from_nsec_from_epoch(@last_time)
292
+ end
293
+
294
+ def first_timestamp
295
+ first_time().to_timestamp # "YYYYMMDDHHmmSSNNNNNNNNN"
296
+ end
297
+
298
+ def last_timestamp
299
+ last_time().to_timestamp # "YYYYMMDDHHmmSSNNNNNNNNN"
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,62 @@
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
+ module PacketLogConstants
22
+ # Constants to detect old file formats
23
+ COSMOS2_FILE_HEADER = 'COSMOS2_'.freeze
24
+ COSMOS4_FILE_HEADER = 'COSMOS4_'.freeze
25
+
26
+ # OPENC3 5 Constants
27
+ OPENC3_FILE_HEADER = 'COSMOS5_'.freeze
28
+ OPENC3_INDEX_HEADER = 'COSIDX5_'.freeze
29
+ OPENC3_HEADER_LENGTH = OPENC3_FILE_HEADER.length
30
+ # Flags which are bit masked into file entries
31
+ OPENC3_ENTRY_TYPE_MASK = 0xF000
32
+ OPENC3_TARGET_DECLARATION_ENTRY_TYPE_MASK = 0x1000
33
+ OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK = 0x2000
34
+ OPENC3_RAW_PACKET_ENTRY_TYPE_MASK = 0x3000
35
+ OPENC3_JSON_PACKET_ENTRY_TYPE_MASK = 0x4000
36
+ OPENC3_OFFSET_MARKER_ENTRY_TYPE_MASK = 0x5000
37
+ OPENC3_ID_FLAG_MASK = 0x0200
38
+ OPENC3_STORED_FLAG_MASK = 0x0400
39
+ OPENC3_CMD_FLAG_MASK = 0x0800
40
+
41
+ OPENC3_ID_FIXED_SIZE = 32
42
+ OPENC3_MAX_PACKET_INDEX = 65535
43
+ OPENC3_MAX_TARGET_INDEX = 65535
44
+
45
+ OPENC3_PRIMARY_FIXED_SIZE = 2
46
+ OPENC3_TARGET_DECLARATION_SECONDARY_FIXED_SIZE = 0
47
+ OPENC3_TARGET_DECLARATION_PACK_DIRECTIVE = 'Nn'.freeze
48
+ OPENC3_TARGET_DECLARATION_PACK_ITEMS = 2 # Useful for testing
49
+
50
+ OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE = 2
51
+ OPENC3_PACKET_DECLARATION_PACK_DIRECTIVE = 'Nnn'.freeze
52
+ OPENC3_PACKET_DECLARATION_PACK_ITEMS = 3 # Useful for testing
53
+
54
+ OPENC3_OFFSET_MARKER_SECONDARY_FIXED_SIZE = 0
55
+ OPENC3_OFFSET_MARKER_PACK_DIRECTIVE = 'Nn'.freeze
56
+ OPENC3_OFFSET_MARKER_PACK_ITEMS = 2 # Useful for testing
57
+
58
+ OPENC3_PACKET_SECONDARY_FIXED_SIZE = 10
59
+ OPENC3_PACKET_PACK_DIRECTIVE = 'NnnQ>'.freeze
60
+ OPENC3_PACKET_PACK_ITEMS = 4 # Useful for testing
61
+ end
62
+ end