cosmos 4.1.1-java → 4.2.0-java

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 (336) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.travis.yml +2 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +1 -0
  6. data/Manifest.txt +130 -0
  7. data/autohotkey/tools/ConfigEditorAHK +19 -0
  8. data/autohotkey/tools/cmd_extractor.ahk +4 -4
  9. data/autohotkey/tools/cmd_sequence.ahk +9 -5
  10. data/autohotkey/tools/config_editor.ahk +197 -0
  11. data/autohotkey/tools/packet_viewer.ahk +12 -6
  12. data/autohotkey/tools/replay.ahk +29 -29
  13. data/autohotkey/tools/script_runner.ahk +10 -2
  14. data/autohotkey/tools/tlm_extractor.ahk +7 -8
  15. data/autohotkey/tools/tlm_grapher.ahk +21 -9
  16. data/bin/dart_import +2 -0
  17. data/cosmos.gemspec +18 -16
  18. data/data/config/cmd_tlm_server.yaml +9 -0
  19. data/data/config/interface_modifiers.yaml +17 -0
  20. data/data/config/item_modifiers.yaml +3 -3
  21. data/data/crc.txt +184 -90
  22. data/data/dart.png +0 -0
  23. data/demo/Gemfile +1 -0
  24. data/demo/Rakefile +4 -0
  25. data/demo/config/dart/Gemfile +54 -0
  26. data/demo/config/data/crc.txt +28 -21
  27. data/demo/config/system/system.txt +3 -0
  28. data/demo/config/system/system2.txt +3 -0
  29. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +3 -3
  30. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +1 -1
  31. data/demo/config/targets/INST/lib/sim_inst.rb +1 -1
  32. data/demo/config/targets/INST/screens/adcs.txt +2 -1
  33. data/demo/config/targets/INST/screens/array.txt +1 -1
  34. data/demo/config/targets/INST/screens/block.txt +1 -1
  35. data/demo/config/targets/INST/screens/commanding.txt +7 -2
  36. data/demo/config/targets/INST/screens/graphs.txt +1 -1
  37. data/demo/config/targets/INST/screens/ground.txt +1 -1
  38. data/demo/config/targets/INST/screens/hs.txt +2 -1
  39. data/demo/config/targets/INST/screens/latest.txt +1 -1
  40. data/demo/config/targets/INST/screens/limits.txt +1 -1
  41. data/demo/config/targets/INST/screens/other.txt +1 -1
  42. data/demo/config/targets/INST/screens/tabs.txt +1 -1
  43. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  44. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +3 -1
  45. data/demo/config/tools/launcher/launcher.txt +3 -2
  46. data/demo/tools/Dart +16 -0
  47. data/demo/tools/Dart.bat +9 -0
  48. data/demo/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +0 -0
  49. data/demo/tools/mac/ConfigEditor.app/Contents/MacOS/main.sh +0 -0
  50. data/install/Gemfile +1 -0
  51. data/install/Rakefile +4 -0
  52. data/install/config/dart/Gemfile +54 -0
  53. data/install/config/data/crc.txt +6 -3
  54. data/install/config/system/system.txt +3 -0
  55. data/install/config/tools/launcher/launcher.txt +3 -2
  56. data/install/tools/Dart +16 -0
  57. data/install/tools/Dart.bat +9 -0
  58. data/install/tools/mac/CmdSequence.app/Contents/MacOS/main.sh +0 -0
  59. data/install/tools/mac/ConfigEditor.app/Contents/MacOS/main.sh +0 -0
  60. data/lib/cosmos/core_ext/time.rb +8 -8
  61. data/lib/cosmos/dart/.rspec +1 -0
  62. data/lib/cosmos/dart/Gemfile +69 -0
  63. data/lib/cosmos/dart/Rakefile +7 -0
  64. data/lib/cosmos/dart/app/assets/config/manifest.js +4 -0
  65. data/lib/cosmos/dart/app/assets/images/.keep +0 -0
  66. data/lib/cosmos/dart/app/assets/javascripts/application.js +13 -0
  67. data/lib/cosmos/dart/app/assets/javascripts/cable.js +13 -0
  68. data/lib/cosmos/dart/app/assets/stylesheets/application.css.scss +15 -0
  69. data/lib/cosmos/dart/app/channels/application_cable/channel.rb +4 -0
  70. data/lib/cosmos/dart/app/channels/application_cable/connection.rb +4 -0
  71. data/lib/cosmos/dart/app/controllers/application_controller.rb +3 -0
  72. data/lib/cosmos/dart/app/helpers/application_helper.rb +2 -0
  73. data/lib/cosmos/dart/app/jobs/application_job.rb +2 -0
  74. data/lib/cosmos/dart/app/mailers/application_mailer.rb +4 -0
  75. data/lib/cosmos/dart/app/models/application_record.rb +3 -0
  76. data/lib/cosmos/dart/app/models/item.rb +6 -0
  77. data/lib/cosmos/dart/app/models/item_to_decom_table_mapping.rb +9 -0
  78. data/lib/cosmos/dart/app/models/packet.rb +4 -0
  79. data/lib/cosmos/dart/app/models/packet_config.rb +7 -0
  80. data/lib/cosmos/dart/app/models/packet_log.rb +3 -0
  81. data/lib/cosmos/dart/app/models/packet_log_entry.rb +41 -0
  82. data/lib/cosmos/dart/app/models/system_config.rb +2 -0
  83. data/lib/cosmos/dart/app/models/target.rb +4 -0
  84. data/lib/cosmos/dart/app/views/layouts/application.html.erb +14 -0
  85. data/lib/cosmos/dart/app/views/layouts/mailer.html.erb +13 -0
  86. data/lib/cosmos/dart/app/views/layouts/mailer.text.erb +1 -0
  87. data/lib/cosmos/dart/bin/bundle +3 -0
  88. data/lib/cosmos/dart/bin/rails +4 -0
  89. data/lib/cosmos/dart/bin/rake +4 -0
  90. data/lib/cosmos/dart/bin/setup +34 -0
  91. data/lib/cosmos/dart/bin/update +29 -0
  92. data/lib/cosmos/dart/config.ru +5 -0
  93. data/lib/cosmos/dart/config/application.rb +29 -0
  94. data/lib/cosmos/dart/config/boot.rb +3 -0
  95. data/lib/cosmos/dart/config/cable.yml +9 -0
  96. data/lib/cosmos/dart/config/database.yml +23 -0
  97. data/lib/cosmos/dart/config/environment.rb +5 -0
  98. data/lib/cosmos/dart/config/environments/development.rb +62 -0
  99. data/lib/cosmos/dart/config/environments/production.rb +84 -0
  100. data/lib/cosmos/dart/config/environments/test.rb +42 -0
  101. data/lib/cosmos/dart/config/initializers/application_controller_renderer.rb +6 -0
  102. data/lib/cosmos/dart/config/initializers/assets.rb +12 -0
  103. data/lib/cosmos/dart/config/initializers/backtrace_silencers.rb +7 -0
  104. data/lib/cosmos/dart/config/initializers/cookies_serializer.rb +5 -0
  105. data/lib/cosmos/dart/config/initializers/filter_parameter_logging.rb +4 -0
  106. data/lib/cosmos/dart/config/initializers/inflections.rb +16 -0
  107. data/lib/cosmos/dart/config/initializers/mime_types.rb +4 -0
  108. data/lib/cosmos/dart/config/initializers/new_framework_defaults.rb +25 -0
  109. data/lib/cosmos/dart/config/initializers/session_store.rb +3 -0
  110. data/lib/cosmos/dart/config/initializers/wrap_parameters.rb +14 -0
  111. data/lib/cosmos/dart/config/locales/en.yml +23 -0
  112. data/lib/cosmos/dart/config/puma.rb +47 -0
  113. data/lib/cosmos/dart/config/routes.rb +3 -0
  114. data/lib/cosmos/dart/config/secrets.yml +22 -0
  115. data/lib/cosmos/dart/db/migrate/20170406172907_create_targets.rb +8 -0
  116. data/lib/cosmos/dart/db/migrate/20170406172927_create_packets.rb +10 -0
  117. data/lib/cosmos/dart/db/migrate/20170406172937_create_packet_logs.rb +9 -0
  118. data/lib/cosmos/dart/db/migrate/20170406172943_create_packet_log_entries.rb +16 -0
  119. data/lib/cosmos/dart/db/migrate/20170406183500_change_packet_log_entries_primary_key.rb +5 -0
  120. data/lib/cosmos/dart/db/migrate/20170407153618_add_unique_requirements.rb +7 -0
  121. data/lib/cosmos/dart/db/migrate/20170511155447_add_meta_id_to_packet_log_entries.rb +6 -0
  122. data/lib/cosmos/dart/db/migrate/20170523185056_rename_received_time_and_add_is_tlm_to_packet_log_entries.rb +7 -0
  123. data/lib/cosmos/dart/db/migrate/20170525201157_create_items.rb +10 -0
  124. data/lib/cosmos/dart/db/migrate/20170525201315_create_system_configs.rb +9 -0
  125. data/lib/cosmos/dart/db/migrate/20170525201624_create_packet_configs.rb +11 -0
  126. data/lib/cosmos/dart/db/migrate/20170525201745_create_item_to_decom_table_mappings.rb +12 -0
  127. data/lib/cosmos/dart/db/migrate/20170525201939_create_decom_tables.rb +12 -0
  128. data/lib/cosmos/dart/db/migrate/20170525202051_add_decom_state_to_packet_log_entry.rb +5 -0
  129. data/lib/cosmos/dart/db/migrate/20170913160409_update_items.rb +6 -0
  130. data/lib/cosmos/dart/db/migrate/20170913160558_update_item_to_decom_table_mapping.rb +11 -0
  131. data/lib/cosmos/dart/db/migrate/20170913160916_udpate_decom_table.rb +6 -0
  132. data/lib/cosmos/dart/db/migrate/20170913212026_add_ready_to_packet_configs.rb +5 -0
  133. data/lib/cosmos/dart/db/migrate/20170913223556_modify_tables.rb +9 -0
  134. data/lib/cosmos/dart/db/migrate/20170914215744_modify_mapping_table.rb +6 -0
  135. data/lib/cosmos/dart/db/migrate/20170919201433_add_system_config_id_to_packet_config.rb +11 -0
  136. data/lib/cosmos/dart/db/migrate/20170919210307_add_max_table_index_to_packet_configs.rb +5 -0
  137. data/lib/cosmos/dart/db/migrate/20171215225546_add_ready_to_packet_log_entries.rb +5 -0
  138. data/lib/cosmos/dart/db/migrate/20180116214338_add_index_for_ple_ready_to_packet_log_entries.rb +5 -0
  139. data/lib/cosmos/dart/db/schema.rb +103 -0
  140. data/lib/cosmos/dart/db/seeds.rb +7 -0
  141. data/lib/cosmos/dart/examples/dart_decom_client.rb +45 -0
  142. data/lib/cosmos/dart/examples/dart_stream_client.rb +93 -0
  143. data/lib/cosmos/dart/lib/dart_common.rb +749 -0
  144. data/lib/cosmos/dart/lib/dart_database_cleaner.rb +172 -0
  145. data/lib/cosmos/dart/lib/dart_decom_query.rb +184 -0
  146. data/lib/cosmos/dart/lib/dart_decommutator.rb +235 -0
  147. data/lib/cosmos/dart/lib/dart_importer.rb +154 -0
  148. data/lib/cosmos/dart/lib/dart_logging.rb +50 -0
  149. data/lib/cosmos/dart/lib/dart_packet_log_writer.rb +139 -0
  150. data/lib/cosmos/dart/lib/dart_reducer_manager.rb +85 -0
  151. data/lib/cosmos/dart/lib/dart_reducer_worker_thread.rb +263 -0
  152. data/lib/cosmos/dart/lib/dart_tcpip_server_interface.rb +142 -0
  153. data/lib/cosmos/dart/processes/dart.rb +145 -0
  154. data/lib/cosmos/dart/processes/dart_decom_server.rb +39 -0
  155. data/lib/cosmos/dart/processes/dart_import.rb +63 -0
  156. data/lib/cosmos/dart/processes/dart_ingester.rb +92 -0
  157. data/lib/cosmos/dart/processes/dart_reducer.rb +27 -0
  158. data/lib/cosmos/dart/processes/dart_stream_server.rb +31 -0
  159. data/lib/cosmos/dart/processes/dart_worker.rb +37 -0
  160. data/lib/cosmos/dart/spec/dart/dart_common_spec.rb +333 -0
  161. data/lib/cosmos/dart/spec/dart/dart_database_cleaner_spec.rb +455 -0
  162. data/lib/cosmos/dart/spec/dart/dart_decom_query_spec.rb +153 -0
  163. data/lib/cosmos/dart/spec/dart/dart_decommutator_spec.rb +336 -0
  164. data/lib/cosmos/dart/spec/dart/dart_importer_spec.rb +83 -0
  165. data/lib/cosmos/dart/spec/dart/dart_logging_spec.rb +30 -0
  166. data/lib/cosmos/dart/spec/dart/dart_packet_log_writer_spec.rb +149 -0
  167. data/lib/cosmos/dart/spec/dart/dart_reducer_manager_spec.rb +289 -0
  168. data/lib/cosmos/dart/spec/dart/dart_tcpip_server_interface_spec.rb +241 -0
  169. data/lib/cosmos/dart/spec/rails_helper.rb +60 -0
  170. data/lib/cosmos/dart/spec/spec_helper.rb +139 -0
  171. data/lib/cosmos/gui/dialogs/about_dialog.rb +1 -1
  172. data/lib/cosmos/gui/dialogs/dart_dialog.rb +60 -0
  173. data/lib/cosmos/gui/dialogs/legal_dialog.rb +1 -0
  174. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +0 -3
  175. data/lib/cosmos/gui/qt.rb +10 -1
  176. data/lib/cosmos/gui/text/completion.rb +10 -9
  177. data/lib/cosmos/gui/text/completion_text_edit.rb +16 -14
  178. data/lib/cosmos/gui/text/ruby_editor.rb +2 -2
  179. data/lib/cosmos/gui/widgets/dart_frame.rb +142 -0
  180. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +119 -0
  181. data/lib/cosmos/gui/widgets/packet_log_frame.rb +42 -12
  182. data/lib/cosmos/interfaces/interface.rb +1 -2
  183. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +26 -8
  184. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +8 -2
  185. data/lib/cosmos/interfaces/protocols/protocol.rb +2 -1
  186. data/lib/cosmos/interfaces/protocols/template_protocol.rb +1 -1
  187. data/lib/cosmos/interfaces/stream_interface.rb +1 -0
  188. data/lib/cosmos/interfaces/tcpip_server_interface.rb +2 -3
  189. data/lib/cosmos/io/json_drb_object.rb +1 -1
  190. data/lib/cosmos/io/json_rpc.rb +2 -1
  191. data/lib/cosmos/io/win32_serial_driver.rb +2 -9
  192. data/lib/cosmos/packet_logs/packet_log_writer.rb +1 -1
  193. data/lib/cosmos/packets/packet.rb +22 -12
  194. data/lib/cosmos/packets/packet_config.rb +2 -1
  195. data/lib/cosmos/packets/packet_item.rb +26 -24
  196. data/lib/cosmos/packets/parsers/macro_parser.rb +5 -2
  197. data/lib/cosmos/packets/parsers/packet_item_parser.rb +35 -17
  198. data/lib/cosmos/packets/parsers/packet_parser.rb +3 -10
  199. data/lib/cosmos/packets/parsers/xtce_converter.rb +21 -35
  200. data/lib/cosmos/packets/parsers/xtce_parser.rb +54 -46
  201. data/lib/cosmos/packets/structure.rb +10 -2
  202. data/lib/cosmos/packets/structure_item.rb +22 -8
  203. data/lib/cosmos/processors/statistics_processor.rb +2 -0
  204. data/lib/cosmos/script/api_shared.rb +13 -12
  205. data/lib/cosmos/script/cmd_tlm_server.rb +4 -0
  206. data/lib/cosmos/script/commands.rb +3 -15
  207. data/lib/cosmos/script/script.rb +69 -23
  208. data/lib/cosmos/streams/tcpip_client_stream.rb +2 -2
  209. data/lib/cosmos/system/system.rb +42 -25
  210. data/lib/cosmos/system/target.rb +6 -2
  211. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +177 -36
  212. data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +3 -2
  213. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +34 -8
  214. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +80 -25
  215. data/lib/cosmos/tools/cmd_tlm_server/api.rb +19 -4
  216. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +15 -14
  217. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +15 -9
  218. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +1 -9
  219. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +1 -6
  220. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +1 -3
  221. data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +84 -7
  222. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +0 -1
  223. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +1 -5
  224. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +3 -2
  225. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +159 -27
  226. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +1 -1
  227. data/lib/cosmos/tools/config_editor/config_editor.rb +17 -52
  228. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +0 -5
  229. data/lib/cosmos/tools/data_viewer/data_viewer.rb +111 -0
  230. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +31 -18
  231. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +12 -3
  232. data/lib/cosmos/tools/script_runner/script_runner.rb +27 -14
  233. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +104 -37
  234. data/lib/cosmos/tools/table_manager/table_config.rb +1 -1
  235. data/lib/cosmos/tools/table_manager/table_item_parser.rb +4 -2
  236. data/lib/cosmos/tools/table_manager/table_manager.rb +0 -5
  237. data/lib/cosmos/tools/table_manager/table_manager_core.rb +0 -1
  238. data/lib/cosmos/tools/test_runner/test.rb +1 -3
  239. data/lib/cosmos/tools/test_runner/test_runner.rb +26 -15
  240. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +290 -137
  241. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +122 -25
  242. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +67 -0
  243. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +28 -0
  244. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +36 -0
  245. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +42 -3
  246. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +88 -14
  247. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +2 -5
  248. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +2 -6
  249. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +74 -18
  250. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +3 -7
  251. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +159 -0
  252. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +49 -2
  253. data/lib/cosmos/tools/tlm_viewer/screen.rb +3 -0
  254. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +0 -2
  255. data/lib/cosmos/tools/tlm_viewer/widgets.rb +1 -0
  256. data/lib/cosmos/tools/tlm_viewer/widgets/backgroundbutton_widget.rb +54 -0
  257. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +5 -5
  258. data/lib/cosmos/top_level.rb +1 -0
  259. data/lib/cosmos/utilities/crc.rb +3 -0
  260. data/lib/cosmos/utilities/csv.rb +1 -0
  261. data/lib/cosmos/utilities/message_log.rb +2 -1
  262. data/lib/cosmos/utilities/simulated_target.rb +8 -8
  263. data/lib/cosmos/version.rb +5 -5
  264. data/lib/cosmos/win32/win32.rb +4 -10
  265. data/run_gui_tests.bat +2 -1
  266. data/spec/config/config_parser_spec.rb +4 -4
  267. data/spec/core_ext/array_spec.rb +1 -1
  268. data/spec/core_ext/exception_spec.rb +12 -12
  269. data/spec/core_ext/file_spec.rb +6 -6
  270. data/spec/core_ext/hash_spec.rb +1 -1
  271. data/spec/core_ext/socket_spec.rb +2 -2
  272. data/spec/core_ext/string_spec.rb +13 -13
  273. data/spec/core_ext/time_spec.rb +0 -2
  274. data/spec/gui/utilities/script_module_gui_spec.rb +3 -3
  275. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +6 -6
  276. data/spec/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +4 -0
  277. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +6 -2
  278. data/spec/interfaces/interface_spec.rb +0 -1
  279. data/spec/interfaces/linc_interface_spec.rb +0 -5
  280. data/spec/interfaces/protocols/crc_protocol_spec.rb +201 -85
  281. data/spec/interfaces/protocols/fixed_protocol_spec.rb +33 -9
  282. data/spec/interfaces/protocols/length_protocol_spec.rb +1 -1
  283. data/spec/interfaces/protocols/override_protocol_spec.rb +6 -2
  284. data/spec/interfaces/protocols/preidentified_protocol_spec.rb +1 -5
  285. data/spec/interfaces/protocols/template_protocol_spec.rb +0 -1
  286. data/spec/interfaces/simulated_target_interface_spec.rb +5 -5
  287. data/spec/interfaces/udp_interface_spec.rb +2 -4
  288. data/spec/io/buffered_file_spec.rb +8 -12
  289. data/spec/io/json_drb_spec.rb +9 -9
  290. data/spec/io/json_rpc_spec.rb +4 -4
  291. data/spec/io/raw_logger_spec.rb +4 -3
  292. data/spec/packet_logs/packet_log_reader_spec.rb +3 -6
  293. data/spec/packet_logs/packet_log_writer_spec.rb +4 -4
  294. data/spec/packets/binary_accessor_spec.rb +5 -8
  295. data/spec/packets/commands_spec.rb +2 -2
  296. data/spec/packets/limits_spec.rb +2 -2
  297. data/spec/packets/packet_config_spec.rb +12 -0
  298. data/spec/packets/packet_item_limits_spec.rb +1 -1
  299. data/spec/packets/packet_item_spec.rb +9 -9
  300. data/spec/packets/packet_spec.rb +15 -5
  301. data/spec/packets/parsers/packet_item_parser_spec.rb +27 -0
  302. data/spec/packets/parsers/xtce_parser_spec.rb +27 -30
  303. data/spec/packets/structure_spec.rb +2 -1
  304. data/spec/packets/telemetry_spec.rb +3 -5
  305. data/spec/processors/statistics_processor_spec.rb +35 -0
  306. data/spec/script/cmd_tlm_server_spec.rb +4 -21
  307. data/spec/script/commands_disconnect_spec.rb +46 -58
  308. data/spec/script/commands_spec.rb +40 -61
  309. data/spec/script/limits_spec.rb +1 -21
  310. data/spec/script/script_spec.rb +32 -41
  311. data/spec/script/scripting_spec.rb +166 -185
  312. data/spec/script/telemetry_spec.rb +10 -5
  313. data/spec/script/tools_spec.rb +2 -24
  314. data/spec/spec_helper.rb +11 -5
  315. data/spec/system/system_spec.rb +17 -12
  316. data/spec/tools/cmd_tlm_server/api_spec.rb +21 -10
  317. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +15 -16
  318. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +0 -1
  319. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +16 -27
  320. data/spec/tools/cmd_tlm_server/commanding_spec.rb +2 -6
  321. data/spec/tools/cmd_tlm_server/connections_spec.rb +0 -4
  322. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +13 -13
  323. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +5 -9
  324. data/spec/tools/cmd_tlm_server/limits_groups_background_task_spec.rb +11 -3
  325. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +0 -4
  326. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +5 -5
  327. data/spec/tools/cmd_tlm_server/routers_spec.rb +5 -9
  328. data/spec/tools/table_manager/table_config_spec.rb +0 -1
  329. data/spec/tools/table_manager/tablemanager_core_spec.rb +23 -23
  330. data/spec/tools/tlm_viewer/tlm_viewer_config_spec.rb +6 -4
  331. data/spec/top_level/top_level_spec.rb +9 -9
  332. data/spec/utilities/csv_spec.rb +2 -12
  333. data/spec/utilities/logger_spec.rb +6 -6
  334. data/spec/utilities/message_log_spec.rb +3 -11
  335. data/tasks/gemfile_stats.rake +2 -2
  336. metadata +167 -60
@@ -0,0 +1,7 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3
+ #
4
+ # Examples:
5
+ #
6
+ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7
+ # Character.create(name: 'Luke', movie: movies.first)
@@ -0,0 +1,45 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2018 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
+ ENV['COSMOS_USERPATH'] = 'C:/git/COSMOS/demo'
12
+ require 'cosmos'
13
+ require 'cosmos/io/json_drb_object'
14
+ Cosmos::Logger.level = Cosmos::Logger::DEBUG
15
+
16
+ start_time = Time.utc(1970, 1, 1, 0, 0, 0)
17
+ end_time = Time.utc(2020, 1, 1, 0, 0, 0)
18
+
19
+ request = {}
20
+ request['start_time_sec'] = start_time.tv_sec
21
+ request['start_time_usec'] = start_time.tv_usec
22
+ request['end_time_sec'] = end_time.tv_sec
23
+ request['end_time_usec'] = end_time.tv_usec
24
+ request['item'] = ['INST', 'HEALTH_STATUS', 'TEMP1']
25
+ request['reduction'] = 'HOUR'
26
+ request['cmd_tlm'] = 'TLM'
27
+ request['offset'] = 0
28
+ request['limit'] = 100000
29
+ request['value_type'] = 'RAW_AVG'
30
+ # request['meta_ids'] = [1, 1062642]
31
+ request['meta_filters'] = ["OPERATOR_NAME == 'Unspecified'"]
32
+
33
+ puts "Connecting to Dart Decom Server..."
34
+ server = Cosmos::JsonDRbObject.new(Cosmos::System.connect_hosts['DART_DECOM'], Cosmos::System.ports['DART_DECOM'])
35
+ puts "Getting SYSTEM META fields"
36
+ result = server.item_names("SYSTEM", "META")
37
+ puts result.inspect(10000)
38
+ puts "Making request"
39
+ begin_time = Time.now
40
+ result = server.query(request)
41
+ finish_time = Time.now
42
+ puts result.inspect(10000)
43
+ puts "Got result of length #{result.length} in #{finish_time - begin_time} seconds"
44
+ puts "Closing..."
45
+ server.shutdown
@@ -0,0 +1,93 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2018 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
+ ENV['COSMOS_USERPATH'] = 'C:/git/COSMOS/demo'
12
+ require 'cosmos'
13
+ Cosmos::Logger.level = Cosmos::Logger::DEBUG
14
+
15
+ request_packet = Cosmos::Packet.new('DART', 'DART')
16
+ request_packet.define_item('REQUEST', 0, 0, :BLOCK)
17
+
18
+ start_time = Time.utc(1970, 1, 1, 0, 0, 0)
19
+ end_time = Time.utc(2020, 1, 1, 0, 0, 0)
20
+
21
+ request = {}
22
+ request['start_time_sec'] = start_time.tv_sec
23
+ request['start_time_usec'] = start_time.tv_usec
24
+ request['end_time_sec'] = end_time.tv_sec
25
+ request['end_time_usec'] = end_time.tv_usec
26
+ #~ request['cmd_tlm'] = 'CMD'
27
+ #~ request['packets'] = [['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]
28
+ #~ request['meta_ids'] = [4962]
29
+ request['meta_filters'] = ["OPERATOR_NAME == 'Unspecified'"]
30
+ request_packet.write('REQUEST', JSON.dump(request))
31
+
32
+ interface = Cosmos::TcpipClientInterface.new(
33
+ Cosmos::System.connect_hosts['DART_STREAM'],
34
+ Cosmos::System.ports['DART_STREAM'],
35
+ Cosmos::System.ports['DART_STREAM'],
36
+ 10, 10, 'PREIDENTIFIED')
37
+ puts "Connecting to Dart Stream Server..."
38
+ interface.connect
39
+ puts "Requesting #{request['packets'].inspect} from #{start_time} to #{end_time}..."
40
+ interface.write(request_packet)
41
+ puts "Receiving packets..."
42
+ while true
43
+ packet = interface.read
44
+ unless packet
45
+ puts "Connection closed by Dart Stream Server"
46
+ break
47
+ end
48
+
49
+ # Identify and update packet
50
+ if packet.identified?
51
+ begin
52
+ # Preidentifed packet - place it into the current value table
53
+ identified_packet = Cosmos::System.telemetry.update!(packet.target_name,
54
+ packet.packet_name,
55
+ packet.buffer)
56
+ rescue RuntimeError
57
+ # Packet identified but we don't know about it
58
+ # Clear packet_name and target_name and try to identify
59
+ Logger.warn "Received unknown identified telemetry: #{packet.target_name} #{packet.packet_name}"
60
+ packet.target_name = nil
61
+ packet.packet_name = nil
62
+ identified_packet = Cosmos::System.telemetry.identify!(packet.buffer,
63
+ @interface.target_names)
64
+ end
65
+ else
66
+ # Packet needs to be identified
67
+ identified_packet = Cosmos::System.telemetry.identify!(packet.buffer,
68
+ @interface.target_names)
69
+ end
70
+
71
+ if identified_packet
72
+ identified_packet.received_time = packet.received_time
73
+ packet = identified_packet
74
+ else
75
+ unknown_packet = Cosmos::System.telemetry.update!('UNKNOWN', 'UNKNOWN', packet.buffer)
76
+ unknown_packet.received_time = packet.received_time
77
+ packet = unknown_packet
78
+ data_length = packet.length
79
+ string = "#{@interface.name} - Unknown #{data_length} byte packet starting: "
80
+ num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, data_length].min
81
+ data_to_print = packet.buffer(false)[0..(num_bytes_to_print - 1)]
82
+ data_to_print.each_byte do |byte|
83
+ string << sprintf("%02X", byte)
84
+ end
85
+ Logger.error string
86
+ end
87
+
88
+ # Switch to correct configuration from SYSTEM META when needed
89
+ if packet.target_name == 'SYSTEM'.freeze and packet.packet_name == 'META'.freeze
90
+ Cosmos::System.load_configuration(packet.read('CONFIG'))
91
+ end
92
+ puts "Got: #{packet.target_name} #{packet.packet_name}"
93
+ end
@@ -0,0 +1,749 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2018 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos/script'
12
+ require 'optparse'
13
+
14
+ # Autoload models here to remove problems loading within Cosmos namespace
15
+ Target
16
+ Packet
17
+ PacketLog
18
+ PacketLogEntry
19
+
20
+ # Implement methods common to DART (Data Archival Retrieval and Trending).
21
+ # Most of these methods handle accessing the DART database.
22
+ module DartCommon
23
+ # @return [Integer] Maximimum byte size of strings in the database
24
+ MAX_STRING_BYTE_SIZE = 191 # Works well with mysql utf8mb4 if we want to support mysql in the future
25
+ # @return [Integer] Maximimum bit size of strings in the database
26
+ MAX_STRING_BIT_SIZE = MAX_STRING_BYTE_SIZE * 8
27
+ # @return [Integer] Maximum number of columns in a database table
28
+ MAX_COLUMNS_PER_TABLE = 200
29
+ # @return [Array<Symbol>] Data types which can be reduced over a time period.
30
+ # These data types will result in minute, hour, and daily database tables.
31
+ REDUCED_TYPES = [:integer, :bigint, :decimal, :float]
32
+
33
+ # States for the Decommutation table reduced_state field
34
+ INITIALIZING = 0 # New rows being created
35
+ READY_TO_REDUCE = 1 # Once all new rows have been created
36
+ REDUCED = 2 # After the data has been reduced
37
+
38
+ # Regular expression used to break up an individual line into a keyword and
39
+ # comma delimited parameters. Handles parameters in single or double quotes.
40
+ PARSING_REGEX = %r{ (?:"(?:[^\\"]|\\.)*") | (?:'(?:[^\\']|\\.)*') | \S+ }x #"
41
+
42
+ # Argument parser for the DART command line tools
43
+ def self.handle_argv(parse = true)
44
+ parser = OptionParser.new do |option_parser|
45
+ option_parser.banner = "Usage: ruby #{option_parser.program_name} [options]"
46
+ option_parser.separator("")
47
+
48
+ # Create the help option
49
+ option_parser.on("-h", "--help", "Show this message") do
50
+ puts option_parser
51
+ exit
52
+ end
53
+
54
+ # Create the version option
55
+ option_parser.on("-v", "--version", "Show version") do
56
+ puts "COSMOS Version: #{COSMOS_VERSION}"
57
+ puts "User Version: #{USER_VERSION}" if defined? USER_VERSION
58
+ exit
59
+ end
60
+
61
+ # Create the system option
62
+ option_parser.on("--system FILE", "Use an alternative system.txt file") do |arg|
63
+ System.instance(File.join(USERPATH, 'config', 'system', arg))
64
+ end
65
+ end
66
+ parser.parse! if parse
67
+ parser
68
+ end
69
+
70
+ # Get the ActiveRecord database handle to the decommutation table
71
+ #
72
+ # @param packet_config_id [Integer] PacketConfig table ID
73
+ # @param table_index [Integer] Index into one of multiple decommutation tables.
74
+ # Since the number of columns is limited to MAX_COLUMNS_PER_TABLE there will
75
+ # be multiple tables for large packets.
76
+ # @param reduction_modifier [String] Blank or one of '_m' for minutes, '_h' for hours,
77
+ # '_d' for days. These are the reduction tables.
78
+ # @return [ActiveRecord::Base] The decommutation table model
79
+ def get_decom_table_model(packet_config_id, table_index, reduction_modifier = "")
80
+ return get_table_model("t#{packet_config_id}_#{table_index}", reduction_modifier)
81
+ end
82
+
83
+ # Get the ActiveRecord model for a database table
84
+ #
85
+ # @param table [String] Database table name
86
+ # @param reduction_modifier [String] One of "_m", "_h", "_d"
87
+ # @return [ActiveRecord] Database model for a commutation or reduction table
88
+ # Commutatiohn tables are named tXXX_YYY where XXX is the PacketConfig ID,
89
+ # and YYY is the table index. Reduction tables have a _m, _h, _d extension
90
+ # on the table name.
91
+ def get_table_model(table, reduction_modifier = "")
92
+ model_name = "T" + table[1..-1] + reduction_modifier
93
+ begin
94
+ model = Cosmos.const_get(model_name)
95
+ rescue
96
+ # Need to create model
97
+ model = Class.new(ActiveRecord::Base) do
98
+ self.table_name = table + reduction_modifier
99
+ end
100
+ Cosmos.const_set(model_name, model)
101
+ end
102
+ return model
103
+ end
104
+
105
+ # Iterate through each decom and reduced table currently in DART
106
+ #
107
+ def each_decom_and_reduced_table
108
+ ActiveRecord::Base.connection.tables.each do |table|
109
+ # Since the decommutation tables are created dynamically we search
110
+ # through all the tables looking for tables named something like
111
+ # tXXX_YYY where XXX is the PacketConfig ID and YYY is the table index
112
+ if table.to_s =~ /^t(\d+)_(\d+)$/ # ASCII art? No! Regex!
113
+ packet_config_id = $1.to_i
114
+ table_index = $2.to_i
115
+ # Get the base decommutation table model
116
+ decom_model = get_table_model(table)
117
+ # Find the reduction table models
118
+ minute_model = get_table_model(table, "_m")
119
+ hour_model = get_table_model(table, "_h")
120
+ day_model = get_table_model(table, "_d")
121
+
122
+ yield packet_config_id, table_index, decom_model, minute_model, hour_model, day_model
123
+ end
124
+ end
125
+ end
126
+
127
+ # Determine if the item must have separate raw and converted value tables
128
+ #
129
+ # @param item [Cosmos::PacketItem] Packet item
130
+ # @return [Boolean] Whether the item must have separate raw and converted value tables
131
+ def separate_raw_con?(item)
132
+ # All items with states must have separate raw and converted values
133
+ return true if item.states
134
+ if item.data_type != :DERIVED
135
+ # Non-derived items with a well defined read conversion have separate raw and converted
136
+ return true if well_defined_read_conversion(item)
137
+ end
138
+ return false
139
+ end
140
+
141
+ # Create the packet configuration in the database. This includes the
142
+ # ItemToDecomTableMapping which maps a telemetry item to its location in the
143
+ # decommutation table as well as the actual decommutation tables which hold
144
+ # the decommutated data. These tables are all named tXXX_YYY where XXX is the
145
+ # PacketConfig ID and YYY is a table index when the packet has more than
146
+ # MAX_COLUMNS_PER_TABLE and must span multiple tables. In addition the
147
+ # reduction tables are setup with the '_m' (minute), '_h' (hour), '_d' (day)
148
+ # extensions added to the tXXX_YYY tables (assuming the packets contain
149
+ # data which can be reduced.)
150
+ #
151
+ # @param packet [Cosmos::Packet] Packet to create database tables for
152
+ # @param packet_id [Integer] Id in the Packet table
153
+ # @param packet_config [PacketConfig] ActiveRecord access to the PacketConfig table
154
+ def setup_packet_config(packet, packet_id, packet_config)
155
+ data_types = setup_item_to_decom_table_mapping(packet, packet_id, packet_config)
156
+ table_index = 0
157
+ # Grab MAX_COLUMNS_PER_TABLE of the total data_types and create a decommutation table
158
+ # This will create a column for each data item named iX where X is a simple counter.
159
+ # Thus the only way to know what data is in these tables is to use the
160
+ # ItemToDecomTableMapping table.
161
+ data_types.each_slice(MAX_COLUMNS_PER_TABLE) do |table_data_types|
162
+ # Create overall decommutation table
163
+ create_table("t#{packet_config.id}_#{table_index}") do |t|
164
+ t.datetime :time
165
+ t.bigint :ple_id
166
+ t.bigint :meta_id
167
+ t.bigint :reduced_id
168
+ t.integer :reduced_state, :default => 0
169
+ table_data_types.each_with_index do |data_type, index|
170
+ item_index = (table_index * MAX_COLUMNS_PER_TABLE) + index
171
+ Cosmos::Logger::info("creating t#{packet_config.id}_#{table_index}:i#{item_index}")
172
+ case data_type
173
+ when :integer_array, :bigint_array, :float_array, :text_array, :binary_array, :decimal_array
174
+ t.column "i#{item_index}", data_type.to_s.split("_")[0].intern, :array => true
175
+ when :integer, :bigint, :float, :text, :binary, :decimal
176
+ t.column "i#{item_index}", data_type
177
+ when :string_array
178
+ t.column "i#{item_index}", data_type.to_s.split("_")[0].intern, :array => true, :limit => MAX_STRING_BYTE_SIZE
179
+ when :string
180
+ t.column "i#{item_index}", data_type, :limit => MAX_STRING_BYTE_SIZE
181
+ else
182
+ raise "Unhandled db type: #{data_type}"
183
+ end
184
+ end
185
+ t.index :time
186
+ t.index :meta_id
187
+ t.index :reduced_state
188
+ t.index :reduced_id
189
+ end
190
+ create_reduction_table("t#{packet_config.id}_#{table_index}_h", table_data_types, table_index) # hour
191
+ create_reduction_table("t#{packet_config.id}_#{table_index}_m", table_data_types, table_index) # month
192
+ create_reduction_table("t#{packet_config.id}_#{table_index}_d", table_data_types, table_index) # day
193
+ table_index += 1
194
+ end
195
+
196
+ # Mark packet config ready
197
+ packet_config.max_table_index = table_index
198
+ packet_config.ready = true
199
+ packet_config.save!
200
+ end
201
+
202
+ # Attempts to load a name system configuration. If the system configuration
203
+ # can't be loaded locally, it is requested from the server and copied
204
+ # locally before proceeding.
205
+ #
206
+ # @param system_config_name [String] System configuration name (MD5) to load
207
+ def switch_and_get_system_config(system_config_name)
208
+ # Switch to this new system configuration
209
+ current_config, error = Cosmos::System.load_configuration(system_config_name)
210
+
211
+ if current_config != system_config_name
212
+ Cosmos::Logger.warn("Failed to load system_config: #{system_config_name}")
213
+ Cosmos::Logger.warn(" Current config: #{current_config}")
214
+ Cosmos::Logger.warn(" Error: #{error.formatted}") if error
215
+ Cosmos::Logger.warn(" Will attempt to retrieve...")
216
+ filename, data = get_saved_config(system_config_name)
217
+ raise "No saved config" unless filename and data and data.length > 0
218
+ configuration = File.join(Cosmos::System.paths['SAVED_CONFIG'], filename)
219
+ unless File.exist?(configuration) and File.size(configuration) > 0
220
+ File.open(configuration, 'wb') {|file| file.write(data)}
221
+ File.chmod(0444, configuration) # Mark readonly
222
+ end
223
+ Cosmos::Logger.info("Configuration retrieved: #{configuration}")
224
+ current_config, error = Cosmos::System.load_configuration(system_config_name)
225
+ raise "Could not load config" if current_config != system_config_name
226
+ end
227
+ end
228
+
229
+ # Iterate through all the defined commands and telemetry and create database
230
+ # entries for all targets (Target table) and packets (Packet table).
231
+ def sync_targets_and_packets
232
+ sync_targets_packets(Cosmos::System.telemetry.all, is_tlm: true)
233
+ sync_targets_packets(Cosmos::System.commands.all, is_tlm: false)
234
+ build_lookups()
235
+ end
236
+
237
+ # Look up the database IDs of the given target and packet names
238
+ #
239
+ # @param target_name [String] Name of the target
240
+ # @param packet_name [String] Name of the packet
241
+ # @param is_tlm [Boolean] Whether the packet is telemetry (true) or commands (false)
242
+ def lookup_target_and_packet_id(target_name, packet_name, is_tlm)
243
+ target_id = @target_name_to_id[target_name] # Check cache
244
+ unless target_id
245
+ target = sync_target(target_name)
246
+ target_id = target.id
247
+ @target_name_to_id[target_name] = target_id # Update cache
248
+ if is_tlm
249
+ @target_id_tlm_packet_name_to_id[target_id] = {}
250
+ else
251
+ @target_id_cmd_packet_name_to_id[target_id] = {}
252
+ end
253
+ end
254
+ if is_tlm
255
+ packet_name_hash = @target_id_tlm_packet_name_to_id[target_id]
256
+ else
257
+ packet_name_hash = @target_id_cmd_packet_name_to_id[target_id]
258
+ end
259
+ packet_id = packet_name_hash[packet_name] # Check cache
260
+ unless packet_id
261
+ packet = sync_packet(target.id, packet_name, is_tlm)
262
+ packet_id = packet.id
263
+ packet_name_hash[packet_name] = packet.id # Update cache
264
+ end
265
+ return [target_id, packet_id]
266
+ end
267
+
268
+ # Find the ActiveRecord database object for the given packet
269
+ #
270
+ # @param packet [Cosmos::Packet] COSMOS Packet to lookup
271
+ # @param is_tlm [Boolean] Whether the packet is telemetry (true) or commands (false)
272
+ # @return [ActiveRecord] PacketLogEntry ActiveRecord object
273
+ def find_packet_log_entry(packet, is_tlm)
274
+ target_id, packet_id = lookup_target_and_packet_id(packet.target_name, packet.packet_name, is_tlm)
275
+ return PacketLogEntry.where("target_id = ? and packet_id = ? and is_tlm = ? and time = ?", target_id, packet_id, is_tlm, packet.received_time).first
276
+ end
277
+
278
+ # Read a Packet from the binary file by using the PacketLogEntry
279
+ #
280
+ # @param ple [ActiveRecord] PacketLogEntry ActiveRecord object
281
+ # @return [Cosmos::Packet] Packet located by the PacketLookupTable
282
+ def read_packet_from_ple(ple)
283
+ begin
284
+ @plr_cache ||= {}
285
+ reader = @plr_cache[ple.packet_log_id]
286
+ unless reader
287
+ packet_log = PacketLog.find(ple.packet_log_id)
288
+ reader = Cosmos::PacketLogReader.new
289
+ reader.open(packet_log.filename)
290
+ @plr_cache[packet_log.id] = reader
291
+ end
292
+ return reader.read_at_offset(ple.data_offset)
293
+ rescue Exception => error
294
+ Cosmos::Logger.error("Error Reading Packet Log Entry:\n#{error.formatted}")
295
+ return nil
296
+ end
297
+ end
298
+
299
+ def decommutate_item?(item)
300
+ # RECEIVED_COUNT is a relative count and should not be decommutated
301
+ return false if item.name == 'RECEIVED_COUNT'
302
+ # ProcessorConversion items are calculated on the fly thus can't
303
+ # be decommutated as they change based on when they're read
304
+ return false if item.read_conversion.class == Cosmos::ProcessorConversion
305
+ # We don't handle DERIVED items without explicit types and sizes
306
+ if item.data_type == :DERIVED
307
+ return false unless well_defined_read_conversion(item)
308
+ end
309
+ true
310
+ end
311
+
312
+ def query_decom_reduced(
313
+ target_name,
314
+ packet_name,
315
+ item_name,
316
+ value_type,
317
+ is_tlm,
318
+ start_time,
319
+ end_time,
320
+ reduction,
321
+ reduction_modifier,
322
+ item_name_modifier,
323
+ limit = 10000,
324
+ offset = 0,
325
+ meta_ids = [])
326
+
327
+ # Upon receiving the above request, the corresponding Target, Packet, and Item
328
+ # objects are requested from the database
329
+ target_model = Target.where("name = ?", target_name).first
330
+ raise "Target: #{target_name} not found" unless target_model
331
+ packet_model = Packet.where("target_id = ? and name = ? and is_tlm = ?", target_model.id, packet_name, is_tlm).first
332
+ raise "Packet: #{packet_name} not found" unless packet_model
333
+ item_model = Item.where("packet_id = ? and name = ?", packet_model.id, item_name).first
334
+ raise "Item: #{item_name} not found" unless item_model
335
+
336
+ # Next the corresponding PacketConfigs are loaded within the requested times.
337
+ # Note the PacketConfig time range covers when that particular packet configuration
338
+ # was valid. Thus it can cover a much larger time period than the data requested.
339
+ packet_configs = PacketConfig.where("packet_id = ?", packet_model.id)
340
+ packet_configs.where("start_time >= ?", start_time) if start_time
341
+ packet_configs.where("end_time <= ?", end_time) if end_time
342
+ packet_configs = packet_configs.order("start_time ASC")
343
+ packet_config_ids = []
344
+ packet_configs.each do |pc|
345
+ packet_config_ids << pc.id
346
+ end
347
+
348
+ # Then, the ItemToDecomTableMapping table is queried to find all entries that match
349
+ # the requested item, value_type, and packet configuration. These entries represent
350
+ # all the entries in the decommutation and reduction tables for the requested item
351
+ # when that PacketConfig was valid.
352
+ mappings = ItemToDecomTableMapping.where("item_id = ? and value_type != ?", item_model.id, value_type).where("packet_config_id" => packet_config_ids)
353
+ # Sort mappings into packet config id order
354
+ mappings.to_a.sort do |a, b|
355
+ packet_config_ids.index(a.packet_config_id) <=> packet_config_ids.index(b.packet_config_id)
356
+ end
357
+ data = []
358
+ current_count = 0
359
+ batch_size = 1000
360
+ mappings.each do |mapping|
361
+ # The item to decommutation table entries are then used to access the actual
362
+ # decommutation table model (ActiveRecord object).
363
+ row_model = get_decom_table_model(mapping.packet_config_id, mapping.table_index, reduction_modifier)
364
+
365
+ batch_count = 0
366
+ loop do
367
+ # The decommutation table itself is then quered for the values with final filters on the requested
368
+ # time range and optional filtering by meta_id. The correct decommutation table is selected by
369
+ # using the passed in reduction value in the request.
370
+ remaining = limit - current_count
371
+ if remaining > batch_size
372
+ limit_value = batch_size
373
+ else
374
+ limit_value = remaining
375
+ end
376
+ if reduction == :NONE
377
+ # For reduced data the time field is called start_time, for non-reduced it is just time
378
+ model_item_name = "i#{mapping.item_index}#{item_name_modifier}"
379
+ rows = row_model.order(time: :asc)
380
+ rows = rows.where("time >= ?", start_time) if start_time
381
+ rows = rows.where("time <= ?", end_time) if end_time
382
+ rows = rows.where("meta_id" => meta_ids) if meta_ids.length > 0
383
+ rows = rows.limit(limit_value).offset(offset + (batch_count * batch_size))
384
+ rows.select(model_item_name, "time", "meta_id")
385
+ break if rows.length <= 0
386
+ rows.each do |row|
387
+ data << [row.read_attribute(model_item_name), row.time.tv_sec, row.time.tv_usec, 1, row.meta_id]
388
+ current_count += 1
389
+ break if current_count >= limit
390
+ end
391
+ elsif mapping.reduced
392
+ # For reduced data the time field is called start_time, for non-reduced it is just time
393
+ model_item_name = "i#{mapping.item_index}#{item_name_modifier}"
394
+ rows = row_model.order(start_time: :asc)
395
+ rows = rows.where("start_time >= ?", start_time) if start_time
396
+ rows = rows.where("start_time <= ?", end_time) if end_time
397
+ rows = rows.where("meta_id" => meta_ids) if meta_ids.length > 0
398
+ rows = rows.limit(limit_value).offset(offset + (batch_count * batch_size))
399
+ rows.select(model_item_name, "start_time", "num_samples", "meta_id")
400
+ break if rows.length <= 0
401
+ rows.each do |row|
402
+ data << [row.read_attribute(model_item_name), row.start_time.tv_sec, row.start_time.tv_usec, row.num_samples, row.meta_id]
403
+ current_count += 1
404
+ break if current_count >= limit
405
+ end
406
+ end
407
+ break if limit_value != batch_size
408
+ batch_count += 1
409
+ end
410
+ end
411
+
412
+ return data
413
+ end
414
+
415
+ def comparison_cast(value1, value2)
416
+ case value1
417
+ when Integer
418
+ return Integer(value2)
419
+ when Float
420
+ return Float(value2)
421
+ when String
422
+ return value2.to_s
423
+ end
424
+ return value2
425
+ end
426
+
427
+ def process_meta_filters(meta_filters, is_tlm, end_time)
428
+ found = []
429
+ meta_filters.each_with_index do |query_string, index|
430
+ found[index] = []
431
+ this_found = found[index]
432
+ item_name, comparison, comparison_value = query_string.scan(PARSING_REGEX)
433
+ item_name = item_name.remove_quotes
434
+ comparison_value = comparison_value.remove_quotes
435
+ comparison_value = nil if comparison_value.to_s.upcase == "NULL"
436
+
437
+ meta_data = query_decom_reduced(
438
+ "SYSTEM", "META", item_name,
439
+ ItemToDecomTableMapping::CONVERTED, is_tlm,
440
+ nil, end_time,
441
+ :NONE, "",
442
+ "", 100000, 0, [])
443
+
444
+ case comparison
445
+ when "=", "=="
446
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value == comparison_cast(value, comparison_value) }
447
+ when "!="
448
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value != comparison_cast(value, comparison_value) }
449
+ when ">"
450
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value > comparison_cast(value, comparison_value) }
451
+ when "<"
452
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value < comparison_cast(value, comparison_value) }
453
+ when ">="
454
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value >= comparison_cast(value, comparison_value) }
455
+ when "<="
456
+ meta_data.each { |value, tv_sec, tv_usec, num_samples, meta_id| this_found << meta_id if value <= comparison_cast(value, comparison_value) }
457
+ end
458
+ end
459
+ meta_ids = found.inject(:&) # Reduce to only common meta_ids to all meta_filters
460
+ meta_ids = [0] if !meta_ids or meta_ids.length == 0
461
+
462
+ return meta_ids
463
+ end
464
+
465
+ protected
466
+
467
+ # Build the internal lookup tables to convert names to database ids
468
+ def build_lookups
469
+ # Get full target name and packet name lists from database
470
+ targets = Target.all
471
+ @target_name_to_id = {}
472
+ @target_id_tlm_packet_name_to_id = {}
473
+ @target_id_cmd_packet_name_to_id = {}
474
+ @packet_id_item_name_to_id = {}
475
+ targets.each do |target|
476
+ @target_name_to_id[target.name] = target.id
477
+ @target_id_tlm_packet_name_to_id[target.id] = {}
478
+ @target_id_cmd_packet_name_to_id[target.id] = {}
479
+ packets = Packet.where("target_id = #{target.id} and is_tlm = true").all
480
+ packets.each do |packet|
481
+ @target_id_tlm_packet_name_to_id[target.id][packet.name] = packet.id
482
+ @packet_id_item_name_to_id[packet.id] = {}
483
+ items = Item.where("packet_id = #{packet.id}").all
484
+ items.each do |item|
485
+ @packet_id_item_name_to_id[packet.id][item.name] = item.id
486
+ end
487
+ end
488
+ packets = Packet.where("target_id = #{target.id} and is_tlm = false").all
489
+ packets.each do |packet|
490
+ @target_id_cmd_packet_name_to_id[target.id][packet.name] = packet.id
491
+ @packet_id_item_name_to_id[packet.id] = {}
492
+ items = Item.where("packet_id = #{packet.id}").all
493
+ items.each do |item|
494
+ @packet_id_item_name_to_id[packet.id][item.name] = item.id
495
+ end
496
+ end
497
+ end
498
+ end
499
+
500
+ # Look up the item id in the Item table based on the previously acquired packet id
501
+ # Note: This method is only safe if lookup_target_and_packet_id was called
502
+ # before it to get the packet_id
503
+ #
504
+ # @param packet_id [Integer] Database ID of the packet
505
+ # @param item_name [String] Name of the item
506
+ # @return [Integer] Database ID of the item
507
+ def lookup_item_id(packet_id, item_name)
508
+ @packet_id_item_name_to_id[packet_id] ||= {}
509
+ item_name_hash = @packet_id_item_name_to_id[packet_id]
510
+ item_id = item_name_hash[item_name] # Check cache
511
+ unless item_id
512
+ item = sync_item(packet_id, item_name)
513
+ item_id = item.id
514
+ item_name_hash[item_name] = item.id # Update cache
515
+ end
516
+ return item_id
517
+ end
518
+
519
+ # Convert the COSMOS data type, bit size, and array into a type used
520
+ # by the SQL database.
521
+ #
522
+ # @param data_type [Symbol] One of :INT, :UINT, :FLOAT, :STRING, :BLOCK
523
+ # @param bit_size [Integer] Size of the COSMOS data type
524
+ # @param array_size [Integer, nil] Size of the array or nil if no array
525
+ # @return [Symbol] Database type such as :integer, :bigint, :string, etc.
526
+ def cosmos_data_type_to_db_type(data_type, bit_size, array_size)
527
+ db_type = nil
528
+ case data_type
529
+ when :INT
530
+ if bit_size <= 32
531
+ db_type = :integer
532
+ elsif bit_size <= 64
533
+ db_type = :bigint
534
+ else
535
+ db_type = :decimal
536
+ end
537
+ when :UINT
538
+ if bit_size <= 31
539
+ db_type = :integer
540
+ elsif bit_size <= 63
541
+ db_type = :bigint
542
+ else
543
+ db_type = :decimal
544
+ end
545
+ when :FLOAT
546
+ db_type = :float
547
+ when :STRING
548
+ if bit_size <= 0 or bit_size > MAX_STRING_BIT_SIZE
549
+ db_type = :text
550
+ else
551
+ db_type = :string
552
+ end
553
+ when :BLOCK
554
+ db_type = :binary
555
+ else
556
+ raise "Unsupported data type for db: #{data_type}:#{bit_size}"
557
+ end
558
+ db_type = (db_type.to_s + "_array").intern if array_size
559
+ return db_type
560
+ end
561
+
562
+ # @param item [Cosmos::PacketItem] Item to convert to a SQL database type
563
+ # @return [Array<Symbol, Symbol | nil>] SQL database type for the raw item
564
+ # followed by the converted item or nil if there is no conversion
565
+ def get_db_types(item)
566
+ raw_data_type = nil
567
+ converted_data_type = nil
568
+ if item.data_type == :DERIVED
569
+ if item.read_conversion
570
+ converted_data_type = cosmos_data_type_to_db_type(item.read_conversion.converted_type, item.read_conversion.converted_bit_size, item.read_conversion.converted_array_size)
571
+ raw_data_type = converted_data_type
572
+ end
573
+ if item.states
574
+ converted_data_type = cosmos_data_type_to_db_type(:STRING, MAX_STRING_BIT_SIZE, item.array_size)
575
+ end
576
+ else
577
+ raw_data_type = cosmos_data_type_to_db_type(item.data_type, item.bit_size, item.array_size)
578
+ if item.read_conversion
579
+ converted_data_type = cosmos_data_type_to_db_type(item.read_conversion.converted_type, item.read_conversion.converted_bit_size, item.read_conversion.converted_array_size)
580
+ elsif item.states
581
+ converted_data_type = cosmos_data_type_to_db_type(:STRING, MAX_STRING_BIT_SIZE, item.array_size)
582
+ end
583
+ end
584
+ return raw_data_type, converted_data_type
585
+ end
586
+
587
+ # Create the item to decommutation table mapping
588
+ #
589
+ # @param packet [Cosmos::Packet] Packet to create item mappings for
590
+ # @param packet_id [Integer] Id in the Packet table
591
+ # @param packet_config [PacketConfig] ActiveRecord access to the PacketConfig table
592
+ # @return [Array<Symbol>] SQL database types for each item in the packet. Note there
593
+ # can be multiple values per item if an item has a raw and converted type.
594
+ def setup_item_to_decom_table_mapping(packet, packet_id, packet_config)
595
+ item_index = 0
596
+ data_types = []
597
+
598
+ # Cleanup old
599
+ ItemToDecomTableMapping.where("packet_config_id = ?", packet_config.id).destroy_all
600
+
601
+ packet.sorted_items.each do |item|
602
+ next unless decommutate_item?(item)
603
+
604
+ raw_data_type, converted_data_type = get_db_types(item)
605
+ item_id = lookup_item_id(packet_id, item.name)
606
+ if separate_raw_con?(item)
607
+ # Need both RAW and CONVERTED
608
+ ItemToDecomTableMapping.create(
609
+ :item_id => item_id,
610
+ :value_type => ItemToDecomTableMapping::RAW,
611
+ :reduced => REDUCED_TYPES.include?(raw_data_type),
612
+ :packet_config_id => packet_config.id,
613
+ :table_index => item_index / MAX_COLUMNS_PER_TABLE,
614
+ :item_index => item_index
615
+ )
616
+ item_index += 1
617
+ data_types << raw_data_type
618
+ ItemToDecomTableMapping.create(
619
+ :item_id => item_id,
620
+ :value_type => ItemToDecomTableMapping::CONVERTED,
621
+ :reduced => REDUCED_TYPES.include?(converted_data_type),
622
+ :packet_config_id => packet_config.id,
623
+ :table_index => item_index / MAX_COLUMNS_PER_TABLE,
624
+ :item_index => item_index
625
+ )
626
+ item_index += 1
627
+ data_types << converted_data_type
628
+ else
629
+ # Can combine RAW and CONVERTED (RAW_CON)
630
+ ItemToDecomTableMapping.create(
631
+ :item_id => item_id,
632
+ :value_type => ItemToDecomTableMapping::RAW_CON,
633
+ :reduced => REDUCED_TYPES.include?(raw_data_type),
634
+ :packet_config_id => packet_config.id,
635
+ :table_index => item_index / MAX_COLUMNS_PER_TABLE,
636
+ :item_index => item_index
637
+ )
638
+ item_index += 1
639
+ data_types << raw_data_type
640
+ end
641
+ end
642
+
643
+ return data_types
644
+ end
645
+
646
+ # Create a table in the database. Tables are first checked for existance
647
+ # and dropped if they exist to ensure a clean table is created.
648
+ def create_table(table_name)
649
+ # Normally there would not be an existing decommutation table, however
650
+ # in the off chance that DART crashed halfway through creating a packet
651
+ # configuration we drop anything that may be existing.
652
+ if ActiveRecord::Base.connection.table_exists?(table_name)
653
+ ActiveRecord::Base.connection.drop_table(table_name)
654
+ end
655
+ ActiveRecord::Base.connection.create_table(table_name) do |table|
656
+ yield table
657
+ end
658
+ # Need to create model
659
+ model = Class.new(ActiveRecord::Base) do
660
+ self.table_name = table_name.dup
661
+ end
662
+ model.reset_column_information
663
+ model_name = table_name.upcase
664
+ Cosmos.send(:remove_const, model_name) if Cosmos.const_defined?(model_name)
665
+ Cosmos.const_set(model_name, model)
666
+ end
667
+
668
+ # Create a data reduction table. These tables hold min, max, and average
669
+ # data points for values that can be reduced over longer time periods
670
+ # for quicker access.
671
+ def create_reduction_table(table_name, table_data_types, table_index)
672
+ create_table(table_name) do |t|
673
+ t.datetime :start_time
674
+ t.integer :num_samples
675
+ t.bigint :meta_id
676
+ t.bigint :reduced_id
677
+ t.integer :reduced_state, :default => 0
678
+ table_data_types.each_with_index do |data_type, index|
679
+ item_index = (table_index * MAX_COLUMNS_PER_TABLE) + index
680
+ case data_type
681
+ when :integer, :bigint, :float, :decimal
682
+ t.column "i#{item_index}max", data_type
683
+ t.column "i#{item_index}min", data_type
684
+ t.column "i#{item_index}avg", :float # Average is always floating point
685
+ t.column "i#{item_index}stddev", :float # Standard deviation is always floating point
686
+ end
687
+ end
688
+ t.index :start_time
689
+ t.index :meta_id
690
+ t.index :reduced_state
691
+ t.index :reduced_id
692
+ end
693
+ end
694
+
695
+ def sync_target(target_name)
696
+ target = Target.where("name = ?", target_name).first
697
+ begin
698
+ unless target
699
+ target = Target.create(:name => target_name)
700
+ Cosmos::Logger::info("Created Target:#{target.id}:#{target.name}")
701
+ end
702
+ rescue
703
+ # Another thread probably already created it - Try to get it one more time
704
+ target = Target.where("name = ?", target_name).first
705
+ end
706
+ target
707
+ end
708
+
709
+ def sync_packet(target_id, packet_name, is_tlm)
710
+ packet = Packet.where("target_id = ? and name = ? and is_tlm = #{is_tlm}", target_id, packet_name).first
711
+ begin
712
+ unless packet
713
+ packet = Packet.create(:target_id => target_id, :name => packet_name, :is_tlm => is_tlm)
714
+ Cosmos::Logger::info("Created Packet:#{packet.id}:#{packet.target_id}:#{packet.name}:#{packet.is_tlm}")
715
+ end
716
+ rescue
717
+ # Another thread probably already created it - Try to get it one more time
718
+ packet = Packet.where("target_id = ? and name = ? and is_tlm = #{is_tlm}", target_id, packet_name).first
719
+ end
720
+ packet
721
+ end
722
+
723
+ def sync_item(packet_id, item_name)
724
+ item = Item.where("packet_id = ? and name = ?", packet_id, item_name).first
725
+ begin
726
+ unless item
727
+ item = Item.create(:packet_id => packet_id, :name => item_name)
728
+ Cosmos::Logger::info("Created Item:#{item.id}:#{item.packet_id}:#{item.name}")
729
+ end
730
+ rescue
731
+ # Another thread probably already created it - Try to get it one more time
732
+ item = Item.where("packet_id = ? and name = ?", packet_id, item_name).first
733
+ end
734
+ item
735
+ end
736
+
737
+ def sync_targets_packets(tgt_pkt_hash, is_tlm:)
738
+ tgt_pkt_hash.each do |target_name, packets|
739
+ target = sync_target(target_name)
740
+ packets.each do |packet_name, packet_obj|
741
+ sync_packet(target.id, packet_name, is_tlm)
742
+ end
743
+ end
744
+ end
745
+
746
+ def well_defined_read_conversion(item)
747
+ item.read_conversion && item.read_conversion.converted_type && item.read_conversion.converted_bit_size
748
+ end
749
+ end