Exemplo n.º 1
0
    def checkFrame(self):
        """
        Check if the next frame is available.
        Return True if we were successful.

        1. Populate header
        2. Discard frame if UID does not match
        """
        try:
            self.populateHeader()

            frame_size = self._header['len']
            # print(frame_size)
            # print(len(self._buffer))
            data = self._buffer[:frame_size - 2]
            crc = self._buffer[frame_size - 2:frame_size]
            crc_val = (byte2int(crc[0]) << 8) + byte2int(crc[1])
            # print(crc)
            # print(self._buffer.hex())
            # print(crc_val)
            # print(len(data))
            if checkCRC(data, crc_val):
                return True
            else:
                _logger.debug("CRC invalid, discarding header!!")
                self.resetFrame()
                return False
        except (IndexError, KeyError, struct.error):
            return False
Exemplo n.º 2
0
 def checkFrame(self):
     '''
     Check if the next frame is available. Return True if we were
     successful.
     '''
     try:
         self.populateHeader()
         frame_size = self.__header['len']
         data = self.__buffer[:frame_size - 2]
         crc = self.__buffer[frame_size - 2:frame_size]
         crc_val = (byte2int(crc[0]) << 8) + byte2int(crc[1])
         return checkCRC(data, crc_val)
     except (IndexError, KeyError):
         return False
Exemplo n.º 3
0
 def checkFrame(self):
     '''
     Check if the next frame is available. Return True if we were
     successful.
     '''
     try:
         self.populateHeader()
         frame_size = self.__header['len']
         data = self.__buffer[:frame_size - 2]
         crc = self.__buffer[frame_size - 2:frame_size]
         crc_val = (ord(crc[0]) << 8) + ord(crc[1])
         return checkCRC(data, crc_val)
     except (IndexError, KeyError):
         return False
Exemplo n.º 4
0
 def checkFrame(self):
     start = self.__buffer.find(self.__start)
     if start == -1:
         return False
     self.__buffer = self.__buffer[start:]
     end = self.__buffer.rfind(self.__end)
     if end == -1:
         return False
     if end - start < 3:
         return False
     self.__header['len'] = end - start + 1
     self.__header['uid'] = struct.unpack('>B', self.__buffer[start + 1])
     self.__header['crc'] = struct.unpack('>H',
                                          self.__buffer[end - 2:end])[0]
     data = self.__buffer[start + 1:end - 2]
     return checkCRC(data, self.__header['crc'])
Exemplo n.º 5
0
    def checkFrame(self):
        """
        Check if the next frame is available.
        Return True if we were successful.

        1. Populate header
        2. Discard frame if UID does not match
        """
        try:
            self.populateHeader()
            frame_size = self._header['len']
            data = self._buffer[:frame_size - 2]
            crc = self._buffer[frame_size - 2:frame_size]
            crc_val = (byte2int(crc[0]) << 8) + byte2int(crc[1])
            return checkCRC(data, crc_val)
        except (IndexError, KeyError):
            return False
Exemplo n.º 6
0
    def checkFrame(self):
        """
        Check if the next frame is available.
        Return True if we were successful.

        1. Populate header
        2. Discard frame if UID does not match
        """
        try:
            self.populateHeader()
            frame_size = self._header['len']
            data = self._buffer[:frame_size - 2]
            crc = self._buffer[frame_size - 2:frame_size]
            crc_val = (byte2int(crc[0]) << 8) + byte2int(crc[1])
            return checkCRC(data, crc_val)
        except (IndexError, KeyError):
            return False
Exemplo n.º 7
0
    def checkFrame(self):
        ''' Check and decode the next frame

        :returns: True if we are successful, False otherwise
        '''
        start = self.__buffer.find(self.__start)
        if start == -1: return False
        if start > 0 :  # go ahead and skip old bad data
            self.__buffer = self.__buffer[start:]

        end = self.__buffer.find(self.__end)
        if (end != -1):
            self.__header['len'] = end
            self.__header['uid'] = struct.unpack('>B', self.__buffer[1:2])
            self.__header['crc'] = struct.unpack('>H', self.__buffer[end - 2:end])[0]
            data = self.__buffer[start + 1:end - 2]
            return checkCRC(data, self.__header['crc'])
        return False
Exemplo n.º 8
0
    def checkFrame(self):
        ''' Check and decode the next frame

        :returns: True if we are successful, False otherwise
        '''
        start = self.__buffer.find(self.__start)
        if start == -1: return False
        if start > 0 :  # go ahead and skip old bad data
            self.__buffer = self.__buffer[start:]

        end = self.__buffer.find(self.__end)
        if (end != -1):
            self.__header['len'] = end
            self.__header['uid'] = struct.unpack('>B', self.__buffer[1:2])
            self.__header['crc'] = struct.unpack('>H', self.__buffer[end - 2:end])[0]
            data = self.__buffer[start + 1:end - 2]
            return checkCRC(data, self.__header['crc'])
        return False
Exemplo n.º 9
0
    def checkFrame(self):
        """
        Check if the next frame is available.
        Return True if we were successful.

        1. Populate header
        2. Discard frame if UID does not match
        """
        try:
            self.populateHeader()
            frame_size = self._header['len']
            data = self._buffer[:frame_size - 2]
            crc = self._buffer[frame_size - 2:frame_size]
            crc_val = (byte2int(crc[0]) << 8) + byte2int(crc[1])
            if checkCRC(data, crc_val):
                return True
            else:
                _logger.debug("CRC invalid, discarding header!!")
                self.resetFrame()
                return False
        except (IndexError, KeyError, struct.error):
            return False
Exemplo n.º 10
0
 def testCyclicRedundancyCheck(self):
     ''' Test the cyclic redundancy check code '''
     self.assertTrue(checkCRC(self.data, 0xe2db))
     self.assertTrue(checkCRC(self.string, 0x889e))
Exemplo n.º 11
0
 def testCyclicRedundancyCheck(self):
     ''' Test the cyclic redundancy check code '''
     self.assertTrue(checkCRC(self.data, 0xe2db))
     self.assertTrue(checkCRC(self.string, 0x889e))
Exemplo n.º 12
0
def modbus_rtu_read(fd, decoder, size=1024, timeout=None):
    """An fd select.select/os.read loop understands Modbus/RTU protocol, and receives all the data
    available up to the end of the first recognized Modbus/RTU request/reply.  A pymodbus.factory
    ClientDecoder or ServerDecoder must be supplied, in order to recognize the allowed RTU
    requests/replies and compute their sizes.

    """
    incoming = b''
    begun = misc.timer()
    logging.debug("Modbus/RTU %s Receive begins  in %7.3f/%7.3fs",
                  decoder.__class__.__name__,
                  misc.timer() - begun,
                  timeout if timeout is not None else misc.inf)
    complete = False
    rejected = 1  # known *not* to be a valid request <function code> ... <crc>
    # Wait up to 'timeout' for an initial request character, then 1/10th second.
    while (len(incoming) < size and not complete and select.select(
        [fd], [], [], 1.0 / 10 if incoming else timeout)[0]):
        # Not yet satisfied, and frame not yet complete, and still readable; get the next one.  If
        # no input is availabe within 1.5 character times, we should quit; we cannot be anywhere
        # near that precise at the "user" level (probably not even at the device driver level; must
        # be implemented in the RS485-capable UART), so wait a long time (adequate for any UART
        # input available to trickle thru the kernel to the serial input buffer and be reported as
        # ready to receive).  Since we don't know baudrate or kernel loading, we must use an
        # extraordinarily long timeout (1/10th) second.  Unfortunately, this is roughly equivalent
        # to opening the serial port with VMIN=0 and VTIME=1 -- but, astonishingly, there is no way
        # to do that via PySerial!
        c = os.read(fd, 1)
        if not c:
            raise serial.SerialException(
                'device reports readiness to read but returned no data (device disconnected or multiple access on port?)'
            )
        incoming += c
        logging.debug(
            "Modbus/RTU %s Receive reading in %7.3f/%7.3fs; %d bytes",
            decoder.__class__.__name__,
            misc.timer() - begun, timeout if timeout is not None else misc.inf,
            len(incoming))
        for i in range(rejected, max(rejected, len(incoming) - 2)):
            # in a buffer N long, the function code could be anywhere from index 1, to within 3
            # characters from the end: <unit> <func_code> [<data> ...] <crc0> <crc1>.  See if we can
            # reject any more input as definitely *not* a potentially valid request in formation.
            # If its a recognized function code, and we have the complete request data, and its CRC
            # is invalid, reject it and move along.  However, if we cannot yet tell (because we
            # don't yet have a CRC), keep receiving.  For actual ExceptionResponse, we'll just
            # timeout and return what we get (because we can't identify those reliably)
            pdu_class = decoder.lookupPduClass(ord(incoming[i]))
            if pdu_class is ExceptionResponse:  # Returned for every unrecognized function...
                rejected = i
                logging.debug(
                    "Modbus/RTU %s Receive rejects in %7.3f/%7.3fs; %d bytes: no frame at offset %d",
                    decoder.__class__.__name__,
                    misc.timer() - begun,
                    timeout if timeout is not None else misc.inf,
                    len(incoming), rejected)
                continue
            # Might be a function code!  How big?  Raises Exception if data not yet available.
            try:
                frame_size = pdu_class.calculateRtuFrameSize(incoming[i - 1:])
                data = incoming[i - 1:i - 1 + frame_size - 2]
                crc = incoming[i - 1 + frame_size - 2:i - 1 + frame_size]
                crc_val = (ord(crc[0]) << 8) + ord(crc[1])
                if checkCRC(data, crc_val):
                    logging.debug(
                        "Modbus/RTU %s Receive framing in %7.3f/%7.3fs; %d bytes: %s of %d bytes",
                        decoder.__class__.__name__,
                        misc.timer() - begun,
                        timeout if timeout is not None else misc.inf,
                        len(incoming), pdu_class.__name__, frame_size)
                    complete = True
                    break
            except Exception:
                # Not yet possible to tell; keep receiving
                break

    logging.debug("Modbus/RTU %s Receive success in %7.3f/%7.3fs; %d bytes",
                  decoder.__class__.__name__,
                  misc.timer() - begun,
                  timeout if timeout is not None else misc.inf, len(incoming))
    return incoming
Exemplo n.º 13
0
def modbus_rtu_read( fd, decoder, size=1024, timeout=None ):
    """An fd select.select/os.read loop understands Modbus/RTU protocol, and receives all the data
    available up to the end of the first recognized Modbus/RTU request/reply.  A pymodbus.factory
    ClientDecoder or ServerDecoder must be supplied, in order to recognize the allowed RTU
    requests/replies and compute their sizes.

    """
    incoming			= b''
    begun			= misc.timer()
    logging.debug( "Modbus/RTU %s Receive begins  in %7.3f/%7.3fs", decoder.__class__.__name__,
                   misc.timer() - begun, timeout if timeout is not None else misc.inf )
    complete			= False
    rejected			= 1 # known *not* to be a valid request <function code> ... <crc>
    # Wait up to 'timeout' for an initial request character, then 1/10th second.
    while ( len( incoming ) < size 
            and not complete
            and select.select( [fd], [], [], 1.0/10 if incoming else timeout )[0] ):
        # Not yet satisfied, and frame not yet complete, and still readable; get the next one.  If
        # no input is availabe within 1.5 character times, we should quit; we cannot be anywhere
        # near that precise at the "user" level (probably not even at the device driver level; must
        # be implemented in the RS485-capable UART), so wait a long time (adequate for any UART
        # input available to trickle thru the kernel to the serial input buffer and be reported as
        # ready to receive).  Since we don't know baudrate or kernel loading, we must use an
        # extraordinarily long timeout (1/10th) second.  Unfortunately, this is roughly equivalent
        # to opening the serial port with VMIN=0 and VTIME=1 -- but, astonishingly, there is no way
        # to do that via PySerial!
        c			= os.read( fd, 1 )
        if not c:
            raise serial.SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
        incoming	       += c
        logging.debug( "Modbus/RTU %s Receive reading in %7.3f/%7.3fs; %d bytes", decoder.__class__.__name__,
                       misc.timer() - begun, timeout if timeout is not None else misc.inf,
                       len( incoming ))
        for i in range( rejected, max( rejected, len( incoming ) - 2 )):
            # in a buffer N long, the function code could be anywhere from index 1, to within 3
            # characters from the end: <unit> <func_code> [<data> ...] <crc0> <crc1>.  See if we can
            # reject any more input as definitely *not* a potentially valid request in formation.
            # If its a recognized function code, and we have the complete request data, and its CRC
            # is invalid, reject it and move along.  However, if we cannot yet tell (because we
            # don't yet have a CRC), keep receiving.  For actual ExceptionResponse, we'll just
            # timeout and return what we get (because we can't identify those reliably)
            pdu_class		= decoder.lookupPduClass( ord( incoming[i] ))
            if pdu_class is ExceptionResponse: # Returned for every unrecognized function...
                rejected	= i
                logging.debug( "Modbus/RTU %s Receive rejects in %7.3f/%7.3fs; %d bytes: no frame at offset %d", decoder.__class__.__name__,
                               misc.timer() - begun, timeout if timeout is not None else misc.inf,
                               len( incoming ), rejected )
                continue
            # Might be a function code!  How big?  Raises Exception if data not yet available.
            try:
                frame_size	= pdu_class.calculateRtuFrameSize( incoming[i-1:] )
                data		= incoming[i-1:i-1+frame_size-2]
                crc		= incoming[i-1+frame_size-2:i-1+frame_size]
                crc_val		= (ord(crc[0]) << 8) + ord(crc[1])
                if checkCRC( data, crc_val ):
                    logging.debug( "Modbus/RTU %s Receive framing in %7.3f/%7.3fs; %d bytes: %s of %d bytes", decoder.__class__.__name__,
                       misc.timer() - begun, timeout if timeout is not None else misc.inf,
                       len( incoming ), pdu_class.__name__, frame_size )
                    complete	= True
                    break
            except Exception:
                # Not yet possible to tell; keep receiving
                break

    logging.debug( "Modbus/RTU %s Receive success in %7.3f/%7.3fs; %d bytes", decoder.__class__.__name__,
                   misc.timer() - begun, timeout if timeout is not None else misc.inf,
                   len( incoming ))
    return incoming