示例#1
0
    def __init__(self,
                 node: pyuavcan.application.Node,
                 level: int = logging.WARNING) -> None:
        self._pub = node.make_publisher(Record)
        self._pub.priority = pyuavcan.transport.Priority.OPTIONAL
        self._pub.send_timeout = 10.0

        self._fut: Optional[asyncio.Future[None]] = None
        self._forward_timestamp = False
        self._started = False
        super().__init__(level)

        def start() -> None:
            self._started = True

        def close() -> None:
            self._started = False
            self._pub.close()
            if self._fut is not None:
                try:
                    self._fut.result()
                except asyncio.InvalidStateError:
                    pass  # May be unset https://github.com/UAVCAN/pyuavcan/issues/192

        node.add_lifetime_hooks(start, close)
示例#2
0
    def __init__(
        self,
        node: pyuavcan.application.Node,
        database_file: Optional[Union[str, pathlib.Path]] = None,
    ):
        """
        :param node:
            The node instance to run the allocator on.
            The 128-bit globally unique-ID of the local node will be sourced from this instance.
            Refer to the Specification for details.

        :param database_file:
            If provided, shall specify the path to the database file containing an allocation table.
            If the file does not exist, it will be automatically created. If None (default), the allocation table
            will be created in memory (therefore the allocation data will be lost after the instance is disposed).
        """
        self._node = node
        local_node_id = self.node.id
        if local_node_id is None:
            raise ValueError("The allocator cannot run on an anonymous node")
        # The database is initialized with ``check_same_thread=False`` to enable delegating its initialization
        # to a thread pool from an async context. This is important for this library because if one needs to
        # initialize a new instance from an async function, running the initialization directly may be unacceptable
        # due to its blocking behavior, so one is likely to rely on :meth:`asyncio.loop.run_in_executor`.
        # The executor will initialize the instance in a worker thread and then hand it over to the main thread,
        # which is perfectly safe, but it would trigger a false error from the SQLite engine complaining about
        # the possibility of concurrency-related bugs.
        self._alloc = _AllocationTable(
            sqlite3.connect(str(database_file or _DB_DEFAULT_LOCATION), timeout=_DB_TIMEOUT, check_same_thread=False)
        )
        self._alloc.register(local_node_id, self.node.info.unique_id.tobytes())
        self._sub1 = self.node.make_subscriber(NodeIDAllocationData_1)
        self._sub2 = self.node.make_subscriber(NodeIDAllocationData_2)
        self._pub1 = self.node.make_publisher(NodeIDAllocationData_1)
        self._pub2 = self.node.make_publisher(NodeIDAllocationData_2)
        self._pub1.send_timeout = self.DEFAULT_PUBLICATION_TIMEOUT
        self._pub2.send_timeout = self.DEFAULT_PUBLICATION_TIMEOUT

        def start() -> None:
            _logger.debug("Centralized allocator starting with the following allocation table:\n%s", self._alloc)
            self._sub1.receive_in_background(self._on_message)
            self._sub2.receive_in_background(self._on_message)

        def close() -> None:
            for port in [self._sub1, self._sub2, self._pub1, self._pub2]:
                assert isinstance(port, pyuavcan.presentation.Port)
                port.close()
            self._alloc.close()

        node.add_lifetime_hooks(start, close)
    def __init__(self, node: pyuavcan.application.Node) -> None:
        """
        :param node: The node instance to serve the register API for.
        """
        self._node = node

        srv_list = self.node.get_server(List)
        srv_access = self.node.get_server(Access)

        def start() -> None:
            srv_list.serve_in_background(self._handle_list)
            srv_access.serve_in_background(self._handle_access)

        def close() -> None:
            srv_list.close()
            srv_access.close()

        node.add_lifetime_hooks(start, close)
示例#4
0
    def __init__(self,
                 node: pyuavcan.application.Node,
                 level: int = logging.WARNING) -> None:
        self._pub = node.make_publisher(Record)
        self._pub.priority = pyuavcan.transport.Priority.OPTIONAL
        self._pub.send_timeout = 10.0

        self._fut: Optional[asyncio.Future[None]] = None
        self._forward_timestamp = False
        self._started = False
        super().__init__(level)

        def start() -> None:
            self._started = True

        def close() -> None:
            self._started = False
            self._pub.close()
            if self._fut is not None:
                self._fut.result()

        node.add_lifetime_hooks(start, close)
示例#5
0
    def __init__(self, node: pyuavcan.application.Node):
        self._node = node
        self._sub_heartbeat = self.node.make_subscriber(Heartbeat)

        self._registry: Dict[int, Entry] = {}
        self._offline_timers: Dict[int, asyncio.TimerHandle] = {}
        self._info_tasks: Dict[int, asyncio.Task[None]] = {}

        self._update_handlers: List[UpdateHandler] = []

        self._get_info_timeout = self.DEFAULT_GET_INFO_TIMEOUT
        self._get_info_attempts = self.DEFAULT_GET_INFO_ATTEMPTS

        def close() -> None:
            """
            When closed the registry is emptied and all handlers are removed.
            This is to avoid accidental reliance on obsolete data.
            """
            _logger.debug("Closing %s", self)
            self._sub_heartbeat.close()
            self._registry.clear()
            self._update_handlers.clear()

            for tm in self._offline_timers.values():
                tm.cancel()
            self._offline_timers.clear()

            for tsk in self._info_tasks.values():
                tsk.cancel()
            self._info_tasks.clear()

        node.add_lifetime_hooks(
            lambda: self._sub_heartbeat.receive_in_background(self.
                                                              _on_heartbeat),
            close,
        )
示例#6
0
    def __init__(
            self, node: pyuavcan.application.Node,
            roots: typing.Iterable[typing.Union[str, pathlib.Path]]) -> None:
        """
        :param node:
            The node instance to initialize the file server on.
            It shall not be anonymous, otherwise it's a
            :class:`pyuavcan.transport.OperationNotDefinedForAnonymousNodeError`.

        :param roots:
            All file operations will be performed in the specified directories.
            The first directory to match takes precedence.
            New files are created in the first directory.
        """
        self._roots = [pathlib.Path(x).resolve() for x in roots]

        # noinspection PyUnresolvedReferences
        self._data_transfer_capacity = int(
            pyuavcan.dsdl.get_model(Unstructured)["value"].data_type.capacity)

        s_ls = node.get_server(List)
        s_if = node.get_server(GetInfo)
        s_mo = node.get_server(Modify)
        s_rd = node.get_server(Read)
        s_wr = node.get_server(Write)

        def start() -> None:
            s_ls.serve_in_background(self._serve_ls)
            s_if.serve_in_background(self._serve_if)
            s_mo.serve_in_background(self._serve_mo)
            s_rd.serve_in_background(self._serve_rd)
            s_wr.serve_in_background(self._serve_wr)

        def close() -> None:
            s_ls.close()
            s_if.close()
            s_mo.close()
            s_rd.close()
            s_wr.close()

        node.add_lifetime_hooks(start, close)
示例#7
0
 def __init__(self, node: pyuavcan.application.Node):
     sub_record = node.make_subscriber(Record)
     node.add_lifetime_hooks(
         lambda: sub_record.receive_in_background(self._on_message),
         sub_record.close,
     )