Add feature flags to lrwn crate.

This avoids pulling and building unnecessary dependencies for simple
use-cases.
This commit is contained in:
Orne Brocaar 2023-04-27 10:37:34 +01:00
parent 08d69502de
commit 0679f10fad
16 changed files with 267 additions and 101 deletions

View File

@ -46,7 +46,7 @@ tracing-subscriber = { version = "0.3", features = [
# ChirpStack API definitions
chirpstack_api = { path = "../api/rust", features = ["default", "internal"] }
lrwn = { path = "../lrwn" }
lrwn = { path = "../lrwn", features = ["serde", "diesel", "regions", "crypto"] }
backend = { path = "../backend" }
# HTTP

View File

@ -8,12 +8,15 @@ authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2018"
repository = "https://github.com/chirpstack/chirpstack"
[package.metadata.docs.rs]
all-features = true
[dependencies]
hex = "0.4"
cmac = "0.7"
aes = "0.8"
serde = { version = "1.0", features = ["derive"] }
diesel = { version = "2.0", features = [ "postgres" ] }
cmac = { version = "0.7", optional = true }
aes = { version = "0.8", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
diesel = { version = "2.0", features = ["postgres"], optional = true }
# Error handling
thiserror = "1.0"
@ -21,3 +24,10 @@ anyhow = "1.0"
# Misc
lazy_static = "1.4"
[features]
default = []
diesel = ["dep:diesel", "serde"]
serde = ["dep:serde"]
crypto = ["dep:cmac", "dep:aes"]
regions = []

View File

@ -4,4 +4,4 @@
test:
cargo fmt --check
cargo clippy
cargo test
cargo test --all-features

View File

@ -2,16 +2,23 @@ use std::fmt;
use std::str::FromStr;
use anyhow::Result;
use diesel::backend::{self, Backend};
use diesel::sql_types::Binary;
use diesel::{deserialize, serialize};
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "diesel")]
use diesel::{
backend::{self, Backend},
deserialize, serialize,
sql_types::Binary,
};
#[cfg(feature = "serde")]
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use crate::Error;
#[derive(Copy, Clone, PartialEq, Eq, AsExpression, FromSqlRow, Default)]
#[diesel(sql_type = diesel::sql_types::Binary)]
#[derive(Copy, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))]
pub struct AES128Key([u8; 16]);
impl AES128Key {
@ -64,6 +71,7 @@ impl FromStr for AES128Key {
}
}
#[cfg(feature = "serde")]
impl Serialize for AES128Key {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -73,6 +81,7 @@ impl Serialize for AES128Key {
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for AES128Key {
fn deserialize<D>(deserialize: D) -> Result<AES128Key, D::Error>
where
@ -82,8 +91,10 @@ impl<'de> Deserialize<'de> for AES128Key {
}
}
#[cfg(feature = "serde")]
struct Aes128KeyVisitor;
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for Aes128KeyVisitor {
type Value = AES128Key;
@ -99,6 +110,7 @@ impl<'de> Visitor<'de> for Aes128KeyVisitor {
}
}
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Binary, DB> for AES128Key
where
DB: Backend,
@ -117,6 +129,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Binary, diesel::pg::Pg> for AES128Key
where
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,

View File

@ -1,7 +1,9 @@
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::Serialize;
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum CFList {
Channels(CFListChannels),
ChannelMask(CFListChannelMasks),
@ -38,7 +40,8 @@ impl CFList {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct CFListChannels([u32; 5]);
impl CFListChannels {
@ -98,7 +101,8 @@ impl CFListChannels {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct CFListChannelMasks(Vec<ChMask>);
impl CFListChannelMasks {
@ -141,7 +145,8 @@ impl CFListChannelMasks {
/// ChMask encodes the channels usable for uplink access. 0 = channel 1,
/// 15 = channel 16.
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ChMask([bool; 16]);
impl ChMask {

View File

@ -2,8 +2,17 @@ use std::fmt;
use std::str::FromStr;
use anyhow::Result;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "diesel")]
use diesel::{
backend::{self, Backend},
deserialize, serialize,
sql_types::Binary,
};
#[cfg(feature = "serde")]
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use super::netid::NetID;
use crate::Error;
@ -58,6 +67,7 @@ impl FromStr for DevAddrPrefix {
}
}
#[cfg(feature = "serde")]
impl Serialize for DevAddrPrefix {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -67,6 +77,7 @@ impl Serialize for DevAddrPrefix {
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for DevAddrPrefix {
fn deserialize<D>(deserialize: D) -> Result<DevAddrPrefix, D::Error>
where
@ -76,8 +87,10 @@ impl<'de> Deserialize<'de> for DevAddrPrefix {
}
}
#[cfg(feature = "serde")]
struct DevAddrPrefixVisitor;
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for DevAddrPrefixVisitor {
type Value = DevAddrPrefix;
@ -93,8 +106,9 @@ impl<'de> Visitor<'de> for DevAddrPrefixVisitor {
}
}
#[derive(PartialEq, Eq, Copy, Clone, AsExpression, FromSqlRow, Default)]
#[diesel(sql_type = diesel::sql_types::Binary)]
#[derive(PartialEq, Eq, Copy, Clone, Default)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))]
pub struct DevAddr([u8; 4]);
impl DevAddr {
@ -226,6 +240,7 @@ impl FromStr for DevAddr {
}
}
#[cfg(feature = "serde")]
impl Serialize for DevAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -235,10 +250,7 @@ impl Serialize for DevAddr {
}
}
use diesel::backend::{self, Backend};
use diesel::sql_types::Binary;
use diesel::{deserialize, serialize};
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Binary, DB> for DevAddr
where
DB: Backend,
@ -257,6 +269,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Binary, diesel::pg::Pg> for DevAddr
where
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,

View File

@ -1,7 +1,9 @@
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::Serialize;
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DLSettings {
pub opt_neg: bool,
pub rx2_dr: u8,

View File

@ -2,13 +2,23 @@ use std::fmt;
use std::str::FromStr;
use anyhow::Result;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "diesel")]
use diesel::{
backend::{self, Backend},
deserialize, serialize,
sql_types::Binary,
};
#[cfg(feature = "serde")]
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use crate::Error;
#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow, Default)]
#[diesel(sql_type = diesel::sql_types::Binary)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))]
pub struct EUI64([u8; 8]);
impl EUI64 {
@ -69,6 +79,7 @@ impl FromStr for EUI64 {
}
}
#[cfg(feature = "serde")]
impl Serialize for EUI64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -78,6 +89,7 @@ impl Serialize for EUI64 {
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for EUI64 {
fn deserialize<D>(deserialize: D) -> Result<EUI64, D::Error>
where
@ -87,8 +99,10 @@ impl<'de> Deserialize<'de> for EUI64 {
}
}
#[cfg(feature = "serde")]
struct Eui64Visitor;
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for Eui64Visitor {
type Value = EUI64;
@ -104,10 +118,7 @@ impl<'de> Visitor<'de> for Eui64Visitor {
}
}
use diesel::backend::{self, Backend};
use diesel::sql_types::Binary;
use diesel::{deserialize, serialize};
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Binary, DB> for EUI64
where
DB: Backend,
@ -126,6 +137,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Binary, diesel::pg::Pg> for EUI64
where
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
@ -138,6 +150,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl diesel::sql_types::SqlType for EUI64 {
type IsNull = diesel::sql_types::is_nullable::NotNull;
}

View File

@ -1,10 +1,12 @@
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::Serialize;
use super::devaddr::DevAddr;
use super::maccommand::MACCommandSet;
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct FHDR {
pub devaddr: DevAddr,
pub f_ctrl: FCtrl,
@ -82,7 +84,8 @@ impl FHDR {
}
}
#[derive(Serialize, Default, Debug, PartialEq, Eq, Clone)]
#[derive(Default, Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct FCtrl {
pub adr: bool,
pub adr_ack_req: bool,

View File

@ -1,3 +1,4 @@
#[cfg(feature = "diesel")]
#[macro_use]
extern crate diesel;
#[macro_use]
@ -25,12 +26,14 @@ mod dl_settings;
mod error;
mod eui64;
mod fhdr;
#[cfg(feature = "crypto")]
pub mod keys;
mod maccommand;
mod mhdr;
mod netid;
mod payload;
mod phy_payload;
#[cfg(feature = "regions")]
pub mod region;
lazy_static! {

View File

@ -3,12 +3,14 @@ use std::ops::{Deref, DerefMut};
use std::time::Duration;
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::Serialize;
use super::cflist::ChMask;
use super::dl_settings::DLSettings;
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum CID {
ResetInd,
ResetConf,
@ -83,7 +85,8 @@ impl CID {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum MACCommand {
ResetInd(ResetIndPayload),
ResetConf(ResetConfPayload),
@ -170,7 +173,8 @@ impl MACCommand {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum Version {
LoRaWAN1_1,
}
@ -198,13 +202,15 @@ impl fmt::Display for Version {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum DwellTime {
NoLimit,
Limit400ms,
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum DeviceModeClass {
ClassA,
ClassC,
@ -242,7 +248,8 @@ impl fmt::Display for DeviceModeClass {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct MACCommandSet(Vec<MACCommand>);
impl Deref for MACCommandSet {
@ -780,7 +787,8 @@ impl MACCommandSet {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ResetIndPayload {
pub dev_lorawan_version: Version,
}
@ -803,7 +811,8 @@ impl ResetIndPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ResetConfPayload {
pub serv_lorawan_version: Version,
}
@ -826,7 +835,8 @@ impl ResetConfPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LinkCheckAnsPayload {
pub margin: u8,
pub gw_cnt: u8,
@ -851,7 +861,8 @@ impl LinkCheckAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LinkADRReqPayload {
pub dr: u8,
pub tx_power: u8,
@ -894,7 +905,8 @@ impl LinkADRReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Redundancy {
pub ch_mask_cntl: u8,
pub nb_rep: u8,
@ -922,7 +934,8 @@ impl Redundancy {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LinkADRAnsPayload {
pub ch_mask_ack: bool,
pub dr_ack: bool,
@ -961,7 +974,8 @@ impl LinkADRAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DutyCycleReqPayload {
pub max_duty_cycle: u8,
}
@ -988,7 +1002,8 @@ impl DutyCycleReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RxParamSetupReqPayload {
pub frequency: u32,
pub dl_settings: DLSettings,
@ -1029,7 +1044,8 @@ impl RxParamSetupReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RxParamSetupAnsPayload {
pub channel_ack: bool,
pub rx2_dr_ack: bool,
@ -1066,7 +1082,8 @@ impl RxParamSetupAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DevStatusAnsPayload {
pub battery: u8,
pub margin: i8,
@ -1110,7 +1127,8 @@ impl DevStatusAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct NewChannelReqPayload {
pub ch_index: u8,
pub freq: u32,
@ -1177,7 +1195,8 @@ impl NewChannelReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct NewChannelAnsPayload {
pub channel_freq_ok: bool,
pub dr_range_ok: bool,
@ -1209,7 +1228,8 @@ impl NewChannelAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RxTimingSetupReqPayload {
pub delay: u8,
}
@ -1234,7 +1254,8 @@ impl RxTimingSetupReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct TxParamSetupReqPayload {
pub uplink_dwell_time: DwellTime,
pub downlink_dwell_time: DwellTime,
@ -1285,7 +1306,8 @@ impl TxParamSetupReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DlChannelReqPayload {
pub ch_index: u8,
pub freq: u32,
@ -1327,7 +1349,8 @@ impl DlChannelReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DlChannelAnsPayload {
pub uplink_freq_exists: bool,
pub channel_freq_ok: bool,
@ -1361,7 +1384,8 @@ impl DlChannelAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RekeyConfPayload {
pub serv_lorawan_version: Version,
}
@ -1384,7 +1408,8 @@ impl RekeyConfPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RekeyIndPayload {
pub dev_lorawan_version: Version,
}
@ -1407,7 +1432,8 @@ impl RekeyIndPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ADRParamSetupReqPayload {
pub adr_param: ADRParam,
}
@ -1430,7 +1456,8 @@ impl ADRParamSetupReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ADRParam {
pub limit_exp: u8,
pub delay_exp: u8,
@ -1462,7 +1489,8 @@ impl ADRParam {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DeviceTimeAnsPayload {
pub time_since_gps_epoch: Duration,
}
@ -1496,7 +1524,8 @@ impl DeviceTimeAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ForceRejoinReqPayload {
pub period: u8,
pub max_retries: u8,
@ -1541,7 +1570,8 @@ impl ForceRejoinReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RejoinParamSetupReqPayload {
pub max_time_n: u8,
pub max_count_n: u8,
@ -1573,7 +1603,8 @@ impl RejoinParamSetupReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RejoinParamSetupAnsPayload {
pub time_ok: bool,
}
@ -1600,7 +1631,8 @@ impl RejoinParamSetupAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PingSlotInfoReqPayload {
pub periodicity: u8,
}
@ -1627,7 +1659,8 @@ impl PingSlotInfoReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PingSlotChannelReqPayload {
pub freq: u32,
pub dr: u8,
@ -1669,7 +1702,8 @@ impl PingSlotChannelReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PingSlotChannelAnsPayload {
pub dr_ok: bool,
pub channel_freq_ok: bool,
@ -1704,7 +1738,8 @@ impl PingSlotChannelAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct BeaconFreqReqPayload {
pub freq: u32,
}
@ -1741,7 +1776,8 @@ impl BeaconFreqReqPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct BeaconFreqAnsPayload {
beacon_freq_ok: bool,
}
@ -1768,7 +1804,8 @@ impl BeaconFreqAnsPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DeviceModeIndPayload {
pub class: DeviceModeClass,
}
@ -1791,7 +1828,8 @@ impl DeviceModeIndPayload {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct DeviceModeConfPayload {
pub class: DeviceModeClass,
}

View File

@ -1,9 +1,11 @@
use std::fmt;
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::Serialize;
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum MType {
JoinRequest,
JoinAccept,
@ -21,12 +23,14 @@ impl fmt::Display for MType {
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum Major {
LoRaWANR1,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct MHDR {
pub m_type: MType,
pub major: Major,

View File

@ -2,8 +2,11 @@ use std::fmt;
use std::str::FromStr;
use anyhow::Result;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")]
use serde::{
de::{self, Visitor},
{Deserialize, Deserializer, Serialize, Serializer},
};
use crate::devaddr::DevAddrPrefix;
use crate::Error;
@ -132,6 +135,7 @@ impl FromStr for NetID {
}
}
#[cfg(feature = "serde")]
impl Serialize for NetID {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -141,6 +145,7 @@ impl Serialize for NetID {
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for NetID {
fn deserialize<D>(deserialize: D) -> Result<NetID, D::Error>
where
@ -150,8 +155,10 @@ impl<'de> Deserialize<'de> for NetID {
}
}
#[cfg(feature = "serde")]
struct NetIdVisitor;
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for NetIdVisitor {
type Value = NetID;

View File

@ -1,4 +1,5 @@
use anyhow::Result;
#[cfg(feature = "serde")]
use serde::{Serialize, Serializer};
use super::cflist::CFList;
@ -21,6 +22,7 @@ pub enum Payload {
Raw(Vec<u8>),
}
#[cfg(feature = "serde")]
impl Serialize for Payload {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -37,7 +39,8 @@ impl Serialize for Payload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum JoinType {
Join,
RejoinType0,
@ -85,7 +88,8 @@ impl Payload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Copy, Clone)]
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct JoinRequestPayload {
pub join_eui: EUI64,
pub dev_eui: EUI64,
@ -120,7 +124,8 @@ impl JoinRequestPayload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct JoinAcceptPayload {
pub join_nonce: u32, // the actual max value is (2^24 -1)
pub home_netid: NetID,
@ -191,6 +196,7 @@ pub enum FRMPayload {
MACCommandSet(MACCommandSet),
}
#[cfg(feature = "serde")]
impl Serialize for FRMPayload {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -212,7 +218,8 @@ impl FRMPayload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Clone, Default)]
#[derive(PartialEq, Eq, Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct MACPayload {
pub fhdr: FHDR,
pub f_port: Option<u8>,
@ -287,7 +294,8 @@ impl MACPayload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RejoinRequestType02Payload {
pub rejoin_type: JoinType,
pub netid: NetID,
@ -343,7 +351,8 @@ impl RejoinRequestType02Payload {
}
}
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RejoinRequestType1Payload {
pub rejoin_type: JoinType,
pub join_eui: EUI64,

View File

@ -1,17 +1,27 @@
use aes::cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt};
use aes::{Aes128, Block};
#[cfg(feature = "crypto")]
use aes::{
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt},
Aes128, Block,
};
use anyhow::Result;
#[cfg(feature = "crypto")]
use cmac::{Cmac, Mac};
#[cfg(feature = "serde")]
use serde::Serialize;
use super::aes128::AES128Key;
use super::devaddr::DevAddr;
use super::eui64::EUI64;
use super::maccommand::{MACCommand, MACCommandSet};
use super::mhdr::{MType, MHDR};
use super::payload::{FRMPayload, JoinAcceptPayload, JoinType, Payload};
use super::payload::{FRMPayload, Payload};
#[cfg(feature = "crypto")]
use super::{
aes128::AES128Key,
devaddr::DevAddr,
eui64::EUI64,
payload::{JoinAcceptPayload, JoinType},
};
#[derive(PartialEq, Eq, Clone, Copy, Serialize)]
#[derive(PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum MACVersion {
LoRaWAN1_0,
LoRaWAN1_1,
@ -310,7 +320,8 @@ pub enum MACVersion {
/// let phy_decoded = PhyPayload::from_slice(&bytes).unwrap();
/// assert_eq!(phy, phy_decoded);
/// ```
#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PhyPayload {
pub mhdr: MHDR,
pub payload: Payload,
@ -374,6 +385,7 @@ impl PhyPayload {
/// Calculate and set the MIC field for uplink data frames.
/// The conf_f_cnt, tx_dr, tx_ch and s_nwk_s_int_key are only required for LoRaWAN 1.1 and can
/// be left blank for LoRaWAN 1.0.
#[cfg(feature = "crypto")]
pub fn set_uplink_data_mic(
&mut self,
mac_version: MACVersion,
@ -399,6 +411,7 @@ impl PhyPayload {
/// frame-counter value, as only the 16 lsb are transmitted over the air.
/// The conf_f_cnt, tx_dr, tx_ch and s_nwk_s_int_key are only required for LoRaWAN 1.1 and can
/// be left blank for LoRaWAN 1.0.
#[cfg(feature = "crypto")]
pub fn validate_uplink_data_mic(
&self,
mac_version: MACVersion,
@ -425,6 +438,7 @@ impl PhyPayload {
/// Set the MIC for downlink data frames.
/// The conf_f_cnt is only required for LoRaWAN 1.1 and can be left blank for LoRaWAN 1.0.
#[cfg(feature = "crypto")]
pub fn set_downlink_data_mic(
&mut self,
mac_version: MACVersion,
@ -436,6 +450,7 @@ impl PhyPayload {
Ok(())
}
#[cfg(feature = "crypto")]
pub fn validate_downlink_data_mic(
&mut self,
mac_version: MACVersion,
@ -453,6 +468,7 @@ impl PhyPayload {
/// Validate the cmacF part of the uplink data MIC (LoRaWAN 1.1 only).
/// In order to validate the MIC, the f_cnt value must be first set to the full 32 bit
/// frame-counter value, as only the 16 lsb are transmitted over the air.
#[cfg(feature = "crypto")]
pub fn validate_uplink_data_micf(&self, f_nwk_s_int_key: &AES128Key) -> Result<bool> {
// We are only interested in mic[2:] (cmacF bytes), therefore there is no
// need to pass the correct confFCnt, txDR, txCh and sNwkSIntKey parameters.
@ -473,12 +489,14 @@ impl PhyPayload {
}
/// Set the join-request MIC.
#[cfg(feature = "crypto")]
pub fn set_join_request_mic(&mut self, key: &AES128Key) -> Result<()> {
self.mic = Some(self.calculate_upink_join_mic(key)?);
Ok(())
}
/// Validate the join-request MIC.
#[cfg(feature = "crypto")]
pub fn validate_join_request_mic(&self, key: &AES128Key) -> Result<bool> {
if let Some(v) = self.mic {
let mic = self.calculate_upink_join_mic(key)?;
@ -489,6 +507,7 @@ impl PhyPayload {
}
/// Set the the downlink join-accept MIC.
#[cfg(feature = "crypto")]
pub fn set_join_accept_mic(
&mut self,
join_req_type: JoinType,
@ -502,6 +521,7 @@ impl PhyPayload {
}
/// Validate the downlink join-accept MIC.
#[cfg(feature = "crypto")]
pub fn validate_join_accept_mic(
&self,
join_req_type: JoinType,
@ -522,6 +542,7 @@ impl PhyPayload {
/// the encrypted payload.
/// For encrypting a join-request response, use the nwk_key, for rejoin-request 0, 1 and 3
/// response, use the js_enc_key.
#[cfg(feature = "crypto")]
pub fn encrypt_join_accept_payload(&mut self, key: &AES128Key) -> Result<()> {
use aes::cipher::KeyInit;
@ -566,6 +587,7 @@ impl PhyPayload {
/// of the encrypted payload.
/// For decrypting a join-request response, use the nwk_key, for rejoin-request 0, 1 and 3
/// response, use the js_enc_key.
#[cfg(feature = "crypto")]
pub fn decrypt_join_accept_payload(&mut self, key: &AES128Key) -> Result<()> {
use aes::cipher::KeyInit;
@ -608,6 +630,7 @@ impl PhyPayload {
}
/// Encrypt the f_opts with the given key.
#[cfg(feature = "crypto")]
pub fn encrypt_f_opts(&mut self, nwk_s_enc_key: &AES128Key) -> Result<()> {
if let Payload::MACPayload(pl) = &mut self.payload {
let f_opts_bytes = pl.fhdr.f_opts.to_vec()?;
@ -638,6 +661,7 @@ impl PhyPayload {
/// Decrypt the f_opts with the given key.
/// This automatically calls decode_f_opts_to_mac_commands.
#[cfg(feature = "crypto")]
pub fn decrypt_f_opts(&mut self, nwk_s_enc_key: &AES128Key) -> Result<()> {
self.encrypt_f_opts(nwk_s_enc_key)?;
self.decode_f_opts_to_mac_commands()?;
@ -674,6 +698,7 @@ impl PhyPayload {
}
/// Encrypt the frm_payload with the given key.
#[cfg(feature = "crypto")]
pub fn encrypt_frm_payload(&mut self, key: &AES128Key) -> Result<()> {
if let Payload::MACPayload(pl) = &mut self.payload {
// nothing to do
@ -693,6 +718,7 @@ impl PhyPayload {
}
/// Decrypt the frm_payload with the given key.
#[cfg(feature = "crypto")]
pub fn decrypt_frm_payload(&mut self, key: &AES128Key) -> Result<()> {
if let Payload::MACPayload(pl) = &mut self.payload {
// nothing to do
@ -718,6 +744,7 @@ impl PhyPayload {
Err(anyhow!("payload must be of type MACPayload"))
}
#[cfg(feature = "crypto")]
fn calculate_uplink_data_mic(
&self,
mac_version: MACVersion,
@ -797,6 +824,7 @@ impl PhyPayload {
Err(anyhow!("payload must be of type MACPayload"))
}
#[cfg(feature = "crypto")]
fn calculate_downlink_data_mic(
&self,
mac_version: MACVersion,
@ -844,6 +872,7 @@ impl PhyPayload {
Err(anyhow!("payload must be of type MACPayload"))
}
#[cfg(feature = "crypto")]
fn calculate_upink_join_mic(&self, key: &AES128Key) -> Result<[u8; 4]> {
// mic bytes
let mut mic_bytes = Vec::new();
@ -864,6 +893,7 @@ impl PhyPayload {
Ok(mic)
}
#[cfg(feature = "crypto")]
fn calculate_downlink_join_mic(
&self,
join_req_type: JoinType,
@ -916,6 +946,7 @@ impl PhyPayload {
/// Set the a_fcnt_down to false and use the n_fcnt_down as f_cnt.
/// For downlink if f_port > 0:
/// Set the a_fcnt_down to true and use the a_f_cnt_down as f_cnt.
#[cfg(feature = "crypto")]
pub fn encrypt_f_opts(
nwk_s_enc_key: &AES128Key,
a_fcnt_down: bool,
@ -963,6 +994,7 @@ pub fn encrypt_f_opts(
/// Encrypt (and decrypt) the frm_payload.
/// Note that the same function is used for encryption and decryption.
#[cfg(feature = "crypto")]
pub fn encrypt_frm_payload(
key: &AES128Key,
uplink: bool,

View File

@ -4,9 +4,13 @@ use std::str::FromStr;
use std::time::Duration;
use anyhow::{Context, Result};
use diesel::backend::{self, Backend};
use diesel::sql_types::Text;
use diesel::{deserialize, serialize};
#[cfg(feature = "diesel")]
use diesel::{
backend::{self, Backend},
sql_types::Text,
{deserialize, serialize},
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
@ -25,9 +29,11 @@ pub mod kr920;
pub mod ru864;
pub mod us915;
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq, AsExpression, FromSqlRow)]
#[allow(non_camel_case_types)]
#[diesel(sql_type = diesel::sql_types::Text)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))]
pub enum CommonName {
EU868,
US915,
@ -51,6 +57,7 @@ impl fmt::Display for CommonName {
}
}
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Text, DB> for CommonName
where
DB: Backend,
@ -62,6 +69,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Text, diesel::pg::Pg> for CommonName
where
str: serialize::ToSql<Text, diesel::pg::Pg>,
@ -104,8 +112,9 @@ impl FromStr for CommonName {
}
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, AsExpression, FromSqlRow)]
#[diesel(sql_type = diesel::sql_types::Text)]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))]
pub enum Revision {
Latest,
A,
@ -159,6 +168,7 @@ impl FromStr for Revision {
}
}
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Text, DB> for Revision
where
DB: Backend,
@ -170,6 +180,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Text, diesel::pg::Pg> for Revision
where
str: serialize::ToSql<Text, diesel::pg::Pg>,
@ -186,8 +197,9 @@ where
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow)]
#[diesel(sql_type = diesel::sql_types::Text)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))]
pub enum MacVersion {
Latest,
LORAWAN_1_0_0,
@ -241,6 +253,7 @@ impl FromStr for MacVersion {
}
}
#[cfg(feature = "diesel")]
impl<DB> deserialize::FromSql<Text, DB> for MacVersion
where
DB: Backend,
@ -252,6 +265,7 @@ where
}
}
#[cfg(feature = "diesel")]
impl serialize::ToSql<Text, diesel::pg::Pg> for MacVersion
where
str: serialize::ToSql<Text, diesel::pg::Pg>,