pamoja_gateway/lib.rs
1//! LoRaWAN gateway protocols for the pamoja SDK.
2//!
3//! A LoRa gateway is a radio with an uplink: it hears packets from every node in range and
4//! hands them to a network server, which hands back the packets to transmit. The protocol
5//! between the two is not LoRaWAN, which is what the packets themselves carry; it is a
6//! separate, deliberately plain exchange of UDP datagrams, and this crate speaks it from
7//! both sides.
8//!
9//! - [`udp`] - the Semtech packet forwarder protocol: the PUSH_DATA and PULL_DATA datagrams a
10//! gateway sends, the PUSH_ACK, PULL_ACK and PULL_RESP a server answers with, the TX_ACK
11//! that reports what became of a downlink, and the `rxpk`, `stat`, `txpk` and `txpk_ack`
12//! objects they carry.
13//! - [`base64`] - the payload encoding of RFC 4648, padded on the way out and read either
14//! way on the way in, because gateways in the field send both.
15//! - [`time`] - the two timestamp formats the protocol prescribes, to the microsecond for a
16//! reception and to the second for a gateway's own clock.
17//! - `network`, with the `network` feature - the network side of one site: admitting a join,
18//! reading an uplink, and working out where and when to answer it.
19//! - `bridge`, with the `bridge` feature - carrying messages between the radio the nodes are
20//! on and the link that leaves the site, under a prefix that names the site.
21//!
22//! Every datagram is data: the crate builds and parses them, and leaves the socket, the
23//! keepalive, and the scheduling to the program that owns them.
24//!
25//! # Examples
26//!
27//! A gateway forwards one packet it heard, and the server acknowledges it.
28//!
29//! ```
30//! use pamoja_gateway::udp::{Eui, Packet, Rxpk, Uplink};
31//! use pamoja_lora::LinkSettings;
32//!
33//! let gateway = Eui::new([0xB8, 0x27, 0xEB, 0xFF, 0xFE, 0x01, 0x02, 0x03]);
34//! let heard = Rxpk::new(868_100_000, LinkSettings::new(7, 125_000), b"hello".to_vec())
35//! .with_rssi_dbm(-35)
36//! .with_snr_db(5.1);
37//! let push = Packet::PushData {
38//! token: 0x1234,
39//! gateway,
40//! uplink: Uplink::from(heard),
41//! };
42//!
43//! let datagram = push.to_bytes();
44//! assert_eq!(&datagram[..4], &[2, 0x12, 0x34, 0x00]);
45//!
46//! // The server reads it and answers with the same token.
47//! let received = Packet::parse(&datagram).expect("the datagram is well formed");
48//! let ack = received.acknowledgment().expect("a PUSH_DATA is acknowledged");
49//! assert_eq!(ack.to_bytes(), [2, 0x12, 0x34, 0x01]);
50//! ```
51
52pub mod base64;
53#[cfg(feature = "bridge")]
54pub mod bridge;
55#[cfg(feature = "network")]
56pub mod network;
57pub mod time;
58pub mod udp;