diff --git a/alarmdecoder/devices/serial_device.py b/alarmdecoder/devices/serial_device.py index 96bc636..69311fc 100644 --- a/alarmdecoder/devices/serial_device.py +++ b/alarmdecoder/devices/serial_device.py @@ -210,8 +210,14 @@ class SerialDevice(Device): timeout_event.reading = False timeout_event.reading = True - if purge_buffer: - self._buffer = b'' + buf = b'' + if not purge_buffer: + #Add previous leftovers to front of buf so leftovers can be searched for newlines + #If there were no leftovers then self._buffer will be empty + buf = self._buffer + + self._buffer = b'' + got_line, data = False, '' @@ -222,17 +228,27 @@ class SerialDevice(Device): leftovers = b'' try: while timeout_event.reading and not got_line: - read_ready, _, _ = select.select([self._device.fileno()], [], [], 0.5) - if len(read_ready) == 0: + #If there is leftover data then only perform a poll to set the read_ready flag + #otherwise block here until short timeout waiting for more data + select_timeout = 0.5 + if len(self._buffer) > 0: + select_timeout = 0.1 + read_ready, _, _ = select.select([self._device.fileno()], [], [], select_timeout) + if len(read_ready) == 0 and len(self._buffer) == 0: continue - bytes_avail = 0 - if hasattr(self._device, "in_waiting"): - bytes_avail = self._device.in_waiting - else: - bytes_avail = self._device.inWaiting() + #Only read data if there is some waiting + if len(read_ready) > 0: + bytes_avail = 0 + if hasattr(self._device, "in_waiting"): + bytes_avail = self._device.in_waiting + else: + bytes_avail = self._device.inWaiting() + + device_data = self._device.read(bytes_avail) - buf = self._device.read(bytes_avail) + #Append new data to previous leftovers, if any + buf = buf + device_data for idx in range(len(buf)): c = buf[idx] @@ -242,15 +258,14 @@ class SerialDevice(Device): ub = bytes([ub]) # NOTE: AD2SERIAL and AD2PI apparently sends down \xFF on boot. - if ub != b'' and ub != b"\xff": - self._buffer += ub - - if ub == b"\n": - self._buffer = self._buffer.strip(b"\r\n") - + if ub != b'' and ub != b"\xff" and ub != b"\r": + if ub != b"\n": + self._buffer += ub + else: + #found end of line if len(self._buffer) > 0: got_line = True - leftovers = buf[idx:] + leftovers = buf[idx+1:] break except (OSError, serial.SerialException) as err: