Skip to main content

pamoja_lorawan/device/
mod.rs

1//! A LoRaWAN Class A end device, without a radio.
2//!
3//! [`EndDevice`] is what a node runs to take part in a network: it joins, chooses a channel
4//! and data rate for each uplink, says when and where to listen for the answer, reads what
5//! comes back, and does what the network's MAC commands ask. It owns no radio and no clock.
6//! Every step takes the time in microseconds and hands back what to put on the air, so the
7//! same logic drives an SX1276 on a microcontroller, an SX1262 on a Linux board, or a test
8//! with no hardware at all.
9//!
10//! One exchange runs like this:
11//!
12//! 1. [`join`](EndDevice::join) or [`send`](EndDevice::send) returns a [`Transmission`]:
13//!    the frame, the carrier, the link, the power, and the two receive windows, each timed
14//!    from the end of the transmission.
15//! 2. The radio sends it, then listens in the first window and, if nothing for this device
16//!    arrived, in the second.
17//! 3. A frame heard in either window goes to [`heard_in`](EndDevice::heard_in), which knows
18//!    the window, or to [`heard`](EndDevice::heard). If neither window held one,
19//!    [`nothing_heard`](EndDevice::nothing_heard) says whether to send the same frame again,
20//!    with [`repeat`](EndDevice::repeat), or move on.
21//!
22//! What it follows, and from where:
23//!
24//! - **Receive windows**: TS001-1.0.4 section 3.3 and RP002-1.0.5 section 3.3, one second and
25//!   two after an uplink and five and six after a join request unless the network moves them.
26//! - **Channels and data rates**: the region's plan from `pamoja-lora`, a join accept's
27//!   channel list, and `LinkADRReq`, `NewChannelReq` and `DlChannelReq`. A fixed plan answers
28//!   each channel on the downlink channel it names, and reads `ChMaskCntl` by its own table.
29//! - **Joining**: a random join channel with the data rate stepping down across attempts, or
30//!   on US902-928 and AU915-928 the passes of RP002-1.0.5 section 3.5.2, eight 125 kHz
31//!   channels from successive groups and then a 500 kHz one. On CN470-510 the common join
32//!   channel that answered puts the device on its plan, section 3.9.2.
33//! - **MAC commands**: every command of TS001-1.0.4 section 5 a device receives, answered in
34//!   order, with the four that change how it listens repeated until a downlink arrives.
35//! - **Downlinks**: TS001-1.0.4 section 4, with a frame whose MACPayload is longer than the
36//!   receive window's data rate carries discarded, and a repeated counter ignored.
37//! - **Repetition**: NbTrans transmissions of each uplink, stopped by any Class A downlink,
38//!   and a retransmission timeout before the next uplink whenever a confirmed one went
39//!   unacknowledged.
40//! - **Staying reachable**: the adaptive data rate back-off of [`adr`](crate::adr).
41//! - **Sharing the air**: the region's sub-band duty cycles, the network's `DutyCycleReq`,
42//!   and the join back-off of TS001-1.0.4 section 7.
43//! - **Sleeping**: [`save`](EndDevice::save) and [`resume`](EndDevice::resume) carry a joined
44//!   device across a loss of power, so a node that sleeps between readings keeps its session,
45//!   its counters and everything its network set.
46//! - **Out of a gateway's reach**: [`use_relay`](EndDevice::use_relay) sends through a
47//!   LoRaWAN relay, TS011-1.0.1. Each uplink then goes out behind a wake-on-radio frame,
48//!   [`Transmission::relay`] says when and with how long a preamble, and a third receive
49//!   window carries what the relay forwards back.
50//!
51//! This covers every published plan: the dynamic EU868, EU433, AS923, KR920, IN865 and RU864,
52//! and the fixed US915, AU915 and CN470, the last in all four of its RP002-1.0.5 plans and the
53//! 96-channel plan before them. KR920, CN470, and AS923 where ARIB STD-T108 applies also
54//! require listening before talking, which is the radio's to do.
55//!
56//! # Examples
57//!
58//! A device joins a European network the test plays the part of:
59//!
60//! ```
61//! use pamoja_lora::region::Region;
62//! use pamoja_lorawan::device::{EndDevice, Heard, Settings};
63//! use pamoja_lorawan::{Device, JoinGrant};
64//!
65//! const APP_KEY: [u8; 16] = [0x2B; 16];
66//! let credentials = Device::new([0x11; 8], [0x22; 8], APP_KEY);
67//! let mut device = EndDevice::new(Region::Eu868.plan(), credentials, Settings::new(2, 14))?;
68//!
69//! // The request goes out on a European default channel, and the answer is due five and
70//! // six seconds after it.
71//! let request = device.join(1, 0)?;
72//! assert!([868_100_000, 868_300_000, 868_500_000].contains(&request.frequency_hz));
73//! assert_eq!(request.rx1.delay_us, 5_000_000);
74//! assert_eq!(request.rx2.frequency_hz, 869_525_000);
75//!
76//! // The network's accept arrives in the first window.
77//! let accept = JoinGrant::new(0x01, 0x13, 0x2601_2E43).accept(&APP_KEY, 1);
78//! let heard = device.heard(accept.as_bytes(), 7)?;
79//! assert_eq!(heard, Heard::Joined { dev_addr: 0x2601_2E43 });
80//!
81//! // And the first reading goes out, answered a second after it ends.
82//! let reading = device.send(2, b"21.5", false, 7_000_000)?;
83//! assert_eq!(reading.rx1.delay_us, 1_000_000);
84//! assert!(reading.carries_payload);
85//! # Ok::<(), pamoja_lorawan::device::DeviceError>(())
86//! ```
87
88mod air;
89mod answers;
90mod channels;
91mod commands;
92mod relayed;
93mod state;
94
95pub use channels::{Channel, MAX_CHANNELS};
96pub use relayed::{AckWindow, RelayExchange, RelayStatus, WakeUp, WorNext};
97pub use state::{Saved, StateError, SAVED_LEN};
98
99use pamoja_lora::region::{ChannelBlock, ChannelPlan, JoinSequence, Modulation, PowerReference};
100use pamoja_lora::LinkSettings;
101
102use crate::adr::{Backoff, Standing, Step};
103use crate::defaults::{
104    JOIN_ACCEPT_DELAY1_US, JOIN_ACCEPT_DELAY2_US, MAX_FCNT_GAP, RECEIVE_DELAY1_US,
105    RETRANSMIT_TIMEOUT_MAX_US, RETRANSMIT_TIMEOUT_MIN_US,
106};
107use crate::mac::{MacCommand, FOPTS_MAX};
108use crate::relay::{smart_enable_uplinks, Carrier, RelayState};
109use crate::{
110    Device, FrameHeader, LorawanError, MessageType, PhyPayload, Session, Uplink, Version,
111    MAX_PAYLOAD,
112};
113use air::{Air, Sequence, MAX_SUB_BANDS};
114use answers::Answers;
115use channels::{Channels, MASK_GROUPS};
116use relayed::Relayed;
117
118/// How long a transmission may hold a channel under a dwell time limit, from RP002-1.0.5
119/// section 3.3 and TS001-1.0.4 table 49.
120const DWELL_LIMIT_US: u64 = 400_000;
121
122/// What a device's radio can do, and how it takes part.
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub struct Settings {
125    version: Version,
126    adr: bool,
127    min_output_dbm: i8,
128    max_output_dbm: i8,
129    antenna_gain_db: i8,
130    lowest_hz: u32,
131    highest_hz: u32,
132    regional_duty_cycle: bool,
133    behind_repeater: bool,
134    crystal_ppm: u32,
135    seed: u32,
136}
137
138impl Settings {
139    /// Settings for a radio with an output power range.
140    ///
141    /// The rest start as a typical node: TS001-1.0.4, adaptive data rate on, an antenna
142    /// with no gain over its cable, a radio that tunes 137 to 1020 MHz as an SX1276 does,
143    /// the region's duty cycle kept, and no repeater in the path.
144    ///
145    /// # Arguments
146    ///
147    /// * `min_output_dbm` - the lowest power the radio puts out, conducted.
148    /// * `max_output_dbm` - the highest, conducted.
149    ///
150    /// # Returns
151    ///
152    /// The settings.
153    pub const fn new(min_output_dbm: i8, max_output_dbm: i8) -> Settings {
154        Settings {
155            version: Version::V1_0_4,
156            adr: true,
157            min_output_dbm,
158            max_output_dbm,
159            antenna_gain_db: 0,
160            lowest_hz: 137_000_000,
161            highest_hz: 1_020_000_000,
162            regional_duty_cycle: true,
163            behind_repeater: false,
164            crystal_ppm: 20,
165            seed: 0,
166        }
167    }
168
169    /// Sets how far the device's own clock may drift.
170    ///
171    /// It decides how much preamble a wake-on-radio frame needs to still cover a relay's
172    /// scan, TS011-1.0.1 appendix 1. The default is the 20 parts per million of a typical
173    /// temperature-compensated crystal.
174    ///
175    /// # Arguments
176    ///
177    /// * `crystal_ppm` - the accuracy in parts per million.
178    ///
179    /// # Returns
180    ///
181    /// The settings.
182    pub const fn with_crystal_ppm(mut self, crystal_ppm: u32) -> Settings {
183        self.crystal_ppm = crystal_ppm;
184        self
185    }
186
187    /// Follows another revision of the link layer.
188    ///
189    /// # Arguments
190    ///
191    /// * `version` - the revision the network was told this device follows.
192    ///
193    /// # Returns
194    ///
195    /// The settings.
196    pub const fn with_version(mut self, version: Version) -> Settings {
197        self.version = version;
198        self
199    }
200
201    /// Turns adaptive data rate on or off.
202    ///
203    /// With it on, the device sets the ADR bit, takes the data rate and power the network
204    /// chooses, and backs off when the network goes quiet. With it off, the device keeps its
205    /// own data rate and TS001-1.0.4 section 5.2 lets it accept a `LinkADRReq` one field at
206    /// a time.
207    ///
208    /// # Arguments
209    ///
210    /// * `adr` - whether the network manages the data rate.
211    ///
212    /// # Returns
213    ///
214    /// The settings.
215    pub const fn with_adr(mut self, adr: bool) -> Settings {
216        self.adr = adr;
217        self
218    }
219
220    /// Accounts for the antenna and its feed.
221    ///
222    /// Most regions limit radiated power, so a device with a 3 dBi antenna puts out 3 dB less
223    /// than one with a 0 dBi antenna to radiate the same. US902-928 limits conducted power
224    /// instead, and only the gain above the 6 dBi its limit allows for comes off.
225    ///
226    /// # Arguments
227    ///
228    /// * `gain_db` - the antenna gain less the cable and connector losses, in dB.
229    ///
230    /// # Returns
231    ///
232    /// The settings.
233    pub const fn with_antenna_gain(mut self, gain_db: i8) -> Settings {
234        self.antenna_gain_db = gain_db;
235        self
236    }
237
238    /// Sets the frequencies the radio and its front end can use.
239    ///
240    /// A network that asks for a channel or a receive window outside them is told so.
241    ///
242    /// # Arguments
243    ///
244    /// * `lowest_hz` - the lowest usable frequency.
245    /// * `highest_hz` - the highest.
246    ///
247    /// # Returns
248    ///
249    /// The settings.
250    pub const fn with_tuning_range(mut self, lowest_hz: u32, highest_hz: u32) -> Settings {
251        self.lowest_hz = lowest_hz;
252        self.highest_hz = highest_hz;
253        self
254    }
255
256    /// Stops holding the device to the region's sub-band duty cycles.
257    ///
258    /// The regional tables report a limit rather than enforce one, because the operator is
259    /// the one who knows whether a regulation applies where the device stands. The network's
260    /// `DutyCycleReq` and the join back-off still hold.
261    ///
262    /// # Returns
263    ///
264    /// The settings.
265    pub const fn without_regional_duty_cycle(mut self) -> Settings {
266        self.regional_duty_cycle = false;
267        self
268    }
269
270    /// Sizes payloads for a path through a relay, which costs a few bytes of each frame.
271    ///
272    /// # Returns
273    ///
274    /// The settings.
275    pub const fn behind_repeater(mut self) -> Settings {
276        self.behind_repeater = true;
277        self
278    }
279
280    /// Seeds the device's random choices of channel and retry delay.
281    ///
282    /// The device identifier is mixed in, so devices given the same seed still differ.
283    ///
284    /// # Arguments
285    ///
286    /// * `seed` - any value, ideally from a hardware random source.
287    ///
288    /// # Returns
289    ///
290    /// The settings.
291    pub const fn with_seed(mut self, seed: u32) -> Settings {
292        self.seed = seed;
293        self
294    }
295
296    /// Reports whether the radio can tune a frequency.
297    pub(crate) const fn usable(&self, hz: u32) -> bool {
298        hz >= 100_000_000 && hz >= self.lowest_hz && hz <= self.highest_hz
299    }
300}
301
302/// How a device reports its battery when a network asks.
303#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
304pub enum Battery {
305    /// Running from an external supply.
306    External,
307    /// A level from 1, empty, to 254, full. Values outside that range are clamped into it.
308    Level(u8),
309    /// The device cannot measure it.
310    #[default]
311    Unknown,
312}
313
314impl Battery {
315    /// The byte `DevStatusAns` carries, from TS001-1.0.4 table 32.
316    const fn code(self) -> u8 {
317        match self {
318            Battery::External => 0,
319            Battery::Level(level) => {
320                if level == 0 {
321                    1
322                } else if level == 255 {
323                    254
324                } else {
325                    level
326                }
327            }
328            Battery::Unknown => 255,
329        }
330    }
331}
332
333/// A frame to put on the air, and where to listen afterward.
334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
335pub struct Transmission {
336    /// The frame.
337    pub frame: PhyPayload,
338    /// The carrier, in hertz.
339    pub frequency_hz: u32,
340    /// The data rate, as the region numbers them.
341    pub data_rate: u8,
342    /// The LoRa settings that data rate stands for: an eight-symbol preamble, an explicit
343    /// header and a payload CRC, sent with standard IQ.
344    pub link: LinkSettings,
345    /// The power to ask of the radio, conducted, with the antenna gain taken off as the
346    /// region's power limit requires.
347    pub output_dbm: i8,
348    /// How long the frame holds the air, in microseconds.
349    pub airtime_us: u64,
350    /// The first receive window.
351    pub rx1: Window,
352    /// The second, which opens only if nothing for this device arrived in the first.
353    pub rx2: Window,
354    /// Whether the application payload went out in this frame.
355    ///
356    /// It is held back when the answers a device owes the network do not leave room for
357    /// it, since TS001-1.0.4 table 15 sends answers first. Send it again afterward.
358    pub carries_payload: bool,
359    /// The wake-on-radio exchange that goes ahead of this frame under a relay, and the
360    /// window a forwarded downlink comes back in.
361    ///
362    /// With it, the frame goes out at
363    /// [`uplink_start_us`](RelayExchange::uplink_start_us) rather than straight away, and
364    /// the two windows above are still timed from the end of it.
365    pub relay: Option<RelayExchange>,
366}
367
368/// When and where to listen for a downlink.
369#[derive(Clone, Copy, Debug, PartialEq, Eq)]
370pub struct Window {
371    /// How long after the end of the transmission the window opens, in microseconds.
372    pub delay_us: u32,
373    /// The carrier, in hertz.
374    pub frequency_hz: u32,
375    /// The downlink data rate, as the region numbers them.
376    pub data_rate: u8,
377    /// The LoRa settings to listen with: no payload CRC, and inverted IQ, as RP002-1.0.5
378    /// table 112 has for a downlink.
379    pub link: LinkSettings,
380}
381
382/// Which receive window a frame arrived in.
383#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
384pub enum ReceiveWindow {
385    /// The first window, on the uplink's downlink channel.
386    Rx1,
387    /// The second, on the fixed frequency and data rate.
388    Rx2,
389    /// The relay window, which a device under a relay opens last when neither of the other
390    /// two held a downlink for it, TS011-1.0.1 chapter 7.
391    Rxr,
392}
393
394/// What a frame heard in a receive window turned out to be.
395// The delivery holds its payload inline, since the crate runs without an allocator.
396#[allow(clippy::large_enum_variant)]
397#[derive(Clone, Copy, Debug, PartialEq, Eq)]
398pub enum Heard {
399    /// A join accept: the device is on the network.
400    Joined {
401        /// The address the network gave it.
402        dev_addr: u32,
403    },
404    /// A data frame for this device.
405    Data(Delivery),
406}
407
408/// A downlink, read and acted on.
409#[derive(Clone, Copy, Debug, PartialEq, Eq)]
410pub struct Delivery {
411    port: Option<u8>,
412    payload: [u8; MAX_PAYLOAD],
413    len: usize,
414    acknowledged: bool,
415    confirmed: bool,
416    more_pending: bool,
417    link_check: Option<LinkCheck>,
418    device_time: Option<DeviceTime>,
419}
420
421impl Delivery {
422    /// Returns the application port the payload arrived on.
423    ///
424    /// # Returns
425    ///
426    /// The port, or `None` for a frame that carried only MAC commands or nothing.
427    pub fn port(&self) -> Option<u8> {
428        self.port
429    }
430
431    /// Returns the application payload, decrypted.
432    ///
433    /// # Returns
434    ///
435    /// The bytes, empty when the frame carried none for the application.
436    pub fn payload(&self) -> &[u8] {
437        &self.payload[..self.len]
438    }
439
440    /// Reports whether the network acknowledged the confirmed uplink this answered.
441    ///
442    /// # Returns
443    ///
444    /// `true` for an acknowledgment of a confirmed uplink.
445    pub fn acknowledged(&self) -> bool {
446        self.acknowledged
447    }
448
449    /// Reports whether the network asked for this downlink to be acknowledged.
450    ///
451    /// The device sets the acknowledgment on its next uplink by itself. A device with
452    /// nothing to send soon can send an empty frame with
453    /// [`send_empty`](EndDevice::send_empty).
454    ///
455    /// # Returns
456    ///
457    /// `true` for a confirmed downlink.
458    pub fn confirmed(&self) -> bool {
459        self.confirmed
460    }
461
462    /// Reports whether the network has more waiting.
463    ///
464    /// TS001-1.0.4 section 4.3.1.4 lets the device send an uplink as soon as it can to
465    /// collect it.
466    ///
467    /// # Returns
468    ///
469    /// The FPending bit.
470    pub fn more_pending(&self) -> bool {
471        self.more_pending
472    }
473
474    /// Returns the answer to a link check the device asked for.
475    ///
476    /// # Returns
477    ///
478    /// The margin and gateway count, when the downlink carried them.
479    pub fn link_check(&self) -> Option<LinkCheck> {
480        self.link_check
481    }
482
483    /// Returns the answer to a time request the device asked for.
484    ///
485    /// # Returns
486    ///
487    /// The network's time, when the downlink carried it.
488    pub fn device_time(&self) -> Option<DeviceTime> {
489        self.device_time
490    }
491}
492
493/// How well the network heard a link check.
494#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
495pub struct LinkCheck {
496    /// How far above the demodulation floor the best gateway heard it, in dB.
497    pub margin_db: u8,
498    /// How many gateways heard it.
499    pub gateways: u8,
500}
501
502/// The time a network gave a device.
503#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
504pub struct DeviceTime {
505    /// Whole seconds since the GPS epoch, 1980-01-06 00:00:00 UTC, at the end of the uplink
506    /// that asked.
507    pub gps_seconds: u32,
508    /// The fraction of a second, in 256ths.
509    pub fraction: u8,
510}
511
512/// What to do once both receive windows have closed with nothing for the device.
513#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
514pub enum Next {
515    /// Send the same frame again with [`repeat`](EndDevice::repeat), no sooner than this.
516    Repeat {
517        /// The earliest time to send it, in the caller's microseconds.
518        not_before_us: u64,
519    },
520    /// The uplink is finished.
521    Done,
522    /// A confirmed uplink went out every time it may without an acknowledgment.
523    Unacknowledged,
524    /// The join got no answer; join again with a new nonce, no sooner than this.
525    JoinAgain {
526        /// The earliest time to try, in the caller's microseconds.
527        not_before_us: u64,
528    },
529}
530
531/// Why a device could not do what it was asked.
532#[derive(Clone, Copy, Debug, PartialEq, Eq)]
533pub enum DeviceError {
534    /// The plan defines more channels than a device keeps.
535    TooManyChannels {
536        /// The most a device keeps, [`MAX_CHANNELS`].
537        max: usize,
538    },
539    /// A device activated by personalization has nothing to join with.
540    NoCredentials,
541    /// The device has not joined.
542    NotJoined,
543    /// A transmission is still waiting on its receive windows.
544    Busy,
545    /// There is no transmission waiting on its windows or due to repeat.
546    NothingPending,
547    /// The air is not free until this time, in the caller's microseconds.
548    Wait {
549        /// The earliest time to try again.
550        until_us: u64,
551    },
552    /// No enabled channel carries the data rate, and restoring the defaults did not help.
553    NoChannel,
554    /// The data rate is not a LoRa one this device can send or hear.
555    DataRate(u8),
556    /// The payload does not fit a frame at the current data rate.
557    PayloadTooLong {
558        /// The most the frame can carry, in bytes.
559        max: usize,
560    },
561    /// The uplink frame counter has reached its end, and the device has to join again.
562    CounterExhausted,
563    /// The frame did not decode.
564    Frame(LorawanError),
565    /// The frame is addressed to another device.
566    Foreign,
567    /// The frame repeats or precedes the last downlink the device accepted.
568    Replayed,
569    /// The frame is further ahead of the last downlink than LoRaWAN 1.0.3 lets a device
570    /// follow.
571    CounterGap,
572    /// A join accept carries settings the region does not allow, which RP002-1.0.5 has a
573    /// device ignore.
574    Refused,
575    /// A saved state could not be resumed.
576    State(StateError),
577}
578
579impl core::fmt::Display for DeviceError {
580    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
581        match self {
582            DeviceError::TooManyChannels { max } => {
583                write!(
584                    f,
585                    "the plan defines more than the {max} channels a device keeps"
586                )
587            }
588            DeviceError::NoCredentials => f.write_str("the device has no keys to join with"),
589            DeviceError::NotJoined => f.write_str("the device has not joined a network"),
590            DeviceError::Busy => f.write_str("a transmission is still waiting on its windows"),
591            DeviceError::NothingPending => f.write_str("nothing is waiting on its windows"),
592            DeviceError::Wait { until_us } => write!(f, "the air is not free until {until_us}"),
593            DeviceError::NoChannel => f.write_str("no enabled channel carries the data rate"),
594            DeviceError::DataRate(rate) => write!(f, "DR{rate} is not a LoRa data rate here"),
595            DeviceError::PayloadTooLong { max } => {
596                write!(f, "the payload does not fit; {max} bytes do")
597            }
598            DeviceError::CounterExhausted => f.write_str("the uplink frame counter is spent"),
599            DeviceError::Frame(error) => write!(f, "the frame did not decode: {error}"),
600            DeviceError::Foreign => f.write_str("the frame is for another device"),
601            DeviceError::Replayed => f.write_str("the frame repeats an earlier downlink"),
602            DeviceError::CounterGap => f.write_str("the frame counter jumped too far ahead"),
603            DeviceError::Refused => f.write_str("the join accept carries settings not allowed"),
604            DeviceError::State(error) => write!(f, "the saved state was not resumed: {error}"),
605        }
606    }
607}
608
609impl core::error::Error for DeviceError {}
610
611impl From<LorawanError> for DeviceError {
612    fn from(error: LorawanError) -> DeviceError {
613        DeviceError::Frame(error)
614    }
615}
616
617/// A transmission that has gone out and is waiting on its windows, or is due to repeat.
618// The frame is kept inline to repeat it byte for byte, with no allocator to box it.
619#[allow(clippy::large_enum_variant)]
620#[derive(Clone, Copy, Debug, PartialEq, Eq)]
621enum Pending {
622    Join {
623        dev_nonce: u16,
624        data_rate: u8,
625        join_channel: u16,
626    },
627    Uplink {
628        frame: PhyPayload,
629        data_rate: u8,
630        confirmed: bool,
631        carries_payload: bool,
632        transmissions_left: u8,
633        windows_closed: bool,
634        not_before_us: u64,
635        windows: Windows,
636    },
637}
638
639/// What a pending uplink's receive windows hold a downlink to.
640#[derive(Clone, Copy, Debug, PartialEq, Eq)]
641struct Windows {
642    rx1_data_rate: u8,
643    rx2_data_rate: u8,
644    rxr_data_rate: Option<u8>,
645    rx2_opens_us: u64,
646}
647
648impl Windows {
649    fn of(transmission: &Transmission, now_us: u64) -> Windows {
650        Windows {
651            rx1_data_rate: transmission.rx1.data_rate,
652            rx2_data_rate: transmission.rx2.data_rate,
653            rxr_data_rate: transmission.relay.map(|relay| relay.rxr.data_rate),
654            rx2_opens_us: now_us
655                .saturating_add(transmission.airtime_us)
656                .saturating_add(u64::from(transmission.rx2.delay_us)),
657        }
658    }
659}
660
661/// A LoRaWAN Class A end device.
662///
663/// See the [module documentation](self) for the exchange it runs.
664pub struct EndDevice<'p> {
665    plan: &'p ChannelPlan<'p>,
666    credentials: Option<Device>,
667    settings: Settings,
668    sequence: Sequence,
669    battery: Battery,
670    session: Option<Session>,
671    joined_on: Option<u16>,
672    fcnt_up: u32,
673    fcnt_down: Option<u32>,
674    data_rate: u8,
675    tx_power: u8,
676    nb_trans: u8,
677    rx1_dr_offset: u8,
678    rx2_frequency_hz: u32,
679    rx2_data_rate: u8,
680    rx1_delay_us: u32,
681    max_eirp_dbm: i8,
682    uplink_dwell: bool,
683    downlink_dwell: bool,
684    max_duty_cycle: u8,
685    channels: Channels,
686    answers: Answers,
687    backoff: Backoff,
688    air: Air,
689    pending: Option<Pending>,
690    ack_owed: bool,
691    joins: u32,
692    join_used: [u16; MASK_GROUPS],
693    join_slot: u32,
694    quiet_until_us: u64,
695    relayed: Relayed,
696}
697
698/// A join channel chosen for one attempt, and how the attempt goes out on it.
699#[derive(Clone, Copy, Debug)]
700struct JoinChoice {
701    number: u16,
702    channel: Channel,
703    data_rate: u8,
704    link: LinkSettings,
705    airtime_us: u64,
706    next_slot: u32,
707    restart_cycle: bool,
708}
709
710impl<'p> EndDevice<'p> {
711    /// A device that joins over the air.
712    ///
713    /// # Arguments
714    ///
715    /// * `plan` - the region's channel plan.
716    /// * `credentials` - the device's identifiers and root key.
717    /// * `settings` - what its radio can do.
718    ///
719    /// # Returns
720    ///
721    /// The device, not yet joined.
722    ///
723    /// # Errors
724    ///
725    /// Returns [`DeviceError::TooManyChannels`] for a plan with more default or join channels
726    /// than [`MAX_CHANNELS`].
727    pub fn new(
728        plan: &'p ChannelPlan<'p>,
729        credentials: Device,
730        settings: Settings,
731    ) -> Result<EndDevice<'p>, DeviceError> {
732        let sequence = Sequence::new(settings.seed, &credentials.dev_eui());
733        EndDevice::build(plan, Some(credentials), sequence, settings)
734    }
735
736    /// A device activated by personalization, with its session provisioned.
737    ///
738    /// Such a device never resets its frame counters, TS001-1.0.4 section 4.3.1.5, so a
739    /// device that loses power carries them over with
740    /// [`with_frame_counters`](EndDevice::with_frame_counters).
741    ///
742    /// # Arguments
743    ///
744    /// * `plan` - the region's channel plan.
745    /// * `session` - the address and session keys it was provisioned with.
746    /// * `settings` - what its radio can do.
747    ///
748    /// # Returns
749    ///
750    /// The device, ready to send at its slowest data rate.
751    ///
752    /// # Errors
753    ///
754    /// Returns [`DeviceError::TooManyChannels`] for a plan with more default or join channels
755    /// than [`MAX_CHANNELS`].
756    pub fn personalized(
757        plan: &'p ChannelPlan<'p>,
758        session: Session,
759        settings: Settings,
760    ) -> Result<EndDevice<'p>, DeviceError> {
761        let mut eui = [0u8; 8];
762        eui[..4].copy_from_slice(&session.dev_addr().to_le_bytes());
763        let sequence = Sequence::new(settings.seed, &eui);
764        let mut device = EndDevice::build(plan, None, sequence, settings)?;
765        device.session = Some(session);
766        device.data_rate = device.lowest_data_rate();
767        Ok(device)
768    }
769
770    fn build(
771        plan: &'p ChannelPlan<'p>,
772        credentials: Option<Device>,
773        sequence: Sequence,
774        settings: Settings,
775    ) -> Result<EndDevice<'p>, DeviceError> {
776        let join_channels = if plan.join_plans.is_empty() {
777            plan.join_channels
778                .iter()
779                .map(|block| usize::from(block.count))
780                .sum::<usize>()
781        } else {
782            plan.join_plans
783                .iter()
784                .map(|run| usize::from(run.channels.count))
785                .sum::<usize>()
786        };
787        if usize::from(plan.default_channel_count()) > MAX_CHANNELS || join_channels > MAX_CHANNELS
788        {
789            return Err(DeviceError::TooManyChannels { max: MAX_CHANNELS });
790        }
791        let mut device = EndDevice {
792            plan,
793            credentials,
794            settings,
795            sequence,
796            battery: Battery::Unknown,
797            session: None,
798            joined_on: None,
799            fcnt_up: 0,
800            fcnt_down: None,
801            data_rate: 0,
802            tx_power: 0,
803            nb_trans: 1,
804            rx1_dr_offset: 0,
805            rx2_frequency_hz: plan.rx2_frequency_hz,
806            rx2_data_rate: plan.rx2_data_rate,
807            rx1_delay_us: RECEIVE_DELAY1_US,
808            max_eirp_dbm: plan.default_max_eirp_dbm,
809            uplink_dwell: false,
810            downlink_dwell: false,
811            max_duty_cycle: 0,
812            channels: Channels::defaults(plan),
813            answers: Answers::new(),
814            backoff: Backoff::recommended(settings.version),
815            air: Air::new(),
816            pending: None,
817            ack_owed: false,
818            joins: 0,
819            join_used: [0; MASK_GROUPS],
820            join_slot: 0,
821            quiet_until_us: 0,
822            relayed: Relayed::new(),
823        };
824        device.reset_mac();
825        Ok(device)
826    }
827
828    /// Carries frame counters over from before a restart.
829    ///
830    /// # Arguments
831    ///
832    /// * `up` - the next uplink counter to use.
833    /// * `down` - the last downlink counter accepted, if any was.
834    ///
835    /// # Returns
836    ///
837    /// The device.
838    pub fn with_frame_counters(mut self, up: u32, down: Option<u32>) -> EndDevice<'p> {
839        self.fcnt_up = up;
840        self.fcnt_down = down;
841        self
842    }
843
844    /// Sets what the device reports its battery as, when a network asks.
845    ///
846    /// # Arguments
847    ///
848    /// * `battery` - the level.
849    pub fn set_battery(&mut self, battery: Battery) {
850        self.battery = battery;
851    }
852
853    /// Asks the network, with the next uplink, how well it hears the device.
854    ///
855    /// The answer arrives in a [`Delivery`]'s [`link_check`](Delivery::link_check).
856    pub fn request_link_check(&mut self) {
857        self.answers.request_link_check();
858    }
859
860    /// Asks the network, with the next uplink, for the time.
861    ///
862    /// The answer arrives in a [`Delivery`]'s [`device_time`](Delivery::device_time).
863    pub fn request_device_time(&mut self) {
864        self.answers.request_device_time();
865    }
866
867    /// Reports whether the device is on a network.
868    ///
869    /// # Returns
870    ///
871    /// `true` once joined, or from the start for a personalized device.
872    pub fn is_joined(&self) -> bool {
873        self.session.is_some()
874    }
875
876    /// Returns the address the device is on the network by.
877    ///
878    /// # Returns
879    ///
880    /// The address, or `None` before joining.
881    pub fn dev_addr(&self) -> Option<u32> {
882        self.session.map(|session| session.dev_addr())
883    }
884
885    /// Returns the data rate the next uplink goes out at, before any back-off step.
886    ///
887    /// # Returns
888    ///
889    /// The data rate.
890    pub fn data_rate(&self) -> u8 {
891        self.data_rate
892    }
893
894    /// Returns the next uplink frame counter.
895    ///
896    /// # Returns
897    ///
898    /// The counter a device stores to carry over a restart.
899    pub fn fcnt_up(&self) -> u32 {
900        self.fcnt_up
901    }
902
903    /// Returns the last downlink frame counter accepted.
904    ///
905    /// # Returns
906    ///
907    /// The counter, or `None` before any downlink.
908    pub fn fcnt_down(&self) -> Option<u32> {
909        self.fcnt_down
910    }
911
912    /// Returns how many times each uplink goes out, as the network last set it.
913    ///
914    /// # Returns
915    ///
916    /// NbTrans, from 1 to 15.
917    pub fn transmissions(&self) -> u8 {
918        self.nb_trans
919    }
920
921    /// Returns the channels the device may send on.
922    ///
923    /// # Returns
924    ///
925    /// Each enabled channel with its index.
926    pub fn channels(&self) -> impl Iterator<Item = (usize, Channel)> + '_ {
927        self.channels.enabled()
928    }
929
930    /// Returns the lowest and highest frequency the device transmits or listens on.
931    ///
932    /// A radio that calibrates for a band, as an SX126x does, calibrates for this one, so
933    /// moving between the device's channels and windows needs no calibration in between.
934    ///
935    /// # Returns
936    ///
937    /// The lower and upper frequency in hertz, across every enabled channel's uplink and
938    /// downlink, the join channels and where their accepts arrive, and the second receive
939    /// window.
940    pub fn frequency_span(&self) -> (u32, u32) {
941        let mut low = self.rx2_frequency_hz.min(self.plan.rx2_frequency_hz);
942        let mut high = self.rx2_frequency_hz.max(self.plan.rx2_frequency_hz);
943        let mut take = |hz: u32| {
944            low = low.min(hz);
945            high = high.max(hz);
946        };
947        for (_, channel) in self.channels.enabled() {
948            take(channel.uplink_hz);
949            take(channel.downlink_hz);
950        }
951        let mut number = 0u16;
952        let mut index = 0;
953        while let Some(block) = self.join_block(index) {
954            for offset in 0..block.count {
955                if let Some(hz) = block.frequency_hz(offset) {
956                    take(hz);
957                    take(self.join_downlink_hz(number, hz));
958                }
959                number = number.saturating_add(1);
960            }
961            index += 1;
962        }
963        (low, high)
964    }
965
966    /// Returns the second receive window's frequency and data rate.
967    ///
968    /// # Returns
969    ///
970    /// The frequency in hertz and the data rate.
971    pub fn rx2(&self) -> (u32, u8) {
972        (self.rx2_frequency_hz, self.rx2_data_rate)
973    }
974
975    /// Returns the delay from the end of an uplink to the first receive window.
976    ///
977    /// # Returns
978    ///
979    /// The delay in microseconds.
980    pub fn receive_delay_us(&self) -> u32 {
981        self.rx1_delay_us
982    }
983
984    /// Builds a join request.
985    ///
986    /// Each attempt picks a join channel at random and a data rate from the fastest the join
987    /// channels carry down to the slowest, one step per attempt and round again, which is
988    /// how TS001-1.0.4 section 6.2.5 asks a device to cover every channel and rate. On a plan
989    /// that joins in octet passes, US902-928 and AU915-928, each attempt instead takes the
990    /// next slot of the pass at the rate its channel carries. The air it takes is held to the
991    /// region's duty cycle and to the join back-off of section 7.
992    ///
993    /// The accept is due on the uplink's frequency in a dynamic plan, on the downlink channel
994    /// a fixed plan answers the join channel on, and on CN470-510 on the frequency table 49
995    /// gives the common join channel, in both windows, as Semtech's LoRaMac-node listens.
996    ///
997    /// # Arguments
998    ///
999    /// * `dev_nonce` - a nonce this device has never used with its join identifier. TS001-1.0.4
1000    ///   counts up from zero and keeps the count across restarts; LoRaWAN 1.0.3 draws one at
1001    ///   random.
1002    /// * `now_us` - the time, in microseconds.
1003    ///
1004    /// # Returns
1005    ///
1006    /// What to transmit, with the join accept windows.
1007    ///
1008    /// # Errors
1009    ///
1010    /// Returns [`DeviceError::NoCredentials`] for a personalized device,
1011    /// [`DeviceError::Busy`] while a transmission waits on its windows, and
1012    /// [`DeviceError::Wait`] when the air is not free.
1013    pub fn join(&mut self, dev_nonce: u16, now_us: u64) -> Result<Transmission, DeviceError> {
1014        let credentials = self
1015            .credentials
1016            .as_ref()
1017            .ok_or(DeviceError::NoCredentials)?;
1018        if self.pending.is_some() {
1019            return Err(DeviceError::Busy);
1020        }
1021        if now_us < self.quiet_until_us {
1022            return Err(DeviceError::Wait {
1023                until_us: self.quiet_until_us,
1024            });
1025        }
1026
1027        let frame = credentials.join_request(dev_nonce);
1028        let length = frame.as_bytes().len();
1029        let choice = match self.plan.join_sequence {
1030            JoinSequence::Random => self.random_join_channel(length, now_us)?,
1031            JoinSequence::OctetPasses => self.octet_pass_channel(length, now_us)?,
1032        };
1033        let rx2_hz = match self.plan.join_plan(choice.number) {
1034            Some(_) => choice.channel.downlink_hz,
1035            None => self.plan.rx2_frequency_hz,
1036        };
1037        self.relayed.joining(self.joins);
1038        let relay = self.wor_exchange(
1039            Carrier::new(choice.channel.uplink_hz, choice.data_rate),
1040            true,
1041            now_us,
1042        )?;
1043        let started_us = relay.map_or(now_us, |relay| relay.uplink_start_us);
1044        let transmission = self.transmission(
1045            frame,
1046            choice.channel,
1047            choice.data_rate,
1048            choice.link,
1049            choice.airtime_us,
1050            self.tx_power,
1051            Some(rx2_hz),
1052            true,
1053            relay,
1054        )?;
1055
1056        self.air.joined_air(choice.airtime_us);
1057        self.record_air(started_us, choice.airtime_us, choice.channel.uplink_hz);
1058        self.joins = self.joins.wrapping_add(1);
1059        self.join_slot = choice.next_slot;
1060        if choice.restart_cycle {
1061            self.join_used = [0; MASK_GROUPS];
1062        }
1063        let number = usize::from(choice.number);
1064        if number < MAX_CHANNELS {
1065            self.join_used[number / 16] |= 1 << (number % 16);
1066        }
1067        self.pending = Some(Pending::Join {
1068            dev_nonce,
1069            data_rate: choice.data_rate,
1070            join_channel: choice.number,
1071        });
1072        Ok(transmission)
1073    }
1074
1075    /// A join channel at random carrying this attempt's data rate.
1076    fn random_join_channel(
1077        &mut self,
1078        length: usize,
1079        now_us: u64,
1080    ) -> Result<JoinChoice, DeviceError> {
1081        let data_rate = self.join_data_rate()?;
1082        let link = self.uplink_link(data_rate)?;
1083        let airtime_us = link.airtime_us(length);
1084        if let Err(until_us) = self.air.join_allowed(now_us, airtime_us) {
1085            return Err(DeviceError::Wait { until_us });
1086        }
1087
1088        let mut candidates = [None; MAX_CHANNELS];
1089        let mut count = 0;
1090        let mut number = 0u16;
1091        let mut index = 0;
1092        while let Some(block) = self.join_block(index) {
1093            for offset in 0..block.count {
1094                if let Some(hz) = block.frequency_hz(offset) {
1095                    if block.min_data_rate <= data_rate
1096                        && data_rate <= block.max_data_rate
1097                        && self.settings.usable(hz)
1098                        && count < MAX_CHANNELS
1099                    {
1100                        candidates[count] = Some((number, self.join_channel(number, hz, &block)));
1101                        count += 1;
1102                    }
1103                }
1104                number = number.saturating_add(1);
1105            }
1106            index += 1;
1107        }
1108        let (number, channel) = self.pick(&candidates[..count], now_us)?;
1109        Ok(JoinChoice {
1110            number,
1111            channel,
1112            data_rate,
1113            link,
1114            airtime_us,
1115            next_slot: self.join_slot,
1116            restart_cycle: false,
1117        })
1118    }
1119
1120    /// The next slot of an octet pass over the join channels, RP002-1.0.5 section 3.5.2.
1121    ///
1122    /// The first join block is split into groups of eight, visited in order, and every block
1123    /// after it forms one more slot at the end of the pass. A slot takes a channel no attempt
1124    /// of the current cycle has used, at random within a group and the lowest in the last
1125    /// slot, as the section's example has the 500 kHz channels go 64, 65 and on. The cycle
1126    /// starts over once every channel has gone out, and a slot with no channel the radio can
1127    /// use is passed over.
1128    fn octet_pass_channel(
1129        &mut self,
1130        length: usize,
1131        now_us: u64,
1132    ) -> Result<JoinChoice, DeviceError> {
1133        let blocks = self.plan.join_channels;
1134        let narrow = blocks.first().map_or(0, |block| block.count);
1135        let groups = u32::from(narrow.div_ceil(8));
1136        let total = blocks.iter().map(|block| block.count).sum::<u16>();
1137        let pass = groups + u32::from(total > narrow);
1138        if pass == 0 {
1139            return Err(DeviceError::NoChannel);
1140        }
1141
1142        let mut every = [(0u16, Channel::new(0, 0, 0)); MAX_CHANNELS];
1143        let mut count = 0;
1144        let mut number = 0u16;
1145        for block in blocks {
1146            for offset in 0..block.count {
1147                if let Some(hz) = block.frequency_hz(offset) {
1148                    if self.settings.usable(hz)
1149                        && self.uplink_link(block.min_data_rate).is_ok()
1150                        && self.application_room(block.min_data_rate).is_ok()
1151                        && count < MAX_CHANNELS
1152                    {
1153                        every[count] = (number, self.join_channel(number, hz, block));
1154                        count += 1;
1155                    }
1156                }
1157                number = number.saturating_add(1);
1158            }
1159        }
1160        let every = &every[..count];
1161        let used = |number: u16| {
1162            let number = usize::from(number);
1163            self.join_used[number / 16] & (1 << (number % 16)) != 0
1164        };
1165        let fresh_cycle = every.iter().all(|(number, _)| used(*number));
1166
1167        for step in 0..pass {
1168            let slot = (self.join_slot + step) % pass;
1169            let in_slot = |number: u16| {
1170                if slot < groups {
1171                    u32::from(number) / 8 == slot && number < narrow
1172                } else {
1173                    number >= narrow
1174                }
1175            };
1176            let mut candidates = [None; 8];
1177            let mut found = 0;
1178            for &(number, channel) in every {
1179                if in_slot(number) && (fresh_cycle || !used(number)) && found < candidates.len() {
1180                    candidates[found] = Some((number, channel));
1181                    found += 1;
1182                    if slot >= groups {
1183                        break;
1184                    }
1185                }
1186            }
1187            let Some((_, first)) = candidates[0] else {
1188                continue;
1189            };
1190            let data_rate = first.min_data_rate;
1191            let link = self.uplink_link(data_rate)?;
1192            let airtime_us = link.airtime_us(length);
1193            if let Err(until_us) = self.air.join_allowed(now_us, airtime_us) {
1194                return Err(DeviceError::Wait { until_us });
1195            }
1196            let (number, channel) = self.pick(&candidates[..found], now_us)?;
1197            return Ok(JoinChoice {
1198                number,
1199                channel,
1200                data_rate,
1201                link,
1202                airtime_us,
1203                next_slot: (slot + 1) % pass,
1204                restart_cycle: fresh_cycle,
1205            });
1206        }
1207        Err(DeviceError::NoChannel)
1208    }
1209
1210    /// One block of the channels a join request may go out on, numbered through in order: the
1211    /// join plans' channels where the plan picks a plan by the join channel, and otherwise its
1212    /// join channels.
1213    fn join_block(&self, index: usize) -> Option<ChannelBlock> {
1214        if self.plan.join_plans.is_empty() {
1215            self.plan.join_channels.get(index).copied()
1216        } else {
1217            self.plan.join_plans.get(index).map(|run| run.channels)
1218        }
1219    }
1220
1221    /// A join channel with the downlink its accept arrives on.
1222    fn join_channel(&self, number: u16, hz: u32, block: &ChannelBlock) -> Channel {
1223        let mut channel = Channel::new(hz, block.min_data_rate, block.max_data_rate);
1224        channel.downlink_hz = self.join_downlink_hz(number, hz);
1225        channel
1226    }
1227
1228    /// Where the accept for a join on a numbered join channel arrives.
1229    fn join_downlink_hz(&self, number: u16, hz: u32) -> u32 {
1230        match self.plan.join_plan(number) {
1231            Some((run, offset)) => run.accept_hz(offset).unwrap_or(hz),
1232            None => self.plan.rx1_frequency_hz(number, hz).unwrap_or(hz),
1233        }
1234    }
1235
1236    /// Builds an uplink carrying a payload.
1237    ///
1238    /// The frame takes every answer the device owes the network. If they leave no room for
1239    /// the payload, the answers go alone and [`Transmission::carries_payload`] says the
1240    /// payload waits.
1241    ///
1242    /// # Arguments
1243    ///
1244    /// * `port` - the application port, 1 to 223, or 224 for the certification test port.
1245    /// * `payload` - the application payload.
1246    /// * `confirmed` - whether to ask the network to acknowledge it.
1247    /// * `now_us` - the time, in microseconds.
1248    ///
1249    /// # Returns
1250    ///
1251    /// What to transmit, with its receive windows.
1252    ///
1253    /// # Errors
1254    ///
1255    /// Returns [`DeviceError::NotJoined`] before joining, [`DeviceError::Busy`] while a
1256    /// transmission waits on its windows or its repeats, [`DeviceError::Wait`] when the air
1257    /// is not free, [`DeviceError::PayloadTooLong`] for a payload the data rate cannot carry,
1258    /// and [`DeviceError::Frame`] for port 0, which belongs to MAC commands.
1259    pub fn send(
1260        &mut self,
1261        port: u8,
1262        payload: &[u8],
1263        confirmed: bool,
1264        now_us: u64,
1265    ) -> Result<Transmission, DeviceError> {
1266        if port == 0 {
1267            return Err(DeviceError::Frame(LorawanError::MalformedFrame));
1268        }
1269        self.uplink(Some((port, payload)), confirmed, now_us)
1270    }
1271
1272    /// Builds an uplink with no payload.
1273    ///
1274    /// It carries the answers the device owes, an acknowledgment of a confirmed downlink,
1275    /// or an ADR acknowledgment request, whichever are due.
1276    ///
1277    /// # Arguments
1278    ///
1279    /// * `now_us` - the time, in microseconds.
1280    ///
1281    /// # Returns
1282    ///
1283    /// What to transmit, with its receive windows.
1284    ///
1285    /// # Errors
1286    ///
1287    /// As [`send`](EndDevice::send).
1288    pub fn send_empty(&mut self, now_us: u64) -> Result<Transmission, DeviceError> {
1289        self.uplink(None, false, now_us)
1290    }
1291
1292    /// Reads a frame heard in one of the receive windows of the last transmission, without
1293    /// saying which.
1294    ///
1295    /// A downlink may be as long as the faster of the two windows allows. When the radio
1296    /// knows the window, [`heard_in`](EndDevice::heard_in) holds the frame to that window's
1297    /// own limit, as TS001-1.0.4 section 4.1 asks.
1298    ///
1299    /// # Arguments
1300    ///
1301    /// * `frame` - the bytes the radio received.
1302    /// * `snr_db` - the frame's signal-to-noise ratio, which a `DevStatusAns` reports.
1303    ///
1304    /// # Returns
1305    ///
1306    /// The join, or the downlink read and acted on.
1307    ///
1308    /// # Errors
1309    ///
1310    /// As [`heard_in`](EndDevice::heard_in).
1311    pub fn heard(&mut self, frame: &[u8], snr_db: i8) -> Result<Heard, DeviceError> {
1312        self.heard_frame(None, frame, snr_db, None)
1313    }
1314
1315    /// Reads a frame heard in a given receive window of the last transmission.
1316    ///
1317    /// Under a relay the windows are three: the first two as ever, and then
1318    /// [`ReceiveWindow::Rxr`], which carries whatever the relay forwards back, TS011-1.0.1
1319    /// chapter 7.
1320    ///
1321    /// A frame that is not for this device, does not verify, or is longer than the window's
1322    /// data rate carries leaves the transmission waiting, so the second window still opens.
1323    /// TS001-1.0.4 section 4.1 has a device discard a MACPayload longer than the region's
1324    /// `M` for the data rate it was received at. RP002-1.0.5 has the device hold a downlink
1325    /// to the limit with no dwell time and no repeater, whatever its own settings, so no
1326    /// frame a network may lawfully send is lost.
1327    ///
1328    /// # Arguments
1329    ///
1330    /// * `window` - the window the radio heard the frame in.
1331    /// * `frame` - the bytes the radio received.
1332    /// * `snr_db` - the frame's signal-to-noise ratio, which a `DevStatusAns` reports.
1333    ///
1334    /// # Returns
1335    ///
1336    /// The join, or the downlink read and acted on.
1337    ///
1338    /// # Errors
1339    ///
1340    /// Returns [`DeviceError::NothingPending`] with no transmission waiting,
1341    /// [`DeviceError::Foreign`] for another device's frame, [`DeviceError::Replayed`] and
1342    /// [`DeviceError::CounterGap`] for a counter the device will not accept,
1343    /// [`DeviceError::Refused`] for a join accept with settings the region forbids, and
1344    /// [`DeviceError::Frame`] for a frame that does not decode or is longer than the window
1345    /// carries.
1346    ///
1347    /// # Examples
1348    ///
1349    /// ```
1350    /// use pamoja_lora::region::Region;
1351    /// use pamoja_lorawan::device::{DeviceError, EndDevice, ReceiveWindow, Settings};
1352    /// use pamoja_lorawan::{Downlink, LorawanError, Session};
1353    ///
1354    /// let session = Session::new(0x2601_1BDA, [0x2B; 16], [0x99; 16]);
1355    /// let settings = Settings::new(2, 14);
1356    /// let mut device = EndDevice::personalized(Region::Eu868.plan(), session, settings)?;
1357    ///
1358    /// // A personalized European device starts at DR0, and the second window listens at DR0
1359    /// // too, where a MACPayload holds no more than 59 bytes.
1360    /// device.send(1, b"hi", false, 0)?;
1361    /// let long = session.encode_downlink(&Downlink::new(0, 1, &[0; 60]))?;
1362    /// assert_eq!(
1363    ///     device.heard_in(ReceiveWindow::Rx2, long.as_bytes(), 5),
1364    ///     Err(DeviceError::Frame(LorawanError::PayloadTooLong)),
1365    /// );
1366    ///
1367    /// let short = session.encode_downlink(&Downlink::new(0, 1, b"ok"))?;
1368    /// assert!(device.heard_in(ReceiveWindow::Rx2, short.as_bytes(), 5).is_ok());
1369    /// # Ok::<(), Box<dyn std::error::Error>>(())
1370    /// ```
1371    pub fn heard_in(
1372        &mut self,
1373        window: ReceiveWindow,
1374        frame: &[u8],
1375        snr_db: i8,
1376    ) -> Result<Heard, DeviceError> {
1377        self.heard_frame(Some(window), frame, snr_db, None)
1378    }
1379
1380    /// Reads a frame as [`heard_in`](EndDevice::heard_in) does, handing the relay commands
1381    /// among its MAC commands to a relay's state in the order they arrived.
1382    pub(crate) fn heard_frame(
1383        &mut self,
1384        window: Option<ReceiveWindow>,
1385        frame: &[u8],
1386        snr_db: i8,
1387        relay: Option<&mut RelayState>,
1388    ) -> Result<Heard, DeviceError> {
1389        match self.pending {
1390            None => Err(DeviceError::NothingPending),
1391            Some(Pending::Join {
1392                dev_nonce,
1393                data_rate,
1394                join_channel,
1395            }) => self.heard_join(frame, dev_nonce, data_rate, join_channel, window),
1396            Some(Pending::Uplink {
1397                windows_closed: true,
1398                ..
1399            }) => Err(DeviceError::NothingPending),
1400            Some(Pending::Uplink {
1401                confirmed, windows, ..
1402            }) => self.heard_data(frame, snr_db, confirmed, windows, window, relay),
1403        }
1404    }
1405
1406    /// Says what comes next once both receive windows closed with nothing for the device.
1407    ///
1408    /// # Arguments
1409    ///
1410    /// * `now_us` - the time the second window closed, in microseconds.
1411    ///
1412    /// # Returns
1413    ///
1414    /// Whether to repeat the frame, join again, or move on.
1415    ///
1416    /// # Errors
1417    ///
1418    /// Returns [`DeviceError::NothingPending`] with no transmission waiting on its windows.
1419    pub fn nothing_heard(&mut self, now_us: u64) -> Result<Next, DeviceError> {
1420        match self.pending {
1421            None
1422            | Some(Pending::Uplink {
1423                windows_closed: true,
1424                ..
1425            }) => Err(DeviceError::NothingPending),
1426            Some(Pending::Join { .. }) => {
1427                self.pending = None;
1428                let wait = self
1429                    .sequence
1430                    .between(RETRANSMIT_TIMEOUT_MIN_US, RETRANSMIT_TIMEOUT_MAX_US);
1431                let not_before_us = now_us.saturating_add(u64::from(wait));
1432                self.quiet_until_us = not_before_us;
1433                Ok(Next::JoinAgain { not_before_us })
1434            }
1435            Some(Pending::Uplink {
1436                frame,
1437                data_rate,
1438                confirmed,
1439                carries_payload,
1440                transmissions_left,
1441                windows,
1442                ..
1443            }) => {
1444                let not_before_us = if confirmed {
1445                    let wait = self
1446                        .sequence
1447                        .between(RETRANSMIT_TIMEOUT_MIN_US, RETRANSMIT_TIMEOUT_MAX_US);
1448                    now_us.saturating_add(u64::from(wait))
1449                } else {
1450                    now_us
1451                };
1452                if transmissions_left > 0 {
1453                    self.pending = Some(Pending::Uplink {
1454                        frame,
1455                        data_rate,
1456                        confirmed,
1457                        carries_payload,
1458                        transmissions_left,
1459                        windows_closed: true,
1460                        not_before_us,
1461                        windows,
1462                    });
1463                    return Ok(Next::Repeat { not_before_us });
1464                }
1465                self.pending = None;
1466                self.relayed
1467                    .uplink_unanswered(smart_enable_uplinks(self.relayed.smart_level));
1468                if confirmed {
1469                    self.quiet_until_us = not_before_us;
1470                    Ok(Next::Unacknowledged)
1471                } else {
1472                    Ok(Next::Done)
1473                }
1474            }
1475        }
1476    }
1477
1478    /// Sends the last uplink again, the same frame on a channel chosen afresh.
1479    ///
1480    /// TS001-1.0.4 section 4.3.1.3 has a device hop between repetitions as usual and keep
1481    /// the frame counter, so the frame is byte for byte the one that went out before.
1482    ///
1483    /// # Arguments
1484    ///
1485    /// * `now_us` - the time, in microseconds.
1486    ///
1487    /// # Returns
1488    ///
1489    /// What to transmit, with its receive windows.
1490    ///
1491    /// # Errors
1492    ///
1493    /// Returns [`DeviceError::NothingPending`] with nothing due to repeat, and
1494    /// [`DeviceError::Wait`] before the retransmission timeout or while the air is not free.
1495    pub fn repeat(&mut self, now_us: u64) -> Result<Transmission, DeviceError> {
1496        let Some(Pending::Uplink {
1497            frame,
1498            data_rate,
1499            confirmed,
1500            carries_payload,
1501            transmissions_left,
1502            windows_closed: true,
1503            not_before_us,
1504            ..
1505        }) = self.pending
1506        else {
1507            return Err(DeviceError::NothingPending);
1508        };
1509        if now_us < not_before_us {
1510            return Err(DeviceError::Wait {
1511                until_us: not_before_us,
1512            });
1513        }
1514        let link = self.uplink_link(data_rate)?;
1515        let airtime_us = link.airtime_us(frame.as_bytes().len());
1516        let channels = self.channels;
1517        let channel = self.pick_enabled(&channels, data_rate, now_us)?;
1518        let relay = self.wor_exchange(Carrier::new(channel.uplink_hz, data_rate), false, now_us)?;
1519        let started_us = relay.map_or(now_us, |relay| relay.uplink_start_us);
1520        let transmission = self.transmission(
1521            frame,
1522            channel,
1523            data_rate,
1524            link,
1525            airtime_us,
1526            self.tx_power,
1527            None,
1528            carries_payload,
1529            relay,
1530        )?;
1531        self.record_air(started_us, airtime_us, channel.uplink_hz);
1532        self.pending = Some(Pending::Uplink {
1533            frame,
1534            data_rate,
1535            confirmed,
1536            carries_payload,
1537            transmissions_left: transmissions_left - 1,
1538            windows_closed: false,
1539            not_before_us: 0,
1540            windows: Windows::of(&transmission, started_us),
1541        });
1542        Ok(transmission)
1543    }
1544
1545    fn uplink(
1546        &mut self,
1547        data: Option<(u8, &[u8])>,
1548        confirmed: bool,
1549        now_us: u64,
1550    ) -> Result<Transmission, DeviceError> {
1551        let session = self.session.ok_or(DeviceError::NotJoined)?;
1552        if self.pending.is_some() {
1553            return Err(DeviceError::Busy);
1554        }
1555        if now_us < self.quiet_until_us {
1556            return Err(DeviceError::Wait {
1557                until_us: self.quiet_until_us,
1558            });
1559        }
1560        if self.fcnt_up == u32::MAX {
1561            return Err(DeviceError::CounterExhausted);
1562        }
1563
1564        // Everything the back-off changes is worked out on copies and kept only if the
1565        // frame goes out, so a refusal leaves the count where it was.
1566        let mut data_rate = self.data_rate;
1567        let mut tx_power = self.tx_power;
1568        let mut nb_trans = self.nb_trans;
1569        let mut channels = self.channels;
1570        let mut backoff = self.backoff;
1571        let lowest = self.lowest_data_rate();
1572
1573        let step = if self.settings.adr {
1574            backoff.uplink(Standing {
1575                default_data_rate: data_rate <= lowest,
1576            })
1577        } else {
1578            Step::default()
1579        };
1580        if step.restore_power {
1581            tx_power = 0;
1582        }
1583        if step.lower_data_rate {
1584            data_rate = self.lower(data_rate, lowest);
1585        }
1586        if step.restore_channels {
1587            channels.enable_defaults();
1588            nb_trans = 1;
1589        }
1590        // TS001-1.0.4 section 4.3.1.1: a combination that leaves no usable channel sends
1591        // the device straight back to its default channels at full power.
1592        if !channels.carries(&channels.mask(), data_rate) {
1593            channels.enable_defaults();
1594            tx_power = 0;
1595            if !channels.carries(&channels.mask(), data_rate) {
1596                data_rate = lowest;
1597            }
1598        }
1599
1600        let room = self.application_room(data_rate)?;
1601        if let Some((_, payload)) = data {
1602            if payload.len() > room {
1603                return Err(DeviceError::PayloadTooLong { max: room });
1604            }
1605        }
1606
1607        let owed = self.answers.len();
1608        let payload_len = data.map_or(0, |(_, payload)| payload.len());
1609        let mut fopts = [0u8; FOPTS_MAX];
1610        let mut mac = [0u8; MAX_PAYLOAD];
1611        let (port, body, fopts_len, carries_payload, written) =
1612            if owed <= FOPTS_MAX && owed + payload_len <= room {
1613                let written = self.answers.write(&mut fopts);
1614                (
1615                    data.map(|(port, _)| port),
1616                    data.map_or(&[][..], |(_, payload)| payload),
1617                    written.len,
1618                    data.is_some(),
1619                    written,
1620                )
1621            } else if owed <= FOPTS_MAX {
1622                let written = self.answers.write(&mut fopts);
1623                (None, &[][..], written.len, false, written)
1624            } else {
1625                let written = self.answers.write(&mut mac[..room]);
1626                (Some(0), &mac[..written.len], 0, false, written)
1627            };
1628
1629        let mut uplink = match port {
1630            Some(port) => Uplink::new(self.fcnt_up, port, body),
1631            None => Uplink::empty(self.fcnt_up),
1632        }
1633        .with_fopts(&fopts[..fopts_len]);
1634        let confirmed = confirmed && carries_payload;
1635        if confirmed {
1636            uplink = uplink.confirmed();
1637        }
1638        if self.settings.adr {
1639            uplink = uplink.with_adr();
1640        }
1641        if step.request_ack {
1642            uplink = uplink.with_adr_ack_req();
1643        }
1644        if self.ack_owed {
1645            uplink = uplink.with_ack();
1646        }
1647        let frame = session.encode_uplink(&uplink)?;
1648
1649        let link = self.uplink_link(data_rate)?;
1650        let airtime_us = link.airtime_us(frame.as_bytes().len());
1651        if self.uplink_dwell && airtime_us > DWELL_LIMIT_US {
1652            return Err(DeviceError::PayloadTooLong { max: room });
1653        }
1654        let channel = self.pick_enabled(&channels, data_rate, now_us)?;
1655        let relay = self.wor_exchange(Carrier::new(channel.uplink_hz, data_rate), false, now_us)?;
1656        let started_us = relay.map_or(now_us, |relay| relay.uplink_start_us);
1657        let transmission = self.transmission(
1658            frame,
1659            channel,
1660            data_rate,
1661            link,
1662            airtime_us,
1663            tx_power,
1664            None,
1665            carries_payload,
1666            relay,
1667        )?;
1668
1669        self.data_rate = data_rate;
1670        self.tx_power = tx_power;
1671        self.nb_trans = nb_trans;
1672        self.channels = channels;
1673        self.backoff = backoff;
1674        self.fcnt_up += 1;
1675        self.answers.sent(written);
1676        self.ack_owed = false;
1677        self.record_air(started_us, airtime_us, channel.uplink_hz);
1678        self.pending = Some(Pending::Uplink {
1679            frame,
1680            data_rate,
1681            confirmed,
1682            carries_payload,
1683            transmissions_left: nb_trans.saturating_sub(1),
1684            windows_closed: false,
1685            not_before_us: 0,
1686            windows: Windows::of(&transmission, started_us),
1687        });
1688        Ok(transmission)
1689    }
1690
1691    fn heard_join(
1692        &mut self,
1693        frame: &[u8],
1694        dev_nonce: u16,
1695        data_rate: u8,
1696        join_channel: u16,
1697        window: Option<ReceiveWindow>,
1698    ) -> Result<Heard, DeviceError> {
1699        let header = FrameHeader::parse(frame)?;
1700        if header.message_type() != MessageType::JoinAccept {
1701            return Err(DeviceError::Frame(LorawanError::UnsupportedMType(
1702                frame[0] & 0xE0,
1703            )));
1704        }
1705        let credentials = self
1706            .credentials
1707            .as_ref()
1708            .ok_or(DeviceError::NoCredentials)?;
1709        let accept = credentials.accept_join(frame, dev_nonce)?;
1710
1711        // RP002-1.0.5 section 3.9.2: the common join channel decides a CN470-510 plan.
1712        let joined_on = self.plan.join_plan(join_channel);
1713        let plan = joined_on.map_or(self.plan, |(run, _)| run.plan);
1714
1715        // RP002-1.0.5 section 3.4.7 and its counterparts: a reserved RX1DROffset in a join
1716        // accept has the accept ignored.
1717        let rx2_is_lora = matches!(
1718            plan.downlink_data_rate(accept.rx2_data_rate())
1719                .map(|rate| rate.modulation),
1720            Some(Modulation::LoRa { .. })
1721        );
1722        if accept.rx1_dr_offset() > plan.max_rx1_data_rate_offset || !rx2_is_lora {
1723            return Err(DeviceError::Refused);
1724        }
1725
1726        // TS001-1.0.4 section 6.2.6: back to the default channels and MAC settings, then the
1727        // accept's own settings, then the channel list as if its commands had arrived, with
1728        // no answers.
1729        self.plan = plan;
1730        self.reset_mac();
1731        if let Some(hz) = joined_on.and_then(|(run, offset)| run.rx2_hz(offset)) {
1732            self.rx2_frequency_hz = hz;
1733        }
1734        self.rx1_dr_offset = accept.rx1_dr_offset();
1735        self.rx2_data_rate = accept.rx2_data_rate();
1736        self.rx1_delay_us = accept.receive_delay_us();
1737        if let Some(list) = accept.cflist() {
1738            let settings = self.settings;
1739            self.channels
1740                .apply_cflist(self.plan, list, |hz| settings.usable(hz));
1741        }
1742        let session = accept.session();
1743        self.session = Some(session);
1744        self.joined_on = joined_on.map(|_| join_channel);
1745        self.fcnt_up = 0;
1746        self.fcnt_down = None;
1747        self.data_rate = if self.channels.carries(&self.channels.mask(), data_rate) {
1748            data_rate
1749        } else {
1750            self.lowest_data_rate()
1751        };
1752        self.relayed.joined(window == Some(ReceiveWindow::Rxr));
1753        self.air.join_done();
1754        self.join_used = [0; MASK_GROUPS];
1755        self.join_slot = 0;
1756        self.pending = None;
1757        self.quiet_until_us = 0;
1758        Ok(Heard::Joined {
1759            dev_addr: session.dev_addr(),
1760        })
1761    }
1762
1763    fn heard_data(
1764        &mut self,
1765        frame: &[u8],
1766        snr_db: i8,
1767        confirmed_uplink: bool,
1768        windows: Windows,
1769        window: Option<ReceiveWindow>,
1770        relay: Option<&mut RelayState>,
1771    ) -> Result<Heard, DeviceError> {
1772        let session = self.session.ok_or(DeviceError::NotJoined)?;
1773        let header = FrameHeader::parse(frame)?;
1774        if !matches!(
1775            header.message_type(),
1776            MessageType::UnconfirmedDown | MessageType::ConfirmedDown
1777        ) {
1778            return Err(DeviceError::Frame(LorawanError::UnsupportedMType(
1779                frame[0] & 0xE0,
1780            )));
1781        }
1782        if header.dev_addr() != Some(session.dev_addr()) {
1783            return Err(DeviceError::Foreign);
1784        }
1785        let limit = |data_rate| {
1786            self.plan
1787                .downlink_max_payload(data_rate, false)
1788                .map(|limit| usize::from(limit.mac_payload))
1789        };
1790        let max_mac_payload = match window {
1791            Some(ReceiveWindow::Rx1) => limit(windows.rx1_data_rate),
1792            Some(ReceiveWindow::Rx2) => limit(windows.rx2_data_rate),
1793            Some(ReceiveWindow::Rxr) => windows.rxr_data_rate.and_then(limit),
1794            None => limit(windows.rx1_data_rate)
1795                .zip(limit(windows.rx2_data_rate))
1796                .map(|(rx1, rx2)| rx1.max(rx2)),
1797        };
1798        if max_mac_payload.is_some_and(|max| frame.len().saturating_sub(5) > max) {
1799            return Err(DeviceError::Frame(LorawanError::PayloadTooLong));
1800        }
1801        let fcnt = self.downlink_counter(header.fcnt().unwrap_or(0))?;
1802        let rx = session.decode(frame, fcnt)?;
1803
1804        self.fcnt_down = Some(fcnt);
1805        self.relayed.heard_downlink();
1806        if window == Some(ReceiveWindow::Rxr) {
1807            self.relayed.heard_on_rxr();
1808        }
1809        self.backoff.downlink();
1810        self.answers.heard_downlink();
1811        self.ack_owed = rx.confirmed();
1812        self.pending = None;
1813        // TS001-1.0.4 section 4.3.1.3: a device still owed an acknowledgment waits out the
1814        // retransmission timeout, counted from the second window, before its next uplink.
1815        self.quiet_until_us = if confirmed_uplink && !rx.ack() {
1816            let wait = self
1817                .sequence
1818                .between(RETRANSMIT_TIMEOUT_MIN_US, RETRANSMIT_TIMEOUT_MAX_US);
1819            windows.rx2_opens_us.saturating_add(u64::from(wait))
1820        } else {
1821            0
1822        };
1823
1824        let mut delivery = Delivery {
1825            port: None,
1826            payload: [0; MAX_PAYLOAD],
1827            len: 0,
1828            acknowledged: confirmed_uplink && rx.ack(),
1829            confirmed: rx.confirmed(),
1830            more_pending: rx.fpending(),
1831            link_check: None,
1832            device_time: None,
1833        };
1834        match rx.fport() {
1835            Some(0) => self.process_commands(rx.payload(), snr_db, &mut delivery, relay),
1836            Some(port) => {
1837                self.process_commands(rx.fopts(), snr_db, &mut delivery, relay);
1838                delivery.port = Some(port);
1839                delivery.len = rx.payload().len();
1840                delivery.payload[..delivery.len].copy_from_slice(rx.payload());
1841            }
1842            None => self.process_commands(rx.fopts(), snr_db, &mut delivery, relay),
1843        }
1844        Ok(Heard::Data(delivery))
1845    }
1846
1847    /// Works the full downlink counter out from the 16 bits a frame carries.
1848    ///
1849    /// TS001-1.0.4 section 4.3.1.5 has the counter only go up and a retransmission of the
1850    /// last downlink ignored. LoRaWAN 1.0.3 also refuses a jump of [`MAX_FCNT_GAP`] or more.
1851    fn downlink_counter(&self, low: u16) -> Result<u32, DeviceError> {
1852        let Some(last) = self.fcnt_down else {
1853            return Ok(u32::from(low));
1854        };
1855        if last as u16 == low {
1856            return Err(DeviceError::Replayed);
1857        }
1858        let mut candidate = (last & !0xFFFF) | u32::from(low);
1859        if candidate < last {
1860            candidate = candidate
1861                .checked_add(0x1_0000)
1862                .ok_or(DeviceError::CounterExhausted)?;
1863        }
1864        if self.settings.version == Version::V1_0_3 && candidate - last >= MAX_FCNT_GAP {
1865            return Err(DeviceError::CounterGap);
1866        }
1867        Ok(candidate)
1868    }
1869
1870    /// Puts every MAC setting back to the region's default, as a join accept does.
1871    fn reset_mac(&mut self) {
1872        self.channels = Channels::defaults(self.plan);
1873        self.tx_power = 0;
1874        self.nb_trans = 1;
1875        self.rx1_dr_offset = 0;
1876        self.rx2_frequency_hz = self.plan.rx2_frequency_hz;
1877        self.rx2_data_rate = self.plan.rx2_data_rate;
1878        self.rx1_delay_us = RECEIVE_DELAY1_US;
1879        self.max_eirp_dbm = self.plan.default_max_eirp_dbm;
1880        // RP002-1.0.5 has AS923 and AU915 devices assume the 400 ms limit until
1881        // `TXParamSetupReq` says otherwise, and no region assume a downlink limit.
1882        self.uplink_dwell = self.plan.tx_param_setup;
1883        self.downlink_dwell = false;
1884        self.max_duty_cycle = 0;
1885        self.answers = Answers::new();
1886        self.backoff = Backoff::recommended(self.settings.version);
1887        self.ack_owed = false;
1888    }
1889
1890    /// The channel plan the device runs on.
1891    pub(crate) const fn plan(&self) -> &'p ChannelPlan<'p> {
1892        self.plan
1893    }
1894
1895    /// Reports whether the radio can tune a frequency.
1896    pub(crate) const fn tunes(&self, hz: u32) -> bool {
1897        self.settings.usable(hz)
1898    }
1899
1900    /// Queues a command the device starts itself, such as a relay's notification, for the
1901    /// next uplink.
1902    ///
1903    /// # Returns
1904    ///
1905    /// `false` if the queue is full.
1906    pub(crate) fn start_command(&mut self, command: MacCommand) -> bool {
1907        self.answers.start(command)
1908    }
1909
1910    /// Reports whether a command the device started, beginning with these bytes, is still
1911    /// to go out.
1912    pub(crate) fn starts_command(&self, prefix: &[u8]) -> bool {
1913        self.answers.starts_with(prefix)
1914    }
1915
1916    /// The default data rate: the slowest LoRa rate a default channel carries, and under a
1917    /// dwell limit the slowest that carries a payload inside it.
1918    fn lowest_data_rate(&self) -> u8 {
1919        (0..16u8)
1920            .find(|rate| {
1921                self.channels.carries(&self.channels.mask(), *rate)
1922                    && self.uplink_link(*rate).is_ok()
1923                    && self.application_room(*rate).is_ok()
1924            })
1925            .unwrap_or(0)
1926    }
1927
1928    /// The next data rate down by the region's back-off table, never below `lowest`.
1929    fn lower(&self, data_rate: u8, lowest: u8) -> u8 {
1930        let mut next = data_rate;
1931        while let Some(lower) = self.plan.next_backoff_data_rate(next) {
1932            next = lower;
1933            if next <= lowest {
1934                return lowest;
1935            }
1936            if self.uplink_link(next).is_ok() && self.application_room(next).is_ok() {
1937                return next;
1938            }
1939        }
1940        data_rate
1941    }
1942
1943    /// The data rate this join attempt goes out at.
1944    fn join_data_rate(&self) -> Result<u8, DeviceError> {
1945        let mut rates = [0u8; 16];
1946        let mut count = 0;
1947        for rate in (0..16u8).rev() {
1948            let carried = (0..)
1949                .map_while(|index| self.join_block(index))
1950                .any(|block| block.min_data_rate <= rate && rate <= block.max_data_rate);
1951            if carried && self.uplink_link(rate).is_ok() && self.application_room(rate).is_ok() {
1952                rates[count] = rate;
1953                count += 1;
1954            }
1955        }
1956        if count == 0 {
1957            return Err(DeviceError::NoChannel);
1958        }
1959        Ok(rates[self.joins as usize % count])
1960    }
1961
1962    /// The most application payload a data rate carries with no frame options, from the
1963    /// region's payload tables.
1964    pub(crate) fn application_room(&self, data_rate: u8) -> Result<usize, DeviceError> {
1965        let limit = if self.uplink_dwell && self.plan.has_dwell_time_limit {
1966            self.plan.max_payload_dwell_limited(data_rate)
1967        } else {
1968            self.plan
1969                .max_payload(data_rate, self.settings.behind_repeater)
1970        };
1971        let room = limit
1972            .map(|limit| usize::from(limit.application).min(MAX_PAYLOAD))
1973            .ok_or(DeviceError::DataRate(data_rate))?;
1974        Ok(
1975            match self.relayed.enabled.then(|| self.relayed_room()).flatten() {
1976                Some(relayed) => room.min(relayed),
1977                None => room,
1978            },
1979        )
1980    }
1981
1982    /// The LoRa settings of an uplink at a data rate.
1983    fn uplink_link(&self, data_rate: u8) -> Result<LinkSettings, DeviceError> {
1984        match self
1985            .plan
1986            .uplink_data_rate(data_rate)
1987            .map(|rate| rate.modulation)
1988        {
1989            Some(Modulation::LoRa {
1990                spreading_factor,
1991                bandwidth_hz,
1992            }) => Ok(LinkSettings::new(spreading_factor, bandwidth_hz)),
1993            _ => Err(DeviceError::DataRate(data_rate)),
1994        }
1995    }
1996
1997    /// The LoRa settings a receive window listens with.
1998    fn downlink_link(&self, data_rate: u8) -> Result<LinkSettings, DeviceError> {
1999        match self
2000            .plan
2001            .downlink_data_rate(data_rate)
2002            .map(|rate| rate.modulation)
2003        {
2004            Some(Modulation::LoRa {
2005                spreading_factor,
2006                bandwidth_hz,
2007            }) => Ok(LinkSettings::new(spreading_factor, bandwidth_hz).without_crc()),
2008            _ => Err(DeviceError::DataRate(data_rate)),
2009        }
2010    }
2011
2012    /// Picks an enabled channel carrying a data rate whose air is free.
2013    fn pick_enabled(
2014        &mut self,
2015        channels: &Channels,
2016        data_rate: u8,
2017        now_us: u64,
2018    ) -> Result<Channel, DeviceError> {
2019        let mut candidates = [None; MAX_CHANNELS];
2020        let mut count = 0;
2021        for (index, channel) in channels.enabled() {
2022            if channel.carries(data_rate) && self.settings.usable(channel.uplink_hz) {
2023                candidates[count] = Some((index as u16, channel));
2024                count += 1;
2025            }
2026        }
2027        self.pick(&candidates[..count], now_us)
2028            .map(|(_, channel)| channel)
2029    }
2030
2031    /// Picks one of `candidates`, numbered channels, at random among those whose air is free
2032    /// now.
2033    fn pick(
2034        &mut self,
2035        candidates: &[Option<(u16, Channel)>],
2036        now_us: u64,
2037    ) -> Result<(u16, Channel), DeviceError> {
2038        let mut free = 0u32;
2039        let mut earliest = u64::MAX;
2040        for (_, channel) in candidates.iter().flatten() {
2041            let at = self.free_at(channel.uplink_hz);
2042            if at <= now_us {
2043                free += 1;
2044            } else {
2045                earliest = earliest.min(at);
2046            }
2047        }
2048        if free == 0 {
2049            return Err(if earliest == u64::MAX {
2050                DeviceError::NoChannel
2051            } else {
2052                DeviceError::Wait { until_us: earliest }
2053            });
2054        }
2055        let mut choice = self.sequence.below(free);
2056        for (number, channel) in candidates.iter().flatten() {
2057            if self.free_at(channel.uplink_hz) <= now_us {
2058                if choice == 0 {
2059                    return Ok((*number, *channel));
2060                }
2061                choice -= 1;
2062            }
2063        }
2064        Err(DeviceError::NoChannel)
2065    }
2066
2067    /// When a frequency's air is next free.
2068    pub(crate) fn free_at(&self, hz: u32) -> u64 {
2069        let sub_band = if self.settings.regional_duty_cycle {
2070            self.air
2071                .sub_band_free_at(self.sub_band(hz).map(|(index, _)| index))
2072        } else {
2073            0
2074        };
2075        sub_band.max(self.air.aggregated_free_at())
2076    }
2077
2078    /// The sub-band a frequency falls in, with its duty cycle.
2079    fn sub_band(&self, hz: u32) -> Option<(usize, u32)> {
2080        self.plan
2081            .sub_bands
2082            .iter()
2083            .enumerate()
2084            .take(MAX_SUB_BANDS)
2085            .find(|(_, band)| band.contains(hz))
2086            .map(|(index, band)| (index, band.duty_cycle_permille))
2087    }
2088
2089    /// Counts a transmission against the duty cycle of the sub-band it went out in.
2090    pub(crate) fn record_air(&mut self, started_us: u64, airtime_us: u64, hz: u32) {
2091        let sub_band = if self.settings.regional_duty_cycle {
2092            self.sub_band(hz)
2093        } else {
2094            None
2095        };
2096        self.air
2097            .transmitted(started_us, airtime_us, sub_band, self.max_duty_cycle);
2098    }
2099
2100    /// The conducted power for a power index on a frequency.
2101    pub(crate) fn output_dbm(&self, hz: u32, tx_power: u8) -> i8 {
2102        let ceiling = self.plan.max_eirp_dbm(hz).min(self.max_eirp_dbm);
2103        let power = self
2104            .plan
2105            .tx_power_dbm(tx_power, self.max_eirp_dbm)
2106            .unwrap_or(ceiling)
2107            .min(ceiling);
2108        self.radio_dbm(power).clamp(
2109            i16::from(self.settings.min_output_dbm),
2110            i16::from(self.settings.max_output_dbm),
2111        ) as i8
2112    }
2113
2114    /// The power to ask of the radio for a power the plan's index names: a radiated power
2115    /// less the antenna's gain, or a conducted one less whatever gain exceeds the plan's
2116    /// allowance.
2117    fn radio_dbm(&self, power: i8) -> i16 {
2118        let gain = i16::from(self.settings.antenna_gain_db);
2119        match self.plan.power_reference {
2120            PowerReference::Eirp => i16::from(power) - gain,
2121            PowerReference::Conducted { gain_allowance_db } => {
2122                i16::from(power) - (gain - i16::from(gain_allowance_db)).max(0)
2123            }
2124        }
2125    }
2126
2127    #[allow(clippy::too_many_arguments)]
2128    fn transmission(
2129        &self,
2130        frame: PhyPayload,
2131        channel: Channel,
2132        data_rate: u8,
2133        link: LinkSettings,
2134        airtime_us: u64,
2135        tx_power: u8,
2136        join_rx2_hz: Option<u32>,
2137        carries_payload: bool,
2138        relay: Option<RelayExchange>,
2139    ) -> Result<Transmission, DeviceError> {
2140        let (delay1, delay2, offset, (rx2_hz, rx2_rate)) = match join_rx2_hz {
2141            Some(hz) => (
2142                JOIN_ACCEPT_DELAY1_US,
2143                JOIN_ACCEPT_DELAY2_US,
2144                0,
2145                (hz, self.plan.rx2_data_rate),
2146            ),
2147            None => (
2148                self.rx1_delay_us,
2149                self.rx1_delay_us.saturating_add(1_000_000),
2150                self.rx1_dr_offset,
2151                (self.rx2_frequency_hz, self.rx2_data_rate),
2152            ),
2153        };
2154        let rx1_rate = if self.downlink_dwell {
2155            self.plan.rx1_data_rate_dwell_limited(data_rate, offset)
2156        } else {
2157            None
2158        }
2159        .or_else(|| self.plan.rx1_data_rate(data_rate, offset))
2160        .ok_or(DeviceError::DataRate(data_rate))?;
2161
2162        Ok(Transmission {
2163            frame,
2164            frequency_hz: channel.uplink_hz,
2165            data_rate,
2166            link,
2167            output_dbm: self.output_dbm(channel.uplink_hz, tx_power),
2168            airtime_us,
2169            rx1: Window {
2170                delay_us: delay1,
2171                frequency_hz: channel.downlink_hz,
2172                data_rate: rx1_rate,
2173                link: self.downlink_link(rx1_rate)?,
2174            },
2175            rx2: Window {
2176                delay_us: delay2,
2177                frequency_hz: rx2_hz,
2178                data_rate: rx2_rate,
2179                link: self.downlink_link(rx2_rate)?,
2180            },
2181            carries_payload,
2182            relay,
2183        })
2184    }
2185}
2186
2187#[cfg(test)]
2188mod relayed_tests;
2189#[cfg(test)]
2190mod tests;