ndn_face_serial/
serial.rs

1use ndn_transport::{FaceId, FaceKind};
2
3#[cfg(feature = "serial")]
4use crate::cobs::CobsCodec;
5
6/// NDN face over a serial port with COBS framing.
7///
8/// COBS (Consistent Overhead Byte Stuffing) provides reliable frame
9/// resynchronisation after line noise — a `0x00` byte never appears in the
10/// encoded payload, so re-sync is just a matter of waiting for the next `0x00`.
11///
12/// Suitable for: UART sensor nodes, LoRa radio modems, RS-485 industrial buses.
13///
14/// Uses [`StreamFace`](ndn_transport::StreamFace) with serial read/write halves
15/// and [`CobsCodec`].  LP-encoding is enabled for network transport.
16#[cfg(feature = "serial")]
17pub type SerialFace = ndn_transport::StreamFace<
18    tokio::io::ReadHalf<tokio_serial::SerialStream>,
19    tokio::io::WriteHalf<tokio_serial::SerialStream>,
20    CobsCodec,
21>;
22
23/// Open a serial port and wrap it as an NDN [`SerialFace`].
24#[cfg(feature = "serial")]
25pub fn serial_face_open(
26    id: FaceId,
27    port: impl Into<String>,
28    baud: u32,
29) -> std::io::Result<SerialFace> {
30    let port = port.into();
31    let builder = tokio_serial::new(&port, baud);
32    let stream = tokio_serial::SerialStream::open(&builder)?;
33    let (r, w) = tokio::io::split(stream);
34    let uri = format!("serial://{}", port);
35    Ok(ndn_transport::StreamFace::new(
36        id,
37        FaceKind::Serial,
38        true,
39        Some(uri.clone()),
40        Some(uri),
41        r,
42        w,
43        CobsCodec::new(),
44    ))
45}
46
47// ─── Fallback when `serial` feature is disabled ────────────────────────────
48
49#[cfg(not(feature = "serial"))]
50use bytes::Bytes;
51#[cfg(not(feature = "serial"))]
52use ndn_transport::{Face, FaceError};
53
54#[cfg(not(feature = "serial"))]
55pub struct SerialFace {
56    id: FaceId,
57    #[allow(dead_code)]
58    port: String,
59    #[allow(dead_code)]
60    baud: u32,
61}
62
63#[cfg(not(feature = "serial"))]
64impl SerialFace {
65    pub fn new(id: FaceId, port: impl Into<String>, baud: u32) -> Self {
66        Self {
67            id,
68            port: port.into(),
69            baud,
70        }
71    }
72}
73
74#[cfg(not(feature = "serial"))]
75impl Face for SerialFace {
76    fn id(&self) -> FaceId {
77        self.id
78    }
79    fn kind(&self) -> FaceKind {
80        FaceKind::Serial
81    }
82
83    async fn recv(&self) -> Result<Bytes, FaceError> {
84        Err(FaceError::Closed)
85    }
86
87    async fn send(&self, _pkt: Bytes) -> Result<(), FaceError> {
88        Err(FaceError::Closed)
89    }
90}