cosmos 3.9.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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