cosmos 4.2.4-java → 4.3.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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Gemfile +1 -1
  4. data/Manifest.txt +12 -0
  5. data/autohotkey/tools/cmd_sequence.ahk +21 -20
  6. data/autohotkey/tools/cmd_sequence2.ahk +1 -1
  7. data/autohotkey/tools/config_editor.ahk +1 -1
  8. data/autohotkey/tools/launcher.ahk +1 -0
  9. data/autohotkey/tools/packet_viewer.ahk +6 -5
  10. data/autohotkey/tools/test_runner.ahk +8 -8
  11. data/bin/cosmos +37 -0
  12. data/bin/dart_util +0 -0
  13. data/data/config/item_modifiers.yaml +9 -0
  14. data/data/crc.txt +91 -86
  15. data/demo/Rakefile +2 -0
  16. data/demo/config/dart/Gemfile +1 -1
  17. data/demo/config/data/crc.txt +8 -5
  18. data/demo/config/system/system.txt +28 -0
  19. data/demo/config/system/system2.txt +21 -3
  20. data/demo/config/system/system_alt_ports.txt +69 -0
  21. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +1 -0
  22. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server_chain.txt +18 -0
  23. data/demo/procedures/cosmos_api_test.rb +18 -14
  24. data/demo/procedures/local_screen_example.rb +51 -0
  25. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +32 -4
  26. data/ext/cosmos/ext/packet/packet.c +6 -0
  27. data/ext/mkrf_conf.rb +2 -2
  28. data/install/config/dart/Gemfile +1 -1
  29. data/install/config/data/crc.txt +2 -2
  30. data/install/config/system/system.txt +23 -1
  31. data/lib/cosmos/conversions.rb +2 -0
  32. data/lib/cosmos/conversions/packet_time_formatted_conversion.rb +38 -0
  33. data/lib/cosmos/conversions/packet_time_seconds_conversion.rb +38 -0
  34. data/lib/cosmos/core_ext/cosmos_io.rb +2 -1
  35. data/lib/cosmos/dart/Gemfile +1 -1
  36. data/lib/cosmos/dart/examples/dart_stream_client.rb +6 -2
  37. data/lib/cosmos/dart/lib/dart_common.rb +1 -1
  38. data/lib/cosmos/dart/lib/dart_database_cleaner.rb +2 -2
  39. data/lib/cosmos/dart/lib/dart_decommutator.rb +4 -4
  40. data/lib/cosmos/dart/lib/dart_importer.rb +3 -3
  41. data/lib/cosmos/dart/lib/dart_packet_log_writer.rb +2 -2
  42. data/lib/cosmos/dart/processes/dart_ingester.rb +2 -0
  43. data/lib/cosmos/dart/processes/dart_util.rb +4 -4
  44. data/lib/cosmos/dart/spec/dart/dart_reducer_manager_spec.rb +3 -3
  45. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +9 -5
  46. data/lib/cosmos/gui/dialogs/details_dialog.rb +29 -29
  47. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +1 -1
  48. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +3 -3
  49. data/lib/cosmos/gui/dialogs/interface_raw_dialog.rb +2 -2
  50. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +1 -1
  51. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +10 -10
  52. data/lib/cosmos/gui/qt.rb +10 -1
  53. data/lib/cosmos/gui/qt_tool.rb +17 -10
  54. data/lib/cosmos/gui/text/ruby_editor.rb +47 -8
  55. data/lib/cosmos/gui/utilities/classification_banner.rb +60 -0
  56. data/lib/cosmos/gui/utilities/script_module_gui.rb +26 -0
  57. data/lib/cosmos/interfaces.rb +1 -0
  58. data/lib/cosmos/interfaces/interface.rb +4 -0
  59. data/lib/cosmos/interfaces/protocols/ignore_packet_protocol.rb +46 -0
  60. data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +68 -23
  61. data/lib/cosmos/packet_logs/packet_log_reader.rb +69 -26
  62. data/lib/cosmos/packet_logs/packet_log_writer.rb +13 -1
  63. data/lib/cosmos/packets/commands.rb +5 -1
  64. data/lib/cosmos/packets/packet.rb +36 -2
  65. data/lib/cosmos/packets/packet_config.rb +0 -1
  66. data/lib/cosmos/packets/parsers/format_string_parser.rb +0 -1
  67. data/lib/cosmos/packets/parsers/xtce_parser.rb +1 -1
  68. data/lib/cosmos/packets/telemetry.rb +4 -0
  69. data/lib/cosmos/script/api_shared.rb +2 -0
  70. data/lib/cosmos/script/limits.rb +4 -0
  71. data/lib/cosmos/script/script.rb +27 -11
  72. data/lib/cosmos/script/telemetry.rb +3 -1
  73. data/lib/cosmos/script/tools.rb +18 -8
  74. data/lib/cosmos/system/system.rb +21 -0
  75. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +26 -24
  76. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +29 -29
  77. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +65 -40
  78. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +6 -6
  79. data/lib/cosmos/tools/cmd_tlm_server/api.rb +13 -0
  80. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +12 -9
  81. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +7 -1
  82. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +8 -8
  83. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +13 -2
  84. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +2 -2
  85. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +13 -13
  86. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +4 -4
  87. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +8 -8
  88. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +5 -5
  89. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +35 -20
  90. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +15 -11
  91. data/lib/cosmos/tools/config_editor/config_editor.rb +69 -69
  92. data/lib/cosmos/tools/data_viewer/data_viewer.rb +42 -38
  93. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +1 -0
  94. data/lib/cosmos/tools/data_viewer/dump_component.rb +1 -0
  95. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +4 -4
  96. data/lib/cosmos/tools/launcher/launcher.rb +1 -1
  97. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +28 -24
  98. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +42 -42
  99. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +56 -53
  100. data/lib/cosmos/tools/script_runner/script_runner.rb +112 -95
  101. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +48 -30
  102. data/lib/cosmos/tools/table_manager/table_manager.rb +42 -42
  103. data/lib/cosmos/tools/test_runner/test_runner.rb +45 -27
  104. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +3 -3
  105. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +45 -45
  106. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +4 -4
  107. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +3 -3
  108. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +7 -7
  109. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +10 -10
  110. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +10 -3
  111. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +6 -6
  112. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +14 -14
  113. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +83 -83
  114. data/lib/cosmos/tools/tlm_viewer/screen.rb +73 -13
  115. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +15 -15
  116. data/lib/cosmos/tools/tlm_viewer/widgets.rb +1 -0
  117. data/lib/cosmos/tools/tlm_viewer/widgets/canvasellipse_widget.rb +40 -0
  118. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +1 -1
  119. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +6 -1
  120. data/lib/cosmos/top_level.rb +14 -1
  121. data/lib/cosmos/version.rb +5 -5
  122. data/lib/cosmos/win32/excel.rb +63 -12
  123. data/make_gems.sh +10 -0
  124. data/spec/conversions/packet_time_formatted_conversion_spec.rb +58 -0
  125. data/spec/conversions/packet_time_seconds_conversion_spec.rb +60 -0
  126. data/spec/interfaces/protocols/ignore_packet_protocol_spec.rb +243 -0
  127. data/spec/interfaces/protocols/preidentified_protocol_spec.rb +227 -4
  128. data/spec/io/serial_driver_spec.rb +15 -13
  129. data/spec/packet_logs/packet_log_reader_spec.rb +72 -17
  130. data/spec/packets/packet_config_spec.rb +5 -16
  131. data/spec/packets/parsers/format_string_parser_spec.rb +0 -11
  132. data/spec/packets/parsers/macro_parser_spec.rb +36 -36
  133. data/spec/packets/parsers/state_parser_spec.rb +36 -0
  134. data/spec/packets/telemetry_spec.rb +11 -9
  135. data/spec/script/script_spec.rb +2 -3
  136. data/spec/script/scripting_spec.rb +2 -1
  137. data/spec/script/tools_spec.rb +0 -1
  138. data/spec/tools/cmd_tlm_server/api_spec.rb +28 -20
  139. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +33 -0
  140. data/spec/tools/cmd_tlm_server/commanding_spec.rb +25 -1
  141. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +15 -0
  142. data/tasks/gemfile_stats.rake +3 -2
  143. metadata +14 -2
@@ -0,0 +1,46 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2018 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/config/config_parser'
12
+ require 'cosmos/interfaces/protocols/protocol'
13
+ require 'cosmos/utilities/crc'
14
+ require 'thread'
15
+
16
+ module Cosmos
17
+ # Ignore a specific packet by not letting it through the protocol
18
+ class IgnorePacketProtocol < Protocol
19
+ # @param target_name [String] Target name
20
+ # @param packet_name [String] Packet name
21
+ def initialize(target_name, packet_name, allow_empty_data = nil)
22
+ super(allow_empty_data)
23
+ System.telemetry.packet(target_name, packet_name)
24
+ @target_name = target_name
25
+ @packet_name = packet_name
26
+ end
27
+
28
+ def read_packet(packet)
29
+ # Need to make sure packet is identified and defined
30
+ target_names = nil
31
+ target_names = @interface.target_names if @interface
32
+ identified_packet = System.telemetry.identify_and_define_packet(packet, target_names)
33
+ if identified_packet
34
+ if identified_packet.target_name == @target_name && identified_packet.packet_name == @packet_name
35
+ return :STOP
36
+ end
37
+ end
38
+ return super(packet)
39
+ end
40
+
41
+ def write_packet(packet)
42
+ return :STOP if packet.target_name == @target_name && packet.packet_name == @packet_name
43
+ return super(packet)
44
+ end
45
+ end
46
+ end
@@ -9,6 +9,7 @@
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
11
  require 'cosmos/interfaces/protocols/burst_protocol'
12
+ require 'cosmos/packet_logs/packet_log_reader'
12
13
 
13
14
  module Cosmos
14
15
  # Delineates packets using the COSMOS preidentification system
@@ -17,10 +18,11 @@ module Cosmos
17
18
  # @param sync_pattern (see BurstProtocol#initialize)
18
19
  # @param max_length [Integer] The maximum allowed value of the length field
19
20
  # @param allow_empty_data [true/false/nil] See Protocol#initialize
20
- def initialize(sync_pattern = nil, max_length = nil, allow_empty_data = nil)
21
+ def initialize(sync_pattern = nil, max_length = nil, mode = 4, allow_empty_data = nil)
21
22
  super(0, sync_pattern, false, allow_empty_data)
22
23
  @max_length = ConfigParser.handle_nil(max_length)
23
24
  @max_length = Integer(@max_length) if @max_length
25
+ @mode = Integer(mode)
24
26
  end
25
27
 
26
28
  def reset
@@ -29,21 +31,34 @@ module Cosmos
29
31
  end
30
32
 
31
33
  def read_packet(packet)
32
- packet.received_time = @received_time
33
- packet.target_name = @target_name
34
- packet.packet_name = @packet_name
34
+ packet.received_time = @read_received_time
35
+ packet.target_name = @read_target_name
36
+ packet.packet_name = @read_packet_name
37
+ if @mode == 4 # COSMOS4.3+ Protocol
38
+ packet.stored = @read_stored
39
+ packet.extra = @read_extra
40
+ end
35
41
  return packet
36
42
  end
37
43
 
38
44
  def write_packet(packet)
39
45
  received_time = packet.received_time
40
46
  received_time = Time.now unless received_time
41
- @time_seconds = [received_time.tv_sec].pack('N') # UINT32
42
- @time_microseconds = [received_time.tv_usec].pack('N') # UINT32
43
- @target_name = packet.target_name
44
- @target_name = 'UNKNOWN' unless @target_name
45
- @packet_name = packet.packet_name
46
- @packet_name = 'UNKNOWN' unless @packet_name
47
+ @write_time_seconds = [received_time.tv_sec].pack('N') # UINT32
48
+ @write_time_microseconds = [received_time.tv_usec].pack('N') # UINT32
49
+ @write_target_name = packet.target_name
50
+ @write_target_name = 'UNKNOWN' unless @write_target_name
51
+ @write_packet_name = packet.packet_name
52
+ @write_packet_name = 'UNKNOWN' unless @write_packet_name
53
+ if @mode == 4 # COSMOS4.3+ Protocol
54
+ @write_flags = 0
55
+ @write_flags |= PacketLogReader::COSMOS4_STORED_FLAG_MASK if packet.stored
56
+ @write_extra = nil
57
+ if packet.extra
58
+ @write_flags |= PacketLogReader::COSMOS4_EXTRA_FLAG_MASK
59
+ @write_extra = packet.extra.to_json
60
+ end
61
+ end
47
62
  return packet
48
63
  end
49
64
 
@@ -51,12 +66,19 @@ module Cosmos
51
66
  data_length = [data.length].pack('N') # UINT32
52
67
  data_to_send = ''
53
68
  data_to_send << @sync_pattern if @sync_pattern
54
- data_to_send << @time_seconds
55
- data_to_send << @time_microseconds
56
- data_to_send << @target_name.length
57
- data_to_send << @target_name
58
- data_to_send << @packet_name.length
59
- data_to_send << @packet_name
69
+ if @mode == 4 # COSMOS4.3+ Protocol
70
+ data_to_send << @write_flags
71
+ if @write_extra
72
+ data_to_send << [@write_extra.length].pack('N')
73
+ data_to_send << @write_extra
74
+ end
75
+ end
76
+ data_to_send << @write_time_seconds
77
+ data_to_send << @write_time_microseconds
78
+ data_to_send << @write_target_name.length
79
+ data_to_send << @write_target_name
80
+ data_to_send << @write_packet_name.length
81
+ data_to_send << @write_packet_name
60
82
  data_to_send << data_length
61
83
  data_to_send << data
62
84
  return data_to_send
@@ -104,27 +126,50 @@ module Cosmos
104
126
  @reduction_state = :SYNC_REMOVED
105
127
  end
106
128
 
107
- # Read and remove packet received time
108
- if @reduction_state == :SYNC_REMOVED
129
+ if @reduction_state == :SYNC_REMOVED and @mode == 4
130
+ # Read and remove flags
131
+ return :STOP if @data.length < 1
132
+ flags = @data[0].unpack('C')[0] # byte
133
+ @data.replace(@data[1..-1])
134
+ @read_stored = false
135
+ @read_stored = true if (flags & PacketLogReader::COSMOS4_STORED_FLAG_MASK) != 0
136
+ @read_extra = nil
137
+ if (flags & PacketLogReader::COSMOS4_EXTRA_FLAG_MASK) != 0
138
+ @reduction_state = :NEED_EXTRA
139
+ else
140
+ @reduction_state = :FLAGS_REMOVED
141
+ end
142
+ end
143
+
144
+ if @reduction_state == :NEED_EXTRA
145
+ # Read and remove extra
146
+ @read_extra = read_length_field_followed_by_string(4)
147
+ return :STOP if @read_extra == :STOP
148
+ @read_extra = JSON.parse(@read_extra)
149
+ @reduction_state = :FLAGS_REMOVED
150
+ end
151
+
152
+ if @reduction_state == :FLAGS_REMOVED or (@reduction_state == :SYNC_REMOVED and @mode != 4)
153
+ # Read and remove packet received time
109
154
  return :STOP if @data.length < 8
110
155
  time_seconds = @data[0..3].unpack('N')[0] # UINT32
111
156
  time_microseconds = @data[4..7].unpack('N')[0] # UINT32
112
- @received_time = Time.at(time_seconds, time_microseconds).sys
157
+ @read_received_time = Time.at(time_seconds, time_microseconds).sys
113
158
  @data.replace(@data[8..-1])
114
159
  @reduction_state = :TIME_REMOVED
115
160
  end
116
161
 
117
162
  if @reduction_state == :TIME_REMOVED
118
163
  # Read and remove the target name
119
- @target_name = read_length_field_followed_by_string(1)
120
- return :STOP if @target_name == :STOP
164
+ @read_target_name = read_length_field_followed_by_string(1)
165
+ return :STOP if @read_target_name == :STOP
121
166
  @reduction_state = :TARGET_NAME_REMOVED
122
167
  end
123
168
 
124
169
  if @reduction_state == :TARGET_NAME_REMOVED
125
170
  # Read and remove the packet name
126
- @packet_name = read_length_field_followed_by_string(1)
127
- return :STOP if @packet_name == :STOP
171
+ @read_packet_name = read_length_field_followed_by_string(1)
172
+ return :STOP if @read_packet_name == :STOP
128
173
  @reduction_state = :PACKET_NAME_REMOVED
129
174
  end
130
175
 
@@ -35,6 +35,18 @@ module Cosmos
35
35
  COSMOS1_LOG_TYPE_RANGE = 6..8
36
36
  COSMOS1_CONFIGURATION_NAME_RANGE = 10..41
37
37
 
38
+ # COSMOS 4.3+ log file header definition
39
+ COSMOS4_MARKER = 'COSMOS4_'
40
+ COSMOS4_HEADER_LENGTH = COSMOS2_HEADER_LENGTH
41
+ COSMOS4_MARKER_RANGE = COSMOS2_MARKER_RANGE
42
+ COSMOS4_LOG_TYPE_RANGE = COSMOS2_LOG_TYPE_RANGE
43
+ COSMOS4_CONFIGURATION_NAME_RANGE = COSMOS2_CONFIGURATION_NAME_RANGE
44
+ COSMOS4_HOSTNAME_RANGE = COSMOS2_HOSTNAME_RANGE
45
+ COSMOS4_STORED_FLAG_MASK = 0x80
46
+ COSMOS4_EXTRA_FLAG_MASK = 0x40
47
+
48
+ MAX_READ_SIZE = 1000000000
49
+
38
50
  # Create a new log file reader
39
51
  def initialize
40
52
  reset()
@@ -62,10 +74,10 @@ module Cosmos
62
74
  packet = read(identify_and_define)
63
75
  break unless packet
64
76
 
65
- received_time = packet.received_time
66
- if received_time
67
- next if start_time and received_time < start_time
68
- break if end_time and received_time > end_time
77
+ time = packet.packet_time
78
+ if time
79
+ next if start_time and time < start_time
80
+ break if end_time and time > end_time
69
81
  end
70
82
 
71
83
  yield packet
@@ -115,6 +127,8 @@ module Cosmos
115
127
  reset()
116
128
  @filename = filename
117
129
  @file = BufferedFile.open(@filename, 'rb')
130
+ @max_read_size = @file.size
131
+ @max_read_size = MAX_READ_SIZE if @max_read_size > MAX_READ_SIZE
118
132
  @bytes_read = 0
119
133
  return read_file_header()
120
134
  rescue => err
@@ -133,11 +147,11 @@ module Cosmos
133
147
  # @return [Packet]
134
148
  def read(identify_and_define = true)
135
149
  # Read the Packet Header
136
- success, target_name, packet_name, received_time = read_entry_header()
150
+ success, target_name, packet_name, received_time, stored, extra = read_entry_header()
137
151
  return nil unless success
138
152
 
139
153
  # Read Packet Data
140
- packet_data = @file.read_length_bytes(4)
154
+ packet_data = @file.read_length_bytes(4, @max_read_size)
141
155
  return nil unless packet_data and packet_data.length > 0
142
156
 
143
157
  if identify_and_define
@@ -147,6 +161,8 @@ module Cosmos
147
161
  packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
148
162
  packet.set_received_time_fast(received_time)
149
163
  end
164
+ packet.stored = stored
165
+ packet.extra = extra
150
166
 
151
167
  # Auto change configuration on SYSTEM META
152
168
  if packet.target_name == 'SYSTEM'.freeze and packet.packet_name == 'META'.freeze
@@ -231,11 +247,13 @@ module Cosmos
231
247
 
232
248
  def reset
233
249
  @file = nil
250
+ @max_read_size = MAX_READ_SIZE
234
251
  @filename = nil
235
252
  @log_type = :TLM
236
253
  @configuration_name = nil
237
254
  @hostname = nil
238
- @file_header_length = COSMOS2_HEADER_LENGTH
255
+ @mode = 4
256
+ @file_header_length = COSMOS4_HEADER_LENGTH
239
257
  end
240
258
 
241
259
  # This is best effort. May return unidentified/undefined packets
@@ -269,10 +287,15 @@ module Cosmos
269
287
 
270
288
  # Should return if successfully switched to requested configuration
271
289
  def read_file_header
272
- header = @file.read(COSMOS2_HEADER_LENGTH)
273
- if header and header.length == COSMOS2_HEADER_LENGTH
274
- if header[COSMOS2_MARKER_RANGE] == COSMOS2_MARKER
275
- # Found COSMOS 2 File Header
290
+ header = @file.read(COSMOS4_HEADER_LENGTH)
291
+ if header and header.length == COSMOS4_HEADER_LENGTH
292
+ if header[COSMOS4_MARKER_RANGE] == COSMOS4_MARKER or header[COSMOS2_MARKER_RANGE] == COSMOS2_MARKER
293
+ # Found COSMOS 2/4 File Header
294
+ if header[COSMOS4_MARKER_RANGE] == COSMOS4_MARKER
295
+ @mode = 4
296
+ else
297
+ @mode = 2
298
+ end
276
299
  @log_type = header[COSMOS2_LOG_TYPE_RANGE].intern
277
300
  raise "Unknown log type #{@log_type}" unless [:CMD, :TLM].include? @log_type
278
301
  @configuration_name = header[COSMOS2_CONFIGURATION_NAME_RANGE]
@@ -283,6 +306,7 @@ module Cosmos
283
306
  return false, error # Did not successfully change to requested configuration name
284
307
  elsif header[COSMOS1_MARKER_RANGE] == COSMOS1_MARKER
285
308
  # Found COSMOS 1 File Header
309
+ @mode = 1
286
310
  @log_type = header[COSMOS1_LOG_TYPE_RANGE].upcase.intern
287
311
  raise "Unknown log type #{@log_type}" unless [:CMD, :TLM].include? @log_type
288
312
  @configuration_name = header[COSMOS1_CONFIGURATION_NAME_RANGE]
@@ -297,29 +321,48 @@ module Cosmos
297
321
  raise "COSMOS file header not found on packet log"
298
322
  end
299
323
  else
300
- raise "Failed to read at least #{COSMOS2_HEADER_LENGTH} bytes from packet log"
324
+ raise "Failed to read at least #{COSMOS4_HEADER_LENGTH} bytes from packet log"
301
325
  end
302
326
  end
303
327
 
304
328
  def read_entry_header
329
+ stored = false
330
+ extra = nil
331
+
332
+ if @mode == 4
333
+ # Read Flags
334
+ flags = @file.read(1)
335
+ return [nil, nil, nil, nil, nil, nil] if flags.nil? or flags.length != 1
336
+ flags = flags.unpack('C')[0]
337
+
338
+ stored = true if (flags & COSMOS4_STORED_FLAG_MASK) != 0
339
+
340
+ if (flags & COSMOS4_EXTRA_FLAG_MASK) != 0
341
+ # Read Extra data
342
+ extra_data = @file.read_length_bytes(4, @max_read_size)
343
+ return [nil, nil, nil, nil, nil, nil] unless extra_data and extra_data.length > 0
344
+ extra = JSON.parse(extra_data)
345
+ end
346
+ end
347
+
305
348
  # Read Received Time
306
349
  time_seconds = @file.read(4)
307
- return [nil, nil, nil, nil] if time_seconds.nil? or time_seconds.length != 4
350
+ return [nil, nil, nil, nil, nil, nil] if time_seconds.nil? or time_seconds.length != 4
308
351
  time_seconds = time_seconds.unpack('N')[0]
309
352
  time_microseconds = @file.read(4)
310
- return [nil, nil, nil, nil] if time_microseconds.nil? or time_microseconds.length != 4
353
+ return [nil, nil, nil, nil, nil, nil] if time_microseconds.nil? or time_microseconds.length != 4
311
354
  time_microseconds = time_microseconds.unpack('N')[0]
312
355
  received_time = Time.at(time_seconds, time_microseconds).sys
313
356
 
314
357
  # Read Target Name
315
358
  target_name = @file.read_length_bytes(1)
316
- return [nil, nil, nil, nil] unless target_name and target_name.length > 0
359
+ return [nil, nil, nil, nil, nil, nil] unless target_name and target_name.length > 0
317
360
 
318
361
  # Read Packet Name
319
362
  packet_name = @file.read_length_bytes(1)
320
- return [nil, nil, nil, nil] unless packet_name and packet_name.length > 0
363
+ return [nil, nil, nil, nil, nil, nil] unless packet_name and packet_name.length > 0
321
364
 
322
- return [true, target_name, packet_name, received_time]
365
+ return [true, target_name, packet_name, received_time, stored, extra]
323
366
  end
324
367
 
325
368
  def test
@@ -331,7 +374,7 @@ module Cosmos
331
374
  begin
332
375
  # Try to read the packet header
333
376
  # This will fail with file read errors and invalid timestamps
334
- success, target_name, packet_name, _ = read_entry_header()
377
+ success, target_name, packet_name, _, _, _ = read_entry_header()
335
378
  if success
336
379
  if target_name !~ File::NON_ASCII_PRINTABLE and packet_name !~ File::NON_ASCII_PRINTABLE
337
380
  packet_data_length = @file.read(4)
@@ -402,17 +445,17 @@ module Cosmos
402
445
  # Read the first packet in the log
403
446
  first_packet = first()
404
447
  raise "Error reading first packet" unless first
405
- raise "First Packet does not contain a packet received time" unless first_packet.received_time
448
+ raise "First Packet does not contain a packet received time" unless first_packet.packet_time
406
449
 
407
450
  # Read the last packet in the log
408
451
  file_size = size()
409
452
  last_packet = last()
410
453
  raise "Search failed looking for last packet" unless last_packet
411
- raise "Last Packet does not contain a packet received time" unless last_packet.received_time
454
+ raise "Last Packet does not contain a packet received time" unless last_packet.packet_time
412
455
 
413
- if time >= first_packet.received_time and time <= last_packet.received_time
456
+ if time >= first_packet.packet_time and time <= last_packet.packet_time
414
457
  # Guess at where to start looking for time in log
415
- percentage = (time - first_packet.received_time) / (last_packet.received_time - first_packet.received_time)
458
+ percentage = (time - first_packet.packet_time) / (last_packet.packet_time - first_packet.packet_time)
416
459
  offset = (percentage * file_size.to_f).to_i
417
460
  offset = @file_header_length if offset < @file_header_length
418
461
  @file.seek(offset, IO::SEEK_SET)
@@ -420,10 +463,10 @@ module Cosmos
420
463
  # Move backwards until a packet before the time is found
421
464
  while true
422
465
  packet = search(-1, :BEFORE)
423
- break if !packet or packet.received_time <= time
466
+ break if !packet or packet.packet_time <= time
424
467
 
425
468
  # Guess again
426
- percentage = 1.0 - ((packet.received_time - time) / (packet.received_time - first_packet.received_time))
469
+ percentage = 1.0 - ((packet.packet_time - time) / (packet.packet_time - first_packet.packet_time))
427
470
  offset = (percentage * @file.pos.to_f).to_i
428
471
  offset = @file_header_length if offset < @file_header_length
429
472
  @file.seek(offset, IO::SEEK_SET)
@@ -434,7 +477,7 @@ module Cosmos
434
477
  position = @file.pos
435
478
  packet = read(false)
436
479
  raise "Search failed looking for packet after time" unless packet
437
- if packet.received_time >= time
480
+ if packet.packet_time >= time
438
481
  # Back up this packet so the read can get it because we want it
439
482
  @file.seek(position, IO::SEEK_SET)
440
483
  break
@@ -442,7 +485,7 @@ module Cosmos
442
485
  end
443
486
 
444
487
  else
445
- if time > last_packet.received_time
488
+ if time > last_packet.packet_time
446
489
  # File is entirely before time, so jump to the end
447
490
  @file.seek(0, IO::SEEK_END)
448
491
  else
@@ -311,7 +311,7 @@ module Cosmos
311
311
 
312
312
  def build_file_header(configuration_name = System.configuration_name)
313
313
  hostname = Socket.gethostname.to_s
314
- file_header = "COSMOS2_#{@log_type}_#{configuration_name.ljust(32, ' ')[0..31]}_"
314
+ file_header = "COSMOS4_#{@log_type}_#{configuration_name.ljust(32, ' ')[0..31]}_"
315
315
  file_header << hostname.ljust(83)
316
316
  return file_header
317
317
  end
@@ -322,6 +322,18 @@ module Cosmos
322
322
  # This is an optimization to avoid creating a new entry_header object
323
323
  # each time we create an entry_header which we do a LOT!
324
324
  @entry_header.clear
325
+ flags = 0
326
+ flags |= PacketLogReader::COSMOS4_STORED_FLAG_MASK if packet.stored
327
+ extra = packet.extra
328
+ if extra
329
+ flags |= PacketLogReader::COSMOS4_EXTRA_FLAG_MASK
330
+ extra = extra.to_json
331
+ end
332
+ @entry_header << [flags].pack('C'.freeze)
333
+ if extra
334
+ @entry_header << [extra.length].pack('N'.freeze)
335
+ @entry_header << extra
336
+ end
325
337
  @entry_header << [received_time.tv_sec].pack('N'.freeze)
326
338
  @entry_header << [received_time.tv_usec].pack('N'.freeze)
327
339
  target_name = packet.target_name
@@ -102,7 +102,9 @@ module Cosmos
102
102
  target_packets.each do |packet_name, packet|
103
103
  if (packet.identify?(packet_data))
104
104
  identified_packet = packet.clone
105
- identified_packet.received_time = nil
105
+ identified_packet.received_time = nil
106
+ identified_packet.stored = false
107
+ identified_packet.extra = nil
106
108
  identified_packet.received_count = 0
107
109
  identified_packet.buffer = packet_data
108
110
  break
@@ -141,6 +143,8 @@ module Cosmos
141
143
 
142
144
  # Set time, parameters, and restore defaults
143
145
  command.received_time = Time.now.sys
146
+ command.stored = false
147
+ command.extra = nil
144
148
  command.given_values = params
145
149
  command.restore_defaults(command.buffer(false), params.keys)
146
150
  command.raw = raw