Expand description
§ados-lora
LoRa transmit governor with cited regional band plans: time-on-air, duty cycle, dwell time, listen-before-talk, power limits and a persisted airtime ledger.
Sub-GHz LoRa bands are licence-exempt only while every transmitter keeps to its region’s limits on duty cycle, dwell time, power and channel access. This crate decides, frame by frame, whether a transmission is legal right now, on which channel and at what power, and charges the airtime to an append-only ledger that survives crashes and reboots. Reach for it when a device sends LoRa frames and must stay inside the band plan without a human watching.
use ados_lora::airtime::Modem;
use ados_lora::band::ModuleCaps;
use ados_lora::governor::power::Antenna;
use ados_lora::governor::{max_window_s, Governor, Setup};
use ados_lora::ledger::{Ledger, Now};
use ados_lora::regions::resolve;
// Resolve the EU868 plan from an explicit region code.
let resolved = resolve(Some("EU"), None).expect("EU has a plan");
assert_eq!(resolved.plan.plan_id, "EU868");
let now = Now { mono_ns: 0, utc_ms: 1_760_000_000_000, utc_trusted: false };
let dir = std::env::temp_dir().join(format!("lora-gov-doc-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let window = max_window_s(Some(resolved.plan));
let (ledger, _report) = Ledger::open(&dir.join("airtime.jsonl"), "boot-1", now, window).unwrap();
let mut gov = Governor::new(
Setup {
resolved: Some(resolved),
caps: ModuleCaps::any(),
modem: Modem::SF9_BW125,
airtime_factor: 1,
freq_mhz: None,
erp_mw: None,
antenna: Antenna { gain_dbi: 2.15, cable_loss_db: 0.0 },
node_id: 7,
},
ledger,
);
// Ask to send 20 bytes on 868.1 MHz (sub-band M: 1 % duty, 25 mW ERP).
let grant = gov.admit(20, Some(868.1), now).expect("admitted");
assert_eq!(grant.sub_band, "868.0-868.6");
gov.commit(&grant, now).unwrap(); // charge the ledger before transmitting
gov.note_sent();
println!("{} MHz at {} dBm, {} us on air", grant.channel_mhz, grant.power_dbm, grant.airtime_us);§Highlights
- Compiled band-plan table where every enforced number carries the regulator document it comes from.
- Exact LoRa time-on-air from the Semtech SX1261/2 datasheet formula.
- Charge-then-send ledger: each admitted frame is appended and fsync’d before it is sent, so a crash over-counts and never under-counts, and a reboot cannot reset the duty budget.
- Fixed check order with a named refusal reason for each rule (region, module band, power, dwell, duty, listen-before-talk).
- Three runtime dependencies:
serde,serde_json,tracing.
§How it works
Modules:
-
regions: the compiled regional band-plan table and region resolution. A row that ships with rules transmits under them; a row whose limits could not all be cited from the regulator text ships with its bands only and is receive-only. Resolution takes an explicit region code first, else a country code mapped to a plan, else none (transmit blocked withregion_unset, receive still on). -
band: what the fitted radio can tune and whether that meets a plan. A plan is supported when at least one tunable channel fits wholly inside a plan sub-band, on the plan’s channel grid where it has one, with at least the plan’s minimum hop-channel count, and with ambient RSSI available where the plan requires listen-before-talk. Otherwise transmit is blocked withmodule_band_mismatch. -
airtime: time on air.T_sym = 2^SF / BW T_pre = (N_pre + 4.25) * T_sym N_pay = 8 + max(ceil((8 PL - 4 SF + 28 + 16 CRC - 20 IH) / (4 (SF - 2 DE))) * (CR + 4), 0) T_oa = T_pre + N_pay * T_symLow data-rate optimisation (
DE) is on whenT_sym >= 16 ms, which is SF11 and SF12 at 125 kHz. -
ledger: the persisted airtime ledger. One JSON line per admitted frame, plus a heartbeat line every minute that bounds how much downtime is credited. On load, entries from this boot keep their monotonic time; entries from a previous boot are aged by UTC when both clocks are trusted, else placed at the last trusted heartbeat, else treated as occurring at start. A torn last line is dropped; any other corrupt line moves the file aside and starts every duty rule exhausted for one full window. -
governor: the admit pipeline.Governor::admitruns region, module band,max_power,dwell_timeandduty_cycleagainst the plan and the ledger; the first refusal wins. Listen-before-talk needs the radio, so the caller runs it on the granted channel and reports the outcome withcommitorrefuse. A commit charges the ledger before the frame is sent.
§Part of ADOS
Used in production by the ADOS Drone Agent, the onboard software of the ADOS software-defined drone platform. All ADOS crates · Docs · Discord
§Other ADOS crates
Platform (versioned with the ADOS Drone Agent)
| Crate | What it does | Docs |
|---|---|---|
ados-protocol | Wire contracts of the ADOS Drone Agent: IPC framing, plugin RPC envelope, capability tokens and the vision frame bus. | docs.rs |
ados-sdk | Write Rust plugins for the ADOS Drone Agent: IPC client, plugin context, driver traits and lifecycle runner. | docs.rs |
ados-vision | Single-object visual tracker: Kalman motion model, appearance re-identification and YOLOv8 head decoding. | docs.rs |
ados-gpio | Drive status buzzers and LEDs on Linux GPIO lines, with bounded software-PWM beep patterns. | docs.rs |
ados-hal-probe | Find out what a board’s hardware can really do by probing it, plus bundled board profiles. | docs.rs |
Standalone
| Crate | What it does | Docs |
|---|---|---|
ados-sensorhub | Sensor hub wire protocol: COBS framing, CRC-16 and fixed-layout IMU, baro, mag and GNSS packets. no_std. | docs.rs |
ados-offload | Choose where perception runs (onboard, offloaded or hybrid) and hold the vehicle when results go stale. | docs.rs |
ados-macpin | Stable MAC addresses for Linux network adapters that randomize theirs every boot. | docs.rs |
ados-crsf-codec | no_std CRSF / ExpressLRS codec for RC channels, telemetry and parameter frames. | docs.rs |
ados-positioning | Split mixed UBX, NMEA and RTCM3 GNSS streams, configure u-blox receivers and run an RTK base survey-in. | docs.rs |
ados-rtcm | RTCM3 framing, CRC-24Q and MAVLink GPS_RTCM_DATA fragmentation for RTK corrections. | docs.rs |
ados-clock | Map remote clocks onto the host clock: least-squares and envelope fits, TIMESYNC and a chrony sink. | docs.rs |
ados-swarm | Swarm control laws: separation, flocking, formations, CBBA task allocation and a point-mass simulator. | docs.rs |
ados-mavlink-tunnel | Send large messages over MAVLink TUNNEL frames with chunking and bounded reassembly. | docs.rs |
ados-display-driver | Small-display output on Linux: SSD1306/SH1106 OLED over I2C, pixel packers and a framebuffer writer. | docs.rs |
ados-hmi | Front-panel input: touchscreen calibration and gestures, button presses and rotary encoders. | docs.rs |
§ADOS repositories
| Repo | Runs on | What it does | Link |
|---|---|---|---|
| ADOS Mission Control | Browser, desktop (Electron) | Ground control station: FC setup, mission planning, flight, 3D simulation, fleet | ADOSMissionControl |
| ADOS Drone Agent | Companion computer on the drone, or a ground node | Onboard agent: MAVLink routing, HD video, long-range radio link, plugins, remote control | ADOSDroneAgent |
| ADOS Android GCS | Android phones and tablets | Native ground control app for agents on the LAN, direct flight controllers and the cloud | ADOSAndroidGCS |
| ADOS Extensions | Drone Agent and Mission Control | First-party signed plugins, each with an agent half and a GCS half | ADOSExtensions |
| ADOS MCP | Your machine | Model Context Protocol server that lets AI clients operate ADOS drones under scopes and a safety gate | ADOS-MCP |
| Documentation | docs.altnautica.com | Public docs for every ADOS product | Documentation |
§License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Modules§
- airtime
- LoRa time on air, from the Semtech SX1261/2 datasheet (section 6.1.4):
- band
- What the fitted radio can tune, and whether that meets a plan.
- governor
- The transmit governor: every frame passes
Governor::admitbefore it reaches a radio. - ledger
- The persisted airtime ledger (charge-then-send).
- regions
- The compiled regional band-plan table and region resolution.