Time-on-air, duty-cycle off-time, and the regional channel plans a LoRa node must keep to. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.
npm install @pamoja/lora
This pulls in @pamoja/native, the compiled engine. npm install pamoja is the whole framework in one package.
The test that runs in CI, spliced here as it ran.
From bindings/node/guides/lora.ts:
import { LoraRegion, airtimeUs, messagesPerHour, minOffTimeUs, planFor } from '@pamoja/lora'
// EU863-870 numbers its data rates from the slowest. DR0 is SF12 at 125 kHz, the setting
// that reaches furthest and holds the channel longest.
const plan = planFor(LoraRegion.Eu868)
const link = plan.linkSettings(0)!
console.log(`${plan.name} DR0 is SF${link.spreadingFactor} at 125 kHz`)
// The time on air for that setting, coding rate 4/5, an eight-symbol preamble, an explicit
// header and CRC on, carrying a ten-byte reading.
const airtime = airtimeUs(link, 10)
console.log(`airtime ${(airtime / 1e6).toFixed(2)} s for ten bytes`)
// 868.1 MHz falls in a sub-band capped at 1% of the time and 16 dBm, so every transmission
// buys ninety-nine times its own length in silence.
const channel = 868_100_000
const permille = plan.dutyCyclePermille(channel)!
console.log(`channel ${permille} per mille duty cycle, ${plan.maxEirpDbm(channel)} dBm`)
const offTime = minOffTimeUs(link, 10, permille)!
console.log(`silence ${(offTime / 1e6).toFixed(1)} s owed after each reading`)
// The airtime plus that silence is what one reading really costs, which is the budget a
// deployment plans against.
console.log(`budget ${messagesPerHour(link, 10, permille)} readings an hour`)
// A frequency in no sub-band the plan describes has no duty cycle to budget against. That
// is a limit published elsewhere, not permission to transmit.
const outside = plan.dutyCyclePermille(700_000_000)
console.log(`700 MHz is outside this plan, so it budgets nothing: ${outside === null}`)
| Language | Package | Reference |
|---|---|---|
| Rust | pamoja-lora |
reference, docs.rs, install |
| TypeScript | @pamoja/lora |
reference, install |
| Python | pamoja-lora |
reference, install |
| C# | Pamoja.Lora |
reference, install |
@pamoja/lora reference, every class, function, and type this package exports.MIT
Ergonomic facade over the generated LoRa binding.
LoRa buys kilometres of range on license-free bands at tiny power, and the price is time: a transmission occupies the channel for a duration the radio settings fix, and the regional rules cap how much of the time a node may transmit. This is the arithmetic that keeps a node inside that budget, with no radio and no floating point in the answer.