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}