cosmos 4.0.3-java → 4.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -5
- data/Manifest.txt +11 -1
- data/README.md +3 -2
- data/Rakefile +18 -4
- data/appveyor.yml +19 -0
- data/cosmos.gemspec +12 -3
- data/data/config/cmd_tlm_server.yaml +3 -0
- data/data/crc.txt +63 -60
- data/demo/config/targets/INST/cmd_tlm_server.txt +1 -0
- data/demo/config/targets/INST/cmd_tlm_server2.txt +7 -0
- data/demo/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +8 -12
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +7 -9
- data/demo/lib/cmd_sequence_exporter.rb +52 -0
- data/demo/lib/example_background_task.rb +1 -0
- data/demo/procedures/replay_test.rb +32 -0
- data/ext/cosmos/ext/structure/structure.c +39 -3
- data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +1 -0
- data/install/config/tools/launcher/launcher.txt +2 -0
- data/lib/cosmos/config/config_parser.rb +2 -0
- data/lib/cosmos/core_ext/io.rb +89 -60
- data/lib/cosmos/gui/qt.rb +5 -8
- data/lib/cosmos/gui/qt_tool.rb +8 -8
- data/lib/cosmos/gui/text/ruby_editor.rb +12 -12
- data/lib/cosmos/gui/utilities/script_module_gui.rb +9 -9
- data/lib/cosmos/gui/widgets/realtime_button_bar.rb +18 -17
- data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +2 -2
- data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -0
- data/lib/cosmos/interfaces/udp_interface.rb +27 -14
- data/lib/cosmos/io/buffered_file.rb +0 -1
- data/lib/cosmos/io/json_drb.rb +134 -214
- data/lib/cosmos/io/json_drb_object.rb +22 -61
- data/lib/cosmos/io/json_drb_rack.rb +79 -0
- data/lib/cosmos/io/json_rpc.rb +27 -0
- data/lib/cosmos/io/udp_sockets.rb +102 -58
- data/lib/cosmos/packets/commands.rb +1 -1
- data/lib/cosmos/packets/structure.rb +1 -1
- data/lib/cosmos/packets/structure_item.rb +37 -5
- data/lib/cosmos/script/cmd_tlm_server.rb +76 -2
- data/lib/cosmos/script/replay.rb +60 -0
- data/lib/cosmos/script/script.rb +20 -2
- data/lib/cosmos/script/scripting.rb +9 -9
- data/lib/cosmos/script/tools.rb +14 -0
- data/lib/cosmos/system/system.rb +185 -92
- data/lib/cosmos/system/target.rb +1 -1
- data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +44 -4
- data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +4 -0
- data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +7 -0
- data/lib/cosmos/tools/cmd_tlm_server/api.rb +347 -20
- data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +3 -0
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +329 -111
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +13 -0
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +261 -95
- data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +46 -35
- data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +18 -8
- data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +39 -28
- data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +242 -0
- data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +24 -8
- data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +18 -6
- data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +5 -4
- data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +375 -0
- data/lib/cosmos/tools/cmd_tlm_server/routers.rb +10 -2
- data/lib/cosmos/tools/data_viewer/data_viewer.rb +40 -5
- data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +18 -20
- data/lib/cosmos/tools/launcher/launcher_config.rb +5 -16
- data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +65 -39
- data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +19 -0
- data/lib/cosmos/tools/replay/replay.rb +5 -505
- data/lib/cosmos/tools/script_runner/script_audit.rb +1 -0
- data/lib/cosmos/tools/script_runner/script_runner.rb +3 -4
- data/lib/cosmos/tools/script_runner/script_runner_config.rb +3 -4
- data/lib/cosmos/tools/script_runner/script_runner_frame.rb +44 -23
- data/lib/cosmos/tools/test_runner/results_writer.rb +4 -0
- data/lib/cosmos/tools/test_runner/test_runner.rb +0 -3
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +6 -2
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +26 -1
- data/lib/cosmos/tools/tlm_viewer/screen.rb +24 -1
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +25 -0
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +24 -14
- data/lib/cosmos/top_level.rb +34 -24
- data/lib/cosmos/utilities/csv.rb +60 -8
- data/lib/cosmos/version.rb +5 -5
- data/spec/config/config_parser_spec.rb +10 -1
- data/spec/core_ext/socket_spec.rb +4 -2
- data/spec/gui/utilities/script_module_gui_spec.rb +102 -0
- data/spec/install/config/data/data.txt +1 -0
- data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
- data/spec/interfaces/cmd_tlm_server_interface_spec.rb +1 -2
- data/spec/interfaces/protocols/template_protocol_spec.rb +72 -2
- data/spec/interfaces/serial_interface_spec.rb +1 -1
- data/spec/interfaces/udp_interface_spec.rb +14 -0
- data/spec/io/buffered_file_spec.rb +37 -0
- data/spec/io/json_drb_object_spec.rb +2 -15
- data/spec/io/json_drb_spec.rb +61 -121
- data/spec/io/udp_sockets_spec.rb +42 -2
- data/spec/packet_logs/packet_log_reader_spec.rb +5 -2
- data/spec/packets/binary_accessor_spec.rb +1 -1
- data/spec/packets/packet_item_spec.rb +1 -1
- data/spec/packets/structure_item_spec.rb +5 -6
- data/spec/script/cmd_tlm_server_spec.rb +39 -4
- data/spec/script/commands_disconnect_spec.rb +1 -1
- data/spec/script/commands_spec.rb +2 -1
- data/spec/script/scripting_spec.rb +18 -3
- data/spec/script/telemetry_spec.rb +5 -0
- data/spec/spec_helper.rb +43 -26
- data/spec/streams/tcpip_socket_stream_spec.rb +2 -2
- data/spec/system/system_spec.rb +11 -9
- data/spec/system/target_spec.rb +3 -0
- data/spec/tools/cmd_tlm_server/api_spec.rb +543 -29
- data/spec/tools/cmd_tlm_server/background_task_spec.rb +2 -2
- data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +31 -75
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +199 -66
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +85 -9
- data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +29 -127
- data/spec/tools/cmd_tlm_server/router_thread_spec.rb +10 -50
- data/spec/tools/launcher/launcher_config_spec.rb +1 -1
- data/spec/tools/table_manager/table_item_spec.rb +1 -1
- data/spec/tools/table_manager/tablemanager_core_spec.rb +4 -4
- data/spec/top_level/top_level_spec.rb +151 -3
- data/spec/utilities/csv_spec.rb +24 -5
- metadata +61 -9
- data/lib/cosmos/tools/replay/replay_server.rb +0 -91
|
@@ -51,6 +51,13 @@ module Cosmos
|
|
|
51
51
|
|
|
52
52
|
protected
|
|
53
53
|
|
|
54
|
+
def get_target_interface_name(target_name)
|
|
55
|
+
@interfaces.each do |interface_name, interface|
|
|
56
|
+
return interface_name if interface.target_names.include?(target_name)
|
|
57
|
+
end
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
54
61
|
# Processes a file and adds in the configuration defined in the file
|
|
55
62
|
#
|
|
56
63
|
# @param filename [String] The name of the configuration file to parse
|
|
@@ -105,6 +112,8 @@ module Cosmos
|
|
|
105
112
|
System.targets.each do |target_name, target|
|
|
106
113
|
target_filename = File.join(target.dir, 'cmd_tlm_server.txt')
|
|
107
114
|
if File.exist?(target_filename)
|
|
115
|
+
# Skip this target if it's already been assigned an interface
|
|
116
|
+
next if get_target_interface_name(target.name)
|
|
108
117
|
raise parser.error("Cannot use #{keyword} with target name substitutions: #{target.name} != #{target.original_name}") if target.name != target.original_name
|
|
109
118
|
process_file(target_filename, true)
|
|
110
119
|
end
|
|
@@ -116,6 +125,8 @@ module Cosmos
|
|
|
116
125
|
parser.verify_num_parameters(1, 2, usage)
|
|
117
126
|
target = System.targets[params[0].upcase]
|
|
118
127
|
raise parser.error("Unknown target: #{params[0].upcase}") unless target
|
|
128
|
+
interface_name = get_target_interface_name(target.name)
|
|
129
|
+
raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
|
|
119
130
|
target_filename = params[1]
|
|
120
131
|
target_filename = 'cmd_tlm_server.txt' unless target_filename
|
|
121
132
|
target_filename = File.join(target.dir, target_filename)
|
|
@@ -164,6 +175,8 @@ module Cosmos
|
|
|
164
175
|
target_name = params[0].upcase
|
|
165
176
|
target = System.targets[target_name]
|
|
166
177
|
if target
|
|
178
|
+
interface_name = get_target_interface_name(target.name)
|
|
179
|
+
raise parser.error("Target #{target.name} already mapped to interface #{interface_name}") if interface_name
|
|
167
180
|
target.interface = current_interface_or_router
|
|
168
181
|
current_interface_or_router.target_names << target_name
|
|
169
182
|
else
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
2
|
|
|
3
|
-
# Copyright
|
|
3
|
+
# Copyright 2017 Ball Aerospace & Technologies Corp.
|
|
4
4
|
# All Rights Reserved.
|
|
5
5
|
#
|
|
6
6
|
# This program is free software; you can modify and/or redistribute it
|
|
@@ -16,6 +16,7 @@ if RUBY_ENGINE == 'ruby'
|
|
|
16
16
|
require 'cosmos/tools/cmd_tlm_server/gui/packets_tab'
|
|
17
17
|
require 'cosmos/tools/cmd_tlm_server/gui/logging_tab'
|
|
18
18
|
require 'cosmos/tools/cmd_tlm_server/gui/status_tab'
|
|
19
|
+
require 'cosmos/tools/cmd_tlm_server/gui/replay_tab'
|
|
19
20
|
require 'cosmos/gui/qt_tool'
|
|
20
21
|
require 'cosmos/gui/dialogs/splash'
|
|
21
22
|
require 'cosmos/gui/dialogs/exception_dialog'
|
|
@@ -85,7 +86,8 @@ module Cosmos
|
|
|
85
86
|
RUNNING = 1
|
|
86
87
|
ERROR = 2
|
|
87
88
|
|
|
88
|
-
TOOL_NAME = "Command and Telemetry Server"
|
|
89
|
+
TOOL_NAME = "Command and Telemetry Server".freeze
|
|
90
|
+
BLANK = ''.freeze
|
|
89
91
|
|
|
90
92
|
attr_writer :no_prompt
|
|
91
93
|
|
|
@@ -109,69 +111,94 @@ module Cosmos
|
|
|
109
111
|
|
|
110
112
|
def initialize(options)
|
|
111
113
|
super(options) # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes
|
|
112
|
-
Cosmos.load_cosmos_icon("cts.png")
|
|
113
114
|
|
|
115
|
+
@ready = false
|
|
116
|
+
@tabs_ready = false
|
|
117
|
+
if options.replay
|
|
118
|
+
@mode = :REPLAY
|
|
119
|
+
Cosmos.load_cosmos_icon("replay.png")
|
|
120
|
+
else
|
|
121
|
+
@mode = :CMD_TLM_SERVER
|
|
122
|
+
Cosmos.load_cosmos_icon("cts.png")
|
|
123
|
+
end
|
|
114
124
|
@production = options.production
|
|
115
125
|
@no_prompt = options.no_prompt
|
|
116
126
|
@message_log = nil
|
|
117
127
|
@output_sleeper = Sleeper.new
|
|
118
128
|
@first_output = 0
|
|
119
|
-
@
|
|
120
|
-
@targets_tab = TargetsTab.new
|
|
121
|
-
@packets_tab = PacketsTab.new(self)
|
|
122
|
-
@logging_tab = LoggingTab.new(@production)
|
|
123
|
-
@status_tab = StatusTab.new
|
|
129
|
+
@options = options
|
|
124
130
|
|
|
125
131
|
statusBar.showMessage(tr("")) # Show blank message to initialize status bar
|
|
126
132
|
|
|
127
133
|
initialize_actions()
|
|
128
134
|
initialize_menus()
|
|
129
135
|
initialize_central_widget()
|
|
130
|
-
configure_tabs(options)
|
|
131
|
-
complete_initialize()
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def configure_tabs(options)
|
|
135
136
|
Splash.execute(self) do |splash|
|
|
136
137
|
ConfigParser.splash = splash
|
|
137
|
-
|
|
138
|
+
process_server_messages(@options)
|
|
139
|
+
start(splash)
|
|
140
|
+
ConfigParser.splash = nil
|
|
141
|
+
end
|
|
142
|
+
complete_initialize()
|
|
143
|
+
end
|
|
138
144
|
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
def start(splash)
|
|
146
|
+
splash.message = "Initializing #{@options.title}" if splash
|
|
141
147
|
|
|
148
|
+
if !CmdTlmServer.instance or @mode == :CMD_TLM_SERVER
|
|
142
149
|
CmdTlmServer.meta_callback = method(:meta_callback)
|
|
143
|
-
cts = CmdTlmServer.new(options.config_file, @production)
|
|
150
|
+
cts = CmdTlmServer.new(@options.config_file, @production, false, @mode)
|
|
151
|
+
CmdTlmServerGui.configure_signal_handlers()
|
|
144
152
|
cts.stop_callback = method(:stop_callback)
|
|
153
|
+
cts.reload_callback = method(:reload)
|
|
154
|
+
CmdTlmServer.replay_backend.config_change_callback = method(:config_change_callback) if @mode != :CMD_TLM_SERVER
|
|
145
155
|
@message_log = CmdTlmServer.message_log
|
|
156
|
+
@ready = true
|
|
157
|
+
end
|
|
146
158
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
@
|
|
156
|
-
|
|
157
|
-
@
|
|
158
|
-
splash.progress = 100/7 * 3
|
|
159
|
-
@packets_tab.populate_telemetry(@tab_widget)
|
|
160
|
-
splash.progress = 100/7 * 4
|
|
161
|
-
@interfaces_tab.populate_routers(@tab_widget)
|
|
162
|
-
splash.progress = 100/7 * 5
|
|
163
|
-
@logging_tab.populate(@tab_widget)
|
|
164
|
-
splash.progress = 100/7 * 6
|
|
165
|
-
@status_tab.populate(@tab_widget)
|
|
166
|
-
splash.progress = 100
|
|
159
|
+
# Now that we've started the server (CmdTlmServer.new) we can populate all the tabs
|
|
160
|
+
splash.message = "Populating Tabs" if splash
|
|
161
|
+
Qt.execute_in_main_thread(true) do
|
|
162
|
+
# Override the default title if one was given in the config file
|
|
163
|
+
self.window_title = CmdTlmServer.title if CmdTlmServer.title
|
|
164
|
+
splash.progress = 0 if splash
|
|
165
|
+
@tabs_ready = false
|
|
166
|
+
if @mode == :CMD_TLM_SERVER
|
|
167
|
+
@interfaces_tab.populate_interfaces
|
|
168
|
+
else
|
|
169
|
+
@replay_tab.populate
|
|
167
170
|
end
|
|
168
|
-
|
|
171
|
+
splash.progress = 100/7 * 1 if splash
|
|
172
|
+
@targets_tab.populate
|
|
173
|
+
splash.progress = 100/7 * 2 if splash
|
|
174
|
+
@commands_tab.populate_commands
|
|
175
|
+
splash.progress = 100/7 * 3 if splash
|
|
176
|
+
@telemetry_tab.populate_telemetry
|
|
177
|
+
splash.progress = 100/7 * 4 if splash
|
|
178
|
+
@routers_tab.populate_routers
|
|
179
|
+
if @mode == :CMD_TLM_SERVER
|
|
180
|
+
splash.progress = 100/7 * 5 if splash
|
|
181
|
+
@logging_tab.populate
|
|
182
|
+
end
|
|
183
|
+
splash.progress = 100/7 * 6 if splash
|
|
184
|
+
@status_tab.populate
|
|
185
|
+
splash.progress = 100 if splash
|
|
186
|
+
@tabs_ready = true
|
|
187
|
+
@tab_widget.setCurrentIndex(0)
|
|
188
|
+
handle_tab_change(0)
|
|
169
189
|
end
|
|
170
190
|
end
|
|
171
191
|
|
|
172
192
|
def initialize_actions
|
|
173
193
|
super()
|
|
174
194
|
|
|
195
|
+
# File actions
|
|
196
|
+
@file_reload = Qt::Action.new(tr('&Reload Configuration'), self)
|
|
197
|
+
@file_reload.statusTip = tr('Reload configuraton and reset')
|
|
198
|
+
@file_reload.connect(SIGNAL('triggered()')) do
|
|
199
|
+
CmdTlmServer.instance.reload()
|
|
200
|
+
end
|
|
201
|
+
|
|
175
202
|
# Edit actions
|
|
176
203
|
@edit_clear_counters = Qt::Action.new(tr('&Clear Counters'), self)
|
|
177
204
|
@edit_clear_counters.statusTip = tr('Clear counters for all interfaces and targets')
|
|
@@ -180,6 +207,7 @@ module Cosmos
|
|
|
180
207
|
|
|
181
208
|
def initialize_menus
|
|
182
209
|
@file_menu = menuBar.addMenu(tr('&File'))
|
|
210
|
+
@file_menu.addAction(@file_reload)
|
|
183
211
|
@file_menu.addAction(@exit_action)
|
|
184
212
|
|
|
185
213
|
# Do not allow clear counters in production mode
|
|
@@ -188,8 +216,12 @@ module Cosmos
|
|
|
188
216
|
@edit_menu.addAction(@edit_clear_counters)
|
|
189
217
|
end
|
|
190
218
|
|
|
191
|
-
@
|
|
192
|
-
|
|
219
|
+
if @mode == :CMD_TLM_SERVER
|
|
220
|
+
@about_string = "#{TOOL_NAME} is the heart of the COSMOS system. "
|
|
221
|
+
@about_string << "It connects to the target and processes command and telemetry requests from other tools."
|
|
222
|
+
else
|
|
223
|
+
@about_string = "Replay allows playing back data into the COSMOS realtime tools. "
|
|
224
|
+
end
|
|
193
225
|
|
|
194
226
|
initialize_help_menu()
|
|
195
227
|
end
|
|
@@ -221,30 +253,97 @@ module Cosmos
|
|
|
221
253
|
Logger.level = Logger::INFO
|
|
222
254
|
|
|
223
255
|
@tab_thread = nil
|
|
256
|
+
|
|
257
|
+
if @mode == :CMD_TLM_SERVER
|
|
258
|
+
@interfaces_tab = InterfacesTab.new(self, InterfacesTab::INTERFACES, @tab_widget)
|
|
259
|
+
else
|
|
260
|
+
@replay_tab = ReplayTab.new(@tab_widget)
|
|
261
|
+
end
|
|
262
|
+
@targets_tab = TargetsTab.new(@tab_widget)
|
|
263
|
+
@commands_tab = PacketsTab.new(self, PacketsTab::COMMANDS, @tab_widget)
|
|
264
|
+
@telemetry_tab = PacketsTab.new(self, PacketsTab::TELEMETRY, @tab_widget)
|
|
265
|
+
@routers_tab = InterfacesTab.new(self, InterfacesTab::ROUTERS, @tab_widget)
|
|
266
|
+
if @mode == :CMD_TLM_SERVER
|
|
267
|
+
@logging_tab = LoggingTab.new(@production, @tab_widget)
|
|
268
|
+
end
|
|
269
|
+
@status_tab = StatusTab.new(@tab_widget)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def config_change_callback
|
|
273
|
+
start(nil)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def reload(confirm = true)
|
|
277
|
+
Qt.execute_in_main_thread(true) do
|
|
278
|
+
if confirm
|
|
279
|
+
msg = Qt::MessageBox.new(self)
|
|
280
|
+
msg.setIcon(Qt::MessageBox::Question)
|
|
281
|
+
msg.setText("Are you sure? All connections will temporarily disconnect as the server restarts")
|
|
282
|
+
msg.setWindowTitle('Confirm Reload')
|
|
283
|
+
msg.setStandardButtons(Qt::MessageBox::Yes | Qt::MessageBox::No)
|
|
284
|
+
continue = false
|
|
285
|
+
continue = true if msg.exec() == Qt::MessageBox::Yes
|
|
286
|
+
msg.dispose
|
|
287
|
+
else
|
|
288
|
+
continue = true
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if continue
|
|
292
|
+
Splash.execute(self) do |splash|
|
|
293
|
+
ConfigParser.splash = splash
|
|
294
|
+
Qt.execute_in_main_thread(true) do
|
|
295
|
+
@tab_widget.setCurrentIndex(0)
|
|
296
|
+
end
|
|
297
|
+
if @mode == :CMD_TLM_SERVER
|
|
298
|
+
Qt.execute_in_main_thread(true) do
|
|
299
|
+
splash.message = "Stopping Threads"
|
|
300
|
+
CmdTlmServer.instance.stop_callback = nil
|
|
301
|
+
stop_threads()
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
System.reset
|
|
305
|
+
start(splash)
|
|
306
|
+
Qt.execute_in_main_thread(true) do
|
|
307
|
+
@tab_widget.setCurrentIndex(0)
|
|
308
|
+
handle_tab_change(0)
|
|
309
|
+
end
|
|
310
|
+
ConfigParser.splash = nil
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
end
|
|
224
314
|
end
|
|
225
315
|
|
|
226
316
|
# Called when the user changes tabs in the Server application. It kills the
|
|
227
317
|
# currently executing tab and then creates a new thread to update the GUI
|
|
228
318
|
# for the selected tab.
|
|
229
319
|
def handle_tab_change(index)
|
|
320
|
+
return unless @tabs_ready
|
|
230
321
|
kill_tab_thread()
|
|
231
322
|
@tab_sleeper = Sleeper.new
|
|
232
323
|
|
|
233
324
|
case index
|
|
234
325
|
when 0
|
|
235
|
-
|
|
326
|
+
if @mode == :CMD_TLM_SERVER
|
|
327
|
+
handle_tab('Interfaces') { @interfaces_tab.update }
|
|
328
|
+
else
|
|
329
|
+
handle_tab('Replay', 0.5) { @replay_tab.update }
|
|
330
|
+
end
|
|
236
331
|
when 1
|
|
237
332
|
handle_tab('Targets') { @targets_tab.update }
|
|
238
333
|
when 2
|
|
239
|
-
handle_tab('Commands') { @
|
|
334
|
+
handle_tab('Commands') { @commands_tab.update }
|
|
240
335
|
when 3
|
|
241
|
-
handle_tab('Telemetry') { @
|
|
336
|
+
handle_tab('Telemetry') { @telemetry_tab.update }
|
|
242
337
|
when 4
|
|
243
|
-
handle_tab('Routers') { @
|
|
338
|
+
handle_tab('Routers') { @routers_tab.update }
|
|
244
339
|
when 5
|
|
245
|
-
|
|
340
|
+
if @mode == :CMD_TLM_SERVER
|
|
341
|
+
handle_tab('Logging') { @logging_tab.update }
|
|
342
|
+
else
|
|
343
|
+
handle_tab('Status') { @status_tab.update }
|
|
344
|
+
end
|
|
246
345
|
when 6
|
|
247
|
-
|
|
346
|
+
handle_tab('Status') { @status_tab.update }
|
|
248
347
|
end
|
|
249
348
|
end
|
|
250
349
|
|
|
@@ -252,7 +351,9 @@ module Cosmos
|
|
|
252
351
|
def kill_tab_thread
|
|
253
352
|
@tab_sleeper ||= nil
|
|
254
353
|
@tab_sleeper.cancel if @tab_sleeper
|
|
354
|
+
@tab_thread_shutdown = true
|
|
255
355
|
Qt::CoreApplication.instance.processEvents
|
|
356
|
+
Qt::RubyThreadFix.queue.pop.call until Qt::RubyThreadFix.queue.empty?
|
|
256
357
|
Cosmos.kill_thread(self, @tab_thread)
|
|
257
358
|
@tab_thread = nil
|
|
258
359
|
end
|
|
@@ -262,12 +363,18 @@ module Cosmos
|
|
|
262
363
|
# Finally it sleeps using a sleeper so it can be interrupted.
|
|
263
364
|
#
|
|
264
365
|
# @param name [String] Name of the tab
|
|
265
|
-
def handle_tab(name)
|
|
366
|
+
def handle_tab(name, period = 1.0)
|
|
367
|
+
@tab_thread_shutdown = false
|
|
266
368
|
@tab_thread = Thread.new do
|
|
267
369
|
begin
|
|
268
370
|
while true
|
|
371
|
+
start_time = Time.now.sys
|
|
372
|
+
break if @tab_thread_shutdown
|
|
269
373
|
Qt.execute_in_main_thread(true) { yield }
|
|
270
|
-
|
|
374
|
+
total_time = Time.now.sys - start_time
|
|
375
|
+
if total_time > 0.0 and total_time < period
|
|
376
|
+
break if @tab_sleeper.sleep(period - total_time)
|
|
377
|
+
end
|
|
271
378
|
end
|
|
272
379
|
rescue Exception => error
|
|
273
380
|
Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : #{name} Tab Thread")}
|
|
@@ -275,22 +382,11 @@ module Cosmos
|
|
|
275
382
|
end
|
|
276
383
|
end
|
|
277
384
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
@
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
start_time = Time.now.sys
|
|
284
|
-
Qt.execute_in_main_thread(true) { @status_tab.update }
|
|
285
|
-
total_time = Time.now.sys - start_time
|
|
286
|
-
if total_time > 0.0 and total_time < 1.0
|
|
287
|
-
break if @tab_sleeper.sleep(1.0 - total_time)
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
rescue Exception => error
|
|
291
|
-
Qt.execute_in_main_thread(true) {|| ExceptionDialog.new(self, error, "COSMOS CTS : Status Tab Thread")}
|
|
292
|
-
end
|
|
293
|
-
end
|
|
385
|
+
def stop_threads
|
|
386
|
+
kill_tab_thread()
|
|
387
|
+
@replay_tab.shutdown if @replay_tab
|
|
388
|
+
CmdTlmServer.instance.stop_logging('ALL') if @mode == :CMD_TLM_SERVER
|
|
389
|
+
CmdTlmServer.instance.stop
|
|
294
390
|
end
|
|
295
391
|
|
|
296
392
|
# Called when the user tries to close the server application. Popup a
|
|
@@ -303,7 +399,11 @@ module Cosmos
|
|
|
303
399
|
else
|
|
304
400
|
msg = Qt::MessageBox.new(self)
|
|
305
401
|
msg.setIcon(Qt::MessageBox::Question)
|
|
306
|
-
|
|
402
|
+
if @mode == :CMD_TLM_SERVER
|
|
403
|
+
msg.setText("Are you sure? All tools connected to this CmdTlmServer will lose connections and cease to function if the CmdTlmServer is closed.")
|
|
404
|
+
else
|
|
405
|
+
msg.setText("Are you sure? All tools connected to this Replay will lose connections and cease to function if the Replay is closed.")
|
|
406
|
+
end
|
|
307
407
|
msg.setWindowTitle('Confirm Close')
|
|
308
408
|
msg.setStandardButtons(Qt::MessageBox::Yes | Qt::MessageBox::No)
|
|
309
409
|
continue = false
|
|
@@ -312,9 +412,7 @@ module Cosmos
|
|
|
312
412
|
end
|
|
313
413
|
|
|
314
414
|
if continue
|
|
315
|
-
|
|
316
|
-
CmdTlmServer.instance.stop_logging('ALL')
|
|
317
|
-
CmdTlmServer.instance.stop
|
|
415
|
+
stop_threads()
|
|
318
416
|
super(event)
|
|
319
417
|
else
|
|
320
418
|
event.ignore()
|
|
@@ -327,7 +425,7 @@ module Cosmos
|
|
|
327
425
|
# Start thread to read server messages
|
|
328
426
|
@output_thread = Thread.new do
|
|
329
427
|
begin
|
|
330
|
-
while !@
|
|
428
|
+
while !@ready
|
|
331
429
|
sleep(1)
|
|
332
430
|
end
|
|
333
431
|
while true
|
|
@@ -347,10 +445,10 @@ module Cosmos
|
|
|
347
445
|
def handle_string_output
|
|
348
446
|
if @string_output.string[-1..-1] == "\n"
|
|
349
447
|
Qt.execute_in_main_thread(true) do
|
|
350
|
-
lines_to_write =
|
|
448
|
+
lines_to_write = []
|
|
351
449
|
string = @string_output.string.clone
|
|
352
450
|
@string_output.string = @string_output.string[string.length..-1]
|
|
353
|
-
string.each_line {|out_line| @output.add_formatted_text(out_line)
|
|
451
|
+
string.each_line {|out_line| lines_to_write << out_line; @output.add_formatted_text(out_line) }
|
|
354
452
|
@output.flush
|
|
355
453
|
if @first_output < 2
|
|
356
454
|
# Scroll to the bottom on the first two outputs for Linux
|
|
@@ -358,7 +456,9 @@ module Cosmos
|
|
|
358
456
|
@output.verticalScrollBar.value = @output.verticalScrollBar.maximum
|
|
359
457
|
@first_output += 1
|
|
360
458
|
end
|
|
361
|
-
|
|
459
|
+
clean_lines, messages = CmdTlmServerGui.process_output_colors(lines_to_write)
|
|
460
|
+
@message_log.write(clean_lines) if @message_log
|
|
461
|
+
messages.each {|msg| CmdTlmServer.instance.post_server_message(msg) }
|
|
362
462
|
end
|
|
363
463
|
end
|
|
364
464
|
end
|
|
@@ -366,11 +466,13 @@ module Cosmos
|
|
|
366
466
|
# CmdTlmServer stop callback called by CmdTlmServer.stop. Ensures all the
|
|
367
467
|
# output is written to the message logs.
|
|
368
468
|
def stop_callback
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
469
|
+
Qt.execute_in_main_thread(true) do
|
|
470
|
+
handle_string_output()
|
|
471
|
+
@output_sleeper.cancel
|
|
472
|
+
Qt::CoreApplication.processEvents()
|
|
473
|
+
Cosmos.kill_thread(self, @output_thread)
|
|
474
|
+
handle_string_output()
|
|
475
|
+
end
|
|
374
476
|
end
|
|
375
477
|
|
|
376
478
|
def graceful_kill
|
|
@@ -383,12 +485,14 @@ module Cosmos
|
|
|
383
485
|
|
|
384
486
|
def self.no_gui_handle_string_output
|
|
385
487
|
if @string_output.string[-1..-1] == "\n"
|
|
386
|
-
lines_to_write =
|
|
488
|
+
lines_to_write = []
|
|
387
489
|
string = @string_output.string.clone
|
|
388
490
|
@string_output.string = @string_output.string[string.length..-1]
|
|
389
491
|
string.each_line {|out_line| lines_to_write << out_line }
|
|
390
|
-
|
|
391
|
-
|
|
492
|
+
clean_lines, messages = CmdTlmServerGui.process_output_colors(lines_to_write)
|
|
493
|
+
@message_log.write(clean_lines) if @mode == :CMD_TLM_SERVER
|
|
494
|
+
messages.each {|msg| CmdTlmServer.instance.post_server_message(msg) }
|
|
495
|
+
STDOUT.print clean_lines if STDIN.isatty # Have a console
|
|
392
496
|
end
|
|
393
497
|
end
|
|
394
498
|
|
|
@@ -399,7 +503,47 @@ module Cosmos
|
|
|
399
503
|
no_gui_handle_string_output()
|
|
400
504
|
end
|
|
401
505
|
|
|
506
|
+
def self.no_gui_reload_callback(confirm = false)
|
|
507
|
+
CmdTlmServer.instance.stop_logging('ALL') if @mode == :CMD_TLM_SERVER
|
|
508
|
+
CmdTlmServer.instance.stop_callback = nil
|
|
509
|
+
CmdTlmServer.instance.stop
|
|
510
|
+
System.reset
|
|
511
|
+
cts = CmdTlmServer.new(@options.config_file, @options.production, false, @mode)
|
|
512
|
+
|
|
513
|
+
# Signal catching needs to be repeated here because Puma interferes
|
|
514
|
+
["TERM", "INT"].each {|sig| Signal.trap(sig) {exit}}
|
|
515
|
+
|
|
516
|
+
@message_log = CmdTlmServer.message_log
|
|
517
|
+
cts.stop_callback = method(:no_gui_stop_callback)
|
|
518
|
+
cts.reload_callback = method(:no_gui_reload_callback)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def self.process_output_colors(lines)
|
|
522
|
+
clean_lines = ''
|
|
523
|
+
messages = []
|
|
524
|
+
lines.each do |line|
|
|
525
|
+
if line =~ /<G>/
|
|
526
|
+
line.gsub!(/<G>/, BLANK)
|
|
527
|
+
messages << [line.strip, 'GREEN']
|
|
528
|
+
elsif line =~ /<Y>/
|
|
529
|
+
line.gsub!(/<Y>/, BLANK)
|
|
530
|
+
messages << [line.strip, 'YELLOW']
|
|
531
|
+
elsif line =~ /<R>/
|
|
532
|
+
line.gsub!(/<R>/, BLANK)
|
|
533
|
+
messages << [line.strip, 'RED']
|
|
534
|
+
elsif line =~ /<B>/
|
|
535
|
+
line.gsub!(/<B>/, BLANK)
|
|
536
|
+
messages << [line.strip, 'BLUE']
|
|
537
|
+
else
|
|
538
|
+
messages << [line.strip, 'BLACK']
|
|
539
|
+
end
|
|
540
|
+
clean_lines << line
|
|
541
|
+
end
|
|
542
|
+
return [clean_lines, messages]
|
|
543
|
+
end
|
|
544
|
+
|
|
402
545
|
def self.post_options_parsed_hook(options)
|
|
546
|
+
@options = options
|
|
403
547
|
if options.no_gui
|
|
404
548
|
["TERM", "INT"].each {|sig| Signal.trap(sig) {exit}}
|
|
405
549
|
|
|
@@ -408,8 +552,18 @@ module Cosmos
|
|
|
408
552
|
@string_output = StringIO.new("", "r+")
|
|
409
553
|
$stdout = @string_output
|
|
410
554
|
Logger.level = Logger::INFO
|
|
411
|
-
|
|
555
|
+
if options.replay
|
|
556
|
+
@mode = :REPLAY
|
|
557
|
+
else
|
|
558
|
+
@mode = :CMD_TLM_SERVER
|
|
559
|
+
end
|
|
560
|
+
cts = CmdTlmServer.new(options.config_file, options.production, false, @mode)
|
|
561
|
+
|
|
562
|
+
# Signal catching needs to be repeated here because Puma interferes
|
|
563
|
+
["TERM", "INT"].each {|sig| Signal.trap(sig) {exit}}
|
|
564
|
+
|
|
412
565
|
@message_log = CmdTlmServer.message_log
|
|
566
|
+
@ready = true
|
|
413
567
|
@output_thread = Thread.new do
|
|
414
568
|
while true
|
|
415
569
|
no_gui_handle_string_output()
|
|
@@ -417,29 +571,34 @@ module Cosmos
|
|
|
417
571
|
end
|
|
418
572
|
end
|
|
419
573
|
cts.stop_callback = method(:no_gui_stop_callback)
|
|
574
|
+
cts.reload_callback = method(:no_gui_reload_callback)
|
|
420
575
|
sleep # Sleep until waked by signal
|
|
421
576
|
ensure
|
|
422
|
-
if
|
|
423
|
-
|
|
424
|
-
|
|
577
|
+
if CmdTlmServer.instance
|
|
578
|
+
CmdTlmServer.instance.stop_logging('ALL') if @mode == :CMD_TLM_SERVER
|
|
579
|
+
CmdTlmServer.instance.stop
|
|
425
580
|
end
|
|
426
581
|
end
|
|
427
582
|
return false
|
|
428
583
|
else
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
584
|
+
CmdTlmServerGui.configure_signal_handlers()
|
|
585
|
+
return true
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
def self.configure_signal_handlers
|
|
590
|
+
["TERM", "INT"].each do |sig|
|
|
591
|
+
Signal.trap(sig) do
|
|
592
|
+
# No synchronization is allowed in trap context, so we have
|
|
593
|
+
# to spawn a thread here to send the close event.
|
|
594
|
+
Thread.new do
|
|
595
|
+
Qt.execute_in_main_thread(true) do
|
|
596
|
+
@@window.no_prompt = true
|
|
597
|
+
@@window.closeEvent(Qt::CloseEvent.new())
|
|
598
|
+
exit
|
|
439
599
|
end
|
|
440
600
|
end
|
|
441
601
|
end
|
|
442
|
-
return true
|
|
443
602
|
end
|
|
444
603
|
end
|
|
445
604
|
|
|
@@ -457,6 +616,13 @@ module Cosmos
|
|
|
457
616
|
options.production = false
|
|
458
617
|
options.no_prompt = false
|
|
459
618
|
options.no_gui = false
|
|
619
|
+
if self.name == "Cosmos::Replay"
|
|
620
|
+
options.replay = true
|
|
621
|
+
options.title = "Replay"
|
|
622
|
+
else
|
|
623
|
+
options.replay = false
|
|
624
|
+
end
|
|
625
|
+
|
|
460
626
|
option_parser.separator "CTS Specific Options:"
|
|
461
627
|
option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
|
|
462
628
|
options.config_file = arg
|