示例#1
0
class SerialClientProtocol(protocol.Protocol, TimeoutMixin):
    '''
    This represents the base asynchronous client protocol.  All the application
    layer code is deferred to a higher level wrapper.
    '''
    def __init__(self, framer=None, **kwargs):
        ''' Initializes the framer module

        :param framer: The framer to use for the protocol
        '''
        self._connected = False
        self.framer = framer or SocketFramer(ClientDecoder())
        if isinstance(self.framer, SocketFramer):
            self.transaction = DictTransactionManager(self, **kwargs)
        else:
            self.transaction = FifoTransactionManager(self, **kwargs)
        self.lock = defer.DeferredLock()
        self.currentRequest = None
        self._reconnecting = False
        self.deferred = None
        self.lastNAK = '\x10\x15'
        self.ENQCount = 0
        self.NAKCount = 0

    def connectionMade(self):
        ''' Called upon a successful client connection.
        '''
        _logger.debug("Client connected to Serial Device")
        self._connected = True

    def connectionLost(self, reason):
        ''' Called upon a client disconnect

        :param reason: The reason for the disconnect
        '''
        _logger.debug("Client disconnected from Serial Device: %s" % reason)
        print "Client disconnected from Serial Device: ", reason
        self._connected = False

        self.reconnect()

    def sendRequest(self, request):
        '''The main entry into the serial link. Any information sent across
           the serial link should be sent throgh this method.

        :param request: the class that holds the data to be sent 
        :return: a deferred that promises a class that holds the response
        '''
        d = self.lock.run(self.execute, request)
        d.addCallback(self.ackPacket)
        d.addErrback(self.errorHandler, 'sendRequest failed')
        return d

    def ackPacket(self, packet):
        '''ACK Message, reset counters/timers and release lock to prepare for next message
           Overide if you need additional code such as sending an ACK message
           for example self.transport.write('\x10\x06')

        :param packet: the class returned from the deferred that called this
        :return: Pass along the class that was returned from the deferred
        '''
        self.resetTimeout()
        self.ENQCount = 0
        self.NAKCount = 0
        self.setTimeout(None)
        self.deffered = None

        return packet

    def dataReceived(self, data):
        ''' Get response, check for valid message, decode result

        :param data: The data returned from the server
        '''
        self.framer.processIncomingPacket(data, self.currentRequest,
                                          self._handleResponse)

    def execute(self, request):
        ''' Write the encoded request across the serial link

        :param request: the class that holds the data to be sent
        :returns: A deferred linked to the current request
        '''
        self.currentRequest = request
        request.transaction_id = self.transaction.getNextTID()
        packet = self.framer.buildPacket(request)
        self.transport.write(packet)
        self.setTimeout(TIMEOUT)

        self.deferred = self._buildResponse(request.transaction_id)
        return self.deferred

    def _handleResponse(self, reply):
        ''' Handle the response recieved on the serial link
            and link to correct deferred

        :param reply: The received data to process
        '''
        if reply is not None:
            if (reply == '\x10\x15'):
                self.NAKCount += 1
                if (self.NAKCount > MAXENQ):
                    #self.result.errBack(defer.fail(IOError("NAK Limit Exceeded")))
                    pass
                else:
                    self.transport.write(self.lastNAK)

            elif (reply == '\x10\x05'):
                self.ENQCount += 1
                if (self.ENQCount > MAXENQ):
                    print("ENQ Limit Exceeded")
                else:
                    self.transport.write(
                        self.framer.buildPacket(self.currentRequest))

            else:
                tid = reply.transaction_id
                handler = self.transaction.getTransaction(tid)
                if handler:
                    handler.callback(reply)
                else:
                    _logger.debug("Unrequested message: " + str(reply))

    def _buildResponse(self, tid):
        ''' Helper method to return a deferred response
        for the current request.

        :param tid: The transaction identifier for this response
        :returns: A defer linked to the latest request
        '''
        d = defer.Deferred()
        self.transaction.addTransaction(d, tid)
        return d

    def timeoutConnection(self):
        print "Timed Out - send ENQ"
        ##############
        # Send ENQ
        ##############
        self.ENQCount += 1
        if (self.ENQCount <= MAXENQ):
            self.resetTimeout()
            self.setTimeout(TIMEOUT)
            self.transport.write('\x10\x05')

        ################################
        # Release Lock for next message
        ################################
        else:
            _logger.debug("ENQ Limit reached")
            self.setTimeout(None)
            self.NAKCount = 0
            self.ENQCount = 0
            if (self._connected and self.deferred):
                #self.deferred = None
                #self.lock.release()
                self.deferred.errback(ConnectionException("Timed Out"))

    def errorHandler(self, error, msg=''):
        stringMsg = msg + ': Failed.  Error was: ', error.value
        _logger.debug(stringMsg)
示例#2
0
class SerialClientProtocol(protocol.Protocol, TimeoutMixin):
    '''
    This represents the base asynchronous client protocol.  All the application
    layer code is deferred to a higher level wrapper.
    '''    
    
    def __init__(self, framer=None, **kwargs):
        ''' Initializes the framer module

        :param framer: The framer to use for the protocol
        '''
        self._connected = False
        self.framer = framer or SocketFramer(ClientDecoder())
        if isinstance(self.framer, SocketFramer):
            self.transaction = DictTransactionManager(self, **kwargs)
        else:
            self.transaction = FifoTransactionManager(self, **kwargs)
        self.lock = defer.DeferredLock()
        self.currentRequest = None
        self._reconnecting = False
        self.deferred = None
        self.lastNAK = '\x10\x15'
        self.ENQCount = 0
        self.NAKCount = 0

    def connectionMade(self):
        ''' Called upon a successful client connection.
        '''
        _logger.debug("Client connected to Serial Device")
        self._connected = True       

    def connectionLost(self, reason):
        ''' Called upon a client disconnect

        :param reason: The reason for the disconnect
        '''
        _logger.debug("Client disconnected from Serial Device: %s" % reason)
        print "Client disconnected from Serial Device: ", reason
        self._connected = False

        self.reconnect()
     
    def sendRequest(self, request):
        '''The main entry into the serial link. Any information sent across
           the serial link should be sent throgh this method.

        :param request: the class that holds the data to be sent 
        :return: a deferred that promises a class that holds the response
        '''
        d = self.lock.run(self.execute, request)
        d.addCallback(self.ackPacket)
        d.addErrback(self.errorHandler, 'sendRequest failed')
        return d

    def ackPacket(self, packet):
        '''ACK Message, reset counters/timers and release lock to prepare for next message
           Overide if you need additional code such as sending an ACK message
           for example self.transport.write('\x10\x06')

        :param packet: the class returned from the deferred that called this
        :return: Pass along the class that was returned from the deferred
        '''
        self.resetTimeout()
        self.ENQCount = 0
        self.NAKCount = 0
        self.setTimeout(None)
        self.deffered = None
        
        return packet

    def dataReceived(self, data):
        ''' Get response, check for valid message, decode result

        :param data: The data returned from the server
        '''
        self.framer.processIncomingPacket(data, self.currentRequest, self._handleResponse)


    def execute(self, request):
        ''' Write the encoded request across the serial link

        :param request: the class that holds the data to be sent
        :returns: A deferred linked to the current request
        '''
        self.currentRequest = request
        request.transaction_id = self.transaction.getNextTID()
        packet = self.framer.buildPacket(request)
        self.transport.write(packet)
        self.setTimeout(TIMEOUT)

        self.deferred = self._buildResponse(request.transaction_id)
        return self.deferred
           
    def _handleResponse(self, reply):
        ''' Handle the response recieved on the serial link
            and link to correct deferred

        :param reply: The received data to process
        '''
        if reply is not None:
            if (reply == '\x10\x15'):
                self.NAKCount += 1
                if (self.NAKCount > MAXENQ):
                    #self.result.errBack(defer.fail(IOError("NAK Limit Exceeded")))
                    pass
                else:
                    self.transport.write(self.lastNAK)

            elif (reply == '\x10\x05'):
                self.ENQCount += 1
                if (self.ENQCount > MAXENQ):
                    print("ENQ Limit Exceeded")
                else:
                    self.transport.write(self.framer.buildPacket(self.currentRequest))

            else:
                tid = reply.transaction_id
                handler = self.transaction.getTransaction(tid)
                if handler:
                    handler.callback(reply)
                else: _logger.debug("Unrequested message: " + str(reply))

    def _buildResponse(self, tid):
        ''' Helper method to return a deferred response
        for the current request.

        :param tid: The transaction identifier for this response
        :returns: A defer linked to the latest request
        '''            
        d = defer.Deferred()
        self.transaction.addTransaction(d, tid)
        return d

    def timeoutConnection(self):
        print "Timed Out - send ENQ"
        ##############
        # Send ENQ
        ##############
        self.ENQCount += 1
        if (self.ENQCount <= MAXENQ):
            self.resetTimeout()
            self.setTimeout(TIMEOUT)
            self.transport.write('\x10\x05')

        ################################
        # Release Lock for next message
        ################################
        else:
            _logger.debug("ENQ Limit reached")
            self.setTimeout(None)
            self.NAKCount = 0
            self.ENQCount = 0
            if (self._connected and self.deferred):
                #self.deferred = None
                #self.lock.release()
                self.deferred.errback(ConnectionException("Timed Out"))
            
        
    def errorHandler(self, error, msg=''):
        stringMsg = msg + ': Failed.  Error was: ', error.value
        _logger.debug(stringMsg)
示例#3
0
class SerialClientProtocol(protocol.Protocol, TimeoutMixin):
    '''
    This represents the base asynchronous client protocol.  All the application
    layer code is deferred to a higher level wrapper.
    '''    
    
    def __init__(self, framer=None, **kwargs):
        ''' Initializes the framer module

        :param framer: The framer to use for the protocol
        '''
        self._connected = False
        self.framer = framer or SocketFramer(ClientDecoder())
        if isinstance(self.framer, SocketFramer):
            self.transaction = DictTransactionManager(self, **kwargs)
            self.framer.addClient(self)
        else:
            self.transaction = FifoTransactionManager(self, **kwargs)
        self.lock = defer.DeferredLock()
        self.currentRequest = None
        self._reconnecting = False
        self.deferred = None
        self.lastNAK = '\x10\x15'
        self.ENQCount = 0
        self.NAKCount = 0

    def connectionMade(self):
        ''' Called upon a successful client connection.
        '''
        _logger.debug("Client connected to Serial Device")
        self._connected = True       

    def connectionLost(self, reason):
        ''' Called upon a client disconnect

        :param reason: The reason for the disconnect
        '''
        _logger.debug("Client disconnected from Serial Device: %s" % reason)
        self._connected = False
        for tid in self.transaction:
            self.transaction.getTransaction(tid).errback(Failure(
                ConnectionException('Connection lost during request')))
     
    def sendRequest(self, request):
        self.deferred = self.lock.run(self.execute, request)
        self.deferred.addCallback(self.ackPacket)
        self.deferred.addErrback(self.errorHandler, 'sendRequest failed')
        return self.deferred

    def ackPacket(self, packet):
        '''ACK Message, reset counters/timers and release lock to prepare for next message
           Overide if you need additional code such as sending an ACK message
           for example self.transport.write('\x10\x06')
        '''
        self.resetTimeout()
        self.ENQCount = 0
        self.NAKCount = 0
        self.setTimeout(None)
        self.deffered = None
        
        return packet

    def dataReceived(self, data):
        ''' Get response, check for valid message, decode result

        :param data: The data returned from the server
        '''
        self.framer.processIncomingPacket(data, self.currentRequest, self._handleResponse)


    def execute(self, request):
        ''' Starts the producer to send the next request to
        consumer.write(Frame(request))
        '''
        self.currentRequest = request
        request.transaction_id = self.transaction.getNextTID()
        packet = self.framer.buildPacket(request)
        self.transport.write(packet)
        self.setTimeout(TIMEOUT)
        
        return self._buildResponse(request.transaction_id)
           
    def _handleResponse(self, reply):
        ''' Handle the processed response and link to correct deferred

        :param reply: The reply to process
        '''
        if (reply != None):        
            tid = reply.transaction_id
            handler = self.transaction.getTransaction(tid)
            if handler:
                handler.callback(reply)
            elif isinstance(reply, protectedWriteRequest):
                print 'Sending Data to MTrim', repr(reply.encode())
            else:
                print "Unrequested message: " + repr(reply)
                _logger.debug("Unrequested message: " + str(reply))

    def _buildResponse(self, tid):
        ''' Helper method to return a deferred response
        for the current request.

        :param tid: The transaction identifier for this response
        :returns: A defer linked to the latest request
        '''
        if not self._connected:
            return defer.fail(Failure(ConnectionException('Client is not connected')))

        d = defer.Deferred()
        self.transaction.addTransaction(d, tid)
        return d

    def timeoutConnection(self):
        print "Timed Out - send ENQ"
        ##############
        # Send ENQ
        ##############
        self.ENQCount += 1
        if (self.ENQCount <= MAXENQ):
            self.resetTimeout()
            self.setTimeout(TIMEOUT)
            self.transport.write('\x10\x05')

        ################################
        # Release Lock for next message
        ################################
        else:
            _logger.debug("ENQ Limit reached")
            self.setTimeout(None)
            self.NAKCount = 0
            self.ENQCount = 0
            #Raise (defer.fail(ConnectionException('Request Timed Out')))
            raise ConnectionException('Request Timed Out')
            #self.lock.release()
        
    def errorHandler(self, error, msg=''):
        stringMsg = msg + ': Failed.  Error was: ', error.value
        _logger.debug(stringMsg)
        self.lock.release()