cosmos 4.0.3 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +14 -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
@@ -19,7 +19,7 @@ module Cosmos
|
|
19
19
|
#
|
20
20
|
# This should not be confused with the Api module which implements the JSON
|
21
21
|
# API that is used by tools when accessing the Server. The Api module always
|
22
|
-
# provides Ruby primatives where the
|
22
|
+
# provides Ruby primatives where the PacketConfig class can return actual
|
23
23
|
# Packet or PacketItem objects. While there are some overlapping methods between
|
24
24
|
# the two, these are separate interfaces into the system.
|
25
25
|
class Commands
|
@@ -198,7 +198,7 @@ module Cosmos
|
|
198
198
|
# to re-sort. We also re-sort if the current item is less than the less
|
199
199
|
# item because we are inserting.
|
200
200
|
if last_item.bit_offset <= 0 or item.bit_offset <= 0 or item.bit_offset < last_item.bit_offset
|
201
|
-
@sorted_items = @sorted_items.sort
|
201
|
+
@sorted_items = @sorted_items.sort
|
202
202
|
end
|
203
203
|
else
|
204
204
|
@sorted_items << item
|
@@ -17,6 +17,8 @@ module Cosmos
|
|
17
17
|
class StructureItem
|
18
18
|
include Comparable
|
19
19
|
|
20
|
+
@@create_index = 0
|
21
|
+
|
20
22
|
# Valid data types adds :DERIVED to those defined by BinaryAccessor
|
21
23
|
DATA_TYPES = BinaryAccessor::DATA_TYPES << :DERIVED
|
22
24
|
|
@@ -81,6 +83,8 @@ module Cosmos
|
|
81
83
|
self.bit_size = bit_size
|
82
84
|
self.array_size = array_size
|
83
85
|
self.overflow = overflow
|
86
|
+
@create_index = @@create_index
|
87
|
+
@@create_index += 1
|
84
88
|
@structure_item_constructed = true
|
85
89
|
verify_overall()
|
86
90
|
end
|
@@ -190,6 +194,10 @@ module Cosmos
|
|
190
194
|
verify_overall() if @structure_item_constructed
|
191
195
|
end
|
192
196
|
|
197
|
+
def create_index
|
198
|
+
@create_index.to_i
|
199
|
+
end
|
200
|
+
|
193
201
|
if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
|
194
202
|
# Comparison Operator based on bit_offset. This means that StructureItems
|
195
203
|
# with different names or bit sizes are equal if they have the same bit
|
@@ -202,9 +210,17 @@ module Cosmos
|
|
202
210
|
if (@bit_offset == 0) && (other_bit_offset == 0)
|
203
211
|
# Both bit_offsets are 0 so sort by bit_size
|
204
212
|
# This allows derived items with bit_size of 0 to be listed first
|
205
|
-
# Compare based on bit size
|
213
|
+
# Compare based on bit size then create index
|
206
214
|
if @bit_size == other_bit_size
|
207
|
-
|
215
|
+
if @create_index
|
216
|
+
if @create_index <= other_item.create_index
|
217
|
+
return -1
|
218
|
+
else
|
219
|
+
return 1
|
220
|
+
end
|
221
|
+
else
|
222
|
+
return 0
|
223
|
+
end
|
208
224
|
elsif @bit_size < other_bit_size
|
209
225
|
return -1
|
210
226
|
else
|
@@ -216,8 +232,16 @@ module Cosmos
|
|
216
232
|
if ((@bit_offset >= 0) && (other_bit_offset >= 0)) || ((@bit_offset < 0) && (other_bit_offset < 0))
|
217
233
|
# Both Have Same Sign
|
218
234
|
if @bit_offset == other_bit_offset
|
219
|
-
|
220
|
-
|
235
|
+
if @create_index
|
236
|
+
if @create_index <= other_item.create_index
|
237
|
+
return -1
|
238
|
+
else
|
239
|
+
return 1
|
240
|
+
end
|
241
|
+
else
|
242
|
+
return 0
|
243
|
+
end
|
244
|
+
elsif @bit_offset <= other_bit_offset
|
221
245
|
return -1
|
222
246
|
else
|
223
247
|
return 1
|
@@ -225,7 +249,15 @@ module Cosmos
|
|
225
249
|
else
|
226
250
|
# Different Signs
|
227
251
|
if @bit_offset == other_bit_offset
|
228
|
-
|
252
|
+
if @create_index
|
253
|
+
if @create_index < other_item.create_index
|
254
|
+
return -1
|
255
|
+
else
|
256
|
+
return 1
|
257
|
+
end
|
258
|
+
else
|
259
|
+
return 0
|
260
|
+
end
|
229
261
|
elsif @bit_offset < other_bit_offset
|
230
262
|
return 1
|
231
263
|
else
|
@@ -57,14 +57,42 @@ module Cosmos
|
|
57
57
|
return $cmd_tlm_server.get_target_info(target_name)
|
58
58
|
end
|
59
59
|
|
60
|
+
def get_all_target_info
|
61
|
+
return $cmd_tlm_server.get_all_target_info
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_target_ignored_parameters(target_name)
|
65
|
+
return $cmd_tlm_server.get_target_ignored_parameters(target_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_target_ignored_items(target_name)
|
69
|
+
return $cmd_tlm_server.get_target_ignored_items(target_name)
|
70
|
+
end
|
71
|
+
|
60
72
|
def get_interface_info(interface_name)
|
61
73
|
return $cmd_tlm_server.get_interface_info(interface_name)
|
62
74
|
end
|
63
75
|
|
76
|
+
def get_all_router_info
|
77
|
+
return $cmd_tlm_server.get_all_router_info
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_all_interface_info
|
81
|
+
return $cmd_tlm_server.get_all_interface_info
|
82
|
+
end
|
83
|
+
|
64
84
|
def get_router_info(router_name)
|
65
85
|
return $cmd_tlm_server.get_router_info(router_name)
|
66
86
|
end
|
67
87
|
|
88
|
+
def get_all_cmd_info
|
89
|
+
return $cmd_tlm_server.get_all_cmd_info
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_all_tlm_info
|
93
|
+
return $cmd_tlm_server.get_all_tlm_info
|
94
|
+
end
|
95
|
+
|
68
96
|
def get_cmd_cnt(target_name, command_name)
|
69
97
|
return $cmd_tlm_server.get_cmd_cnt(target_name, command_name)
|
70
98
|
end
|
@@ -73,10 +101,34 @@ module Cosmos
|
|
73
101
|
return $cmd_tlm_server.get_tlm_cnt(target_name, packet_name)
|
74
102
|
end
|
75
103
|
|
104
|
+
def get_packet_loggers
|
105
|
+
return $cmd_tlm_server.get_packet_loggers
|
106
|
+
end
|
107
|
+
|
76
108
|
def get_packet_logger_info(packet_logger_name)
|
77
109
|
return $cmd_tlm_server.get_packet_logger_info(packet_logger_name)
|
78
110
|
end
|
79
111
|
|
112
|
+
def get_all_packet_logger_info
|
113
|
+
return $cmd_tlm_server.get_all_packet_logger_info
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_background_tasks
|
117
|
+
return $cmd_tlm_server.get_background_tasks
|
118
|
+
end
|
119
|
+
|
120
|
+
def start_background_task(task_name)
|
121
|
+
return $cmd_tlm_server.start_background_task(task_name)
|
122
|
+
end
|
123
|
+
|
124
|
+
def stop_background_task(task_name)
|
125
|
+
return $cmd_tlm_server.stop_background_task(task_name)
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_server_status
|
129
|
+
return $cmd_tlm_server.get_server_status
|
130
|
+
end
|
131
|
+
|
80
132
|
def get_cmd_log_filename(packet_log_writer_name = 'DEFAULT')
|
81
133
|
return $cmd_tlm_server.get_cmd_log_filename(packet_log_writer_name)
|
82
134
|
end
|
@@ -133,6 +185,28 @@ module Cosmos
|
|
133
185
|
return $cmd_tlm_server.start_new_server_message_log
|
134
186
|
end
|
135
187
|
|
136
|
-
|
188
|
+
def subscribe_server_messages(queue_size = CmdTlmServer::DEFAULT_SERVER_MESSAGES_QUEUE_SIZE)
|
189
|
+
return $cmd_tlm_server.subscribe_server_messages(queue_size)
|
190
|
+
end
|
191
|
+
|
192
|
+
def unsubscribe_server_messages(id)
|
193
|
+
return $cmd_tlm_server.unsubscribe_server_messages(id)
|
194
|
+
end
|
195
|
+
|
196
|
+
def get_server_message(id, non_block = false)
|
197
|
+
return $cmd_tlm_server.get_server_message(id, non_block)
|
198
|
+
end
|
199
|
+
|
200
|
+
def cmd_tlm_reload
|
201
|
+
return $cmd_tlm_server.cmd_tlm_reload
|
202
|
+
end
|
203
|
+
|
204
|
+
def cmd_tlm_clear_counters
|
205
|
+
return $cmd_tlm_server.cmd_tlm_clear_counters
|
206
|
+
end
|
137
207
|
|
138
|
-
|
208
|
+
def get_output_logs_filenames(filter = '*tlm.bin')
|
209
|
+
return $cmd_tlm_server.get_output_logs_filenames(filter)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2017 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
|
+
module Cosmos
|
12
|
+
|
13
|
+
module Script
|
14
|
+
private
|
15
|
+
|
16
|
+
def replay_select_file(filename, packet_log_reader = "DEFAULT")
|
17
|
+
$cmd_tlm_server.replay_select_file(filename, packet_log_reader)
|
18
|
+
end
|
19
|
+
|
20
|
+
def replay_status
|
21
|
+
$cmd_tlm_server.replay_status
|
22
|
+
end
|
23
|
+
|
24
|
+
def replay_set_playback_delay(delay)
|
25
|
+
$cmd_tlm_server.replay_set_playback_delay(delay)
|
26
|
+
end
|
27
|
+
|
28
|
+
def replay_play
|
29
|
+
$cmd_tlm_server.replay_play
|
30
|
+
end
|
31
|
+
|
32
|
+
def replay_reverse_play
|
33
|
+
$cmd_tlm_server.replay_reverse_play
|
34
|
+
end
|
35
|
+
|
36
|
+
def replay_stop
|
37
|
+
$cmd_tlm_server.replay_stop
|
38
|
+
end
|
39
|
+
|
40
|
+
def replay_step_forward
|
41
|
+
$cmd_tlm_server.replay_step_forward
|
42
|
+
end
|
43
|
+
|
44
|
+
def replay_step_back
|
45
|
+
$cmd_tlm_server.replay_step_back
|
46
|
+
end
|
47
|
+
|
48
|
+
def replay_move_start
|
49
|
+
$cmd_tlm_server.replay_move_start
|
50
|
+
end
|
51
|
+
|
52
|
+
def replay_move_end
|
53
|
+
$cmd_tlm_server.replay_move_end
|
54
|
+
end
|
55
|
+
|
56
|
+
def replay_move_index(index)
|
57
|
+
$cmd_tlm_server.replay_move_index(index)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/cosmos/script/script.rb
CHANGED
@@ -12,6 +12,7 @@ require 'cosmos'
|
|
12
12
|
require 'cosmos/io/json_drb_object'
|
13
13
|
require 'cosmos/tools/cmd_tlm_server/cmd_tlm_server'
|
14
14
|
require 'cosmos/script/cmd_tlm_server'
|
15
|
+
require 'cosmos/script/replay'
|
15
16
|
require 'cosmos/script/commands'
|
16
17
|
require 'cosmos/script/telemetry'
|
17
18
|
require 'cosmos/script/limits'
|
@@ -20,6 +21,7 @@ require 'cosmos/script/tools'
|
|
20
21
|
|
21
22
|
$cmd_tlm_server = nil
|
22
23
|
$cmd_tlm_disconnect = false
|
24
|
+
$cmd_tlm_replay_mode = false
|
23
25
|
|
24
26
|
module Cosmos
|
25
27
|
class CheckError < RuntimeError; end
|
@@ -39,6 +41,7 @@ module Cosmos
|
|
39
41
|
# Called when this module is mixed in using "include Cosmos::Script"
|
40
42
|
def self.included(base)
|
41
43
|
$cmd_tlm_disconnect = false
|
44
|
+
$cmd_tlm_replay_mode = false
|
42
45
|
$cmd_tlm_server = nil
|
43
46
|
initialize_script_module()
|
44
47
|
end
|
@@ -48,8 +51,12 @@ module Cosmos
|
|
48
51
|
# Start up a standalone CTS in disconnected mode
|
49
52
|
$cmd_tlm_server = CmdTlmServer.new(config_file, false, true)
|
50
53
|
else
|
51
|
-
# Start a Json connect to the real
|
52
|
-
$
|
54
|
+
# Start a Json connect to the real server
|
55
|
+
if $cmd_tlm_replay_mode
|
56
|
+
$cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['REPLAY_API'], System.ports['REPLAY_API'])
|
57
|
+
else
|
58
|
+
$cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['CTS_API'], System.ports['CTS_API'])
|
59
|
+
end
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
@@ -72,5 +79,16 @@ module Cosmos
|
|
72
79
|
$cmd_tlm_server.disconnect if $cmd_tlm_server && !$cmd_tlm_disconnect
|
73
80
|
end
|
74
81
|
|
82
|
+
def set_replay_mode(replay_mode)
|
83
|
+
if replay_mode != $cmd_tlm_replay_mode
|
84
|
+
$cmd_tlm_replay_mode = replay_mode
|
85
|
+
initialize_script_module()
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_replay_mode
|
90
|
+
$cmd_tlm_replay_mode
|
91
|
+
end
|
92
|
+
|
75
93
|
end
|
76
94
|
end
|
@@ -72,9 +72,9 @@ module Cosmos
|
|
72
72
|
prompt_combo_box(string, options)
|
73
73
|
end
|
74
74
|
|
75
|
-
def _file_dialog(message, directory, select_files = true)
|
75
|
+
def _file_dialog(message, directory, filter, select_files = true)
|
76
76
|
answer = ''
|
77
|
-
files = Dir["#{directory}
|
77
|
+
files = Dir["#{directory}/#{filter}"]
|
78
78
|
if select_files
|
79
79
|
files.select! {|f| !File.directory? f }
|
80
80
|
else
|
@@ -87,17 +87,17 @@ module Cosmos
|
|
87
87
|
end
|
88
88
|
return answer
|
89
89
|
end
|
90
|
-
def save_file_dialog(directory = Cosmos::USERPATH, message = "Save File")
|
91
|
-
_file_dialog(message, directory)
|
90
|
+
def save_file_dialog(directory = Cosmos::USERPATH, message = "Save File", filter = "*")
|
91
|
+
_file_dialog(message, directory, filter)
|
92
92
|
end
|
93
|
-
def open_file_dialog(directory = Cosmos::USERPATH, message = "Open File")
|
94
|
-
_file_dialog(message, directory)
|
93
|
+
def open_file_dialog(directory = Cosmos::USERPATH, message = "Open File", filter = "*")
|
94
|
+
_file_dialog(message, directory, filter)
|
95
95
|
end
|
96
|
-
def open_files_dialog(directory = Cosmos::USERPATH, message = "Open File(s)")
|
97
|
-
_file_dialog(message, directory)
|
96
|
+
def open_files_dialog(directory = Cosmos::USERPATH, message = "Open File(s)", filter = "*")
|
97
|
+
_file_dialog(message, directory, filter)
|
98
98
|
end
|
99
99
|
def open_directory_dialog(directory = Cosmos::USERPATH, message = "Open Directory")
|
100
|
-
_file_dialog(message, directory, false)
|
100
|
+
_file_dialog(message, directory, "*", false)
|
101
101
|
end
|
102
102
|
|
103
103
|
def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
|
data/lib/cosmos/script/tools.rb
CHANGED
@@ -92,6 +92,20 @@ module Cosmos
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
+
###########################
|
96
|
+
# Telemetry Screen methods
|
97
|
+
###########################
|
98
|
+
|
99
|
+
# Get the organized list of available telemetry screens
|
100
|
+
def get_screen_list(config_filename = nil, force_refresh = false)
|
101
|
+
$cmd_tlm_server.get_screen_list(config_filename, force_refresh)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get a specific screen definition
|
105
|
+
def get_screen_definition(screen_full_name, config_filename = nil, force_refresh = false)
|
106
|
+
$cmd_tlm_server.get_screen_definition(screen_full_name, config_filename, force_refresh)
|
107
|
+
end
|
108
|
+
|
95
109
|
end # module Script
|
96
110
|
|
97
111
|
end # module Cosmos
|
data/lib/cosmos/system/system.rb
CHANGED
@@ -17,6 +17,8 @@ require 'cosmos/system/target'
|
|
17
17
|
require 'cosmos/packet_logs'
|
18
18
|
require 'fileutils'
|
19
19
|
require 'drb/acl'
|
20
|
+
require 'zip'
|
21
|
+
require 'zip/filesystem'
|
20
22
|
require 'bundler'
|
21
23
|
|
22
24
|
module Cosmos
|
@@ -52,7 +54,7 @@ module Cosmos
|
|
52
54
|
# @return [String] Stores the initial configuration file used when this
|
53
55
|
# System was initialized
|
54
56
|
instance_attr_reader :initial_filename
|
55
|
-
# @return [
|
57
|
+
# @return [PacketConfig] Stores the initial packet list used when this
|
56
58
|
# System was initialized
|
57
59
|
instance_attr_reader :initial_config
|
58
60
|
# @return [ACL] Access control list showing which machines can have access
|
@@ -71,9 +73,9 @@ module Cosmos
|
|
71
73
|
instance_attr_reader :additional_md5_files
|
72
74
|
|
73
75
|
# Known COSMOS ports
|
74
|
-
KNOWN_PORTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER']
|
76
|
+
KNOWN_PORTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER']
|
75
77
|
# Known COSMOS hosts
|
76
|
-
KNOWN_HOSTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER']
|
78
|
+
KNOWN_HOSTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER']
|
77
79
|
# Known COSMOS paths
|
78
80
|
KNOWN_PATHS = ['LOGS', 'TMP', 'SAVED_CONFIG', 'TABLES', 'HANDBOOKS', 'PROCEDURES', 'SEQUENCES']
|
79
81
|
|
@@ -88,69 +90,7 @@ module Cosmos
|
|
88
90
|
# read. Be default this is <Cosmos::USERPATH>/config/system/system.txt
|
89
91
|
def initialize(filename = nil)
|
90
92
|
raise "Cosmos::System created twice" unless @@instance.nil?
|
91
|
-
|
92
|
-
@targets['UNKNOWN'] = Target.new('UNKNOWN')
|
93
|
-
@config = nil
|
94
|
-
@commands = nil
|
95
|
-
@telemetry = nil
|
96
|
-
@limits = nil
|
97
|
-
@default_packet_log_writer = PacketLogWriter
|
98
|
-
@default_packet_log_writer_params = []
|
99
|
-
@default_packet_log_reader = PacketLogReader
|
100
|
-
@default_packet_log_reader_params = []
|
101
|
-
@sound = false
|
102
|
-
@use_dns = false
|
103
|
-
@acl = nil
|
104
|
-
@staleness_seconds = 30
|
105
|
-
@limits_set = :DEFAULT
|
106
|
-
@use_utc = false
|
107
|
-
@additional_md5_files = []
|
108
|
-
@meta_init_filename = nil
|
109
|
-
|
110
|
-
@ports = {}
|
111
|
-
@ports['CTS_API'] = 7777
|
112
|
-
@ports['TLMVIEWER_API'] = 7778
|
113
|
-
@ports['CTS_PREIDENTIFIED'] = 7779
|
114
|
-
@ports['CTS_CMD_ROUTER'] = 7780
|
115
|
-
|
116
|
-
@listen_hosts = {}
|
117
|
-
@listen_hosts['CTS_API'] = '127.0.0.1'
|
118
|
-
@listen_hosts['TLMVIEWER_API'] = '127.0.0.1'
|
119
|
-
# Localhost would be more secure but historically these are open to allow for chaining servers by default
|
120
|
-
@listen_hosts['CTS_PREIDENTIFIED'] = '0.0.0.0'
|
121
|
-
@listen_hosts['CTS_CMD_ROUTER'] = '0.0.0.0'
|
122
|
-
|
123
|
-
@connect_hosts = {}
|
124
|
-
@connect_hosts['CTS_API'] = '127.0.0.1'
|
125
|
-
@connect_hosts['TLMVIEWER_API'] = '127.0.0.1'
|
126
|
-
@connect_hosts['CTS_PREIDENTIFIED'] = '127.0.0.1'
|
127
|
-
@connect_hosts['CTS_CMD_ROUTER'] = '127.0.0.1'
|
128
|
-
|
129
|
-
@paths = {}
|
130
|
-
@paths['LOGS'] = File.join(USERPATH, 'outputs', 'logs')
|
131
|
-
@paths['TMP'] = File.join(USERPATH, 'outputs', 'tmp')
|
132
|
-
@paths['SAVED_CONFIG'] = File.join(USERPATH, 'outputs', 'saved_config')
|
133
|
-
@paths['TABLES'] = File.join(USERPATH, 'outputs', 'tables')
|
134
|
-
@paths['HANDBOOKS'] = File.join(USERPATH, 'outputs', 'handbooks')
|
135
|
-
@paths['PROCEDURES'] = [File.join(USERPATH, 'procedures')]
|
136
|
-
@paths['SEQUENCES'] = File.join(USERPATH, 'outputs', 'sequences')
|
137
|
-
|
138
|
-
unless filename
|
139
|
-
system_arg = false
|
140
|
-
ARGV.each do |arg|
|
141
|
-
if system_arg
|
142
|
-
filename = File.join(USERPATH, 'config', 'system', arg)
|
143
|
-
break
|
144
|
-
end
|
145
|
-
system_arg = true if arg == '--system'
|
146
|
-
end
|
147
|
-
filename = File.join(USERPATH, 'config', 'system', 'system.txt') unless filename
|
148
|
-
end
|
149
|
-
process_file(filename)
|
150
|
-
ENV['COSMOS_LOGS_DIR'] = @paths['LOGS']
|
151
|
-
|
152
|
-
@initial_filename = filename
|
153
|
-
@initial_config = nil
|
93
|
+
reset_variables(filename)
|
154
94
|
@@instance = self
|
155
95
|
end
|
156
96
|
|
@@ -489,6 +429,8 @@ module Cosmos
|
|
489
429
|
end # parser.parse_file
|
490
430
|
end
|
491
431
|
|
432
|
+
|
433
|
+
|
492
434
|
# Load the specified configuration by iterating through the SAVED_CONFIG
|
493
435
|
# directory looking for a matching MD5 sum. Updates the internal state so
|
494
436
|
# subsequent commands and telemetry methods return the new configuration.
|
@@ -507,12 +449,16 @@ module Cosmos
|
|
507
449
|
update_config(@initial_config)
|
508
450
|
else
|
509
451
|
# Look for the requested configuration in the saved configurations
|
510
|
-
|
511
|
-
if
|
452
|
+
configuration = find_configuration(name)
|
453
|
+
if configuration
|
512
454
|
# We found the configuration requested. Reprocess the system.txt
|
513
455
|
# and reload the packets
|
514
456
|
begin
|
515
|
-
|
457
|
+
unless File.directory?(configuration)
|
458
|
+
# Zip file configuration so unzip and reset configuration path
|
459
|
+
configuration = unzip(configuration)
|
460
|
+
end
|
461
|
+
process_file(File.join(configuration, 'system.txt'), configuration)
|
516
462
|
load_packets(name)
|
517
463
|
rescue Exception => error
|
518
464
|
# Failed to load - Restore initial
|
@@ -539,8 +485,145 @@ module Cosmos
|
|
539
485
|
return self.instance.load_configuration(name)
|
540
486
|
end
|
541
487
|
|
488
|
+
# Resets the System's internal state to defaults.
|
489
|
+
#
|
490
|
+
# @params [String] Path to system.txt config file to process. Defaults to config/system/system.txt
|
491
|
+
def reset_variables(filename = nil)
|
492
|
+
@targets = {}
|
493
|
+
@targets['UNKNOWN'] = Target.new('UNKNOWN')
|
494
|
+
@config = nil
|
495
|
+
@commands = nil
|
496
|
+
@telemetry = nil
|
497
|
+
@limits = nil
|
498
|
+
@default_packet_log_writer = PacketLogWriter
|
499
|
+
@default_packet_log_writer_params = []
|
500
|
+
@default_packet_log_reader = PacketLogReader
|
501
|
+
@default_packet_log_reader_params = []
|
502
|
+
@sound = false
|
503
|
+
@use_dns = false
|
504
|
+
@acl = nil
|
505
|
+
@staleness_seconds = 30
|
506
|
+
@limits_set = :DEFAULT
|
507
|
+
@use_utc = false
|
508
|
+
@additional_md5_files = []
|
509
|
+
@meta_init_filename = nil
|
510
|
+
|
511
|
+
@ports = {}
|
512
|
+
@ports['CTS_API'] = 7777
|
513
|
+
@ports['TLMVIEWER_API'] = 7778
|
514
|
+
@ports['CTS_PREIDENTIFIED'] = 7779
|
515
|
+
@ports['CTS_CMD_ROUTER'] = 7780
|
516
|
+
@ports['REPLAY_API'] = 7877
|
517
|
+
@ports['REPLAY_PREIDENTIFIED'] = 7879
|
518
|
+
@ports['REPLAY_CMD_ROUTER'] = 7880
|
519
|
+
|
520
|
+
@listen_hosts = {}
|
521
|
+
@listen_hosts['CTS_API'] = '127.0.0.1'
|
522
|
+
@listen_hosts['TLMVIEWER_API'] = '127.0.0.1'
|
523
|
+
# Localhost would be more secure but historically these are open to allow for chaining servers by default
|
524
|
+
@listen_hosts['CTS_PREIDENTIFIED'] = '0.0.0.0'
|
525
|
+
@listen_hosts['CTS_CMD_ROUTER'] = '0.0.0.0'
|
526
|
+
@listen_hosts['REPLAY_API'] = '127.0.0.1'
|
527
|
+
# Localhost would be more secure but historically these are open to allow for chaining servers by default
|
528
|
+
@listen_hosts['REPLAY_PREIDENTIFIED'] = '0.0.0.0'
|
529
|
+
@listen_hosts['REPLAY_CMD_ROUTER'] = '0.0.0.0'
|
530
|
+
|
531
|
+
@connect_hosts = {}
|
532
|
+
@connect_hosts['CTS_API'] = '127.0.0.1'
|
533
|
+
@connect_hosts['TLMVIEWER_API'] = '127.0.0.1'
|
534
|
+
@connect_hosts['CTS_PREIDENTIFIED'] = '127.0.0.1'
|
535
|
+
@connect_hosts['CTS_CMD_ROUTER'] = '127.0.0.1'
|
536
|
+
@connect_hosts['REPLAY_API'] = '127.0.0.1'
|
537
|
+
@connect_hosts['REPLAY_PREIDENTIFIED'] = '127.0.0.1'
|
538
|
+
@connect_hosts['REPLAY_CMD_ROUTER'] = '127.0.0.1'
|
539
|
+
|
540
|
+
@paths = {}
|
541
|
+
@paths['LOGS'] = File.join(USERPATH, 'outputs', 'logs')
|
542
|
+
@paths['TMP'] = File.join(USERPATH, 'outputs', 'tmp')
|
543
|
+
@paths['SAVED_CONFIG'] = File.join(USERPATH, 'outputs', 'saved_config')
|
544
|
+
@paths['TABLES'] = File.join(USERPATH, 'outputs', 'tables')
|
545
|
+
@paths['HANDBOOKS'] = File.join(USERPATH, 'outputs', 'handbooks')
|
546
|
+
@paths['PROCEDURES'] = [File.join(USERPATH, 'procedures')]
|
547
|
+
@paths['SEQUENCES'] = File.join(USERPATH, 'outputs', 'sequences')
|
548
|
+
|
549
|
+
unless filename
|
550
|
+
system_arg = false
|
551
|
+
ARGV.each do |arg|
|
552
|
+
if system_arg
|
553
|
+
filename = File.join(USERPATH, 'config', 'system', arg)
|
554
|
+
break
|
555
|
+
end
|
556
|
+
system_arg = true if arg == '--system'
|
557
|
+
end
|
558
|
+
filename = File.join(USERPATH, 'config', 'system', 'system.txt') unless filename
|
559
|
+
end
|
560
|
+
process_file(filename)
|
561
|
+
ENV['COSMOS_LOGS_DIR'] = @paths['LOGS']
|
562
|
+
|
563
|
+
@initial_filename = filename
|
564
|
+
@initial_config = nil
|
565
|
+
end
|
566
|
+
|
567
|
+
# Reset variables and load packets
|
568
|
+
def reset(filename = nil)
|
569
|
+
reset_variables(filename)
|
570
|
+
load_packets()
|
571
|
+
end
|
572
|
+
|
573
|
+
# Class level convenience reset method
|
574
|
+
def self.reset
|
575
|
+
self.instance.reset
|
576
|
+
end
|
577
|
+
|
542
578
|
protected
|
543
579
|
|
580
|
+
def unzip(zip_file)
|
581
|
+
zip_dir = File.join(@paths['TMP'], File.basename(zip_file, ".*"))
|
582
|
+
# Only unzip if we have to. We assume the unzipped directory structure is
|
583
|
+
# intact. If not they'll get a popop with the errors encountered when
|
584
|
+
# loading the configuration.
|
585
|
+
unless File.exist? zip_dir
|
586
|
+
Zip::File.open(zip_file) do |zip_file|
|
587
|
+
zip_file.each do |entry|
|
588
|
+
path = File.join(@paths['TMP'], entry.name)
|
589
|
+
FileUtils.mkdir_p(File.dirname(path))
|
590
|
+
zip_file.extract(entry, path) unless File.exist?(path)
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
594
|
+
zip_dir
|
595
|
+
end
|
596
|
+
|
597
|
+
# A helper method to make the zip writing recursion work
|
598
|
+
def write_zip_entries(base_dir, entries, zip_path, io)
|
599
|
+
io.add(zip_path, base_dir) # Add the directory whether it has entries or not
|
600
|
+
entries.each do |e|
|
601
|
+
zip_file_path = File.join(zip_path, e)
|
602
|
+
disk_file_path = File.join(base_dir, e)
|
603
|
+
if File.directory? disk_file_path
|
604
|
+
recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
605
|
+
else
|
606
|
+
put_into_archive(disk_file_path, io, zip_file_path)
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
def recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
612
|
+
io.add(zip_file_path, disk_file_path)
|
613
|
+
entries = Dir.entries(disk_file_path) - %w(. ..)
|
614
|
+
write_zip_entries(disk_file_path, entries, zip_file_path, io)
|
615
|
+
end
|
616
|
+
|
617
|
+
def put_into_archive(disk_file_path, io, zip_file_path)
|
618
|
+
io.get_output_stream(zip_file_path) do |f|
|
619
|
+
data = nil
|
620
|
+
File.open(disk_file_path, 'rb') do |file|
|
621
|
+
data = file.read
|
622
|
+
end
|
623
|
+
f.write(data)
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
544
627
|
def auto_detect_gem_based_targets
|
545
628
|
Bundler.load.specs.each do |spec|
|
546
629
|
spec_name_split = spec.name.split('-')
|
@@ -577,7 +660,7 @@ module Cosmos
|
|
577
660
|
Cosmos.set_working_dir do
|
578
661
|
Dir.foreach(@paths['SAVED_CONFIG']) do |filename|
|
579
662
|
full_path = File.join(@paths['SAVED_CONFIG'], filename)
|
580
|
-
if
|
663
|
+
if File.exist?(full_path) && File.basename(filename, ".*")[-32..-1] == name
|
581
664
|
return full_path
|
582
665
|
end
|
583
666
|
end
|
@@ -587,35 +670,45 @@ module Cosmos
|
|
587
670
|
|
588
671
|
def save_configuration
|
589
672
|
Cosmos.set_working_dir do
|
590
|
-
|
591
|
-
|
592
|
-
unless
|
673
|
+
configuration = find_configuration(@config.name)
|
674
|
+
configuration = File.join(@paths['SAVED_CONFIG'], File.build_timestamped_filename([@config.name], '.zip')) unless configuration
|
675
|
+
unless File.exist?(configuration)
|
593
676
|
begin
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
@targets.each do |target_name, target|
|
599
|
-
destination_dir = File.join(configuration_directory, target.original_name)
|
600
|
-
unless Dir.exist?(destination_dir)
|
601
|
-
FileUtils.cp_r(target.dir, destination_dir)
|
602
|
-
end
|
603
|
-
end
|
677
|
+
Zip.continue_on_exists_proc = true
|
678
|
+
Zip::File.open(configuration, Zip::File::CREATE) do |zipfile|
|
679
|
+
zip_file_path = File.basename(configuration, ".zip")
|
680
|
+
zipfile.mkdir zip_file_path
|
604
681
|
|
605
|
-
|
606
|
-
|
682
|
+
# Copy target files into archive
|
683
|
+
zip_targets = []
|
607
684
|
@targets.each do |target_name, target|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
685
|
+
entries = Dir.entries(target.dir) - %w(. ..)
|
686
|
+
zip_target = File.join(zip_file_path, target.original_name)
|
687
|
+
# Check the stored list of targets. We can't ask the zip file
|
688
|
+
# itself because it's in progress and hasn't been saved
|
689
|
+
unless zip_targets.include?(zip_target)
|
690
|
+
write_zip_entries(target.dir, entries, zip_target, zipfile)
|
691
|
+
zip_targets << zip_target
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
# Create custom system.txt file
|
696
|
+
zipfile.get_output_stream(File.join(zip_file_path, 'system.txt')) do |file|
|
697
|
+
@targets.each do |target_name, target|
|
698
|
+
target_filename = File.basename(target.filename)
|
699
|
+
target_filename = nil unless File.exist?(target.filename)
|
700
|
+
# Create a newline character since Zip opens files in binary mode
|
701
|
+
newline = Kernel.is_windows? ? "\r\n" : "\n"
|
702
|
+
if target.substitute
|
703
|
+
file.write "DECLARE_TARGET #{target.original_name} #{target.name} #{target_filename}#{newline}"
|
704
|
+
else
|
705
|
+
file.write "DECLARE_TARGET #{target.name} nil #{target_filename}#{newline}"
|
706
|
+
end
|
614
707
|
end
|
615
708
|
end
|
616
709
|
end
|
617
710
|
rescue Exception => error
|
618
|
-
Logger.error "Problem saving configuration to #{
|
711
|
+
Logger.error "Problem saving configuration to #{configuration}: #{error.class}:#{error.message}\n#{error.backtrace.join("\n")}\n"
|
619
712
|
end
|
620
713
|
end
|
621
714
|
end
|