From 4f12f7ce7869cd24bdc0acd224881bf26ec35de2 Mon Sep 17 00:00:00 2001 From: Michael Stovenour Date: Wed, 4 Sep 2019 20:26:22 -0500 Subject: [PATCH] Resolve issue nutechsoftware/alarmdecoder#issue_40 Solution adds previous leftover to front of buf so leftovers can be searched for newline. It also will process leftover data even if there is no more serial data arriving. --- alarmdecoder/devices/serial_device.py | 49 +++++++++++++++++---------- 1 file changed, 32 insertions(+), 17 deletions(-) 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: