cosmos 3.1.2 → 3.2.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Manifest.txt +17 -1
  4. data/autohotkey/tools/test_runner2.ahk +1 -0
  5. data/autohotkey/tools/tlm_grapher.ahk +13 -1
  6. data/data/crc.txt +39 -30
  7. data/demo/config/data/crc.txt +3 -3
  8. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +3 -1
  9. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +7 -1
  10. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +6 -1
  11. data/lib/cosmos.rb +2 -2
  12. data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -5
  13. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +0 -7
  14. data/lib/cosmos/gui/line_graph/overview_graph.rb +12 -2
  15. data/lib/cosmos/gui/utilities/script_module_gui.rb +11 -3
  16. data/lib/cosmos/interfaces/interface.rb +12 -0
  17. data/lib/cosmos/interfaces/stream_interface.rb +1 -21
  18. data/lib/cosmos/interfaces/tcpip_server_interface.rb +10 -0
  19. data/lib/cosmos/io/json_drb_object.rb +75 -56
  20. data/lib/cosmos/io/tcpip_server.rb +1 -11
  21. data/lib/cosmos/packet_logs.rb +1 -0
  22. data/lib/cosmos/packet_logs/ccsds_log_reader.rb +103 -0
  23. data/lib/cosmos/packets/packet.rb +70 -1
  24. data/lib/cosmos/packets/packet_config.rb +59 -611
  25. data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -0
  26. data/lib/cosmos/packets/parsers/limits_parser.rb +146 -0
  27. data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -0
  28. data/lib/cosmos/packets/parsers/macro_parser.rb +116 -0
  29. data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -0
  30. data/lib/cosmos/packets/parsers/packet_parser.rb +123 -0
  31. data/lib/cosmos/packets/parsers/processor_parser.rb +63 -0
  32. data/lib/cosmos/packets/parsers/state_parser.rb +116 -0
  33. data/lib/cosmos/packets/structure.rb +59 -22
  34. data/lib/cosmos/packets/structure_item.rb +1 -1
  35. data/lib/cosmos/script/script.rb +4 -5
  36. data/lib/cosmos/streams/serial_stream.rb +5 -0
  37. data/lib/cosmos/streams/stream.rb +8 -2
  38. data/lib/cosmos/streams/stream_protocol.rb +1 -0
  39. data/lib/cosmos/streams/tcpip_client_stream.rb +37 -7
  40. data/lib/cosmos/streams/tcpip_socket_stream.rb +9 -6
  41. data/lib/cosmos/system/target.rb +3 -6
  42. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +57 -48
  43. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +7 -3
  44. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +1 -1
  45. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +7 -1
  46. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +1 -2
  47. data/lib/cosmos/top_level.rb +22 -11
  48. data/lib/cosmos/utilities/message_log.rb +14 -9
  49. data/lib/cosmos/version.rb +5 -5
  50. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +16 -16
  51. data/spec/interfaces/linc_interface_spec.rb +3 -0
  52. data/spec/interfaces/tcpip_client_interface_spec.rb +1 -0
  53. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -0
  54. data/spec/io/json_drb_object_spec.rb +1 -1
  55. data/spec/io/serial_driver_spec.rb +0 -1
  56. data/spec/packet_logs/packet_log_writer_spec.rb +5 -3
  57. data/spec/packets/packet_config_spec.rb +22 -837
  58. data/spec/packets/packet_item_spec.rb +10 -10
  59. data/spec/packets/packet_spec.rb +239 -1
  60. data/spec/packets/parsers/format_string_parser_spec.rb +122 -0
  61. data/spec/packets/parsers/limits_parser_spec.rb +282 -0
  62. data/spec/packets/parsers/limits_response_parser_spec.rb +149 -0
  63. data/spec/packets/parsers/macro_parser_spec.rb +184 -0
  64. data/spec/packets/parsers/packet_item_parser_spec.rb +306 -0
  65. data/spec/packets/parsers/packet_parser_spec.rb +99 -0
  66. data/spec/packets/parsers/processor_parser_spec.rb +114 -0
  67. data/spec/packets/parsers/state_parser_spec.rb +156 -0
  68. data/spec/packets/structure_item_spec.rb +14 -14
  69. data/spec/packets/structure_spec.rb +162 -16
  70. data/spec/streams/fixed_stream_protocol_spec.rb +7 -4
  71. data/spec/streams/length_stream_protocol_spec.rb +3 -0
  72. data/spec/streams/preidentified_stream_protocol_spec.rb +3 -0
  73. data/spec/streams/serial_stream_spec.rb +12 -0
  74. data/spec/streams/stream_protocol_spec.rb +14 -0
  75. data/spec/streams/stream_spec.rb +1 -0
  76. data/spec/streams/tcpip_client_stream_spec.rb +3 -0
  77. data/spec/streams/tcpip_socket_stream_spec.rb +15 -3
  78. data/spec/streams/template_stream_protocol_spec.rb +5 -0
  79. data/spec/streams/terminated_stream_protocol_spec.rb +4 -0
  80. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +21 -1
  81. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +1 -1
  82. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +1 -1
  83. metadata +19 -3
@@ -116,13 +116,6 @@ module Cosmos
116
116
  end
117
117
 
118
118
  def value_update_timeout
119
- # Check to see that the server is still running. If the user shut down
120
- # the underlying tool (like PacketViewer for example) the $cmd_tlm_server
121
- # will be nil.
122
- unless $cmd_tlm_server
123
- @timer.stop
124
- return
125
- end
126
119
  begin
127
120
  # Gather updated values
128
121
  values, limits_states, limits_settings, limits_set = get_tlm_values(@item_array, VALUE_TYPES)
@@ -111,12 +111,12 @@ module Cosmos
111
111
  temp_max = (@window_max_start + (x - @drag_start_x))
112
112
 
113
113
  # Only graph if the user hasn't dragged the window outside the graph
114
- if temp_min >= 0 and temp_max <= @graph_right_x
114
+ if temp_min >= @graph_left_x and temp_max <= @graph_right_x
115
115
  #Now convert the graph coordinates back to the x values
116
116
  @window_min_x = scale_graph_to_value_x(temp_min)
117
117
  @window_max_x = scale_graph_to_value_x(temp_max)
118
118
  else # The user dragged outside the allowable area
119
- if temp_min < 0
119
+ if temp_min < @graph_left_x
120
120
  @window_min_x = @x_min
121
121
  @window_max_x = @x_min + @window_size
122
122
  elsif temp_max > @graph_right_x
@@ -124,6 +124,8 @@ module Cosmos
124
124
  @window_min_x = @window_max_x - @window_size
125
125
  end
126
126
  end
127
+ @window_min_x = @x_min if @window_min_x < @x_min
128
+ @window_max_x = @x_max if @window_max_x > @x_max
127
129
  @redraw_needed = true
128
130
  graph()
129
131
  end
@@ -171,6 +173,8 @@ module Cosmos
171
173
  end
172
174
 
173
175
  # Update window size
176
+ @window_min_x = @x_min if @window_min_x < @x_min
177
+ @window_max_x = @x_max if @window_max_x > @x_max
174
178
  @window_size = @window_max_x - @window_min_x
175
179
 
176
180
  @redraw_needed = true
@@ -315,6 +319,8 @@ module Cosmos
315
319
  @window_min_x = center - @window_size / 2
316
320
  @window_max_x = center + @window_size / 2
317
321
  end
322
+ @window_min_x = @x_min if @window_min_x < @x_min
323
+ @window_max_x = @x_max if @window_max_x > @x_max
318
324
  @drag_window = true
319
325
  @redraw_needed = true
320
326
  graph()
@@ -346,6 +352,8 @@ module Cosmos
346
352
  @window_min_x = @x_max - @window_size
347
353
  @window_max_x = @x_max
348
354
  end
355
+ @window_min_x = @x_min if @window_min_x < @x_min
356
+ @window_max_x = @x_max if @window_max_x > @x_max
349
357
 
350
358
  @drag_window = true
351
359
  @redraw_needed = true
@@ -427,8 +435,10 @@ module Cosmos
427
435
  # The window lines are in terms of the graph x values so convert to the graph coordinate system
428
436
  @window_left_x = scale_value_to_graph_x(@window_min_x)
429
437
  @window_left_x = @graph_left_x if @window_left_x < @graph_left_x
438
+ @window_left_x = @graph_right_x if @window_left_x > @graph_right_x
430
439
  @window_right_x = scale_value_to_graph_x(@window_max_x)
431
440
  @window_right_x = @graph_right_x if @window_right_x > @graph_right_x
441
+ @window_right_x = @graph_left_x if @window_right_x < @graph_left_x
432
442
  else # If we're not dragging the window we want to adjust the window lines automatically
433
443
  @window_max_x = @x_max
434
444
 
@@ -21,7 +21,7 @@ module Cosmos
21
21
 
22
22
  @@qt_boolean = Qt::Boolean.new
23
23
 
24
- def ask_string(question, allow_blank = false)
24
+ def ask_string(question, allow_blank = false, password = false)
25
25
  answer = ""
26
26
  loop do
27
27
  canceled = false
@@ -29,7 +29,11 @@ module Cosmos
29
29
  window = nil
30
30
  window = get_cmd_tlm_gui_window() if get_cmd_tlm_gui_window()
31
31
  # Create a special mutable QT variable that can return what button was pressed
32
- answer = Qt::InputDialog::getText(window, "Ask", question, Qt::LineEdit::Normal, "", @@qt_boolean)
32
+ if password
33
+ answer = Qt::InputDialog::getText(window, "Ask", question, Qt::LineEdit::Password, "", @@qt_boolean)
34
+ else
35
+ answer = Qt::InputDialog::getText(window, "Ask", question, Qt::LineEdit::Normal, "", @@qt_boolean)
36
+ end
33
37
  # @@qt_boolean is nil if the user presses cancel in the dialog
34
38
  # Note that it is not actually nil, just the nil? method returns true
35
39
  canceled = @@qt_boolean.nil?
@@ -42,7 +46,11 @@ module Cosmos
42
46
  break if allow_blank or (not answer.nil? and answer.strip.length != 0)
43
47
  end
44
48
 
45
- Logger.info "User entered '#{answer}' for '#{question}'"
49
+ if password
50
+ Logger.info "User responded to '#{question}'"
51
+ else
52
+ Logger.info "User entered '#{answer}' for '#{question}'"
53
+ end
46
54
  return answer.to_s
47
55
  end
48
56
 
@@ -81,6 +81,9 @@ module Cosmos
81
81
  # (when used as a Router)
82
82
  attr_accessor :interfaces
83
83
 
84
+ # @return [Hash<option name, option values>] Hash of options supplied to interface/router
85
+ attr_accessor :options
86
+
84
87
  # Initialize default attribute values
85
88
  def initialize
86
89
  @name = self.class.to_s
@@ -104,6 +107,7 @@ module Cosmos
104
107
  @read_allowed = true
105
108
  @write_allowed = true
106
109
  @write_raw_allowed = true
110
+ @options = {}
107
111
  end
108
112
 
109
113
  # Connects the interface to its target(s). Must be implemented by a
@@ -198,6 +202,14 @@ module Cosmos
198
202
  # read_queue_size is the number of packets in the queue so don't copy
199
203
  # write_queue_size is the number of packets in the queue so don't copy
200
204
  other_interface.interfaces = self.interfaces.clone
205
+ other_interface.options = self.options.clone
206
+ end
207
+
208
+ # Set an interface or router specific option
209
+ # @param option_name name of the option
210
+ # @param option_values array of option values
211
+ def set_option(option_name, option_values)
212
+ @options[option_name.upcase] = option_values.clone
201
213
  end
202
214
 
203
215
  # This method is called by the CmdTlmServer after each read packet is
@@ -34,27 +34,7 @@ module Cosmos
34
34
  super()
35
35
 
36
36
  stream_protocol_class = stream_protocol_type.to_s.capitalize << 'StreamProtocol'
37
- klass = stream_protocol_class.to_class
38
- unless klass
39
- begin
40
- require stream_protocol_class.class_name_to_filename
41
- # If the stream protocol doesn't exist require will throw a LoadError
42
- rescue LoadError => err
43
- msg = "Unable to require " \
44
- "#{stream_protocol_class.class_name_to_filename} due to #{err.message}. " \
45
- "Ensure #{stream_protocol_class.class_name_to_filename} "\
46
- "is in the COSMOS lib directory."
47
- Logger.instance.error msg
48
- raise msg
49
- # If the stream protocol exists but has problems we rescue those here
50
- rescue => err
51
- msg = "Unable to require " \
52
- "#{stream_protocol_class.class_name_to_filename} due to #{err.message}."
53
- Logger.instance.error msg
54
- raise msg
55
- end
56
- end
57
-
37
+ klass = Cosmos.require_class(stream_protocol_class.class_name_to_filename)
58
38
  @stream_protocol = klass.new(*stream_protocol_args)
59
39
  @stream_protocol.interface = self
60
40
  end
@@ -149,6 +149,16 @@ module Cosmos
149
149
  @tcpip_server.stop_raw_logging
150
150
  end
151
151
 
152
+ # Supported Options
153
+ # LISTEN_ADDRESS - Ip address of the interface to accept connections on - Default: 0.0.0.0
154
+ # (see Interface#set_option)
155
+ def set_option(option_name, option_values)
156
+ super(option_name, option_values)
157
+ if option_name.upcase == 'LISTEN_ADDRESS'
158
+ @tcpip_server.listen_address = option_values[0]
159
+ end
160
+ end
161
+
152
162
  end # class TcpipServerInterface
153
163
 
154
164
  end # module Cosmos
@@ -33,7 +33,7 @@ module Cosmos
33
33
  # @param hostname [String] The name of the machine which has started
34
34
  # the JSON service
35
35
  # @param port [Integer] The port number of the JSON service
36
- def initialize(hostname, port)
36
+ def initialize(hostname, port, connect_timeout = 1.0)
37
37
  hostname = '127.0.0.1' if (hostname.to_s.upcase == 'LOCALHOST')
38
38
  begin
39
39
  @addr = Socket.pack_sockaddr_in(port, hostname)
@@ -50,11 +50,21 @@ module Cosmos
50
50
  @socket = nil
51
51
  @id = 0
52
52
  @request_in_progress = false
53
+ @connect_timeout = connect_timeout
54
+ @connect_timeout = @connect_timeout.to_f if @connect_timeout
55
+ @shutdown = false
53
56
  end
54
57
 
55
58
  # Disconnects from the JSON server
56
59
  def disconnect
57
- @socket.close if @socket and !@socket.closed?
60
+ socket = @socket
61
+ socket.close if socket and !socket.closed?
62
+ end
63
+
64
+ # Permanently disconnects from the JSON server
65
+ def shutdown
66
+ @shutdown = true
67
+ disconnect()
58
68
  end
59
69
 
60
70
  # Forwards all method calls to the remote service.
@@ -66,70 +76,79 @@ module Cosmos
66
76
  # protocol a DRb::DRbConnError exception is raised.
67
77
  def method_missing(method_name, *method_params)
68
78
  @mutex.synchronize do
69
- first_try = true
70
- loop do
71
- if !@socket or @socket.closed? or @request_in_progress
72
- if @request_in_progress
73
- @socket.close if @socket and !@socket.closed?
74
- @socket = nil
75
- @request_in_progress = false
76
- end
79
+ raise DRb::DRbConnError, "Shutdown" if @shutdown
80
+ if !@socket or @socket.closed? or @request_in_progress
81
+ if @request_in_progress
82
+ disconnect()
83
+ @socket = nil
84
+ @request_in_progress = false
85
+ end
86
+ begin
87
+ addr = Socket.pack_sockaddr_in(@port, @hostname)
88
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
89
+ @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
77
90
  begin
78
- @socket = TCPSocket.new(@hostname, @port)
79
- @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
80
- rescue => e
81
- raise DRb::DRbConnError, e.message
91
+ @socket.connect_nonblock(addr)
92
+ rescue IO::WaitWritable
93
+ begin
94
+ _, sockets, _ = IO.select(nil, [@socket], nil, @connect_timeout) # wait 3-way handshake completion
95
+ rescue Errno::ENOTSOCK
96
+ disconnect()
97
+ @socket = nil
98
+ raise "Connect canceled"
99
+ end
100
+ if sockets and !sockets.empty?
101
+ begin
102
+ @socket.connect_nonblock(addr) # check connection failure
103
+ rescue Errno::EISCONN
104
+ end
105
+ else
106
+ disconnect()
107
+ @socket = nil
108
+ raise "Connect timeout"
109
+ end
82
110
  end
111
+ rescue => e
112
+ raise DRb::DRbConnError, e.message
83
113
  end
114
+ end
84
115
 
85
- request = JsonRpcRequest.new(method_name, method_params, @id)
86
- @id += 1
116
+ request = JsonRpcRequest.new(method_name, method_params, @id)
117
+ @id += 1
87
118
 
88
- request_data = request.to_json(:allow_nan => true)
89
- begin
90
- @request_in_progress = true
91
- STDOUT.puts "Request:\n" if JsonDRb.debug?
92
- STDOUT.puts request_data if JsonDRb.debug?
93
- JsonDRb.send_data(@socket, request_data)
94
- response_data = JsonDRb.receive_message(@socket, '')
95
- STDOUT.puts "\nResponse:\n" if JsonDRb.debug?
96
- STDOUT.puts response_data if JsonDRb.debug?
97
- @request_in_progress = false
98
- rescue => e
99
- @socket.close if @socket and !@socket.closed?
100
- @socket = nil
101
- if first_try
102
- first_try = false
103
- next
104
- else
105
- raise DRb::DRbConnError, e.message, e.backtrace
106
- end
107
- end
119
+ request_data = request.to_json(:allow_nan => true)
120
+ begin
121
+ @request_in_progress = true
122
+ STDOUT.puts "Request:\n" if JsonDRb.debug?
123
+ STDOUT.puts request_data if JsonDRb.debug?
124
+ JsonDRb.send_data(@socket, request_data)
125
+ response_data = JsonDRb.receive_message(@socket, '')
126
+ STDOUT.puts "\nResponse:\n" if JsonDRb.debug?
127
+ STDOUT.puts response_data if JsonDRb.debug?
128
+ @request_in_progress = false
129
+ rescue => e
130
+ disconnect()
131
+ @socket = nil
132
+ raise DRb::DRbConnError, e.message, e.backtrace
133
+ end
108
134
 
109
- if response_data
110
- response = JsonRpcResponse.from_json(response_data)
111
- if JsonRpcErrorResponse === response
112
- if response.error.data
113
- raise Exception.from_hash(response.error.data)
114
- else
115
- raise "JsonDRb Error (#{response.error.code}): #{response.error.message}"
116
- end
135
+ if response_data
136
+ response = JsonRpcResponse.from_json(response_data)
137
+ if JsonRpcErrorResponse === response
138
+ if response.error.data
139
+ raise Exception.from_hash(response.error.data)
117
140
  else
118
- return response.result
141
+ raise "JsonDRb Error (#{response.error.code}): #{response.error.message}"
119
142
  end
120
143
  else
121
- # Socket was closed by server
122
- @socket.close if @socket and !@socket.closed?
123
- @socket = nil
124
- if first_try
125
- first_try = false
126
- next
127
- else
128
- # Socket already closed by receive_message
129
- raise DRb::DRbConnError, "Socket closed by server"
130
- end
144
+ return response.result
131
145
  end
132
- end # loop
146
+ else
147
+ # Socket was closed by server
148
+ disconnect()
149
+ @socket = nil
150
+ raise DRb::DRbConnError, "Socket closed by server"
151
+ end
133
152
  end
134
153
  end
135
154
  end
@@ -70,17 +70,7 @@ module Cosmos
70
70
  @read_timeout = @read_timeout.to_f if @read_timeout
71
71
 
72
72
  stream_protocol_class = stream_protocol_type.to_s.capitalize << 'StreamProtocol'
73
- @stream_protocol_class = stream_protocol_class.to_class
74
- unless @stream_protocol_class
75
- begin
76
- require "cosmos/streams/#{stream_protocol_class.class_name_to_filename}"
77
- @stream_protocol_class = stream_protocol_class.to_class
78
- rescue LoadError => err
79
- Logger.instance.error "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
80
- raise "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
81
- end
82
- end
83
-
73
+ @stream_protocol_class = Cosmos.require_class(stream_protocol_class.class_name_to_filename)
84
74
  @stream_protocol_args = stream_protocol_args
85
75
 
86
76
  @listen_sockets = []
@@ -4,3 +4,4 @@ require 'cosmos/packet_logs/packet_log_writer'
4
4
  require 'cosmos/packet_logs/meta_packet_log_writer'
5
5
  require 'cosmos/packet_logs/packet_log_writer_pair'
6
6
  require 'cosmos/packet_logs/packet_log_reader'
7
+ require 'cosmos/packet_logs/ccsds_log_reader'
@@ -0,0 +1,103 @@
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/packet_logs/packet_log_reader'
12
+ require 'cosmos/ccsds/ccsds_packet'
13
+
14
+ module Cosmos
15
+
16
+ # Reads a CCSDS packet log of either commands or telemetry.
17
+ class CcsdsLogReader < PacketLogReader
18
+
19
+ # Length of the header on a CCSDS source packet
20
+ CCSDS_HEADER_LENGTH = 6
21
+
22
+ # Create a new log file reader
23
+ def initialize
24
+ super()
25
+ @ccsds_header = CcsdsPacket.new(nil, nil, false)
26
+ end
27
+
28
+ # Read a packet from the log file
29
+ #
30
+ # @param identify_and_define (see #each)
31
+ # @return [Packet]
32
+ def read(identify_and_define = true)
33
+ # Read the CCSDS packet header
34
+ header = @file.read(CCSDS_HEADER_LENGTH)
35
+ return nil unless header and header.length == CCSDS_HEADER_LENGTH
36
+ @ccsds_header.buffer = header
37
+
38
+ # Extract the length field
39
+ length = @ccsds_header.read('CcsdsLength') + 1
40
+
41
+ # Read the remainder of the packet data
42
+ data = @file.read(length)
43
+ return nil unless data and data.length == length
44
+
45
+ # Combine into the full packet data
46
+ packet_data = header << data
47
+
48
+ # Determine packet time and set it as received time
49
+ received_time = determine_received_time(packet_data)
50
+
51
+ # Build the actual Packet object
52
+ if identify_and_define
53
+ packet = identify_and_define_packet_data(nil, nil, received_time, packet_data)
54
+ else
55
+ # Build Packet
56
+ packet = Packet.new(nil, nil, :BIG_ENDIAN, nil, packet_data)
57
+ packet.set_received_time_fast(received_time)
58
+ end
59
+
60
+ # Return the packet
61
+ packet
62
+ rescue => err
63
+ close()
64
+ raise err
65
+ end
66
+
67
+ protected
68
+
69
+ # TODO : Add code here or in subclass to derive received time from the packet timestamp
70
+ # CCSDS timestamp formats and even the presence of a timestamp vary
71
+ def determine_received_time(packet_data)
72
+ nil
73
+ end
74
+
75
+ def read_file_header
76
+ # Read the first CCSDS packet header
77
+ header = @file.read(CCSDS_HEADER_LENGTH)
78
+
79
+ if header and header.length == CCSDS_HEADER_LENGTH
80
+ @ccsds_header.buffer = header
81
+ packet_type = @ccsds_header.read('CcsdsType')
82
+ if packet_type == CcsdsPacket::TELEMETRY
83
+ @log_type = :TLM
84
+ else
85
+ @log_type = :CMD
86
+ end
87
+ @configuration_name = nil
88
+ @hostname = nil
89
+ @file_header_length = 0
90
+ @file.seek(0, IO::SEEK_SET)
91
+ System.load_configuration(nil)
92
+ else
93
+ raise "Failed to read at least #{CCSDS_HEADER_LENGTH} bytes from packet log"
94
+ end
95
+ end
96
+
97
+ def seek_to_time(time)
98
+ # Not supported
99
+ end
100
+
101
+ end # class CcsdsLogReader
102
+
103
+ end # module Cosmos