Пример #1
0
class OEFConnection(Connection):
    """The OEFConnection connects the to the mailbox."""

    def __init__(self, oef_addr: str, oef_port: int = 10000, **kwargs):
        """
        Initialize.

        :param oef_addr: the OEF IP address.
        :param oef_port: the OEF port.
        :param kwargs: the keyword arguments (check the parent constructor)
        """
        if kwargs.get("configuration") is None and kwargs.get("connection_id") is None:
            kwargs["connection_id"] = PublicId("fetchai", "oef", "0.1.0")
        super().__init__(**kwargs)
        self.oef_addr = oef_addr
        self.oef_port = oef_port
        self._core = AsyncioCore(logger=logger)  # type: AsyncioCore
        self.in_queue = None  # type: Optional[asyncio.Queue]
        self.channel = OEFChannel(self.address, self.oef_addr, self.oef_port, core=self._core)  # type: ignore
        self._connection_check_task = None  # type: Optional[asyncio.Future]

    async def connect(self) -> None:
        """
        Connect to the channel.

        :return: None
        :raises Exception if the connection to the OEF fails.
        """
        if self.connection_status.is_connected:
            return
        try:
            self.connection_status.is_connecting = True
            self._core.run_threaded()
            loop = asyncio.get_event_loop()
            self.in_queue = asyncio.Queue()
            await self._try_connect()
            self.connection_status.is_connecting = False
            self.connection_status.is_connected = True
            self.channel.loop = loop
            self.channel.in_queue = self.in_queue
            self._connection_check_task = asyncio.ensure_future(
                self._connection_check(), loop=self._loop
            )
        except (CancelledError, Exception) as e:  # pragma: no cover
            self._core.stop()
            self.connection_status.is_connected = False
            raise e

    async def _try_connect(self) -> None:
        """
        Try connect to the channel.

        :return: None
        :raises Exception if the connection to the OEF fails.
        """
        while not self.connection_status.is_connected:
            if not self.channel.connect():
                logger.warning("Cannot connect to OEFChannel. Retrying in 5 seconds...")
                await asyncio.sleep(5.0)
            else:
                break

    async def _connection_check(self) -> None:
        """
        Check for connection to the channel.

        Try to reconnect if connection is dropped.

        :return: None
        """
        while self.connection_status.is_connected:
            await asyncio.sleep(2.0)
            if not self.channel.get_state() == "connected":  # pragma: no cover
                self.connection_status.is_connected = False
                self.connection_status.is_connecting = True
                logger.warning(
                    "Lost connection to OEFChannel. Retrying to connect soon ..."
                )
                await self._try_connect()
                self.connection_status.is_connected = True
                logger.warning("Successfully re-established connection to OEFChannel.")

    async def disconnect(self) -> None:
        """
        Disconnect from the channel.

        :return: None
        """
        assert (
            self.connection_status.is_connected or self.connection_status.is_connecting
        ), "Call connect before disconnect."
        assert self.in_queue is not None
        self.connection_status.is_connected = False
        self.connection_status.is_connecting = False
        if self._connection_check_task is not None:
            self._connection_check_task.cancel()
            self._connection_check_task = None
        self.channel.disconnect()
        await self.in_queue.put(None)
        self._core.stop()

    async def receive(self, *args, **kwargs) -> Optional["Envelope"]:
        """
        Receive an envelope. Blocking.

        :return: the envelope received, or None.
        """
        try:
            assert self.in_queue is not None
            envelope = await self.in_queue.get()
            if envelope is None:
                logger.debug("Received None.")
                return None
            logger.debug("Received envelope: {}".format(envelope))
            return envelope
        except CancelledError:
            logger.debug("Receive cancelled.")
            return None
        except Exception as e:
            logger.exception(e)
            return None

    async def send(self, envelope: "Envelope") -> None:
        """
        Send an envelope.

        :param envelope: the envelope to send.
        :return: None
        """
        if self.connection_status.is_connected:
            self.channel.send(envelope)

    @classmethod
    def from_config(
        cls, address: Address, configuration: ConnectionConfig
    ) -> "Connection":
        """
        Get the OEF connection from the connection configuration.
        :param address: the address of the agent.
        :param configuration: the connection configuration object.
        :return: the connection object
        """
        oef_addr = cast(str, configuration.config.get("addr"))
        oef_port = cast(int, configuration.config.get("port"))
        return OEFConnection(
            oef_addr, oef_port, address=address, configuration=configuration
        )
Пример #2
0
    core.run_threaded()

    # create and connect the agent
    agent = WeatherClient("weatherCLient",
                          oef_addr="127.0.0.1",
                          oef_port=10000,
                          core=core)
    agent.connect()

    # look for service agents registered as 'weather_station' that:
    # - provide measurements for temperature
    # - provide measurements for air pressure
    # - provide measurements for humidity
    query = Query([
        Constraint(TEMPERATURE_ATTR.name, Eq(True)),
        Constraint(AIR_PRESSURE_ATTR.name, Eq(True)),
        Constraint(HUMIDITY_ATTR.name, Eq(True))
    ], WEATHER_DATA_MODEL)

    agent.search_services(0, query)

    try:
        agent.run()
        time.sleep(3)
    except Exception as ex:
        print("EXCEPTION:", ex)
    finally:
        agent.stop()
        agent.disconnect()
        core.stop()
Пример #3
0
class OEFConnection(Connection):
    """The OEFConnection connects the to the mailbox."""

    restricted_to_protocols = set()  # type: Set[str]

    def __init__(self,
                 public_key: str,
                 oef_addr: str,
                 oef_port: int = 10000,
                 connection_id: str = "oef",
                 restricted_to_protocols: Optional[Set[str]] = None):
        """
        Initialize.

        :param public_key: the public key of the agent.
        :param oef_addr: the OEF IP address.
        :param oef_port: the OEF port.
        :param connection_id: the identifier of the connection object.
        :param restricted_to_protocols: the only supported protocols for this connection.
        """
        super().__init__(connection_id=connection_id,
                         restricted_to_protocols=restricted_to_protocols)
        self._core = AsyncioCore(logger=logger)  # type: AsyncioCore
        self.in_queue = None  # type: Optional[asyncio.Queue]
        self.channel = OEFChannel(public_key,
                                  oef_addr,
                                  oef_port,
                                  core=self._core)

        self._connection_check_thread = None  # type: Optional[Thread]

    async def connect(self) -> None:
        """
        Connect to the channel.

        :return: None
        :raises Exception if the connection to the OEF fails.
        """
        if self.connection_status.is_connected:
            return
        try:
            self._core.run_threaded()
            loop = asyncio.get_event_loop()
            self.in_queue = asyncio.Queue()
            await self._try_connect()
            self.connection_status.is_connected = True
            self.channel.loop = loop
            self.channel.in_queue = self.in_queue
            self._connection_check_thread = Thread(
                target=self._connection_check)
            self._connection_check_thread.start()
        except (CancelledError, Exception) as e:  # pragma: no cover
            self._core.stop()
            self.connection_status.is_connected = False
            raise e

    async def _try_connect(self) -> None:
        """
        Try connect to the channel.

        :return: None
        :raises Exception if the connection to the OEF fails.
        """
        while not self.connection_status.is_connected:
            if not self.channel.connect():
                logger.warning(
                    "Cannot connect to OEFChannel. Retrying in 5 seconds...")
                await asyncio.sleep(5.0)
            else:
                break

    def _connection_check(self) -> None:
        """
        Check for connection to the channel.

        Try to reconnect if connection is dropped.

        :return: None
        """
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        while self.connection_status.is_connected:
            time.sleep(2.0)
            if not self.channel.get_state() == "connected":  # pragma: no cover
                self.connection_status.is_connected = False
                logger.warning(
                    "Lost connection to OEFChannel. Retrying to connect soon ..."
                )
                loop.run_until_complete(self._try_connect())
                self.connection_status.is_connected = True
                logger.warning(
                    "Successfully re-established connection to OEFChannel.")

    async def disconnect(self) -> None:
        """
        Disconnect from the channel.

        :return: None
        """
        assert self._connection_check_thread is not None, "Call connect before disconnect."
        assert self.in_queue is not None
        self.connection_status.is_connected = False
        self._connection_check_thread.join()
        self._connection_check_thread = None
        self.channel.disconnect()
        await self.in_queue.put(None)
        self._core.stop()

    async def receive(self, *args, **kwargs) -> Optional['Envelope']:
        """
        Receive an envelope. Blocking.

        :return: the envelope received, or None.
        """
        try:
            assert self.in_queue is not None
            envelope = await self.in_queue.get()
            if envelope is None:
                logger.debug("Received None.")
                return None
            logger.debug("Received envelope: {}".format(envelope))
            return envelope
        except CancelledError:
            logger.debug("Receive cancelled.")
            return None
        except Exception as e:
            logger.exception(e)
            return None

    async def send(self, envelope: 'Envelope') -> None:
        """
        Send an envelope.

        :param envelope: the envelope to send.
        :return: None
        """
        if self.connection_status.is_connected:
            self.channel.send(envelope)

    @classmethod
    def from_config(
            cls, public_key: str,
            connection_configuration: ConnectionConfig) -> 'Connection':
        """
        Get the OEF connection from the connection configuration.

        :param public_key: the public key of the agent.
        :param connection_configuration: the connection configuration object.
        :return: the connection object
        """
        oef_addr = cast(str, connection_configuration.config.get("addr"))
        oef_port = cast(int, connection_configuration.config.get("port"))
        return OEFConnection(
            public_key,
            oef_addr,
            oef_port,
            connection_id=connection_configuration.name,
            restricted_to_protocols=set(
                connection_configuration.restricted_to_protocols))