Class: OpenC3::LengthProtocol
- Inherits:
-
BurstProtocol
- Object
- Protocol
- BurstProtocol
- OpenC3::LengthProtocol
- Defined in:
- lib/openc3/interfaces/protocols/length_protocol.rb
Overview
Protocol which delineates packets using a length field at a fixed location in each packet.
Instance Attribute Summary
Attributes inherited from Protocol
#allow_empty_data, #extra, #interface
Instance Method Summary collapse
-
#calculate_length(buffer_length) ⇒ Object
protected.
-
#initialize(length_bit_offset = 0, length_bit_size = 16, length_value_offset = 0, length_bytes_per_count = 1, length_endianness = 'BIG_ENDIAN', discard_leading_bytes = 0, sync_pattern = nil, max_length = nil, fill_length_and_sync_pattern = false, allow_empty_data = nil) ⇒ LengthProtocol
constructor
A new instance of LengthProtocol.
- #read_details ⇒ Object
- #reduce_to_single_packet ⇒ Object
-
#write_data(data, extra = nil) ⇒ String
Called to perform modifications on write data before making it into a packet.
- #write_details ⇒ Object
-
#write_packet(packet) ⇒ Packet
Called to perform modifications on a command packet before it is send.
Methods inherited from BurstProtocol
#handle_sync_pattern, #log_discard, #read_data, #reset
Methods inherited from Protocol
#connect_reset, #disconnect_reset, #post_write_interface, #protocol_cmd, #read_data, #read_packet, #read_protocol_input_base, #read_protocol_output_base, #reset, #write_protocol_input_base, #write_protocol_output_base
Constructor Details
#initialize(length_bit_offset = 0, length_bit_size = 16, length_value_offset = 0, length_bytes_per_count = 1, length_endianness = 'BIG_ENDIAN', discard_leading_bytes = 0, sync_pattern = nil, max_length = nil, fill_length_and_sync_pattern = false, allow_empty_data = nil) ⇒ LengthProtocol
Returns a new instance of LengthProtocol.
49 50 51 52 53 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 80 81 82 83 84 85 86 87 88 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 49 def initialize( length_bit_offset = 0, length_bit_size = 16, length_value_offset = 0, length_bytes_per_count = 1, length_endianness = 'BIG_ENDIAN', discard_leading_bytes = 0, sync_pattern = nil, max_length = nil, fill_length_and_sync_pattern = false, allow_empty_data = nil ) super(discard_leading_bytes, sync_pattern, fill_length_and_sync_pattern, allow_empty_data) # Save length field attributes @length_bit_offset = Integer(length_bit_offset) @length_bit_size = Integer(length_bit_size) @length_value_offset = Integer(length_value_offset) @length_bytes_per_count = Integer(length_bytes_per_count) # Save endianness if length_endianness.to_s.upcase == 'LITTLE_ENDIAN' @length_endianness = :LITTLE_ENDIAN else @length_endianness = :BIG_ENDIAN end # Derive number of bytes required to contain entire length field if @length_endianness == :BIG_ENDIAN or ((@length_bit_offset % 8) == 0) length_bits_needed = @length_bit_offset + @length_bit_size length_bits_needed += 8 if (length_bits_needed % 8) != 0 @length_bytes_needed = ((length_bits_needed - 1) / 8) + 1 else @length_bytes_needed = (length_bit_offset / 8) + 1 end # Save max length setting @max_length = ConfigParser.handle_nil(max_length) @max_length = Integer(@max_length) if @max_length end |
Instance Method Details
#calculate_length(buffer_length) ⇒ Object
protected
154 155 156 157 158 159 160 161 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 154 def calculate_length(buffer_length) length = (buffer_length / @length_bytes_per_count) - @length_value_offset if @max_length && length > @max_length raise "Calculated length #{length} larger than max_length #{@max_length}" end length end |
#read_details ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 140 def read_details result = super() result['length_bit_offset'] = @length_bit_offset result['length_bit_size'] = @length_bit_size result['length_value_offset'] = @length_value_offset result['length_bytes_per_count'] = @length_bytes_per_count result['length_endianness'] = @length_endianness result['length_bytes_needed'] = @length_bytes_needed result['max_length'] = @max_length return result end |
#reduce_to_single_packet ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 163 def reduce_to_single_packet # Make sure we have at least enough data to reach the length field return :STOP if @data.length < @length_bytes_needed # Determine the packet's length length = BinaryAccessor.read(@length_bit_offset, @length_bit_size, :UINT, @data, @length_endianness) raise "Length value received larger than max_length: #{length} > #{@max_length}" if @max_length and length > @max_length packet_length = (length * @length_bytes_per_count) + @length_value_offset # Ensure the calculated packet length is long enough to support the location of the length field # without overlap into the next packet if (packet_length * 8) < (@length_bit_offset + @length_bit_size) raise "Calculated packet length of #{packet_length * 8} bits < (offset:#{@length_bit_offset} + size:#{@length_bit_size})" end # Make sure we have enough data for the packet return :STOP if @data.length < packet_length # Reduce to packet data and setup current_data for next packet packet_data = @data[0..(packet_length - 1)] @data.replace(@data[packet_length..-1]) return packet_data, @extra end |
#write_data(data, extra = nil) ⇒ String
Called to perform modifications on write data before making it into a packet
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 115 def write_data(data, extra = nil) data, extra = super(data, extra) if @fill_fields # If the start of the length field is before what we discard, then the # length field is outside the packet if @length_bit_offset < (@discard_leading_bytes * 8) BinaryAccessor.write(calculate_length(data.length), @length_bit_offset, @length_bit_size, :UINT, data, @length_endianness, :ERROR) end end return data, extra end |
#write_details ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 128 def write_details result = super() result['length_bit_offset'] = @length_bit_offset result['length_bit_size'] = @length_bit_size result['length_value_offset'] = @length_value_offset result['length_bytes_per_count'] = @length_bytes_per_count result['length_endianness'] = @length_endianness result['length_bytes_needed'] = @length_bytes_needed result['max_length'] = @max_length return result end |
#write_packet(packet) ⇒ Packet
Called to perform modifications on a command packet before it is send
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/openc3/interfaces/protocols/length_protocol.rb', line 94 def write_packet(packet) if @fill_fields # If the start of the length field is past what we discard, then the # length field is inside the packet if @length_bit_offset >= (@discard_leading_bytes * 8) length = calculate_length(packet.buffer(false).length + @discard_leading_bytes) # Subtract off the discarded bytes since they haven't been added yet # Adding bytes happens in the write_data method offset = @length_bit_offset - (@discard_leading_bytes * 8) # Directly write the packet buffer and fill in the length BinaryAccessor.write(length, offset, @length_bit_size, :UINT, packet.buffer(false), @length_endianness, :ERROR) end end return super(packet) # Allow burst_protocol to set the sync if needed end |