diff --git a/lib/kiss/kiss.rb b/lib/kiss/kiss.rb index 57ea6974f8422ac3e65d395006f42cc89871edc4..a53f895318eebe9089ff7ee50681891b3e5ed330 100644 --- a/lib/kiss/kiss.rb +++ b/lib/kiss/kiss.rb @@ -10,6 +10,7 @@ module KISS def initialize(strip_df_start=true, exit_kiss=true) @strip_df_start = strip_df_start @exit_kiss = exit_kiss + @frame_buffer = [] @lock = Mutex.new end @@ -57,24 +58,95 @@ module KISS # ) end + private + def fill_buffer + new_frames = [] + read_buffer = [] + read_data = self.read_interface + while read_data&.length + split_data = [[]] + read_data.each do |read_byte| + if read_byte == KISS::FEND + split_data << [] + else + split_data[-1] << read_byte + end + end + len_fend = split_data.length + + # No FEND in frame + if len_fend == 1 + read_buffer += split_data[0] + # Single FEND in frame + elsif len_fend == 2 + # Closing FEND found + if split_data[0] + # Partial frame continued, otherwise drop + new_frames << read_buffer + split_data[0] + read_buffer = [] + # Opening FEND found + else + new_frames << read_buffer + read_buffer = split_data[1] + end + # At least one complete frame received + elsif len_fend >= 3 + (0...len_fend - 1).each do |i| + read_buffer_tmp = read_buffer + split_data[i] + if read_buffer_tmp.length + new_frames << read_buffer_tmp + read_buffer = [] + end + end + if split_data[len_fend - 1] + read_buffer = split_data[len_fend - 1] + end + end + # Get anymore data that is waiting + read_data = self.read_interface + end + + new_frames.each do |new_frame| + if new_frame.length and not new_frame[0] + if @strip_df_start + new_frame = KISS.strip_df_start(new_frame) + end + @frame_buffer << new_frame + end + end + end + def connect(mode_init=None, *args, **kwargs) end - def close() + def close if @exit_kiss self.write_interface(KISS::MODE_END) end end - def read() + def read @lock.synchronize do - # read stuff + if @frame_buffer.length > 0 + self.fill_buffer + end + + if @frame_buffer.length + return_frame = @frame_buffer[0] + @frame_buffer.shift + return return_frame + else + return nil + end end end def write(frame_bytes, port=0) @lock.synchronize do - # write stuff + kiss_packet = [KISS:FEND] + [self.command_byte_combine(port, KISS::DATA_FRAME)] + + self.escape_special_codes(frame_bytes) + [KISS::FEND] + + return self.write_interface(kiss_packet) end end end