class ModbusUdpClientProtocol(protocol.DatagramProtocol, ModbusClientMixin): ''' This represents the base modbus 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.framer = framer or ModbusSocketFramer(ClientDecoder()) if isinstance(self.framer, ModbusSocketFramer): self.transaction = DictTransactionManager(self, **kwargs) else: self.transaction = FifoTransactionManager(self, **kwargs) def datagramReceived(self, data, params): ''' Get response, check for valid message, decode result :param data: The data returned from the server :param params: The host parameters sending the datagram ''' _logger.debug("Datagram from: %s:%d" % params) self.framer.processIncomingPacket(data, self._handleResponse) def execute(self, request): ''' Starts the producer to send the next request to consumer.write(Frame(request)) ''' request.transaction_id = self.transaction.getNextTID() packet = self.framer.buildPacket(request) self.transport.write(packet) 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 is not None: 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
class ModbusClientProtocol(protocol.Protocol, ModbusClientMixin): ''' This represents the base modbus 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 ModbusSocketFramer(ClientDecoder()) if isinstance(self.framer, ModbusSocketFramer): self.transaction = DictTransactionManager(self, **kwargs) else: self.transaction = FifoTransactionManager(self, **kwargs) def connectionMade(self): ''' Called upon a successful client connection. ''' _logger.debug("Client connected to modbus server") self._connected = True def connectionLost(self, reason): ''' Called upon a client disconnect :param reason: The reason for the disconnect ''' _logger.debug("Client disconnected from modbus server: %s" % reason) self._connected = False for tid in self.transaction: self.transaction.getTransaction(tid).errback(Failure( ConnectionException('Connection lost during request'))) 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._handleResponse) def execute(self, request): ''' Starts the producer to send the next request to consumer.write(Frame(request)) ''' request.transaction_id = self.transaction.getNextTID() packet = self.framer.buildPacket(request) self.transport.write(packet) 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 is not None: 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 ''' if not self._connected: return defer.fail(Failure( ConnectionException('Client is not connected'))) d = defer.Deferred() self.transaction.addTransaction(d, tid) return d