maviola/sync/node/
ext.rs

1//! # 🔒 Synchronous I/O extensions for node
2
3use std::marker::PhantomData;
4use std::sync::Arc;
5use std::time::Duration;
6
7use crate::core::marker::{Edge, NodeKind, Proxy};
8use crate::core::node::{NodeBuilder, NodeConf};
9use crate::core::utils::Guarded;
10use crate::error::{NodeError, RecvResult, RecvTimeoutResult, TryRecvResult};
11use crate::protocol::{Peer, Unset};
12use crate::sync::marker::ConnConf;
13
14use crate::prelude::*;
15use crate::sync::prelude::*;
16
17impl Node<Proxy, Versionless, Unset> {
18    /// <sup>[`sync`](crate::sync)</sup>
19    /// Instantiate an empty [`NodeBuilder`] with specified MAVLink protocol version in asynchronous
20    /// mode.
21    ///
22    /// The version either should be specified using [turbofish](https://turbo.fish/about) syntax
23    /// or can be derived by Rust compiler.
24    pub fn sync<V: MaybeVersioned>() -> NodeBuilder<Unset, Unset, V, Unset, SyncApi<V>> {
25        NodeBuilder::synchronous().version::<V>()
26    }
27}
28
29impl<K: NodeKind, V: MaybeVersioned> Node<K, V, SyncApi<V>> {
30    /// <sup>[`sync`](crate::sync)</sup>
31    /// Instantiates node from synchronous configuration.
32    ///
33    /// Creates an instance of [`Node`] from [`NodeConf`].
34    pub fn try_from_conf(conf: NodeConf<K, V, ConnConf<V>>) -> Result<Self> {
35        let (conn, conn_handler) = conf.connection().build()?;
36
37        let processor = Arc::new(conf.make_processor());
38        let api = SyncApi::new(conn, processor.clone());
39
40        let state = api.share_state();
41        let is_active = Guarded::from(&state);
42
43        let node = Self {
44            kind: conf.kind,
45            api,
46            state,
47            is_active,
48            heartbeat_timeout: conf.heartbeat_timeout,
49            heartbeat_interval: conf.heartbeat_interval,
50            processor,
51            _version: PhantomData,
52        };
53
54        node.api.start_default_handlers(node.heartbeat_timeout);
55        node.api.handle_conn_stop(conn_handler);
56
57        Ok(node)
58    }
59
60    /// <sup>[`sync`](crate::sync)</sup>
61    /// Returns `true` if node has connected MAVLink peers.
62    ///
63    /// Disconnected node will always return `false`.
64    pub fn has_peers(&self) -> bool {
65        self.api.has_peers()
66    }
67
68    /// <sup>[`sync`](crate::sync)</sup>
69    /// Returns an iterator over current peers.
70    ///
71    /// This method will return a snapshot of the current peers relevant to the time when it was
72    /// called. A more reliable approach to peer management is to use [`Node::events`] and track
73    /// [`Event::NewPeer`] / [`Event::PeerLost`] events.
74    pub fn peers(&self) -> impl Iterator<Item = Peer> {
75        self.api.peers()
76    }
77
78    /// <sup>[`sync`](crate::sync)</sup>
79    /// Returns a reference to an event receiver.
80    ///
81    /// This receiver can be cloned and passed to other threads.
82    ///
83    /// **âš ** In order to have access to [`EventReceiver`] methods, you have to import
84    /// [`ReceiveEvent`] and [`ReceiveFrame`] traits. You may import [`sync::prelude`] as well.
85    ///
86    /// [`sync::prelude`]: crate::sync::prelude
87    #[inline(always)]
88    pub fn receiver(&self) -> &EventReceiver<V> {
89        self.api.event_receiver()
90    }
91
92    #[inline(always)]
93    pub(in crate::sync) fn frame_sender(&self) -> &FrameSender<V, Proxy> {
94        self.api.frame_sender()
95    }
96}
97
98impl<V: MaybeVersioned> Node<Proxy, V, SyncApi<V>> {
99    /// <sup>[`sync`](crate::sync)</sup>
100    /// Returns a new instance of a frame sender.
101    ///
102    /// Senders can be cloned and passed to other threads.
103    ///
104    /// Senders returned by [`Proxy`] nodes (i.e. [`ProxyNode`]) can't create frames from MAVLink
105    /// messages. This is only possible for [`Edge`] nodes ([`EdgeNode`]) with specified system and
106    /// component `ID`s.
107    pub fn sender(&self) -> FrameSender<V, Proxy> {
108        self.api.frame_sender().clone()
109    }
110}
111
112impl<V: MaybeVersioned> Node<Edge<V>, V, SyncApi<V>> {
113    /// <sup>[`sync`](crate::sync)</sup>
114    /// Returns a new instance of a frame sender that will use the same endpoint settings as the
115    /// parent node.
116    ///
117    /// Senders can be cloned and passed to other threads.
118    pub fn sender(&self) -> FrameSender<V, Edge<V>> {
119        self.api.frame_sender().clone().into_edge(self.kind.clone())
120    }
121}
122
123impl<V: Versioned> Node<Edge<V>, V, SyncApi<V>> {
124    /// <sup>[`sync`](crate::sync)</sup>
125    /// Activates the node.
126    ///
127    /// Active nodes emit heartbeats and perform other operations which do not depend on user
128    /// initiative directly.
129    ///
130    /// This method is available only for nodes which are [`Edge`] and [`Versioned`].
131    ///
132    /// [`Node::activate`] is idempotent while node is connected. Otherwise, it will return
133    /// [`NodeError::Inactive`] variant of [`Error::Node`].
134    pub fn activate(&mut self) -> Result<()> {
135        if self.state.is_closed() {
136            return Err(Error::Node(NodeError::Inactive));
137        }
138
139        if self.is_active.is() {
140            return Ok(());
141        }
142
143        self.is_active.set(true);
144
145        self.api.start_sending_heartbeats(
146            self.kind.endpoint.clone(),
147            self.heartbeat_interval,
148            self.is_active.clone(),
149            self.dialect().version(),
150        );
151
152        Ok(())
153    }
154}
155
156impl<K: NodeKind, V: MaybeVersioned> ReceiveEvent<V> for Node<K, V, SyncApi<V>> {
157    #[inline(always)]
158    fn recv(&self) -> RecvResult<Event<V>> {
159        self.receiver().recv()
160    }
161
162    #[inline(always)]
163    fn recv_timeout(&self, timeout: Duration) -> RecvTimeoutResult<Event<V>> {
164        self.receiver().recv_timeout(timeout)
165    }
166
167    #[inline(always)]
168    fn try_recv(&self) -> TryRecvResult<Event<V>> {
169        self.receiver().try_recv()
170    }
171
172    #[inline(always)]
173    fn events(&self) -> impl Iterator<Item = Event<V>> {
174        self.receiver().events()
175    }
176}
177
178impl<K: NodeKind, V: MaybeVersioned> ReceiveFrame<V> for Node<K, V, SyncApi<V>> {}