Skip to content

Commit

Permalink
examples: nrf52840: Support customising LoRaWAN keys via ENV
Browse files Browse the repository at this point in the history
Add possibility to overriding LoRaWAN keys from env during compile.
  • Loading branch information
plaes committed Mar 28, 2024
1 parent f0e1dc5 commit 57c1c13
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 14 deletions.
5 changes: 3 additions & 2 deletions examples/nrf52840/Cargo.toml
Expand Up @@ -26,6 +26,7 @@ debug = 2

[features]
default = []

## Customize target binary to make it runnable from RAM (ie via teleprobe)
## Customize target binary to make it runnable from RAM
link-to-ram = []
# Add teleprobe specific hooks to code
teleprobe = ["link-to-ram"]
69 changes: 66 additions & 3 deletions examples/nrf52840/build.rs
Expand Up @@ -10,14 +10,77 @@

use std::env;
use std::fs::File;
use std::io::Write;
use std::io::{BufWriter, Write};
use std::path::PathBuf;

fn hex_to_bytes(s: &str) -> Option<Vec<u8>> {
if s.len() % 2 == 0 {
(0..s.len())
.step_by(2)
.map(|i| s.get(i..i + 2).and_then(|sub| u8::from_str_radix(sub, 16).ok()))
.collect()
} else {
None
}
}

/// Read and parse LoRaWAN keys as HEX strings from an environment variable
fn parse_lorawan_id(val: Option<&str>, var: &str, len: usize) -> Option<String> {
if let Some(s) = val {
let l = s.len();
// Allow empty keys
if l == 0 {
return None;
}
if l % 2 == 1 || l != 2 * len {
panic!(
"Environment variable {} has invalid length: {}, expecting: {}",
&var,
l,
2 * len
);
}
if let Some(v) = hex_to_bytes(s) {
return Some(format!("Some({:?})", v));
} else {
panic!(
"Unable to parse {} from environment, make sure it's a valid hex string with length {}",
&var,
2 * len
);
}
}
None
}

fn main() {
// Put linker configuration in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());

// Generate LoRaWAN eui and key overrides from environment variables
{
let path = &out.join("lorawan_keys.rs");
let mut file = BufWriter::new(File::create(&path).unwrap());

// TODO: Figure out how to not generate this file every time...
write!(
&mut file,
"{}",
format_args!(
"\
// Generated by build.rs\n\
const DEVEUI: Option<[u8; 8]> = {};\n\
const APPEUI: Option<[u8; 8]> = {};\n\
const APPKEY: Option<[u8; 16]> = {};\n",
parse_lorawan_id(option_env!("LORA_DEVEUI"), "LORA_DEVEUI", 8).unwrap_or("None".to_string()),
parse_lorawan_id(option_env!("LORA_APPEUI"), "LORA_APPEUI", 8).unwrap_or("None".to_string()),
parse_lorawan_id(option_env!("LORA_APPKEY"), "LORA_APPKEY", 16).unwrap_or("None".to_string()),
)
)
.unwrap();
}

// Put linker configuration in our output directory and ensure it's
// on the linker search path.
if cfg!(feature = "link-to-ram") {
File::create(out.join("link_ram_cortex_m.x"))
.unwrap()
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf52840/src/bin/lora_cad.rs
Expand Up @@ -11,7 +11,7 @@ use embassy_nrf::{bind_interrupts, peripherals, spim};
use embassy_time::{Delay, Timer};
use embedded_hal_bus::spi::ExclusiveDevice;
use lora_phy::iv::GenericSx126xInterfaceVariant;
use lora_phy::sx126x::{Sx126xVariant, TcxoCtrlVoltage, Sx126x};
use lora_phy::sx126x::{Sx126x, Sx126xVariant, TcxoCtrlVoltage};
use lora_phy::LoRa;
use lora_phy::{mod_params::*, sx126x};
use {defmt_rtt as _, panic_probe as _};
Expand Down
21 changes: 16 additions & 5 deletions examples/nrf52840/src/bin/lora_lorawan.rs
Expand Up @@ -13,7 +13,7 @@ use embassy_time::Delay;
use embedded_hal_bus::spi::ExclusiveDevice;
use lora_phy::iv::GenericSx126xInterfaceVariant;
use lora_phy::lorawan_radio::LorawanRadio;
use lora_phy::sx126x::{self, Sx126xVariant, TcxoCtrlVoltage, Sx126x};
use lora_phy::sx126x::{self, Sx126x, Sx126xVariant, TcxoCtrlVoltage};
use lora_phy::LoRa;
use lorawan_device::async_device::{region, Device, EmbassyTimer, JoinMode};
use lorawan_device::default_crypto::DefaultFactory as Crypto;
Expand All @@ -24,6 +24,15 @@ use {defmt_rtt as _, panic_probe as _};
const LORAWAN_REGION: region::Region = region::Region::EU868;
const MAX_TX_POWER: u8 = 14;

// Load optional override values for EUIs and APPKEY generated by build.rs from
// environment values
include!(concat!(env!("OUT_DIR"), "/lorawan_keys.rs"));

// Fallback values
const DEFAULT_DEVEUI: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
const DEFAULT_APPEUI: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
const DEFAULT_APPKEY: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

bind_interrupts!(struct Irqs {
SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
RNG => rng::InterruptHandler<peripherals::RNG>;
Expand Down Expand Up @@ -60,15 +69,17 @@ async fn main(_spawner: Spawner) {

defmt::info!("Joining LoRaWAN network");

// TODO: Adjust the EUI and Keys according to your network credentials
let resp = device
.join(&JoinMode::OTAA {
deveui: DevEui::from([0, 0, 0, 0, 0, 0, 0, 0]),
appeui: AppEui::from([0, 0, 0, 0, 0, 0, 0, 0]),
appkey: AppKey::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
deveui: DevEui::from(DEVEUI.unwrap_or(DEFAULT_DEVEUI)),
appeui: AppEui::from(APPEUI.unwrap_or(DEFAULT_APPEUI)),
appkey: AppKey::from(APPKEY.unwrap_or(DEFAULT_APPKEY)),
})
.await
.unwrap();

info!("LoRaWAN network joined: {:?}", resp);

#[cfg(feature = "teleprobe")]
cortex_m::asm::bkpt();
}
2 changes: 1 addition & 1 deletion examples/nrf52840/src/bin/lora_p2p_receive.rs
Expand Up @@ -11,7 +11,7 @@ use embassy_nrf::{bind_interrupts, peripherals, spim};
use embassy_time::{Delay, Timer};
use embedded_hal_bus::spi::ExclusiveDevice;
use lora_phy::iv::GenericSx126xInterfaceVariant;
use lora_phy::sx126x::{Sx126xVariant, TcxoCtrlVoltage, Sx126x};
use lora_phy::sx126x::{Sx126x, Sx126xVariant, TcxoCtrlVoltage};
use lora_phy::{mod_params::*, sx126x};
use lora_phy::{LoRa, RxMode};
use {defmt_rtt as _, panic_probe as _};
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
Expand Up @@ -11,7 +11,7 @@ use embassy_nrf::{bind_interrupts, peripherals, spim};
use embassy_time::{Delay, Timer};
use embedded_hal_bus::spi::ExclusiveDevice;
use lora_phy::iv::GenericSx126xInterfaceVariant;
use lora_phy::sx126x::{Sx126xVariant, TcxoCtrlVoltage, Sx126x};
use lora_phy::sx126x::{Sx126x, Sx126xVariant, TcxoCtrlVoltage};
use lora_phy::{mod_params::*, sx126x};
use lora_phy::{LoRa, RxMode};
use {defmt_rtt as _, panic_probe as _};
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf52840/src/bin/lora_p2p_send.rs
Expand Up @@ -11,7 +11,7 @@ use embassy_nrf::{bind_interrupts, peripherals, spim};
use embassy_time::Delay;
use embedded_hal_bus::spi::ExclusiveDevice;
use lora_phy::iv::GenericSx126xInterfaceVariant;
use lora_phy::sx126x::{Sx126xVariant, TcxoCtrlVoltage, Sx126x};
use lora_phy::sx126x::{Sx126x, Sx126xVariant, TcxoCtrlVoltage};
use lora_phy::LoRa;
use lora_phy::{mod_params::*, sx126x};
use {defmt_rtt as _, panic_probe as _};
Expand Down

0 comments on commit 57c1c13

Please sign in to comment.