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,1008 +1,1033 @@
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
- require 'cosmos'
12
- require 'cosmos/tools/cmd_tlm_server/cmd_tlm_server'
13
- require 'cosmos/gui/qt_tool'
14
- require 'cosmos/gui/dialogs/splash'
15
- require 'cosmos/gui/dialogs/cmd_tlm_raw_dialog'
16
- require 'cosmos/gui/dialogs/exception_dialog'
17
- require 'cosmos/gui/dialogs/set_tlm_dialog'
18
-
19
- module Cosmos
20
-
21
- # Implements the GUI functions of the Command and Telemetry Server. All the
22
- # QT calls are implemented here. The non-GUI functionality is contained in
23
- # the CmdTlmServer class.
24
- class CmdTlmServerGui < QtTool
25
- slots 'handle_tab_change(int)'
26
-
27
- STOPPED = 0
28
- RUNNING = 1
29
- ERROR = 2
30
-
31
- CMD = "Command"
32
- TLM = "Telemetry"
33
-
34
- # For the CTS we display all the tables as full size
35
- # Thus we don't want the table to absorb the scroll wheel events but
36
- # instead pass them up to the container so the entire window will scroll.
37
- class Qt::TableWidget
38
- def wheelEvent(event)
39
- event.ignore()
40
- end
41
- end
42
-
43
- def meta_callback(meta_target_name, meta_packet_name)
44
- Qt.execute_in_main_thread(true) do
45
- result = SetTlmDialog.execute(self, 'Enter Metadata', 'Set Metadata', 'Cancel', meta_target_name, meta_packet_name)
46
- exit(1) unless result
47
- end
48
- end
49
-
50
- def initialize(options)
51
- super(options) # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes
52
- Cosmos.load_cosmos_icon("cts.png")
53
-
54
- @production = options.production
55
- @no_prompt = options.no_prompt
56
- @message_log = nil
57
-
58
- statusBar.showMessage(tr("")) # Show blank message to initialize status bar
59
-
60
- initialize_actions()
61
- initialize_menus()
62
- initialize_central_widget()
63
- complete_initialize()
64
-
65
- Splash.execute(self) do |splash|
66
- ConfigParser.splash = splash
67
- splash.message = "Initializing #{CMD} and #{TLM} Server"
68
-
69
- # Start the thread that will process server messages and add them to the output text
70
- process_server_messages(options)
71
-
72
- CmdTlmServer.meta_callback = method(:meta_callback)
73
- CmdTlmServer.new(options.config_file, @production)
74
- @message_log = CmdTlmServer.message_log
75
-
76
- # Now that we've started the server (CmdTlmServer.new) we can populate all the tabs
77
- splash.message = "Populating Tabs"
78
- Qt.execute_in_main_thread(true) do
79
- # Override the default title if one was given in the config file
80
- self.window_title = CmdTlmServer.title if CmdTlmServer.title
81
- splash.progress = 0
82
- populate_interfaces('Interfaces')
83
- splash.progress = 100/7 * 1
84
- populate_targets()
85
- splash.progress = 100/7 * 2
86
- populate_packets(CMD)
87
- splash.progress = 100/7 * 3
88
- populate_packets(TLM)
89
- splash.progress = 100/7 * 4
90
- populate_interfaces('Routers')
91
- splash.progress = 100/7 * 5
92
- populate_logging()
93
- splash.progress = 100/7 * 6
94
- populate_status()
95
- splash.progress = 100
96
- handle_tab_change(0)
97
- end
98
- ConfigParser.splash = nil
99
- end
100
- end
101
-
102
- def initialize_actions
103
- super()
104
-
105
- # Edit actions
106
- @edit_clear_counters = Qt::Action.new(tr('&Clear Counters'), self)
107
- @edit_clear_counters.statusTip = tr('Clear counters for all interfaces and targets')
108
- @edit_clear_counters.connect(SIGNAL('triggered()')) { edit_clear_counters() }
109
- end
110
-
111
- def initialize_menus
112
- @file_menu = menuBar.addMenu(tr('&File'))
113
- @file_menu.addAction(@exit_action)
114
-
115
- # Do not allow clear counters in production mode
116
- unless @production
117
- @edit_menu = menuBar.addMenu(tr('&Edit'))
118
- @edit_menu.addAction(@edit_clear_counters)
119
- end
120
-
121
- @about_string = "#{CMD} and #{TLM} Server is the heart of the COSMOS system. "
122
- @about_string << "It connects to the target and processes command and telemetry requests from other tools."
123
-
124
- initialize_help_menu()
125
- end
126
-
127
- ###########################################
128
- # Edit Menu Options
129
- ###########################################
130
-
131
- # Edit->Clear Counters
132
- def edit_clear_counters
133
- CmdTlmServer.clear_counters
134
- end
135
-
136
- def initialize_central_widget
137
- # Create the central widget
138
- @splitter = Qt::Splitter.new(Qt::Vertical, central_widget)
139
- setCentralWidget(@splitter)
140
-
141
- @tabbook = Qt::TabWidget.new
142
- connect(@tabbook, SIGNAL('currentChanged(int)'), self, SLOT('handle_tab_change(int)'))
143
- @splitter.addWidget(@tabbook)
144
-
145
- # Add the message output
146
- @output = Qt::PlainTextEdit.new
147
- @output.setReadOnly(true)
148
- @output.setMaximumBlockCount(10000) # 10000 lines of history will be displayed
149
-
150
- @splitter.addWidget(@output)
151
- # Set the stretch factor to give priority to the tabbook (index 0) instead of the output (index 1)
152
- @splitter.setStretchFactor(0, 1) # (index, stretch)
153
-
154
- # Override stdout to the message window
155
- # All code attempting to print into the GUI must use $stdout rather than STDOUT
156
- @string_output = StringIO.new("", "r+")
157
- $stdout = @string_output
158
- Logger.level = Logger::INFO
159
-
160
- @tab_thread = nil
161
- end
162
-
163
- def kill_tab_thread
164
- if @tab_thread != nil
165
- @tab_thread.kill()
166
- @tab_thread = nil
167
- end
168
- end
169
-
170
- def handle_tab_change(index)
171
- kill_tab_thread()
172
- case index
173
- when 0
174
- handle_interfaces_tab('Interfaces')
175
- when 1
176
- handle_targets_tab()
177
- when 2
178
- handle_packets_tab(CMD)
179
- when 3
180
- handle_packets_tab(TLM)
181
- when 4
182
- handle_interfaces_tab('Routers')
183
- when 5
184
- handle_logging_tab()
185
- when 6
186
- handle_status_tab()
187
- end
188
- end
189
-
190
- def populate_interfaces(name)
191
- @interfaces_table ||= {}
192
-
193
- if name == 'Routers'
194
- interfaces = CmdTlmServer.routers
195
- else
196
- interfaces = CmdTlmServer.interfaces
197
- end
198
-
199
- num_interfaces = interfaces.names.length
200
- if interfaces.names.length > 0
201
- scroll = Qt::ScrollArea.new
202
- scroll.setMinimumSize(800, 150)
203
- widget = Qt::Widget.new
204
- layout = Qt::VBoxLayout.new(widget)
205
- # Since the layout will be inside a scroll area make sure it respects the sizes we set
206
- layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
207
-
208
- interfaces_table = Qt::TableWidget.new()
209
- interfaces_table.verticalHeader.hide()
210
- interfaces_table.setRowCount(num_interfaces)
211
- interfaces_table.setColumnCount(10)
212
- if name == 'Routers'
213
- interfaces_table.setHorizontalHeaderLabels(["Router", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
214
- else
215
- interfaces_table.setHorizontalHeaderLabels(["Interface", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
216
- end
217
-
218
- row = 0
219
- interfaces.all.each do |interface_name, interface|
220
- item = Qt::TableWidgetItem.new(tr(interface_name))
221
- item.setTextAlignment(Qt::AlignCenter)
222
- interfaces_table.setItem(row, 0, item)
223
-
224
- if interface.connected?
225
- button_text = 'Disconnect'
226
- elsif interface.thread.nil?
227
- button_text = 'Connect'
228
- else
229
- button_text = 'Cancel Connect'
230
- end
231
- button = Qt::PushButton.new(button_text)
232
- if name == 'Routers'
233
- button.connect(SIGNAL('clicked()')) do
234
- if interface.thread
235
- CmdTlmServer.instance.disconnect_router(interface_name)
236
- else
237
- CmdTlmServer.instance.connect_router(interface_name)
238
- end
239
- end
240
- else
241
- button.connect(SIGNAL('clicked()')) do
242
- if interface.thread
243
- CmdTlmServer.instance.disconnect_interface(interface_name)
244
- else
245
- CmdTlmServer.instance.connect_interface(interface_name)
246
- end
247
- end
248
- end
249
- button.setDisabled(true) if interface.disable_disconnect
250
- interfaces_table.setCellWidget(row, 1, button)
251
-
252
- state = Qt::TableWidgetItem.new
253
- if interface.connected?
254
- state.setText('true')
255
- state.textColor = Cosmos::GREEN
256
- elsif interface.thread
257
- state.setText('attempting')
258
- state.textColor = Cosmos::YELLOW
259
- else
260
- state.setText('false')
261
- state.textColor = Cosmos::BLACK
262
- end
263
- state.setTextAlignment(Qt::AlignCenter)
264
- interfaces_table.setItem(row, 2, state)
265
-
266
- num_clients = Qt::TableWidgetItem.new(tr(interface.num_clients.to_s))
267
- num_clients.setTextAlignment(Qt::AlignCenter)
268
- interfaces_table.setItem(row, 3, num_clients)
269
-
270
- write_queue_size = Qt::TableWidgetItem.new(tr(interface.write_queue_size.to_s))
271
- write_queue_size.setTextAlignment(Qt::AlignCenter)
272
- interfaces_table.setItem(row, 4, write_queue_size)
273
-
274
- read_queue_size = Qt::TableWidgetItem.new(tr(interface.read_queue_size.to_s))
275
- read_queue_size.setTextAlignment(Qt::AlignCenter)
276
- interfaces_table.setItem(row, 5, read_queue_size)
277
-
278
- bytes_written = Qt::TableWidgetItem.new(tr(interface.bytes_written.to_s))
279
- bytes_written.setTextAlignment(Qt::AlignCenter)
280
- interfaces_table.setItem(row, 6, bytes_written)
281
-
282
- bytes_read = Qt::TableWidgetItem.new(tr(interface.bytes_read.to_s))
283
- bytes_read.setTextAlignment(Qt::AlignCenter)
284
- interfaces_table.setItem(row, 7, bytes_read)
285
-
286
- write_count = Qt::TableWidgetItem.new(tr(interface.write_count.to_s))
287
- write_count.setTextAlignment(Qt::AlignCenter)
288
- interfaces_table.setItem(row, 8, write_count)
289
-
290
- read_count = Qt::TableWidgetItem.new(tr(interface.read_count.to_s))
291
- read_count.setTextAlignment(Qt::AlignCenter)
292
- interfaces_table.setItem(row, 9, read_count)
293
-
294
- row += 1
295
- end
296
- interfaces_table.displayFullSize
297
-
298
- layout.addWidget(interfaces_table)
299
- scroll.setWidget(widget)
300
- if name == 'Routers'
301
- @tabbook.addTab(scroll, "Routers")
302
- @interfaces_table['Routers'] = interfaces_table
303
- else
304
- @tabbook.addTab(scroll, "Interfaces")
305
- @interfaces_table['Interfaces'] = interfaces_table
306
- end
307
- end
308
- end
309
-
310
- def handle_interfaces_tab(name)
311
- @tab_thread = Thread.new do
312
- if @interfaces_table[name]
313
- begin
314
- while true
315
- Qt.execute_in_main_thread(true) do
316
- row = 0
317
- if name == 'Routers'
318
- interfaces = CmdTlmServer.routers
319
- else
320
- interfaces = CmdTlmServer.interfaces
321
- end
322
- interfaces.all.each do |interface_name, interface|
323
- button = @interfaces_table[name].cellWidget(row,1)
324
- state = @interfaces_table[name].item(row,2)
325
- if interface.connected?
326
- button.setText('Disconnect')
327
- button.setDisabled(true) if interface.disable_disconnect
328
- state.setText('true')
329
- state.textColor = Cosmos::GREEN
330
- elsif interface.thread
331
- button.text = 'Cancel Connect'
332
- button.setDisabled(false)
333
- state.text = 'attempting'
334
- state.textColor = Cosmos::RED
335
- else
336
- button.setText('Connect')
337
- button.setDisabled(false)
338
- state.setText('false')
339
- state.textColor = Cosmos::BLACK
340
- end
341
- @interfaces_table[name].item(row,3).setText(interface.num_clients.to_s)
342
- @interfaces_table[name].item(row,4).setText(interface.write_queue_size.to_s)
343
- @interfaces_table[name].item(row,5).setText(interface.read_queue_size.to_s)
344
- @interfaces_table[name].item(row,6).setText(interface.bytes_written.to_s)
345
- @interfaces_table[name].item(row,7).setText(interface.bytes_read.to_s)
346
- if name == 'Routers'
347
- @interfaces_table[name].item(row,8).setText(interface.read_count.to_s)
348
- @interfaces_table[name].item(row,9).setText(interface.write_count.to_s)
349
- else
350
- @interfaces_table[name].item(row,8).setText(interface.write_count.to_s)
351
- @interfaces_table[name].item(row,9).setText(interface.read_count.to_s)
352
- end
353
- row += 1
354
- end
355
- end
356
- sleep(1)
357
- end
358
- rescue Exception => error
359
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : #{name} Tab Thread")}
360
- end
361
- end
362
- end
363
- end
364
-
365
- def populate_targets
366
- num_targets = System.targets.length
367
- if num_targets > 0
368
- return if num_targets == 1 and System.targets['SYSTEM']
369
- num_targets -= 1 if System.targets['SYSTEM']
370
-
371
- scroll = Qt::ScrollArea.new
372
- widget = Qt::Widget.new
373
- layout = Qt::VBoxLayout.new(widget)
374
- # Since the layout will be inside a scroll area make sure it respects the sizes we set
375
- layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
376
-
377
- @targets_table = Qt::TableWidget.new()
378
- @targets_table.verticalHeader.hide()
379
- @targets_table.setRowCount(num_targets)
380
- @targets_table.setColumnCount(4)
381
- @targets_table.setHorizontalHeaderLabels(["Target Name", "Interface", "#{CMD} Count", "#{TLM} Count"])
382
-
383
- row = 0
384
- System.targets.sort.each do |target_name, target|
385
- next if target_name == 'SYSTEM'
386
- target_name_widget = Qt::TableWidgetItem.new(tr(target_name))
387
- target_name_widget.setTextAlignment(Qt::AlignCenter)
388
- @targets_table.setItem(row, 0, target_name_widget)
389
- if target.interface
390
- interface_name_widget = Qt::TableWidgetItem.new(tr(target.interface.name.to_s))
391
- else
392
- interface_name_widget = Qt::TableWidgetItem.new(tr(''))
393
- end
394
- interface_name_widget.setTextAlignment(Qt::AlignCenter)
395
- @targets_table.setItem(row, 1, interface_name_widget)
396
- cmd_cnt = Qt::TableWidgetItem.new(tr(target.cmd_cnt.to_s))
397
- cmd_cnt.setTextAlignment(Qt::AlignCenter)
398
- @targets_table.setItem(row, 2, cmd_cnt)
399
-
400
- tlm_cnt = Qt::TableWidgetItem.new(tr(target.tlm_cnt.to_s))
401
- tlm_cnt.setTextAlignment(Qt::AlignCenter)
402
- @targets_table.setItem(row, 3, tlm_cnt)
403
-
404
- row += 1
405
- end
406
- @targets_table.displayFullSize
407
-
408
- layout.addWidget(@targets_table)
409
- scroll.setWidget(widget)
410
- @tabbook.addTab(scroll, "Targets")
411
- end
412
- end
413
-
414
- def handle_targets_tab
415
- @tab_thread = Thread.new do
416
- begin
417
- while true
418
- Qt.execute_in_main_thread(true) do
419
- row = 0
420
- System.targets.sort.each do |target_name, target|
421
- next if target_name == 'SYSTEM'
422
- @targets_table.item(row,2).setText(target.cmd_cnt.to_s)
423
- @targets_table.item(row,3).setText(target.tlm_cnt.to_s)
424
- row += 1
425
- end
426
- end
427
- sleep(1)
428
- end
429
- rescue Exception => error
430
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Targets Tab Thread")}
431
- end
432
- end
433
- end
434
-
435
- def get_cmd_tlm_def(name)
436
- case name
437
- when CMD
438
- return System.commands
439
- when TLM
440
- return System.telemetry
441
- end
442
- end
443
-
444
- def populate_packets(name)
445
- cmd_tlm = get_cmd_tlm_def(name)
446
-
447
- unless cmd_tlm.target_names.empty?
448
- count = 0
449
- cmd_tlm.target_names.sort.each do |target_name|
450
- packets = cmd_tlm.packets(target_name)
451
- packets.each do |packet_name, packet|
452
- count += 1 unless packet.hidden
453
- end
454
- end
455
-
456
- scroll = Qt::ScrollArea.new
457
- widget = Qt::Widget.new
458
- layout = Qt::VBoxLayout.new(widget)
459
- # Since the layout will be inside a scroll area
460
- # make sure it respects the sizes we set
461
- layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
462
-
463
- table = Qt::TableWidget.new()
464
- table.verticalHeader.hide()
465
- table.setRowCount(count)
466
- column_cnt = 4
467
- column_cnt += 1 if name == TLM
468
- table.setColumnCount(column_cnt)
469
- # Force the last section to fill all available space in the frame
470
- #~ table.horizontalHeader.setStretchLastSection(true)
471
- headers = ["Target Name", "Packet Name", "Packet Count", "View Raw"]
472
- headers << "View in Packet Viewer" if name == TLM
473
- table.setHorizontalHeaderLabels(headers)
474
-
475
- row = 0
476
- cmd_tlm.target_names.sort.each do |target_name|
477
- packets = cmd_tlm.packets(target_name)
478
- packets.sort.each do |packet_name, packet|
479
- packet.received_count ||= 0
480
- next if packet.hidden
481
- target_name_widget = Qt::TableWidgetItem.new(tr(target_name))
482
- target_name_widget.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
483
- table.setItem(row, 0, target_name_widget)
484
- table.setItem(row, 1, Qt::TableWidgetItem.new(tr(packet_name)))
485
- packet_count = Qt::TableWidgetItem.new(tr(packet.received_count.to_s))
486
- packet_count.setTextAlignment(Qt::AlignCenter)
487
- table.setItem(row, 2, packet_count)
488
- view_raw = Qt::PushButton.new("View Raw")
489
- view_raw.connect(SIGNAL('clicked()')) do
490
- @raw_dialogs ||= []
491
- @raw_dialogs << CmdRawDialog.new(self, target_name, packet_name) if name == CMD
492
- @raw_dialogs << TlmRawDialog.new(self, target_name, packet_name) if name == TLM
493
- end
494
- table.setCellWidget(row, 3, view_raw)
495
-
496
- if name == TLM
497
- if target_name != 'UNKNOWN' and packet_name != 'UNKNOWN'
498
- view_pv = Qt::PushButton.new("View in Packet Viewer")
499
- view_pv.connect(SIGNAL('clicked()')) do
500
- if Kernel.is_windows?
501
- Cosmos.run_process("rubyw tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
502
- elsif Kernel.is_mac? and File.exist?("tools/mac/PacketViewer.app")
503
- Cosmos.run_process("open tools/mac/PacketViewer.app --args -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
504
- else
505
- Cosmos.run_process("ruby tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
506
- end
507
- end
508
- table.setCellWidget(row, 4, view_pv)
509
- else
510
- table_widget = Qt::TableWidgetItem.new(tr('N/A'))
511
- table_widget.setTextAlignment(Qt::AlignCenter)
512
- table.setItem(row, 4, table_widget)
513
- end
514
- end
515
-
516
- row += 1
517
- end
518
- end
519
- table.displayFullSize
520
-
521
- layout.addWidget(table)
522
- scroll.setWidget(widget)
523
- tab_name = "Cmd Packets" if name == CMD
524
- tab_name = "Tlm Packets" if name == TLM
525
- @tabbook.addTab(scroll, tab_name)
526
-
527
- @packets_table ||= {}
528
- @packets_table[name] = table
529
- end
530
- end
531
-
532
- def handle_packets_tab(name)
533
- cmd_tlm = get_cmd_tlm_def(name)
534
-
535
- @tab_thread = Thread.new do
536
- begin
537
- unless cmd_tlm.target_names.empty?
538
- while true
539
- Qt.execute_in_main_thread(true) do
540
- row = 0
541
- cmd_tlm.target_names.sort.each do |target_name|
542
- packets = cmd_tlm.packets(target_name)
543
- packets.sort.each do |packet_name, packet|
544
- next if packet.hidden
545
- @packets_table[name].item(row, 2).setText(packet.received_count.to_s)
546
- row += 1
547
- end
548
- end
549
- end
550
- sleep(1)
551
- end
552
- end
553
- rescue Exception => error
554
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : #{name} Packets Tab Thread")}
555
- end
556
- end
557
- end
558
-
559
- def populate_logging_actions(layout)
560
- # Add all the action buttons
561
- actions = Qt::GroupBox.new(tr("Actions"))
562
- actions_layout = Qt::VBoxLayout.new(actions)
563
- button_layout = Qt::GridLayout.new
564
-
565
- log_buttons = [
566
- ["Start Logging on All", [0,0], :start_logging],
567
- ["Stop Logging on All", [0,1], :stop_logging],
568
- ["Start #{TLM} Logging on All", [1,0], :start_tlm_log],
569
- ["Stop #{TLM} Logging on All", [1,1], :stop_tlm_log],
570
- ["Start #{CMD} Logging on All", [2,0], :start_cmd_log],
571
- ["Stop #{CMD} Logging on All", [2,1], :stop_cmd_log]
572
- ]
573
-
574
- log_buttons.each do |text, location, method|
575
- next if text =~ /Stop/ and @production
576
- button = Qt::PushButton.new(tr(text))
577
- button_layout.addWidget(button, location[0], location[1])
578
- button.connect(SIGNAL('clicked()')) do
579
- begin
580
- CmdTlmServer.instance.send(method, 'ALL')
581
- rescue Exception => error
582
- statusBar.showMessage(tr(error.message))
583
- end
584
- end
585
- end
586
-
587
- actions_layout.addLayout(button_layout)
588
-
589
- layout.addWidget(actions)
590
- end
591
-
592
- def populate_log_file_info(layout)
593
- CmdTlmServer.packet_logging.all.sort.each do |packet_log_writer_pair_name, packet_log_writer_pair|
594
- log = Qt::GroupBox.new("#{packet_log_writer_pair_name} Packet Log Writer")
595
- log_layout = Qt::VBoxLayout.new(log)
596
- interfaces = []
597
- CmdTlmServer.interfaces.all.each do |interface_name, interface|
598
- if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
599
- interfaces << interface.name
600
- end
601
- end
602
-
603
- form_layout = Qt::FormLayout.new
604
- @logging_layouts[packet_log_writer_pair_name] = form_layout
605
- form_layout.addRow("Interfaces:", Qt::Label.new(tr(interfaces.join(", "))))
606
-
607
- form_layout.addRow("Cmd Logging:", Qt::Label.new(tr(packet_log_writer_pair.cmd_log_writer.logging_enabled.to_s)))
608
- form_layout.addRow("Cmd Queue Size:", Qt::Label.new(tr(packet_log_writer_pair.cmd_log_writer.queue.size.to_s)))
609
- form_layout.addRow("Cmd Filename:", Qt::Label.new(tr(packet_log_writer_pair.cmd_log_writer.filename)))
610
- file_size = 0
611
- begin
612
- file_size = File.size(packet_log_writer_pair.cmd_log_writer.filename) if packet_log_writer_pair.cmd_log_writer.filename
613
- rescue Exception
614
- # Do nothing on error
615
- end
616
- form_layout.addRow("Cmd File Size:", Qt::Label.new(tr(file_size.to_s)))
617
-
618
- form_layout.addRow("Tlm Logging:", Qt::Label.new(tr(packet_log_writer_pair.tlm_log_writer.logging_enabled.to_s)))
619
- form_layout.addRow("Tlm Queue Size:", Qt::Label.new(tr(packet_log_writer_pair.tlm_log_writer.queue.size.to_s)))
620
- form_layout.addRow("Tlm Filename:", Qt::Label.new(tr(packet_log_writer_pair.tlm_log_writer.filename)))
621
- file_size = 0
622
- begin
623
- file_size = File.size(packet_log_writer_pair.tlm_log_writer.filename) if packet_log_writer_pair.tlm_log_writer.filename
624
- rescue Exception
625
- # Do nothing on error
626
- end
627
- form_layout.addRow("Tlm File Size:", Qt::Label.new(tr(file_size.to_s)))
628
-
629
- button_layout = Qt::HBoxLayout.new
630
- start_button = Qt::PushButton.new(tr('Start Cmd Logging'))
631
- button_layout.addWidget(start_button)
632
- start_button.connect(SIGNAL('clicked()')) do
633
- CmdTlmServer.instance.start_cmd_log(packet_log_writer_pair_name)
634
- end
635
- start_button = Qt::PushButton.new(tr('Start Tlm Logging'))
636
- button_layout.addWidget(start_button)
637
- start_button.connect(SIGNAL('clicked()')) do
638
- CmdTlmServer.instance.start_tlm_log(packet_log_writer_pair_name)
639
- end
640
- if @production == false
641
- stop_button = Qt::PushButton.new(tr('Stop Cmd Logging'))
642
- button_layout.addWidget(stop_button)
643
- stop_button.connect(SIGNAL('clicked()')) do
644
- CmdTlmServer.instance.stop_cmd_log(packet_log_writer_pair_name)
645
- end
646
- stop_button = Qt::PushButton.new(tr('Stop Tlm Logging'))
647
- button_layout.addWidget(stop_button)
648
- stop_button.connect(SIGNAL('clicked()')) do
649
- CmdTlmServer.instance.stop_tlm_log(packet_log_writer_pair_name)
650
- end
651
- end
652
- form_layout.addRow("Actions:", button_layout)
653
- log_layout.addLayout(form_layout)
654
- layout.addWidget(log)
655
- end
656
- layout.addWidget(Qt::Label.new(tr("Note: Buffered IO operations cause file size to not reflect total logged data size until the log file is closed.")))
657
- end
658
-
659
- def populate_logging
660
- scroll = Qt::ScrollArea.new
661
- widget = Qt::Widget.new
662
- layout = Qt::VBoxLayout.new(widget)
663
- # Since the layout will be inside a scroll area
664
- # make sure it respects the sizes we set
665
- layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
666
-
667
- populate_logging_actions(layout)
668
-
669
- # Create the hash which will hold the logging layouts
670
- @logging_layouts = {}
671
-
672
- # Add the cmd/tlm log files information
673
- populate_log_file_info(layout)
674
-
675
- # Set the scroll area widget last now that all the items have been layed out
676
- scroll.setWidget(widget)
677
- @tabbook.addTab(scroll, "Logging")
678
- end
679
-
680
- def update_filename_and_logging_state
681
- CmdTlmServer.packet_logging.all.each do |packet_log_writer_pair_name, packet_log_writer_pair|
682
- @logging_layouts[packet_log_writer_pair_name].itemAt(1, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.logging_enabled.to_s)
683
- @logging_layouts[packet_log_writer_pair_name].itemAt(2, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.queue.size.to_s)
684
- @logging_layouts[packet_log_writer_pair_name].itemAt(3, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.filename)
685
- file_size = 0
686
- begin
687
- file_size = File.size(packet_log_writer_pair.cmd_log_writer.filename) if packet_log_writer_pair.cmd_log_writer.filename
688
- rescue Exception
689
- # Do nothing on error
690
- end
691
- @logging_layouts[packet_log_writer_pair_name].itemAt(4, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
692
- @logging_layouts[packet_log_writer_pair_name].itemAt(5, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.logging_enabled.to_s)
693
- @logging_layouts[packet_log_writer_pair_name].itemAt(6, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.queue.size.to_s)
694
- @logging_layouts[packet_log_writer_pair_name].itemAt(7, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.filename)
695
- file_size = 0
696
- begin
697
- file_size = File.size(packet_log_writer_pair.tlm_log_writer.filename) if packet_log_writer_pair.tlm_log_writer.filename
698
- rescue Exception
699
- # Do nothing on error
700
- end
701
- @logging_layouts[packet_log_writer_pair_name].itemAt(8, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
702
- end
703
- end
704
-
705
- def handle_logging_tab
706
- @tab_thread = Thread.new do
707
- begin
708
- while true
709
- Qt.execute_in_main_thread(true) do
710
- update_filename_and_logging_state()
711
- end
712
- sleep(1)
713
- end
714
- rescue Exception => error
715
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Logging Tab Thread")}
716
- end
717
- end
718
- end
719
-
720
- def populate_status
721
- scroll = Qt::ScrollArea.new
722
- widget = Qt::Widget.new
723
- layout = Qt::VBoxLayout.new(widget)
724
-
725
- limits = Qt::GroupBox.new(tr("Limits Status"))
726
- limits_layout = Qt::FormLayout.new(limits)
727
- current_limits_set = System.limits_set.to_s
728
-
729
- known_limits_sets = System.limits.sets
730
- known_limits_sets = known_limits_sets.map {|x| x.to_s}.sort
731
- current_index = known_limits_sets.index(current_limits_set.to_s)
732
-
733
- @limits_set_combo = Qt::ComboBox.new
734
- limits_layout.addRow("Limits Set:", @limits_set_combo)
735
- layout.addWidget(limits)
736
-
737
- known_limits_sets.sort.each do |limits_set|
738
- @limits_set_combo.addItem(limits_set.to_s)
739
- end
740
- @limits_set_combo.setMaxVisibleItems(6)
741
- @limits_set_combo.setCurrentIndex(current_index)
742
- # Only connect to the signal that is sent when the user chooses an item.
743
- # If the limits set is changed programatically the code in
744
- # handle_status_tab will pick up the change.
745
- @limits_set_combo.connect(SIGNAL('activated(int)')) do
746
- selected_limits_set = @limits_set_combo.currentText
747
- if selected_limits_set
748
- System.limits_set = selected_limits_set.intern if System.limits_set != selected_limits_set.intern
749
- end
750
- end
751
-
752
- api = Qt::GroupBox.new(tr("API Status"))
753
- api_layout = Qt::VBoxLayout.new(api)
754
- @api_table = Qt::TableWidget.new()
755
- @api_table.verticalHeader.hide()
756
- @api_table.setRowCount(1)
757
- @api_table.setColumnCount(6)
758
- @api_table.setHorizontalHeaderLabels(["Port", "Num Clients", "Requests", "Requests/Sec", "Avg Request Time", "Estimated Utilization"])
759
-
760
- @api_table.setItem(0, 0, Qt::TableWidgetItem.new(tr(System.ports['CTS_API'].to_s)))
761
- item0 = Qt::TableWidgetItem.new(tr(CmdTlmServer.json_drb.num_clients.to_s))
762
- item0.setTextAlignment(Qt::AlignCenter)
763
- @api_table.setItem(0, 1, item0)
764
- item = Qt::TableWidgetItem.new(tr(CmdTlmServer.json_drb.request_count.to_s))
765
- item.setTextAlignment(Qt::AlignCenter)
766
- @api_table.setItem(0, 2, item)
767
- item2 = Qt::TableWidgetItem.new("0.0")
768
- item2.setTextAlignment(Qt::AlignCenter)
769
- @api_table.setItem(0, 3, item2)
770
- item3 = Qt::TableWidgetItem.new("0.0")
771
- item3.setTextAlignment(Qt::AlignCenter)
772
- @api_table.setItem(0, 4, item3)
773
- item4 = Qt::TableWidgetItem.new("0.0")
774
- item4.setTextAlignment(Qt::AlignCenter)
775
- @api_table.setItem(0, 5, item4)
776
- @api_table.displayFullSize
777
- api_layout.addWidget(@api_table)
778
- layout.addWidget(api)
779
-
780
- system = Qt::GroupBox.new(tr("System Status"))
781
- system_layout = Qt::VBoxLayout.new(system)
782
- @system_table = Qt::TableWidget.new()
783
- @system_table.verticalHeader.hide()
784
- @system_table.setRowCount(1)
785
- @system_table.setColumnCount(4)
786
- @system_table.setHorizontalHeaderLabels(["Threads", "Total Objs", "Free Objs", "Allocated Objs"])
787
-
788
- item0 = Qt::TableWidgetItem.new("0")
789
- item0.setTextAlignment(Qt::AlignCenter)
790
- @system_table.setItem(0, 0, item0)
791
- item1 = Qt::TableWidgetItem.new("0.0")
792
- item1.setTextAlignment(Qt::AlignCenter)
793
- @system_table.setItem(0, 1, item1)
794
- item2 = Qt::TableWidgetItem.new("0.0")
795
- item2.setTextAlignment(Qt::AlignCenter)
796
- @system_table.setItem(0, 2, item2)
797
- item3 = Qt::TableWidgetItem.new("0.0")
798
- item3.setTextAlignment(Qt::AlignCenter)
799
- @system_table.setItem(0, 3, item3)
800
- @system_table.displayFullSize
801
- system_layout.addWidget(@system_table)
802
- layout.addWidget(system)
803
-
804
- background_tasks_groupbox = Qt::GroupBox.new(tr("Background Tasks"))
805
- background_tasks_layout = Qt::VBoxLayout.new(background_tasks_groupbox)
806
- @background_tasks_table = Qt::TableWidget.new()
807
- @background_tasks_table.verticalHeader.hide()
808
- @background_tasks_table.setRowCount(CmdTlmServer.background_tasks.all.length)
809
- @background_tasks_table.setColumnCount(3)
810
- @background_tasks_table.setHorizontalHeaderLabels(["Name", "State", "Status"])
811
-
812
- background_tasks = CmdTlmServer.background_tasks.all
813
- if background_tasks.length > 0
814
- row = 0
815
- background_tasks.each_with_index do |background_task, index|
816
- background_task_name = background_task.name
817
- background_task_name = "Background Task ##{index + 1}" unless background_task_name
818
- background_task_name_widget = Qt::TableWidgetItem.new(background_task_name)
819
- background_task_name_widget.setTextAlignment(Qt::AlignCenter)
820
- @background_tasks_table.setItem(row, 0, background_task_name_widget)
821
- if background_task.thread
822
- status = background_task.thread.status
823
- status = 'complete' if status == false
824
- background_task_state_widget = Qt::TableWidgetItem.new(status.to_s)
825
- else
826
- background_task_state_widget = Qt::TableWidgetItem.new('no thread')
827
- end
828
- background_task_state_widget.setTextAlignment(Qt::AlignCenter)
829
- background_task_state_widget.setSizeHint(Qt::Size.new(80, 30))
830
- @background_tasks_table.setItem(row, 1, background_task_state_widget)
831
- background_task_status_widget = Qt::TableWidgetItem.new(background_task.status.to_s)
832
- background_task_status_widget.setTextAlignment(Qt::AlignCenter)
833
- background_task_status_widget.setSizeHint(Qt::Size.new(500, 30))
834
- @background_tasks_table.setItem(row, 2, background_task_status_widget)
835
-
836
- row += 1
837
- end
838
- end
839
- @background_tasks_table.displayFullSize
840
- background_tasks_layout.addWidget(@background_tasks_table)
841
- layout.addWidget(background_tasks_groupbox)
842
-
843
- # Set the scroll area widget last now that all the items have been layed out
844
- scroll.setWidget(widget)
845
- @tabbook.addTab(scroll, "Status")
846
- end
847
-
848
- def handle_status_tab
849
- @tab_thread = Thread.new do
850
- begin
851
- if CmdTlmServer.json_drb
852
- previous_request_count = CmdTlmServer.json_drb.request_count
853
- else
854
- previous_request_count = 0
855
- end
856
- while true
857
- start_time = Time.now
858
- Qt.execute_in_main_thread(true) do
859
- # Update limits set
860
- current_limits_set = System.limits_set.to_s
861
- if @limits_set_combo.currentText != current_limits_set
862
- known_limits_sets = System.limits.sets
863
- known_limits_sets = known_limits_sets.map {|x| x.to_s}.sort
864
- current_index = known_limits_sets.index(current_limits_set.to_s)
865
- @limits_set_combo.clear
866
- known_limits_sets.sort.each do |limits_set|
867
- @limits_set_combo.addItem(limits_set.to_s)
868
- end
869
- @limits_set_combo.setCurrentIndex(current_index)
870
- end
871
-
872
- # Update API status
873
- if CmdTlmServer.json_drb
874
- @api_table.item(0,1).setText(CmdTlmServer.json_drb.num_clients.to_s)
875
- @api_table.item(0,2).setText(CmdTlmServer.json_drb.request_count.to_s)
876
- request_count = CmdTlmServer.json_drb.request_count
877
- requests_per_second = request_count - previous_request_count
878
- @api_table.item(0,3).setText(requests_per_second.to_s)
879
- previous_request_count = request_count
880
- average_request_time = CmdTlmServer.json_drb.average_request_time
881
- @api_table.item(0,4).setText(sprintf("%0.6f s", average_request_time))
882
- estimated_utilization = requests_per_second * average_request_time * 100.0
883
- @api_table.item(0,5).setText(sprintf("%0.2f %", estimated_utilization))
884
- end
885
-
886
- # Update system status
887
- @system_table.item(0,0).setText(Thread.list.length.to_s)
888
- objs = ObjectSpace.count_objects
889
- @system_table.item(0,1).setText(objs[:TOTAL].to_s)
890
- @system_table.item(0,2).setText(objs[:FREE].to_s)
891
- total = 0
892
- objs.each do |key, val|
893
- next if key == :TOTAL || key == :FREE
894
- total += val
895
- end
896
- @system_table.item(0,3).setText(total.to_s)
897
-
898
- # Update background task status
899
- background_tasks = CmdTlmServer.background_tasks.all
900
- if background_tasks.length > 0
901
- row = 0
902
- background_tasks.each_with_index do |background_task, index|
903
- if background_task.thread
904
- status = background_task.thread.status
905
- status = 'complete' if status == false
906
- @background_tasks_table.item(row, 1).setText(status.to_s)
907
- else
908
- @background_tasks_table.item(row, 1).setText('no thread')
909
- end
910
- @background_tasks_table.item(row, 2).setText(background_task.status.to_s)
911
- row += 1
912
- end
913
- end
914
- end
915
- total_time = Time.now - start_time
916
- sleep(1.0 - total_time) if total_time > 0.0 and total_time < 1.0
917
- end
918
- rescue Exception => error
919
- Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Settings Tab Thread")}
920
- end
921
- end
922
- end
923
-
924
- def closeEvent(event)
925
- # Create are you sure dialog
926
- if @no_prompt
927
- continue = true
928
- else
929
- msg = Qt::MessageBox.new(self)
930
- msg.setIcon(Qt::MessageBox::Question)
931
- msg.setText("Are you sure? All tools connected to this CmdTlmServer will lose connections and cease to function if the CmdTlmServer is closed.")
932
- msg.setWindowTitle('Confirm Close')
933
- msg.setStandardButtons(Qt::MessageBox::Yes | Qt::MessageBox::No)
934
- continue = false
935
- continue = true if msg.exec() == Qt::MessageBox::Yes
936
- msg.dispose
937
- end
938
-
939
- if continue
940
- kill_tab_thread()
941
- @output_thread.kill()
942
- @message_log.stop
943
- CmdTlmServer.instance.stop_logging('ALL')
944
- CmdTlmServer.instance.stop
945
- super(event)
946
- else
947
- event.ignore()
948
- end
949
- end
950
-
951
- def self.run(option_parser = nil, options = nil)
952
- Cosmos.catch_fatal_exception do
953
- unless option_parser and options
954
- option_parser, options = create_default_options()
955
- options.width = 800
956
- options.height = 500
957
- # Set the default title which can be overridden in the config file
958
- options.title = "#{CMD} and #{TLM} Server"
959
- options.auto_size = false
960
- options.config_file = CmdTlmServer::DEFAULT_CONFIG_FILE
961
- options.production = false
962
- options.no_prompt = false
963
- option_parser.separator "CTS Specific Options:"
964
- option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
965
- options.config_file = arg
966
- end
967
- option_parser.on("-p", "--production", "Run the server in production mode which disables the ability to stop logging.") do |arg|
968
- options.production = true
969
- end
970
- option_parser.on("-n", "--no-prompt", "Don't prompt with Are You Sure dialog on close.") do |arg|
971
- options.no_prompt = true
972
- end
973
- end
974
-
975
- super(option_parser, options)
976
- end
977
- end
978
-
979
- def process_server_messages(options)
980
- # Start thread to read server messages
981
- @output_thread = Thread.new do
982
- begin
983
- while !@message_log
984
- sleep(1)
985
- end
986
- while true
987
- if @string_output.string[-1..-1] == "\n"
988
- Qt.execute_in_main_thread(true) do
989
- lines_to_write = ''
990
- string = @string_output.string.clone
991
- @string_output.string = @string_output.string[string.length..-1]
992
- string.each_line {|out_line| @output.add_formatted_text(out_line); lines_to_write += out_line }
993
- @output.flush
994
- @message_log.write(lines_to_write)
995
- end
996
- end
997
- sleep(1)
998
- end
999
- rescue Exception => error
1000
- Qt.execute_in_main_thread(true) do
1001
- ExceptionDialog.new(self, error, "#{options.title}: Messages Thread")
1002
- end
1003
- end
1004
- end
1005
- end
1006
- end # class CmdTlmServerGui
1007
-
1008
- end # module Cosmos
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
+ require 'cosmos'
12
+ require 'cosmos/tools/cmd_tlm_server/cmd_tlm_server'
13
+ require 'cosmos/gui/qt_tool'
14
+ require 'cosmos/gui/dialogs/splash'
15
+ require 'cosmos/gui/dialogs/cmd_tlm_raw_dialog'
16
+ require 'cosmos/gui/dialogs/exception_dialog'
17
+ require 'cosmos/gui/dialogs/set_tlm_dialog'
18
+
19
+ module Cosmos
20
+
21
+ # Implements the GUI functions of the Command and Telemetry Server. All the
22
+ # QT calls are implemented here. The non-GUI functionality is contained in
23
+ # the CmdTlmServer class.
24
+ class CmdTlmServerGui < QtTool
25
+ slots 'handle_tab_change(int)'
26
+
27
+ STOPPED = 0
28
+ RUNNING = 1
29
+ ERROR = 2
30
+
31
+ CMD = "Command"
32
+ TLM = "Telemetry"
33
+
34
+ # For the CTS we display all the tables as full size
35
+ # Thus we don't want the table to absorb the scroll wheel events but
36
+ # instead pass them up to the container so the entire window will scroll.
37
+ class Qt::TableWidget
38
+ def wheelEvent(event)
39
+ event.ignore()
40
+ end
41
+ end
42
+
43
+ def meta_callback(meta_target_name, meta_packet_name)
44
+ Qt.execute_in_main_thread(true) do
45
+ result = SetTlmDialog.execute(self, 'Enter Metadata', 'Set Metadata', 'Cancel', meta_target_name, meta_packet_name)
46
+ exit(1) unless result
47
+ end
48
+ end
49
+
50
+ def initialize(options)
51
+ super(options) # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes
52
+ Cosmos.load_cosmos_icon("cts.png")
53
+
54
+ @production = options.production
55
+ @no_prompt = options.no_prompt
56
+ @message_log = nil
57
+ @output_sleeper = Sleeper.new
58
+
59
+ statusBar.showMessage(tr("")) # Show blank message to initialize status bar
60
+
61
+ initialize_actions()
62
+ initialize_menus()
63
+ initialize_central_widget()
64
+ complete_initialize()
65
+
66
+ Splash.execute(self) do |splash|
67
+ ConfigParser.splash = splash
68
+ splash.message = "Initializing #{CMD} and #{TLM} Server"
69
+
70
+ # Start the thread that will process server messages and add them to the output text
71
+ process_server_messages(options)
72
+
73
+ CmdTlmServer.meta_callback = method(:meta_callback)
74
+ cts = CmdTlmServer.new(options.config_file, @production)
75
+ cts.stop_callback = method(:stop_callback)
76
+ @message_log = CmdTlmServer.message_log
77
+
78
+ # Now that we've started the server (CmdTlmServer.new) we can populate all the tabs
79
+ splash.message = "Populating Tabs"
80
+ Qt.execute_in_main_thread(true) do
81
+ # Override the default title if one was given in the config file
82
+ self.window_title = CmdTlmServer.title if CmdTlmServer.title
83
+ splash.progress = 0
84
+ populate_interfaces('Interfaces')
85
+ splash.progress = 100/7 * 1
86
+ populate_targets()
87
+ splash.progress = 100/7 * 2
88
+ populate_packets(CMD)
89
+ splash.progress = 100/7 * 3
90
+ populate_packets(TLM)
91
+ splash.progress = 100/7 * 4
92
+ populate_interfaces('Routers')
93
+ splash.progress = 100/7 * 5
94
+ populate_logging()
95
+ splash.progress = 100/7 * 6
96
+ populate_status()
97
+ splash.progress = 100
98
+ end
99
+ ConfigParser.splash = nil
100
+ end
101
+ end
102
+
103
+ def initialize_actions
104
+ super()
105
+
106
+ # Edit actions
107
+ @edit_clear_counters = Qt::Action.new(tr('&Clear Counters'), self)
108
+ @edit_clear_counters.statusTip = tr('Clear counters for all interfaces and targets')
109
+ @edit_clear_counters.connect(SIGNAL('triggered()')) { edit_clear_counters() }
110
+ end
111
+
112
+ def initialize_menus
113
+ @file_menu = menuBar.addMenu(tr('&File'))
114
+ @file_menu.addAction(@exit_action)
115
+
116
+ # Do not allow clear counters in production mode
117
+ unless @production
118
+ @edit_menu = menuBar.addMenu(tr('&Edit'))
119
+ @edit_menu.addAction(@edit_clear_counters)
120
+ end
121
+
122
+ @about_string = "#{CMD} and #{TLM} Server is the heart of the COSMOS system. "
123
+ @about_string << "It connects to the target and processes command and telemetry requests from other tools."
124
+
125
+ initialize_help_menu()
126
+ end
127
+
128
+ ###########################################
129
+ # Edit Menu Options
130
+ ###########################################
131
+
132
+ # Edit->Clear Counters
133
+ def edit_clear_counters
134
+ CmdTlmServer.clear_counters
135
+ end
136
+
137
+ def initialize_central_widget
138
+ # Create the central widget
139
+ @splitter = Qt::Splitter.new(Qt::Vertical, central_widget)
140
+ setCentralWidget(@splitter)
141
+
142
+ @tabbook = Qt::TabWidget.new
143
+ connect(@tabbook, SIGNAL('currentChanged(int)'), self, SLOT('handle_tab_change(int)'))
144
+ @splitter.addWidget(@tabbook)
145
+
146
+ # Add the message output
147
+ @output = Qt::PlainTextEdit.new
148
+ @output.setReadOnly(true)
149
+ @output.setMaximumBlockCount(10000) # 10000 lines of history will be displayed
150
+
151
+ @splitter.addWidget(@output)
152
+ # Set the stretch factor to give priority to the tabbook (index 0) instead of the output (index 1)
153
+ @splitter.setStretchFactor(0, 1) # (index, stretch)
154
+
155
+ # Override stdout to the message window
156
+ # All code attempting to print into the GUI must use $stdout rather than STDOUT
157
+ @string_output = StringIO.new("", "r+")
158
+ $stdout = @string_output
159
+ Logger.level = Logger::INFO
160
+
161
+ @tab_thread = nil
162
+ end
163
+
164
+ def kill_tab_thread
165
+ @tab_sleeper ||= nil
166
+ @tab_sleeper.cancel if @tab_sleeper
167
+ Cosmos.kill_thread(self, @tab_thread)
168
+ @tab_thread = nil
169
+ end
170
+
171
+ def handle_tab_change(index)
172
+ kill_tab_thread()
173
+ @tab_sleeper = Sleeper.new
174
+ case index
175
+ when 0
176
+ handle_interfaces_tab('Interfaces')
177
+ when 1
178
+ handle_targets_tab()
179
+ when 2
180
+ handle_packets_tab(CMD)
181
+ when 3
182
+ handle_packets_tab(TLM)
183
+ when 4
184
+ handle_interfaces_tab('Routers')
185
+ when 5
186
+ handle_logging_tab()
187
+ when 6
188
+ handle_status_tab()
189
+ end
190
+ end
191
+
192
+ def populate_interfaces(name)
193
+ @interfaces_table ||= {}
194
+
195
+ if name == 'Routers'
196
+ interfaces = CmdTlmServer.routers
197
+ else
198
+ interfaces = CmdTlmServer.interfaces
199
+ end
200
+
201
+ num_interfaces = interfaces.names.length
202
+ if interfaces.names.length > 0
203
+ scroll = Qt::ScrollArea.new
204
+ scroll.setMinimumSize(800, 150)
205
+ widget = Qt::Widget.new
206
+ layout = Qt::VBoxLayout.new(widget)
207
+ # Since the layout will be inside a scroll area make sure it respects the sizes we set
208
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
209
+
210
+ interfaces_table = Qt::TableWidget.new()
211
+ interfaces_table.verticalHeader.hide()
212
+ interfaces_table.setRowCount(num_interfaces)
213
+ interfaces_table.setColumnCount(10)
214
+ if name == 'Routers'
215
+ interfaces_table.setHorizontalHeaderLabels(["Router", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
216
+ else
217
+ interfaces_table.setHorizontalHeaderLabels(["Interface", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
218
+ end
219
+
220
+ row = 0
221
+ interfaces.all.each do |interface_name, interface|
222
+ item = Qt::TableWidgetItem.new(tr(interface_name))
223
+ item.setTextAlignment(Qt::AlignCenter)
224
+ interfaces_table.setItem(row, 0, item)
225
+
226
+ if interface.connected?
227
+ button_text = 'Disconnect'
228
+ elsif interface.thread.nil?
229
+ button_text = 'Connect'
230
+ else
231
+ button_text = 'Cancel Connect'
232
+ end
233
+ button = Qt::PushButton.new(button_text)
234
+ if name == 'Routers'
235
+ button.connect(SIGNAL('clicked()')) do
236
+ if interface.thread
237
+ Logger.info "User disconnecting router #{interface_name}"
238
+ CmdTlmServer.instance.disconnect_router(interface_name)
239
+ else
240
+ Logger.info "User connecting router #{interface_name}"
241
+ CmdTlmServer.instance.connect_router(interface_name)
242
+ end
243
+ end
244
+ else
245
+ button.connect(SIGNAL('clicked()')) do
246
+ if interface.thread
247
+ Logger.info "User disconnecting interface #{interface_name}"
248
+ CmdTlmServer.instance.disconnect_interface(interface_name)
249
+ else
250
+ Logger.info "User connecting interface #{interface_name}"
251
+ CmdTlmServer.instance.connect_interface(interface_name)
252
+ end
253
+ end
254
+ end
255
+ button.setDisabled(true) if interface.disable_disconnect
256
+ interfaces_table.setCellWidget(row, 1, button)
257
+
258
+ state = Qt::TableWidgetItem.new
259
+ if interface.connected?
260
+ state.setText('true')
261
+ state.textColor = Cosmos::GREEN
262
+ elsif interface.thread
263
+ state.setText('attempting')
264
+ state.textColor = Cosmos::YELLOW
265
+ else
266
+ state.setText('false')
267
+ state.textColor = Cosmos::BLACK
268
+ end
269
+ state.setTextAlignment(Qt::AlignCenter)
270
+ interfaces_table.setItem(row, 2, state)
271
+
272
+ num_clients = Qt::TableWidgetItem.new(tr(interface.num_clients.to_s))
273
+ num_clients.setTextAlignment(Qt::AlignCenter)
274
+ interfaces_table.setItem(row, 3, num_clients)
275
+
276
+ write_queue_size = Qt::TableWidgetItem.new(tr(interface.write_queue_size.to_s))
277
+ write_queue_size.setTextAlignment(Qt::AlignCenter)
278
+ interfaces_table.setItem(row, 4, write_queue_size)
279
+
280
+ read_queue_size = Qt::TableWidgetItem.new(tr(interface.read_queue_size.to_s))
281
+ read_queue_size.setTextAlignment(Qt::AlignCenter)
282
+ interfaces_table.setItem(row, 5, read_queue_size)
283
+
284
+ bytes_written = Qt::TableWidgetItem.new(tr(interface.bytes_written.to_s))
285
+ bytes_written.setTextAlignment(Qt::AlignCenter)
286
+ interfaces_table.setItem(row, 6, bytes_written)
287
+
288
+ bytes_read = Qt::TableWidgetItem.new(tr(interface.bytes_read.to_s))
289
+ bytes_read.setTextAlignment(Qt::AlignCenter)
290
+ interfaces_table.setItem(row, 7, bytes_read)
291
+
292
+ write_count = Qt::TableWidgetItem.new(tr(interface.write_count.to_s))
293
+ write_count.setTextAlignment(Qt::AlignCenter)
294
+ interfaces_table.setItem(row, 8, write_count)
295
+
296
+ read_count = Qt::TableWidgetItem.new(tr(interface.read_count.to_s))
297
+ read_count.setTextAlignment(Qt::AlignCenter)
298
+ interfaces_table.setItem(row, 9, read_count)
299
+
300
+ row += 1
301
+ end
302
+ interfaces_table.displayFullSize
303
+
304
+ layout.addWidget(interfaces_table)
305
+ scroll.setWidget(widget)
306
+ if name == 'Routers'
307
+ @tabbook.addTab(scroll, "Routers")
308
+ @interfaces_table['Routers'] = interfaces_table
309
+ else
310
+ @tabbook.addTab(scroll, "Interfaces")
311
+ @interfaces_table['Interfaces'] = interfaces_table
312
+ end
313
+ end
314
+ end
315
+
316
+ def handle_interfaces_tab(name)
317
+ @tab_thread = Thread.new do
318
+ if @interfaces_table[name]
319
+ begin
320
+ while true
321
+ Qt.execute_in_main_thread(true) do
322
+ row = 0
323
+ if name == 'Routers'
324
+ interfaces = CmdTlmServer.routers
325
+ else
326
+ interfaces = CmdTlmServer.interfaces
327
+ end
328
+ interfaces.all.each do |interface_name, interface|
329
+ button = @interfaces_table[name].cellWidget(row,1)
330
+ state = @interfaces_table[name].item(row,2)
331
+ if interface.connected?
332
+ button.setText('Disconnect')
333
+ button.setDisabled(true) if interface.disable_disconnect
334
+ state.setText('true')
335
+ state.textColor = Cosmos::GREEN
336
+ elsif interface.thread
337
+ button.text = 'Cancel Connect'
338
+ button.setDisabled(false)
339
+ state.text = 'attempting'
340
+ state.textColor = Cosmos::RED
341
+ else
342
+ button.setText('Connect')
343
+ button.setDisabled(false)
344
+ state.setText('false')
345
+ state.textColor = Cosmos::BLACK
346
+ end
347
+ @interfaces_table[name].item(row,3).setText(interface.num_clients.to_s)
348
+ @interfaces_table[name].item(row,4).setText(interface.write_queue_size.to_s)
349
+ @interfaces_table[name].item(row,5).setText(interface.read_queue_size.to_s)
350
+ @interfaces_table[name].item(row,6).setText(interface.bytes_written.to_s)
351
+ @interfaces_table[name].item(row,7).setText(interface.bytes_read.to_s)
352
+ if name == 'Routers'
353
+ @interfaces_table[name].item(row,8).setText(interface.read_count.to_s)
354
+ @interfaces_table[name].item(row,9).setText(interface.write_count.to_s)
355
+ else
356
+ @interfaces_table[name].item(row,8).setText(interface.write_count.to_s)
357
+ @interfaces_table[name].item(row,9).setText(interface.read_count.to_s)
358
+ end
359
+ row += 1
360
+ end
361
+ end
362
+ break if @tab_sleeper.sleep(1)
363
+ end
364
+ rescue Exception => error
365
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : #{name} Tab Thread")}
366
+ end
367
+ end
368
+ end
369
+ end
370
+
371
+ def populate_targets
372
+ num_targets = System.targets.length
373
+ if num_targets > 0
374
+ return if num_targets == 1 and System.targets['SYSTEM']
375
+ num_targets -= 1 if System.targets['SYSTEM']
376
+
377
+ scroll = Qt::ScrollArea.new
378
+ widget = Qt::Widget.new
379
+ layout = Qt::VBoxLayout.new(widget)
380
+ # Since the layout will be inside a scroll area make sure it respects the sizes we set
381
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
382
+
383
+ @targets_table = Qt::TableWidget.new()
384
+ @targets_table.verticalHeader.hide()
385
+ @targets_table.setRowCount(num_targets)
386
+ @targets_table.setColumnCount(4)
387
+ @targets_table.setHorizontalHeaderLabels(["Target Name", "Interface", "#{CMD} Count", "#{TLM} Count"])
388
+
389
+ row = 0
390
+ System.targets.sort.each do |target_name, target|
391
+ next if target_name == 'SYSTEM'
392
+ target_name_widget = Qt::TableWidgetItem.new(tr(target_name))
393
+ target_name_widget.setTextAlignment(Qt::AlignCenter)
394
+ @targets_table.setItem(row, 0, target_name_widget)
395
+ if target.interface
396
+ interface_name_widget = Qt::TableWidgetItem.new(tr(target.interface.name.to_s))
397
+ else
398
+ interface_name_widget = Qt::TableWidgetItem.new(tr(''))
399
+ end
400
+ interface_name_widget.setTextAlignment(Qt::AlignCenter)
401
+ @targets_table.setItem(row, 1, interface_name_widget)
402
+ cmd_cnt = Qt::TableWidgetItem.new(tr(target.cmd_cnt.to_s))
403
+ cmd_cnt.setTextAlignment(Qt::AlignCenter)
404
+ @targets_table.setItem(row, 2, cmd_cnt)
405
+
406
+ tlm_cnt = Qt::TableWidgetItem.new(tr(target.tlm_cnt.to_s))
407
+ tlm_cnt.setTextAlignment(Qt::AlignCenter)
408
+ @targets_table.setItem(row, 3, tlm_cnt)
409
+
410
+ row += 1
411
+ end
412
+ @targets_table.displayFullSize
413
+
414
+ layout.addWidget(@targets_table)
415
+ scroll.setWidget(widget)
416
+ @tabbook.addTab(scroll, "Targets")
417
+ end
418
+ end
419
+
420
+ def handle_targets_tab
421
+ @tab_thread = Thread.new do
422
+ begin
423
+ while true
424
+ Qt.execute_in_main_thread(true) do
425
+ row = 0
426
+ System.targets.sort.each do |target_name, target|
427
+ next if target_name == 'SYSTEM'
428
+ @targets_table.item(row,2).setText(target.cmd_cnt.to_s)
429
+ @targets_table.item(row,3).setText(target.tlm_cnt.to_s)
430
+ row += 1
431
+ end
432
+ end
433
+ break if @tab_sleeper.sleep(1)
434
+ end
435
+ rescue Exception => error
436
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Targets Tab Thread")}
437
+ end
438
+ end
439
+ end
440
+
441
+ def get_cmd_tlm_def(name)
442
+ case name
443
+ when CMD
444
+ return System.commands
445
+ when TLM
446
+ return System.telemetry
447
+ end
448
+ end
449
+
450
+ def populate_packets(name)
451
+ cmd_tlm = get_cmd_tlm_def(name)
452
+
453
+ unless cmd_tlm.target_names.empty?
454
+ count = 0
455
+ cmd_tlm.target_names.sort.each do |target_name|
456
+ packets = cmd_tlm.packets(target_name)
457
+ packets.each do |packet_name, packet|
458
+ count += 1 unless packet.hidden
459
+ end
460
+ end
461
+
462
+ scroll = Qt::ScrollArea.new
463
+ widget = Qt::Widget.new
464
+ layout = Qt::VBoxLayout.new(widget)
465
+ # Since the layout will be inside a scroll area
466
+ # make sure it respects the sizes we set
467
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
468
+
469
+ table = Qt::TableWidget.new()
470
+ table.verticalHeader.hide()
471
+ table.setRowCount(count)
472
+ column_cnt = 4
473
+ column_cnt += 1 if name == TLM
474
+ table.setColumnCount(column_cnt)
475
+ # Force the last section to fill all available space in the frame
476
+ #~ table.horizontalHeader.setStretchLastSection(true)
477
+ headers = ["Target Name", "Packet Name", "Packet Count", "View Raw"]
478
+ headers << "View in Packet Viewer" if name == TLM
479
+ table.setHorizontalHeaderLabels(headers)
480
+
481
+ row = 0
482
+ cmd_tlm.target_names.sort.each do |target_name|
483
+ packets = cmd_tlm.packets(target_name)
484
+ packets.sort.each do |packet_name, packet|
485
+ packet.received_count ||= 0
486
+ next if packet.hidden
487
+ target_name_widget = Qt::TableWidgetItem.new(tr(target_name))
488
+ target_name_widget.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
489
+ table.setItem(row, 0, target_name_widget)
490
+ table.setItem(row, 1, Qt::TableWidgetItem.new(tr(packet_name)))
491
+ packet_count = Qt::TableWidgetItem.new(tr(packet.received_count.to_s))
492
+ packet_count.setTextAlignment(Qt::AlignCenter)
493
+ table.setItem(row, 2, packet_count)
494
+ view_raw = Qt::PushButton.new("View Raw")
495
+ view_raw.connect(SIGNAL('clicked()')) do
496
+ @raw_dialogs ||= []
497
+ @raw_dialogs << CmdRawDialog.new(self, target_name, packet_name) if name == CMD
498
+ @raw_dialogs << TlmRawDialog.new(self, target_name, packet_name) if name == TLM
499
+ end
500
+ table.setCellWidget(row, 3, view_raw)
501
+
502
+ if name == TLM
503
+ if target_name != 'UNKNOWN' and packet_name != 'UNKNOWN'
504
+ view_pv = Qt::PushButton.new("View in Packet Viewer")
505
+ view_pv.connect(SIGNAL('clicked()')) do
506
+ if Kernel.is_windows?
507
+ Cosmos.run_process("rubyw tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
508
+ elsif Kernel.is_mac? and File.exist?("tools/mac/PacketViewer.app")
509
+ Cosmos.run_process("open tools/mac/PacketViewer.app --args -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
510
+ else
511
+ Cosmos.run_process("ruby tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
512
+ end
513
+ end
514
+ table.setCellWidget(row, 4, view_pv)
515
+ else
516
+ table_widget = Qt::TableWidgetItem.new(tr('N/A'))
517
+ table_widget.setTextAlignment(Qt::AlignCenter)
518
+ table.setItem(row, 4, table_widget)
519
+ end
520
+ end
521
+
522
+ row += 1
523
+ end
524
+ end
525
+ table.displayFullSize
526
+
527
+ layout.addWidget(table)
528
+ scroll.setWidget(widget)
529
+ tab_name = "Cmd Packets" if name == CMD
530
+ tab_name = "Tlm Packets" if name == TLM
531
+ @tabbook.addTab(scroll, tab_name)
532
+
533
+ @packets_table ||= {}
534
+ @packets_table[name] = table
535
+ end
536
+ end
537
+
538
+ def handle_packets_tab(name)
539
+ cmd_tlm = get_cmd_tlm_def(name)
540
+
541
+ @tab_thread = Thread.new do
542
+ begin
543
+ unless cmd_tlm.target_names.empty?
544
+ while true
545
+ Qt.execute_in_main_thread(true) do
546
+ row = 0
547
+ cmd_tlm.target_names.sort.each do |target_name|
548
+ packets = cmd_tlm.packets(target_name)
549
+ packets.sort.each do |packet_name, packet|
550
+ next if packet.hidden
551
+ @packets_table[name].item(row, 2).setText(packet.received_count.to_s)
552
+ row += 1
553
+ end
554
+ end
555
+ end
556
+ break if @tab_sleeper.sleep(1)
557
+ end
558
+ end
559
+ rescue Exception => error
560
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : #{name} Packets Tab Thread")}
561
+ end
562
+ end
563
+ end
564
+
565
+ def populate_logging_actions(layout)
566
+ # Add all the action buttons
567
+ actions = Qt::GroupBox.new(tr("Actions"))
568
+ actions_layout = Qt::VBoxLayout.new(actions)
569
+ button_layout = Qt::GridLayout.new
570
+
571
+ log_buttons = [
572
+ ["Start Logging on All", [0,0], :start_logging],
573
+ ["Stop Logging on All", [0,1], :stop_logging],
574
+ ["Start #{TLM} Logging on All", [1,0], :start_tlm_log],
575
+ ["Stop #{TLM} Logging on All", [1,1], :stop_tlm_log],
576
+ ["Start #{CMD} Logging on All", [2,0], :start_cmd_log],
577
+ ["Stop #{CMD} Logging on All", [2,1], :stop_cmd_log]
578
+ ]
579
+
580
+ log_buttons.each do |text, location, method|
581
+ next if text =~ /Stop/ and @production
582
+ button = Qt::PushButton.new(tr(text))
583
+ button_layout.addWidget(button, location[0], location[1])
584
+ button.connect(SIGNAL('clicked()')) do
585
+ begin
586
+ CmdTlmServer.instance.send(method, 'ALL')
587
+ rescue Exception => error
588
+ statusBar.showMessage(tr(error.message))
589
+ end
590
+ end
591
+ end
592
+
593
+ actions_layout.addLayout(button_layout)
594
+
595
+ layout.addWidget(actions)
596
+ end
597
+
598
+ def create_log_layout(form_layout, log_writer, label_prefix)
599
+ label = Qt::Label.new(tr(log_writer.logging_enabled.to_s))
600
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
601
+ form_layout.addRow("#{label_prefix} Logging:", label)
602
+ label = Qt::Label.new(tr(log_writer.queue.size.to_s))
603
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
604
+ form_layout.addRow("#{label_prefix} Queue Size:", label)
605
+ label = Qt::Label.new(tr(log_writer.filename))
606
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
607
+ form_layout.addRow("#{label_prefix} Filename:", label)
608
+ file_size = 0
609
+ begin
610
+ file_size = File.size(log_writer.filename) if log_writer.filename
611
+ rescue Exception
612
+ # Do nothing on error
613
+ end
614
+ label = Qt::Label.new(tr(file_size.to_s))
615
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
616
+ form_layout.addRow("#{label_prefix} File Size:", label)
617
+ end
618
+
619
+ def populate_log_file_info(layout)
620
+ CmdTlmServer.packet_logging.all.sort.each do |packet_log_writer_pair_name, packet_log_writer_pair|
621
+ log = Qt::GroupBox.new("#{packet_log_writer_pair_name} Packet Log Writer")
622
+ log_layout = Qt::VBoxLayout.new(log)
623
+ interfaces = []
624
+ CmdTlmServer.interfaces.all.each do |interface_name, interface|
625
+ if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
626
+ interfaces << interface.name
627
+ end
628
+ end
629
+
630
+ form_layout = Qt::FormLayout.new
631
+ @logging_layouts[packet_log_writer_pair_name] = form_layout
632
+ label = Qt::Label.new(tr(interfaces.join(", ")))
633
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
634
+ form_layout.addRow("Interfaces:", label)
635
+ create_log_layout(form_layout, packet_log_writer_pair.cmd_log_writer, 'Cmd')
636
+ create_log_layout(form_layout, packet_log_writer_pair.tlm_log_writer, 'Tlm')
637
+
638
+ button_layout = Qt::HBoxLayout.new
639
+ start_button = Qt::PushButton.new(tr('Start Cmd Logging'))
640
+ button_layout.addWidget(start_button)
641
+ start_button.connect(SIGNAL('clicked()')) do
642
+ CmdTlmServer.instance.start_cmd_log(packet_log_writer_pair_name)
643
+ end
644
+ start_button = Qt::PushButton.new(tr('Start Tlm Logging'))
645
+ button_layout.addWidget(start_button)
646
+ start_button.connect(SIGNAL('clicked()')) do
647
+ CmdTlmServer.instance.start_tlm_log(packet_log_writer_pair_name)
648
+ end
649
+ if @production == false
650
+ stop_button = Qt::PushButton.new(tr('Stop Cmd Logging'))
651
+ button_layout.addWidget(stop_button)
652
+ stop_button.connect(SIGNAL('clicked()')) do
653
+ CmdTlmServer.instance.stop_cmd_log(packet_log_writer_pair_name)
654
+ end
655
+ stop_button = Qt::PushButton.new(tr('Stop Tlm Logging'))
656
+ button_layout.addWidget(stop_button)
657
+ stop_button.connect(SIGNAL('clicked()')) do
658
+ CmdTlmServer.instance.stop_tlm_log(packet_log_writer_pair_name)
659
+ end
660
+ end
661
+ form_layout.addRow("Actions:", button_layout)
662
+ log_layout.addLayout(form_layout)
663
+ layout.addWidget(log)
664
+ end
665
+ layout.addWidget(Qt::Label.new(tr("Note: Buffered IO operations cause file size to not reflect total logged data size until the log file is closed.")))
666
+ end
667
+
668
+ def populate_logging
669
+ scroll = Qt::ScrollArea.new
670
+ widget = Qt::Widget.new
671
+ layout = Qt::VBoxLayout.new(widget)
672
+ # Since the layout will be inside a scroll area
673
+ # make sure it respects the sizes we set
674
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
675
+
676
+ populate_logging_actions(layout)
677
+
678
+ # Create the hash which will hold the logging layouts
679
+ @logging_layouts = {}
680
+
681
+ # Add the cmd/tlm log files information
682
+ populate_log_file_info(layout)
683
+
684
+ # Set the scroll area widget last now that all the items have been layed out
685
+ scroll.setWidget(widget)
686
+ @tabbook.addTab(scroll, "Logging")
687
+ end
688
+
689
+ def update_filename_and_logging_state
690
+ CmdTlmServer.packet_logging.all.each do |packet_log_writer_pair_name, packet_log_writer_pair|
691
+ @logging_layouts[packet_log_writer_pair_name].itemAt(1, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.logging_enabled.to_s)
692
+ @logging_layouts[packet_log_writer_pair_name].itemAt(2, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.queue.size.to_s)
693
+ @logging_layouts[packet_log_writer_pair_name].itemAt(3, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.filename)
694
+ file_size = 0
695
+ begin
696
+ file_size = File.size(packet_log_writer_pair.cmd_log_writer.filename) if packet_log_writer_pair.cmd_log_writer.filename
697
+ rescue Exception
698
+ # Do nothing on error
699
+ end
700
+ @logging_layouts[packet_log_writer_pair_name].itemAt(4, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
701
+ @logging_layouts[packet_log_writer_pair_name].itemAt(5, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.logging_enabled.to_s)
702
+ @logging_layouts[packet_log_writer_pair_name].itemAt(6, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.queue.size.to_s)
703
+ @logging_layouts[packet_log_writer_pair_name].itemAt(7, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.filename)
704
+ file_size = 0
705
+ begin
706
+ file_size = File.size(packet_log_writer_pair.tlm_log_writer.filename) if packet_log_writer_pair.tlm_log_writer.filename
707
+ rescue Exception
708
+ # Do nothing on error
709
+ end
710
+ @logging_layouts[packet_log_writer_pair_name].itemAt(8, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
711
+ end
712
+ end
713
+
714
+ def handle_logging_tab
715
+ @tab_thread = Thread.new do
716
+ begin
717
+ while true
718
+ Qt.execute_in_main_thread(true) do
719
+ update_filename_and_logging_state()
720
+ end
721
+ break if @tab_sleeper.sleep(1)
722
+ end
723
+ rescue Exception => error
724
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Logging Tab Thread")}
725
+ end
726
+ end
727
+ end
728
+
729
+ def populate_status
730
+ scroll = Qt::ScrollArea.new
731
+ widget = Qt::Widget.new
732
+ layout = Qt::VBoxLayout.new(widget)
733
+
734
+ limits = Qt::GroupBox.new(tr("Limits Status"))
735
+ limits_layout = Qt::FormLayout.new(limits)
736
+ current_limits_set = System.limits_set.to_s
737
+
738
+ known_limits_sets = System.limits.sets
739
+ known_limits_sets = known_limits_sets.map {|x| x.to_s}.sort
740
+ current_index = known_limits_sets.index(current_limits_set.to_s)
741
+
742
+ @limits_set_combo = Qt::ComboBox.new
743
+ limits_layout.addRow("Limits Set:", @limits_set_combo)
744
+ layout.addWidget(limits)
745
+
746
+ known_limits_sets.sort.each do |limits_set|
747
+ @limits_set_combo.addItem(limits_set.to_s)
748
+ end
749
+ @limits_set_combo.setMaxVisibleItems(6)
750
+ @limits_set_combo.setCurrentIndex(current_index)
751
+ # Only connect to the signal that is sent when the user chooses an item.
752
+ # If the limits set is changed programatically the code in
753
+ # handle_status_tab will pick up the change.
754
+ @limits_set_combo.connect(SIGNAL('activated(int)')) do
755
+ selected_limits_set = @limits_set_combo.currentText
756
+ if selected_limits_set
757
+ System.limits_set = selected_limits_set.intern if System.limits_set != selected_limits_set.intern
758
+ end
759
+ end
760
+
761
+ api = Qt::GroupBox.new(tr("API Status"))
762
+ api_layout = Qt::VBoxLayout.new(api)
763
+ @api_table = Qt::TableWidget.new()
764
+ @api_table.verticalHeader.hide()
765
+ @api_table.setRowCount(1)
766
+ @api_table.setColumnCount(6)
767
+ @api_table.setHorizontalHeaderLabels(["Port", "Num Clients", "Requests", "Requests/Sec", "Avg Request Time", "Estimated Utilization"])
768
+
769
+ @api_table.setItem(0, 0, Qt::TableWidgetItem.new(tr(System.ports['CTS_API'].to_s)))
770
+ item0 = Qt::TableWidgetItem.new(tr(CmdTlmServer.json_drb.num_clients.to_s))
771
+ item0.setTextAlignment(Qt::AlignCenter)
772
+ @api_table.setItem(0, 1, item0)
773
+ item = Qt::TableWidgetItem.new(tr(CmdTlmServer.json_drb.request_count.to_s))
774
+ item.setTextAlignment(Qt::AlignCenter)
775
+ @api_table.setItem(0, 2, item)
776
+ item2 = Qt::TableWidgetItem.new("0.0")
777
+ item2.setTextAlignment(Qt::AlignCenter)
778
+ @api_table.setItem(0, 3, item2)
779
+ item3 = Qt::TableWidgetItem.new("0.0")
780
+ item3.setTextAlignment(Qt::AlignCenter)
781
+ @api_table.setItem(0, 4, item3)
782
+ item4 = Qt::TableWidgetItem.new("0.0")
783
+ item4.setTextAlignment(Qt::AlignCenter)
784
+ @api_table.setItem(0, 5, item4)
785
+ @api_table.displayFullSize
786
+ api_layout.addWidget(@api_table)
787
+ layout.addWidget(api)
788
+
789
+ system = Qt::GroupBox.new(tr("System Status"))
790
+ system_layout = Qt::VBoxLayout.new(system)
791
+ @system_table = Qt::TableWidget.new()
792
+ @system_table.verticalHeader.hide()
793
+ @system_table.setRowCount(1)
794
+ @system_table.setColumnCount(4)
795
+ @system_table.setHorizontalHeaderLabels(["Threads", "Total Objs", "Free Objs", "Allocated Objs"])
796
+
797
+ item0 = Qt::TableWidgetItem.new("0")
798
+ item0.setTextAlignment(Qt::AlignCenter)
799
+ @system_table.setItem(0, 0, item0)
800
+ item1 = Qt::TableWidgetItem.new("0.0")
801
+ item1.setTextAlignment(Qt::AlignCenter)
802
+ @system_table.setItem(0, 1, item1)
803
+ item2 = Qt::TableWidgetItem.new("0.0")
804
+ item2.setTextAlignment(Qt::AlignCenter)
805
+ @system_table.setItem(0, 2, item2)
806
+ item3 = Qt::TableWidgetItem.new("0.0")
807
+ item3.setTextAlignment(Qt::AlignCenter)
808
+ @system_table.setItem(0, 3, item3)
809
+ @system_table.displayFullSize
810
+ system_layout.addWidget(@system_table)
811
+ layout.addWidget(system)
812
+
813
+ background_tasks_groupbox = Qt::GroupBox.new(tr("Background Tasks"))
814
+ background_tasks_layout = Qt::VBoxLayout.new(background_tasks_groupbox)
815
+ @background_tasks_table = Qt::TableWidget.new()
816
+ @background_tasks_table.verticalHeader.hide()
817
+ @background_tasks_table.setRowCount(CmdTlmServer.background_tasks.all.length)
818
+ @background_tasks_table.setColumnCount(3)
819
+ @background_tasks_table.setHorizontalHeaderLabels(["Name", "State", "Status"])
820
+
821
+ background_tasks = CmdTlmServer.background_tasks.all
822
+ if background_tasks.length > 0
823
+ row = 0
824
+ background_tasks.each_with_index do |background_task, index|
825
+ background_task_name = background_task.name
826
+ background_task_name = "Background Task ##{index + 1}" unless background_task_name
827
+ background_task_name_widget = Qt::TableWidgetItem.new(background_task_name)
828
+ background_task_name_widget.setTextAlignment(Qt::AlignCenter)
829
+ @background_tasks_table.setItem(row, 0, background_task_name_widget)
830
+ if background_task.thread
831
+ status = background_task.thread.status
832
+ status = 'complete' if status == false
833
+ background_task_state_widget = Qt::TableWidgetItem.new(status.to_s)
834
+ else
835
+ background_task_state_widget = Qt::TableWidgetItem.new('no thread')
836
+ end
837
+ background_task_state_widget.setTextAlignment(Qt::AlignCenter)
838
+ background_task_state_widget.setSizeHint(Qt::Size.new(80, 30))
839
+ @background_tasks_table.setItem(row, 1, background_task_state_widget)
840
+ background_task_status_widget = Qt::TableWidgetItem.new(background_task.status.to_s)
841
+ background_task_status_widget.setTextAlignment(Qt::AlignCenter)
842
+ background_task_status_widget.setSizeHint(Qt::Size.new(500, 30))
843
+ @background_tasks_table.setItem(row, 2, background_task_status_widget)
844
+
845
+ row += 1
846
+ end
847
+ end
848
+ @background_tasks_table.displayFullSize
849
+ background_tasks_layout.addWidget(@background_tasks_table)
850
+ layout.addWidget(background_tasks_groupbox)
851
+
852
+ # Set the scroll area widget last now that all the items have been layed out
853
+ scroll.setWidget(widget)
854
+ @tabbook.addTab(scroll, "Status")
855
+ end
856
+
857
+ def handle_status_tab
858
+ @tab_thread = Thread.new do
859
+ begin
860
+ if CmdTlmServer.json_drb
861
+ previous_request_count = CmdTlmServer.json_drb.request_count
862
+ else
863
+ previous_request_count = 0
864
+ end
865
+ while true
866
+ start_time = Time.now
867
+ Qt.execute_in_main_thread(true) do
868
+ # Update limits set
869
+ current_limits_set = System.limits_set.to_s
870
+ if @limits_set_combo.currentText != current_limits_set
871
+ known_limits_sets = System.limits.sets
872
+ known_limits_sets = known_limits_sets.map {|x| x.to_s}.sort
873
+ current_index = known_limits_sets.index(current_limits_set.to_s)
874
+ @limits_set_combo.clear
875
+ known_limits_sets.sort.each do |limits_set|
876
+ @limits_set_combo.addItem(limits_set.to_s)
877
+ end
878
+ @limits_set_combo.setCurrentIndex(current_index)
879
+ end
880
+
881
+ # Update API status
882
+ if CmdTlmServer.json_drb
883
+ @api_table.item(0,1).setText(CmdTlmServer.json_drb.num_clients.to_s)
884
+ @api_table.item(0,2).setText(CmdTlmServer.json_drb.request_count.to_s)
885
+ request_count = CmdTlmServer.json_drb.request_count
886
+ requests_per_second = request_count - previous_request_count
887
+ @api_table.item(0,3).setText(requests_per_second.to_s)
888
+ previous_request_count = request_count
889
+ average_request_time = CmdTlmServer.json_drb.average_request_time
890
+ @api_table.item(0,4).setText(sprintf("%0.6f s", average_request_time))
891
+ estimated_utilization = requests_per_second * average_request_time * 100.0
892
+ @api_table.item(0,5).setText(sprintf("%0.2f %", estimated_utilization))
893
+ end
894
+
895
+ # Update system status
896
+ @system_table.item(0,0).setText(Thread.list.length.to_s)
897
+ objs = ObjectSpace.count_objects
898
+ @system_table.item(0,1).setText(objs[:TOTAL].to_s)
899
+ @system_table.item(0,2).setText(objs[:FREE].to_s)
900
+ total = 0
901
+ objs.each do |key, val|
902
+ next if key == :TOTAL || key == :FREE
903
+ total += val
904
+ end
905
+ @system_table.item(0,3).setText(total.to_s)
906
+
907
+ # Update background task status
908
+ background_tasks = CmdTlmServer.background_tasks.all
909
+ if background_tasks.length > 0
910
+ row = 0
911
+ background_tasks.each_with_index do |background_task, index|
912
+ if background_task.thread
913
+ status = background_task.thread.status
914
+ status = 'complete' if status == false
915
+ @background_tasks_table.item(row, 1).setText(status.to_s)
916
+ else
917
+ @background_tasks_table.item(row, 1).setText('no thread')
918
+ end
919
+ @background_tasks_table.item(row, 2).setText(background_task.status.to_s)
920
+ row += 1
921
+ end
922
+ end
923
+ end
924
+ total_time = Time.now - start_time
925
+ if total_time > 0.0 and total_time < 1.0
926
+ break if @tab_sleeper.sleep(1.0 - total_time)
927
+ end
928
+ end
929
+ rescue Exception => error
930
+ Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Settings Tab Thread")}
931
+ end
932
+ end
933
+ end
934
+
935
+ def closeEvent(event)
936
+ # Create are you sure dialog
937
+ if @no_prompt
938
+ continue = true
939
+ else
940
+ msg = Qt::MessageBox.new(self)
941
+ msg.setIcon(Qt::MessageBox::Question)
942
+ msg.setText("Are you sure? All tools connected to this CmdTlmServer will lose connections and cease to function if the CmdTlmServer is closed.")
943
+ msg.setWindowTitle('Confirm Close')
944
+ msg.setStandardButtons(Qt::MessageBox::Yes | Qt::MessageBox::No)
945
+ continue = false
946
+ continue = true if msg.exec() == Qt::MessageBox::Yes
947
+ msg.dispose
948
+ end
949
+
950
+ if continue
951
+ kill_tab_thread()
952
+ CmdTlmServer.instance.stop_logging('ALL')
953
+ CmdTlmServer.instance.stop
954
+ super(event)
955
+ else
956
+ event.ignore()
957
+ end
958
+ end
959
+
960
+ def self.run(option_parser = nil, options = nil)
961
+ Cosmos.catch_fatal_exception do
962
+ unless option_parser and options
963
+ option_parser, options = create_default_options()
964
+ options.width = 800
965
+ options.height = 500
966
+ # Set the default title which can be overridden in the config file
967
+ options.title = "#{CMD} and #{TLM} Server"
968
+ options.auto_size = false
969
+ options.config_file = CmdTlmServer::DEFAULT_CONFIG_FILE
970
+ options.production = false
971
+ options.no_prompt = false
972
+ option_parser.separator "CTS Specific Options:"
973
+ option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
974
+ options.config_file = arg
975
+ end
976
+ option_parser.on("-p", "--production", "Run the server in production mode which disables the ability to stop logging.") do |arg|
977
+ options.production = true
978
+ end
979
+ option_parser.on("-n", "--no-prompt", "Don't prompt with Are You Sure dialog on close.") do |arg|
980
+ options.no_prompt = true
981
+ end
982
+ end
983
+
984
+ super(option_parser, options)
985
+ end
986
+ end
987
+
988
+ def process_server_messages(options)
989
+ # Start thread to read server messages
990
+ @output_thread = Thread.new do
991
+ begin
992
+ while !@message_log
993
+ sleep(1)
994
+ end
995
+ while true
996
+ handle_string_output()
997
+ break if @output_sleeper.sleep(1)
998
+ end
999
+ rescue Exception => error
1000
+ Qt.execute_in_main_thread(true) do
1001
+ ExceptionDialog.new(self, error, "#{options.title}: Messages Thread")
1002
+ end
1003
+ end
1004
+ end
1005
+ end
1006
+
1007
+ def handle_string_output
1008
+ if @string_output.string[-1..-1] == "\n"
1009
+ Qt.execute_in_main_thread(true) do
1010
+ lines_to_write = ''
1011
+ string = @string_output.string.clone
1012
+ @string_output.string = @string_output.string[string.length..-1]
1013
+ string.each_line {|out_line| @output.add_formatted_text(out_line); lines_to_write += out_line }
1014
+ @output.flush
1015
+ @message_log.write(lines_to_write)
1016
+ end
1017
+ end
1018
+ end
1019
+
1020
+ def stop_callback
1021
+ handle_string_output()
1022
+ @output_sleeper.cancel
1023
+ Qt::CoreApplication.processEvents()
1024
+ Cosmos.kill_thread(self, @output_thread)
1025
+ handle_string_output()
1026
+ end
1027
+
1028
+ def graceful_kill
1029
+ # Just to avoid warning
1030
+ end
1031
+ end # class CmdTlmServerGui
1032
+
1033
+ end # module Cosmos