cosmos 3.9.2 → 4.0.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 (438) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +23 -0
  3. data/.travis.yml +1 -0
  4. data/.yardopts +3 -0
  5. data/Gemfile +1 -1
  6. data/Manifest.txt +137 -52
  7. data/Rakefile +50 -44
  8. data/autohotkey/config/system/system.txt +0 -5
  9. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +6 -1
  10. data/autohotkey/config/targets/INST/screens/extra.txt +19 -0
  11. data/autohotkey/config/targets/INST/sequences/run_sequence.txt +1 -0
  12. data/autohotkey/config/targets/META/screens/data.txt +12 -0
  13. data/autohotkey/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  14. data/autohotkey/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  15. data/autohotkey/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  16. data/autohotkey/config/targets/SYSTEM/screens/limits_change.txt +14 -0
  17. data/autohotkey/config/targets/SYSTEM/screens/meta.txt +14 -0
  18. data/autohotkey/config/targets/SYSTEM/target.txt +12 -0
  19. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  20. data/autohotkey/config/tools/test_runner/test_runner2.txt +1 -1
  21. data/autohotkey/tools/CmdSequence +14 -0
  22. data/autohotkey/tools/CmdSequenceAHK +23 -0
  23. data/autohotkey/tools/CmdSequenceAHK2 +16 -0
  24. data/autohotkey/tools/cmd_extractor.ahk +2 -2
  25. data/autohotkey/tools/cmd_sender.ahk +4 -6
  26. data/autohotkey/tools/cmd_sequence.ahk +215 -0
  27. data/autohotkey/tools/cmd_sequence2.ahk +23 -0
  28. data/autohotkey/tools/data_viewer.ahk +2 -3
  29. data/autohotkey/tools/limits_monitor.ahk +9 -11
  30. data/autohotkey/tools/open_gl_builder.ahk +1 -2
  31. data/autohotkey/tools/packet_viewer.ahk +51 -35
  32. data/autohotkey/tools/replay.ahk +1 -2
  33. data/autohotkey/tools/script_runner.ahk +1 -2
  34. data/autohotkey/tools/script_runner2.ahk +1 -2
  35. data/autohotkey/tools/test_runner2.ahk +1 -5
  36. data/autohotkey/tools/test_runner3.ahk +1 -3
  37. data/autohotkey/tools/tlm_grapher.ahk +1 -3
  38. data/autohotkey/tools/tlm_grapher3.ahk +1 -2
  39. data/autohotkey/tools/tlm_viewer.ahk +8 -3
  40. data/autohotkey/tools/tlm_viewer2.ahk +2 -3
  41. data/autohotkey/tools/tlm_viewer5.ahk +1 -2
  42. data/cosmos.gemspec +26 -20
  43. data/data/cmd_sequence.png +0 -0
  44. data/data/config/_array_params.yaml +23 -0
  45. data/data/config/_id_items.yaml +24 -0
  46. data/data/config/_id_params.yaml +58 -0
  47. data/data/config/_interfaces.yaml +206 -0
  48. data/data/config/_items.yaml +20 -0
  49. data/data/config/_params.yaml +58 -0
  50. data/data/config/cmd_tlm_server.yaml +110 -0
  51. data/data/config/command.yaml +38 -0
  52. data/data/config/command_modifiers.yaml +127 -0
  53. data/data/config/command_telemetry.yaml +3 -0
  54. data/data/config/data_viewer.yaml +43 -0
  55. data/data/config/handbook_creator.yaml +23 -0
  56. data/data/config/housekeeping_params.yaml +71 -0
  57. data/data/config/interface_modifiers.yaml +44 -0
  58. data/data/config/item_modifiers.yaml +172 -0
  59. data/data/config/launcher.yaml +117 -0
  60. data/data/config/limits_monitor.yaml +53 -0
  61. data/data/config/linegraph_params.yaml +30 -0
  62. data/data/config/linegraph_plot.yaml +106 -0
  63. data/data/config/page_modifiers.yaml +128 -0
  64. data/data/config/param_item_modifiers.yaml +41 -0
  65. data/data/config/parameter_modifiers.yaml +144 -0
  66. data/data/config/protocols.yaml +257 -0
  67. data/data/config/screen.yaml +151 -0
  68. data/data/config/script_runner.yaml +15 -0
  69. data/data/config/system.yaml +153 -0
  70. data/data/config/table_manager.yaml +76 -0
  71. data/data/config/table_parameter_modifiers.yaml +9 -0
  72. data/data/config/target.yaml +71 -0
  73. data/data/config/telemetry.yaml +73 -0
  74. data/data/config/telemetry_modifiers.yaml +129 -0
  75. data/data/config/test_runner.yaml +118 -0
  76. data/data/config/tlm_extractor.yaml +109 -0
  77. data/data/config/tlm_grapher.yaml +78 -0
  78. data/data/config/tlm_viewer.yaml +107 -0
  79. data/data/config/unknown.yaml +3 -0
  80. data/data/config/widgets.yaml +1339 -0
  81. data/data/config/xy_params.yaml +50 -0
  82. data/data/config/xy_plot.yaml +12 -0
  83. data/data/config_editor.png +0 -0
  84. data/data/crc.txt +172 -161
  85. data/data/delete.png +0 -0
  86. data/demo/config/data/crc.txt +56 -36
  87. data/demo/config/data/meta_init.txt +1 -4
  88. data/demo/config/system/system.txt +15 -3
  89. data/demo/config/system/system2.txt +13 -3
  90. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +2 -6
  91. data/demo/config/targets/EXAMPLE/target.txt +3 -1
  92. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -0
  93. data/demo/config/targets/INST/lib/inst_dump_component.rb +34 -0
  94. data/demo/config/targets/INST/screens/adcs.txt +39 -15
  95. data/demo/config/targets/INST/screens/commanding.txt +26 -19
  96. data/demo/config/targets/INST/screens/spacing_box.txt +44 -0
  97. data/demo/config/targets/INST/screens/spacing_grid.txt +78 -0
  98. data/demo/config/targets/INST/screens/tabs.txt +0 -2
  99. data/demo/config/targets/INST/sequences/sequence.tsv +3 -0
  100. data/demo/config/targets/INST/tables/EventAction.csv +9 -0
  101. data/demo/config/targets/INST/tables/EventAction.dat +0 -0
  102. data/demo/config/targets/INST/tables/McConfigTable.csv +20 -0
  103. data/demo/config/targets/INST/tables/McConfigTable.dat +0 -0
  104. data/demo/config/targets/INST/target.txt +4 -0
  105. data/demo/config/targets/INST/tools/data_viewer/data_viewer.txt +2 -0
  106. data/demo/config/targets/INST/tools/data_viewer/data_viewer2.txt +2 -0
  107. data/demo/config/targets/INST/tools/table_manager/EventAction_def.txt +6 -0
  108. data/demo/config/targets/INST/tools/table_manager/McConfigTable_def.txt +38 -0
  109. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -3
  110. data/demo/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  111. data/demo/config/targets/{COSMOS/cmd_tlm/cosmos_server_cmds.txt → SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  112. data/demo/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  113. data/demo/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
  114. data/demo/config/targets/SYSTEM/lib/limits_groups.rb +39 -0
  115. data/demo/config/targets/SYSTEM/screens/status.txt +1 -1
  116. data/demo/config/targets/SYSTEM/target.txt +12 -0
  117. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +1 -1
  118. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +8 -5
  119. data/demo/config/targets/TEMPLATED/target.txt +2 -0
  120. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +15 -6
  121. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +13 -5
  122. data/demo/config/tools/data_viewer/data_viewer.txt +9 -0
  123. data/demo/config/tools/launcher/launcher.txt +9 -6
  124. data/demo/config/tools/launcher/launcher2.txt +16 -13
  125. data/demo/config/tools/launcher/launcher_mini.txt +45 -0
  126. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +12 -11
  127. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +12 -11
  128. data/demo/config/tools/test_runner/test_runner.txt +1 -1
  129. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  130. data/demo/lib/example_background_task.rb +9 -5
  131. data/demo/lib/example_target.rb +5 -15
  132. data/demo/lib/scpi_target.rb +4 -10
  133. data/demo/procedures/cosmos_api_test.rb +17 -0
  134. data/demo/tools/CmdSequence +16 -0
  135. data/demo/tools/CmdSequence.bat +9 -0
  136. data/demo/tools/ConfigEditor +16 -0
  137. data/demo/tools/ConfigEditor.bat +9 -0
  138. data/demo/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
  139. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
  140. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
  141. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
  142. data/demo/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
  143. data/ext/cosmos/ext/packet/packet.c +5 -5
  144. data/install/config/data/crc.txt +12 -8
  145. data/install/config/system/system.txt +13 -3
  146. data/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +14 -0
  147. data/install/config/targets/SYSTEM/target.txt +12 -0
  148. data/install/tools/CmdSequence +16 -0
  149. data/install/tools/CmdSequence.bat +9 -0
  150. data/install/tools/ConfigEditor +16 -0
  151. data/install/tools/ConfigEditor.bat +9 -0
  152. data/install/tools/mac/CmdSequence.app/Contents/Info.plist +38 -0
  153. data/install/tools/mac/CmdSequence.app/Contents/MacOS/CmdSequence.rb +16 -0
  154. data/install/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +10 -0
  155. data/install/tools/mac/CmdSequence.app/Contents/MacOS/tool_launch.rb +38 -0
  156. data/install/tools/mac/CmdSequence.app/Contents/Resources/appIcon.icns +0 -0
  157. data/lib/cosmos.rb +1 -1
  158. data/lib/cosmos/config/config_parser.rb +147 -59
  159. data/lib/cosmos/config/meta_config_parser.rb +57 -0
  160. data/lib/cosmos/conversions/polynomial_conversion.rb +20 -4
  161. data/lib/cosmos/conversions/unix_time_conversion.rb +4 -4
  162. data/lib/cosmos/core_ext/array.rb +45 -5
  163. data/lib/cosmos/core_ext/cosmos_io.rb +31 -15
  164. data/lib/cosmos/core_ext/file.rb +2 -2
  165. data/lib/cosmos/core_ext/kernel.rb +1 -6
  166. data/lib/cosmos/core_ext/objectspace.rb +0 -2
  167. data/lib/cosmos/core_ext/string.rb +27 -4
  168. data/lib/cosmos/core_ext/time.rb +39 -10
  169. data/lib/cosmos/gui/choosers/combobox_chooser.rb +37 -26
  170. data/lib/cosmos/gui/choosers/file_chooser.rb +23 -6
  171. data/lib/cosmos/gui/choosers/float_chooser.rb +13 -11
  172. data/lib/cosmos/gui/choosers/integer_chooser.rb +13 -11
  173. data/lib/cosmos/gui/choosers/string_chooser.rb +18 -36
  174. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +64 -64
  175. data/lib/cosmos/gui/choosers/value_chooser.rb +15 -15
  176. data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -13
  177. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +11 -3
  178. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +1 -1
  179. data/lib/cosmos/gui/dialogs/details_dialog.rb +1 -1
  180. data/lib/cosmos/gui/dialogs/exception_dialog.rb +7 -7
  181. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +20 -15
  182. data/lib/cosmos/gui/dialogs/interface_raw_dialog.rb +143 -0
  183. data/lib/cosmos/gui/dialogs/legal_dialog.rb +6 -5
  184. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +5 -2
  185. data/lib/cosmos/gui/dialogs/progress_dialog.rb +1 -1
  186. data/lib/cosmos/gui/dialogs/pry_dialog.rb +4 -4
  187. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +3 -0
  188. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +7 -6
  189. data/lib/cosmos/gui/dialogs/splash.rb +1 -1
  190. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +1 -1
  191. data/lib/cosmos/gui/dialogs/tlm_graph_dialog.rb +114 -0
  192. data/lib/cosmos/gui/line_graph/line_graph.rb +9 -10
  193. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +7 -5
  194. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +3 -7
  195. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +3 -8
  196. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +2 -7
  197. data/lib/cosmos/gui/line_graph/overview_graph.rb +6 -1
  198. data/lib/cosmos/gui/opengl/earth_model.rb +6 -3
  199. data/lib/cosmos/gui/opengl/gl_bounds.rb +11 -23
  200. data/lib/cosmos/gui/opengl/gl_light.rb +3 -4
  201. data/lib/cosmos/gui/opengl/gl_material.rb +3 -4
  202. data/lib/cosmos/gui/opengl/gl_scene.rb +10 -4
  203. data/lib/cosmos/gui/opengl/gl_shape.rb +6 -2
  204. data/lib/cosmos/gui/opengl/gl_viewer.rb +5 -5
  205. data/lib/cosmos/gui/opengl/gl_viewport.rb +11 -12
  206. data/lib/cosmos/gui/opengl/moon_model.rb +6 -3
  207. data/lib/cosmos/gui/opengl/stl_reader.rb +8 -9
  208. data/lib/cosmos/gui/opengl/stl_shape.rb +4 -5
  209. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +7 -7
  210. data/lib/cosmos/gui/qt.rb +1 -1
  211. data/lib/cosmos/gui/qt_tool.rb +21 -10
  212. data/lib/cosmos/gui/text/completion.rb +23 -2
  213. data/lib/cosmos/gui/text/completion_text_edit.rb +38 -23
  214. data/lib/cosmos/gui/utilities/analyze_log.rb +1 -1
  215. data/lib/cosmos/gui/utilities/screenshot.rb +2 -2
  216. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +11 -1
  217. data/lib/cosmos/gui/widgets/packet_log_frame.rb +19 -6
  218. data/lib/cosmos/interfaces.rb +10 -0
  219. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +28 -47
  220. data/lib/cosmos/interfaces/interface.rb +240 -22
  221. data/lib/cosmos/interfaces/linc_interface.rb +3 -5
  222. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +173 -0
  223. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +141 -0
  224. data/lib/cosmos/{streams/fixed_stream_protocol.rb → interfaces/protocols/fixed_protocol.rb} +40 -37
  225. data/lib/cosmos/{streams/length_stream_protocol.rb → interfaces/protocols/length_protocol.rb} +55 -48
  226. data/lib/cosmos/interfaces/protocols/override_protocol.rb +52 -0
  227. data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +141 -0
  228. data/lib/cosmos/interfaces/protocols/protocol.rb +60 -0
  229. data/lib/cosmos/interfaces/protocols/template_protocol.rb +209 -0
  230. data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +81 -0
  231. data/lib/cosmos/interfaces/serial_interface.rb +28 -23
  232. data/lib/cosmos/interfaces/simulated_target_interface.rb +27 -16
  233. data/lib/cosmos/interfaces/stream_interface.rb +36 -108
  234. data/lib/cosmos/interfaces/tcpip_client_interface.rb +21 -21
  235. data/lib/cosmos/interfaces/tcpip_server_interface.rb +555 -94
  236. data/lib/cosmos/interfaces/udp_interface.rb +51 -83
  237. data/lib/cosmos/io/buffered_file.rb +92 -2
  238. data/lib/cosmos/io/json_drb.rb +2 -2
  239. data/lib/cosmos/io/posix_serial_driver.rb +3 -1
  240. data/lib/cosmos/io/raw_logger.rb +3 -3
  241. data/lib/cosmos/io/serial_driver.rb +14 -5
  242. data/lib/cosmos/io/win32_serial_driver.rb +16 -4
  243. data/lib/cosmos/packet_logs.rb +0 -1
  244. data/lib/cosmos/packet_logs/packet_log_reader.rb +11 -1
  245. data/lib/cosmos/packet_logs/packet_log_writer.rb +31 -13
  246. data/lib/cosmos/packets/binary_accessor.rb +599 -32
  247. data/lib/cosmos/packets/commands.rb +48 -24
  248. data/lib/cosmos/packets/packet.rb +140 -54
  249. data/lib/cosmos/packets/packet_config.rb +0 -2
  250. data/lib/cosmos/packets/parsers/packet_item_parser.rb +10 -2
  251. data/lib/cosmos/packets/structure.rb +81 -33
  252. data/lib/cosmos/packets/structure_item.rb +45 -5
  253. data/lib/cosmos/packets/telemetry.rb +149 -55
  254. data/lib/cosmos/script/api_shared.rb +1000 -0
  255. data/lib/cosmos/script/commands.rb +2 -2
  256. data/lib/cosmos/script/extract.rb +19 -4
  257. data/lib/cosmos/script/limits.rb +2 -0
  258. data/lib/cosmos/script/script.rb +1 -1
  259. data/lib/cosmos/script/scripting.rb +4 -784
  260. data/lib/cosmos/script/telemetry.rb +44 -23
  261. data/lib/cosmos/script/tools.rb +15 -69
  262. data/lib/cosmos/streams/serial_stream.rb +12 -19
  263. data/lib/cosmos/streams/stream.rb +2 -11
  264. data/lib/cosmos/streams/tcpip_socket_stream.rb +3 -13
  265. data/lib/cosmos/system/system.rb +187 -31
  266. data/lib/cosmos/system/target.rb +11 -2
  267. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +12 -11
  268. data/lib/cosmos/tools/cmd_sender/{cmd_sender_item_delegate.rb → cmd_param_table_item_delegate.rb} +11 -10
  269. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +209 -164
  270. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +652 -0
  271. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +510 -0
  272. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +194 -0
  273. data/lib/cosmos/tools/cmd_tlm_server/api.rb +179 -5
  274. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +31 -14
  275. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +23 -16
  276. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +92 -20
  277. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +1 -1
  278. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -4
  279. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +0 -5
  280. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +1 -2
  281. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +4 -4
  282. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +121 -0
  283. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +8 -4
  284. data/lib/cosmos/tools/config_editor/config_editor.rb +720 -0
  285. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +675 -0
  286. data/lib/cosmos/tools/data_viewer/data_viewer.rb +44 -27
  287. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +8 -22
  288. data/lib/cosmos/tools/launcher/launcher.rb +29 -12
  289. data/lib/cosmos/tools/launcher/launcher_config.rb +1 -1
  290. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +153 -42
  291. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +44 -6
  292. data/lib/cosmos/tools/replay/replay.rb +36 -20
  293. data/lib/cosmos/tools/replay/replay_server.rb +1 -1
  294. data/lib/cosmos/tools/script_runner/script_runner_config.rb +1 -1
  295. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +31 -21
  296. data/lib/cosmos/tools/table_manager/table_config.rb +9 -3
  297. data/lib/cosmos/tools/table_manager/table_manager.rb +27 -7
  298. data/lib/cosmos/tools/test_runner/results_writer.rb +6 -6
  299. data/lib/cosmos/tools/test_runner/test_runner.rb +4 -6
  300. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +4 -5
  301. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -1
  302. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +1 -1
  303. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +23 -6
  304. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +44 -3
  305. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +20 -7
  306. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1 -1
  307. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +11 -4
  308. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +2 -2
  309. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +1 -1
  310. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +16 -0
  311. data/lib/cosmos/tools/tlm_viewer/screen.rb +36 -32
  312. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +59 -50
  313. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +2 -2
  314. data/lib/cosmos/tools/tlm_viewer/widgets.rb +1 -0
  315. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +1 -0
  316. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +22 -4
  317. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +9 -0
  318. data/lib/cosmos/tools/tlm_viewer/widgets/spacer_widget.rb +55 -0
  319. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +3 -2
  320. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +3 -2
  321. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +12 -12
  322. data/lib/cosmos/top_level.rb +34 -24
  323. data/lib/cosmos/utilities/crc.rb +108 -6
  324. data/lib/cosmos/utilities/csv.rb +68 -14
  325. data/lib/cosmos/utilities/logger.rb +2 -2
  326. data/lib/cosmos/utilities/low_fragmentation_array.rb +9 -1
  327. data/lib/cosmos/version.rb +6 -6
  328. data/lib/cosmos/win32/win32_main.rb +50 -46
  329. data/run_gui_tests.bat +3 -1
  330. data/spec/conversions/unix_time_formatted_conversion_spec.rb +2 -2
  331. data/spec/conversions/unix_time_seconds_conversion_spec.rb +2 -2
  332. data/spec/core_ext/file_spec.rb +1 -1
  333. data/spec/core_ext/objectspace_spec.rb +12 -9
  334. data/spec/core_ext/string_spec.rb +6 -0
  335. data/spec/core_ext/time_spec.rb +10 -0
  336. data/spec/gui/line_graph/line_clip_spec.rb +226 -224
  337. data/spec/gui/qt_spec.rb +81 -79
  338. data/spec/install/config/system/system.txt +0 -6
  339. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +5 -5
  340. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +8 -8
  341. data/spec/install/config/targets/SYSTEM/cmd_tlm/meta_cmd_tlm.txt +16 -0
  342. data/{install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt → spec/install/config/targets/SYSTEM/cmd_tlm/system_cmds.txt} +8 -8
  343. data/spec/install/config/targets/SYSTEM/cmd_tlm/system_tlm.txt +7 -0
  344. data/spec/install/config/targets/{COSMOS → SYSTEM}/cmd_tlm_server.txt +2 -2
  345. data/spec/install/config/targets/SYSTEM/screens/status.txt +12 -0
  346. data/spec/install/config/targets/SYSTEM/target.txt +12 -0
  347. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +9 -13
  348. data/spec/interfaces/interface_spec.rb +402 -18
  349. data/spec/interfaces/linc_interface_spec.rb +37 -39
  350. data/spec/interfaces/protocols/burst_protocol_spec.rb +300 -0
  351. data/spec/interfaces/protocols/crc_protocol_spec.rb +709 -0
  352. data/spec/interfaces/protocols/fixed_protocol_spec.rb +119 -0
  353. data/spec/interfaces/protocols/length_protocol_spec.rb +499 -0
  354. data/spec/interfaces/protocols/override_protocol_spec.rb +158 -0
  355. data/spec/interfaces/protocols/preidentified_protocol_spec.rb +149 -0
  356. data/spec/interfaces/protocols/template_protocol_spec.rb +218 -0
  357. data/spec/interfaces/protocols/terminated_protocol_spec.rb +174 -0
  358. data/spec/interfaces/serial_interface_spec.rb +35 -34
  359. data/spec/interfaces/simulated_target_interface_spec.rb +13 -13
  360. data/spec/interfaces/tcpip_client_interface_spec.rb +21 -16
  361. data/spec/interfaces/tcpip_server_interface_spec.rb +66 -69
  362. data/spec/interfaces/udp_interface_spec.rb +120 -55
  363. data/spec/io/serial_driver_spec.rb +41 -39
  364. data/spec/io/udp_sockets_spec.rb +13 -8
  365. data/spec/io/win32_serial_driver_spec.rb +62 -59
  366. data/spec/packet_logs/packet_log_reader_spec.rb +68 -47
  367. data/spec/packet_logs/packet_log_writer_spec.rb +7 -5
  368. data/spec/packets/commands_spec.rb +5 -5
  369. data/spec/packets/packet_spec.rb +2 -14
  370. data/spec/script/extract_spec.rb +21 -7
  371. data/spec/script/scripting_spec.rb +261 -6
  372. data/spec/script/telemetry_spec.rb +17 -9
  373. data/spec/spec_helper.rb +26 -10
  374. data/spec/streams/serial_stream_spec.rb +87 -82
  375. data/spec/streams/tcpip_client_stream_spec.rb +12 -4
  376. data/spec/streams/tcpip_socket_stream_spec.rb +5 -0
  377. data/spec/system/system_spec.rb +66 -50
  378. data/spec/system/target_spec.rb +33 -11
  379. data/spec/tools/cmd_tlm_server/api_spec.rb +5 -5
  380. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +75 -15
  381. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +125 -5
  382. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +244 -232
  383. data/spec/tools/cmd_tlm_server/commanding_spec.rb +18 -18
  384. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +124 -29
  385. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +2 -2
  386. data/spec/tools/cmd_tlm_server/limits_groups_background_task_spec.rb +145 -0
  387. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +50 -10
  388. data/spec/tools/table_manager/tablemanager_core_spec.rb +0 -1
  389. data/spec/top_level/top_level_spec.rb +39 -11
  390. data/spec/utilities/csv_spec.rb +62 -20
  391. data/tasks/gemfile_stats.rake +6 -3
  392. data/test/performance/config/system/system_packets.txt +0 -1
  393. data/test/performance/config/system/system_threads.txt +0 -1
  394. metadata +177 -92
  395. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  396. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
  397. data/autohotkey/config/targets/COSMOS/target.txt +0 -5
  398. data/autohotkey/userpath.txt +0 -1
  399. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  400. data/demo/config/targets/COSMOS/screens/limits_change.txt +0 -20
  401. data/demo/config/targets/COSMOS/screens/version.txt +0 -19
  402. data/demo/config/targets/COSMOS/target.txt +0 -11
  403. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +0 -10
  404. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +0 -13
  405. data/demo/userpath.txt +0 -1
  406. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  407. data/install/config/targets/COSMOS/cmd_tlm_server.txt +0 -6
  408. data/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
  409. data/install/config/targets/COSMOS/screens/version.txt +0 -19
  410. data/install/config/targets/COSMOS/target.txt +0 -9
  411. data/install/config/targets/SYSTEM/README.txt +0 -1
  412. data/install/userpath.txt +0 -1
  413. data/lib/cosmos/io/tcpip_server.rb +0 -571
  414. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +0 -107
  415. data/lib/cosmos/streams/burst_stream_protocol.rb +0 -25
  416. data/lib/cosmos/streams/preidentified_stream_protocol.rb +0 -118
  417. data/lib/cosmos/streams/stream_protocol.rb +0 -373
  418. data/lib/cosmos/streams/template_stream_protocol.rb +0 -140
  419. data/lib/cosmos/streams/terminated_stream_protocol.rb +0 -85
  420. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +0 -41
  421. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +0 -15
  422. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +0 -20
  423. data/spec/install/config/targets/COSMOS/screens/version.txt +0 -19
  424. data/spec/install/config/targets/COSMOS/target.txt +0 -5
  425. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +0 -4
  426. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +0 -4
  427. data/spec/install/userpath.txt +0 -1
  428. data/spec/interfaces/stream_interface_spec.rb +0 -157
  429. data/spec/io/tcpip_server_spec.rb +0 -338
  430. data/spec/packet_logs/meta_packet_log_writer_spec.rb +0 -170
  431. data/spec/streams/burst_stream_protocol_spec.rb +0 -32
  432. data/spec/streams/fixed_stream_protocol_spec.rb +0 -113
  433. data/spec/streams/length_stream_protocol_spec.rb +0 -300
  434. data/spec/streams/preidentified_stream_protocol_spec.rb +0 -121
  435. data/spec/streams/stream_protocol_spec.rb +0 -346
  436. data/spec/streams/template_stream_protocol_spec.rb +0 -156
  437. data/spec/streams/terminated_stream_protocol_spec.rb +0 -127
  438. data/test/performance/userpath.txt +0 -1
@@ -8,7 +8,7 @@
8
8
  # as published by the Free Software Foundation; version 3 with
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
- require 'cosmos/ext/packet'
11
+ require 'cosmos/ext/packet' if RUBY_ENGINE == 'ruby' and !ENV['COSMOS_NO_EXT']
12
12
 
13
13
  module Cosmos
14
14
 
@@ -190,10 +190,50 @@ module Cosmos
190
190
  verify_overall() if @structure_item_constructed
191
191
  end
192
192
 
193
- # Comparison Operator based on bit_offset. This means that StructureItems
194
- # with different names or bit sizes are equal if they have the same bit
195
- # offset.
196
- # def <=>(other_item)
193
+ if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
194
+ # Comparison Operator based on bit_offset. This means that StructureItems
195
+ # with different names or bit sizes are equal if they have the same bit
196
+ # offset.
197
+ def <=>(other_item)
198
+ other_bit_offset = other_item.bit_offset
199
+ other_bit_size = other_item.bit_size
200
+
201
+ # Handle same bit offset case
202
+ if (@bit_offset == 0) && (other_bit_offset == 0)
203
+ # Both bit_offsets are 0 so sort by bit_size
204
+ # This allows derived items with bit_size of 0 to be listed first
205
+ # Compare based on bit size
206
+ if @bit_size == other_bit_size
207
+ return 0
208
+ elsif @bit_size < other_bit_size
209
+ return -1
210
+ else
211
+ return 1
212
+ end
213
+ end
214
+
215
+ # Handle different bit offsets
216
+ if ((@bit_offset >= 0) && (other_bit_offset >= 0)) || ((@bit_offset < 0) && (other_bit_offset < 0))
217
+ # Both Have Same Sign
218
+ if @bit_offset == other_bit_offset
219
+ return 0
220
+ elsif @bit_offset < other_bit_offset
221
+ return -1
222
+ else
223
+ return 1
224
+ end
225
+ else
226
+ # Different Signs
227
+ if @bit_offset == other_bit_offset
228
+ return 0
229
+ elsif @bit_offset < other_bit_offset
230
+ return 1
231
+ else
232
+ return -1
233
+ end
234
+ end
235
+ end
236
+ end
197
237
 
198
238
  # Make a light weight clone of this item
199
239
  def clone
@@ -9,7 +9,7 @@
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
11
  require 'cosmos/packets/packet_config'
12
- require 'cosmos/ext/telemetry'
12
+ require 'cosmos/ext/telemetry' if RUBY_ENGINE == 'ruby' and !ENV['COSMOS_NO_EXT']
13
13
 
14
14
  module Cosmos
15
15
 
@@ -46,16 +46,114 @@ module Cosmos
46
46
  return result
47
47
  end
48
48
 
49
- # @param target_name [String] The target name
50
- # @return [Hash<packet_name=>Packet>] Hash of the telemetry packets for the given
51
- # target name keyed by the packet name
52
- # def packets(target_name)
49
+ if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
50
+ # @param target_name [String] The target name
51
+ # @return [Hash<packet_name=>Packet>] Hash of the telemetry packets for the given
52
+ # target name keyed by the packet name
53
+ def packets(target_name)
54
+ upcase_target_name = target_name.to_s.upcase
55
+ target_packets = @config.telemetry[upcase_target_name]
56
+ raise "Telemetry target '#{upcase_target_name}' does not exist" unless target_packets
57
+ target_packets
58
+ end
53
59
 
54
- # @param target_name [String] The target name
55
- # @param packet_name [String] The packet name. Must be a defined packet name
56
- # and not 'LATEST'.
57
- # @return [Packet] The telemetry packet for the given target and packet name
58
- # def packet(target_name, packet_name)
60
+ # @param target_name [String] The target name
61
+ # @param packet_name [String] The packet name. Must be a defined packet name
62
+ # and not 'LATEST'.
63
+ # @return [Packet] The telemetry packet for the given target and packet name
64
+ def packet(target_name, packet_name)
65
+ target_packets = packets(target_name)
66
+ upcase_packet_name = packet_name.to_s.upcase
67
+ packet = target_packets[upcase_packet_name]
68
+ unless packet
69
+ upcase_target_name = target_name.to_s.upcase
70
+ raise "Telemetry packet '#{upcase_target_name} #{upcase_packet_name}' does not exist"
71
+ end
72
+ packet
73
+ end
74
+
75
+ # @param target_name (see #packet)
76
+ # @param packet_name [String] The packet name. 'LATEST' can also be given
77
+ # to specify the last received (or defined if no packets have been
78
+ # received) packet within the given target that contains the
79
+ # item_name.
80
+ # @param item_name [String] The item name
81
+ # @return [Packet, PacketItem] The packet and the packet item
82
+ def packet_and_item(target_name, packet_name, item_name)
83
+ upcase_packet_name = packet_name.to_s.upcase
84
+ if upcase_packet_name == "LATEST".freeze
85
+ return_packet = newest_packet(target_name, item_name)
86
+ else
87
+ return_packet = packet(target_name, packet_name)
88
+ end
89
+ item = return_packet.get_item(item_name)
90
+ return [return_packet, item]
91
+ end
92
+
93
+ # Return a telemetry value from a packet.
94
+ #
95
+ # @param target_name (see #packet_and_item)
96
+ # @param packet_name (see #packet_and_item)
97
+ # @param item_name (see #packet_and_item)
98
+ # @param value_type [Symbol] How to convert the item before returning.
99
+ # Must be one of {Packet::VALUE_TYPES}
100
+ # @return The value. :FORMATTED and :WITH_UNITS values are always returned
101
+ # as Strings. :RAW values will match their data_type. :CONVERTED values
102
+ # can be any type.
103
+ def value(target_name, packet_name, item_name, value_type = :CONVERTED)
104
+ packet, _ = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
105
+ return packet.read(item_name, value_type)
106
+ end
107
+
108
+ # Reads the specified list of items and returns their values and limits
109
+ # state.
110
+ #
111
+ # @param item_array [Array<Array(String String String)>] An array
112
+ # consisting of [target name, packet name, item name]
113
+ # @param value_types [Symbol|Array<Symbol>] How to convert the items before
114
+ # returning. A single symbol of {Packet::VALUE_TYPES}
115
+ # can be passed which will convert all items the same way. Or
116
+ # an array of symbols can be passed to control how each item is
117
+ # converted.
118
+ # @return [Array, Array, Array] The first array contains the item values and the
119
+ # second their limits state, and the third their limits settings which includes
120
+ # the red, yellow, and green (if given) limits values.
121
+ def values_and_limits_states(item_array, value_types = :CONVERTED)
122
+ items = []
123
+
124
+ # Verify item_array is a nested array
125
+ raise(ArgumentError, "item_array must be a nested array consisting of [[tgt,pkt,item],[tgt,pkt,item],...]") unless Array === item_array[0]
126
+
127
+ states = []
128
+ settings = []
129
+ limits_set = System.limits_set
130
+
131
+ raise(ArgumentError, "Passed #{item_array.length} items but only #{value_types.length} value types") if (Array === value_types) and item_array.length != value_types.length
132
+
133
+ value_type = value_types.intern unless Array === value_types
134
+ item_array.length.times do |index|
135
+ entry = item_array[index]
136
+ target_name = entry[0]
137
+ packet_name = entry[1]
138
+ item_name = entry[2]
139
+ value_type = value_types[index].intern if Array === value_types
140
+
141
+ packet, item = packet_and_item(target_name, packet_name, item_name) # Handles LATEST
142
+ items << packet.read(item_name, value_type)
143
+ limits = item.limits
144
+ states << limits.state
145
+ limits_values = limits.values
146
+ if limits_values
147
+ limits_settings = limits_values[limits_set]
148
+ else
149
+ limits_settings = nil
150
+ end
151
+ settings << limits_settings
152
+ end
153
+
154
+ return [items, states, settings]
155
+ end
156
+ end
59
157
 
60
158
  # @param target_name (see #packet)
61
159
  # @param packet_name (see #packet)
@@ -81,27 +179,6 @@ module Cosmos
81
179
  item_names
82
180
  end
83
181
 
84
- # @param target_name (see #packet)
85
- # @param packet_name [String] The packet name. 'LATEST' can also be given
86
- # to specify the last received (or defined if no packets have been
87
- # received) packet within the given target that contains the
88
- # item_name.
89
- # @param item_name [String] The item name
90
- # @return [Packet, PacketItem] The packet and the packet item
91
- # def packet_and_item(target_name, packet_name, item_name)
92
-
93
- # Return a telemetry value from a packet.
94
- #
95
- # @param target_name (see #packet_and_item)
96
- # @param packet_name (see #packet_and_item)
97
- # @param item_name (see #packet_and_item)
98
- # @param value_type [Symbol] How to convert the item before returning.
99
- # Must be one of {Packet::VALUE_TYPES}
100
- # @return The value. :FORMATTED and :WITH_UNITS values are always returned
101
- # as Strings. :RAW values will match their data_type. :CONVERTED values
102
- # can be any type.
103
- # def value(target_name, packet_name, item_name, value_type = :CONVERTED)
104
-
105
182
  # Set a telemetry value in a packet.
106
183
  #
107
184
  # @param target_name (see #packet_and_item)
@@ -173,8 +250,19 @@ module Cosmos
173
250
  # @return [Packet] The identified packet with its data set to the given
174
251
  # packet_data buffer. Returns nil if no packet could be identified.
175
252
  def identify!(packet_data, target_names = nil)
176
- identified_packet = nil
253
+ identified_packet = identify(packet_data, target_names)
254
+ identified_packet.buffer = packet_data if identified_packet
255
+ return identified_packet
256
+ end
177
257
 
258
+ # Finds a packet from the Current Value Table that matches the given data
259
+ # and returns it. Does not fill the packets buffer. Use identify! to update the CVT.
260
+ #
261
+ # @param packet_data [String] The binary packet data buffer
262
+ # @param target_names [Array<String>] List of target names to limit the search. The
263
+ # default value of nil means to search all known targets.
264
+ # @return [Packet] The identified packet, Returns nil if no packet could be identified.
265
+ def identify(packet_data, target_names = nil)
178
266
  target_names = target_names() unless target_names
179
267
 
180
268
  target_names.each do |target_name|
@@ -188,15 +276,36 @@ module Cosmos
188
276
 
189
277
  # Iterate through the packets and see if any represent the buffer
190
278
  target_packets.each do |packet_name, packet|
191
- if packet.identify?(packet_data)
192
- identified_packet = packet
193
- identified_packet.buffer = packet_data
194
- break
195
- end
279
+ return packet if packet.identify?(packet_data)
196
280
  end
197
- break if identified_packet
198
281
  end
199
- return identified_packet
282
+
283
+ return nil
284
+ end
285
+
286
+ def identify_and_define_packet(packet, target_names = nil)
287
+ if !packet.identified?
288
+ identified_packet = identify(packet.buffer(false), target_names)
289
+ return nil unless identified_packet
290
+ identified_packet = identified_packet.clone
291
+ identified_packet.buffer = packet.buffer
292
+ identified_packet.received_time = packet.received_time
293
+ return identified_packet
294
+ end
295
+
296
+ if !packet.defined?
297
+ begin
298
+ identified_packet = self.packet(packet.target_name, packet.packet_name)
299
+ rescue RuntimeError
300
+ return nil
301
+ end
302
+ identified_packet = identified_packet.clone
303
+ identified_packet.buffer = packet.buffer
304
+ identified_packet.received_time = packet.received_time
305
+ return identified_packet
306
+ end
307
+
308
+ return packet
200
309
  end
201
310
 
202
311
  # Updates the specified packet with the given packet data. Raises an error
@@ -227,28 +336,13 @@ module Cosmos
227
336
  end
228
337
  end
229
338
 
230
- # Reads the specified list of items and returns their values and limits
231
- # state.
232
- #
233
- # @param item_array [Array<Array(String String String)>] An array
234
- # consisting of [target name, packet name, item name]
235
- # @param value_types [Symbol|Array<Symbol>] How to convert the items before
236
- # returning. A single symbol of {Packet::VALUE_TYPES}
237
- # can be passed which will convert all items the same way. Or
238
- # an array of symbols can be passed to control how each item is
239
- # converted.
240
- # @return [Array, Array, Array] The first array contains the item values and the
241
- # second their limits state, and the third their limits settings which includes
242
- # the red, yellow, and green (if given) limits values.
243
- # def values_and_limits_states(item_array, value_types = :CONVERTED)
244
-
245
339
  # Iterates through all the telemetry packets and marks them stale if they
246
340
  # haven't been received for over the System.staleness_seconds value.
247
341
  #
248
342
  # @return [Array(Packet)] Array of the stale packets
249
343
  def check_stale
250
344
  stale = []
251
- time = Time.now
345
+ time = Time.now.sys
252
346
  @config.telemetry.each do |target_name, target_packets|
253
347
  target_packets.each do |packet_name, packet|
254
348
  if packet.received_time and (!packet.stale) and (time - packet.received_time > System.staleness_seconds)
@@ -0,0 +1,1000 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2017 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
+ module Cosmos
12
+ module ApiShared
13
+ DEFAULT_TLM_POLLING_RATE = 0.25
14
+
15
+ private
16
+
17
+ # Get a packet which was previously subscribed to by
18
+ # subscribe_packet_data. This method can block waiting for new packets or
19
+ # not based on the second parameter. It returns a single Cosmos::Packet instance
20
+ # and will return nil when no more packets are buffered (assuming non_block
21
+ # is false).
22
+ # Usage:
23
+ # get_packet(id, <true or false to block>)
24
+ def get_packet(id, non_block = false)
25
+ packet = nil
26
+ buffer, target_name, packet_name, received_time, received_count = get_packet_data(id, non_block)
27
+ if buffer
28
+ packet = System.telemetry.packet(target_name, packet_name).clone
29
+ packet.buffer = buffer
30
+ packet.received_time = received_time
31
+ packet.received_count = received_count
32
+ end
33
+ packet
34
+ end
35
+
36
+ # Creates a string with the parameters upcased
37
+ def _upcase(target_name, packet_name, item_name)
38
+ "#{target_name.upcase} #{packet_name.upcase} #{item_name.upcase}"
39
+ end
40
+
41
+ # Implementaton of the various check commands. It yields back to the
42
+ # caller to allow the return of the value through various telemetry calls.
43
+ # This method should not be called directly by application code.
44
+ def _check(*args)
45
+ target_name, packet_name, item_name, comparison_to_eval = check_process_args(args, 'check')
46
+ value = yield(target_name, packet_name, item_name)
47
+ if comparison_to_eval
48
+ check_eval(target_name, packet_name, item_name, comparison_to_eval, value)
49
+ else
50
+ Logger.info "CHECK: #{_upcase(target_name, packet_name, item_name)} == #{value}"
51
+ end
52
+ end
53
+
54
+ # Check the converted value of a telmetry item against a condition
55
+ # Always print the value of the telemetry item to STDOUT
56
+ # If the condition check fails, raise an error
57
+ # Supports two signatures:
58
+ # check(target_name, packet_name, item_name, comparison_to_eval)
59
+ # or
60
+ # check('target_name packet_name item_name > 1')
61
+ def check(*args)
62
+ _check(*args) {|tgt,pkt,item| tlm(tgt,pkt,item) }
63
+ end
64
+
65
+ # Check the formatted value of a telmetry item against a condition
66
+ # Always print the value of the telemetry item to STDOUT
67
+ # If the condition check fails, raise an error
68
+ # Supports two signatures:
69
+ # check(target_name, packet_name, item_name, comparison_to_eval)
70
+ # or
71
+ # check('target_name packet_name item_name > 1')
72
+ def check_formatted(*args)
73
+ _check(*args) {|tgt,pkt,item| tlm_formatted(tgt,pkt,item) }
74
+ end
75
+
76
+ # Check the formatted with units value of a telmetry item against a condition
77
+ # Always print the value of the telemetry item to STDOUT
78
+ # If the condition check fails, raise an error
79
+ # Supports two signatures:
80
+ # check(target_name, packet_name, item_name, comparison_to_eval)
81
+ # or
82
+ # check('target_name packet_name item_name > 1')
83
+ def check_with_units(*args)
84
+ _check(*args) {|tgt,pkt,item| tlm_with_units(tgt,pkt,item) }
85
+ end
86
+
87
+ # Check the raw value of a telmetry item against a condition
88
+ # Always print the value of the telemetry item to STDOUT
89
+ # If the condition check fails, raise an error
90
+ # Supports two signatures:
91
+ # check(target_name, packet_name, item_name, comparison_to_eval)
92
+ # or
93
+ # check('target_name packet_name item_name > 1')
94
+ def check_raw(*args)
95
+ _check(*args) {|tgt,pkt,item| tlm_raw(tgt,pkt,item) }
96
+ end
97
+
98
+ # Executes the passed method and expects an exception to be raised.
99
+ # Raises a CheckError if an Exception is not raised.
100
+ # Usage:
101
+ # check_exception(method_name, method_params}
102
+ def check_exception(method_name, *method_params)
103
+ begin
104
+ send(method_name, *method_params)
105
+ rescue Exception => error
106
+ Logger.info "CHECK: #{method_name}(#{method_params.join(", ")}) raised #{error.class}:#{error.message}"
107
+ else
108
+ raise(CheckError, "#{method_name}(#{method_params.join(", ")}) should have raised an exception but did not.")
109
+ end
110
+ end
111
+
112
+ def _check_tolerance(*args)
113
+ target_name, packet_name, item_name, expected_value, tolerance =
114
+ check_tolerance_process_args(args, 'check_tolerance')
115
+ value = yield(target_name, packet_name, item_name)
116
+ if value.is_a?(Array)
117
+ expected_value, tolerance = array_tolerance_process_args(value.size, expected_value, tolerance, 'check_tolerance')
118
+
119
+ message = ""
120
+ all_checks_ok = true
121
+ value.size.times do |i|
122
+ range = (expected_value[i]-tolerance[i]..expected_value[i]+tolerance[i])
123
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}[#{i}]"
124
+ range_str = "range #{range.first} to #{range.last} with value == #{value[i]}"
125
+ if range.include?(value[i])
126
+ message << "#{check_str} was within #{range_str}\n"
127
+ else
128
+ message << "#{check_str} failed to be within #{range_str}\n"
129
+ all_checks_ok = false
130
+ end
131
+ end
132
+
133
+ if all_checks_ok
134
+ Logger.info message
135
+ else
136
+ if $cmd_tlm_disconnect
137
+ Logger.error message
138
+ else
139
+ raise CheckError, message
140
+ end
141
+ end
142
+ else
143
+ range = (expected_value - tolerance)..(expected_value + tolerance)
144
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}"
145
+ range_str = "range #{range.first} to #{range.last} with value == #{value}"
146
+ if range.include?(value)
147
+ Logger.info "#{check_str} was within #{range_str}"
148
+ else
149
+ message = "#{check_str} failed to be within #{range_str}"
150
+ if $cmd_tlm_disconnect
151
+ Logger.error message
152
+ else
153
+ raise CheckError, message
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ # Check the converted value of a telmetry item against an expected value with a tolerance
160
+ # Always print the value of the telemetry item to STDOUT
161
+ # If the condition check fails, raise an error
162
+ # Supports two signatures:
163
+ # check_tolerance(target_name, packet_name, item_name, expected_value, tolerance)
164
+ # or
165
+ # check_tolerance('target_name packet_name item_name', expected_value, tolerance)
166
+ def check_tolerance(*args)
167
+ _check_tolerance(*args) {|tgt,pkt,item| tlm(tgt,pkt,item) }
168
+ end
169
+
170
+ # Check the raw value of a telmetry item against an expected value with a tolerance
171
+ # Always print the value of the telemetry item to STDOUT
172
+ # If the condition check fails, raise an error
173
+ # Supports two signatures:
174
+ # check_tolerance_raw(target_name, packet_name, item_name, expected_value, tolerance)
175
+ # or
176
+ # check_tolerance_raw('target_name packet_name item_name', expected_value, tolerance)
177
+ def check_tolerance_raw(*args)
178
+ _check_tolerance(*args) {|tgt,pkt,item| tlm_raw(tgt,pkt,item) }
179
+ end
180
+
181
+ # Check to see if an expression is true without waiting. If the expression
182
+ # is not true, the script will pause.
183
+ def check_expression(exp_to_eval, context = nil)
184
+ success = cosmos_script_wait_implementation_expression(exp_to_eval, 0, DEFAULT_TLM_POLLING_RATE, context)
185
+ if success
186
+ Logger.info "CHECK: #{exp_to_eval} is TRUE"
187
+ else
188
+ message = "CHECK: #{exp_to_eval} is FALSE"
189
+ if $cmd_tlm_disconnect
190
+ Logger.error message
191
+ else
192
+ raise CheckError, message
193
+ end
194
+ end
195
+ end
196
+
197
+ # Wait on an expression to be true. On a timeout, the script will continue.
198
+ # Supports multiple signatures:
199
+ # wait(time)
200
+ # wait('target_name packet_name item_name > 1', timeout, polling_rate)
201
+ # wait('target_name', 'packet_name', 'item_name', comparison_to_eval, timeout, polling_rate)
202
+ def wait(*args)
203
+ wait_process_args(args, 'wait', :CONVERTED)
204
+ end
205
+
206
+ # Wait on an expression to be true. On a timeout, the script will continue.
207
+ # Supports multiple signatures:
208
+ # wait(time)
209
+ # wait_raw('target_name packet_name item_name > 1', timeout, polling_rate)
210
+ # wait_raw('target_name', 'packet_name', 'item_name', comparison_to_eval, timeout, polling_rate)
211
+ def wait_raw(*args)
212
+ wait_process_args(args, 'wait_raw', :RAW)
213
+ end
214
+
215
+ def _wait_tolerance(raw, *args)
216
+ type = (raw ? :RAW : :CONVERTED)
217
+ type_string = 'wait_tolerance'
218
+ type_string << '_raw' if raw
219
+ target_name, packet_name, item_name, expected_value, tolerance, timeout, polling_rate = wait_tolerance_process_args(args, type_string)
220
+ start_time = Time.now.sys
221
+ value = tlm_variable(target_name, packet_name, item_name, type)
222
+ if value.is_a?(Array)
223
+ expected_value, tolerance = array_tolerance_process_args(value.size, expected_value, tolerance, type_string)
224
+
225
+ success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate)
226
+ time = Time.now.sys - start_time
227
+
228
+ message = ""
229
+ value.size.times do |i|
230
+ range = (expected_value[i]-tolerance[i]..expected_value[i]+tolerance[i])
231
+ wait_str = "WAIT: #{_upcase(target_name, packet_name, item_name)}[#{i}]"
232
+ range_str = "range #{range.first} to #{range.last} with value == #{value[i]} after waiting #{time} seconds"
233
+ if range.include?(value[i])
234
+ message << "#{wait_str} was within #{range_str}\n"
235
+ else
236
+ message << "#{wait_str} failed to be within #{range_str}\n"
237
+ end
238
+ end
239
+
240
+ if success
241
+ Logger.info message
242
+ else
243
+ Logger.warn message
244
+ end
245
+ else
246
+ success, value = cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate)
247
+ time = Time.now.sys - start_time
248
+ range = (expected_value - tolerance)..(expected_value + tolerance)
249
+ wait_str = "WAIT: #{_upcase(target_name, packet_name, item_name)}"
250
+ range_str = "range #{range.first} to #{range.last} with value == #{value} after waiting #{time} seconds"
251
+ if success
252
+ Logger.info "#{wait_str} was within #{range_str}"
253
+ else
254
+ Logger.warn "#{wait_str} failed to be within #{range_str}"
255
+ end
256
+ end
257
+ time
258
+ end
259
+
260
+ # Wait on an expression to be true. On a timeout, the script will continue.
261
+ # Supports multiple signatures:
262
+ # wait_tolerance('target_name packet_name item_name', expected_value, tolerance, timeout, polling_rate)
263
+ # wait_tolerance('target_name', 'packet_name', 'item_name', expected_value, tolerance, timeout, polling_rate)
264
+ def wait_tolerance(*args)
265
+ _wait_tolerance(false, *args)
266
+ end
267
+
268
+ # Wait on an expression to be true. On a timeout, the script will continue.
269
+ # Supports multiple signatures:
270
+ # wait_tolerance_raw('target_name packet_name item_name', expected_value, tolerance, timeout, polling_rate)
271
+ # wait_tolerance_raw('target_name', 'packet_name', 'item_name', expected_value, tolerance, timeout, polling_rate)
272
+ def wait_tolerance_raw(*args)
273
+ _wait_tolerance(true, *args)
274
+ end
275
+
276
+ # Wait on a custom expression to be true
277
+ def wait_expression(exp_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, context = nil)
278
+ start_time = Time.now.sys
279
+ success = cosmos_script_wait_implementation_expression(exp_to_eval, timeout, polling_rate, context)
280
+ time = Time.now.sys - start_time
281
+ if success
282
+ Logger.info "WAIT: #{exp_to_eval} is TRUE after waiting #{time} seconds"
283
+ else
284
+ Logger.warn "WAIT: #{exp_to_eval} is FALSE after waiting #{time} seconds"
285
+ end
286
+ time
287
+ end
288
+
289
+ def _wait_check(raw, *args)
290
+ type = (raw ? :RAW : :CONVERTED)
291
+ target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate = wait_check_process_args(args, 'wait_check')
292
+ start_time = Time.now.sys
293
+ success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, type, comparison_to_eval, timeout, polling_rate)
294
+ time = Time.now.sys - start_time
295
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
296
+ with_value_str = "with value == #{value} after waiting #{time} seconds"
297
+ if success
298
+ Logger.info "#{check_str} success #{with_value_str}"
299
+ else
300
+ message = "#{check_str} failed #{with_value_str}"
301
+ if $cmd_tlm_disconnect
302
+ Logger.error message
303
+ else
304
+ raise CheckError, message
305
+ end
306
+ end
307
+ time
308
+ end
309
+
310
+ # Wait for the converted value of a telmetry item against a condition or for a timeout
311
+ # and then check against the condition
312
+ # Supports two signatures:
313
+ # wait_check(target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate)
314
+ # or
315
+ # wait_check('target_name packet_name item_name > 1', timeout, polling_rate)
316
+ def wait_check(*args)
317
+ _wait_check(false, *args)
318
+ end
319
+
320
+ # Wait for the raw value of a telmetry item against a condition or for a timeout
321
+ # and then check against the condition
322
+ # Supports two signatures:
323
+ # wait_check_raw(target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate)
324
+ # or
325
+ # wait_check_raw('target_name packet_name item_name > 1', timeout, polling_rate)
326
+ def wait_check_raw(*args)
327
+ _wait_check(true, *args)
328
+ end
329
+
330
+ def _wait_check_tolerance(raw, *args)
331
+ type_string = 'wait_check_tolerance'
332
+ type_string << '_raw' if raw
333
+ type = (raw ? :RAW : :CONVERTED)
334
+ target_name, packet_name, item_name, expected_value, tolerance, timeout, polling_rate = wait_tolerance_process_args(args, type_string)
335
+ start_time = Time.now.sys
336
+ value = tlm_variable(target_name, packet_name, item_name, type)
337
+ if value.is_a?(Array)
338
+ expected_value, tolerance = array_tolerance_process_args(value.size, expected_value, tolerance, type_string)
339
+
340
+ success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate)
341
+ time = Time.now.sys - start_time
342
+
343
+ message = ""
344
+ value.size.times do |i|
345
+ range = (expected_value[i]-tolerance[i]..expected_value[i]+tolerance[i])
346
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}[#{i}]"
347
+ range_str = "range #{range.first} to #{range.last} with value == #{value[i]} after waiting #{time} seconds"
348
+ if range.include?(value[i])
349
+ message << "#{check_str} was within #{range_str}\n"
350
+ else
351
+ message << "#{check_str} failed to be within #{range_str}\n"
352
+ end
353
+ end
354
+
355
+ if success
356
+ Logger.info message
357
+ else
358
+ if $cmd_tlm_disconnect
359
+ Logger.error message
360
+ else
361
+ raise CheckError, message
362
+ end
363
+ end
364
+ else
365
+ success, value = cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate)
366
+ time = Time.now.sys - start_time
367
+ range = (expected_value - tolerance)..(expected_value + tolerance)
368
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)}"
369
+ range_str = "range #{range.first} to #{range.last} with value == #{value} after waiting #{time} seconds"
370
+ if success
371
+ Logger.info "#{check_str} was within #{range_str}"
372
+ else
373
+ message = "#{check_str} failed to be within #{range_str}"
374
+ if $cmd_tlm_disconnect
375
+ Logger.error message
376
+ else
377
+ raise CheckError, message
378
+ end
379
+ end
380
+ end
381
+
382
+ time
383
+ end
384
+
385
+ def wait_check_tolerance(*args)
386
+ _wait_check_tolerance(false, *args)
387
+ end
388
+
389
+ def wait_check_tolerance_raw(*args)
390
+ _wait_check_tolerance(true, *args)
391
+ end
392
+
393
+ # Wait on an expression to be true. On a timeout, the script will pause.
394
+ def wait_check_expression(exp_to_eval,
395
+ timeout,
396
+ polling_rate = DEFAULT_TLM_POLLING_RATE,
397
+ context = nil)
398
+ start_time = Time.now.sys
399
+ success = cosmos_script_wait_implementation_expression(exp_to_eval,
400
+ timeout,
401
+ polling_rate,
402
+ context)
403
+ time = Time.now.sys - start_time
404
+ if success
405
+ Logger.info "CHECK: #{exp_to_eval} is TRUE after waiting #{time} seconds"
406
+ else
407
+ message = "CHECK: #{exp_to_eval} is FALSE after waiting #{time} seconds"
408
+ if $cmd_tlm_disconnect
409
+ Logger.error message
410
+ else
411
+ raise CheckError, message
412
+ end
413
+ end
414
+ time
415
+ end
416
+ alias wait_expression_stop_on_timeout wait_check_expression
417
+
418
+ # Wait for a telemetry packet to be received a certain number of times or timeout
419
+ def _wait_packet(check,
420
+ target_name,
421
+ packet_name,
422
+ num_packets,
423
+ timeout,
424
+ polling_rate = DEFAULT_TLM_POLLING_RATE)
425
+ type = (check ? 'CHECK' : 'WAIT')
426
+ initial_count = tlm(target_name, packet_name, 'RECEIVED_COUNT')
427
+ start_time = Time.now.sys
428
+ success, value = cosmos_script_wait_implementation(target_name,
429
+ packet_name,
430
+ 'RECEIVED_COUNT',
431
+ :CONVERTED,
432
+ ">= #{initial_count + num_packets}",
433
+ timeout,
434
+ polling_rate)
435
+ time = Time.now.sys - start_time
436
+ if success
437
+ Logger.info "#{type}: #{target_name.upcase} #{packet_name.upcase} received #{value - initial_count} times after waiting #{time} seconds"
438
+ else
439
+ message = "#{type}: #{target_name.upcase} #{packet_name.upcase} expected to be received #{num_packets} times but only received #{value - initial_count} times after waiting #{time} seconds"
440
+ if check
441
+ if $cmd_tlm_disconnect
442
+ Logger.error message
443
+ else
444
+ raise CheckError, message
445
+ end
446
+ else
447
+ Logger.warn message
448
+ end
449
+ end
450
+ time
451
+ end
452
+
453
+ def wait_packet(target_name,
454
+ packet_name,
455
+ num_packets,
456
+ timeout,
457
+ polling_rate = DEFAULT_TLM_POLLING_RATE)
458
+ _wait_packet(false, target_name, packet_name, num_packets, timeout, polling_rate)
459
+ end
460
+
461
+ # Wait for a telemetry packet to be received a certain number of times or timeout and raise an error
462
+ def wait_check_packet(target_name,
463
+ packet_name,
464
+ num_packets,
465
+ timeout,
466
+ polling_rate = DEFAULT_TLM_POLLING_RATE)
467
+ _wait_packet(true, target_name, packet_name, num_packets, timeout, polling_rate)
468
+ end
469
+
470
+ def _get_procedure_path(procedure_name)
471
+ # Handle not-giving an extension
472
+ procedure_name_with_extension = nil
473
+ procedure_name_with_extension = procedure_name + '.rb' if File.extname(procedure_name).empty?
474
+
475
+ path = nil
476
+
477
+ # Find filename in search path
478
+ ($:).each do |directory|
479
+ if File.exist?(directory + '/' + procedure_name) and not File.directory?(directory + '/' + procedure_name)
480
+ path = directory + '/' + procedure_name
481
+ break
482
+ end
483
+
484
+ if procedure_name_with_extension and File.exist?(directory + '/' + procedure_name_with_extension)
485
+ procedure_name = procedure_name_with_extension
486
+ path = directory + '/' + procedure_name
487
+ break
488
+ end
489
+ end
490
+
491
+ # Handle absolute path
492
+ path = procedure_name if !path and File.exist?(procedure_name)
493
+ path = procedure_name_with_extension if !path and procedure_name_with_extension and File.exist?(procedure_name_with_extension)
494
+
495
+ raise LoadError, "Procedure not found -- #{procedure_name}" unless path
496
+ path
497
+ end
498
+
499
+ def check_file_cache_for_instrumented_script(path, md5)
500
+ file_text = nil
501
+ instrumented_script = nil
502
+ cached = true
503
+ use_file_cache = true
504
+
505
+ Cosmos.set_working_dir do
506
+ cache_path = File.join(System.paths['TMP'], 'script_runner')
507
+ unless File.directory?(cache_path)
508
+ # Try to create .cache directory
509
+ begin
510
+ Dir.mkdir(cache_path)
511
+ rescue
512
+ use_file_cache = false
513
+ end
514
+ end
515
+
516
+ cache_filename = nil
517
+ if use_file_cache
518
+ # Check file based instrumented cache
519
+ flat_path = path.tr("/", "_").gsub("\\", "_").tr(":", "_").tr(" ", "_")
520
+ flat_path_with_md5 = flat_path + '_' + md5
521
+ cache_filename = File.join(cache_path, flat_path_with_md5)
522
+ end
523
+
524
+ begin
525
+ file_text = File.read(path)
526
+ rescue Exception => error
527
+ raise "Error reading procedure file : #{path}"
528
+ end
529
+
530
+ if use_file_cache and File.exist?(cache_filename)
531
+ # Use file cached instrumentation
532
+ File.open(cache_filename, 'r') {|file| instrumented_script = file.read}
533
+ else
534
+ cached = false
535
+
536
+ # Build instrumentation
537
+ instrumented_script = ScriptRunnerFrame.instrument_script(file_text, path, true)
538
+
539
+ # Cache instrumentation into file
540
+ if use_file_cache
541
+ begin
542
+ File.open(cache_filename, 'w') {|file| file.write(instrumented_script)}
543
+ rescue
544
+ # Oh well, failed to write cache file
545
+ end
546
+ end
547
+ end
548
+ end
549
+ [file_text, instrumented_script, cached]
550
+ end
551
+
552
+ def start(procedure_name)
553
+ cached = true
554
+ path = _get_procedure_path(procedure_name)
555
+
556
+ if defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
557
+ md5 = nil
558
+ begin
559
+ md5 = Cosmos.md5_files([path]).hexdigest
560
+ rescue Exception => error
561
+ raise "Error calculating md5 on procedure file : #{path}"
562
+ end
563
+
564
+ # Check RAM based instrumented cache
565
+ instrumented_cache = ScriptRunnerFrame.instrumented_cache[path]
566
+ instrumented_script = nil
567
+ if instrumented_cache and md5 == instrumented_cache[1]
568
+ # Use cached instrumentation
569
+ instrumented_script = instrumented_cache[0]
570
+ else
571
+ file_text, instrumented_script, cached = check_file_cache_for_instrumented_script(path, md5)
572
+ # Cache instrumentation into RAM
573
+ ScriptRunnerFrame.file_cache[path] = file_text
574
+ ScriptRunnerFrame.instrumented_cache[path] = [instrumented_script, md5]
575
+ end
576
+
577
+ Object.class_eval(instrumented_script, path, 1)
578
+ else # No ScriptRunnerFrame so just start it locally
579
+ cached = false
580
+ begin
581
+ Kernel::load(path)
582
+ rescue LoadError => error
583
+ raise LoadError, "Error loading -- #{procedure_name}\n#{error.message}"
584
+ end
585
+ end
586
+ # Return whether we had to load and instrument this file, i.e. it was not cached
587
+ !cached
588
+ end
589
+
590
+ # Require an additional ruby file
591
+ def load_utility(procedure_name)
592
+ not_cached = false
593
+ if defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
594
+ saved = ScriptRunnerFrame.instance.use_instrumentation
595
+ begin
596
+ ScriptRunnerFrame.instance.use_instrumentation = false
597
+ not_cached = start(procedure_name)
598
+ ensure
599
+ ScriptRunnerFrame.instance.use_instrumentation = saved
600
+ end
601
+ else # Just call start
602
+ not_cached = start(procedure_name)
603
+ end
604
+ # Return whether we had to load and instrument this file, i.e. it was not cached
605
+ # This is designed to match the behavior of Ruby's require and load keywords
606
+ not_cached
607
+ end
608
+ alias require_utility load_utility
609
+
610
+ ##########################################
611
+ # Protected Methods
612
+ ##########################################
613
+
614
+ def check_process_args(args, function_name)
615
+ case args.length
616
+ when 1
617
+ target_name, packet_name, item_name, comparison_to_eval = extract_fields_from_check_text(args[0])
618
+ when 4
619
+ target_name = args[0]
620
+ packet_name = args[1]
621
+ item_name = args[2]
622
+ comparison_to_eval = args[3]
623
+ else
624
+ # Invalid number of arguments
625
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
626
+ end
627
+ return [target_name, packet_name, item_name, comparison_to_eval]
628
+ end
629
+
630
+ def check_tolerance_process_args(args, function_name)
631
+ case args.length
632
+ when 3
633
+ target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
634
+ expected_value = args[1]
635
+ if args[2].is_a?(Array)
636
+ tolerance = args[2].map!(&:abs)
637
+ else
638
+ tolerance = args[2].abs
639
+ end
640
+ when 5
641
+ target_name = args[0]
642
+ packet_name = args[1]
643
+ item_name = args[2]
644
+ expected_value = args[3]
645
+ if args[4].is_a?(Array)
646
+ tolerance = args[4].map!(&:abs)
647
+ else
648
+ tolerance = args[4].abs
649
+ end
650
+ else
651
+ # Invalid number of arguments
652
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
653
+ end
654
+ return [target_name, packet_name, item_name, expected_value, tolerance]
655
+ end
656
+
657
+ def _execute_wait(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate)
658
+ start_time = Time.now.sys
659
+ success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate)
660
+ time = Time.now.sys - start_time
661
+ wait_str = "WAIT: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
662
+ value_str = "with value == #{value} after waiting #{time} seconds"
663
+ if success
664
+ Logger.info "#{wait_str} success #{value_str}"
665
+ else
666
+ Logger.warn "#{wait_str} failed #{value_str}"
667
+ end
668
+ end
669
+
670
+ def wait_process_args(args, function_name, value_type)
671
+ time = nil
672
+
673
+ case args.length
674
+ when 0
675
+ start_time = Time.now.sys
676
+ cosmos_script_sleep()
677
+ time = Time.now.sys - start_time
678
+ Logger.info("WAIT: Indefinite for actual time of #{time} seconds")
679
+ when 1
680
+ if args[0].kind_of? Numeric
681
+ start_time = Time.now.sys
682
+ cosmos_script_sleep(args[0])
683
+ time = Time.now.sys - start_time
684
+ Logger.info("WAIT: #{args[0]} seconds with actual time of #{time} seconds")
685
+ else
686
+ raise "Non-numeric wait time specified"
687
+ end
688
+ when 2, 3
689
+ target_name, packet_name, item_name, comparison_to_eval = extract_fields_from_check_text(args[0])
690
+ timeout = args[1]
691
+ if args.length == 3
692
+ polling_rate = args[2]
693
+ else
694
+ polling_rate = DEFAULT_TLM_POLLING_RATE
695
+ end
696
+ _execute_wait(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate)
697
+
698
+ when 5, 6
699
+ target_name = args[0]
700
+ packet_name = args[1]
701
+ item_name = args[2]
702
+ comparison_to_eval = args[3]
703
+ timeout = args[4]
704
+ if args.length == 6
705
+ polling_rate = args[5]
706
+ else
707
+ polling_rate = DEFAULT_TLM_POLLING_RATE
708
+ end
709
+ _execute_wait(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate)
710
+
711
+ else
712
+ # Invalid number of arguments
713
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
714
+ end
715
+ time
716
+ end
717
+
718
+ def wait_tolerance_process_args(args, function_name)
719
+ case args.length
720
+ when 4, 5
721
+ target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
722
+ expected_value = args[1]
723
+ if args[2].is_a?(Array)
724
+ tolerance = args[2].map!(&:abs)
725
+ else
726
+ tolerance = args[2].abs
727
+ end
728
+ timeout = args[3]
729
+ if args.length == 5
730
+ polling_rate = args[4]
731
+ else
732
+ polling_rate = DEFAULT_TLM_POLLING_RATE
733
+ end
734
+ when 6, 7
735
+ target_name = args[0]
736
+ packet_name = args[1]
737
+ item_name = args[2]
738
+ expected_value = args[3]
739
+ if args[4].is_a?(Array)
740
+ tolerance = args[4].map!(&:abs)
741
+ else
742
+ tolerance = args[4].abs
743
+ end
744
+ timeout = args[5]
745
+ if args.length == 7
746
+ polling_rate = args[6]
747
+ else
748
+ polling_rate = DEFAULT_TLM_POLLING_RATE
749
+ end
750
+ else
751
+ # Invalid number of arguments
752
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
753
+ end
754
+ return [target_name, packet_name, item_name, expected_value, tolerance, timeout, polling_rate]
755
+ end
756
+
757
+ # When testing an array with a tolerance, the expected value and tolerance
758
+ # can both be supplied as either an array or a single value. If a single
759
+ # value is passed in, that value will be used for all array elements.
760
+ def array_tolerance_process_args(array_size, expected_value, tolerance, function_name)
761
+ if expected_value.is_a?(Array)
762
+ if array_size != expected_value.size
763
+ raise "ERROR: Invalid array size for expected_value passed to #{function_name}()"
764
+ end
765
+ else
766
+ expected_value = Array.new(array_size, expected_value)
767
+ end
768
+ if tolerance.is_a?(Array)
769
+ if array_size != tolerance.size
770
+ raise "ERROR: Invalid array size for tolerance passed to #{function_name}()"
771
+ end
772
+ else
773
+ tolerance = Array.new(array_size, tolerance)
774
+ end
775
+ return [expected_value, tolerance]
776
+ end
777
+
778
+ def wait_check_process_args(args, function_name)
779
+ case args.length
780
+ when 2, 3
781
+ target_name, packet_name, item_name, comparison_to_eval = extract_fields_from_check_text(args[0])
782
+ timeout = args[1]
783
+ if args.length == 3
784
+ polling_rate = args[2]
785
+ else
786
+ polling_rate = DEFAULT_TLM_POLLING_RATE
787
+ end
788
+ when 5, 6
789
+ target_name = args[0]
790
+ packet_name = args[1]
791
+ item_name = args[2]
792
+ comparison_to_eval = args[3]
793
+ timeout = args[4]
794
+ if args.length == 6
795
+ polling_rate = args[5]
796
+ else
797
+ polling_rate = DEFAULT_TLM_POLLING_RATE
798
+ end
799
+ else
800
+ # Invalid number of arguments
801
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
802
+ end
803
+ return [target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate]
804
+ end
805
+
806
+ # sleep in a script - returns true if canceled mid sleep
807
+ def cosmos_script_sleep(sleep_time = nil)
808
+ return false if $cmd_tlm_disconnect
809
+ if defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
810
+ sleep_time = 30000000 unless sleep_time # Handle infinite wait
811
+ if sleep_time > 0.0
812
+ end_time = Time.now.sys + sleep_time
813
+ until (Time.now.sys >= end_time)
814
+ sleep(0.01)
815
+ if ScriptRunnerFrame.instance.pause?
816
+ ScriptRunnerFrame.instance.perform_pause
817
+ return true
818
+ end
819
+ return true if ScriptRunnerFrame.instance.go?
820
+ raise StopScript if ScriptRunnerFrame.instance.stop?
821
+ end
822
+ end
823
+ else
824
+ if sleep_time
825
+ sleep(sleep_time)
826
+ else
827
+ print 'Infinite Wait - Press Enter to Continue: '
828
+ gets()
829
+ end
830
+ end
831
+ return false
832
+ end
833
+
834
+ def _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate)
835
+ end_time = Time.now.sys + timeout
836
+ exp_to_eval = yield
837
+
838
+ while true
839
+ work_start = Time.now.sys
840
+ value = tlm_variable(target_name, packet_name, item_name, value_type)
841
+ if eval(exp_to_eval)
842
+ return true, value
843
+ end
844
+ break if Time.now.sys >= end_time || $cmd_tlm_disconnect
845
+
846
+ delta = Time.now.sys - work_start
847
+ sleep_time = polling_rate - delta
848
+ end_delta = end_time - Time.now.sys
849
+ sleep_time = end_delta if end_delta < sleep_time
850
+ sleep_time = 0 if sleep_time < 0
851
+ canceled = cosmos_script_sleep(sleep_time)
852
+
853
+ if canceled
854
+ value = tlm_variable(target_name, packet_name, item_name, value_type)
855
+ if eval(exp_to_eval)
856
+ return true, value
857
+ else
858
+ return false, value
859
+ end
860
+ end
861
+ end
862
+
863
+ return false, value
864
+ end
865
+
866
+ # Wait for a converted telemetry item to pass a comparison
867
+ def cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE)
868
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate) do
869
+ "value " + comparison_to_eval
870
+ end
871
+ end
872
+
873
+ def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE)
874
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate) do
875
+ "((#{expected_value} - #{tolerance})..(#{expected_value} + #{tolerance})).include? value"
876
+ end
877
+ end
878
+
879
+ def cosmos_script_wait_implementation_array_tolerance(array_size, target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE)
880
+ statements = []
881
+ array_size.times {|i| statements << "(((#{expected_value[i]} - #{tolerance[i]})..(#{expected_value[i]} + #{tolerance[i]})).include? value[#{i}])"}
882
+ exp_to_eval = statements.join(" && ")
883
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate) do
884
+ exp_to_eval
885
+ end
886
+ end
887
+
888
+ # Wait on an expression to be true.
889
+ def cosmos_script_wait_implementation_expression(exp_to_eval, timeout, polling_rate, context)
890
+ end_time = Time.now.sys + timeout
891
+ context = ScriptRunnerFrame.instance.script_binding if !context and defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
892
+
893
+ while true
894
+ work_start = Time.now.sys
895
+ if eval(exp_to_eval, context)
896
+ return true
897
+ end
898
+ break if Time.now.sys >= end_time
899
+
900
+ delta = Time.now.sys - work_start
901
+ sleep_time = polling_rate - delta
902
+ end_delta = end_time - Time.now.sys
903
+ sleep_time = end_delta if end_delta < sleep_time
904
+ sleep_time = 0 if sleep_time < 0
905
+ canceled = cosmos_script_sleep(sleep_time)
906
+
907
+ if canceled
908
+ if eval(exp_to_eval, context)
909
+ return true
910
+ else
911
+ return nil
912
+ end
913
+ end
914
+ end
915
+
916
+ return nil
917
+ end
918
+
919
+ def check_eval(target_name, packet_name, item_name, comparison_to_eval, value)
920
+ string = "value " + comparison_to_eval
921
+ check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
922
+ value_str = "with value == #{value}"
923
+ if eval(string)
924
+ Logger.info "#{check_str} success #{value_str}"
925
+ else
926
+ message = "#{check_str} failed #{value_str}"
927
+ if $cmd_tlm_disconnect
928
+ Logger.error message
929
+ else
930
+ raise CheckError, message
931
+ end
932
+ end
933
+ end
934
+
935
+ #######################################
936
+ # Methods accessing tlm_viewer
937
+ #######################################
938
+
939
+ def display(display_name, x_pos = nil, y_pos = nil)
940
+ run_tlm_viewer("display", display_name) do |tlm_viewer|
941
+ tlm_viewer.display(display_name, x_pos, y_pos)
942
+ end
943
+ end
944
+
945
+ def clear(display_name)
946
+ run_tlm_viewer("clear", display_name) do |tlm_viewer|
947
+ tlm_viewer.clear(display_name)
948
+ end
949
+ end
950
+
951
+ def clear_all(target = nil)
952
+ run_tlm_viewer("clear_all") do |tlm_viewer|
953
+ tlm_viewer.clear_all(target)
954
+ end
955
+ end
956
+
957
+ def run_tlm_viewer(action, display_name = '')
958
+ tlm_viewer = JsonDRbObject.new System.connect_hosts['TLMVIEWER_API'], System.ports['TLMVIEWER_API']
959
+ begin
960
+ yield tlm_viewer
961
+ tlm_viewer.disconnect
962
+ rescue DRb::DRbConnError
963
+ # No Listening Tlm Viewer - So Start One
964
+ start_tlm_viewer
965
+ max_retries = 60
966
+ retry_count = 0
967
+ begin
968
+ yield tlm_viewer
969
+ tlm_viewer.disconnect
970
+ rescue DRb::DRbConnError
971
+ retry_count += 1
972
+ if retry_count < max_retries
973
+ canceled = cosmos_script_sleep(1)
974
+ retry unless canceled
975
+ end
976
+ raise "Unable to Successfully Start Listening Telemetry Viewer: Could not #{action} #{display_name}"
977
+ rescue Errno::ENOENT
978
+ raise "Display Screen File: #{display_name}.txt does not exist"
979
+ end
980
+ rescue Errno::ENOENT
981
+ raise "Display Screen File: #{display_name}.txt does not exist"
982
+ end
983
+ end
984
+
985
+ def start_tlm_viewer
986
+ system_file = File.basename(System.initial_filename)
987
+ mac_app = File.join(Cosmos::USERPATH, 'tools', 'mac', 'TlmViewer.app')
988
+
989
+ if Kernel.is_mac? && File.exist?(mac_app)
990
+ Cosmos.run_process("open '#{mac_app}' --args --system #{system_file}")
991
+ else
992
+ cmd = 'ruby'
993
+ cmd << 'w' if Kernel.is_windows? # Windows uses rubyw to avoid creating a DOS shell
994
+ Cosmos.run_process("#{cmd} '#{File.join(Cosmos::USERPATH, 'tools', 'TlmViewer')}' --system #{system_file}")
995
+ end
996
+ cosmos_script_sleep(1)
997
+ end
998
+
999
+ end
1000
+ end