cosmos 3.0.1 → 3.1.0

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 (912) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +48 -48
  4. data/.travis.yml +7 -7
  5. data/CONTRIBUTING.txt +50 -50
  6. data/Gemfile +6 -6
  7. data/Guardfile +27 -27
  8. data/LICENSE.txt +879 -879
  9. data/Manifest.txt +1116 -1114
  10. data/README.md +109 -107
  11. data/Rakefile +214 -214
  12. data/autohotkey/config/data/diamond.STL +57 -57
  13. data/autohotkey/config/system/system.txt +34 -34
  14. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  15. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  16. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  17. data/autohotkey/config/targets/COSMOS/target.txt +5 -5
  18. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  19. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  20. data/autohotkey/config/targets/INST/cmd_tlm_server.txt +5 -5
  21. data/autohotkey/config/targets/INST/lib/example_limits_response.rb +30 -30
  22. data/autohotkey/config/targets/INST/lib/sim_inst.rb +305 -294
  23. data/autohotkey/config/targets/INST/screens/adcs.txt +46 -46
  24. data/autohotkey/config/targets/INST/screens/array.txt +7 -7
  25. data/autohotkey/config/targets/INST/screens/block.txt +8 -8
  26. data/autohotkey/config/targets/INST/screens/commanding.txt +30 -30
  27. data/autohotkey/config/targets/INST/screens/graphs.txt +14 -14
  28. data/autohotkey/config/targets/INST/screens/ground.txt +25 -25
  29. data/autohotkey/config/targets/INST/screens/health_status.txt +33 -33
  30. data/autohotkey/config/targets/INST/screens/hs.txt +49 -49
  31. data/autohotkey/config/targets/INST/screens/image.txt +21 -21
  32. data/autohotkey/config/targets/INST/screens/latest.txt +23 -23
  33. data/autohotkey/config/targets/INST/screens/mech.txt +25 -25
  34. data/autohotkey/config/targets/INST/screens/other.txt +25 -25
  35. data/autohotkey/config/targets/INST/screens/params.txt +25 -25
  36. data/autohotkey/config/targets/INST/screens/tabs.txt +68 -68
  37. data/autohotkey/config/targets/INST/target.txt +26 -26
  38. data/autohotkey/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  39. data/autohotkey/config/targets/META/cmd_tlm/meta_tlm.txt +9 -9
  40. data/autohotkey/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  41. data/autohotkey/config/targets/SYSTEM/screens/error.txt +11 -11
  42. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +22 -22
  43. data/autohotkey/config/tools/data_viewer/data_viewer.txt +11 -11
  44. data/autohotkey/config/tools/handbook_creator/handbook_creator.txt +49 -49
  45. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  46. data/autohotkey/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  47. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  48. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +25 -25
  49. data/autohotkey/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  50. data/autohotkey/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  51. data/autohotkey/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  52. data/autohotkey/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  53. data/autohotkey/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  54. data/autohotkey/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  55. data/autohotkey/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  56. data/autohotkey/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  57. data/autohotkey/config/tools/handbook_creator/templates/title.html.erb +1 -1
  58. data/autohotkey/config/tools/launcher/launcher.txt +38 -38
  59. data/autohotkey/config/tools/script_runner/script_runner.txt +3 -3
  60. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +8 -8
  61. data/autohotkey/config/tools/table_manager/OneDimensionalTable_def.txt +19 -19
  62. data/autohotkey/config/tools/table_manager/TwoDimensionalTable_def.txt +248 -248
  63. data/autohotkey/config/tools/test_runner/test_runner.txt +8 -8
  64. data/autohotkey/config/tools/test_runner/test_runner2.txt +11 -11
  65. data/autohotkey/config/tools/test_runner/test_runner3.txt +6 -6
  66. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  67. data/autohotkey/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  68. data/autohotkey/config/tools/tlm_extractor/tlm_extractor2.txt +9 -9
  69. data/autohotkey/config/tools/tlm_grapher/bad.txt +50 -50
  70. data/autohotkey/config/tools/tlm_grapher/temp1-4.txt +51 -51
  71. data/autohotkey/config/tools/tlm_grapher/test2.txt +111 -111
  72. data/autohotkey/config/tools/tlm_viewer/tlm_viewer.txt +24 -24
  73. data/autohotkey/config/tools/tlm_viewer/tlm_viewer2.txt +4 -4
  74. data/autohotkey/config/tools/tlm_viewer/tlm_viewer3.txt +3 -3
  75. data/autohotkey/lib/example_background_task.rb +42 -42
  76. data/autohotkey/lib/user_version.rb +3 -3
  77. data/autohotkey/procedures/clear_util.rb +7 -7
  78. data/autohotkey/procedures/collect.rb +18 -18
  79. data/autohotkey/procedures/collect_util.rb +14 -14
  80. data/autohotkey/procedures/example_test.rb +67 -67
  81. data/autohotkey/procedures/example_test2.rb +74 -74
  82. data/autohotkey/procedures/script_test.rb +17 -17
  83. data/autohotkey/procedures/syntax_error.rb +18 -18
  84. data/autohotkey/tools/CmdExtractorAHK +16 -16
  85. data/autohotkey/tools/CmdSender +14 -14
  86. data/autohotkey/tools/CmdSenderAHK +18 -18
  87. data/autohotkey/tools/CmdTlmServer +14 -14
  88. data/autohotkey/tools/CmdTlmServerAHK +28 -28
  89. data/autohotkey/tools/CmdTlmServerAHK2 +17 -17
  90. data/autohotkey/tools/DataViewer +14 -14
  91. data/autohotkey/tools/DataViewerAHK +17 -17
  92. data/autohotkey/tools/HandbookCreatorAHK +20 -20
  93. data/autohotkey/tools/LauncherAHK +17 -17
  94. data/autohotkey/tools/LimitsMonitorAHK +20 -20
  95. data/autohotkey/tools/OpenGLBuilderAHK +20 -20
  96. data/autohotkey/tools/PacketViewer +14 -14
  97. data/autohotkey/tools/PacketViewerAHK +18 -18
  98. data/autohotkey/tools/PacketViewerAHK2 +17 -17
  99. data/autohotkey/tools/Replay +14 -14
  100. data/autohotkey/tools/Replay.bat +59 -59
  101. data/autohotkey/tools/ReplayAHK +17 -17
  102. data/autohotkey/tools/ScriptRunner +14 -14
  103. data/autohotkey/tools/ScriptRunnerAHK +20 -20
  104. data/autohotkey/tools/ScriptRunnerAHK2 +17 -17
  105. data/autohotkey/tools/TableManager +14 -14
  106. data/autohotkey/tools/TableManagerAHK +30 -30
  107. data/autohotkey/tools/TestRunner +15 -15
  108. data/autohotkey/tools/TestRunnerAHK +17 -17
  109. data/autohotkey/tools/TestRunnerAHK2 +17 -17
  110. data/autohotkey/tools/TestRunnerAHK3 +17 -17
  111. data/autohotkey/tools/TestRunnerAHK4 +17 -17
  112. data/autohotkey/tools/TlmExtractor +15 -15
  113. data/autohotkey/tools/TlmExtractorAHK +19 -19
  114. data/autohotkey/tools/TlmExtractorAHK2 +16 -16
  115. data/autohotkey/tools/TlmExtractorAHK3 +16 -16
  116. data/autohotkey/tools/TlmGrapher +14 -14
  117. data/autohotkey/tools/TlmGrapherAHK +19 -19
  118. data/autohotkey/tools/TlmGrapherAHK2 +23 -23
  119. data/autohotkey/tools/TlmGrapherAHK3 +17 -17
  120. data/autohotkey/tools/TlmGrapherAHK4 +17 -17
  121. data/autohotkey/tools/TlmViewer +14 -14
  122. data/autohotkey/tools/TlmViewerAHK +28 -28
  123. data/autohotkey/tools/TlmViewerAHK2 +18 -18
  124. data/autohotkey/tools/TlmViewerAHK3 +18 -18
  125. data/autohotkey/tools/TlmViewerAHK4 +18 -18
  126. data/autohotkey/tools/TlmViewerAHK5 +18 -18
  127. data/autohotkey/tools/autohotkey.rb +37 -37
  128. data/autohotkey/tools/cmd_extractor.ahk +27 -27
  129. data/autohotkey/tools/cmd_sender.ahk +182 -162
  130. data/autohotkey/tools/cmd_tlm_server.ahk +89 -89
  131. data/autohotkey/tools/cmd_tlm_server2.ahk +45 -45
  132. data/autohotkey/tools/data_viewer.ahk +135 -135
  133. data/autohotkey/tools/handbook_creator.ahk +23 -23
  134. data/autohotkey/tools/launcher.ahk +41 -41
  135. data/autohotkey/tools/limits_monitor.ahk +70 -70
  136. data/autohotkey/tools/open_gl_builder.ahk +134 -134
  137. data/autohotkey/tools/packet_viewer.ahk +143 -143
  138. data/autohotkey/tools/packet_viewer2.ahk +9 -9
  139. data/autohotkey/tools/replay.ahk +98 -98
  140. data/autohotkey/tools/script_runner.ahk +589 -589
  141. data/autohotkey/tools/script_runner2.ahk +34 -31
  142. data/autohotkey/tools/table_manager.ahk +220 -220
  143. data/autohotkey/tools/test_runner.ahk +262 -259
  144. data/autohotkey/tools/test_runner2.ahk +52 -52
  145. data/autohotkey/tools/test_runner3.ahk +13 -13
  146. data/autohotkey/tools/tlm_extractor.ahk +272 -272
  147. data/autohotkey/tools/tlm_grapher.ahk +642 -642
  148. data/autohotkey/tools/tlm_grapher2.ahk +115 -115
  149. data/autohotkey/tools/tlm_grapher3.ahk +24 -24
  150. data/autohotkey/tools/tlm_viewer.ahk +133 -133
  151. data/autohotkey/tools/tlm_viewer2.ahk +50 -49
  152. data/autohotkey/tools/tlm_viewer4.ahk +4 -4
  153. data/autohotkey/tools/tlm_viewer5.ahk +20 -20
  154. data/bin/cosmos +96 -96
  155. data/bin/cstol_converter +1166 -1166
  156. data/bin/rubysloc +85 -85
  157. data/cosmos.gemspec +98 -97
  158. data/data/about.txt +4 -4
  159. data/data/crc.txt +306 -305
  160. data/data/diamond.STL +57 -57
  161. data/data/legal.txt +9 -9
  162. data/demo/Gemfile +6 -6
  163. data/demo/Launcher +15 -15
  164. data/demo/Launcher.bat +59 -59
  165. data/demo/Rakefile +61 -61
  166. data/demo/config/data/crc.txt +222 -206
  167. data/demo/config/data/diamond.STL +57 -57
  168. data/demo/config/data/meta_init.txt +4 -4
  169. data/demo/config/system/system.txt +34 -34
  170. data/demo/config/system/system2.txt +33 -33
  171. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  172. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  173. data/demo/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  174. data/demo/config/targets/COSMOS/screens/limits_change.txt +20 -20
  175. data/demo/config/targets/COSMOS/screens/version.txt +19 -19
  176. data/demo/config/targets/COSMOS/target.txt +11 -11
  177. data/demo/config/targets/EXAMPLE/cmd_tlm/example_cmds.txt +2 -2
  178. data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +3 -3
  179. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +6 -6
  180. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +22 -22
  181. data/demo/config/targets/EXAMPLE/target.txt +6 -6
  182. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  183. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  184. data/demo/config/targets/INST/cmd_tlm_server.txt +5 -5
  185. data/demo/config/targets/INST/lib/example_limits_response.rb +30 -30
  186. data/demo/config/targets/INST/lib/sim_inst.rb +305 -294
  187. data/demo/config/targets/INST/screens/adcs.txt +46 -46
  188. data/demo/config/targets/INST/screens/array.txt +15 -15
  189. data/demo/config/targets/INST/screens/block.txt +8 -8
  190. data/demo/config/targets/INST/screens/commanding.txt +30 -30
  191. data/demo/config/targets/INST/screens/graphs.txt +14 -14
  192. data/demo/config/targets/INST/screens/ground.txt +25 -25
  193. data/demo/config/targets/INST/screens/hs.txt +44 -44
  194. data/demo/config/targets/INST/screens/latest.txt +23 -23
  195. data/demo/config/targets/INST/screens/other.txt +29 -29
  196. data/demo/config/targets/INST/screens/tabs.txt +70 -70
  197. data/demo/config/targets/INST/target.txt +33 -33
  198. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  199. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +13 -13
  200. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  201. data/demo/config/targets/SYSTEM/cmd_tlm/override.txt +29 -29
  202. data/demo/config/targets/SYSTEM/screens/status.txt +12 -12
  203. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_cmds.txt +13 -12
  204. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_tlm.txt +3 -3
  205. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +6 -6
  206. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +54 -48
  207. data/demo/config/targets/TEMPLATED/target.txt +6 -6
  208. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +33 -33
  209. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +29 -29
  210. data/demo/config/tools/data_viewer/data_viewer.txt +11 -11
  211. data/demo/config/tools/handbook_creator/handbook_creator.txt +66 -66
  212. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  213. data/demo/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  214. data/demo/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  215. data/demo/config/tools/handbook_creator/templates/header.html.erb +25 -25
  216. data/demo/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  217. data/demo/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  218. data/demo/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  219. data/demo/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  220. data/demo/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  221. data/demo/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  222. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  223. data/demo/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  224. data/demo/config/tools/handbook_creator/templates/title.html.erb +1 -1
  225. data/demo/config/tools/launcher/launcher.txt +45 -45
  226. data/demo/config/tools/launcher/launcher2.txt +45 -45
  227. data/demo/config/tools/script_runner/script_runner.txt +3 -3
  228. data/demo/config/tools/table_manager/ConfigTables_def.txt +8 -8
  229. data/demo/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  230. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  231. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  232. data/demo/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  233. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  234. data/demo/config/tools/test_runner/test_runner.txt +17 -17
  235. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  236. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  237. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  238. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  239. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +41 -41
  240. data/demo/lib/example_background_task.rb +57 -52
  241. data/demo/lib/example_target.rb +113 -108
  242. data/demo/lib/scpi_target.rb +74 -74
  243. data/demo/lib/user_version.rb +3 -3
  244. data/demo/procedures/checks.rb +11 -11
  245. data/demo/procedures/clear_util.rb +7 -7
  246. data/demo/procedures/collect.rb +18 -18
  247. data/demo/procedures/collect_util.rb +14 -14
  248. data/demo/procedures/cosmos_api_test.rb +293 -293
  249. data/demo/procedures/disconnect.rb +29 -29
  250. data/demo/procedures/example_test.rb +182 -182
  251. data/demo/procedures/plot_test.rb +8 -8
  252. data/demo/procedures/run_example_test.rb +3 -3
  253. data/demo/procedures/test.rb +51 -51
  254. data/demo/tools/CmdExtractor +15 -15
  255. data/demo/tools/CmdExtractor.bat +59 -59
  256. data/demo/tools/CmdSender +15 -15
  257. data/demo/tools/CmdSender.bat +59 -59
  258. data/demo/tools/CmdTlmServer +15 -15
  259. data/demo/tools/CmdTlmServer.bat +59 -59
  260. data/demo/tools/DataViewer +15 -15
  261. data/demo/tools/DataViewer.bat +59 -59
  262. data/demo/tools/ExampleTarget +15 -15
  263. data/demo/tools/ExampleTarget.bat +59 -59
  264. data/demo/tools/HandbookCreator +15 -15
  265. data/demo/tools/HandbookCreator.bat +61 -61
  266. data/demo/tools/Launcher +15 -15
  267. data/demo/tools/Launcher.bat +59 -59
  268. data/demo/tools/LimitsMonitor +15 -15
  269. data/demo/tools/LimitsMonitor.bat +59 -59
  270. data/demo/tools/OpenGLBuilder +15 -15
  271. data/demo/tools/OpenGLBuilder.bat +59 -59
  272. data/demo/tools/PacketViewer +15 -15
  273. data/demo/tools/PacketViewer.bat +59 -59
  274. data/demo/tools/Replay +15 -15
  275. data/demo/tools/Replay.bat +59 -59
  276. data/demo/tools/ScpiTarget +15 -15
  277. data/demo/tools/ScpiTarget.bat +59 -59
  278. data/demo/tools/ScriptRunner +15 -15
  279. data/demo/tools/ScriptRunner.bat +59 -59
  280. data/demo/tools/TableManager +15 -15
  281. data/demo/tools/TableManager.bat +59 -59
  282. data/demo/tools/TestRunner +15 -15
  283. data/demo/tools/TestRunner.bat +59 -59
  284. data/demo/tools/TlmExtractor +15 -15
  285. data/demo/tools/TlmExtractor.bat +59 -59
  286. data/demo/tools/TlmGrapher +15 -15
  287. data/demo/tools/TlmGrapher.bat +59 -59
  288. data/demo/tools/TlmViewer +15 -15
  289. data/demo/tools/TlmViewer.bat +59 -59
  290. data/demo/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  291. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  292. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  293. data/demo/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  294. data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  295. data/demo/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  296. data/demo/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  297. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  298. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  299. data/demo/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  300. data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  301. data/demo/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  302. data/demo/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  303. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  304. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  305. data/demo/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  306. data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  307. data/demo/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  308. data/demo/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  309. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  310. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  311. data/demo/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  312. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  313. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  314. data/demo/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  315. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  316. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  317. data/demo/tools/mac/Replay.app/Contents/Info.plist +38 -38
  318. data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  319. data/demo/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  320. data/demo/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  321. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  322. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  323. data/demo/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  324. data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  325. data/demo/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  326. data/demo/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  327. data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  328. data/demo/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  329. data/demo/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  330. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  331. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  332. data/demo/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  333. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  334. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  335. data/demo/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  336. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  337. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  338. data/ext/cosmos/ext/array/array.c +111 -111
  339. data/ext/cosmos/ext/array/extconf.rb +13 -13
  340. data/ext/cosmos/ext/buffered_file/buffered_file.c +167 -167
  341. data/ext/cosmos/ext/buffered_file/extconf.rb +13 -13
  342. data/ext/cosmos/ext/config_parser/config_parser.c +237 -237
  343. data/ext/cosmos/ext/config_parser/extconf.rb +13 -13
  344. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +117 -117
  345. data/ext/cosmos/ext/cosmos_io/extconf.rb +13 -13
  346. data/ext/cosmos/ext/crc/crc.c +341 -341
  347. data/ext/cosmos/ext/crc/extconf.rb +12 -12
  348. data/ext/cosmos/ext/line_graph/extconf.rb +13 -13
  349. data/ext/cosmos/ext/line_graph/line_graph.c +501 -501
  350. data/ext/cosmos/ext/low_fragmentation_array/extconf.rb +12 -12
  351. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +261 -261
  352. data/ext/cosmos/ext/packet/extconf.rb +13 -13
  353. data/ext/cosmos/ext/packet/packet.c +339 -339
  354. data/ext/cosmos/ext/platform/extconf.rb +13 -13
  355. data/ext/cosmos/ext/platform/platform.c +81 -81
  356. data/ext/cosmos/ext/polynomial_conversion/extconf.rb +13 -13
  357. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +73 -73
  358. data/ext/cosmos/ext/string/extconf.rb +13 -13
  359. data/ext/cosmos/ext/string/string.c +49 -49
  360. data/ext/cosmos/ext/structure/structure.c +894 -894
  361. data/ext/cosmos/ext/tabbed_plots_config/extconf.rb +13 -13
  362. data/ext/cosmos/ext/tabbed_plots_config/tabbed_plots_config.c +51 -51
  363. data/ext/cosmos/ext/telemetry/extconf.rb +13 -13
  364. data/ext/cosmos/ext/telemetry/telemetry.c +306 -306
  365. data/ext/mkrf_conf.rb +40 -40
  366. data/install/Gemfile +6 -6
  367. data/install/Launcher +14 -14
  368. data/install/Launcher.bat +59 -59
  369. data/install/Rakefile +61 -61
  370. data/install/config/data/crc.txt +134 -133
  371. data/install/config/system/system.txt +29 -29
  372. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  373. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  374. data/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  375. data/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  376. data/install/config/targets/COSMOS/screens/version.txt +19 -19
  377. data/install/config/targets/COSMOS/target.txt +8 -8
  378. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  379. data/install/config/tools/data_viewer/data_viewer.txt +3 -3
  380. data/install/config/tools/handbook_creator/handbook_creator.txt +49 -49
  381. data/install/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  382. data/install/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  383. data/install/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  384. data/install/config/tools/handbook_creator/templates/header.html.erb +25 -25
  385. data/install/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  386. data/install/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  387. data/install/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  388. data/install/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  389. data/install/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  390. data/install/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  391. data/install/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  392. data/install/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  393. data/install/config/tools/handbook_creator/templates/title.html.erb +1 -1
  394. data/install/config/tools/launcher/launcher.txt +39 -39
  395. data/install/config/tools/script_runner/script_runner.txt +3 -3
  396. data/install/config/tools/test_runner/test_runner.txt +8 -8
  397. data/install/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  398. data/install/lib/user_version.rb +3 -3
  399. data/install/tools/CmdExtractor +15 -15
  400. data/install/tools/CmdExtractor.bat +59 -59
  401. data/install/tools/CmdSender +15 -15
  402. data/install/tools/CmdSender.bat +59 -59
  403. data/install/tools/CmdTlmServer +15 -15
  404. data/install/tools/CmdTlmServer.bat +59 -59
  405. data/install/tools/DataViewer +15 -15
  406. data/install/tools/DataViewer.bat +59 -59
  407. data/install/tools/HandbookCreator +15 -15
  408. data/install/tools/HandbookCreator.bat +61 -61
  409. data/install/tools/Launcher +15 -15
  410. data/install/tools/Launcher.bat +59 -59
  411. data/install/tools/LimitsMonitor +15 -15
  412. data/install/tools/LimitsMonitor.bat +59 -59
  413. data/install/tools/OpenGLBuilder +15 -15
  414. data/install/tools/OpenGLBuilder.bat +59 -59
  415. data/install/tools/PacketViewer +15 -15
  416. data/install/tools/PacketViewer.bat +59 -59
  417. data/install/tools/Replay +15 -15
  418. data/install/tools/Replay.bat +59 -59
  419. data/install/tools/ScriptRunner +15 -15
  420. data/install/tools/ScriptRunner.bat +59 -59
  421. data/install/tools/TableManager +15 -15
  422. data/install/tools/TableManager.bat +59 -59
  423. data/install/tools/TestRunner +15 -15
  424. data/install/tools/TestRunner.bat +59 -59
  425. data/install/tools/TlmExtractor +15 -15
  426. data/install/tools/TlmExtractor.bat +59 -59
  427. data/install/tools/TlmGrapher +15 -15
  428. data/install/tools/TlmGrapher.bat +59 -59
  429. data/install/tools/TlmViewer +15 -15
  430. data/install/tools/TlmViewer.bat +59 -59
  431. data/install/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  432. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  433. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  434. data/install/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  435. data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  436. data/install/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  437. data/install/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  438. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  439. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  440. data/install/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  441. data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  442. data/install/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  443. data/install/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  444. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  445. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  446. data/install/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  447. data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  448. data/install/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  449. data/install/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  450. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  451. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  452. data/install/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  453. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  454. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  455. data/install/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  456. data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  457. data/install/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  458. data/install/tools/mac/Replay.app/Contents/Info.plist +38 -38
  459. data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  460. data/install/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  461. data/install/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  462. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  463. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  464. data/install/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  465. data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  466. data/install/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  467. data/install/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  468. data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  469. data/install/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  470. data/install/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  471. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  472. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  473. data/install/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  474. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  475. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  476. data/install/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  477. data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  478. data/install/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  479. data/lib/cosmos.rb +63 -63
  480. data/lib/cosmos/ccsds/ccsds_packet.rb +63 -63
  481. data/lib/cosmos/ccsds/ccsds_parser.rb +143 -143
  482. data/lib/cosmos/config/config_parser.rb +324 -324
  483. data/lib/cosmos/conversions.rb +13 -13
  484. data/lib/cosmos/conversions/conversion.rb +47 -47
  485. data/lib/cosmos/conversions/generic_conversion.rb +55 -55
  486. data/lib/cosmos/conversions/new_packet_log_conversion.rb +45 -45
  487. data/lib/cosmos/conversions/polynomial_conversion.rb +57 -57
  488. data/lib/cosmos/conversions/processor_conversion.rb +46 -46
  489. data/lib/cosmos/conversions/received_count_conversion.rb +33 -33
  490. data/lib/cosmos/conversions/received_time_formatted_conversion.rb +37 -37
  491. data/lib/cosmos/conversions/received_time_seconds_conversion.rb +37 -37
  492. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +128 -128
  493. data/lib/cosmos/conversions/unix_time_conversion.rb +50 -50
  494. data/lib/cosmos/conversions/unix_time_formatted_conversion.rb +44 -44
  495. data/lib/cosmos/conversions/unix_time_seconds_conversion.rb +44 -44
  496. data/lib/cosmos/core_ext.rb +18 -18
  497. data/lib/cosmos/core_ext/array.rb +354 -354
  498. data/lib/cosmos/core_ext/class.rb +51 -51
  499. data/lib/cosmos/core_ext/cosmos_io.rb +29 -29
  500. data/lib/cosmos/core_ext/exception.rb +52 -52
  501. data/lib/cosmos/core_ext/file.rb +75 -75
  502. data/lib/cosmos/core_ext/hash.rb +28 -28
  503. data/lib/cosmos/core_ext/io.rb +75 -75
  504. data/lib/cosmos/core_ext/kernel.rb +38 -38
  505. data/lib/cosmos/core_ext/math.rb +119 -119
  506. data/lib/cosmos/core_ext/matrix.rb +146 -146
  507. data/lib/cosmos/core_ext/objectspace.rb +29 -29
  508. data/lib/cosmos/core_ext/range.rb +22 -22
  509. data/lib/cosmos/core_ext/socket.rb +32 -32
  510. data/lib/cosmos/core_ext/string.rb +310 -310
  511. data/lib/cosmos/core_ext/stringio.rb +24 -24
  512. data/lib/cosmos/core_ext/time.rb +446 -446
  513. data/lib/cosmos/gui/choosers/combobox_chooser.rb +130 -130
  514. data/lib/cosmos/gui/choosers/file_chooser.rb +68 -68
  515. data/lib/cosmos/gui/choosers/float_chooser.rb +82 -82
  516. data/lib/cosmos/gui/choosers/integer_chooser.rb +80 -80
  517. data/lib/cosmos/gui/choosers/string_chooser.rb +53 -53
  518. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +317 -317
  519. data/lib/cosmos/gui/dialogs/about_dialog.rb +128 -128
  520. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +136 -136
  521. data/lib/cosmos/gui/dialogs/cmd_details_dialog.rb +52 -52
  522. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +149 -149
  523. data/lib/cosmos/gui/dialogs/details_dialog.rb +174 -174
  524. data/lib/cosmos/gui/dialogs/exception_dialog.rb +97 -97
  525. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +59 -59
  526. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +196 -196
  527. data/lib/cosmos/gui/dialogs/legal_dialog.rb +169 -168
  528. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +118 -118
  529. data/lib/cosmos/gui/dialogs/progress_dialog.rb +270 -262
  530. data/lib/cosmos/gui/dialogs/pry_dialog.rb +165 -161
  531. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +37 -37
  532. data/lib/cosmos/gui/dialogs/select_dialog.rb +54 -54
  533. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +131 -131
  534. data/lib/cosmos/gui/dialogs/splash.rb +113 -113
  535. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +206 -206
  536. data/lib/cosmos/gui/dialogs/tlm_edit_dialog.rb +81 -81
  537. data/lib/cosmos/gui/line_graph/line_graph.rb +456 -456
  538. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +34 -34
  539. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +494 -494
  540. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +116 -116
  541. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +460 -460
  542. data/lib/cosmos/gui/line_graph/line_graph_script.rb +26 -26
  543. data/lib/cosmos/gui/line_graph/lines.rb +290 -290
  544. data/lib/cosmos/gui/line_graph/overview_graph.rb +459 -459
  545. data/lib/cosmos/gui/opengl/earth_model.rb +22 -22
  546. data/lib/cosmos/gui/opengl/gl_bounds.rb +67 -67
  547. data/lib/cosmos/gui/opengl/gl_light.rb +39 -39
  548. data/lib/cosmos/gui/opengl/gl_material.rb +29 -29
  549. data/lib/cosmos/gui/opengl/gl_scene.rb +72 -72
  550. data/lib/cosmos/gui/opengl/gl_shape.rb +146 -146
  551. data/lib/cosmos/gui/opengl/gl_viewer.rb +724 -712
  552. data/lib/cosmos/gui/opengl/gl_viewport.rb +35 -35
  553. data/lib/cosmos/gui/opengl/moon_model.rb +22 -22
  554. data/lib/cosmos/gui/opengl/opengl.rb +8 -8
  555. data/lib/cosmos/gui/opengl/stl_reader.rb +211 -211
  556. data/lib/cosmos/gui/opengl/stl_shape.rb +124 -124
  557. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +202 -202
  558. data/lib/cosmos/gui/qt.rb +813 -786
  559. data/lib/cosmos/gui/qt_tool.rb +378 -373
  560. data/lib/cosmos/gui/text/completion.rb +381 -381
  561. data/lib/cosmos/gui/text/completion_line_edit.rb +30 -30
  562. data/lib/cosmos/gui/text/completion_text_edit.rb +179 -179
  563. data/lib/cosmos/gui/text/ruby_editor.rb +395 -395
  564. data/lib/cosmos/gui/utilities/screenshot.rb +25 -25
  565. data/lib/cosmos/gui/utilities/script_module_gui.rb +203 -203
  566. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +161 -161
  567. data/lib/cosmos/gui/widgets/packet_log_frame.rb +305 -305
  568. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +98 -98
  569. data/lib/cosmos/interfaces.rb +11 -11
  570. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +153 -149
  571. data/lib/cosmos/interfaces/interface.rb +213 -213
  572. data/lib/cosmos/interfaces/linc_interface.rb +360 -360
  573. data/lib/cosmos/interfaces/serial_interface.rb +76 -76
  574. data/lib/cosmos/interfaces/simulated_target_interface.rb +129 -128
  575. data/lib/cosmos/interfaces/stream_interface.rb +156 -156
  576. data/lib/cosmos/interfaces/tcpip_client_interface.rb +60 -60
  577. data/lib/cosmos/interfaces/tcpip_server_interface.rb +154 -154
  578. data/lib/cosmos/interfaces/udp_interface.rb +173 -173
  579. data/lib/cosmos/io/buffered_file.rb +11 -11
  580. data/lib/cosmos/io/cosmos_snmp.rb +50 -50
  581. data/lib/cosmos/io/io_multiplexer.rb +89 -89
  582. data/lib/cosmos/io/json_drb.rb +344 -320
  583. data/lib/cosmos/io/json_drb_object.rb +137 -137
  584. data/lib/cosmos/io/json_rpc.rb +365 -365
  585. data/lib/cosmos/io/posix_serial_driver.rb +145 -145
  586. data/lib/cosmos/io/raw_logger.rb +174 -174
  587. data/lib/cosmos/io/raw_logger_pair.rb +71 -71
  588. data/lib/cosmos/io/serial_driver.rb +85 -85
  589. data/lib/cosmos/io/stderr.rb +36 -36
  590. data/lib/cosmos/io/stdout.rb +36 -36
  591. data/lib/cosmos/io/tcpip_server.rb +583 -532
  592. data/lib/cosmos/io/udp_sockets.rb +152 -152
  593. data/lib/cosmos/io/win32_serial_driver.rb +147 -147
  594. data/lib/cosmos/packet_logs.rb +6 -6
  595. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +107 -107
  596. data/lib/cosmos/packet_logs/packet_log_reader.rb +441 -439
  597. data/lib/cosmos/packet_logs/packet_log_writer.rb +321 -309
  598. data/lib/cosmos/packet_logs/packet_log_writer_pair.rb +30 -30
  599. data/lib/cosmos/packets/binary_accessor.rb +921 -921
  600. data/lib/cosmos/packets/commands.rb +291 -291
  601. data/lib/cosmos/packets/limits.rb +263 -263
  602. data/lib/cosmos/packets/limits_response.rb +38 -38
  603. data/lib/cosmos/packets/packet.rb +714 -699
  604. data/lib/cosmos/packets/packet_config.rb +1034 -1034
  605. data/lib/cosmos/packets/packet_item.rb +317 -317
  606. data/lib/cosmos/packets/packet_item_limits.rb +128 -128
  607. data/lib/cosmos/packets/structure.rb +421 -386
  608. data/lib/cosmos/packets/structure_item.rb +233 -233
  609. data/lib/cosmos/packets/telemetry.rb +317 -317
  610. data/lib/cosmos/processors.rb +6 -6
  611. data/lib/cosmos/processors/new_packet_log_processor.rb +34 -34
  612. data/lib/cosmos/processors/processor.rb +71 -71
  613. data/lib/cosmos/processors/statistics_processor.rb +65 -65
  614. data/lib/cosmos/processors/watermark_processor.rb +44 -44
  615. data/lib/cosmos/script.rb +9 -9
  616. data/lib/cosmos/script/extract.rb +115 -115
  617. data/lib/cosmos/script/script.rb +1513 -1493
  618. data/lib/cosmos/streams/burst_stream_protocol.rb +25 -25
  619. data/lib/cosmos/streams/fixed_stream_protocol.rb +111 -111
  620. data/lib/cosmos/streams/length_stream_protocol.rb +140 -140
  621. data/lib/cosmos/streams/preidentified_stream_protocol.rb +118 -118
  622. data/lib/cosmos/streams/serial_stream.rb +152 -143
  623. data/lib/cosmos/streams/stream.rb +57 -57
  624. data/lib/cosmos/streams/stream_protocol.rb +369 -369
  625. data/lib/cosmos/streams/tcpip_client_stream.rb +77 -77
  626. data/lib/cosmos/streams/tcpip_socket_stream.rb +139 -139
  627. data/lib/cosmos/streams/template_stream_protocol.rb +140 -140
  628. data/lib/cosmos/streams/terminated_stream_protocol.rb +81 -81
  629. data/lib/cosmos/system.rb +4 -4
  630. data/lib/cosmos/system/system.rb +558 -558
  631. data/lib/cosmos/system/target.rb +178 -178
  632. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +254 -253
  633. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +716 -716
  634. data/lib/cosmos/tools/cmd_sender/cmd_sender_item_delegate.rb +77 -77
  635. data/lib/cosmos/tools/cmd_sender/cmd_sender_text_edit.rb +70 -70
  636. data/lib/cosmos/tools/cmd_tlm_server/api.rb +936 -940
  637. data/lib/cosmos/tools/cmd_tlm_server/background_task.rb +46 -46
  638. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +67 -63
  639. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +511 -497
  640. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +241 -241
  641. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1033 -1008
  642. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +112 -112
  643. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +176 -176
  644. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +241 -221
  645. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +127 -127
  646. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +132 -132
  647. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +66 -66
  648. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +97 -97
  649. data/lib/cosmos/tools/data_viewer/data_viewer.rb +628 -600
  650. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +167 -167
  651. data/lib/cosmos/tools/data_viewer/dump_component.rb +40 -40
  652. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +149 -149
  653. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +360 -360
  654. data/lib/cosmos/tools/launcher/launcher.rb +184 -184
  655. data/lib/cosmos/tools/launcher/launcher_config.rb +175 -167
  656. data/lib/cosmos/tools/launcher/launcher_multitool.rb +40 -41
  657. data/lib/cosmos/tools/launcher/launcher_tool.rb +104 -104
  658. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +796 -768
  659. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +416 -416
  660. data/lib/cosmos/tools/opengl_builder/scene_config.rb +118 -118
  661. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +525 -525
  662. data/lib/cosmos/tools/replay/replay.rb +495 -488
  663. data/lib/cosmos/tools/replay/replay_server.rb +91 -91
  664. data/lib/cosmos/tools/script_runner/script_audit.rb +147 -139
  665. data/lib/cosmos/tools/script_runner/script_runner.rb +914 -914
  666. data/lib/cosmos/tools/script_runner/script_runner_config.rb +40 -40
  667. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +1892 -1859
  668. data/lib/cosmos/tools/table_manager/table.rb +70 -70
  669. data/lib/cosmos/tools/table_manager/table_config.rb +764 -764
  670. data/lib/cosmos/tools/table_manager/table_item.rb +74 -74
  671. data/lib/cosmos/tools/table_manager/table_manager.rb +1065 -1065
  672. data/lib/cosmos/tools/table_manager/table_manager_core.rb +539 -539
  673. data/lib/cosmos/tools/test_runner/results_writer.rb +283 -283
  674. data/lib/cosmos/tools/test_runner/test.rb +480 -480
  675. data/lib/cosmos/tools/test_runner/test_runner.rb +1157 -1157
  676. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +338 -338
  677. data/lib/cosmos/tools/tlm_extractor/text_item_chooser.rb +60 -60
  678. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +1008 -1008
  679. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +371 -371
  680. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +60 -60
  681. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +75 -75
  682. data/lib/cosmos/tools/tlm_grapher/data_object_adders/singlexy_data_object_adder.rb +44 -44
  683. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +94 -94
  684. data/lib/cosmos/tools/tlm_grapher/data_object_editors/data_object_editor.rb +61 -61
  685. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +180 -180
  686. data/lib/cosmos/tools/tlm_grapher/data_object_editors/linegraph_data_object_editor.rb +141 -141
  687. data/lib/cosmos/tools/tlm_grapher/data_object_editors/singlexy_data_object_editor.rb +30 -30
  688. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +173 -173
  689. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +177 -177
  690. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +412 -409
  691. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +176 -176
  692. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +25 -25
  693. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +323 -320
  694. data/lib/cosmos/tools/tlm_grapher/plot_editors/linegraph_plot_editor.rb +181 -181
  695. data/lib/cosmos/tools/tlm_grapher/plot_editors/plot_editor.rb +28 -28
  696. data/lib/cosmos/tools/tlm_grapher/plot_editors/singlexy_plot_editor.rb +30 -30
  697. data/lib/cosmos/tools/tlm_grapher/plot_editors/xy_plot_editor.rb +59 -59
  698. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/linegraph_plot_gui_object.rb +172 -172
  699. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/singlexy_plot_gui_object.rb +27 -27
  700. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/xy_plot_gui_object.rb +74 -74
  701. data/lib/cosmos/tools/tlm_grapher/plots/linegraph_plot.rb +201 -201
  702. data/lib/cosmos/tools/tlm_grapher/plots/plot.rb +69 -69
  703. data/lib/cosmos/tools/tlm_grapher/plots/singlexy_plot.rb +20 -20
  704. data/lib/cosmos/tools/tlm_grapher/plots/xy_plot.rb +61 -61
  705. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1278 -1278
  706. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +430 -430
  707. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_data_object_editor.rb +107 -107
  708. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +111 -95
  709. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +101 -101
  710. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +72 -66
  711. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tab.rb +57 -57
  712. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +1004 -1004
  713. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +87 -87
  714. data/lib/cosmos/tools/tlm_viewer/screen.rb +486 -458
  715. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +563 -544
  716. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +287 -287
  717. data/lib/cosmos/tools/tlm_viewer/widgets.rb +53 -53
  718. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +110 -110
  719. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +70 -70
  720. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +61 -61
  721. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +39 -39
  722. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +62 -62
  723. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +41 -41
  724. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +57 -57
  725. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +37 -37
  726. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +56 -56
  727. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +55 -55
  728. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +66 -66
  729. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +124 -124
  730. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +31 -31
  731. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +30 -30
  732. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +36 -36
  733. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +35 -35
  734. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +27 -27
  735. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +31 -31
  736. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +26 -26
  737. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +29 -29
  738. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +39 -39
  739. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +38 -38
  740. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +38 -38
  741. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +39 -39
  742. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +42 -42
  743. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +37 -37
  744. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +37 -37
  745. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +34 -34
  746. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +178 -178
  747. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +54 -54
  748. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +47 -47
  749. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +116 -116
  750. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +34 -34
  751. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +30 -30
  752. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +57 -57
  753. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +34 -34
  754. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +35 -35
  755. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +33 -33
  756. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +26 -26
  757. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +28 -28
  758. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +47 -47
  759. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +26 -26
  760. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +88 -88
  761. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +27 -27
  762. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +130 -130
  763. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +46 -46
  764. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +43 -43
  765. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +37 -37
  766. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +37 -37
  767. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +35 -35
  768. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +37 -37
  769. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +257 -257
  770. data/lib/cosmos/top_level.rb +647 -596
  771. data/lib/cosmos/utilities.rb +11 -10
  772. data/lib/cosmos/utilities/crc.rb +166 -166
  773. data/lib/cosmos/utilities/csv.rb +83 -83
  774. data/lib/cosmos/utilities/logger.rb +137 -137
  775. data/lib/cosmos/utilities/low_fragmentation_array.rb +11 -11
  776. data/lib/cosmos/utilities/message_log.rb +74 -74
  777. data/lib/cosmos/utilities/quaternion.rb +258 -258
  778. data/lib/cosmos/utilities/ruby_lex_utils.rb +313 -313
  779. data/lib/cosmos/utilities/simulated_target.rb +99 -99
  780. data/lib/cosmos/utilities/sleeper.rb +44 -0
  781. data/lib/cosmos/version.rb +12 -12
  782. data/lib/cosmos/win32/excel.rb +66 -66
  783. data/lib/cosmos/win32/win32.rb +387 -387
  784. data/lib/cosmos/win32/win32_main.rb +311 -311
  785. data/roodi.yml +24 -24
  786. data/run_gui_tests.bat +32 -32
  787. data/spec/ccsds/ccsds_packet_spec.rb +67 -67
  788. data/spec/ccsds/ccsds_parser_spec.rb +148 -148
  789. data/spec/config/config_parser_spec.rb +322 -322
  790. data/spec/conversions/conversion_spec.rb +31 -31
  791. data/spec/conversions/generic_conversion_spec.rb +45 -45
  792. data/spec/conversions/new_packet_log_conversion_spec.rb +39 -39
  793. data/spec/conversions/polynomial_conversion_spec.rb +40 -40
  794. data/spec/conversions/processor_conversion_spec.rb +45 -45
  795. data/spec/conversions/received_count_conversion_spec.rb +43 -43
  796. data/spec/conversions/received_time_formatted_conversion_spec.rb +49 -49
  797. data/spec/conversions/received_time_seconds_conversion_spec.rb +50 -50
  798. data/spec/conversions/segmented_polynomial_conversion_spec.rb +51 -51
  799. data/spec/conversions/unix_time_formatted_conversion_spec.rb +74 -74
  800. data/spec/conversions/unix_time_seconds_conversion_spec.rb +76 -76
  801. data/spec/core_ext/array_spec.rb +186 -186
  802. data/spec/core_ext/class_spec.rb +36 -36
  803. data/spec/core_ext/cosmos_io_spec.rb +77 -77
  804. data/spec/core_ext/exception_spec.rb +91 -91
  805. data/spec/core_ext/file_spec.rb +72 -72
  806. data/spec/core_ext/hash_spec.rb +24 -24
  807. data/spec/core_ext/io_spec.rb +46 -46
  808. data/spec/core_ext/kernel_spec.rb +54 -54
  809. data/spec/core_ext/math_spec.rb +116 -116
  810. data/spec/core_ext/matrix_spec.rb +66 -66
  811. data/spec/core_ext/objectspace_spec.rb +29 -29
  812. data/spec/core_ext/range_spec.rb +21 -21
  813. data/spec/core_ext/socket_spec.rb +32 -32
  814. data/spec/core_ext/string_spec.rb +223 -223
  815. data/spec/core_ext/stringio_spec.rb +21 -21
  816. data/spec/core_ext/time_spec.rb +151 -151
  817. data/spec/gui/line_graph/line_clip_spec.rb +322 -322
  818. data/spec/install/config/system/system.txt +33 -33
  819. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  820. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  821. data/spec/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  822. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  823. data/spec/install/config/targets/COSMOS/screens/version.txt +19 -19
  824. data/spec/install/config/targets/COSMOS/target.txt +5 -5
  825. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +30 -30
  826. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +111 -111
  827. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +236 -236
  828. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +25 -25
  829. data/spec/install/config/targets/INST/cmd_tlm_server.txt +5 -5
  830. data/spec/install/config/targets/INST/lib/sim_inst.rb +305 -294
  831. data/spec/install/config/targets/INST/target.txt +10 -10
  832. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +4 -4
  833. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +4 -4
  834. data/spec/install/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  835. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +150 -150
  836. data/spec/interfaces/interface_spec.rb +130 -131
  837. data/spec/interfaces/linc_interface_spec.rb +199 -199
  838. data/spec/interfaces/serial_interface_spec.rb +56 -56
  839. data/spec/interfaces/simulated_target_interface_spec.rb +128 -128
  840. data/spec/interfaces/stream_interface_spec.rb +157 -157
  841. data/spec/interfaces/tcpip_client_interface_spec.rb +54 -54
  842. data/spec/interfaces/tcpip_server_interface_spec.rb +151 -151
  843. data/spec/interfaces/udp_interface_spec.rb +175 -177
  844. data/spec/io/buffered_file_spec.rb +113 -113
  845. data/spec/io/io_multiplexer_spec.rb +94 -94
  846. data/spec/io/json_drb_object_spec.rb +99 -99
  847. data/spec/io/json_drb_spec.rb +311 -311
  848. data/spec/io/json_rpc_spec.rb +264 -264
  849. data/spec/io/raw_logger_pair_spec.rb +76 -76
  850. data/spec/io/raw_logger_spec.rb +133 -133
  851. data/spec/io/serial_driver_spec.rb +61 -61
  852. data/spec/io/stderr_spec.rb +32 -32
  853. data/spec/io/stdout_spec.rb +32 -32
  854. data/spec/io/tcpip_server_spec.rb +338 -338
  855. data/spec/io/udp_sockets_spec.rb +94 -94
  856. data/spec/io/win32_serial_driver_spec.rb +88 -88
  857. data/spec/packet_logs/meta_packet_log_writer_spec.rb +170 -170
  858. data/spec/packet_logs/packet_log_reader_spec.rb +408 -408
  859. data/spec/packet_logs/packet_log_writer_pair_spec.rb +30 -30
  860. data/spec/packet_logs/packet_log_writer_spec.rb +223 -223
  861. data/spec/packets/binary_accessor_spec.rb +2073 -2073
  862. data/spec/packets/commands_spec.rb +369 -369
  863. data/spec/packets/limits_response_spec.rb +25 -25
  864. data/spec/packets/limits_spec.rb +326 -326
  865. data/spec/packets/packet_config_spec.rb +1620 -1620
  866. data/spec/packets/packet_item_limits_spec.rb +161 -161
  867. data/spec/packets/packet_item_spec.rb +386 -386
  868. data/spec/packets/packet_spec.rb +1057 -949
  869. data/spec/packets/structure_item_spec.rb +195 -195
  870. data/spec/packets/structure_spec.rb +419 -419
  871. data/spec/packets/telemetry_spec.rb +535 -535
  872. data/spec/processors/new_packet_log_processor_spec.rb +39 -39
  873. data/spec/processors/processor_spec.rb +55 -55
  874. data/spec/processors/statistics_processor_spec.rb +60 -60
  875. data/spec/processors/watermark_processor_spec.rb +51 -51
  876. data/spec/script/script_spec.rb +654 -654
  877. data/spec/spec_helper.rb +154 -148
  878. data/spec/streams/burst_stream_protocol_spec.rb +32 -32
  879. data/spec/streams/fixed_stream_protocol_spec.rb +110 -110
  880. data/spec/streams/length_stream_protocol_spec.rb +297 -297
  881. data/spec/streams/preidentified_stream_protocol_spec.rb +118 -118
  882. data/spec/streams/serial_stream_spec.rb +105 -105
  883. data/spec/streams/stream_protocol_spec.rb +332 -332
  884. data/spec/streams/stream_spec.rb +29 -29
  885. data/spec/streams/tcpip_client_stream_spec.rb +54 -54
  886. data/spec/streams/tcpip_socket_stream_spec.rb +146 -146
  887. data/spec/streams/template_stream_protocol_spec.rb +151 -151
  888. data/spec/streams/terminated_stream_protocol_spec.rb +123 -123
  889. data/spec/system/system_spec.rb +645 -645
  890. data/spec/system/target_spec.rb +248 -248
  891. data/spec/tools/cmd_tlm_server/api_spec.rb +1087 -1113
  892. data/spec/tools/cmd_tlm_server/background_task_spec.rb +32 -32
  893. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +81 -81
  894. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +411 -411
  895. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +415 -415
  896. data/spec/tools/cmd_tlm_server/commanding_spec.rb +123 -123
  897. data/spec/tools/cmd_tlm_server/connections_spec.rb +147 -147
  898. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +306 -306
  899. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +252 -238
  900. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +143 -143
  901. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +98 -101
  902. data/spec/tools/cmd_tlm_server/routers_spec.rb +223 -208
  903. data/spec/top_level/top_level_spec.rb +334 -321
  904. data/spec/utilities/crc_spec.rb +45 -45
  905. data/spec/utilities/csv_spec.rb +97 -97
  906. data/spec/utilities/logger_spec.rb +102 -102
  907. data/spec/utilities/message_log_spec.rb +89 -89
  908. data/spec/utilities/quaternion_spec.rb +107 -107
  909. data/spec/utilities/ruby_lex_utils_spec.rb +86 -86
  910. data/tasks/manifest.rake +22 -22
  911. data/tasks/spec.rake +23 -23
  912. metadata +18 -2
@@ -1,596 +1,647 @@
1
- # encoding: ascii-8bit
2
-
3
- # Copyright 2014 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 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 file contains top level functions in the Cosmos namespace
12
-
13
- require 'thread'
14
- require 'digest/md5'
15
- require 'open3'
16
- require 'cosmos/core_ext'
17
- require 'cosmos/version'
18
- require 'cosmos/utilities/logger'
19
-
20
- # If a hazardous command is sent through the {Cosmos::Api} this error is raised.
21
- # {Cosmos::Script} rescues the error and prompts the user to continue.
22
- class HazardousError < StandardError
23
- attr_accessor :target_name
24
- attr_accessor :cmd_name
25
- attr_accessor :cmd_params
26
- attr_accessor :hazardous_description
27
- end
28
-
29
- # The COSMOS (COmprehensive SysteM Operations Suite) system is almost
30
- # wholly contained within the Cosmos module. COSMOS also extends some of the
31
- # core Ruby classes to add additional functionality as well as creates
32
- # additional QT GUI classes under the {Qt} module.
33
- #
34
- # The primary entry point into COSMOS is through {Cosmos::System}. The System
35
- # class provides two class variables {Cosmos::System#commands} and
36
- # {Cosmos::System#telemetry} which provide access to all the commands and
37
- # telemetry in Cosmos. The targets are available through the
38
- # {Cosmos::System#targets} hash whose keys are the target names and values are
39
- # {Cosmos::Target} instances.
40
- #
41
- # Creating a new COSMOS tool involves subclassing {Cosmos::QtTool}. All COSMOS
42
- # tools derive from {Cosmos::QtTool} and provide a good basis for creating a
43
- # new tool. Be sure to explore the various GUI classes
44
- module Cosmos
45
-
46
- # FatalErrors cause an exit but are not as dangerous as other errors.
47
- # They are used for known issues and thus we don't need a full error report.
48
- class FatalError < StandardError; end
49
-
50
- # Global mutex for the Cosmos module
51
- COSMOS_MUTEX = Mutex.new
52
-
53
- # Path to COSMOS Gem based on location of top_level.rb
54
- PATH = File.expand_path(File.join(File.dirname(__FILE__), '../..'))
55
- PATH.freeze
56
-
57
- # Header to put on all marshal files created by COSMOS
58
- COSMOS_MARSHAL_HEADER = "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}] COSMOS #{COSMOS_VERSION}"
59
-
60
- # Disables the Ruby interpreter warnings such as when redefining a constant
61
- def self.disable_warnings
62
- saved_verbose = $VERBOSE
63
- $VERBOSE = nil
64
- yield
65
- $VERBOSE = saved_verbose
66
- end
67
-
68
- # Searches for the file userpath.txt to define the USERPATH constant
69
- #
70
- # @param start_dir [String] Path to start the search for userpath.txt. The
71
- # search will continue by moving up directories until the root directory is
72
- # reached.
73
- def self.define_user_path(start_dir = Dir.pwd)
74
- current_dir = File.expand_path(start_dir)
75
- while true
76
- if File.exist?(File.join(current_dir, 'userpath.txt'))
77
- disable_warnings do
78
- Cosmos.const_set(:USERPATH, current_dir)
79
- end
80
- break
81
- else
82
- old_current_dir = current_dir
83
- current_dir = File.expand_path(File.join(current_dir, '..'))
84
- if old_current_dir == current_dir
85
- # Hit the root dir - give up
86
- break
87
- end
88
- end
89
- end
90
- end
91
-
92
- #############################################################################
93
- # This code is executed in place when this file is required
94
-
95
- # Initialize to nil before searching
96
- USERPATH = nil
97
-
98
- # First attempt try from the location of the executable ($0)
99
- # Note this method will fail when a intermediary executable is used like rcov
100
- self.define_user_path(File.dirname($0))
101
- if USERPATH.nil?
102
- # Second attempt try from location of the current working directory
103
- self.define_user_path(Dir.pwd)
104
- if USERPATH.nil?
105
- # Last chance - Check environment
106
- if ENV['COSMOS_USERPATH']
107
- disable_warnings do
108
- Cosmos.const_set(:USERPATH, ENV['COSMOS_USERPATH'])
109
- end
110
- else
111
- # Give up and assume we are in the tools directory and there is no userpath.txt file
112
- disable_warnings do
113
- Cosmos.const_set(:USERPATH, File.expand_path(File.join(File.dirname($0), '..')))
114
- end
115
- end
116
- end
117
- end
118
- USERPATH.freeze
119
-
120
- #############################################################################
121
-
122
-
123
- # Adds a path to the global Ruby search path
124
- #
125
- # @param path [String] Directory path
126
- def self.add_to_search_path(path, front = true)
127
- Cosmos.set_working_dir do
128
- path = File.expand_path(path)
129
- $:.delete(path)
130
- if front
131
- $:.unshift(path)
132
- else # Back
133
- $: << path
134
- end
135
- end
136
- end
137
-
138
- # Creates a marshal file by serializing the given obj
139
- #
140
- # @param marshal_filename [String] Name of the marshal file to create
141
- # @param obj [Object] The object to serialize to the file
142
- def self.marshal_dump(marshal_filename, obj)
143
- begin
144
- Cosmos.set_working_dir do
145
- File.open(marshal_filename, 'wb') do |file|
146
- file.write(COSMOS_MARSHAL_HEADER)
147
- file.write(Marshal.dump(obj))
148
- end
149
- end
150
- rescue Exception => exception
151
- begin
152
- Cosmos.set_working_dir do
153
- File.delete(marshal_filename)
154
- end
155
- rescue Exception
156
- # Oh well - we tried
157
- end
158
- self.handle_fatal_exception(exception)
159
- end
160
- end
161
-
162
- # Loads the marshal file back into a Ruby object
163
- #
164
- # @param marshal_filename [String] Name of the marshal file to load
165
- def self.marshal_load(marshal_filename)
166
- begin
167
- cosmos_marshal_header = nil
168
- data = nil
169
- Cosmos.set_working_dir do
170
- File.open(marshal_filename, 'rb') do |file|
171
- cosmos_marshal_header = file.read(COSMOS_MARSHAL_HEADER.length)
172
- data = file.read
173
- end
174
- end
175
- if cosmos_marshal_header == COSMOS_MARSHAL_HEADER
176
- return Marshal.load(data)
177
- else
178
- Logger.warn "Marshal load failed with invalid marshal file: #{marshal_filename}"
179
- return nil
180
- end
181
- rescue Exception => exception
182
- Cosmos.set_working_dir do
183
- if File.exist?(marshal_filename)
184
- Logger.error "Marshal load failed with exception: #{marshal_filename}\n#{exception.formatted}"
185
- else
186
- Logger.info "Marshal file does not exist: #{marshal_filename}"
187
- end
188
-
189
- # Try to delete the bad marshal file
190
- begin
191
- File.delete(marshal_filename)
192
- rescue Exception
193
- # Oh well - we tried
194
- end
195
- self.handle_fatal_exception(exception) if File.exist?(marshal_filename)
196
- end
197
- return nil
198
- end
199
- end
200
-
201
- # Changes the current working directory to the USERPATH and then executes the
202
- # command in a new Ruby Thread.
203
- #
204
- # @param command [String] The command to execute via the 'system' call
205
- def self.run_process(command)
206
- thread = nil
207
- Cosmos.set_working_dir do
208
- thread = Thread.new do
209
- system(command)
210
- end
211
- # Wait for the thread and process to start
212
- sleep 0.01 until !thread.status.nil?
213
- sleep 0.1
214
- end
215
- thread
216
- end
217
-
218
- # Changes the current working directory to the USERPATH and then executes the
219
- # command in a new Ruby Thread. Will show a messagebox or print the output if the
220
- # process produces any output
221
- #
222
- # @param command [String] The command to execute via the 'system' call
223
- def self.run_process_check_output(command)
224
- thread = nil
225
- Cosmos.set_working_dir do
226
- thread = Thread.new do
227
- output, _ = Open3.capture2e(command)
228
- if !output.empty?
229
- # Work around modalSession messages on Mac Mavericks
230
- real_lines = 0
231
- output.each_line do |line|
232
- real_lines += 1 if line !~ /modalSession/
233
- end
234
-
235
- if real_lines > 0
236
- Logger.error output
237
- self.write_unexpected_file(output)
238
- if defined? Qt and Qt::Application.instance
239
- Qt.execute_in_main_thread(false) do
240
- dialog = Qt::Dialog.new do |box|
241
- box.setWindowTitle('Unexpected text output')
242
- box.resize(600, 600)
243
- text_field = Qt::PlainTextEdit.new
244
- text_field.setReadOnly(true)
245
- orig_font = text_field.font
246
- text_field.setFont(Cosmos.getFont(orig_font.family, orig_font.point_size+2))
247
- text_field.setWordWrapMode(Qt::TextOption::NoWrap)
248
- text_field.appendPlainText(output)
249
- vframe = Qt::VBoxLayout.new
250
- vframe.addWidget(text_field)
251
- sep = Qt::Frame.new(box)
252
- sep.setFrameStyle(Qt::Frame::VLine | Qt::Frame::Sunken)
253
- vframe.addWidget(sep)
254
- ok = Qt::PushButton.new('OK')
255
- ok.setDefault(true)
256
- ok.connect(SIGNAL('clicked(bool)')) { box.accept }
257
- vframe.addWidget(ok)
258
- box.setLayout(vframe)
259
- box.show
260
- box.raise
261
- end
262
- dialog.exec
263
- dialog.dispose
264
- end
265
- end
266
- end
267
- end
268
- end
269
- # Wait for the thread and process to start
270
- sleep 0.01 until !thread.status.nil?
271
- sleep 0.1
272
- end
273
- thread
274
- end
275
-
276
- # Runs an md5 sum over one or more files and returns the Digest::MD5 object.
277
- # Handles windows/unix new line differences but changes in whitespace will
278
- # change the md5 sum.
279
- #
280
- # Usage:
281
- # digest = Cosmos.md5_files(files)
282
- # digest.digest # => the 16 bytes of digest
283
- # digest.hexdigest # => the formatted string in hex
284
- #
285
- # @param filenames [Array<String>] List of files to read and calculate a md5
286
- # sum on
287
- # @param additional_data [String] Additional data to add to the md5 sum
288
- # @return [Digest::MD5] The md5 sum
289
- def self.md5_files(filenames, additional_data = nil)
290
- digest = Digest::MD5.new
291
- Cosmos.set_working_dir do
292
- filenames.each do |filename|
293
- # Read the file's data
294
- data = ''
295
- File.open(filename, 'r') {|file| data = file.read.gsub("\r",'')}
296
-
297
- # Add to the running MD5 sum
298
- digest << data
299
- end
300
- end
301
- digest << additional_data if additional_data
302
- digest
303
- end
304
-
305
- # Opens a timestamped log file for writing. The opened file is yielded back
306
- # to the block.
307
- #
308
- # @param filename [String] String to append to the exception log filename.
309
- # The filename will start with a date/time stamp.
310
- # @param log_dir [String] By default this method will write to the COSMOS
311
- # default log directory. By setting this parameter you can override the
312
- # directory the log will be written to.
313
- # @yieldparam file [File] The log file
314
- # @return [String|nil] The fully pathed log file name or nil if there was
315
- # an error creating the log file.
316
- def self.create_log_file(filename, log_dir)
317
- log_file = nil
318
- Cosmos.set_working_dir do
319
- begin
320
- # The following code goes inside a begin rescue because it reads the
321
- # system.txt configuration file. If this has an error we won't be able
322
- # to determine the log path but we still want to write the log.
323
- log_dir = System.instance.paths['LOGS'] unless log_dir
324
- log_file = File.join(log_dir,
325
- File.build_timestamped_filename([filename]))
326
- # Make sure the log directory exists
327
- raise unless File.exist?(log_dir)
328
- log_file
329
- rescue
330
- # If not then we just build a file locally
331
- if File.exist?('./outputs/logs')
332
- log_file = File.join('./outputs/logs', File.build_timestamped_filename([filename]))
333
- elsif File.exist?('./logs')
334
- log_file = File.join('./logs', File.build_timestamped_filename([filename]))
335
- else
336
- log_file = File.build_timestamped_filename([filename])
337
- end
338
- end
339
- begin
340
- # Log exception to file, open the file in append mode in case we get
341
- # multiple exceptions in the same second. That way we don't lose
342
- # exceptions by overwritting the last exception file.
343
- COSMOS_MUTEX.synchronize do
344
- File.open(log_file, 'a') {|file| yield file }
345
- end
346
- rescue Exception
347
- # Ensure we always return
348
- end
349
- log_file = File.expand_path(log_file)
350
- end
351
- return log_file
352
- end
353
-
354
- # Writes a log file with information about the current configuration
355
- # including the Ruby version, Cosmos version, whether you are on Windows, the
356
- # COSMOS path and userpath, and the Ruby path along with the exception that
357
- # is passed in.
358
- #
359
- # @param [String] filename String to append to the exception log filename.
360
- # The filename will start with a date/time stamp.
361
- # @param [String] log_dir By default this method will write to the COSMOS
362
- # default log directory. By setting this parameter you can override the
363
- # directory the log will be written to.
364
- # @return [String|nil] The fully pathed log file name or nil if there was
365
- # an error creating the log file.
366
- def self.write_exception_file(exception, filename = 'exception', log_dir = nil)
367
- log_file = create_log_file(filename, log_dir) do |file|
368
- file.puts "Exception:"
369
- if exception
370
- file.puts exception.formatted
371
- file.puts
372
- else
373
- file.puts "No Exception Given"
374
- file.puts caller.join("\n")
375
- file.puts
376
- end
377
- file.puts "Caller Backtrace:"
378
- file.puts caller().join("\n")
379
- file.puts
380
-
381
- file.puts "Ruby Version: ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
382
- file.puts "Rubygems Version: #{Gem::VERSION}"
383
- file.puts "Cosmos Version: #{Cosmos::VERSION}"
384
- file.puts "Cosmos::PATH: #{Cosmos::PATH}"
385
- file.puts "Cosmos::USERPATH: #{Cosmos::USERPATH}"
386
- file.puts ""
387
- file.puts "Environment:"
388
- file.puts "RUBYOPT: #{ENV['GEM_HOME']}"
389
- file.puts "RUBYLIB: #{ENV['GEM_HOME']}"
390
- file.puts "GEM_PATH: #{ENV['GEM_HOME']}"
391
- file.puts "GEMRC: #{ENV['GEM_HOME']}"
392
- file.puts "RI_DEVKIT: #{ENV['GEM_HOME']}"
393
- file.puts "GEM_HOME: #{ENV['GEM_HOME']}"
394
- file.puts "PATH: #{ENV['PATH']}"
395
- file.puts ""
396
- file.puts "Ruby Path:\n #{$:.join("\n ")}\n\n"
397
- file.puts "Gems:"
398
- Gem.loaded_specs.values.map {|x| file.puts "#{x.name} #{x.version} #{x.platform}"}
399
- file.puts ""
400
- file.puts ""
401
- end
402
- return log_file
403
- end
404
-
405
- # Writes a log file with information about unexpected output
406
- #
407
- # @param[String] text The unexpected output text
408
- # @param [String] filename String to append to the exception log filename.
409
- # The filename will start with a date/time stamp.
410
- # @param [String] log_dir By default this method will write to the COSMOS
411
- # default log directory. By setting this parameter you can override the
412
- # directory the log will be written to.
413
- # @return [String|nil] The fully pathed log file name or nil if there was
414
- # an error creating the log file.
415
- def self.write_unexpected_file(text, filename = 'unexpected', log_dir = nil)
416
- log_file = create_log_file(filename, log_dir) do |file|
417
- file.puts "Unexpected Output:\n\n"
418
- file.puts text
419
- end
420
- return log_file
421
- end
422
-
423
- # Catch fatal exceptions within the block
424
- # This is intended to catch exceptions before the GUI is available
425
- def self.catch_fatal_exception
426
- begin
427
- yield
428
- rescue Exception => error
429
- unless error.class == SystemExit or error.class == Interrupt
430
- Logger.level = Logger::FATAL
431
- Cosmos.handle_fatal_exception(error, false)
432
- end
433
- end
434
- end
435
-
436
- # Write a message to the Logger, write an exception file, and popup a GUI
437
- # window if try_gui. Finally 'exit 1' is called to end the calling program.
438
- #
439
- # @param error [Exception] The exception to handle
440
- # @param try_gui [Boolean] Whether to try and create a GUI exception popup
441
- def self.handle_fatal_exception(error, try_gui = true)
442
- log_file = self.write_exception_file(error)
443
- Logger.level = Logger::FATAL unless try_gui
444
- Logger.fatal "Fatal Exception! Exiting..."
445
- Logger.fatal error.formatted
446
- if defined? ExceptionDialog and try_gui
447
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(nil, error, '', true, false, log_file)}
448
- else
449
- if $stdout != STDOUT
450
- $stdout = STDOUT
451
- Logger.fatal "Fatal Exception! Exiting..."
452
- Logger.fatal error.formatted
453
- end
454
- sleep 1 # Allow the messages to be printed and then crash
455
- exit 1
456
- end
457
- end
458
-
459
- # CriticalErrors are errors that need to be brought to a user's attention but
460
- # do not cause an exit. A good example is if the packet log writer fails and
461
- # can no longer write the log file. Write a message to the Logger, write an
462
- # exception file, and popup a GUI window if try_gui. Ensure the GUI only
463
- # comes up once so this method can be called over and over by failing code.
464
- #
465
- # @param error [Exception] The exception to handle
466
- # @param try_gui [Boolean] Whether to try and create a GUI exception popup
467
- def self.handle_critical_exception(error, try_gui = true)
468
- Logger.error "Critical Exception! #{error.formatted}"
469
- if defined? ExceptionDialog and !ExceptionDialog.dialog_open?
470
- log_file = self.write_exception_file(error)
471
- if try_gui
472
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(nil, error, '', false, false, log_file)}
473
- end
474
- end
475
- end
476
-
477
- # Creates a Ruby Thread to run the given block. Rescues any exceptions and
478
- # retries the threads the given number of times before handling the thread
479
- # death by calling {Cosmos.handle_fatal_exception}.
480
- #
481
- # @param name [String] Name of the thread
482
- # @param retry_attempts [Integer] The number of times to allow the thread to
483
- # restart before exiting
484
- def self.safe_thread(name, retry_attempts = 0)
485
- Thread.new do
486
- retry_count = 0
487
- begin
488
- yield
489
- rescue Exception => error
490
- Logger.error "#{name} thread unexpectedly died. Retries: #{retry_count} of #{retry_attempts}"
491
- Logger.error error.formatted
492
- retry_count += 1
493
- if retry_count <= retry_attempts
494
- self.write_exception_file(error)
495
- retry
496
- end
497
- handle_fatal_exception(error)
498
- end
499
- end
500
- end
501
-
502
- # Require the class represented by the filename. This uses the standard Ruby
503
- # convention of having a single class per file where the class name is camel
504
- # cased and filename is lowercase with underscores.
505
- #
506
- # @param class_filename [String] The name of the file which contains the
507
- # Ruby class to require
508
- def self.require_class(class_filename)
509
- class_name = class_filename.filename_to_class_name
510
- return class_name.to_class if class_name.to_class and defined? class_name.to_class
511
- begin
512
- require class_filename
513
- rescue LoadError => err
514
- msg = "Unable to require #{class_filename} due to #{err.message}. Ensure #{class_filename} is in the COSMOS lib directory."
515
- Logger.error msg
516
- raise msg
517
- end
518
- klass = class_name.to_class
519
- if klass
520
- return klass
521
- else
522
- raise "Ruby class #{class_name} not found"
523
- end
524
- end
525
-
526
- # @param filename [String] Name of the file to open in the editor
527
- def self.open_in_text_editor(filename)
528
- if filename
529
- if Kernel.is_windows?
530
- if File.extname(filename).to_s.downcase == '.csv'
531
- self.run_process("cmd /c \"start wordpad \"#{filename.gsub('/','\\')}\"\"")
532
- else
533
- self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
534
- end
535
- elsif Kernel.is_mac?
536
- self.run_process("open -a TextEdit \"#{filename}\"")
537
- else
538
- which_gedit = `which gedit 2>&1`.chomp
539
- if which_gedit =~ /Command not found/i or which_gedit =~ /no .* in/i
540
- # No gedit
541
- editor = ENV['EDITOR']
542
- editor = 'vi' unless editor
543
- which_xterm = `which xterm 2>&1`.chomp
544
- if which_xterm =~ /Command not found/i or which_xterm =~ /no .* in/i
545
- # No xterm
546
- which_gnome_terminal = `which gnome-terminal 2>&1`.chomp
547
- if which_gnome_terminal =~ /Command not found/i or which_gnome_terminal =~ /no .* in/i
548
- # No gnome-terminal - Do nothing
549
- else
550
- # Have gnome-terminal
551
- system_call = "gnome-terminal -e #{editor} \"#{filename}\""
552
- end
553
- else
554
- # Have xterm
555
- system_call = "xterm -e #{editor} \"#{filename}\""
556
- end
557
- else
558
- # Have gedit
559
- system_call = "gedit \"#{filename}\""
560
- end
561
- self.run_process(system_call)
562
- end
563
- end
564
- end
565
-
566
- # @param filename [String] Name of the file to open in the web browser
567
- def self.open_in_web_browser(filename)
568
- if filename
569
- if Kernel.is_windows?
570
- self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
571
- elsif Kernel.is_mac?
572
- self.run_process("open -a Safari \"#{filename}\"")
573
- else
574
- which_firefox = `which firefox`.chomp
575
- if which_firefox =~ /Command not found/i or which_firefox =~ /no .* in/i
576
- raise "Firefox not found"
577
- else
578
- system_call = "#{which_firefox} \"#{filename}\""
579
- end
580
- self.run_process(system_call)
581
- end
582
- end
583
- end
584
-
585
- # Temporarily set the working directory during a block
586
- def self.set_working_dir(working_dir = Cosmos::USERPATH)
587
- current_dir = Dir.pwd
588
- Dir.chdir(working_dir)
589
- begin
590
- yield
591
- ensure
592
- Dir.chdir(current_dir)
593
- end
594
- end
595
-
596
- end
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 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 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 file contains top level functions in the Cosmos namespace
12
+
13
+ require 'thread'
14
+ require 'digest/md5'
15
+ require 'open3'
16
+ require 'cosmos/core_ext'
17
+ require 'cosmos/version'
18
+ require 'cosmos/utilities/logger'
19
+
20
+ # If a hazardous command is sent through the {Cosmos::Api} this error is raised.
21
+ # {Cosmos::Script} rescues the error and prompts the user to continue.
22
+ class HazardousError < StandardError
23
+ attr_accessor :target_name
24
+ attr_accessor :cmd_name
25
+ attr_accessor :cmd_params
26
+ attr_accessor :hazardous_description
27
+ end
28
+
29
+ # The COSMOS (COmprehensive SysteM Operations Suite) system is almost
30
+ # wholly contained within the Cosmos module. COSMOS also extends some of the
31
+ # core Ruby classes to add additional functionality as well as creates
32
+ # additional QT GUI classes under the {Qt} module.
33
+ #
34
+ # The primary entry point into COSMOS is through {Cosmos::System}. The System
35
+ # class provides two class variables {Cosmos::System#commands} and
36
+ # {Cosmos::System#telemetry} which provide access to all the commands and
37
+ # telemetry in Cosmos. The targets are available through the
38
+ # {Cosmos::System#targets} hash whose keys are the target names and values are
39
+ # {Cosmos::Target} instances.
40
+ #
41
+ # Creating a new COSMOS tool involves subclassing {Cosmos::QtTool}. All COSMOS
42
+ # tools derive from {Cosmos::QtTool} and provide a good basis for creating a
43
+ # new tool. Be sure to explore the various GUI classes
44
+ module Cosmos
45
+
46
+ # FatalErrors cause an exit but are not as dangerous as other errors.
47
+ # They are used for known issues and thus we don't need a full error report.
48
+ class FatalError < StandardError; end
49
+
50
+ # Global mutex for the Cosmos module
51
+ COSMOS_MUTEX = Mutex.new
52
+
53
+ # Path to COSMOS Gem based on location of top_level.rb
54
+ PATH = File.expand_path(File.join(File.dirname(__FILE__), '../..'))
55
+ PATH.freeze
56
+
57
+ # Header to put on all marshal files created by COSMOS
58
+ COSMOS_MARSHAL_HEADER = "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}] COSMOS #{COSMOS_VERSION}"
59
+
60
+ # Disables the Ruby interpreter warnings such as when redefining a constant
61
+ def self.disable_warnings
62
+ saved_verbose = $VERBOSE
63
+ $VERBOSE = nil
64
+ yield
65
+ $VERBOSE = saved_verbose
66
+ end
67
+
68
+ # Searches for the file userpath.txt to define the USERPATH constant
69
+ #
70
+ # @param start_dir [String] Path to start the search for userpath.txt. The
71
+ # search will continue by moving up directories until the root directory is
72
+ # reached.
73
+ def self.define_user_path(start_dir = Dir.pwd)
74
+ current_dir = File.expand_path(start_dir)
75
+ while true
76
+ if File.exist?(File.join(current_dir, 'userpath.txt'))
77
+ disable_warnings do
78
+ Cosmos.const_set(:USERPATH, current_dir)
79
+ end
80
+ break
81
+ else
82
+ old_current_dir = current_dir
83
+ current_dir = File.expand_path(File.join(current_dir, '..'))
84
+ if old_current_dir == current_dir
85
+ # Hit the root dir - give up
86
+ break
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ #############################################################################
93
+ # This code is executed in place when this file is required
94
+
95
+ # Initialize to nil before searching
96
+ USERPATH = nil
97
+
98
+ # First attempt try from the location of the executable ($0)
99
+ # Note this method will fail when a intermediary executable is used like rcov
100
+ self.define_user_path(File.dirname($0))
101
+ if USERPATH.nil?
102
+ # Second attempt try from location of the current working directory
103
+ self.define_user_path(Dir.pwd)
104
+ if USERPATH.nil?
105
+ # Last chance - Check environment
106
+ if ENV['COSMOS_USERPATH']
107
+ disable_warnings do
108
+ Cosmos.const_set(:USERPATH, ENV['COSMOS_USERPATH'])
109
+ end
110
+ else
111
+ # Give up and assume we are in the tools directory and there is no userpath.txt file
112
+ disable_warnings do
113
+ Cosmos.const_set(:USERPATH, File.expand_path(File.join(File.dirname($0), '..')))
114
+ end
115
+ end
116
+ end
117
+ end
118
+ USERPATH.freeze
119
+
120
+ #############################################################################
121
+
122
+
123
+ # Adds a path to the global Ruby search path
124
+ #
125
+ # @param path [String] Directory path
126
+ def self.add_to_search_path(path, front = true)
127
+ Cosmos.set_working_dir do
128
+ path = File.expand_path(path)
129
+ $:.delete(path)
130
+ if front
131
+ $:.unshift(path)
132
+ else # Back
133
+ $: << path
134
+ end
135
+ end
136
+ end
137
+
138
+ # Creates a marshal file by serializing the given obj
139
+ #
140
+ # @param marshal_filename [String] Name of the marshal file to create
141
+ # @param obj [Object] The object to serialize to the file
142
+ def self.marshal_dump(marshal_filename, obj)
143
+ begin
144
+ Cosmos.set_working_dir do
145
+ File.open(marshal_filename, 'wb') do |file|
146
+ file.write(COSMOS_MARSHAL_HEADER)
147
+ file.write(Marshal.dump(obj))
148
+ end
149
+ end
150
+ rescue Exception => exception
151
+ begin
152
+ Cosmos.set_working_dir do
153
+ File.delete(marshal_filename)
154
+ end
155
+ rescue Exception
156
+ # Oh well - we tried
157
+ end
158
+ self.handle_fatal_exception(exception)
159
+ end
160
+ end
161
+
162
+ # Loads the marshal file back into a Ruby object
163
+ #
164
+ # @param marshal_filename [String] Name of the marshal file to load
165
+ def self.marshal_load(marshal_filename)
166
+ begin
167
+ cosmos_marshal_header = nil
168
+ data = nil
169
+ Cosmos.set_working_dir do
170
+ File.open(marshal_filename, 'rb') do |file|
171
+ cosmos_marshal_header = file.read(COSMOS_MARSHAL_HEADER.length)
172
+ data = file.read
173
+ end
174
+ end
175
+ if cosmos_marshal_header == COSMOS_MARSHAL_HEADER
176
+ return Marshal.load(data)
177
+ else
178
+ Logger.warn "Marshal load failed with invalid marshal file: #{marshal_filename}"
179
+ return nil
180
+ end
181
+ rescue Exception => exception
182
+ Cosmos.set_working_dir do
183
+ if File.exist?(marshal_filename)
184
+ Logger.error "Marshal load failed with exception: #{marshal_filename}\n#{exception.formatted}"
185
+ else
186
+ Logger.info "Marshal file does not exist: #{marshal_filename}"
187
+ end
188
+
189
+ # Try to delete the bad marshal file
190
+ begin
191
+ File.delete(marshal_filename)
192
+ rescue Exception
193
+ # Oh well - we tried
194
+ end
195
+ self.handle_fatal_exception(exception) if File.exist?(marshal_filename)
196
+ end
197
+ return nil
198
+ end
199
+ end
200
+
201
+ # Changes the current working directory to the USERPATH and then executes the
202
+ # command in a new Ruby Thread.
203
+ #
204
+ # @param command [String] The command to execute via the 'system' call
205
+ def self.run_process(command)
206
+ thread = nil
207
+ Cosmos.set_working_dir do
208
+ thread = Thread.new do
209
+ system(command)
210
+ end
211
+ # Wait for the thread and process to start
212
+ sleep 0.01 until !thread.status.nil?
213
+ sleep 0.1
214
+ end
215
+ thread
216
+ end
217
+
218
+ # Changes the current working directory to the USERPATH and then executes the
219
+ # command in a new Ruby Thread. Will show a messagebox or print the output if the
220
+ # process produces any output
221
+ #
222
+ # @param command [String] The command to execute via the 'system' call
223
+ def self.run_process_check_output(command)
224
+ thread = nil
225
+ Cosmos.set_working_dir do
226
+ thread = Thread.new do
227
+ output, _ = Open3.capture2e(command)
228
+ if !output.empty?
229
+ # Work around modalSession messages on Mac Mavericks
230
+ real_lines = 0
231
+ output.each_line do |line|
232
+ real_lines += 1 if line !~ /modalSession/
233
+ end
234
+
235
+ if real_lines > 0
236
+ Logger.error output
237
+ self.write_unexpected_file(output)
238
+ if defined? Qt and Qt::Application.instance
239
+ Qt.execute_in_main_thread(false) do
240
+ dialog = Qt::Dialog.new do |box|
241
+ box.setWindowTitle('Unexpected text output')
242
+ box.resize(600, 600)
243
+ text_field = Qt::PlainTextEdit.new
244
+ text_field.setReadOnly(true)
245
+ orig_font = text_field.font
246
+ text_field.setFont(Cosmos.getFont(orig_font.family, orig_font.point_size+2))
247
+ text_field.setWordWrapMode(Qt::TextOption::NoWrap)
248
+ text_field.appendPlainText(output)
249
+ vframe = Qt::VBoxLayout.new
250
+ vframe.addWidget(text_field)
251
+ sep = Qt::Frame.new(box)
252
+ sep.setFrameStyle(Qt::Frame::VLine | Qt::Frame::Sunken)
253
+ vframe.addWidget(sep)
254
+ ok = Qt::PushButton.new('OK')
255
+ ok.setDefault(true)
256
+ ok.connect(SIGNAL('clicked(bool)')) { box.accept }
257
+ vframe.addWidget(ok)
258
+ box.setLayout(vframe)
259
+ box.show
260
+ box.raise
261
+ end
262
+ dialog.exec
263
+ dialog.dispose
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
269
+ # Wait for the thread and process to start
270
+ sleep 0.01 until !thread.status.nil?
271
+ sleep 0.1
272
+ end
273
+ thread
274
+ end
275
+
276
+ # Runs an md5 sum over one or more files and returns the Digest::MD5 object.
277
+ # Handles windows/unix new line differences but changes in whitespace will
278
+ # change the md5 sum.
279
+ #
280
+ # Usage:
281
+ # digest = Cosmos.md5_files(files)
282
+ # digest.digest # => the 16 bytes of digest
283
+ # digest.hexdigest # => the formatted string in hex
284
+ #
285
+ # @param filenames [Array<String>] List of files to read and calculate a md5
286
+ # sum on
287
+ # @param additional_data [String] Additional data to add to the md5 sum
288
+ # @return [Digest::MD5] The md5 sum
289
+ def self.md5_files(filenames, additional_data = nil)
290
+ digest = Digest::MD5.new
291
+ Cosmos.set_working_dir do
292
+ filenames.each do |filename|
293
+ # Read the file's data
294
+ data = ''
295
+ File.open(filename, 'r') {|file| data = file.read.gsub("\r",'')}
296
+
297
+ # Add to the running MD5 sum
298
+ digest << data
299
+ end
300
+ end
301
+ digest << additional_data if additional_data
302
+ digest
303
+ end
304
+
305
+ # Opens a timestamped log file for writing. The opened file is yielded back
306
+ # to the block.
307
+ #
308
+ # @param filename [String] String to append to the exception log filename.
309
+ # The filename will start with a date/time stamp.
310
+ # @param log_dir [String] By default this method will write to the COSMOS
311
+ # default log directory. By setting this parameter you can override the
312
+ # directory the log will be written to.
313
+ # @yieldparam file [File] The log file
314
+ # @return [String|nil] The fully pathed log file name or nil if there was
315
+ # an error creating the log file.
316
+ def self.create_log_file(filename, log_dir)
317
+ log_file = nil
318
+ Cosmos.set_working_dir do
319
+ begin
320
+ # The following code goes inside a begin rescue because it reads the
321
+ # system.txt configuration file. If this has an error we won't be able
322
+ # to determine the log path but we still want to write the log.
323
+ log_dir = System.instance.paths['LOGS'] unless log_dir
324
+ log_file = File.join(log_dir,
325
+ File.build_timestamped_filename([filename]))
326
+ # Make sure the log directory exists
327
+ raise unless File.exist?(log_dir)
328
+ log_file
329
+ rescue
330
+ # If not then we just build a file locally
331
+ if File.exist?('./outputs/logs')
332
+ log_file = File.join('./outputs/logs', File.build_timestamped_filename([filename]))
333
+ elsif File.exist?('./logs')
334
+ log_file = File.join('./logs', File.build_timestamped_filename([filename]))
335
+ else
336
+ log_file = File.build_timestamped_filename([filename])
337
+ end
338
+ end
339
+ begin
340
+ # Log exception to file, open the file in append mode in case we get
341
+ # multiple exceptions in the same second. That way we don't lose
342
+ # exceptions by overwritting the last exception file.
343
+ COSMOS_MUTEX.synchronize do
344
+ begin
345
+ file = File.open(log_file, 'a')
346
+ yield file
347
+ ensure
348
+ file.close unless file.closed?
349
+ end
350
+ end
351
+ rescue Exception
352
+ # Ensure we always return
353
+ end
354
+ log_file = File.expand_path(log_file)
355
+ end
356
+ return log_file
357
+ end
358
+
359
+ # Writes a log file with information about the current configuration
360
+ # including the Ruby version, Cosmos version, whether you are on Windows, the
361
+ # COSMOS path and userpath, and the Ruby path along with the exception that
362
+ # is passed in.
363
+ #
364
+ # @param [String] filename String to append to the exception log filename.
365
+ # The filename will start with a date/time stamp.
366
+ # @param [String] log_dir By default this method will write to the COSMOS
367
+ # default log directory. By setting this parameter you can override the
368
+ # directory the log will be written to.
369
+ # @return [String|nil] The fully pathed log file name or nil if there was
370
+ # an error creating the log file.
371
+ def self.write_exception_file(exception, filename = 'exception', log_dir = nil)
372
+ log_file = create_log_file(filename, log_dir) do |file|
373
+ begin
374
+ file.puts "Exception:"
375
+ if exception
376
+ file.puts exception.formatted
377
+ file.puts
378
+ else
379
+ file.puts "No Exception Given"
380
+ file.puts caller.join("\n")
381
+ file.puts
382
+ end
383
+ file.puts "Caller Backtrace:"
384
+ file.puts caller().join("\n")
385
+ file.puts
386
+
387
+ file.puts "Ruby Version: ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
388
+ file.puts "Rubygems Version: #{Gem::VERSION}"
389
+ file.puts "Cosmos Version: #{Cosmos::VERSION}"
390
+ file.puts "Cosmos::PATH: #{Cosmos::PATH}"
391
+ file.puts "Cosmos::USERPATH: #{Cosmos::USERPATH}"
392
+ file.puts ""
393
+ file.puts "Environment:"
394
+ file.puts "RUBYOPT: #{ENV['GEM_HOME']}"
395
+ file.puts "RUBYLIB: #{ENV['GEM_HOME']}"
396
+ file.puts "GEM_PATH: #{ENV['GEM_HOME']}"
397
+ file.puts "GEMRC: #{ENV['GEM_HOME']}"
398
+ file.puts "RI_DEVKIT: #{ENV['GEM_HOME']}"
399
+ file.puts "GEM_HOME: #{ENV['GEM_HOME']}"
400
+ file.puts "PATH: #{ENV['PATH']}"
401
+ file.puts ""
402
+ file.puts "Ruby Path:\n #{$:.join("\n ")}\n\n"
403
+ file.puts "Gems:"
404
+ Gem.loaded_specs.values.map {|x| file.puts "#{x.name} #{x.version} #{x.platform}"}
405
+ file.puts ""
406
+ file.puts "All Threads Backtraces:"
407
+ Thread.list.each do |thread|
408
+ file.puts thread.backtrace.join("\n")
409
+ file.puts
410
+ end
411
+ file.puts ""
412
+ file.puts ""
413
+ ensure
414
+ file.close
415
+ end
416
+ end
417
+ return log_file
418
+ end
419
+
420
+ # Writes a log file with information about unexpected output
421
+ #
422
+ # @param[String] text The unexpected output text
423
+ # @param [String] filename String to append to the exception log filename.
424
+ # The filename will start with a date/time stamp.
425
+ # @param [String] log_dir By default this method will write to the COSMOS
426
+ # default log directory. By setting this parameter you can override the
427
+ # directory the log will be written to.
428
+ # @return [String|nil] The fully pathed log file name or nil if there was
429
+ # an error creating the log file.
430
+ def self.write_unexpected_file(text, filename = 'unexpected', log_dir = nil)
431
+ log_file = create_log_file(filename, log_dir) do |file|
432
+ begin
433
+ file.puts "Unexpected Output:\n\n"
434
+ file.puts text
435
+ ensure
436
+ file.close
437
+ end
438
+ end
439
+ return log_file
440
+ end
441
+
442
+ # Catch fatal exceptions within the block
443
+ # This is intended to catch exceptions before the GUI is available
444
+ def self.catch_fatal_exception
445
+ begin
446
+ yield
447
+ rescue Exception => error
448
+ unless error.class == SystemExit or error.class == Interrupt
449
+ Logger.level = Logger::FATAL
450
+ Cosmos.handle_fatal_exception(error, false)
451
+ end
452
+ end
453
+ end
454
+
455
+ # Write a message to the Logger, write an exception file, and popup a GUI
456
+ # window if try_gui. Finally 'exit 1' is called to end the calling program.
457
+ #
458
+ # @param error [Exception] The exception to handle
459
+ # @param try_gui [Boolean] Whether to try and create a GUI exception popup
460
+ def self.handle_fatal_exception(error, try_gui = true)
461
+ log_file = self.write_exception_file(error)
462
+ Logger.level = Logger::FATAL unless try_gui
463
+ Logger.fatal "Fatal Exception! Exiting..."
464
+ Logger.fatal error.formatted
465
+ if defined? ExceptionDialog and try_gui
466
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(nil, error, '', true, false, log_file)}
467
+ else
468
+ if $stdout != STDOUT
469
+ $stdout = STDOUT
470
+ Logger.fatal "Fatal Exception! Exiting..."
471
+ Logger.fatal error.formatted
472
+ end
473
+ sleep 1 # Allow the messages to be printed and then crash
474
+ exit 1
475
+ end
476
+ end
477
+
478
+ # CriticalErrors are errors that need to be brought to a user's attention but
479
+ # do not cause an exit. A good example is if the packet log writer fails and
480
+ # can no longer write the log file. Write a message to the Logger, write an
481
+ # exception file, and popup a GUI window if try_gui. Ensure the GUI only
482
+ # comes up once so this method can be called over and over by failing code.
483
+ #
484
+ # @param error [Exception] The exception to handle
485
+ # @param try_gui [Boolean] Whether to try and create a GUI exception popup
486
+ def self.handle_critical_exception(error, try_gui = true)
487
+ Logger.error "Critical Exception! #{error.formatted}"
488
+ if defined? ExceptionDialog and !ExceptionDialog.dialog_open?
489
+ log_file = self.write_exception_file(error)
490
+ if try_gui
491
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(nil, error, '', false, false, log_file)}
492
+ end
493
+ end
494
+ end
495
+
496
+ # Creates a Ruby Thread to run the given block. Rescues any exceptions and
497
+ # retries the threads the given number of times before handling the thread
498
+ # death by calling {Cosmos.handle_fatal_exception}.
499
+ #
500
+ # @param name [String] Name of the thread
501
+ # @param retry_attempts [Integer] The number of times to allow the thread to
502
+ # restart before exiting
503
+ def self.safe_thread(name, retry_attempts = 0)
504
+ Thread.new do
505
+ retry_count = 0
506
+ begin
507
+ yield
508
+ rescue Exception => error
509
+ Logger.error "#{name} thread unexpectedly died. Retries: #{retry_count} of #{retry_attempts}"
510
+ Logger.error error.formatted
511
+ retry_count += 1
512
+ if retry_count <= retry_attempts
513
+ self.write_exception_file(error)
514
+ retry
515
+ end
516
+ handle_fatal_exception(error)
517
+ end
518
+ end
519
+ end
520
+
521
+ # Require the class represented by the filename. This uses the standard Ruby
522
+ # convention of having a single class per file where the class name is camel
523
+ # cased and filename is lowercase with underscores.
524
+ #
525
+ # @param class_filename [String] The name of the file which contains the
526
+ # Ruby class to require
527
+ def self.require_class(class_filename)
528
+ class_name = class_filename.filename_to_class_name
529
+ return class_name.to_class if class_name.to_class and defined? class_name.to_class
530
+ begin
531
+ require class_filename
532
+ rescue LoadError => err
533
+ msg = "Unable to require #{class_filename} due to #{err.message}. Ensure #{class_filename} is in the COSMOS lib directory."
534
+ Logger.error msg
535
+ raise msg
536
+ end
537
+ klass = class_name.to_class
538
+ if klass
539
+ return klass
540
+ else
541
+ raise "Ruby class #{class_name} not found"
542
+ end
543
+ end
544
+
545
+ # @param filename [String] Name of the file to open in the editor
546
+ def self.open_in_text_editor(filename)
547
+ if filename
548
+ if Kernel.is_windows?
549
+ if File.extname(filename).to_s.downcase == '.csv'
550
+ self.run_process("cmd /c \"start wordpad \"#{filename.gsub('/','\\')}\"\"")
551
+ else
552
+ self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
553
+ end
554
+ elsif Kernel.is_mac?
555
+ self.run_process("open -a TextEdit \"#{filename}\"")
556
+ else
557
+ which_gedit = `which gedit 2>&1`.chomp
558
+ if which_gedit =~ /Command not found/i or which_gedit =~ /no .* in/i
559
+ # No gedit
560
+ editor = ENV['EDITOR']
561
+ editor = 'vi' unless editor
562
+ which_xterm = `which xterm 2>&1`.chomp
563
+ if which_xterm =~ /Command not found/i or which_xterm =~ /no .* in/i
564
+ # No xterm
565
+ which_gnome_terminal = `which gnome-terminal 2>&1`.chomp
566
+ if which_gnome_terminal =~ /Command not found/i or which_gnome_terminal =~ /no .* in/i
567
+ # No gnome-terminal - Do nothing
568
+ else
569
+ # Have gnome-terminal
570
+ system_call = "gnome-terminal -e #{editor} \"#{filename}\""
571
+ end
572
+ else
573
+ # Have xterm
574
+ system_call = "xterm -e #{editor} \"#{filename}\""
575
+ end
576
+ else
577
+ # Have gedit
578
+ system_call = "gedit \"#{filename}\""
579
+ end
580
+ self.run_process(system_call)
581
+ end
582
+ end
583
+ end
584
+
585
+ # @param filename [String] Name of the file to open in the web browser
586
+ def self.open_in_web_browser(filename)
587
+ if filename
588
+ if Kernel.is_windows?
589
+ self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
590
+ elsif Kernel.is_mac?
591
+ self.run_process("open -a Safari \"#{filename}\"")
592
+ else
593
+ which_firefox = `which firefox`.chomp
594
+ if which_firefox =~ /Command not found/i or which_firefox =~ /no .* in/i
595
+ raise "Firefox not found"
596
+ else
597
+ system_call = "#{which_firefox} \"#{filename}\""
598
+ end
599
+ self.run_process(system_call)
600
+ end
601
+ end
602
+ end
603
+
604
+ # Temporarily set the working directory during a block
605
+ def self.set_working_dir(working_dir = Cosmos::USERPATH)
606
+ current_dir = Dir.pwd
607
+ Dir.chdir(working_dir)
608
+ begin
609
+ yield
610
+ ensure
611
+ Dir.chdir(current_dir)
612
+ end
613
+ end
614
+
615
+ # Attempt to gracefully kill a thread
616
+ # @param owner Object that owns the thread and may have a graceful_kill method
617
+ # @param thread The thread to gracefully kill
618
+ # @param graceful_timeout Timeout in seconds to wait for it to die gracefully
619
+ # @param timeout_interval How often to poll for aliveness
620
+ # @param hard_timeout Timeout in seconds to wait for it to die ungracefully
621
+ def self.kill_thread(owner, thread, graceful_timeout = 1, timeout_interval = 0.01, hard_timeout = 1)
622
+ if thread
623
+ if owner and owner.respond_to? :graceful_kill
624
+ owner.graceful_kill
625
+ end_time = Time.now + graceful_timeout
626
+ while thread.alive? && ((end_time - Time.now) > 0)
627
+ sleep(timeout_interval)
628
+ end
629
+ elsif owner
630
+ Logger.info "Thread owner #{owner.class} does not support graceful_kill"
631
+ end
632
+ if thread.alive?
633
+ # Graceful failed
634
+ Logger.warn "Failed to gracefully kill thread:\n #{thread.backtrace.join("\n ")}\n"
635
+ thread.kill
636
+ end_time = Time.now + hard_timeout
637
+ while thread.alive? && ((end_time - Time.now) > 0)
638
+ sleep(timeout_interval)
639
+ end
640
+ end
641
+ if thread.alive?
642
+ Logger.error "Failed to kill thread"
643
+ end
644
+ end
645
+ end
646
+
647
+ end