Skip to main content

LoraPacketBuilder

Struct LoraPacketBuilder 

Source
pub struct LoraPacketBuilder { /* private fields */ }
Expand description

Fluent builder for assembling a LoraPacket field by field.

Pick the message variant first with data, join_request, join_accept, or rejoin_request. Then set the per-variant fields. Finalise with one of:

Every field is optional; required-field validation happens in build_unsigned based on the selected variant.

Implementations§

Source§

impl LoraPacketBuilder

Source

pub const fn data(self, direction: Direction, confirmed: bool) -> Self

Set message type and direction for a Data message.

Source

pub const fn join_request(self) -> Self

Begin a Join Request.

Source

pub const fn join_accept(self) -> Self

Begin a Join Accept.

Source

pub const fn rejoin_request(self, rejoin_type: u8) -> Self

Begin a Rejoin Request with the given type (0, 1, or 2).

Source

pub const fn dev_addr(self, addr: DevAddr) -> Self

Set DevAddr (Data and Join Accept).

Source

pub const fn f_ctrl(self, c: FCtrl) -> Self

Set FCtrl byte (Data).

Source

pub const fn f_cnt(self, n: u16) -> Self

Set FCnt (Data).

Source

pub fn f_opts(self, opts: &[u8]) -> Self

Set FOpts MAC commands (Data).

Source

pub const fn f_port(self, p: u8) -> Self

Set FPort (Data).

Source

pub fn payload(self, p: &[u8]) -> Self

Set FRMPayload plaintext (Data).

Source

pub const fn join_eui(self, e: AppEui) -> Self

Set Join EUI (Join Request / Rejoin Type 1).

Source

pub const fn dev_eui(self, e: DevEui) -> Self

Set Device EUI (Join Request / Rejoin).

Source

pub const fn dev_nonce(self, n: DevNonce) -> Self

Set DevNonce (Join Request).

Source

pub const fn join_nonce(self, n: AppNonce) -> Self

Set Join Nonce / AppNonce (Join Accept).

Source

pub const fn net_id(self, id: NetId) -> Self

Set NetID (Join Accept / Rejoin Type 0/2).

Source

pub const fn dl_settings(self, s: DlSettings) -> Self

Set DLSettings (Join Accept).

Source

pub const fn rx_delay(self, r: u8) -> Self

Set RxDelay (Join Accept).

Source

pub const fn cf_list(self, c: [u8; 16]) -> Self

Set CFList (Join Accept).

Source

pub const fn join_req_type(self, t: u8) -> Self

Set JoinReqType (LoRaWAN 1.1 Join Accept MIC context).

Source

pub const fn rj_count_0(self, count: u16) -> Self

Set RJcount0 (Rejoin Request Type 0 and Type 2).

Stored little-endian on the wire. Defaults to 0 when not set.

Source

pub const fn rj_count_1(self, count: u16) -> Self

Set RJcount1 (Rejoin Request Type 1).

Stored little-endian on the wire. Defaults to 0 when not set.

Source

pub fn sign_join_accept(self, app_key: &AppKey) -> Result<(LoraPacket, Vec<u8>)>

Build a Join Accept, compute the MIC, and produce the encrypted wire bytes.

Returns (plaintext_packet, encrypted_wire). The plaintext packet has MIC populated and phy_payload set to the plaintext form. The wire bytes are what you send over the air; the device will decrypt them back to the plaintext form.

§Errors

Error::MissingField if required Join Accept fields are missing.

Source

pub fn sign_join_request(self, app_key: &AppKey) -> Result<LoraPacket>

Build a Join Request and compute its MIC using LoRaWAN 1.0 AppKey.

For LoRaWAN 1.1, use sign_join_request_v1_1 which takes a NwkKey directly.

§Errors

Error::MissingField if required fields are missing.

Source

pub fn sign_join_request_v1_1(self, nwk_key: &NwkKey) -> Result<LoraPacket>

Build a Join Request and compute its MIC using LoRaWAN 1.1 NwkKey.

The CMAC algorithm is identical to 1.0; only the key changes.

§Errors

Error::MissingField if required fields are missing.

Source

pub fn sign_and_encrypt( self, app_s_key: &AppSKey, nwk_s_key: &NwkSKey, ) -> Result<LoraPacket>

Build a Data packet, encrypt FRMPayload, and compute the LoRaWAN 1.0 MIC in one shot.

The plaintext payload provided via payload is encrypted with AppSKey (when FPort > 0) or NwkSKey (when FPort == 0). The MIC is then calculated under NwkSKey with the 1.0 algorithm.

For 1.1 Data frames, build with build_unsigned, encrypt manually with Data::encrypt_payload, and sign with LoraPacket::recalculate_mic_v1_1.

§Errors
§Examples
use lora_packet::{LoraPacket, Direction, DevAddr, AppSKey, NwkSKey};

let app_s_key = AppSKey::from_slice(&hex::decode("ec925802ae430ca77fd3dd73cb2cc588")?)?;
let nwk_s_key = NwkSKey::from_slice(&hex::decode("44024241ed4ce9a68c6a8bc055233fd3")?)?;

let packet = LoraPacket::builder()
  .data(Direction::Uplink, false)
  .dev_addr(DevAddr::new([0x49, 0xbe, 0x7d, 0xf1]))
  .f_cnt(2)
  .f_port(1)
  .payload(b"test")
  .sign_and_encrypt(&app_s_key, &nwk_s_key)?;

assert_eq!(packet.to_wire(), hex::decode("40f17dbe4900020001954378762b11ff0d")?);
Source

pub fn build_unsigned(self) -> Result<LoraPacket>

Finalise the builder into a LoraPacket with MIC set to zero.

Useful when you want to sign and emit in separate steps (e.g. for test vectors or when the signing keys arrive asynchronously). Call a sign_* method on the builder, or call recalculate_mic_v1_0 / recalculate_mic_v1_1 on the resulting packet, to fill in the MIC.

§Errors

Trait Implementations§

Source§

impl Clone for LoraPacketBuilder

Source§

fn clone(&self) -> LoraPacketBuilder

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LoraPacketBuilder

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for LoraPacketBuilder

Source§

fn default() -> LoraPacketBuilder

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.