Class: OpenC3::PacketLogReader

Inherits:
Object
  • Object
show all
Includes:
PacketLogConstants
Defined in:
lib/openc3/logs/packet_log_reader.rb

Overview

Reads a packet log of either commands or telemetry.

Constant Summary collapse

MAX_READ_SIZE =
1000000000

Constants included from PacketLogConstants

OpenC3::PacketLogConstants::COSMOS2_FILE_HEADER, OpenC3::PacketLogConstants::COSMOS4_FILE_HEADER, OpenC3::PacketLogConstants::OPENC3_CMD_FLAG_MASK, OpenC3::PacketLogConstants::OPENC3_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_FILE_HEADER, OpenC3::PacketLogConstants::OPENC3_HEADER_LENGTH, OpenC3::PacketLogConstants::OPENC3_ID_FIXED_SIZE, OpenC3::PacketLogConstants::OPENC3_ID_FLAG_MASK, OpenC3::PacketLogConstants::OPENC3_INDEX_HEADER, OpenC3::PacketLogConstants::OPENC3_JSON_PACKET_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_MAX_PACKET_INDEX, OpenC3::PacketLogConstants::OPENC3_MAX_TARGET_INDEX, OpenC3::PacketLogConstants::OPENC3_OFFSET_MARKER_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_OFFSET_MARKER_PACK_DIRECTIVE, OpenC3::PacketLogConstants::OPENC3_OFFSET_MARKER_PACK_ITEMS, OpenC3::PacketLogConstants::OPENC3_OFFSET_MARKER_SECONDARY_FIXED_SIZE, OpenC3::PacketLogConstants::OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_PACKET_DECLARATION_PACK_DIRECTIVE, OpenC3::PacketLogConstants::OPENC3_PACKET_DECLARATION_PACK_ITEMS, OpenC3::PacketLogConstants::OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE, OpenC3::PacketLogConstants::OPENC3_PACKET_PACK_DIRECTIVE, OpenC3::PacketLogConstants::OPENC3_PACKET_PACK_ITEMS, OpenC3::PacketLogConstants::OPENC3_PACKET_SECONDARY_FIXED_SIZE, OpenC3::PacketLogConstants::OPENC3_PRIMARY_FIXED_SIZE, OpenC3::PacketLogConstants::OPENC3_RAW_PACKET_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_STORED_FLAG_MASK, OpenC3::PacketLogConstants::OPENC3_TARGET_DECLARATION_ENTRY_TYPE_MASK, OpenC3::PacketLogConstants::OPENC3_TARGET_DECLARATION_PACK_DIRECTIVE, OpenC3::PacketLogConstants::OPENC3_TARGET_DECLARATION_PACK_ITEMS, OpenC3::PacketLogConstants::OPENC3_TARGET_DECLARATION_SECONDARY_FIXED_SIZE

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePacketLogReader

Create a new log file reader



36
37
38
# File 'lib/openc3/logs/packet_log_reader.rb', line 36

def initialize
  reset()
end

Instance Attribute Details

#redis_offsetObject (readonly)

Returns the value of attribute redis_offset.



31
32
33
# File 'lib/openc3/logs/packet_log_reader.rb', line 31

def redis_offset
  @redis_offset
end

Instance Method Details

#bytes_readInteger



280
281
282
# File 'lib/openc3/logs/packet_log_reader.rb', line 280

def bytes_read
  @file.pos
end

#closeObject

Closes the current log file



99
100
101
# File 'lib/openc3/logs/packet_log_reader.rb', line 99

def close
  @file.close if @file and !@file.closed?
end

#each(filename, identify_and_define = true, start_time = nil, end_time = nil) {|packet| ... } ⇒ Boolean

Yields back each packet as it is found in the log file.

Yield Parameters:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/openc3/logs/packet_log_reader.rb', line 54

def each(filename, identify_and_define = true, start_time = nil, end_time = nil)
  reached_end_time = false
  open(filename)

  # seek_to_time(start_time) if start_time

  while true
    packet = read(identify_and_define)
    break unless packet

    time = packet.packet_time
    if time
      next if start_time and time < start_time
      # If we reach the end_time that means we found all the packets we asked for
      # This can be used by callers to know they are done reading
      if end_time and time > end_time
        reached_end_time = true
        break
      end
    end
    yield packet
  end
  reached_end_time
ensure # No implicit return value in the ensure block
  close()
end

#open(filename) ⇒ Boolean, Exception



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/openc3/logs/packet_log_reader.rb', line 85

def open(filename)
  close()
  reset()
  @filename = filename
  @file = BufferedFile.open(@filename, 'rb')
  @max_read_size = @file.size
  @max_read_size = MAX_READ_SIZE if @max_read_size > MAX_READ_SIZE
  return read_file_header()
rescue => err
  close()
  raise err
end

#read(identify_and_define = true) ⇒ Packet

Read a packet from the log file



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/openc3/logs/packet_log_reader.rb', line 107

def read(identify_and_define = true)
  # Read entry length
  length = @file.read(4)
  return nil if !length or length.length <= 0

  length = length.unpack('N')[0]
  entry = @file.read(length)
  flags = entry[0..1].unpack('n')[0]

  cmd_or_tlm = :TLM
  cmd_or_tlm = :CMD if flags & OPENC3_CMD_FLAG_MASK == OPENC3_CMD_FLAG_MASK
  stored = false
  stored = true if flags & OPENC3_STORED_FLAG_MASK == OPENC3_STORED_FLAG_MASK
  id = false
  id = true if flags & OPENC3_ID_FLAG_MASK == OPENC3_ID_FLAG_MASK

  if flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_JSON_PACKET_ENTRY_TYPE_MASK
    packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
    json_data = entry[12..-1]
    lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
    if cmd_or_tlm != lookup_cmd_or_tlm
      raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
    end

    return JsonPacket.new(cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, json_data)
  elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_RAW_PACKET_ENTRY_TYPE_MASK
    packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
    packet_data = entry[12..-1]
    lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
    if cmd_or_tlm != lookup_cmd_or_tlm
      raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
    end

    received_time = Time.from_nsec_from_epoch(time_nsec_since_epoch)
    if identify_and_define
      packet = identify_and_define_packet_data(cmd_or_tlm, target_name, packet_name, received_time, packet_data)
    else
      # Build Packet
      packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
    end
    packet.set_received_time_fast(received_time)
    packet.cmd_or_tlm = cmd_or_tlm
    packet.stored = stored
    packet.received_count += 1
    return packet
  elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_TARGET_DECLARATION_ENTRY_TYPE_MASK
    target_name_length = length - OPENC3_PRIMARY_FIXED_SIZE - OPENC3_TARGET_DECLARATION_SECONDARY_FIXED_SIZE
    target_name_length -= OPENC3_ID_FIXED_SIZE if id
    target_name = entry[2..(target_name_length + 1)]
    if id
      id = entry[(target_name_length + 3)..(target_name_length + 34)]
      @target_ids << id
    end
    @target_names << target_name
    return read(identify_and_define)
  elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK
    target_index = entry[2..3].unpack('n')[0]
    target_name = @target_names[target_index]
    packet_name_length = length - OPENC3_PRIMARY_FIXED_SIZE - OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE
    packet_name_length -= OPENC3_ID_FIXED_SIZE if id
    packet_name = entry[4..(packet_name_length + 3)]
    if id
      id = entry[(packet_name_length + 4)..-1]
      @packet_ids << id
    end
    @packets << [cmd_or_tlm, target_name, packet_name, id]
    return read(identify_and_define)
  elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_OFFSET_MARKER_ENTRY_TYPE_MASK
    @redis_offset = entry[2..-1]
    return read(identify_and_define)
  else
    raise "Invalid Entry Flags: #{flags}"
  end
rescue => err
  close()
  raise err
end

#sizeInteger



275
276
277
# File 'lib/openc3/logs/packet_log_reader.rb', line 275

def size
  @file.stat.size
end