Skip to main content

Data

Struct Data 

Source
pub struct Data {
    pub direction: Direction,
    pub confirmed: bool,
    pub dev_addr: DevAddr,
    pub f_ctrl: FCtrl,
    pub f_cnt: [u8; 2],
    pub f_opts: Vec<u8>,
    pub f_port: Option<u8>,
    pub frm_payload: Option<Vec<u8>>,
}
Expand description

Fields of a Data message (confirmed or unconfirmed, uplink or downlink).

FRMPayload is encrypted on the wire; call Data::decrypt_payload to recover the plaintext. MAC commands in FOpts are encrypted only in LoRaWAN 1.1; call Data::decrypt_fopts when applicable.

§Frame counters

The wire carries only the lower 16 bits of the 32-bit FCnt. The caller tracks the upper 16 bits and passes it to Data::f_cnt_32 and to every crypt / MIC call. Pass 0 for sessions that never wrap.

Fields§

§direction: Direction

Frame direction, inferred from MType.

§confirmed: bool

true for ConfirmedData{Up,Down}.

§dev_addr: DevAddr

Device address.

§f_ctrl: FCtrl

Frame-control byte.

§f_cnt: [u8; 2]

Lower 16 bits of FCnt as on the wire (little-endian).

Use Data::f_cnt for a u16 value or Data::f_cnt_32 for the full 32-bit counter with a caller-supplied upper half.

§f_opts: Vec<u8>

MAC commands carried in FOpts (empty when none); up to 15 bytes. Encrypted with NwkSEncKey in 1.1; plaintext in 1.0.

§f_port: Option<u8>

FPort byte. Some(0) means FRMPayload carries MAC commands; Some(p) with p > 0 means application data; None when neither FPort nor FRMPayload is present.

§frm_payload: Option<Vec<u8>>

FRMPayload. Encrypted on the wire; replace with plaintext after Data::decrypt_payload.

Implementations§

Source§

impl Data

Source

pub const fn f_cnt(&self) -> u16

Lower 16 bits of FCnt as read from the wire (little-endian).

The wire stores only the bottom 16 bits of the actual 32-bit counter. For the full counter use Data::f_cnt_32 together with a caller-tracked upper half.

Source

pub const fn f_cnt_32(&self, msb: u16) -> u32

Full 32-bit FCnt, combining the wire LSB16 with a caller-tracked MSB16.

msb is the upper 16 bits the caller has been tracking. Pass 0 if frame counters never wrap in your deployment; otherwise increment msb each time the wire counter rolls over from 0xFFFF to 0x0000.

Source§

impl Data

Source

pub fn decrypt_payload( &self, app_s_key: &AppSKey, nwk_s_key: &NwkSKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>

Decrypt FRMPayload.

LoRaWAN uses an AES-CTR-like keystream so the same operation works in both directions; this method is named for the typical use (receiver side). The key is selected by FPort:

  • FPort == 0: NwkSKey (MAC commands in FRMPayload).
  • FPort > 0: AppSKey (application data).

f_cnt_msb is the upper 16 bits of the 32-bit FCnt; pass 0 if frame counters never wrap. See crate::Data::f_cnt_32.

§Errors

crate::Error::PayloadTooLarge if the ciphertext exceeds the AES-CTR block-index limit (255 blocks = 4080 bytes).

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

let bytes = hex::decode("40f17dbe4900020001954378762b11ff0d")?;
let packet = LoraPacket::from_wire(&bytes)?;
let app_s_key = AppSKey::from_slice(&hex::decode("ec925802ae430ca77fd3dd73cb2cc588")?)?;
let nwk_s_key = NwkSKey::from_slice(&hex::decode("44024241ed4ce9a68c6a8bc055233fd3")?)?;
let plain = packet.as_data().unwrap().decrypt_payload(&app_s_key, &nwk_s_key, 0)?;
assert_eq!(&plain, b"test");
Source

pub fn encrypt_payload( &self, plaintext: &[u8], app_s_key: &AppSKey, nwk_s_key: &NwkSKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>

Encrypt the given plaintext under the FRMPayload keystream.

Same primitive as Self::decrypt_payload; named differently for clarity at call sites. Used by crate::LoraPacketBuilder::sign_and_encrypt for downlink building.

Selects NwkSKey when FPort == 0, AppSKey otherwise.

§Errors

crate::Error::PayloadTooLarge if the plaintext exceeds 4080 bytes (255 AES blocks). Beyond this, the 1-byte block counter in the Ai keystream block overflows and silently produces ciphertext no other LoRaWAN stack can decrypt.

Source§

impl Data

Source

pub fn decrypt_fopts( &self, nwk_s_enc_key: &NwkSEncKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>

Decrypt FOpts MAC commands (LoRaWAN 1.1 only).

In 1.0, FOpts is plaintext on the wire; this method is a no-op (but still callable). In 1.1, FOpts is encrypted under NwkSEncKey with a single AES-ECB block.

Uses the keystream layout from the LoRa Alliance errata “FCntDwn Usage in FOpts Encryption” (CR v2 r1): when the frame is a downlink with FPort > 0 the aFCntDown flag selects byte 4 = 0x02; otherwise it is 0x01.

§Errors

Currently infallible; returns Result for forward compatibility.

Source

pub fn encrypt_fopts( &self, nwk_s_enc_key: &NwkSEncKey, f_cnt_msb: u16, ) -> Result<Vec<u8>>

Encrypt FOpts MAC commands (LoRaWAN 1.1 only).

Symmetric to Self::decrypt_fopts; same primitive in both directions. Use when building a 1.1 frame that carries MAC commands in FOpts.

§Errors

Currently infallible; returns Result for forward compatibility.

Trait Implementations§

Source§

impl Clone for Data

Source§

fn clone(&self) -> Data

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 Data

Source§

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

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

impl<'de> Deserialize<'de> for Data

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Data

Source§

fn eq(&self, other: &Data) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Data

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for Data

Source§

impl StructuralPartialEq for Data

Auto Trait Implementations§

§

impl Freeze for Data

§

impl RefUnwindSafe for Data

§

impl Send for Data

§

impl Sync for Data

§

impl Unpin for Data

§

impl UnsafeUnpin for Data

§

impl UnwindSafe for Data

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.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,