Source code for spynnaker.pyNN.external_devices_models.push_bot.ethernet.push_bot_wifi_connection

# Copyright (c) 2017 The University of Manchester
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import select
import socket
from spinn_utilities.log import FormatAdapter
from spinn_utilities.ping import Ping
from spinnman.connections.abstract_classes import Listenable, Connection
from spinnman.utilities.socket_utils import (
    get_tcp_socket, connect_socket, get_socket_address, resolve_host,
    receive_message, send_message)
from spinn_front_end_common.utilities.constants import BYTES_PER_KB

logger = FormatAdapter(logging.getLogger(__name__))
# A set of connections that have already been made
_existing_connections = dict()


def get_pushbot_wifi_connection(remote_host, remote_port=56000):
    """
    Get an existing connection to a PushBot, or make a new one.

    :param str remote_host: The IP address of the PushBot
    :param int remote_port: The port number of the PushBot (default 56000)
    """
    key = (remote_host, remote_port)
    if key not in _existing_connections:
        _existing_connections[key] = \
            PushBotWIFIConnection(remote_host, remote_port)
    return _existing_connections[key]


class PushBotWIFIConnection(Connection, Listenable):
    """
    A connection to a PushBot via Wi-Fi.
    """
    __slots__ = [
        "__local_ip_address",
        "__local_port",
        "__remote_ip_address",
        "__remote_port",
        "__socket"]

    RECV_SIZE = 1 * BYTES_PER_KB

    def __init__(self, remote_host, remote_port=56000):
        """
        :param str remote_host: The IP address of the PushBot
        :param int remote_port: The port number of the PushBot (default 56000)
        :raise ~spinnman.exceptions.SpinnmanIOException:
            If there is an error setting up the communication channel
        """
        # Create a TCP Socket
        self.__socket = get_tcp_socket()

        # Get the port to connect to
        self.__remote_port = int(remote_port)

        # Get the host to connect to
        self.__remote_ip_address = resolve_host(remote_host)

        logger.info("Trying to connect to the PushBot via Wi-Fi")
        # Connect the socket
        connect_socket(
            self.__socket, self.__remote_ip_address, self.__remote_port)
        logger.info("Succeeded in connecting to PushBot via Wi-Fi")

        # Get the details of where the socket is connected
        self.__local_ip_address, self.__local_port = get_socket_address(
            self.__socket)

[docs] def is_connected(self): """ See :py:meth:`~spinnman.connections.Connection.is_connected`. """ # check if machine is active and on the network for _ in range(5): # Try up to five times... # ping the remote address if Ping.ping(self.__remote_ip_address) == 0: # ping worked return True # If the ping fails this number of times, the host cannot be contacted return False
@property def local_ip_address(self): """ The local IP address to which the connection is bound, as a dotted string, e.g. `0.0.0.0`. :rtype: str """ return self.__local_ip_address @property def local_port(self): """ The local port to which the connection is bound. :rtype: int """ return self.__local_port @property def remote_ip_address(self): """ The remote IP address to which the connection is connected, as a dotted string, or `None` if not connected remotely. :rtype: str or None """ return self.__remote_ip_address @property def remote_port(self): """ The remote port to which the connection is connected, or `None` if not connected remotely. :rtype: int or None """ return self.__remote_port
[docs] def receive(self, timeout=None): """ Receive data from the connection :param timeout: The timeout, or `None` to wait forever :type timeout: float or None :return: The data received :rtype: bytes :raise SpinnmanTimeoutException: If a timeout occurs before any data is received :raise ~spinnman.exceptions.SpinnmanIOException: If an error occurs receiving the data """ return receive_message(self.__socket, timeout, self.RECV_SIZE)
[docs] def send(self, data): """ Send data down this connection :param bytearray data: The data to be sent :raise ~spinnman.exceptions.SpinnmanIOException: If there is an error sending the data """ send_message(self.__socket, data)
[docs] def close(self): """ See :py:meth:`spinnman.connections.Connection.close`. """ try: self.__socket.shutdown(socket.SHUT_WR) except Exception: # pylint: disable=broad-except pass self.__socket.close()
[docs] def is_ready_to_receive(self, timeout=0): return bool(select.select([self.__socket], [], [], timeout)[0])
[docs] def get_receive_method(self): return self.receive