cosmos 3.1.1 → 3.1.2
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 +6 -0
- data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +1 -1
- data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +2 -2
- data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +4 -4
- data/autohotkey/tools/autohotkey.rb +1 -1
- data/autohotkey/tools/cmd_tlm_server.ahk +1 -0
- data/autohotkey/tools/packet_viewer.ahk +45 -2
- data/data/crc.txt +20 -15
- data/demo/Rakefile +16 -0
- data/demo/config/data/crc.txt +3 -3
- data/demo/config/tools/handbook_creator/templates/footer.html.erb +2 -2
- data/demo/config/tools/handbook_creator/templates/header.html.erb +4 -4
- data/demo/procedures/example_test.rb +1 -1
- data/install/Rakefile +16 -0
- data/install/config/data/crc.txt +2 -2
- data/install/config/tools/handbook_creator/templates/footer.html.erb +2 -2
- data/install/config/tools/handbook_creator/templates/header.html.erb +4 -4
- data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +64 -57
- data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +0 -9
- data/lib/cosmos/gui/qt.rb +22 -18
- data/lib/cosmos/packet_logs/packet_log_writer.rb +6 -2
- data/lib/cosmos/script/script.rb +1 -1
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +0 -1
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +99 -784
- data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +189 -0
- data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +176 -0
- data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +144 -0
- data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +240 -0
- data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +90 -0
- data/lib/cosmos/tools/launcher/launcher_config.rb +142 -110
- data/lib/cosmos/tools/test_runner/results_writer.rb +1 -1
- data/lib/cosmos/tools/test_runner/test_runner.rb +3 -2
- data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +18 -2
- data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +4 -9
- data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +5 -5
- data/lib/cosmos/top_level.rb +1 -1
- data/lib/cosmos/version.rb +4 -4
- data/run_gui_tests.bat +33 -31
- data/spec/core_ext/time_spec.rb +51 -0
- data/spec/script/script_spec.rb +96 -0
- data/spec/tools/cmd_tlm_server/commanding_spec.rb +28 -0
- data/spec/tools/cmd_tlm_server/connections_spec.rb +88 -0
- data/spec/tools/cmd_tlm_server/router_thread_spec.rb +78 -25
- data/spec/tools/launcher/launcher_config_spec.rb +460 -0
- data/spec/top_level/top_level_spec.rb +1 -1
- metadata +8 -2
@@ -0,0 +1,189 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2014 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
|
11
|
+
require 'cosmos'
|
12
|
+
require 'cosmos/gui/qt'
|
13
|
+
|
14
|
+
module Cosmos
|
15
|
+
|
16
|
+
# Implements the interfaces and routers tabs in the Command and Telemetry Server GUI
|
17
|
+
class InterfacesTab
|
18
|
+
INTERFACES = 'Interfaces'
|
19
|
+
ROUTERS = 'Routers'
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@interfaces_table = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create the interfaces tab and add it to the tab_widget
|
26
|
+
#
|
27
|
+
# @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
|
28
|
+
def populate_interfaces(tab_widget)
|
29
|
+
populate(INTERFACES, CmdTlmServer.interfaces, tab_widget)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create the routers tab and add it to the tab_widget
|
33
|
+
#
|
34
|
+
# @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
|
35
|
+
def populate_routers(tab_widget)
|
36
|
+
populate(ROUTERS, CmdTlmServer.routers, tab_widget)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Update the interfaces or routers tab
|
40
|
+
#
|
41
|
+
# @param name [String] Must be Interfaces or Routers
|
42
|
+
def update(name)
|
43
|
+
if name == ROUTERS
|
44
|
+
interfaces = CmdTlmServer.routers
|
45
|
+
else
|
46
|
+
interfaces = CmdTlmServer.interfaces
|
47
|
+
end
|
48
|
+
row = 0
|
49
|
+
interfaces.all.each do |interface_name, interface|
|
50
|
+
button = @interfaces_table[name].cellWidget(row,1)
|
51
|
+
state = @interfaces_table[name].item(row,2)
|
52
|
+
if interface.connected?
|
53
|
+
button.setText('Disconnect')
|
54
|
+
button.setDisabled(true) if interface.disable_disconnect
|
55
|
+
state.setText('true')
|
56
|
+
state.textColor = Cosmos::GREEN
|
57
|
+
elsif interface.thread
|
58
|
+
button.text = 'Cancel Connect'
|
59
|
+
button.setDisabled(false)
|
60
|
+
state.text = 'attempting'
|
61
|
+
state.textColor = Cosmos::RED
|
62
|
+
else
|
63
|
+
button.setText('Connect')
|
64
|
+
button.setDisabled(false)
|
65
|
+
state.setText('false')
|
66
|
+
state.textColor = Cosmos::BLACK
|
67
|
+
end
|
68
|
+
@interfaces_table[name].item(row,3).setText(interface.num_clients.to_s)
|
69
|
+
@interfaces_table[name].item(row,4).setText(interface.write_queue_size.to_s)
|
70
|
+
@interfaces_table[name].item(row,5).setText(interface.read_queue_size.to_s)
|
71
|
+
@interfaces_table[name].item(row,6).setText(interface.bytes_written.to_s)
|
72
|
+
@interfaces_table[name].item(row,7).setText(interface.bytes_read.to_s)
|
73
|
+
if name == ROUTERS
|
74
|
+
@interfaces_table[name].item(row,8).setText(interface.read_count.to_s)
|
75
|
+
@interfaces_table[name].item(row,9).setText(interface.write_count.to_s)
|
76
|
+
else
|
77
|
+
@interfaces_table[name].item(row,8).setText(interface.write_count.to_s)
|
78
|
+
@interfaces_table[name].item(row,9).setText(interface.read_count.to_s)
|
79
|
+
end
|
80
|
+
row += 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def populate(name, interfaces, tab_widget)
|
87
|
+
return if interfaces.all.empty?
|
88
|
+
|
89
|
+
scroll = Qt::ScrollArea.new
|
90
|
+
scroll.setMinimumSize(800, 150)
|
91
|
+
widget = Qt::Widget.new
|
92
|
+
layout = Qt::VBoxLayout.new(widget)
|
93
|
+
# Since the layout will be inside a scroll area make sure it respects the sizes we set
|
94
|
+
layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
|
95
|
+
|
96
|
+
interfaces_table = Qt::TableWidget.new()
|
97
|
+
interfaces_table.verticalHeader.hide()
|
98
|
+
interfaces_table.setRowCount(interfaces.all.length)
|
99
|
+
interfaces_table.setColumnCount(10)
|
100
|
+
if name == ROUTERS
|
101
|
+
interfaces_table.setHorizontalHeaderLabels(["Router", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
|
102
|
+
else
|
103
|
+
interfaces_table.setHorizontalHeaderLabels(["Interface", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
|
104
|
+
end
|
105
|
+
|
106
|
+
populate_interface_table(name, interfaces, interfaces_table)
|
107
|
+
interfaces_table.displayFullSize
|
108
|
+
|
109
|
+
layout.addWidget(interfaces_table)
|
110
|
+
scroll.setWidget(widget)
|
111
|
+
@interfaces_table[name] = interfaces_table
|
112
|
+
tab_widget.addTab(scroll, name)
|
113
|
+
end
|
114
|
+
|
115
|
+
def populate_interface_table(name, interfaces, interfaces_table)
|
116
|
+
row = 0
|
117
|
+
interfaces.all.each do |interface_name, interface|
|
118
|
+
item = Qt::TableWidgetItem.new(Qt::Object.tr(interface_name))
|
119
|
+
item.setTextAlignment(Qt::AlignCenter)
|
120
|
+
interfaces_table.setItem(row, 0, item)
|
121
|
+
interfaces_table.setCellWidget(row, 1, create_button(name, interface, interface_name))
|
122
|
+
interfaces_table.setItem(row, 2, create_state(interface))
|
123
|
+
|
124
|
+
index = 3
|
125
|
+
[interface.num_clients, interface.write_queue_size, interface.read_queue_size,
|
126
|
+
interface.bytes_written, interface.bytes_read,
|
127
|
+
interface.write_count, interface.read_count].each do |val|
|
128
|
+
|
129
|
+
item = Qt::TableWidgetItem.new(Qt::Object.tr(val.to_s))
|
130
|
+
item.setTextAlignment(Qt::AlignCenter)
|
131
|
+
interfaces_table.setItem(row, index, item)
|
132
|
+
index += 1
|
133
|
+
end
|
134
|
+
row += 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def create_button(name, interface, interface_name)
|
139
|
+
if interface.connected?
|
140
|
+
button_text = 'Disconnect'
|
141
|
+
elsif interface.thread.nil?
|
142
|
+
button_text = 'Connect'
|
143
|
+
else
|
144
|
+
button_text = 'Cancel Connect'
|
145
|
+
end
|
146
|
+
button = Qt::PushButton.new(button_text)
|
147
|
+
if name == ROUTERS
|
148
|
+
button.connect(SIGNAL('clicked()')) do
|
149
|
+
if interface.thread
|
150
|
+
Logger.info "User disconnecting router #{interface_name}"
|
151
|
+
CmdTlmServer.instance.disconnect_router(interface_name)
|
152
|
+
else
|
153
|
+
Logger.info "User connecting router #{interface_name}"
|
154
|
+
CmdTlmServer.instance.connect_router(interface_name)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
else
|
158
|
+
button.connect(SIGNAL('clicked()')) do
|
159
|
+
if interface.thread
|
160
|
+
Logger.info "User disconnecting interface #{interface_name}"
|
161
|
+
CmdTlmServer.instance.disconnect_interface(interface_name)
|
162
|
+
else
|
163
|
+
Logger.info "User connecting interface #{interface_name}"
|
164
|
+
CmdTlmServer.instance.connect_interface(interface_name)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
button.setDisabled(true) if interface.disable_disconnect
|
169
|
+
button
|
170
|
+
end
|
171
|
+
|
172
|
+
def create_state(interface)
|
173
|
+
state = Qt::TableWidgetItem.new
|
174
|
+
if interface.connected?
|
175
|
+
state.setText('true')
|
176
|
+
state.textColor = Cosmos::GREEN
|
177
|
+
elsif interface.thread
|
178
|
+
state.setText('attempting')
|
179
|
+
state.textColor = Cosmos::YELLOW
|
180
|
+
else
|
181
|
+
state.setText('false')
|
182
|
+
state.textColor = Cosmos::BLACK
|
183
|
+
end
|
184
|
+
state.setTextAlignment(Qt::AlignCenter)
|
185
|
+
state
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end # module Cosmos
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2014 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
|
11
|
+
require 'cosmos'
|
12
|
+
require 'cosmos/gui/qt'
|
13
|
+
|
14
|
+
module Cosmos
|
15
|
+
|
16
|
+
# Implements the logging tab in the Command and Telemetry Server GUI
|
17
|
+
class LoggingTab
|
18
|
+
|
19
|
+
def initialize(production)
|
20
|
+
@production = production
|
21
|
+
@logging_layouts = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create the logging tab and add it to the tab_widget
|
25
|
+
#
|
26
|
+
# @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
|
27
|
+
def populate(tab_widget)
|
28
|
+
scroll = Qt::ScrollArea.new
|
29
|
+
widget = Qt::Widget.new
|
30
|
+
layout = Qt::VBoxLayout.new(widget)
|
31
|
+
# Since the layout will be inside a scroll area
|
32
|
+
# make sure it respects the sizes we set
|
33
|
+
layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
|
34
|
+
|
35
|
+
populate_logging_actions(layout)
|
36
|
+
|
37
|
+
# Add the cmd/tlm log files information
|
38
|
+
populate_log_file_info(layout)
|
39
|
+
|
40
|
+
# Set the scroll area widget last now that all the items have been layed out
|
41
|
+
scroll.setWidget(widget)
|
42
|
+
tab_widget.addTab(scroll, "Logging")
|
43
|
+
end
|
44
|
+
|
45
|
+
def update
|
46
|
+
CmdTlmServer.packet_logging.all.each do |packet_log_writer_pair_name, packet_log_writer_pair|
|
47
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(1, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.logging_enabled.to_s)
|
48
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(2, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.queue.size.to_s)
|
49
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(3, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.filename)
|
50
|
+
file_size = 0
|
51
|
+
begin
|
52
|
+
file_size = File.size(packet_log_writer_pair.cmd_log_writer.filename) if packet_log_writer_pair.cmd_log_writer.filename
|
53
|
+
rescue Exception
|
54
|
+
# Do nothing on error
|
55
|
+
end
|
56
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(4, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
|
57
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(5, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.logging_enabled.to_s)
|
58
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(6, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.queue.size.to_s)
|
59
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(7, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.filename)
|
60
|
+
file_size = 0
|
61
|
+
begin
|
62
|
+
file_size = File.size(packet_log_writer_pair.tlm_log_writer.filename) if packet_log_writer_pair.tlm_log_writer.filename
|
63
|
+
rescue Exception
|
64
|
+
# Do nothing on error
|
65
|
+
end
|
66
|
+
@logging_layouts[packet_log_writer_pair_name].itemAt(8, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def populate_logging_actions(layout)
|
73
|
+
# Add all the action buttons
|
74
|
+
actions = Qt::GroupBox.new(Qt::Object.tr("Actions"))
|
75
|
+
actions_layout = Qt::VBoxLayout.new(actions)
|
76
|
+
button_layout = Qt::GridLayout.new
|
77
|
+
|
78
|
+
log_buttons = [
|
79
|
+
["Start Logging on All", [0,0], :start_logging],
|
80
|
+
["Stop Logging on All", [0,1], :stop_logging],
|
81
|
+
["Start Telemetry Logging on All", [1,0], :start_tlm_log],
|
82
|
+
["Stop Telemetry Logging on All", [1,1], :stop_tlm_log],
|
83
|
+
["Start Command Logging on All", [2,0], :start_cmd_log],
|
84
|
+
["Stop Command Logging on All", [2,1], :stop_cmd_log]
|
85
|
+
]
|
86
|
+
|
87
|
+
log_buttons.each do |text, location, method|
|
88
|
+
next if text =~ /Stop/ and @production
|
89
|
+
button = Qt::PushButton.new(Qt::Object.tr(text))
|
90
|
+
button_layout.addWidget(button, location[0], location[1])
|
91
|
+
button.connect(SIGNAL('clicked()')) do
|
92
|
+
begin
|
93
|
+
CmdTlmServer.instance.send(method, 'ALL')
|
94
|
+
rescue Exception => error
|
95
|
+
statusBar.showMessage(Qt::Object.tr(error.message))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
actions_layout.addLayout(button_layout)
|
101
|
+
|
102
|
+
layout.addWidget(actions)
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_log_layout(form_layout, log_writer, label_prefix)
|
106
|
+
label = Qt::Label.new(Qt::Object.tr(log_writer.logging_enabled.to_s))
|
107
|
+
label.setTextInteractionFlags(Qt::TextSelectableByMouse)
|
108
|
+
form_layout.addRow("#{label_prefix} Logging:", label)
|
109
|
+
label = Qt::Label.new(Qt::Object.tr(log_writer.queue.size.to_s))
|
110
|
+
label.setTextInteractionFlags(Qt::TextSelectableByMouse)
|
111
|
+
form_layout.addRow("#{label_prefix} Queue Size:", label)
|
112
|
+
label = Qt::Label.new(Qt::Object.tr(log_writer.filename))
|
113
|
+
label.setTextInteractionFlags(Qt::TextSelectableByMouse)
|
114
|
+
form_layout.addRow("#{label_prefix} Filename:", label)
|
115
|
+
file_size = 0
|
116
|
+
begin
|
117
|
+
file_size = File.size(log_writer.filename) if log_writer.filename
|
118
|
+
rescue Exception
|
119
|
+
# Do nothing on error
|
120
|
+
end
|
121
|
+
label = Qt::Label.new(Qt::Object.tr(file_size.to_s))
|
122
|
+
label.setTextInteractionFlags(Qt::TextSelectableByMouse)
|
123
|
+
form_layout.addRow("#{label_prefix} File Size:", label)
|
124
|
+
end
|
125
|
+
|
126
|
+
def populate_log_file_info(layout)
|
127
|
+
CmdTlmServer.packet_logging.all.sort.each do |packet_log_writer_pair_name, packet_log_writer_pair|
|
128
|
+
log = Qt::GroupBox.new("#{packet_log_writer_pair_name} Packet Log Writer")
|
129
|
+
log_layout = Qt::VBoxLayout.new(log)
|
130
|
+
interfaces = []
|
131
|
+
CmdTlmServer.interfaces.all.each do |interface_name, interface|
|
132
|
+
if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
|
133
|
+
interfaces << interface.name
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
form_layout = Qt::FormLayout.new
|
138
|
+
@logging_layouts[packet_log_writer_pair_name] = form_layout
|
139
|
+
label = Qt::Label.new(Qt::Object.tr(interfaces.join(", ")))
|
140
|
+
label.setTextInteractionFlags(Qt::TextSelectableByMouse)
|
141
|
+
form_layout.addRow("Interfaces:", label)
|
142
|
+
create_log_layout(form_layout, packet_log_writer_pair.cmd_log_writer, 'Cmd')
|
143
|
+
create_log_layout(form_layout, packet_log_writer_pair.tlm_log_writer, 'Tlm')
|
144
|
+
|
145
|
+
button_layout = Qt::HBoxLayout.new
|
146
|
+
start_button = Qt::PushButton.new(Qt::Object.tr('Start Cmd Logging'))
|
147
|
+
button_layout.addWidget(start_button)
|
148
|
+
start_button.connect(SIGNAL('clicked()')) do
|
149
|
+
CmdTlmServer.instance.start_cmd_log(packet_log_writer_pair_name)
|
150
|
+
end
|
151
|
+
start_button = Qt::PushButton.new(Qt::Object.tr('Start Tlm Logging'))
|
152
|
+
button_layout.addWidget(start_button)
|
153
|
+
start_button.connect(SIGNAL('clicked()')) do
|
154
|
+
CmdTlmServer.instance.start_tlm_log(packet_log_writer_pair_name)
|
155
|
+
end
|
156
|
+
if @production == false
|
157
|
+
stop_button = Qt::PushButton.new(Qt::Object.tr('Stop Cmd Logging'))
|
158
|
+
button_layout.addWidget(stop_button)
|
159
|
+
stop_button.connect(SIGNAL('clicked()')) do
|
160
|
+
CmdTlmServer.instance.stop_cmd_log(packet_log_writer_pair_name)
|
161
|
+
end
|
162
|
+
stop_button = Qt::PushButton.new(Qt::Object.tr('Stop Tlm Logging'))
|
163
|
+
button_layout.addWidget(stop_button)
|
164
|
+
stop_button.connect(SIGNAL('clicked()')) do
|
165
|
+
CmdTlmServer.instance.stop_tlm_log(packet_log_writer_pair_name)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
form_layout.addRow("Actions:", button_layout)
|
169
|
+
log_layout.addLayout(form_layout)
|
170
|
+
layout.addWidget(log)
|
171
|
+
end
|
172
|
+
layout.addWidget(Qt::Label.new(Qt::Object.tr("Note: Buffered IO operations cause file size to not reflect total logged data size until the log file is closed.")))
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end # module Cosmos
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2014 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
|
11
|
+
require 'cosmos'
|
12
|
+
require 'cosmos/gui/qt'
|
13
|
+
require 'cosmos/gui/dialogs/cmd_tlm_raw_dialog'
|
14
|
+
|
15
|
+
module Cosmos
|
16
|
+
|
17
|
+
# Implements the packets tab in the Command and Telemetry Server GUI
|
18
|
+
class PacketsTab
|
19
|
+
COMMANDS = "Commands"
|
20
|
+
TELEMETRY = "Telemetry"
|
21
|
+
|
22
|
+
def initialize(server_gui)
|
23
|
+
@server_gui = server_gui
|
24
|
+
@packets_table = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def populate_commands(tab_widget)
|
28
|
+
populate(COMMANDS, System.commands, tab_widget)
|
29
|
+
end
|
30
|
+
|
31
|
+
def populate_telemetry(tab_widget)
|
32
|
+
populate(TELEMETRY, System.telemetry, tab_widget)
|
33
|
+
end
|
34
|
+
|
35
|
+
def update(name)
|
36
|
+
cmd_tlm = nil
|
37
|
+
cmd_tlm = System.commands if name == COMMANDS
|
38
|
+
cmd_tlm = System.telemetry if name == TELEMETRY
|
39
|
+
return if cmd_tlm.nil? || cmd_tlm.target_names.empty?
|
40
|
+
|
41
|
+
row = 0
|
42
|
+
cmd_tlm.target_names.sort.each do |target_name|
|
43
|
+
packets = cmd_tlm.packets(target_name)
|
44
|
+
packets.sort.each do |packet_name, packet|
|
45
|
+
next if packet.hidden
|
46
|
+
@packets_table[name].item(row, 2).setText(packet.received_count.to_s)
|
47
|
+
row += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def populate(name, cmd_tlm, tab_widget)
|
55
|
+
return if cmd_tlm.target_names.empty?
|
56
|
+
|
57
|
+
count = 0
|
58
|
+
cmd_tlm.target_names.sort.each do |target_name|
|
59
|
+
packets = cmd_tlm.packets(target_name)
|
60
|
+
packets.each do |packet_name, packet|
|
61
|
+
count += 1 unless packet.hidden
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
scroll = Qt::ScrollArea.new
|
66
|
+
widget = Qt::Widget.new
|
67
|
+
layout = Qt::VBoxLayout.new(widget)
|
68
|
+
# Since the layout will be inside a scroll area
|
69
|
+
# make sure it respects the sizes we set
|
70
|
+
layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
|
71
|
+
|
72
|
+
table = Qt::TableWidget.new()
|
73
|
+
table.verticalHeader.hide()
|
74
|
+
table.setRowCount(count)
|
75
|
+
column_cnt = 4
|
76
|
+
column_cnt += 1 if name == TELEMETRY
|
77
|
+
table.setColumnCount(column_cnt)
|
78
|
+
# Force the last section to fill all available space in the frame
|
79
|
+
#~ table.horizontalHeader.setStretchLastSection(true)
|
80
|
+
headers = ["Target Name", "Packet Name", "Packet Count", "View Raw"]
|
81
|
+
headers << "View in Packet Viewer" if name == TELEMETRY
|
82
|
+
table.setHorizontalHeaderLabels(headers)
|
83
|
+
|
84
|
+
populate_packets_table(name, cmd_tlm, table)
|
85
|
+
table.displayFullSize
|
86
|
+
|
87
|
+
layout.addWidget(table)
|
88
|
+
scroll.setWidget(widget)
|
89
|
+
tab_name = "Cmd Packets" if name == COMMANDS
|
90
|
+
tab_name = "Tlm Packets" if name == TELEMETRY
|
91
|
+
tab_widget.addTab(scroll, tab_name)
|
92
|
+
|
93
|
+
@packets_table[name] = table
|
94
|
+
end
|
95
|
+
|
96
|
+
def populate_packets_table(name, cmd_tlm, table)
|
97
|
+
row = 0
|
98
|
+
cmd_tlm.target_names.sort.each do |target_name|
|
99
|
+
packets = cmd_tlm.packets(target_name)
|
100
|
+
packets.sort.each do |packet_name, packet|
|
101
|
+
packet.received_count ||= 0
|
102
|
+
next if packet.hidden
|
103
|
+
target_name_widget = Qt::TableWidgetItem.new(Qt::Object.tr(target_name))
|
104
|
+
target_name_widget.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
|
105
|
+
table.setItem(row, 0, target_name_widget)
|
106
|
+
table.setItem(row, 1, Qt::TableWidgetItem.new(Qt::Object.tr(packet_name)))
|
107
|
+
packet_count = Qt::TableWidgetItem.new(Qt::Object.tr(packet.received_count.to_s))
|
108
|
+
packet_count.setTextAlignment(Qt::AlignCenter)
|
109
|
+
table.setItem(row, 2, packet_count)
|
110
|
+
view_raw = Qt::PushButton.new("View Raw")
|
111
|
+
view_raw.connect(SIGNAL('clicked()')) do
|
112
|
+
@raw_dialogs ||= []
|
113
|
+
@raw_dialogs << CmdRawDialog.new(@server_gui, target_name, packet_name) if name == COMMANDS
|
114
|
+
@raw_dialogs << TlmRawDialog.new(@server_gui, target_name, packet_name) if name == TELEMETRY
|
115
|
+
end
|
116
|
+
table.setCellWidget(row, 3, view_raw)
|
117
|
+
|
118
|
+
if name == TELEMETRY
|
119
|
+
if target_name != 'UNKNOWN' and packet_name != 'UNKNOWN'
|
120
|
+
view_pv = Qt::PushButton.new("View in Packet Viewer")
|
121
|
+
view_pv.connect(SIGNAL('clicked()')) do
|
122
|
+
if Kernel.is_windows?
|
123
|
+
Cosmos.run_process("rubyw tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
|
124
|
+
elsif Kernel.is_mac? and File.exist?("tools/mac/PacketViewer.app")
|
125
|
+
Cosmos.run_process("open tools/mac/PacketViewer.app --args -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
|
126
|
+
else
|
127
|
+
Cosmos.run_process("ruby tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
table.setCellWidget(row, 4, view_pv)
|
131
|
+
else
|
132
|
+
table_widget = Qt::TableWidgetItem.new(Qt::Object.tr('N/A'))
|
133
|
+
table_widget.setTextAlignment(Qt::AlignCenter)
|
134
|
+
table.setItem(row, 4, table_widget)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
row += 1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end # module Cosmos
|