lorawan_device/mac/
otaa.rs1use super::{del_to_delay_ms, session::Session, Response};
2use crate::radio::RadioBuffer;
3use crate::region::Configuration;
4use crate::{AppEui, AppKey, DevEui};
5use lorawan::keys::CryptoFactory;
6use lorawan::{
7 creator::JoinRequestCreator,
8 parser::{parse_with_factory as lorawan_parse, *},
9};
10use rand_core::RngCore;
11
12pub(crate) type DevNonce = lorawan::parser::DevNonce<[u8; 2]>;
13
14pub(crate) struct Otaa {
15 dev_nonce: DevNonce,
16 network_credentials: NetworkCredentials,
17}
18#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19#[derive(Debug, Clone)]
20pub struct NetworkCredentials {
21 deveui: DevEui,
22 appeui: AppEui,
23 appkey: AppKey,
24}
25
26impl Otaa {
27 pub fn new(network_credentials: NetworkCredentials) -> Self {
28 Self { dev_nonce: DevNonce::from([0, 0]), network_credentials }
29 }
30
31 pub(crate) fn prepare_buffer<C: CryptoFactory + Default, G: RngCore, const N: usize>(
34 &mut self,
35 rng: &mut G,
36 buf: &mut RadioBuffer<N>,
37 ) -> u16 {
38 self.dev_nonce = DevNonce::from(rng.next_u32() as u16);
39 buf.clear();
40 let mut phy: JoinRequestCreator<[u8; 23], C> = JoinRequestCreator::default();
41 phy.set_app_eui(self.network_credentials.appeui)
42 .set_dev_eui(self.network_credentials.deveui)
43 .set_dev_nonce(self.dev_nonce);
44 let vec = phy.build(&self.network_credentials.appkey);
45 buf.extend_from_slice(vec).unwrap();
46 u16::from(self.dev_nonce)
47 }
48
49 pub(crate) fn handle_rx<C: CryptoFactory + Default, const N: usize>(
50 &mut self,
51 region: &mut Configuration,
52 configuration: &mut super::Configuration,
53 rx: &mut RadioBuffer<N>,
54 ) -> Option<Session> {
55 if let Ok(PhyPayload::JoinAccept(JoinAcceptPayload::Encrypted(encrypted))) =
56 lorawan_parse(rx.as_mut_for_read(), C::default())
57 {
58 let decrypt = encrypted.decrypt(&self.network_credentials.appkey);
59 region.process_join_accept(&decrypt);
60 configuration.rx1_delay = del_to_delay_ms(decrypt.rx_delay());
61 if decrypt.validate_mic(&self.network_credentials.appkey) {
62 return Some(Session::derive_new(
63 &decrypt,
64 self.dev_nonce,
65 &self.network_credentials,
66 ));
67 }
68 }
69 None
70 }
71
72 pub(crate) fn rx2_complete(&mut self) -> Response {
73 Response::NoJoinAccept
74 }
75}
76
77impl NetworkCredentials {
78 pub fn new(appeui: AppEui, deveui: DevEui, appkey: AppKey) -> Self {
79 Self { deveui, appeui, appkey }
80 }
81 pub fn appeui(&self) -> &AppEui {
82 &self.appeui
83 }
84
85 pub fn deveui(&self) -> &DevEui {
86 &self.deveui
87 }
88
89 pub fn appkey(&self) -> &AppKey {
90 &self.appkey
91 }
92}