Skip to main content

embedded_nano_mesh/mesh_lib/node/
mod.rs

1mod constants;
2mod packet;
3mod receiver;
4mod router;
5mod timer;
6mod transmitter;
7mod types;
8
9pub use packet::{
10    ExactAddressType, GeneralAddressType, IdType, LifeTimeType, Packet, PacketDataBytes,
11};
12
13use types::PacketQueue;
14pub use types::{ms, NodeString};
15
16use self::router::{RouteError, RouteResult, Router};
17
18/// The main and only structure of the library that brings API for
19/// communication trough the mesh network.
20/// It works in the manner of listening of ether for
21/// specified period of time, which is called `listen_period`,
22/// and then sending out packets out of queues between those periods.
23///
24/// Also node resends caught packets, that were addressed to other
25/// nodes.
26///
27/// It has next methods:
28/// * `new` -                   Creates new instance of `Node`.
29/// * `send_to_exact` -         Sends the `data` to exact device. Call of this method does not provide any
30///                             response back.
31/// * `broadcast` -             Sends the `data` to all devices. Call of this method does not provide any
32///                             response back.
33/// * `update` -                Updates the state of the node. This method should be called in
34///                             every loop iteration.
35pub struct Node {
36    transmitter: transmitter::Transmitter,
37    receiver: receiver::Receiver,
38    my_address: ExactAddressType,
39    timer: timer::Timer,
40    received_packet_queue: PacketQueue,
41    router: Router,
42}
43
44/// Error that can be returned by `Node` `update` method.
45pub struct NodeUpdateError {
46    /// Whether the received packet queue is full, meaning that a packet
47    /// addressed to this node could not be stored.
48    pub is_receive_queue_full: bool,
49    /// Whether the transit queue is full, meaning that a packet addressed
50    /// to another node could not be scheduled for forwarding.
51    pub is_transit_queue_full: bool,
52}
53
54/// Error that can be returned by `Node` `send` method or `broadcast` method.
55pub enum SendError {
56    /// The sending queue is full. Retry sending later.
57    SendingQueueIsFull,
58}
59
60impl core::fmt::Debug for SendError {
61    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62        match self {
63            SendError::SendingQueueIsFull => write!(f, "SendingQueueIsFull"),
64        }
65    }
66}
67
68/// User-friendly `Node` configuration structure.
69pub struct NodeConfig {
70    /// Address of configurable device. Instance of `ExactAddressType`.
71    pub device_address: ExactAddressType,
72
73    /// Instance of `ms` type. The time period in
74    /// milliseconds that configured device will listen for incoming packets
75    /// before speaking back into the ether.
76    pub listen_period: ms,
77}
78
79impl Node {
80    /// New Method
81    /// To initialize a `Node`, you need to provide `NodeConfig` with values:
82    /// - `ExactAddressType`: Sets the device's identification address in the network. Multiple deivces can share same address in the same network.
83    /// - `listen_period`: Sets period in milliseconds that determines how long the device will wait before transmitting packet to the network. It prevents network congestion.
84
85    /// `main.rs`:
86    /// ```ignore
87    /// let mut mesh_node = Node::new(NodeConfig {
88    ///     device_address: ExactAddressType::new(1).unwrap(),
89    ///     listen_period: 150 as ms,
90    /// });
91    /// ```
92    pub fn new(config: NodeConfig) -> Node {
93        Node {
94            transmitter: transmitter::Transmitter::new(),
95            receiver: receiver::Receiver::new(),
96            my_address: config.device_address.clone(),
97            timer: timer::Timer::new(config.listen_period),
98            received_packet_queue: PacketQueue::new(),
99            router: Router::new(config.device_address.into()),
100        }
101    }
102
103    /// Send to exact Method
104    /// Sends the message to device with exact address in the network.
105    /// The `send_to_exact` method requires the following arguments:
106    ///
107    /// `main.rs`:
108    /// ```ignore
109    /// let _ = match mesh_node.send_to_exact(
110    ///     message.into_bytes(),              // Content.
111    ///     ExactAddressType::new(2).unwrap(), // Send to device with address 2.
112    ///     10 as LifeTimeType, // Let message travel 10 devices before being destroyed.
113    ///     true, // filter_out_duplication
114    /// );
115    /// ```
116    ///
117    /// * `data` - Is the instance of `PacketDataBytes`, which is just type alias of
118    /// heapless vector of bytes of special size. This size is configured in the
119    /// node/packet/config.rs file.
120    /// `Note!` That all devices should have same version of protocol flashed, in order to
121    /// have best compatibility with each other.
122    ///
123    /// * `destination_device_identifier` is instance of `ExactAddressType`,
124    /// That type is made to limit possible mess-ups during the usage of method.
125    ///
126    /// * `lifetime` - is the instance of `LifeTimeType`. This value configures the count of
127    /// how many nodes - the packet will be able to pass. Also this value is provided
128    /// to void the ether being jammed by packets, that in theory might be echoed
129    /// by other nodes to the infinity...
130    /// Each device, once passes transit packet trough it - it reduces packet's lifetime.
131    ///
132    /// * `filter_out_duplication` - Tells if the other devices shall ignore
133    /// echoes of this message. It is strongly recommended to use in order to make lower load
134    /// onto the network.
135    pub fn send_to_exact(
136        &mut self,
137        data: PacketDataBytes,
138        destination_device_identifier: ExactAddressType,
139        lifetime: LifeTimeType,
140        filter_out_duplication: bool,
141    ) -> Result<(), SendError> {
142        match self._send(Packet::new(
143            self.my_address.into(),
144            destination_device_identifier.into(),
145            0, // Anyway it will be set later in the trasmitter.
146            lifetime,
147            filter_out_duplication,
148            data,
149        )) {
150            Ok(_) => Ok(()),
151            Err(err) => Err(err),
152        }
153    }
154
155    /// Broadcast Method
156    /// Shares the message to all nodes in the network.
157    /// Distance of sharing is set by `lifetime` parameter.
158    /// It sends packet with destination address set as
159    /// `GeneralAddressType::BROADCAST`. Every device will treats `GeneralAddressType::Broadcast`
160    /// as it's own address, so they keep the message as received and transits copy of that message further.
161    /// `main.rs`:
162    /// ```ignore
163    /// let _ = mesh_node.broadcast(
164    ///     message.into_bytes(), // data.
165    ///     10 as LifeTimeType,   // lifetime.
166    /// );
167    /// ```
168    /// Sends the `data` to all devices.
169    ///
170    /// * `data` - Is the instance of `PacketDataBytes`, which is just type alias of
171    /// heapless vector of bytes of special size. This size is configured in the
172    /// node/packet/config.rs file.
173    /// `Note!` That all devices should have same version of protocol flashed, in order to
174    /// be able to correctly to communicate with each other.
175    ///
176    /// * `lifetime` - is the instance of `LifeTimeType`. This value configures the count of
177    /// how many nodes - the packet will be able to pass. Also this value is provided
178    /// to void the ether being jammed by packets, that in theory might be echoed
179    /// by other nodes to the infinity...
180    /// Each device, once passes transit packet trough it - it reduces packet's lifetime.
181    pub fn broadcast(
182        &mut self,
183        data: PacketDataBytes,
184        lifetime: LifeTimeType,
185    ) -> Result<(), SendError> {
186        match self._send(Packet::new(
187            self.my_address.into(),
188            GeneralAddressType::Broadcast.into(),
189            0,
190            lifetime,
191            true,
192            data,
193        )) {
194            Ok(_) => Ok(()),
195            Err(err) => Err(err),
196        }
197    }
198
199    fn _send(&mut self, packet: Packet) -> Result<IdType, SendError> {
200        match self.transmitter.send(packet) {
201            Ok(generated_packet_id) => Ok(generated_packet_id),
202            Err(transmitter::PacketQueueIsFull) => Err(SendError::SendingQueueIsFull),
203        }
204    }
205
206    /// Receive Method
207    /// Optionally returns `PacketDataBytes` instance with data,
208    /// which has been send exactly to this device, or has been
209    /// `broadcast`ed trough all the network.
210    ///
211    /// `main.rs`:
212    /// ```ignore
213    /// match mesh_node.receive() {
214    ///     Some(packet) => ...,
215    ///     Node => ....,
216    /// }
217    /// ```
218
219    pub fn receive(&mut self) -> Option<Packet> {
220        self.received_packet_queue.pop_front()
221    }
222
223    /// Update Method
224    /// The most important method.
225    /// During call of `update` method - it does all internal work:
226    /// - routes packets trough the network
227    /// - transits packets that were sent to other devices
228    /// - handles `lifetime` of packets
229    /// - saves received packets that will be available trough `receive` method.
230    /// - sends packets, that are in the `send` queue.
231    ///
232    /// As the protocol relies on physical device - it is crucial to provide
233    /// driver for communication interface.
234    /// Also node shall know if it's the time to broadcast into the ether or not,
235    /// so for that purpose the closure that counts milliseconds since program start
236    /// is required.
237    ///
238    /// With out call this method in a loop - the node will stop working.
239    ///
240    ///`main.rs`:
241    ///```ignore
242    /// loop {
243    ///    let current_time = Instant::now()
244    ///        .duration_since(program_start_time)
245    ///        .as_millis() as ms;
246    ///
247    ///    let _ = mesh_node.update(&mut serial, current_time);
248    /// }
249    ///```
250
251    /// Does all necessary internal work of mesh node:
252    /// * Receives packets from ether, and manages their further life.
253    ///     ** Data that is addressed to other devices are going to be send back into ether.
254    ///     ** Data addressed to current device, will be unpacked and stored.
255    ///
256    /// * Call of this method also requires the general types to be passed in.
257    /// As the process relies onto timing countings and onto serial stream,
258    ///
259    /// parameters:
260    /// * `interface_driver` - is instance of `MutNonBlockingRx` and `MutBlockingTx`
261    /// traits.
262    ///
263    /// * `current_time` - Is a closure which returns current time in milliseconds
264    /// since the start of the program.
265    pub fn update<I>(
266        &mut self,
267        interface_driver: &mut I,
268        current_time: ms,
269    ) -> Result<(), NodeUpdateError>
270    where
271        I: embedded_io::ReadReady + embedded_io::Read + embedded_io::Write,
272    {
273        if self.timer.is_time_to_speak(current_time) {
274            self.transmitter.update(interface_driver);
275            self.timer.record_speak_time(current_time);
276        }
277        self.receiver.update(current_time, interface_driver);
278
279        let packet_to_route = match self.receiver.receive(current_time) {
280            Some(packet_to_handle) => packet_to_handle,
281            None => return Ok(()),
282        };
283
284        let (received_packet, transit_packet) = match self.router.route(packet_to_route) {
285            Ok(ok_case) => match ok_case {
286                RouteResult::ReceivedOnly(packet) => (Some(packet), None),
287                RouteResult::TransitOnly(transit) => (None, Some(transit)),
288                RouteResult::ReceivedAndTransit { received, transit } => {
289                    (Some(received), Some(transit))
290                }
291            },
292            Err(RouteError::PacketLifetimeEnded) => (None, None),
293        };
294
295        let (mut is_receive_queue_full, mut is_transit_queue_full): (bool, bool) = (false, false);
296
297        if let Some(received_packet) = received_packet {
298            match self.received_packet_queue.push_back(received_packet) {
299                Ok(()) => (),
300                Err(_) => {
301                    is_receive_queue_full = true;
302                }
303            }
304        }
305
306        if let Some(transit_packet) = transit_packet {
307            match self.transmitter.send_transit(transit_packet) {
308                Ok(_) => (),
309                Err(transmitter::PacketTransitQueueIsFull) => {
310                    is_transit_queue_full = true;
311                }
312            }
313        }
314
315        if is_receive_queue_full || is_transit_queue_full {
316            return Err(NodeUpdateError {
317                is_receive_queue_full,
318                is_transit_queue_full,
319            });
320        } else {
321            Ok(())
322        }
323    }
324}