Class: Cosmos::LimitsMonitor
- Defined in:
- lib/cosmos/tools/limits_monitor/limits_monitor.rb
Overview
The LimitsMonitor application displays all the out of limits items encountered by the COSMOS server. It provides the ability to ignore and restore limits as well as logs all limits events.
Defined Under Namespace
Classes: LimitsWidget
Class Method Summary collapse
-
.run(option_parser = nil, options = nil) ⇒ Object
Initialize tool options.
Instance Method Summary collapse
-
#clear_gui_items ⇒ Object
Reset the GUI by clearing all items.
-
#closeEvent(event) ⇒ Object
Handle the window closing.
-
#config_path ⇒ String
Fully qualified path to the configuration file.
-
#edit_ignored_items ⇒ Object
Opens a dialog to allow the user to remove ignored items.
-
#graceful_kill ⇒ Object
Gracefully kill threads.
-
#ignore(widget, item) ⇒ Object
Update front panel to ignore an item when the corresponding button is pressed.
-
#initialize(options) ⇒ LimitsMonitor
constructor
Create the main application GUI.
-
#initialize_actions ⇒ Object
Initialize all the actions in the application Menu.
-
#initialize_central_widget ⇒ Object
Layout the main GUI tab widget with a view of all the out of limits items in one tab and a log tab showing all limits events.
-
#initialize_menus ⇒ Object
Initialize the application menu bar options.
-
#limits_thread ⇒ Object
Thread to monitor for broken limits and add them to the log and front panel when found.
-
#new_gui_item(target_name, packet_name, item_name) ⇒ Qt::Widget
Add new out of limit item or stale packet.
-
#open_config_file ⇒ Object
Opens the configuration file and loads the ignored items.
-
#save_config_file ⇒ Object
Saves the ignored items to the configuration file.
- #show_options_dialog ⇒ Object
-
#update_gui_item(widget, value, limits_state, limits_set) ⇒ Object
Update out of limit item with a values.
-
#update_log(message, color) ⇒ Object
Update the log panel with limits change information.
-
#update_overall_limits_state(state) ⇒ Object
Changes the limits state on the status bar at the top of the screen.
-
#value_thread ⇒ Object
Thread to request the out of limits values and update them at 1Hz.
Methods inherited from QtTool
#about, #complete_initialize, create_default_options, graceful_kill, #initialize_help_menu, post_options_parsed_hook, pre_window_new_hook, redirect_io, restore_io
Constructor Details
#initialize(options) ⇒ LimitsMonitor
Create the main application GUI. Start the limits thread which responds to asynchronous limits events from the server and the value thread which polls the server at 1Hz for the out of limits items values.
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 409 def initialize() super() Cosmos.load_cosmos_icon("limits_monitor.png") @cancel_thread = false @limits_sleeper = Sleeper.new @value_sleeper = Sleeper.new initialize_actions() () () complete_initialize() @limits_items = LimitsItems.new( method(:new_gui_item), method(:update_gui_item), method(:clear_gui_items)) result = @limits_items.open_config(.config_file) statusBar.showMessage(tr(result)) limits_thread() value_thread() end |
Class Method Details
.run(option_parser = nil, options = nil) ⇒ Object
Initialize tool options.
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 814 def self.run(option_parser = nil, = nil) Cosmos.catch_fatal_exception do unless option_parser and option_parser, = () .width = 600 .height = 500 .remember_geometry = false .title = "Limits Monitor" .auto_size = false .config_file = nil .production = false .no_prompt = false option_parser.separator "Limits Monitor Specific Options:" option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg| .config_file = arg end end super(option_parser, ) end end |
Instance Method Details
#clear_gui_items ⇒ Object
Reset the GUI by clearing all items
698 699 700 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 698 def clear_gui_items Qt.execute_in_main_thread(true) { @scroll_layout.removeAll } end |
#closeEvent(event) ⇒ Object
Handle the window closing
798 799 800 801 802 803 804 805 806 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 798 def closeEvent(event) @cancel_thread = true @value_sleeper.cancel @limits_sleeper.cancel shutdown_cmd_tlm() Cosmos.kill_thread(self, @limits_thread, 2) Cosmos.kill_thread(self, @value_thread, 2) super(event) end |
#config_path ⇒ String
Returns Fully qualified path to the configuration file.
566 567 568 569 570 571 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 566 def config_path # If the config file has been set then just return it return @filename if @filename # This is the default path to the configuration files File.join(::Cosmos::USERPATH, 'config', 'tools', 'limits_monitor', 'limits_monitor.txt') end |
#edit_ignored_items ⇒ Object
Opens a dialog to allow the user to remove ignored items
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 595 def edit_ignored_items items = [] index = 0 @limits_items.ignored.each do |target_name, packet_name, item_name| item = Qt::ListWidgetItem.new("#{target_name} #{packet_name} #{item_name}") item.setData(Qt::UserRole, Qt::Variant.new(@limits_items.ignored[index])) items << item index += 1 end Qt::Dialog.new(self) do |dialog| dialog.setWindowTitle('Ignored Telemetry Items') list = Qt::ListWidget.new list.setFocus() # Allow multiple sections list.setSelectionMode(Qt::AbstractItemView::ExtendedSelection) items.each {|item| list.addItem(item) } shortcut = Qt::Shortcut.new(Qt::KeySequence.new(Qt::KeySequence::Delete), list) list.connect(shortcut, SIGNAL('activated()')) do items = list.selectedItems() (0...items.length).each do |index| @limits_items.remove_ignored(items[index].data(Qt::UserRole).value) end list.remove_selected_items list.setCurrentRow(0) end # Preselect the first row (works if list is empty) so the keyboard # works instantly without having to click the list list.setCurrentRow(0) ok = Qt::PushButton.new('Ok') do connect(SIGNAL('clicked()')) { dialog.done(0) } end remove = Qt::PushButton.new('Remove Selected') do connect(SIGNAL('clicked()')) { shortcut.activated() } end = Qt::HBoxLayout.new do addWidget(ok) addStretch(1) addWidget(remove) end dialog.layout = Qt::VBoxLayout.new do addWidget(list) addLayout() end dialog.resize(500, 200) dialog.exec dialog.dispose end end |
#graceful_kill ⇒ Object
Gracefully kill threads
809 810 811 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 809 def graceful_kill Qt::CoreApplication.processEvents() end |
#ignore(widget, item) ⇒ Object
Update front panel to ignore an item when the corresponding button is pressed.
706 707 708 709 710 711 712 713 714 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 706 def ignore(, item) @limits_items.ignore(item) Qt.execute_in_main_thread(true) do @scroll_layout.removeWidget() .dispose @scroll_widget.adjustSize statusBar.showMessage('Warning: Some Telemetry Items are Ignored') end end |
#initialize_actions ⇒ Object
Initialize all the actions in the application Menu
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 432 def initialize_actions super @options_action = Qt::Action.new(tr('O&ptions'), self) @options_action.statusTip = tr('Open the options dialog') @options_action.connect(SIGNAL('triggered()')) { () } @reset_action = Qt::Action.new(tr('&Reset'), self) @reset_action_keyseq = Qt::KeySequence.new(tr('Ctrl+R')) @reset_action.shortcut = @reset_action_keyseq @reset_action.statusTip = tr('Reset connection and clear all items. This does not modify the ignored items.') @reset_action.connect(SIGNAL('triggered()')) { @limits_items.request_reset() } @open_ignored_action = Qt::Action.new(Cosmos.get_icon('open.png'), tr('&Open Config'), self) @open_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+O')) @open_ignored_action.shortcut = @open_ignored_action_keyseq @open_ignored_action.statusTip = tr('Open ignored telemetry items configuration file') @open_ignored_action.connect(SIGNAL('triggered()')) { open_config_file() } @save_ignored_action = Qt::Action.new(Cosmos.get_icon('save.png'), tr('&Save Config'), self) @save_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+S')) @save_ignored_action.shortcut = @save_ignored_action_keyseq @save_ignored_action.statusTip = tr('Save all ignored telemetry items in a configuration file') @save_ignored_action.connect(SIGNAL('triggered()')) { save_config_file() } @edit_ignored_action = Qt::Action.new(tr('&Edit Ignored'), self) @edit_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+E')) @edit_ignored_action.shortcut = @edit_ignored_action_keyseq @edit_ignored_action.statusTip = tr('Edit the ignored telemetry items list') @edit_ignored_action.connect(SIGNAL('triggered()')) { edit_ignored_items() } end |
#initialize_central_widget ⇒ Object
Layout the main GUI tab widget with a view of all the out of limits items in one tab and a log tab showing all limits events.
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 486 def @tabbook = Qt::TabWidget.new(self) setCentralWidget(@tabbook) @widget = Qt::Widget.new @layout = Qt::VBoxLayout.new(@widget) @monitored_state_text_field = Qt::LineEdit.new(self) @monitored_state_text_field.setText('Stale') @monitored_state_text_field.setAlignment(Qt::AlignCenter) @monitored_state_text_field.setReadOnly(true) @palette = Qt::Palette.new() @palette.setColor(Qt::Palette::Base, Qt::Color.new(255,0,255)) @monitored_state_text_field.setPalette(@palette) @state_label = Qt::Label.new('Monitored Limits State: ') @monitored_state_frame = Qt::HBoxLayout.new @monitored_state_frame.addWidget(@state_label) @monitored_state_frame.addWidget(@monitored_state_text_field) label = Qt::Label.new filename = File.join(::Cosmos::PATH, 'data', 'spinner.gif') movie = Qt::Movie.new(filename) label.setMovie(movie) movie.start @monitored_state_frame.addWidget(label) @monitored_state_frame.setAlignment(Qt::AlignTop) @layout.addLayout(@monitored_state_frame) @scroll = Qt::ScrollArea.new @scroll_widget = Qt::Widget.new @scroll.setWidget(@scroll_widget) @scroll_layout = Qt::VBoxLayout.new(@scroll_widget) @scroll_layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize) @layout.addWidget(@scroll) @log_output = Qt::PlainTextEdit.new @log_output.setReadOnly(true) @log_output.setMaximumBlockCount(100) @tabbook.addTab(@widget, "Limits") @tabbook.addTab(@log_output, "Log") end |
#initialize_menus ⇒ Object
Initialize the application menu bar options
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 467 def @file_menu = .addMenu(tr('&File')) @file_menu.addAction(@open_ignored_action) @file_menu.addAction(@save_ignored_action) @file_menu.addAction(@edit_ignored_action) @file_menu.addSeparator() @file_menu.addAction(@reset_action) @file_menu.addAction(@options_action) @file_menu.addSeparator() @file_menu.addAction(@exit_action) # Help Menu @about_string = "Limits Monitor displays all telemetry items that are or have been out of limits since it was started or reset." () end |
#limits_thread ⇒ Object
Thread to monitor for broken limits and add them to the log and front panel when found.
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 649 def limits_thread result = nil color = nil @limits_thread = Thread.new do while true break if @cancel_thread Qt.execute_in_main_thread(true) do result, color = @limits_items.process_events() end if result update_log(result, color) else break if @limits_sleeper.sleep(1) end end end rescue Exception => error Cosmos.handle_fatal_exception(error) end |
#new_gui_item(target_name, packet_name, item_name) ⇒ Qt::Widget
Add new out of limit item or stale packet
676 677 678 679 680 681 682 683 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 676 def new_gui_item(target_name, packet_name, item_name) = nil Qt.execute_in_main_thread(true) do = LimitsWidget.new(self, target_name, packet_name, item_name) @scroll_layout.addWidget() end end |
#open_config_file ⇒ Object
Opens the configuration file and loads the ignored items
574 575 576 577 578 579 580 581 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 574 def open_config_file filename = Qt::FileDialog::getOpenFileName(self, "Open Configuration File", config_path()) unless filename.nil? || filename.empty? result = @limits_items.open_config(filename) statusBar.showMessage(tr(result)) end end |
#save_config_file ⇒ Object
Saves the ignored items to the configuration file
584 585 586 587 588 589 590 591 592 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 584 def save_config_file filename = Qt::FileDialog.getSaveFileName(self, 'Save As...', config_path(), 'Configuration Files (*.txt)') unless filename.nil? || filename.empty? result = @limits_items.save_config(filename) statusBar.showMessage(tr(result)) @filename = filename end end |
#show_options_dialog ⇒ Object
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 528 def Qt::Dialog.new(self) do |dialog| dialog.setWindowTitle('Options') colorblind_box = Qt::CheckBox.new('Colorblind Mode Enabled', self) colorblind_box.setCheckState(Qt::Checked) if @colorblind ok = Qt::PushButton.new('Ok') do connect(SIGNAL('clicked()')) { dialog.accept } end cancel = Qt::PushButton.new('Cancel') do connect(SIGNAL('clicked()')) { dialog.reject } end = Qt::HBoxLayout.new do addWidget(ok) addWidget(cancel) end dialog.layout = Qt::VBoxLayout.new do addWidget(colorblind_box) addLayout() end case dialog.exec when Qt::Dialog::Accepted if (colorblind_box.checkState() == Qt::Checked) @colorblind = true else @colorblind = false end (0...@scroll_layout.count).each do |index| @scroll_layout.itemAt(index)..set_colorblind(@colorblind) end end dialog.dispose end end |
#update_gui_item(widget, value, limits_state, limits_set) ⇒ Object
Update out of limit item with a values
691 692 693 694 695 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 691 def update_gui_item(, value, limits_state, limits_set) Qt.execute_in_main_thread(true) do .set_values(value, limits_state, limits_set) if end end |
#update_log(message, color) ⇒ Object
Update the log panel with limits change information.
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 721 def update_log(, color) return if @cancel_thread Qt.execute_in_main_thread(true) do @tf ||= Qt::TextCharFormat.new case color when :GREEN brush = Cosmos.getBrush(Cosmos::GREEN) when :YELLOW brush = Cosmos.getBrush(Cosmos::YELLOW) when :RED brush = Cosmos.getBrush(Cosmos::RED) when :BLUE brush = Cosmos.getBrush(Cosmos::BLUE) else # :BLACK brush = Cosmos.getBrush(Cosmos::BLACK) end @tf.setForeground(brush) @log_output.setCurrentCharFormat(@tf) @log_output.appendPlainText(.chomp) end end |
#update_overall_limits_state(state) ⇒ Object
Changes the limits state on the status bar at the top of the screen.
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 767 def update_overall_limits_state(state) Qt.execute_in_main_thread(true) do text = '' case state when :STALE palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,255)) @monitored_state_text_field.setPalette(palette) text = 'Stale' when :GREEN, :GREEN_HIGH, :GREEN_LOW palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,255,0)) @monitored_state_text_field.setPalette(palette) text = 'Green' when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,255,0)) @monitored_state_text_field.setPalette(palette) text = 'Yellow' when :RED, :RED_HIGH, :RED_LOW palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,0)) @monitored_state_text_field.setPalette(palette) text = 'Red' when :BLUE palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,0,255)) @monitored_state_text_field.setPalette(palette) text = 'Blue' end text << ' - Some Items Ignored' if @limits_items.ignored_items? @monitored_state_text_field.text = text end end |
#value_thread ⇒ Object
Thread to request the out of limits values and update them at 1Hz. Also updates the status bar at the top of the front panel indicating the overall limits value of the system.
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/cosmos/tools/limits_monitor/limits_monitor.rb', line 746 def value_thread @value_thread = Thread.new do while true break if @cancel_thread Qt.execute_in_main_thread(true) do if @limits_items.initialized @limits_items.update_values() update_overall_limits_state(@limits_items.overall_state()) else # Set the status bar message to expire in 2s since this runs at 1Hz statusBar.showMessage('Error Connecting to Command and Telemetry Server', 2000) end end break if @value_sleeper.sleep(1) end end rescue Exception => error Cosmos.handle_fatal_exception(error) end |