Exemplo n.º 1
0
class DataReader(IDataReader, IErrorMessage, IStartableObject, Publisher):
    def __init__(self, dataTransfer):
        if (isinstance(dataTransfer, IDataTransfer) != True):
            raise ValueError(
                "@DataReader : expecting parameter one to be IDataTransfer object"
            )
        self.__dataTransfer = dataTransfer
        self.__rxQueue = ByteBuffer()
        self.__rxThread = threading.Thread(target=self.__RunInBackground,
                                           name="mxDataReader",
                                           args=(self.__rxQueue, ))
        self.__rxThread.daemon = True
        self.__waitEvent = threading.Event()
        self.__waitTaskCompleted = threading.Event()
        self.__isAlive = False
        self.__mutex = threading.Lock()

    def IsRunning(self):
        return ((self.__dataTransfer != None)
                and (self.__dataTransfer.IsConnected()) and self.__isAlive)

    def __del__(self):
        if (self.__rxThread != None):
            self.__rxThread.join(READ_THREAD_DELAY_TIMEOUT)
            pass
        self.__rxThread = None
        self.__waitEvent = None

    def GetLastError(self):
        return self.__errorCode

    def Start(self):
        if (self.IsRunning() != True):
            if (self.__rxThread.isAlive() != True):
                self.__rxThread.daemon = True
                self.__waitTaskCompleted.clear()
                self.__waitEvent.clear()
                self.__rxThread.start()

    def __RunInBackground(self, SeqQueue):
        if (self.__isAlive != True):
            self.__error = None
            if (self.__waitEvent.is_set != True):
                self.__waitEvent.set()
                self.__isAlive = True

                while (self.IsRunning()):
                    time.sleep(
                        0.003
                    )  #put a delay on the read thread, lets not blow the pi up
                    try:
                        if (self.__error != None):
                            break
                        if ((self.__dataTransfer != None)
                                and (self.__dataTransfer.IsDataAvailable())):
                            self.__rxQueue.put(self.__dataTransfer.Read())
                    except Exception as err:
                        self.__error = err
                        print(self.__error)

            self.__isAlive = False
            self.__waitTaskCompleted.set()

    def IsDataAvailable(self):
        return (self.__rxQueue.empty() != True)

    def __isStartByte(self, byte):
        sbyte = ord(byte)
        return ((sbyte == ACK) or (sbyte == SOH))

    """
     The function will handle an event packet errors.
    """

    def _GetInvalidBytes(self, argbytes):
        bytes = bytearray()

        for byte in argbytes:
            bytes.append(byte)

        while (self.__rxQueue.empty() != True):
            byte = self.__rxQueue.peek(0)
            if (byte != None):
                if (self.__isStartByte(byte)):
                    break
            byte = self.__rxQueue.get()
            bytes.append(byte)
        return bytes

    def Stop(self):
        if (self.IsRunning()):
            try:
                self.__isAlive = False
                if (self.__waitTaskCompleted != None):
                    self.__waitTaskCompleted.wait()
                if (self.__rxThread != None):
                    self.__rxThread.join(READ_THREAD_DELAY_TIMEOUT)
            except Exception as err:
                print(err)
            finally:
                self.__rxThread = None

        return (self.__rxThread == True)

    """*********************************************
    *@brief
    * The function will read the current packet bytes from 
    * The queue , return ACK if
    *  throw an exception if invalid packet is read.
    *  throw an exception for incompleted bytes.
    *********************************************"""

    def Read(self):
        bytes = bytearray()
        with self.__mutex:
            if (self.IsDataAvailable()):
                continueWith = True
                try:
                    if (self.IsRunning() == True):
                        byte = self.__rxQueue.get()
                        #if(self.__isStartByte(byte)):
                        bytes.append(byte)

                        if (ord(byte) == SOH):
                            byte = self.__rxQueue.get(
                                True, READ_THREAD_DELAY_TIMEOUT)
                            bytes.append(byte)
                            byte = self.__rxQueue.get(
                                True, READ_THREAD_DELAY_TIMEOUT)
                            pLength = ord(byte)
                            bytes.append(byte)

                            for index in range(0, pLength):
                                byte = self.__rxQueue.get(
                                    True, READ_THREAD_DELAY_TIMEOUT)
                                bytes.append(byte)
                    #else:
                    # bytes =  self._GetInvalidBytes(byte);
                    # raise (BadPacketReadError("Invalid start byte read.",bytes,INVALID_PACKET_START_BYTE));

                except Exception as err:
                    bytes = self._GetInvalidBytes(bytes)
                    raise BadPacketReadError(err.message, bytes,
                                             TRANSPORT_READ_TIMEOUT)
        return bytes