Beispiel #1
0
    def __init__(self, uri, agent='s', send_buffer_size=2048, recv_buffer_size=2048):
        """
        This functions simplifies functionality of the quanser_stream module to provide a 
        simple blocking server or client. \n \n

        INPUTS: \n
        uri - IP server and port in one string, eg. 'tcpip://IP_ADDRESS:PORT' \n
        agent - 's' or 'c' string representing server or client respectively
        send_buffer_size - (optional) size of send buffer, default is 2048 \n
        recv_buffer_size - (optional) size of recv buffer, default is 2048 \n

        """
        self.agent = agent
        self.send_buffer_size = send_buffer_size
        self.recv_buffer_size = recv_buffer_size
        self.uri = uri
        
        # If the agent is a Client, then Server isn't needed. 
        # If the agent is a Server, a Client will also be needed. The server can start listening immediately.
        
        self.clientStream = Stream()
        if agent=='s':
            self.serverStream = Stream()
            
        # Set polling timeout to 1 second, and initialize counter for polling connections         
        self.t_out = Timeout(seconds=0, nanoseconds=1000000)
        # counter = 0

        # connected flag initialized to False
        self.connected = False
        non_blocking = False

        try:
            if agent == 'c':
                self.connected = self.clientStream.connect(uri, non_blocking, self.send_buffer_size, self.recv_buffer_size)
       
            elif agent == 's':
                self.serverStream.listen(self.uri, non_blocking)
            pass

        except StreamError as e:
            if self.agent == 's':
                print('Server initialization failed.')
            elif self.agent == 'c':
                print('Client initialization failed.')
            print(e.get_error_message())
    def __init__(self,port):
       # Establish a server stream
        self._server_stream = Stream()

        self._server_stream.listen("{}{}".format("tcpip://localhost:",port), True)

        # Wait for incoming client connection
        print ("Waiting for simulation to connect...")
        
        poll_result = self._server_stream.poll(Timeout(3), PollFlag.ACCEPT)

        while poll_result & PollFlag.ACCEPT != PollFlag.ACCEPT:
            poll_result = self._server_stream.poll(Timeout(3), PollFlag.ACCEPT)


        if poll_result & PollFlag.ACCEPT == PollFlag.ACCEPT:
            print("Connection accepted")
        else:
            print("Connection timeout")
        
        
        self._client_connection = self._server_stream.accept(1460, self._BUFFER_SIZE)
        print ("Simulation connected")
class comm_modular_server:

    # Define class-level variables   
    _server_stream = None
    _client_connection = None

    _BUFFER_SIZE = 65537
    _read_buffer = bytearray(_BUFFER_SIZE)
    _send_buffer = bytearray()
#    _new_packet = True   


    _receive_packet_buffer = bytearray()
    _receive_packet_size = 0
    _receive_packet_container_index = 0

    # Initilize class
    def __init__(self,port):
       # Establish a server stream
        self._server_stream = Stream()

        self._server_stream.listen("{}{}".format("tcpip://localhost:",port), True)

        # Wait for incoming client connection
        print ("Waiting for simulation to connect...")
        
        poll_result = self._server_stream.poll(Timeout(3), PollFlag.ACCEPT)

        while poll_result & PollFlag.ACCEPT != PollFlag.ACCEPT:
            poll_result = self._server_stream.poll(Timeout(3), PollFlag.ACCEPT)


        if poll_result & PollFlag.ACCEPT == PollFlag.ACCEPT:
            print("Connection accepted")
        else:
            print("Connection timeout")
        
        
        self._client_connection = self._server_stream.accept(1460, self._BUFFER_SIZE)
        print ("Simulation connected")
        
    
    # Pack data and send immediately
    def send_container (self, container):
        try:
            data = bytearray(struct.pack("<i", 1+container.container_size)) + bytearray(struct.pack(">BiiBB", 123, container.container_size, container.device_id, container.device_number, container.device_function)) + container.payload
            num_bytes = len(data)
            bytes_written = self._client_connection.send(data, num_bytes)
            self._client_connection.flush()
        except:
            return
            
    # Build send buffer
    def queue_container (self, container):
        self._send_buffer = self._send_buffer + bytearray(struct.pack(">iiBB", container.container_size, container.device_id, container.device_number, container.device_function)) + container.payload
        #print("{} bytes added to queue.".format(len(self._send_buffer)))
        return            

    # Transmit send buffer
    def send_queue (self):
    
        if (len(self._send_buffer) > 0):
            #print("Sending queue of {} bytes.".format(len(self._send_buffer)))
    
            self._send_buffer = bytearray(struct.pack("<iB", 1+len(self._send_buffer), 123)) + self._send_buffer
            
            num_bytes = len(self._send_buffer)
            
            try:
            
                bytes_written = self._client_connection.send(self._send_buffer, num_bytes)
                self._client_connection.flush()  
                self._send_buffer = bytearray()   
                return bytes_written
            except StreamError as e:
                return e.error_code
        else:
            return 0


    # Check if new data is available.  Returns true if a complete packet has been received.
    def receive_new_data(self):    
        bytes_read = 0
        
        try:
            bytes_read = self._client_connection.receive(self._read_buffer, self._BUFFER_SIZE)
        except StreamError as e:
            if e.error_code == -34:
                # would block
                bytes_read = 0
        #print("Bytes read: {}".format(bytes_read))
            
        new_data = False

    
        while bytes_read > 0:
            #print("Received {} bytes".format(bytes_read))
            self._receive_packet_buffer += bytearray(self._read_buffer[0:(bytes_read)])

            #while we're here, check if there are any more bytes in the receive buffer
            try:
                bytes_read = self._client_connection.receive(self._read_buffer, self._BUFFER_SIZE)
            except StreamError as e:
                if e.error_code == -34:
                    # would block
                    bytes_read = 0
                    
        # check if we already have data in the receive buffer that was unprocessed (multiple packets in a single receive)
        if len(self._receive_packet_buffer) > 5:
            if (self._receive_packet_buffer[4] == 123):
                
                # packet size
                self._receive_packet_size, = struct.unpack("<I", self._receive_packet_buffer[0:4])
                # add the 4 bytes for the size to the packet size
                self._receive_packet_size = self._receive_packet_size + 4
            
            
                if len(self._receive_packet_buffer) >= self._receive_packet_size:
                    
                    self._receive_packet_container_index = 5
                    new_data = True
                   
            else:
                print("Error parsing multiple packets in receive buffer.  Clearing internal buffers.")
                _receive_packet_buffer = bytearray()
                
        return new_data



    # Parse out received containers
    def get_next_container(self):
        c = comm_modular_container()
        is_more_containers = False
    
        if (self._receive_packet_container_index > 0):
            c.container_size, = struct.unpack(">I", self._receive_packet_buffer[self._receive_packet_container_index:(self._receive_packet_container_index+4)])
            c.device_id, = struct.unpack(">I", self._receive_packet_buffer[(self._receive_packet_container_index+4):(self._receive_packet_container_index+8)])
            c.device_number = self._receive_packet_buffer[self._receive_packet_container_index+8]
            c.device_function = self._receive_packet_buffer[self._receive_packet_container_index+9]
            c.payload = bytearray(self._receive_packet_buffer[(self._receive_packet_container_index+10):(self._receive_packet_container_index+c.container_size)])
            
            self._receive_packet_container_index = self._receive_packet_container_index + c.container_size
            
            if (self._receive_packet_container_index >= self._receive_packet_size):
                
                is_more_containers = False
                
                if len(self._receive_packet_buffer) == self._receive_packet_size:
                    # The data buffer contains only the one packet.  Clear the buffer.
                    self._receive_packet_buffer = bytearray()
                else:
                    # Remove the packet from the data buffer.  There is another packet in the buffer already.
                    self._receive_packet_buffer = self._receive_packet_buffer[(self._receive_packet_container_index):(len(self._receive_packet_buffer))]
                    
                self._receive_packet_container_index = 0
                
            else:
                is_more_containers = True
                
    
        return c, is_more_containers
        
    

    ################## DEVICE MANAGEMENT ##################
    
    # Close Comm Server
    def close (self):
        self._server_stream.shutdown()
        self._server_stream.close()
        print ("Comm Server Closed")
Beispiel #4
0
class BasicStream:
    '''Class object consisting of basic stream server/client functionality'''
    def __init__(self, uri, agent='s', send_buffer_size=2048, recv_buffer_size=2048):
        """
        This functions simplifies functionality of the quanser_stream module to provide a 
        simple blocking server or client. \n \n

        INPUTS: \n
        uri - IP server and port in one string, eg. 'tcpip://IP_ADDRESS:PORT' \n
        agent - 's' or 'c' string representing server or client respectively
        send_buffer_size - (optional) size of send buffer, default is 2048 \n
        recv_buffer_size - (optional) size of recv buffer, default is 2048 \n

        """
        self.agent = agent
        self.send_buffer_size = send_buffer_size
        self.recv_buffer_size = recv_buffer_size
        self.uri = uri
        
        # If the agent is a Client, then Server isn't needed. 
        # If the agent is a Server, a Client will also be needed. The server can start listening immediately.
        
        self.clientStream = Stream()
        if agent=='s':
            self.serverStream = Stream()
            
        # Set polling timeout to 1 second, and initialize counter for polling connections         
        self.t_out = Timeout(seconds=0, nanoseconds=1000000)
        # counter = 0

        # connected flag initialized to False
        self.connected = False
        non_blocking = False

        try:
            if agent == 'c':
                self.connected = self.clientStream.connect(uri, non_blocking, self.send_buffer_size, self.recv_buffer_size)
       
            elif agent == 's':
                self.serverStream.listen(self.uri, non_blocking)
            pass

        except StreamError as e:
            if self.agent == 's':
                print('Server initialization failed.')
            elif self.agent == 'c':
                print('Client initialization failed.')
            print(e.get_error_message())

    def checkConnection(self):

        if self.agent == 'c' and not self.connected:
            try:
                poll_result = self.clientStream.poll(self.t_out, PollFlag.CONNECT)
                                
                if (poll_result & PollFlag.CONNECT) == PollFlag.CONNECT:
                    self.connected = True
                    print('Connected to the Server successfully.')            

            except StreamError as e:
                if e.error_code == -33:
                    self.connected = self.clientStream.connect(self.uri, True, self.send_buffer_size, self.recv_buffer_size)
                else:
                    print('Client initialization failed.')
                    print(e.get_error_message())

        if self.agent == 's' and not self.connected:
            try:
                poll_result = self.serverStream.poll(self.t_out, PollFlag.ACCEPT)
                if (poll_result & PollFlag.ACCEPT) == PollFlag.ACCEPT:
                    self.connected = True
                    print('Found a Client successfully.')
                    self.clientStream = self.serverStream.accept(self.send_buffer_size, self.recv_buffer_size)

            except StreamError as e:
                print('Server initialization failed.')
                print(e.get_error_message())

    def terminate(self):
        if self.connected:
            self.clientStream.shutdown()
            self.clientStream.close()
            print('Successfully terminated clients.')

        if self.agent == 's':
            self.serverStream.shutdown()
            self.serverStream.close()
            print('Successfully terminated servers.')

    def receive(self, buffer, iterations=1000):
        """
        This functions receives a numpy buffer object that it will fill with bytes if available. \n \n

        INPUTS: \n
        buffer -  numpy float32 array  \n
        iterations - (optional) number of times to poll for incoming data before terminating, default is 1000 \n 

        OUTPUTS: \n
        buffer - data received \n
        bytes_received - number of bytes received \n
        """
        
        self.t_out = Timeout(1)
        counter = 0
        dataShape = buffer.shape

        # Find number of bytes per array cell based on type
        numBytesBasedOnType = len(np.array([0], dtype=buffer.dtype).tobytes())

        # Calculate total dimensions
        dim = 1
        for i in range(len(dataShape)):
            dim = dim*dataShape[i]
        
        # Calculate total number of bytes needed and set up the bytearray to receive that
        totalNumBytes = dim*numBytesBasedOnType
        self.data = bytearray(totalNumBytes)
        self.bytes_received = 0        

        # Poll to see if data is incoming, and if so, receive it. Poll a max of 'iteration' times
        try:
            while True:

                # See if data is available
                poll_result = self.clientStream.poll(self.t_out, PollFlag.RECEIVE)
                counter += 1
                if not (iterations == 'Inf'):
                    if counter >= iterations:
                        break        
                if not ((poll_result & PollFlag.RECEIVE) == PollFlag.RECEIVE):
                    continue # Data not available, skip receiving

                # Receive data
                self.bytes_received = self.clientStream.receive(self.data, totalNumBytes)
                
                # data received, so break this loop
                break 

            #  convert byte array back into numpy array and reshape.
            buffer = np.reshape(np.frombuffer(self.data, dtype=buffer.dtype), dataShape) 

        except StreamError as e:
            print(e.get_error_message())
        finally:
            return buffer, self.bytes_received

    def send(self, buffer):
        """
        This functions sends the data in the numpy array buffer
        (server or client). \n \n

        INPUTS: \n
        buffer - numpy array of data to be sent \n

        OUTPUTS: \n
        bytesSent - number of bytes actually sent (-1 if send failed) \n
        """

        # Set up array to hold bytes to be sent
        byteArray = buffer.tobytes()
        self.bytesSent = 0
        
        # Send bytes and flush immediately after
        try:
            self.bytesSent = self.clientStream.send(byteArray, len(byteArray))
            self.clientStream.flush()
        except StreamError as e:
            print(e.get_error_message())
            self.bytesSent = -1 # If an error occurs, set bytesSent to -1 for user to check
        finally:
            return self.bytesSent