cosmos 3.4.2 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Manifest.txt +69 -11
- data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +23 -0
- data/autohotkey/tools/TestRunnerAHK5 +17 -0
- data/autohotkey/tools/TestRunnerAHK6 +17 -0
- data/autohotkey/tools/cmd_extractor.ahk +6 -0
- data/autohotkey/tools/data_viewer.ahk +6 -0
- data/autohotkey/tools/limits_monitor.ahk +67 -14
- data/autohotkey/tools/replay.ahk +6 -0
- data/autohotkey/tools/test_runner5.ahk +8 -0
- data/autohotkey/tools/test_runner6.ahk +5 -0
- data/autohotkey/tools/tlm_extractor.ahk +25 -1
- data/autohotkey/tools/tlm_grapher.ahk +6 -0
- data/cosmos.gemspec +19 -19
- data/data/crc.txt +46 -46
- data/data/critical.wav +0 -0
- data/data/information.wav +0 -0
- data/data/input.wav +0 -0
- data/data/message.wav +0 -0
- data/data/question.wav +0 -0
- data/data/warning.wav +0 -0
- data/demo/Gemfile +5 -1
- data/demo/Launcher +5 -4
- data/demo/Launcher.bat +6 -56
- data/demo/config/data/crc.txt +73 -55
- data/demo/config/system/system.txt +1 -0
- data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +2 -0
- data/demo/procedures/example_test.rb +17 -16
- data/demo/tools/CmdExtractor +6 -5
- data/demo/tools/CmdExtractor.bat +6 -56
- data/demo/tools/CmdSender +6 -5
- data/demo/tools/CmdSender.bat +6 -56
- data/demo/tools/CmdTlmServer +6 -5
- data/demo/tools/CmdTlmServer.bat +6 -56
- data/demo/tools/DataViewer +6 -5
- data/demo/tools/DataViewer.bat +6 -56
- data/demo/tools/ExampleTarget +6 -5
- data/demo/tools/ExampleTarget.bat +6 -56
- data/demo/tools/HandbookCreator +6 -5
- data/demo/tools/HandbookCreator.bat +6 -58
- data/demo/tools/Launcher +6 -5
- data/demo/tools/Launcher.bat +6 -56
- data/demo/tools/LimitsMonitor +6 -5
- data/demo/tools/LimitsMonitor.bat +6 -56
- data/demo/tools/OpenGLBuilder +6 -5
- data/demo/tools/OpenGLBuilder.bat +6 -56
- data/demo/tools/PacketViewer +6 -5
- data/demo/tools/PacketViewer.bat +6 -56
- data/demo/tools/Replay +6 -5
- data/demo/tools/Replay.bat +6 -56
- data/demo/tools/ScpiTarget +6 -5
- data/demo/tools/ScpiTarget.bat +6 -56
- data/demo/tools/ScriptRunner +6 -5
- data/demo/tools/ScriptRunner.bat +6 -56
- data/demo/tools/TableManager +6 -5
- data/demo/tools/TableManager.bat +6 -56
- data/demo/tools/TestRunner +6 -5
- data/demo/tools/TestRunner.bat +6 -56
- data/demo/tools/TlmExtractor +6 -5
- data/demo/tools/TlmExtractor.bat +6 -56
- data/demo/tools/TlmGrapher +6 -5
- data/demo/tools/TlmGrapher.bat +6 -56
- data/demo/tools/TlmViewer +6 -5
- data/demo/tools/TlmViewer.bat +6 -56
- data/demo/tools/ToolLaunch.bat +63 -0
- data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +6 -5
- data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +6 -5
- data/demo/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +6 -5
- data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +6 -5
- data/demo/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +6 -5
- data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +6 -5
- data/demo/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +6 -5
- data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +6 -5
- data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +6 -5
- data/demo/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +6 -5
- data/demo/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +6 -5
- data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +6 -5
- data/demo/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +6 -5
- data/demo/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +6 -5
- data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +6 -5
- data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +6 -5
- data/demo/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/demo/tools/tool_launch.rb +38 -0
- data/install/Gemfile +5 -1
- data/install/Launcher +5 -3
- data/install/Launcher.bat +6 -56
- data/install/config/data/crc.txt +67 -49
- data/install/config/tools/launcher/launcher.txt +1 -0
- data/install/tools/CmdExtractor +6 -5
- data/install/tools/CmdExtractor.bat +6 -56
- data/install/tools/CmdSender +6 -5
- data/install/tools/CmdSender.bat +6 -56
- data/install/tools/CmdTlmServer +6 -5
- data/install/tools/CmdTlmServer.bat +6 -56
- data/install/tools/DataViewer +6 -5
- data/install/tools/DataViewer.bat +6 -56
- data/install/tools/HandbookCreator +6 -5
- data/install/tools/HandbookCreator.bat +6 -58
- data/install/tools/Launcher +6 -5
- data/install/tools/Launcher.bat +6 -56
- data/install/tools/LimitsMonitor +6 -5
- data/install/tools/LimitsMonitor.bat +6 -56
- data/install/tools/OpenGLBuilder +6 -5
- data/install/tools/OpenGLBuilder.bat +6 -56
- data/install/tools/PacketViewer +6 -5
- data/install/tools/PacketViewer.bat +6 -56
- data/install/tools/Replay +6 -5
- data/install/tools/Replay.bat +6 -56
- data/install/tools/ScriptRunner +6 -5
- data/install/tools/ScriptRunner.bat +6 -56
- data/install/tools/TableManager +6 -5
- data/install/tools/TableManager.bat +6 -56
- data/install/tools/TestRunner +6 -5
- data/install/tools/TestRunner.bat +6 -56
- data/install/tools/TlmExtractor +6 -5
- data/install/tools/TlmExtractor.bat +6 -56
- data/install/tools/TlmGrapher +6 -5
- data/install/tools/TlmGrapher.bat +6 -56
- data/install/tools/TlmViewer +6 -5
- data/install/tools/TlmViewer.bat +6 -56
- data/install/tools/ToolLaunch.bat +63 -0
- data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +6 -5
- data/install/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +6 -5
- data/install/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +6 -5
- data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +6 -5
- data/install/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +6 -5
- data/install/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +6 -5
- data/install/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +6 -5
- data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +6 -5
- data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +6 -5
- data/install/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +6 -5
- data/install/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +6 -5
- data/install/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +6 -5
- data/install/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +6 -5
- data/install/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +6 -5
- data/install/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +6 -5
- data/install/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +6 -5
- data/install/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -0
- data/install/tools/tool_launch.rb +38 -0
- data/lib/cosmos/core_ext/string.rb +3 -2
- data/lib/cosmos/gui/dialogs/about_dialog.rb +3 -7
- data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +200 -136
- data/lib/cosmos/gui/opengl/gl_viewer.rb +8 -8
- data/lib/cosmos/gui/qt.rb +56 -27
- data/lib/cosmos/gui/qt_tool.rb +3 -1
- data/lib/cosmos/gui/text/ruby_editor.rb +130 -110
- data/lib/cosmos/gui/utilities/script_module_gui.rb +150 -4
- data/lib/cosmos/io/json_drb.rb +1 -1
- data/lib/cosmos/io/win32_serial_driver.rb +2 -4
- data/lib/cosmos/packet_logs/ccsds_log_reader.rb +1 -0
- data/lib/cosmos/packet_logs/packet_log_reader.rb +13 -4
- data/lib/cosmos/packets/limits.rb +6 -3
- data/lib/cosmos/packets/telemetry.rb +34 -3
- data/lib/cosmos/processors/new_packet_log_processor.rb +1 -1
- data/lib/cosmos/script/commands.rb +20 -2
- data/lib/cosmos/script/extract.rb +11 -3
- data/lib/cosmos/script/limits.rb +6 -0
- data/lib/cosmos/script/scripting.rb +17 -9
- data/lib/cosmos/system/system.rb +73 -17
- data/lib/cosmos/system/target.rb +10 -5
- data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +1 -0
- data/lib/cosmos/tools/cmd_tlm_server/api.rb +95 -0
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +8 -4
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +55 -0
- data/lib/cosmos/tools/data_viewer/data_viewer.rb +5 -12
- data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +14 -48
- data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -5
- data/lib/cosmos/tools/launcher/launcher.rb +4 -0
- data/lib/cosmos/tools/launcher/launcher_config.rb +50 -0
- data/lib/cosmos/tools/launcher/launcher_tool.rb +21 -9
- data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +607 -566
- data/lib/cosmos/tools/replay/replay.rb +51 -45
- data/lib/cosmos/tools/script_runner/script_runner.rb +13 -5
- data/lib/cosmos/tools/script_runner/script_runner_frame.rb +8 -109
- data/lib/cosmos/tools/test_runner/test.rb +65 -6
- data/lib/cosmos/tools/test_runner/test_runner.rb +4 -4
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +5 -0
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +3 -0
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +3 -2
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +9 -6
- data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +1 -5
- data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +1 -5
- data/lib/cosmos/top_level.rb +86 -3
- data/lib/cosmos/version.rb +5 -5
- data/lib/cosmos/win32/win32_main.rb +7 -1
- data/spec/packet_logs/packet_log_reader_spec.rb +67 -7
- data/spec/packets/limits_spec.rb +19 -1
- data/spec/packets/telemetry_spec.rb +44 -1
- data/spec/script/commands_spec.rb +14 -0
- data/spec/script/scripting_spec.rb +5 -1
- data/spec/script/telemetry_spec.rb +38 -3
- data/spec/system/system_spec.rb +24 -4
- data/spec/tools/cmd_tlm_server/api_spec.rb +30 -0
- data/test/benchmarks/gsub_benchmark.rb +42 -4
- data/test/benchmarks/is_a_benchmark.rb +34 -0
- data/test/performance/config/data/crc.txt +161 -171
- data/test/performance/config/system/system_packets.txt +10 -10
- data/test/performance/config/system/system_threads.txt +30 -30
- data/test/performance/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +7 -2
- data/test/performance/config/targets/PACKET/cmd_tlm/packet_cmds.txt +20 -0
- data/test/performance/config/targets/PACKET/cmd_tlm/packet_tlm.txt +98 -0
- data/test/performance/config/targets/{EXAMPLE → PACKET}/cmd_tlm_server.txt +2 -2
- data/test/performance/config/targets/PACKET/lib/packet_interface.rb +22 -0
- data/test/performance/config/targets/PACKET/lib/packet_limits_response.rb +24 -0
- data/test/performance/config/targets/PACKET/screens/status.txt +25 -0
- data/test/performance/config/targets/PACKET/target.txt +28 -0
- data/test/performance/config/targets/{EXAMPLE/cmd_tlm/example_cmds.txt → THREAD/cmd_tlm/thread_cmds.txt} +1 -1
- data/test/performance/config/targets/{EXAMPLE/cmd_tlm/example_tlm.txt → THREAD/cmd_tlm/thread_tlm.txt} +1 -1
- data/test/performance/config/targets/THREAD/cmd_tlm_server.txt +6 -0
- data/test/performance/config/targets/{EXAMPLE/lib/example_interface.rb → THREAD/lib/thread_interface.rb} +1 -1
- data/test/performance/config/targets/THREAD/screens/status.txt +25 -0
- data/test/performance/config/targets/{EXAMPLE → THREAD}/target.txt +0 -0
- data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_packets.txt +24 -30
- data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_threads.txt +31 -31
- data/test/performance/config/tools/launcher/launcher_packets.txt +16 -11
- data/test/performance/config/tools/launcher/launcher_threads.txt +41 -35
- data/test/performance/config/tools/tlm_grapher/tlm_grapher.txt +204 -0
- data/test/performance/config/tools/tlm_viewer/tlm_viewer.txt +10 -38
- data/test/performance/lib/packet_target.rb +126 -0
- data/test/performance/lib/{example_target.rb → thread_target.rb} +9 -9
- data/test/performance/tools/CmdTlmServerMemProf +1 -1
- data/test/performance/tools/{ExampleTarget → PacketTarget} +2 -2
- data/test/performance/tools/{ExampleTarget.bat → PacketTarget.bat} +0 -0
- data/test/performance/tools/ThreadTarget +14 -0
- data/test/performance/tools/ThreadTarget.bat +59 -0
- data/test/performance/tools/TlmGrapherMemProf +1 -1
- data/test/performance/tools/TlmViewerMemProf +19 -0
- data/{autohotkey/tools/Replay.bat → test/performance/tools/TlmViewerMemProf.bat} +1 -1
- metadata +107 -55
- data/test/performance/lib/example_background_task.rb +0 -57
- data/test/performance/lib/scpi_target.rb +0 -74
|
@@ -180,28 +180,20 @@ module Cosmos
|
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
def find
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
@find_dialog.connect(SIGNAL('find_next()')) do
|
|
186
|
-
current_component do |component|
|
|
187
|
-
component.find(@find_dialog)
|
|
188
|
-
end
|
|
189
|
-
end
|
|
183
|
+
current_component do |component|
|
|
184
|
+
FindReplaceDialog.show_find(component.text)
|
|
190
185
|
end
|
|
191
|
-
@find_dialog.show
|
|
192
|
-
@find_dialog.raise
|
|
193
|
-
@find_dialog.activateWindow
|
|
194
186
|
end
|
|
195
187
|
|
|
196
188
|
def find_next
|
|
197
189
|
current_component do |component|
|
|
198
|
-
|
|
190
|
+
FindReplaceDialog.find_next(component.text)
|
|
199
191
|
end
|
|
200
192
|
end
|
|
201
193
|
|
|
202
194
|
def find_previous
|
|
203
195
|
current_component do |component|
|
|
204
|
-
|
|
196
|
+
FindReplaceDialog.find_previous(component.text)
|
|
205
197
|
end
|
|
206
198
|
end
|
|
207
199
|
|
|
@@ -435,6 +427,7 @@ module Cosmos
|
|
|
435
427
|
file_size = File.size(filename).to_f
|
|
436
428
|
dialog.append_text("Processing: #{filename}")
|
|
437
429
|
|
|
430
|
+
Cosmos.check_log_configuration(@packet_log_reader, filename)
|
|
438
431
|
@packet_log_reader.each(filename, true, @time_start, @time_end) do |packet|
|
|
439
432
|
break if @cancel_progress
|
|
440
433
|
progress = @packet_log_reader.bytes_read.to_f / file_size
|
|
@@ -15,8 +15,12 @@ module Cosmos
|
|
|
15
15
|
class DataViewerComponent < Qt::Widget
|
|
16
16
|
attr_reader :tab_name
|
|
17
17
|
attr_reader :packets
|
|
18
|
+
attr_reader :text
|
|
18
19
|
|
|
19
|
-
#
|
|
20
|
+
# Create a component to go inside the DataViewer
|
|
21
|
+
#
|
|
22
|
+
# @param parent [Qt::Widget] Parent widget
|
|
23
|
+
# @param tab_name [String] Name of the tab which displays this widget
|
|
20
24
|
def initialize(parent, tab_name)
|
|
21
25
|
super(parent)
|
|
22
26
|
@tab_name = tab_name
|
|
@@ -28,6 +32,9 @@ module Cosmos
|
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
# Adds a packet to the list of packets this components processes
|
|
35
|
+
#
|
|
36
|
+
# @param target_name [String] Name of the target
|
|
37
|
+
# @param packet_name [String] Name of the packet
|
|
31
38
|
def add_packet(target_name, packet_name)
|
|
32
39
|
@packets << [target_name, packet_name]
|
|
33
40
|
end
|
|
@@ -39,11 +46,7 @@ module Cosmos
|
|
|
39
46
|
@text = Qt::PlainTextEdit.new
|
|
40
47
|
@text.setReadOnly(true)
|
|
41
48
|
@text.setMaximumBlockCount(@max_block_count)
|
|
42
|
-
|
|
43
|
-
@text.font = Cosmos.getFont("courier", 9)
|
|
44
|
-
else
|
|
45
|
-
@text.font = Cosmos.getFont("courier", 12)
|
|
46
|
-
end
|
|
49
|
+
@text.font = Cosmos.get_default_small_font
|
|
47
50
|
@text.setWordWrapMode(Qt::TextOption::NoWrap)
|
|
48
51
|
@top_layout.addWidget(@text)
|
|
49
52
|
|
|
@@ -93,49 +96,12 @@ module Cosmos
|
|
|
93
96
|
@text.setPlainText("")
|
|
94
97
|
end
|
|
95
98
|
|
|
96
|
-
def find(dialog)
|
|
97
|
-
found = @text.find(dialog.find_text, dialog.find_flags)
|
|
98
|
-
if not found and dialog.wrap_around?
|
|
99
|
-
cursor = @text.textCursor
|
|
100
|
-
if dialog.find_up?
|
|
101
|
-
cursor.movePosition(Qt::TextCursor::End)
|
|
102
|
-
else
|
|
103
|
-
cursor.movePosition(Qt::TextCursor::Start)
|
|
104
|
-
end
|
|
105
|
-
@text.setTextCursor(cursor)
|
|
106
|
-
@text.find(dialog.find_text, dialog.find_flags)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def find_next(dialog)
|
|
111
|
-
flags = dialog.find_flags
|
|
112
|
-
flags &= ~Qt::TextDocument::FindBackward.to_i
|
|
113
|
-
found = @text.find(dialog.find_text, flags)
|
|
114
|
-
if not found and dialog.wrap_around?
|
|
115
|
-
cursor = @text.textCursor
|
|
116
|
-
cursor.movePosition(Qt::TextCursor::Start)
|
|
117
|
-
@text.setTextCursor(cursor)
|
|
118
|
-
@text.find(dialog.find_text, flags)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def find_previous(dialog)
|
|
123
|
-
flags = dialog.find_flags
|
|
124
|
-
flags |= Qt::TextDocument::FindBackward.to_i
|
|
125
|
-
found = @text.find(dialog.find_text, flags)
|
|
126
|
-
if not found and dialog.wrap_around?
|
|
127
|
-
cursor = @text.textCursor
|
|
128
|
-
cursor.movePosition(Qt::TextCursor::End)
|
|
129
|
-
@text.setTextCursor(cursor)
|
|
130
|
-
@text.find(dialog.find_text, flags)
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
99
|
def showEvent(event)
|
|
135
|
-
# When the tab is shown we want to ensure the scroll bar is at the
|
|
136
|
-
# the PlainTextArea to automatically hold the scroll
|
|
137
|
-
#
|
|
138
|
-
#
|
|
100
|
+
# When the tab is shown we want to ensure the scroll bar is at the
|
|
101
|
+
# maximum to allow the PlainTextArea to automatically hold the scroll
|
|
102
|
+
# at the bottom of the display while appending things.
|
|
103
|
+
# If this is not done, switching tabs will cause the scroll bar
|
|
104
|
+
# to "stick" and not stay at the bottom with the newest text.
|
|
139
105
|
@timer.start(100)
|
|
140
106
|
end
|
|
141
107
|
|
|
@@ -83,11 +83,7 @@ module Cosmos
|
|
|
83
83
|
if @pdf
|
|
84
84
|
if progress_dialog
|
|
85
85
|
Qt.execute_in_main_thread(true) do
|
|
86
|
-
|
|
87
|
-
progress_dialog.set_text_font(Cosmos.getFont("courier",10))
|
|
88
|
-
else
|
|
89
|
-
progress_dialog.set_text_font(Cosmos.getFont("courier",14))
|
|
90
|
-
end
|
|
86
|
+
progress_dialog.set_text_font(Cosmos.get_default_font)
|
|
91
87
|
end
|
|
92
88
|
end
|
|
93
89
|
Cosmos.set_working_dir do
|
|
@@ -23,6 +23,10 @@ module Cosmos
|
|
|
23
23
|
|
|
24
24
|
def initialize(options)
|
|
25
25
|
super(options) # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes
|
|
26
|
+
|
|
27
|
+
# Set environment variable of COSMOS_USERPATH so that all launched apps know where to find the configuration
|
|
28
|
+
ENV['COSMOS_USERPATH'] = Cosmos::USERPATH
|
|
29
|
+
|
|
26
30
|
Cosmos.load_cosmos_icon("launcher.png")
|
|
27
31
|
layout.setSizeConstraint(Qt::Layout::SetFixedSize)
|
|
28
32
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
require 'cosmos'
|
|
12
12
|
require 'cosmos/config/config_parser'
|
|
13
13
|
require 'ostruct'
|
|
14
|
+
require 'bundler'
|
|
14
15
|
|
|
15
16
|
module Cosmos
|
|
16
17
|
|
|
@@ -62,6 +63,9 @@ module Cosmos
|
|
|
62
63
|
# Handle each keyword
|
|
63
64
|
case keyword
|
|
64
65
|
|
|
66
|
+
when 'AUTO_GEM_TOOLS'
|
|
67
|
+
parse_gem_tool(parser)
|
|
68
|
+
|
|
65
69
|
when 'TOOL'
|
|
66
70
|
parse_tool(parser, params, multitool)
|
|
67
71
|
|
|
@@ -140,6 +144,25 @@ module Cosmos
|
|
|
140
144
|
|
|
141
145
|
protected
|
|
142
146
|
|
|
147
|
+
def parse_gem_tool(parser)
|
|
148
|
+
parser.verify_num_parameters(0, 0, parser.keyword)
|
|
149
|
+
Bundler.load.specs.each do |spec|
|
|
150
|
+
spec_name_split = spec.name.split('-')
|
|
151
|
+
if spec_name_split.length > 1 and spec_name_split[0] == 'cosmos'
|
|
152
|
+
# Filter to just tools and not targets
|
|
153
|
+
if File.exist?(File.join(spec.gem_dir, 'tools'))
|
|
154
|
+
Dir[File.join(spec.gem_dir, 'tools', '*')].each do |filename|
|
|
155
|
+
if File.extname(filename) == ''
|
|
156
|
+
@items << [:TOOL, File.basename(filename), format_shell_command(parser, "LAUNCH_GEM #{File.basename(filename)}"), true, File.basename(filename).class_name_to_filename(false) + '.png', nil]
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
rescue Bundler::GemfileNotFound
|
|
163
|
+
# No Gemfile - so no gem based tools
|
|
164
|
+
end
|
|
165
|
+
|
|
143
166
|
def parse_tool(parser, params, multitool)
|
|
144
167
|
if multitool
|
|
145
168
|
parser.verify_num_parameters(1, 1, "TOOL <Shell command>")
|
|
@@ -165,6 +188,8 @@ module Cosmos
|
|
|
165
188
|
formatted_command = parse_launch(shell_command)
|
|
166
189
|
when 'LAUNCH_TERMINAL'
|
|
167
190
|
formatted_command = parse_launch_terminal(shell_command)
|
|
191
|
+
when 'LAUNCH_GEM'
|
|
192
|
+
formatted_command = parse_launch_gem(shell_command)
|
|
168
193
|
else
|
|
169
194
|
# Nothing to do if they aren't using our keywords
|
|
170
195
|
formatted_command = shell_command
|
|
@@ -201,6 +226,31 @@ module Cosmos
|
|
|
201
226
|
formatted
|
|
202
227
|
end
|
|
203
228
|
|
|
229
|
+
def parse_launch_gem(command)
|
|
230
|
+
split = command.split
|
|
231
|
+
|
|
232
|
+
# Find the gem with this file
|
|
233
|
+
begin
|
|
234
|
+
Bundler.load.specs.each do |spec|
|
|
235
|
+
spec_name_split = spec.name.split('-')
|
|
236
|
+
if spec_name_split.length > 1 and spec_name_split[0] == 'cosmos'
|
|
237
|
+
# Filter to just tools and not targets
|
|
238
|
+
if File.exist?(File.join(spec.gem_dir, 'tools', split[1]))
|
|
239
|
+
if Kernel.is_mac? and File.exist?(File.join(USERPATH, 'tools', 'mac'))
|
|
240
|
+
return "open #{spec.gem_dir}/tools/mac/#{split[1]}.app --args #{split[2..-1].join(' ')}".strip
|
|
241
|
+
else
|
|
242
|
+
return "RUBYW #{spec.gem_dir}/tools/#{split[1]} #{split[2..-1].join(' ')}".strip
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
rescue Bundler::GemfileNotFound
|
|
248
|
+
# No Gemfile - so no gem based tools
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
raise "Could not find gem containing tool: #{split[1]} - Make sure the appropriate gem is in your Gemfile"
|
|
252
|
+
end
|
|
253
|
+
|
|
204
254
|
end # class LauncherConfig
|
|
205
255
|
|
|
206
256
|
end # module Cosmos
|
|
@@ -12,7 +12,6 @@ require 'cosmos'
|
|
|
12
12
|
require 'cosmos/gui/qt'
|
|
13
13
|
|
|
14
14
|
module Cosmos
|
|
15
|
-
|
|
16
15
|
class LauncherTool < Qt::Object
|
|
17
16
|
slots 'button_clicked()'
|
|
18
17
|
|
|
@@ -26,7 +25,7 @@ module Cosmos
|
|
|
26
25
|
|
|
27
26
|
def button_clicked
|
|
28
27
|
if @variable_parameters
|
|
29
|
-
parameters = parameters_dialog
|
|
28
|
+
parameters = parameters_dialog
|
|
30
29
|
if parameters
|
|
31
30
|
if @capture_io
|
|
32
31
|
Cosmos.run_process_check_output(@shell_command + ' ' + parameters)
|
|
@@ -44,7 +43,7 @@ module Cosmos
|
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
def parameters_dialog
|
|
47
|
-
dialog = Qt::Dialog.new(
|
|
46
|
+
dialog = Qt::Dialog.new(parent)
|
|
48
47
|
dialog.window_title = "#{@button_text} Options"
|
|
49
48
|
layout = Qt::VBoxLayout.new
|
|
50
49
|
dialog.layout = layout
|
|
@@ -53,10 +52,24 @@ module Cosmos
|
|
|
53
52
|
@variable_parameters.each do |parameter_name, parameter_value|
|
|
54
53
|
hlayout = Qt::HBoxLayout.new
|
|
55
54
|
hlayout.addWidget(Qt::Label.new(parameter_name))
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
parameter_options = parameter_value.split('|')
|
|
56
|
+
if parameter_options.length > 1
|
|
57
|
+
combo_box = Qt::ComboBox.new
|
|
58
|
+
combo_box.setEditable(true)
|
|
59
|
+
idx = 0
|
|
60
|
+
parameter_options.each do |option|
|
|
61
|
+
combo_box.insertItem(idx, option)
|
|
62
|
+
idx += 1
|
|
63
|
+
end
|
|
64
|
+
combo_box.setCurrentIndex(0) # Default Option is the first one
|
|
65
|
+
hlayout.addWidget(combo_box)
|
|
66
|
+
widgets << combo_box
|
|
67
|
+
else
|
|
68
|
+
line_edit = Qt::LineEdit.new
|
|
69
|
+
line_edit.setText(parameter_value)
|
|
70
|
+
hlayout.addWidget(line_edit)
|
|
71
|
+
widgets << line_edit
|
|
72
|
+
end
|
|
60
73
|
layout.addLayout(hlayout)
|
|
61
74
|
end
|
|
62
75
|
|
|
@@ -85,7 +98,7 @@ module Cosmos
|
|
|
85
98
|
if result == Qt::Dialog::Accepted
|
|
86
99
|
parameters = ''
|
|
87
100
|
index = 0
|
|
88
|
-
@variable_parameters.each do |parameter_name,
|
|
101
|
+
@variable_parameters.each do |parameter_name, _parameter_value|
|
|
89
102
|
parameters << parameter_name
|
|
90
103
|
parameters << ' '
|
|
91
104
|
parameters << widgets[index].text
|
|
@@ -100,5 +113,4 @@ module Cosmos
|
|
|
100
113
|
end
|
|
101
114
|
end
|
|
102
115
|
end
|
|
103
|
-
|
|
104
116
|
end
|
|
@@ -15,232 +15,460 @@ Cosmos.catch_fatal_exception do
|
|
|
15
15
|
require 'cosmos/gui/dialogs/cmd_tlm_raw_dialog'
|
|
16
16
|
require 'cosmos/script'
|
|
17
17
|
require 'cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget'
|
|
18
|
+
require 'cosmos/tools/tlm_viewer/widgets/label_widget'
|
|
19
|
+
require 'pathname'
|
|
18
20
|
end
|
|
19
21
|
|
|
22
|
+
# Extend Array to search for and delete telemetry items.
|
|
23
|
+
# Telemetry items are Arrays of [target name, packet name, item name].
|
|
20
24
|
class Array
|
|
21
25
|
def includes_item?(item)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return true
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
return false
|
|
26
|
+
found, index = find_item(item)
|
|
27
|
+
return found
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def delete_item(item)
|
|
31
|
+
found, index = find_item(item)
|
|
32
|
+
self.delete_at(index) if found
|
|
33
|
+
return index
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
def find_item(item)
|
|
38
|
+
found = false
|
|
31
39
|
index = 0
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
self.each do |target_name, packet_name, item_name|
|
|
41
|
+
if ((target_name == item[0]) &&
|
|
42
|
+
(packet_name == item[1]) &&
|
|
43
|
+
# If the item name is nil we're dealing with a packet
|
|
44
|
+
(item_name == item[2] || item_name.nil?))
|
|
45
|
+
found = true
|
|
36
46
|
break
|
|
37
47
|
end
|
|
38
48
|
index += 1
|
|
39
49
|
end
|
|
40
|
-
|
|
41
|
-
self.delete_at(delete_index) if delete_index
|
|
42
|
-
return delete_index
|
|
50
|
+
return found, index
|
|
43
51
|
end
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
module Cosmos
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@out_of_limits_items = []
|
|
56
|
+
class LimitsItems
|
|
57
|
+
# @return [Array<String,String,String>] Target name, packet name, item name
|
|
58
|
+
attr_reader :ignored
|
|
59
|
+
# @return [Boolean] Whether the limits items have been fetched from the server
|
|
60
|
+
attr_reader :initialized
|
|
61
|
+
|
|
62
|
+
UNKNOWN_ARRAY = ['UNKNOWN', 'UNKNOWN', nil]
|
|
63
|
+
|
|
64
|
+
# @param new_item_callback [Proc] Method to create a new item in the GUI
|
|
65
|
+
# @param update_item_callback [Proc] Method to update an item in the GUI
|
|
66
|
+
# @param clear_items_callback [Proc] Method to clear all items in the GUI
|
|
67
|
+
def initialize(new_item_callback, update_item_callback, clear_items_callback)
|
|
68
|
+
@new_item_callback = new_item_callback
|
|
69
|
+
@update_item_callback = update_item_callback
|
|
70
|
+
@clear_items_callback = clear_items_callback
|
|
71
|
+
@ignored = []
|
|
72
|
+
@items = {}
|
|
73
|
+
@out_of_limits = []
|
|
68
74
|
@queue_id = nil
|
|
69
|
-
@limits_set =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
@limits_set = :DEFAULT
|
|
76
|
+
request_reset()
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Request that the limits items be refreshed from the server
|
|
80
|
+
def request_reset
|
|
75
81
|
@initialized = false
|
|
76
|
-
|
|
77
|
-
@ignored_items = []
|
|
78
|
-
@ignored_filename = nil
|
|
79
|
-
@colorblind = false
|
|
80
|
-
@new_widgets = []
|
|
81
|
-
@buttons = []
|
|
82
|
-
@cancel_thread = false
|
|
83
|
-
@limits_sleeper = Sleeper.new
|
|
84
|
-
@value_sleeper = Sleeper.new
|
|
82
|
+
end
|
|
85
83
|
|
|
86
|
-
|
|
84
|
+
# Ignore an item. Don't display it in the GUI if it goes out of limits
|
|
85
|
+
# and don't have it count towards the overall limit state. Still display
|
|
86
|
+
# its limits transitions in the log.
|
|
87
|
+
#
|
|
88
|
+
# @param item [Array<String,String,String>] Target name, packet name,
|
|
89
|
+
# item name to ignore
|
|
90
|
+
def ignore(item)
|
|
91
|
+
index = @out_of_limits.delete_item(item)
|
|
92
|
+
@items.delete("#{item[0]} #{item[1]} #{item[2]}") if index
|
|
93
|
+
unless @ignored.includes_item?(item)
|
|
94
|
+
@ignored << item
|
|
95
|
+
end
|
|
96
|
+
end
|
|
87
97
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
# Remove an item from the ignored list to have it be displayed and
|
|
99
|
+
# count towards the overall limits state.
|
|
100
|
+
#
|
|
101
|
+
# @param item [Array<String,String,String> Target name, packet name,
|
|
102
|
+
# item name to remove from ignored list
|
|
103
|
+
def remove_ignored(item)
|
|
104
|
+
index = @ignored.delete_item(item)
|
|
105
|
+
if index
|
|
106
|
+
# If we deleted a packet we need to recalculate the stale packets
|
|
107
|
+
if item[2].empty?
|
|
108
|
+
get_stale(true).each do |target, packet|
|
|
109
|
+
stale_packet(target, packet)
|
|
110
|
+
end
|
|
111
|
+
# We deleted an item so get all the current out of limit items
|
|
112
|
+
else
|
|
113
|
+
get_out_of_limits().each do |target, packet, item, state|
|
|
114
|
+
limits_change(target, packet, item, state)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
rescue DRb::DRbConnError
|
|
119
|
+
# Do nothing
|
|
120
|
+
end
|
|
91
121
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
122
|
+
# @return [Boolean] Whether there are any items being ignored
|
|
123
|
+
def ignored_items?
|
|
124
|
+
!@ignored.empty?
|
|
125
|
+
end
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
@
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@state_label = Qt::Label.new('Monitored Limits State: ')
|
|
127
|
+
# @return [Symbol] The overall limits state. Returns :STALE if there
|
|
128
|
+
# is no connection to the server.
|
|
129
|
+
def overall_state
|
|
130
|
+
get_overall_limits_state(@ignored)
|
|
131
|
+
rescue DRb::DRbConnError
|
|
132
|
+
:STALE
|
|
133
|
+
end
|
|
105
134
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
135
|
+
# Calls get_limits_event to process all the server limits events that
|
|
136
|
+
# were subscribed to. This method should be called continuously until
|
|
137
|
+
# it returns nil which indicates no more events.
|
|
138
|
+
#
|
|
139
|
+
# @return [Array<String,Symbol] String describing the event and a symbol
|
|
140
|
+
# indicating how the event string should be colored (:BLACK, :BLUE,
|
|
141
|
+
# :GREEN, :YELLOW, or :RED)
|
|
142
|
+
def process_events
|
|
143
|
+
result = nil
|
|
144
|
+
type = nil
|
|
145
|
+
data = nil
|
|
146
|
+
begin
|
|
147
|
+
reset() unless @initialized
|
|
148
|
+
# Get events non-blocking which is why we rescue ThreadError
|
|
149
|
+
type, data = get_limits_event(@queue_id, true)
|
|
150
|
+
rescue ThreadError
|
|
151
|
+
# Do nothing (nominal exception if there are no events)
|
|
152
|
+
rescue DRb::DRbConnError
|
|
153
|
+
# The server is down so request a reset
|
|
154
|
+
request_reset()
|
|
155
|
+
end
|
|
156
|
+
return result unless type
|
|
157
|
+
|
|
158
|
+
case type
|
|
159
|
+
when :LIMITS_CHANGE
|
|
160
|
+
# The most common event: target, packet, item, state
|
|
161
|
+
result = limits_change(data[0], data[1], data[2], data[4])
|
|
162
|
+
|
|
163
|
+
when :LIMITS_SET
|
|
164
|
+
# Check if the overall limits set changed. If so we need to reset
|
|
165
|
+
# to incorporate all the new limits.
|
|
166
|
+
if @limits_set != data
|
|
167
|
+
request_reset()
|
|
168
|
+
result = ["INFO: Limits Set Changed to: #{data}\n", :BLACK]
|
|
169
|
+
end
|
|
115
170
|
|
|
116
|
-
|
|
171
|
+
when :LIMITS_SETTINGS
|
|
172
|
+
# The limits settings for an individual item changed. Set our local tool
|
|
173
|
+
# knowledge of the limits to match the server.
|
|
174
|
+
begin
|
|
175
|
+
System.limits.set(data[0], data[1], data[2], data[6], data[7], data[8], data[9], data[10], data[11], data[3], data[4], data[5])
|
|
176
|
+
result = ["INFO: Limits Settings Changed: #{data}\n", :BLACK]
|
|
177
|
+
rescue
|
|
178
|
+
# This can fail if we missed setting the DEFAULT limits set earlier
|
|
179
|
+
end
|
|
117
180
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
181
|
+
when :STALE_PACKET
|
|
182
|
+
# A packet has gone stale: target, packet
|
|
183
|
+
result = stale_packet(data[0], data[1])
|
|
184
|
+
end
|
|
185
|
+
result
|
|
186
|
+
end
|
|
122
187
|
|
|
123
|
-
|
|
188
|
+
# Update the values for all the out of limits items being tracked.
|
|
189
|
+
def update_values
|
|
190
|
+
# Reject any out of limits packets as they don't have values
|
|
191
|
+
items = @out_of_limits.reject {|item| item[2].nil? }
|
|
124
192
|
|
|
125
|
-
|
|
126
|
-
|
|
193
|
+
values, limits_states, limits_settings, limits_set = get_tlm_values(items, :WITH_UNITS)
|
|
194
|
+
index = 0
|
|
195
|
+
items.each do |target_name, packet_name, item_name|
|
|
196
|
+
begin
|
|
197
|
+
# Update the limits settings each time we update values
|
|
198
|
+
# to stay in sync with the Server. Responding to :LIMITS_SETTINGS
|
|
199
|
+
# events isn't enough since we don't get those upon startup.
|
|
200
|
+
System.limits.set(target_name, packet_name, item_name,
|
|
201
|
+
limits_settings[index][0], limits_settings[index][1],
|
|
202
|
+
limits_settings[index][2], limits_settings[index][3],
|
|
203
|
+
limits_settings[index][4], limits_settings[index][5],
|
|
204
|
+
limits_set) if limits_settings[index]
|
|
205
|
+
rescue
|
|
206
|
+
# This can fail if we missed setting the DEFAULT limits set earlier
|
|
207
|
+
end
|
|
208
|
+
name = "#{target_name} #{packet_name} #{item_name}"
|
|
209
|
+
@update_item_callback.call(@items[name], values[index], limits_states[index], limits_set)
|
|
210
|
+
index += 1
|
|
211
|
+
end
|
|
212
|
+
rescue DRb::DRbConnError
|
|
213
|
+
# Do nothing
|
|
214
|
+
end
|
|
127
215
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
216
|
+
# Load a new configuration of ignored items and packets and reset
|
|
217
|
+
#
|
|
218
|
+
# @param config_file [String] Configuration file base name which will be
|
|
219
|
+
# expanded to find a file in the config/tools/limits_monitor dir.
|
|
220
|
+
# @return [String] Message indicating success or fail
|
|
221
|
+
def open_config(filename)
|
|
222
|
+
return "" unless filename
|
|
223
|
+
|
|
224
|
+
unless Pathname.new(filename).absolute?
|
|
225
|
+
filename = File.join(::Cosmos::USERPATH, 'config', 'tools', 'limits_monitor', filename)
|
|
226
|
+
end
|
|
227
|
+
return "Configuration file #{filename} not found!" unless File.exist?(filename)
|
|
131
228
|
|
|
132
|
-
@
|
|
133
|
-
|
|
229
|
+
@ignored = []
|
|
230
|
+
begin
|
|
231
|
+
parser = ConfigParser.new
|
|
232
|
+
parser.parse_file(filename) do |keyword, params|
|
|
233
|
+
case keyword
|
|
234
|
+
# TODO: Eventually we can deprecate 'IGNORE' in favor
|
|
235
|
+
# of 'IGNORE_ITEM' now that we also have 'IGNORE_PACKET'
|
|
236
|
+
when 'IGNORE', 'IGNORE_ITEM'
|
|
237
|
+
@ignored << ([params[0], params[1], params[2]])
|
|
238
|
+
when 'IGNORE_PACKET'
|
|
239
|
+
@ignored << ([params[0], params[1], nil])
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
result = "#{filename} loaded. "
|
|
243
|
+
result << "Warning: Some items ignored" if ignored_items?
|
|
244
|
+
rescue => e
|
|
245
|
+
result = "Error loading configuration : #{e.message}"
|
|
246
|
+
end
|
|
247
|
+
# Since we may have loaded new ignored items we need to reset
|
|
248
|
+
request_reset()
|
|
249
|
+
result
|
|
250
|
+
end
|
|
134
251
|
|
|
135
|
-
|
|
136
|
-
|
|
252
|
+
# Save the current configuration of ignored items and packets.
|
|
253
|
+
#
|
|
254
|
+
# @param config_file [String] Configuration file to save.
|
|
255
|
+
# @return [String] Message indicating success or fail
|
|
256
|
+
def save_config(filename)
|
|
257
|
+
begin
|
|
258
|
+
File.open(filename, "w") do |file|
|
|
259
|
+
@ignored.each do |target, pkt_name, item_name|
|
|
260
|
+
if item_name
|
|
261
|
+
file.puts("IGNORE_ITEM #{target} #{pkt_name} #{item_name}")
|
|
262
|
+
else
|
|
263
|
+
file.puts("IGNORE_PACKET #{target} #{pkt_name}")
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
result = "#{filename} saved"
|
|
268
|
+
rescue => e
|
|
269
|
+
result = "Error saving configuration : #{e.message}"
|
|
270
|
+
end
|
|
271
|
+
result
|
|
272
|
+
end
|
|
137
273
|
|
|
138
|
-
|
|
139
|
-
value_thread()
|
|
140
|
-
limits_thread()
|
|
141
|
-
end # initialize
|
|
274
|
+
private
|
|
142
275
|
|
|
143
|
-
#
|
|
276
|
+
# Clear all tracked out of limits items and resubscribe to the server
|
|
277
|
+
# limits events. Clear the GUI and re-create all out of limits items
|
|
278
|
+
# and stale packets.
|
|
144
279
|
#
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
280
|
+
# Note this method can raise a DRb::DRbConnError error!
|
|
281
|
+
def reset
|
|
282
|
+
@items = {}
|
|
283
|
+
@out_of_limits = []
|
|
284
|
+
@limits_set = get_limits_set()
|
|
285
|
+
unsubscribe_limits_events(@queue_id) if @queue_id
|
|
286
|
+
@queue_id = subscribe_limits_events(100000)
|
|
287
|
+
@clear_items_callback.call
|
|
288
|
+
get_out_of_limits().each do |target, packet, item, state|
|
|
289
|
+
limits_change(target, packet, item, state)
|
|
290
|
+
end
|
|
291
|
+
get_stale(true).each do |target, packet|
|
|
292
|
+
stale_packet(target, packet)
|
|
293
|
+
end
|
|
154
294
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
new_widget.set_setting('COLORBLIND', [@colorblind])
|
|
158
|
-
new_widget.process_settings
|
|
295
|
+
@initialized = true
|
|
296
|
+
end
|
|
159
297
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
298
|
+
# Process a limits_change event by recoloring out of limits events
|
|
299
|
+
# and creating a log message.
|
|
300
|
+
def limits_change(target_name, packet_name, item_name, state)
|
|
301
|
+
message = ''
|
|
302
|
+
color = :BLACK
|
|
303
|
+
item = [target_name, packet_name, item_name]
|
|
304
|
+
|
|
305
|
+
case state
|
|
306
|
+
when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
|
|
307
|
+
message << "WARN: "
|
|
308
|
+
color = :YELLOW
|
|
309
|
+
out_of_limit(item)
|
|
310
|
+
when :RED, :RED_HIGH, :RED_LOW
|
|
311
|
+
message << "ERROR: "
|
|
312
|
+
color = :RED
|
|
313
|
+
out_of_limit(item)
|
|
314
|
+
when :GREEN, :GREEN_HIGH, :GREEN_LOW
|
|
315
|
+
message << "INFO: "
|
|
316
|
+
color = :GREEN
|
|
317
|
+
when :BLUE
|
|
318
|
+
message << "INFO: "
|
|
319
|
+
color = :BLUE
|
|
320
|
+
end
|
|
321
|
+
value = tlm(target_name, packet_name, item_name)
|
|
322
|
+
message << "#{target_name} #{packet_name} #{item_name} = #{value} is #{state}\n"
|
|
323
|
+
[message, color]
|
|
324
|
+
end
|
|
164
325
|
|
|
165
|
-
|
|
326
|
+
# Record the stale packet and generate a log message
|
|
327
|
+
def stale_packet(target_name, packet_name)
|
|
328
|
+
out_of_limit([target_name, packet_name, nil])
|
|
329
|
+
return ["INFO: Packet #{target_name} #{packet_name} is STALE\n", :BLACK]
|
|
330
|
+
end
|
|
166
331
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
332
|
+
# Record an out of limits item and call the new item callback.
|
|
333
|
+
# Existing out of limits and ignored items are not recorded.
|
|
334
|
+
def out_of_limit(item)
|
|
335
|
+
unless (@out_of_limits.includes_item?(item) || @ignored.includes_item?(item) || UNKNOWN_ARRAY.includes_item?(item))
|
|
336
|
+
@out_of_limits << item
|
|
337
|
+
@items["#{item[0]} #{item[1]} #{item[2]}"] = @new_item_callback.call(*item)
|
|
171
338
|
end
|
|
172
339
|
end
|
|
340
|
+
end
|
|
173
341
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
342
|
+
# The LimitsMonitor application displays all the out of limits items
|
|
343
|
+
# encountered by the COSMOS server. It provides the ability to ignore and
|
|
344
|
+
# restore limits as well as logs all limits events.
|
|
345
|
+
class LimitsMonitor < QtTool
|
|
346
|
+
# LimitsWidget displays either a stale packet using the Label widget
|
|
347
|
+
# or more commonly an out of limits item using the Labelvaluelimitsbar
|
|
348
|
+
# Widget.
|
|
349
|
+
class LimitsWidget < Qt::Widget
|
|
350
|
+
# @return [Widget] The widget which displays the value
|
|
351
|
+
attr_accessor :value
|
|
352
|
+
|
|
353
|
+
# @parent [Qt::Widget] Parent widget (the LimitsMonitor tool)
|
|
354
|
+
# @target_name [String] Target name
|
|
355
|
+
# @packet_name [String] Packet name
|
|
356
|
+
# @item_name [String] Telemetry item name (nil for stale packets)
|
|
357
|
+
def initialize(parent, target_name, packet_name, item_name)
|
|
358
|
+
super(parent)
|
|
359
|
+
@layout = Qt::HBoxLayout.new
|
|
360
|
+
@layout.setSpacing(0)
|
|
361
|
+
@layout.setContentsMargins(0,0,0,0)
|
|
362
|
+
setLayout(@layout)
|
|
363
|
+
|
|
364
|
+
item = [target_name, packet_name, item_name]
|
|
365
|
+
if item_name
|
|
366
|
+
@value = LabelvaluelimitsbarWidget.new(@layout, target_name, packet_name, item_name)
|
|
367
|
+
@value.set_setting('COLORBLIND', [@colorblind])
|
|
368
|
+
@value.process_settings
|
|
192
369
|
else
|
|
193
|
-
|
|
370
|
+
@value = LabelWidget.new(layout, "#{target_name} #{packet_name} is STALE")
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
@ignore_button = Qt::PushButton.new('Ignore')
|
|
374
|
+
@ignore_button.connect(SIGNAL('clicked()')) { parent.ignore(self, item) }
|
|
375
|
+
@layout.addWidget(@ignore_button)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Update the widget's value, limits_state, and limits_set
|
|
379
|
+
def set_values(value, limits_state, limits_set)
|
|
380
|
+
if LabelvaluelimitsbarWidget === @value
|
|
381
|
+
@value.value = value
|
|
382
|
+
@value.limits_state = limits_state
|
|
383
|
+
@value.limits_set = limits_set
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Enable or disable Colorblind mode
|
|
388
|
+
def set_colorblind(enabled)
|
|
389
|
+
if LabelvaluelimitsbarWidget === @value
|
|
390
|
+
@value.set_setting('COLORBLIND', [enabled])
|
|
391
|
+
@value.process_settings
|
|
194
392
|
end
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# Dispose of the widget
|
|
396
|
+
def dispose
|
|
397
|
+
@ignore_button.dispose
|
|
398
|
+
@value.dispose
|
|
399
|
+
@layout.dispose
|
|
400
|
+
super()
|
|
199
401
|
end
|
|
200
402
|
end
|
|
201
403
|
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
404
|
+
# Create the main application GUI. Start the limits thread which responds to
|
|
405
|
+
# asynchronous limits events from the server and the value thread which
|
|
406
|
+
# polls the server at 1Hz for the out of limits items values.
|
|
407
|
+
#
|
|
408
|
+
# @param options [Options] Contains the options for the window.
|
|
409
|
+
def initialize(options)
|
|
410
|
+
super(options)
|
|
411
|
+
Cosmos.load_cosmos_icon("limits_monitor.png")
|
|
412
|
+
|
|
413
|
+
@cancel_thread = false
|
|
414
|
+
@limits_sleeper = Sleeper.new
|
|
415
|
+
@value_sleeper = Sleeper.new
|
|
416
|
+
|
|
417
|
+
initialize_actions()
|
|
418
|
+
initialize_menus()
|
|
419
|
+
initialize_central_widget()
|
|
420
|
+
complete_initialize()
|
|
421
|
+
|
|
422
|
+
@limits_items = LimitsItems.new(
|
|
423
|
+
method(:new_gui_item), method(:update_gui_item), method(:clear_gui_items))
|
|
424
|
+
result = @limits_items.open_config(options.config_file)
|
|
425
|
+
statusBar.showMessage(tr(result))
|
|
426
|
+
|
|
427
|
+
limits_thread()
|
|
428
|
+
value_thread()
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
# Initialize all the actions in the application Menu
|
|
432
|
+
def initialize_actions
|
|
433
|
+
super
|
|
207
434
|
|
|
208
435
|
@options_action = Qt::Action.new(tr('O&ptions'), self)
|
|
209
436
|
@options_action.statusTip = tr('Open the options dialog')
|
|
210
|
-
connect(
|
|
437
|
+
@options_action.connect(SIGNAL('triggered()')) { show_options_dialog() }
|
|
211
438
|
|
|
212
439
|
@reset_action = Qt::Action.new(tr('&Reset'), self)
|
|
213
440
|
@reset_action_keyseq = Qt::KeySequence.new(tr('Ctrl+R'))
|
|
214
441
|
@reset_action.shortcut = @reset_action_keyseq
|
|
215
442
|
@reset_action.statusTip = tr('Reset connection and clear all items. This does not modify the ignored items.')
|
|
216
|
-
connect(
|
|
443
|
+
@reset_action.connect(SIGNAL('triggered()')) { @limits_items.request_reset() }
|
|
217
444
|
|
|
218
445
|
@open_ignored_action = Qt::Action.new(Cosmos.get_icon('open.png'),
|
|
219
446
|
tr('&Open Config'), self)
|
|
220
447
|
@open_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+O'))
|
|
221
448
|
@open_ignored_action.shortcut = @open_ignored_action_keyseq
|
|
222
449
|
@open_ignored_action.statusTip = tr('Open ignored telemetry items configuration file')
|
|
223
|
-
connect(
|
|
450
|
+
@open_ignored_action.connect(SIGNAL('triggered()')) { open_config_file() }
|
|
224
451
|
|
|
225
452
|
@save_ignored_action = Qt::Action.new(Cosmos.get_icon('save.png'),
|
|
226
453
|
tr('&Save Config'), self)
|
|
227
454
|
@save_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+S'))
|
|
228
455
|
@save_ignored_action.shortcut = @save_ignored_action_keyseq
|
|
229
456
|
@save_ignored_action.statusTip = tr('Save all ignored telemetry items in a configuration file')
|
|
230
|
-
connect(
|
|
457
|
+
@save_ignored_action.connect(SIGNAL('triggered()')) { save_config_file() }
|
|
231
458
|
|
|
232
|
-
@
|
|
233
|
-
@
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
@
|
|
237
|
-
|
|
238
|
-
connect(@view_ignored_action, SIGNAL('triggered()'), self, SLOT('handle_view_ignored_items()'))
|
|
459
|
+
@edit_ignored_action = Qt::Action.new(tr('&Edit Ignored'), self)
|
|
460
|
+
@edit_ignored_action_keyseq = Qt::KeySequence.new(tr('Ctrl+E'))
|
|
461
|
+
@edit_ignored_action.shortcut = @edit_ignored_action_keyseq
|
|
462
|
+
@edit_ignored_action.statusTip = tr('Edit the ignored telemetry items list')
|
|
463
|
+
@edit_ignored_action.connect(SIGNAL('triggered()')) { edit_ignored_items() }
|
|
464
|
+
end
|
|
239
465
|
|
|
466
|
+
# Initialize the application menu bar options
|
|
467
|
+
def initialize_menus
|
|
468
|
+
@file_menu = menuBar.addMenu(tr('&File'))
|
|
240
469
|
@file_menu.addAction(@open_ignored_action)
|
|
241
470
|
@file_menu.addAction(@save_ignored_action)
|
|
242
|
-
@file_menu.addAction(@
|
|
243
|
-
@file_menu.addAction(@view_ignored_action)
|
|
471
|
+
@file_menu.addAction(@edit_ignored_action)
|
|
244
472
|
@file_menu.addSeparator()
|
|
245
473
|
@file_menu.addAction(@reset_action)
|
|
246
474
|
@file_menu.addAction(@options_action)
|
|
@@ -253,29 +481,67 @@ module Cosmos
|
|
|
253
481
|
initialize_help_menu()
|
|
254
482
|
end
|
|
255
483
|
|
|
256
|
-
#
|
|
257
|
-
|
|
484
|
+
# Layout the main GUI tab widget with a view of all the out of limits items
|
|
485
|
+
# in one tab and a log tab showing all limits events.
|
|
486
|
+
def initialize_central_widget
|
|
487
|
+
@tabbook = Qt::TabWidget.new(self)
|
|
488
|
+
setCentralWidget(@tabbook)
|
|
489
|
+
@widget = Qt::Widget.new
|
|
490
|
+
@layout = Qt::VBoxLayout.new(@widget)
|
|
491
|
+
|
|
492
|
+
@monitored_state_text_field = Qt::LineEdit.new(self)
|
|
493
|
+
@monitored_state_text_field.setText('Stale')
|
|
494
|
+
@monitored_state_text_field.setAlignment(Qt::AlignCenter)
|
|
495
|
+
@monitored_state_text_field.setReadOnly(true)
|
|
496
|
+
@palette = Qt::Palette.new()
|
|
497
|
+
@palette.setColor(Qt::Palette::Base, Qt::Color.new(255,0,255))
|
|
498
|
+
@monitored_state_text_field.setPalette(@palette)
|
|
499
|
+
@state_label = Qt::Label.new('Monitored Limits State: ')
|
|
500
|
+
|
|
501
|
+
@monitored_state_frame = Qt::HBoxLayout.new
|
|
502
|
+
@monitored_state_frame.addWidget(@state_label)
|
|
503
|
+
@monitored_state_frame.addWidget(@monitored_state_text_field)
|
|
504
|
+
label = Qt::Label.new
|
|
505
|
+
filename = File.join(::Cosmos::PATH, 'data', 'spinner.gif')
|
|
506
|
+
movie = Qt::Movie.new(filename)
|
|
507
|
+
label.setMovie(movie)
|
|
508
|
+
movie.start
|
|
509
|
+
@monitored_state_frame.addWidget(label)
|
|
510
|
+
@monitored_state_frame.setAlignment(Qt::AlignTop)
|
|
511
|
+
@layout.addLayout(@monitored_state_frame)
|
|
512
|
+
|
|
513
|
+
@scroll = Qt::ScrollArea.new
|
|
514
|
+
@scroll_widget = Qt::Widget.new
|
|
515
|
+
@scroll.setWidget(@scroll_widget)
|
|
516
|
+
@scroll_layout = Qt::VBoxLayout.new(@scroll_widget)
|
|
517
|
+
@scroll_layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
|
|
518
|
+
@layout.addWidget(@scroll)
|
|
519
|
+
|
|
520
|
+
@log_output = Qt::PlainTextEdit.new
|
|
521
|
+
@log_output.setReadOnly(true)
|
|
522
|
+
@log_output.setMaximumBlockCount(100)
|
|
523
|
+
|
|
524
|
+
@tabbook.addTab(@widget, "Limits")
|
|
525
|
+
@tabbook.addTab(@log_output, "Log")
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def show_options_dialog
|
|
258
529
|
Qt::Dialog.new(self) do |dialog|
|
|
259
530
|
dialog.setWindowTitle('Options')
|
|
260
531
|
|
|
261
532
|
colorblind_box = Qt::CheckBox.new('Colorblind Mode Enabled', self)
|
|
262
|
-
if
|
|
263
|
-
colorblind_box.setCheckState(Qt::Checked)
|
|
264
|
-
end
|
|
533
|
+
colorblind_box.setCheckState(Qt::Checked) if @colorblind
|
|
265
534
|
|
|
266
535
|
ok = Qt::PushButton.new('Ok') do
|
|
267
536
|
connect(SIGNAL('clicked()')) { dialog.accept }
|
|
268
537
|
end
|
|
269
|
-
|
|
270
538
|
cancel = Qt::PushButton.new('Cancel') do
|
|
271
539
|
connect(SIGNAL('clicked()')) { dialog.reject }
|
|
272
540
|
end
|
|
273
|
-
|
|
274
541
|
buttons = Qt::HBoxLayout.new do
|
|
275
542
|
addWidget(ok)
|
|
276
543
|
addWidget(cancel)
|
|
277
544
|
end
|
|
278
|
-
|
|
279
545
|
dialog.layout = Qt::VBoxLayout.new do
|
|
280
546
|
addWidget(colorblind_box)
|
|
281
547
|
addLayout(buttons)
|
|
@@ -288,471 +554,247 @@ module Cosmos
|
|
|
288
554
|
else
|
|
289
555
|
@colorblind = false
|
|
290
556
|
end
|
|
291
|
-
|
|
292
|
-
widget.
|
|
293
|
-
widget.process_settings
|
|
557
|
+
(0...@scroll_layout.count).each do |index|
|
|
558
|
+
@scroll_layout.itemAt(index).widget.set_colorblind(@colorblind)
|
|
294
559
|
end
|
|
295
560
|
end
|
|
296
561
|
dialog.dispose
|
|
297
562
|
end
|
|
298
563
|
end
|
|
299
564
|
|
|
300
|
-
#
|
|
301
|
-
def
|
|
302
|
-
|
|
565
|
+
# @return [String] Fully qualified path to the configuration file
|
|
566
|
+
def config_path
|
|
567
|
+
# If the config file has been set then just return it
|
|
568
|
+
return @filename if @filename
|
|
569
|
+
# This is the default path to the configuration files
|
|
570
|
+
File.join(::Cosmos::USERPATH, 'config', 'tools', 'limits_monitor', 'limits_monitor.txt')
|
|
303
571
|
end
|
|
304
572
|
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
begin
|
|
313
|
-
initialized = nil
|
|
314
|
-
break if @cancel_thread
|
|
315
|
-
Qt.execute_in_main_thread(true) do
|
|
316
|
-
initialized = @initialized
|
|
317
|
-
end
|
|
318
|
-
unless initialized
|
|
319
|
-
@limits_set = nil
|
|
320
|
-
break if @cancel_thread
|
|
321
|
-
Qt.execute_in_main_thread(true) do
|
|
322
|
-
@out_of_limits_items = []
|
|
323
|
-
end
|
|
324
|
-
unsubscribe_limits_events(@queue_id) if @queue_id
|
|
325
|
-
@queue_id = nil
|
|
326
|
-
|
|
327
|
-
handle_reset()
|
|
328
|
-
|
|
329
|
-
# Get the current limits set
|
|
330
|
-
@limits_set = get_limits_set()
|
|
331
|
-
|
|
332
|
-
# Subscribe to limits notifications
|
|
333
|
-
@queue_id = subscribe_limits_events(100000)
|
|
334
|
-
|
|
335
|
-
# Get initial list of out of limits items
|
|
336
|
-
items = get_out_of_limits()
|
|
337
|
-
unless items.empty?
|
|
338
|
-
break if @cancel_thread
|
|
339
|
-
Qt.execute_in_main_thread(true) do
|
|
340
|
-
items.each do |item|
|
|
341
|
-
unless @ignored_items.includes_item?(item) and !@items.includes_item?(item)
|
|
342
|
-
@new_items << [item[0], item[1], item[2]]
|
|
343
|
-
@out_of_limits_items << [item[0], item[1], item[2]]
|
|
344
|
-
end
|
|
345
|
-
end
|
|
346
|
-
handle_new_items()
|
|
347
|
-
end
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
break if @cancel_thread
|
|
351
|
-
Qt.execute_in_main_thread(true) do
|
|
352
|
-
@initialized = true
|
|
353
|
-
if @ignored_items.empty?
|
|
354
|
-
statusBar.showMessage(tr(""))
|
|
355
|
-
else
|
|
356
|
-
statusBar.showMessage('Warning: Some Telemetry Items are Ignored')
|
|
357
|
-
end
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
begin
|
|
363
|
-
break if @cancel_thread
|
|
364
|
-
type, data = get_limits_event(@queue_id, true)
|
|
365
|
-
break if @cancel_thread
|
|
366
|
-
rescue ThreadError
|
|
367
|
-
break if @cancel_thread
|
|
368
|
-
break if @limits_sleeper.sleep(1)
|
|
369
|
-
next
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
break if @cancel_thread
|
|
373
|
-
|
|
374
|
-
case type
|
|
375
|
-
when :LIMITS_CHANGE
|
|
376
|
-
item = [data[0], data[1], data[2]]
|
|
377
|
-
if data[4] != :GREEN and data[4] != :GREEN_HIGH and data[4] != :GREEN_LOW and data[4] != :BLUE and data[4] != nil
|
|
378
|
-
case data[4]
|
|
379
|
-
when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
|
|
380
|
-
to_print = Time.now.formatted << ' ' << "WARN: #{data[0]} #{data[1]} #{data[2]} = #{tlm(data[0], data[1], data[2])} is #{data[4]}\n"
|
|
381
|
-
update_log(to_print, 1)
|
|
382
|
-
when :RED, :RED_HIGH, :RED_LOW
|
|
383
|
-
to_print = Time.now.formatted << ' ' << "ERROR: #{data[0]} #{data[1]} #{data[2]} = #{tlm(data[0], data[1], data[2])} is #{data[4]}\n"
|
|
384
|
-
update_log(to_print, 2)
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
# Limits changed to non-green
|
|
388
|
-
unless @out_of_limits_items.includes_item?(item) or @ignored_items.includes_item?(item)
|
|
389
|
-
@out_of_limits_items << item
|
|
390
|
-
@new_items << item
|
|
391
|
-
handle_new_items()
|
|
392
|
-
end
|
|
393
|
-
elsif data[4] == :GREEN or data[4] == :GREEN_HIGH or data[4] == :GREEN_LOW or data[4] == :BLUE
|
|
394
|
-
to_print = Time.now.formatted << ' ' << "INFO: #{data[0]} #{data[1]} #{data[2]} = #{tlm(data[0], data[1], data[2])} returned to GREEN\n"
|
|
395
|
-
|
|
396
|
-
if data[4] == :BLUE
|
|
397
|
-
update_log(to_print, 3)
|
|
398
|
-
else
|
|
399
|
-
update_log(to_print, 0)
|
|
400
|
-
end
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
when :LIMITS_SET
|
|
404
|
-
if @limits_set != data
|
|
405
|
-
break if @cancel_thread
|
|
406
|
-
Qt.execute_in_main_thread(true) do
|
|
407
|
-
statusBar.showMessage('Limits Set Changed - Reseting')
|
|
408
|
-
@initialized = false
|
|
409
|
-
to_print = Time.now.formatted << ' ' << "INFO: Limits Set Changed to: #{data}\n"
|
|
410
|
-
update_log(to_print, 4)
|
|
411
|
-
end
|
|
412
|
-
break if @cancel_thread
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
when :LIMITS_SETTINGS
|
|
416
|
-
begin
|
|
417
|
-
System.limits.set(data[0], data[1], data[2], data[6], data[7], data[8], data[9], data[10], data[11], data[3], data[4], data[5])
|
|
418
|
-
break if @cancel_thread
|
|
419
|
-
Qt.execute_in_main_thread(true) do
|
|
420
|
-
statusBar.showMessage('Limits Settings Changed - Reseting')
|
|
421
|
-
@initialized = false
|
|
422
|
-
to_print = Time.now.formatted << ' ' << "INFO: Limits Settings Changed: #{data}\n"
|
|
423
|
-
update_log(to_print, 4)
|
|
424
|
-
end
|
|
425
|
-
break if @cancel_thread
|
|
426
|
-
rescue
|
|
427
|
-
# This can fail if we missed setting the DEFAULT limits set earlier - Oh well
|
|
428
|
-
end
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
rescue DRb::DRbConnError
|
|
432
|
-
break if @cancel_thread
|
|
433
|
-
@queue_id = nil
|
|
434
|
-
break if @cancel_thread
|
|
435
|
-
Qt.execute_in_main_thread(true) do
|
|
436
|
-
statusBar.showMessage('Error Connecting to Command and Telemetry Server - Reseting')
|
|
437
|
-
@initialized = false
|
|
438
|
-
end
|
|
439
|
-
break if @cancel_thread
|
|
440
|
-
break if @limits_sleeper.sleep(1)
|
|
441
|
-
end
|
|
442
|
-
end # loop
|
|
443
|
-
rescue Exception => error
|
|
444
|
-
Cosmos.handle_fatal_exception(error)
|
|
445
|
-
end
|
|
573
|
+
# Opens the configuration file and loads the ignored items
|
|
574
|
+
def open_config_file
|
|
575
|
+
filename = Qt::FileDialog::getOpenFileName(self,
|
|
576
|
+
"Open Configuration File", config_path())
|
|
577
|
+
unless filename.nil? || filename.empty?
|
|
578
|
+
result = @limits_items.open_config(filename)
|
|
579
|
+
statusBar.showMessage(tr(result))
|
|
446
580
|
end
|
|
447
581
|
end
|
|
448
582
|
|
|
449
|
-
#
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
Qt.execute_in_main_thread(true) do
|
|
458
|
-
begin
|
|
459
|
-
# Gather items for widgets
|
|
460
|
-
values, limits_states, limits_settings, limits_set = get_tlm_values(@items, :WITH_UNITS)
|
|
461
|
-
index = 0
|
|
462
|
-
@items.each do |target_name, packet_name, item_name|
|
|
463
|
-
begin
|
|
464
|
-
System.limits.set(target_name, packet_name, item_name, limits_settings[index][0], limits_settings[index][1], limits_settings[index][2], limits_settings[index][3], limits_settings[index][4], limits_settings[index][5], limits_set) if limits_settings[index]
|
|
465
|
-
rescue
|
|
466
|
-
# This can fail if we missed setting the DEFAULT limits set earlier - Oh well
|
|
467
|
-
end
|
|
468
|
-
index += 1
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
# Handle change in limits set
|
|
472
|
-
if limits_set != @value_limits_set
|
|
473
|
-
@value_limits_set = limits_set
|
|
474
|
-
@widgets.each do |widget|
|
|
475
|
-
widget.limits_set = @value_limits_set
|
|
476
|
-
end
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
# Update widgets with values and limits_states
|
|
480
|
-
@overall_limits_state = :STALE
|
|
481
|
-
(0..(values.length - 1)).each do |widget_index|
|
|
482
|
-
limits_state = limits_states[widget_index]
|
|
483
|
-
@widgets[widget_index].limits_state = limits_state
|
|
484
|
-
@widgets[widget_index].value = values[widget_index]
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
# Update overall limits state
|
|
488
|
-
modify_overall_limits_state(get_overall_limits_state(@ignored_items))
|
|
489
|
-
update_overall_limits_state()
|
|
490
|
-
rescue DRb::DRbConnError
|
|
491
|
-
# Do nothing
|
|
492
|
-
end
|
|
493
|
-
end
|
|
494
|
-
else
|
|
495
|
-
@overall_limits_state = :STALE
|
|
496
|
-
break if @cancel_thread
|
|
497
|
-
Qt.execute_in_main_thread(true) do
|
|
498
|
-
begin
|
|
499
|
-
modify_overall_limits_state(get_overall_limits_state(@ignored_items))
|
|
500
|
-
rescue DRb::DRbConnError
|
|
501
|
-
# Do nothing
|
|
502
|
-
end
|
|
503
|
-
update_overall_limits_state()
|
|
504
|
-
end
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
# Sleep until next polling period
|
|
508
|
-
break if @value_sleeper.sleep(1)
|
|
509
|
-
end
|
|
510
|
-
rescue Exception => error
|
|
511
|
-
Cosmos.handle_fatal_exception(error)
|
|
512
|
-
end
|
|
583
|
+
# Saves the ignored items to the configuration file
|
|
584
|
+
def save_config_file
|
|
585
|
+
filename = Qt::FileDialog.getSaveFileName(self,
|
|
586
|
+
'Save As...', config_path(), 'Configuration Files (*.txt)')
|
|
587
|
+
unless filename.nil? || filename.empty?
|
|
588
|
+
result = @limits_items.save_config(filename)
|
|
589
|
+
statusBar.showMessage(tr(result))
|
|
590
|
+
@filename = filename
|
|
513
591
|
end
|
|
514
592
|
end
|
|
515
593
|
|
|
516
|
-
#
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
@
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
@overall_limits_state = limits_state
|
|
526
|
-
end
|
|
527
|
-
when :GREEN, :GREEN_HIGH, :GREEN_LOW
|
|
528
|
-
if limits_state != nil and limits_state != :STALE and limits_state != :BLUE
|
|
529
|
-
@overall_limits_state = limits_state
|
|
530
|
-
end
|
|
531
|
-
when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
|
|
532
|
-
if limits_state == :RED or limits_state == :RED_HIGH or limits_state == :RED_LOW
|
|
533
|
-
@overall_limits_state = limits_state
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
# Changes the limits state on the status bar at the top of the screen.
|
|
539
|
-
def update_overall_limits_state
|
|
540
|
-
text = ''
|
|
541
|
-
case @overall_limits_state
|
|
542
|
-
when :STALE
|
|
543
|
-
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,255))
|
|
544
|
-
@monitored_state_text_field.setPalette(palette)
|
|
545
|
-
text = 'Stale'
|
|
546
|
-
when :GREEN, :GREEN_HIGH, :GREEN_LOW
|
|
547
|
-
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,255,0))
|
|
548
|
-
@monitored_state_text_field.setPalette(palette)
|
|
549
|
-
text = 'Green'
|
|
550
|
-
when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
|
|
551
|
-
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,255,0))
|
|
552
|
-
@monitored_state_text_field.setPalette(palette)
|
|
553
|
-
text = 'Yellow'
|
|
554
|
-
when :RED, :RED_HIGH, :RED_LOW
|
|
555
|
-
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,0))
|
|
556
|
-
@monitored_state_text_field.setPalette(palette)
|
|
557
|
-
text = 'Red'
|
|
558
|
-
when :BLUE
|
|
559
|
-
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,0,255))
|
|
560
|
-
@monitored_state_text_field.setPalette(palette)
|
|
561
|
-
text = 'Blue'
|
|
562
|
-
end
|
|
563
|
-
text << ' - Some Items Ignored' unless @ignored_items.empty?
|
|
564
|
-
@monitored_state_text_field.text = text
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
# Slot to handle when the clear ignored items menu option is selected.
|
|
568
|
-
def handle_clear_ignored_items
|
|
569
|
-
@ignored_items.clear
|
|
570
|
-
@initialized = false
|
|
571
|
-
statusBar.showMessage('')
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
# Slot to handle when the view ignored items menu option is selected.
|
|
575
|
-
def handle_view_ignored_items
|
|
576
|
-
# Turn Command into scripting text string
|
|
577
|
-
string = ''
|
|
578
|
-
@ignored_items.each do |item|
|
|
579
|
-
string << "#{item[0]} #{item[1]} #{item[2]}\n"
|
|
594
|
+
# Opens a dialog to allow the user to remove ignored items
|
|
595
|
+
def edit_ignored_items
|
|
596
|
+
items = []
|
|
597
|
+
index = 0
|
|
598
|
+
@limits_items.ignored.each do |target_name, packet_name, item_name|
|
|
599
|
+
item = Qt::ListWidgetItem.new("#{target_name} #{packet_name} #{item_name}")
|
|
600
|
+
item.setData(Qt::UserRole, Qt::Variant.new(@limits_items.ignored[index]))
|
|
601
|
+
items << item
|
|
602
|
+
index += 1
|
|
580
603
|
end
|
|
581
604
|
|
|
582
|
-
# Show Dialog box with text displaying ignored items
|
|
583
605
|
Qt::Dialog.new(self) do |dialog|
|
|
584
606
|
dialog.setWindowTitle('Ignored Telemetry Items')
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
607
|
+
list = Qt::ListWidget.new
|
|
608
|
+
list.setFocus()
|
|
609
|
+
# Allow multiple sections
|
|
610
|
+
list.setSelectionMode(Qt::AbstractItemView::ExtendedSelection)
|
|
611
|
+
items.each {|item| list.addItem(item) }
|
|
612
|
+
|
|
613
|
+
shortcut = Qt::Shortcut.new(Qt::KeySequence.new(Qt::KeySequence::Delete), list)
|
|
614
|
+
list.connect(shortcut, SIGNAL('activated()')) do
|
|
615
|
+
items = list.selectedItems()
|
|
616
|
+
(0...items.length).each do |index|
|
|
617
|
+
@limits_items.remove_ignored(items[index].data(Qt::UserRole).value)
|
|
618
|
+
end
|
|
619
|
+
list.remove_selected_items
|
|
620
|
+
list.setCurrentRow(0)
|
|
621
|
+
end
|
|
622
|
+
# Preselect the first row (works if list is empty) so the keyboard
|
|
623
|
+
# works instantly without having to click the list
|
|
624
|
+
list.setCurrentRow(0)
|
|
588
625
|
|
|
589
626
|
ok = Qt::PushButton.new('Ok') do
|
|
590
627
|
connect(SIGNAL('clicked()')) { dialog.done(0) }
|
|
591
628
|
end
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
629
|
+
remove = Qt::PushButton.new('Remove Selected') do
|
|
630
|
+
connect(SIGNAL('clicked()')) { shortcut.activated() }
|
|
631
|
+
end
|
|
632
|
+
button_layout = Qt::HBoxLayout.new do
|
|
595
633
|
addWidget(ok)
|
|
634
|
+
addStretch(1)
|
|
635
|
+
addWidget(remove)
|
|
636
|
+
end
|
|
637
|
+
dialog.layout = Qt::VBoxLayout.new do
|
|
638
|
+
addWidget(list)
|
|
639
|
+
addLayout(button_layout)
|
|
596
640
|
end
|
|
597
|
-
|
|
598
641
|
dialog.resize(500, 200)
|
|
599
642
|
dialog.exec
|
|
600
643
|
dialog.dispose
|
|
601
644
|
end
|
|
602
645
|
end
|
|
603
646
|
|
|
604
|
-
#
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
647
|
+
# Thread to monitor for broken limits and add them to the log and
|
|
648
|
+
# front panel when found.
|
|
649
|
+
def limits_thread
|
|
650
|
+
result = nil
|
|
651
|
+
color = nil
|
|
652
|
+
@limits_thread = Thread.new do
|
|
653
|
+
while true
|
|
654
|
+
break if @cancel_thread
|
|
655
|
+
Qt.execute_in_main_thread(true) do
|
|
656
|
+
result, color = @limits_items.process_events()
|
|
657
|
+
end
|
|
658
|
+
if result
|
|
659
|
+
update_log(result, color)
|
|
660
|
+
else
|
|
661
|
+
break if @limits_sleeper.sleep(1)
|
|
617
662
|
end
|
|
618
|
-
statusBar.showMessage("#{filename} saved")
|
|
619
|
-
rescue => e
|
|
620
|
-
statusBar.showMessage("Error Saving Configuration : #{e.message}")
|
|
621
663
|
end
|
|
622
664
|
end
|
|
665
|
+
rescue Exception => error
|
|
666
|
+
Cosmos.handle_fatal_exception(error)
|
|
623
667
|
end
|
|
624
668
|
|
|
625
|
-
#
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
669
|
+
# Add new out of limit item or stale packet
|
|
670
|
+
#
|
|
671
|
+
# @param target_name [String] Target name of out of limits item.
|
|
672
|
+
# @param packet_name [String] Packet name of out of limits item.
|
|
673
|
+
# @param item_name [String] Item name of out of limits item or nil
|
|
674
|
+
# if its a stale packet
|
|
675
|
+
# @return [Qt::Widget] The new widget that was created
|
|
676
|
+
def new_gui_item(target_name, packet_name, item_name)
|
|
677
|
+
widget = nil
|
|
678
|
+
Qt.execute_in_main_thread(true) do
|
|
679
|
+
widget = LimitsWidget.new(self, target_name, packet_name, item_name)
|
|
680
|
+
@scroll_layout.addWidget(widget)
|
|
634
681
|
end
|
|
682
|
+
widget
|
|
635
683
|
end
|
|
636
684
|
|
|
637
|
-
#
|
|
685
|
+
# Update out of limit item with a values
|
|
638
686
|
#
|
|
639
|
-
# @param
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
parser.parse_file(filename) do |keyword, params|
|
|
647
|
-
case keyword
|
|
648
|
-
when 'IGNORE'
|
|
649
|
-
ignore_item([params[0], params[1], params[2]])
|
|
650
|
-
end
|
|
651
|
-
end
|
|
652
|
-
statusBar.showMessage("#{filename} loaded")
|
|
653
|
-
rescue => e
|
|
654
|
-
statusBar.showMessage("Error Loading Configuration : #{e.message}")
|
|
687
|
+
# @param target_name [String] Target name of out of limits item.
|
|
688
|
+
# @param packet_name [String] Packet name of out of limits item.
|
|
689
|
+
# @param item_name [String] Item name of out of limits item or nil
|
|
690
|
+
# if its a stale packet
|
|
691
|
+
def update_gui_item(widget, value, limits_state, limits_set)
|
|
692
|
+
Qt.execute_in_main_thread(true) do
|
|
693
|
+
widget.set_values(value, limits_state, limits_set) if widget
|
|
655
694
|
end
|
|
656
695
|
end
|
|
657
696
|
|
|
697
|
+
# Reset the GUI by clearing all items
|
|
698
|
+
def clear_gui_items
|
|
699
|
+
Qt.execute_in_main_thread(true) { @scroll_layout.removeAll }
|
|
700
|
+
end
|
|
701
|
+
|
|
658
702
|
# Update front panel to ignore an item when the corresponding button is pressed.
|
|
659
703
|
#
|
|
660
|
-
# @param item [Array] Array containing the target
|
|
661
|
-
# item to ignore.
|
|
662
|
-
def
|
|
704
|
+
# @param item [Array<String,String,String] Array containing the target name,
|
|
705
|
+
# packet name, and item name of the item to ignore.
|
|
706
|
+
def ignore(widget, item)
|
|
707
|
+
@limits_items.ignore(item)
|
|
663
708
|
Qt.execute_in_main_thread(true) do
|
|
664
|
-
@
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
hframe_to_dispose = @widget_hframes[delete_index]
|
|
668
|
-
widget_to_dispose = @widgets[delete_index]
|
|
669
|
-
button_to_dispose = @buttons[delete_index]
|
|
670
|
-
@widgets.delete_at(delete_index)
|
|
671
|
-
@buttons.delete_at(delete_index)
|
|
672
|
-
@widget_hframes.delete_at(delete_index)
|
|
673
|
-
@scroll_layout.removeItem(hframe_to_dispose)
|
|
674
|
-
widget_to_dispose.dispose
|
|
675
|
-
button_to_dispose.dispose
|
|
676
|
-
hframe_to_dispose.dispose
|
|
677
|
-
@scroll.repaint
|
|
678
|
-
end
|
|
709
|
+
@scroll_layout.removeWidget(widget)
|
|
710
|
+
widget.dispose
|
|
711
|
+
@scroll_widget.adjustSize
|
|
679
712
|
statusBar.showMessage('Warning: Some Telemetry Items are Ignored')
|
|
680
713
|
end
|
|
681
714
|
end
|
|
682
715
|
|
|
683
|
-
#
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
716
|
+
# Update the log panel with limits change information.
|
|
717
|
+
#
|
|
718
|
+
# @param message [String] Text string with information about which item is out of
|
|
719
|
+
# limits, what its value is, and what limit was broken (red_low, yellow_low, etc.)
|
|
720
|
+
# @param color [Symbol] Color of text to add.
|
|
721
|
+
def update_log(message, color)
|
|
722
|
+
return if @cancel_thread
|
|
687
723
|
Qt.execute_in_main_thread(true) do
|
|
688
|
-
@
|
|
689
|
-
|
|
690
|
-
|
|
724
|
+
@tf ||= Qt::TextCharFormat.new
|
|
725
|
+
case color
|
|
726
|
+
when :GREEN
|
|
727
|
+
brush = Cosmos.getBrush(Cosmos::GREEN)
|
|
728
|
+
when :YELLOW
|
|
729
|
+
brush = Cosmos.getBrush(Cosmos::YELLOW)
|
|
730
|
+
when :RED
|
|
731
|
+
brush = Cosmos.getBrush(Cosmos::RED)
|
|
732
|
+
when :BLUE
|
|
733
|
+
brush = Cosmos.getBrush(Cosmos::BLUE)
|
|
734
|
+
else # :BLACK
|
|
735
|
+
brush = Cosmos.getBrush(Cosmos::BLACK)
|
|
691
736
|
end
|
|
737
|
+
@tf.setForeground(brush)
|
|
738
|
+
@log_output.setCurrentCharFormat(@tf)
|
|
739
|
+
@log_output.appendPlainText(message.chomp)
|
|
692
740
|
end
|
|
741
|
+
end
|
|
693
742
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
743
|
+
# Thread to request the out of limits values and update them at 1Hz.
|
|
744
|
+
# Also updates the status bar at the top of the front panel indicating
|
|
745
|
+
# the overall limits value of the system.
|
|
746
|
+
def value_thread
|
|
747
|
+
@value_thread = Thread.new do
|
|
748
|
+
while true
|
|
749
|
+
break if @cancel_thread
|
|
750
|
+
Qt.execute_in_main_thread(true) do
|
|
751
|
+
if @limits_items.initialized
|
|
752
|
+
@limits_items.update_values()
|
|
753
|
+
update_overall_limits_state(@limits_items.overall_state())
|
|
754
|
+
else
|
|
755
|
+
# Set the status bar message to expire in 2s since this runs at 1Hz
|
|
756
|
+
statusBar.showMessage('Error Connecting to Command and Telemetry Server', 2000)
|
|
705
757
|
end
|
|
706
|
-
index += 1
|
|
707
|
-
end
|
|
708
|
-
index = 0
|
|
709
|
-
|
|
710
|
-
@new_widgets.each do |widget|
|
|
711
|
-
limits_state = limits_states[index]
|
|
712
|
-
widget.limits_set = limits_set
|
|
713
|
-
widget.limits_state = limits_state
|
|
714
|
-
widget.value = values[index]
|
|
715
|
-
index += 1
|
|
716
|
-
modify_overall_limits_state(limits_state)
|
|
717
|
-
end
|
|
718
|
-
|
|
719
|
-
update_overall_limits_state()
|
|
720
|
-
|
|
721
|
-
@new_items.each do |item|
|
|
722
|
-
@items << item
|
|
723
758
|
end
|
|
724
|
-
|
|
725
|
-
rescue DRb::DRbConnError
|
|
726
|
-
statusBar.showMessage('Error Connecting to Command and Telemetry Server - Reseting')
|
|
727
|
-
@initialized = false
|
|
759
|
+
break if @value_sleeper.sleep(1)
|
|
728
760
|
end
|
|
729
761
|
end
|
|
762
|
+
rescue Exception => error
|
|
763
|
+
Cosmos.handle_fatal_exception(error)
|
|
730
764
|
end
|
|
731
765
|
|
|
732
|
-
#
|
|
733
|
-
def
|
|
766
|
+
# Changes the limits state on the status bar at the top of the screen.
|
|
767
|
+
def update_overall_limits_state(state)
|
|
734
768
|
Qt.execute_in_main_thread(true) do
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
769
|
+
text = ''
|
|
770
|
+
case state
|
|
771
|
+
when :STALE
|
|
772
|
+
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,255))
|
|
773
|
+
@monitored_state_text_field.setPalette(palette)
|
|
774
|
+
text = 'Stale'
|
|
775
|
+
when :GREEN, :GREEN_HIGH, :GREEN_LOW
|
|
776
|
+
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,255,0))
|
|
777
|
+
@monitored_state_text_field.setPalette(palette)
|
|
778
|
+
text = 'Green'
|
|
779
|
+
when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
|
|
780
|
+
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,255,0))
|
|
781
|
+
@monitored_state_text_field.setPalette(palette)
|
|
782
|
+
text = 'Yellow'
|
|
783
|
+
when :RED, :RED_HIGH, :RED_LOW
|
|
784
|
+
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,0))
|
|
785
|
+
@monitored_state_text_field.setPalette(palette)
|
|
786
|
+
text = 'Red'
|
|
787
|
+
when :BLUE
|
|
788
|
+
palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,0,255))
|
|
789
|
+
@monitored_state_text_field.setPalette(palette)
|
|
790
|
+
text = 'Blue'
|
|
740
791
|
end
|
|
741
|
-
@
|
|
742
|
-
|
|
743
|
-
@widgets = []
|
|
744
|
-
@new_widgets = []
|
|
745
|
-
@buttons = []
|
|
746
|
-
@widget_hframes = []
|
|
747
|
-
@items = []
|
|
748
|
-
@value_limits_set = :DEFAULT
|
|
749
|
-
|
|
750
|
-
@overall_limits_state = :STALE
|
|
751
|
-
update_overall_limits_state()
|
|
792
|
+
text << ' - Some Items Ignored' if @limits_items.ignored_items?
|
|
793
|
+
@monitored_state_text_field.text = text
|
|
752
794
|
end
|
|
753
795
|
end
|
|
754
796
|
|
|
755
|
-
# Handle the window closing
|
|
797
|
+
# Handle the window closing
|
|
756
798
|
def closeEvent(event)
|
|
757
799
|
@cancel_thread = true
|
|
758
800
|
@value_sleeper.cancel
|
|
@@ -792,5 +834,4 @@ module Cosmos
|
|
|
792
834
|
end
|
|
793
835
|
|
|
794
836
|
end # class LimitsMonitor
|
|
795
|
-
|
|
796
837
|
end # module Cosmos
|