-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture Overview
Every node type derives from a common templated base class, Duck<WifiCapability, RadioType> (src/Ducks/Duck.h):
Duck<WifiCapability, RadioType> (src/Ducks/Duck.h)
├── DuckLink (leaf sensor node, no relay)
├── MamaDuck (core mesh relay node)
├── PapaDuck (gateway/sink node, WiFi/MQTT uplink)
└── DetectorDuck (RSSI survey tool, no data relay)
See Duck Types for what each subclass is for.
WifiCapability and RadioType are template parameters (defaulting to DuckWifiNone and DuckLoRa), so the same Duck subclass can be compiled with or without WiFi depending on the board/role.
A sketch typically does:
MamaDuck duck("MAMA0001");
void setup() {
duck.setupWithDefaults();
}
void loop() {
duck.run();
}setupWithDefaults() (in Duck.h) initializes, in order:
- Serial (115200 baud).
-
duckidentity::begin()— loads or generates this device's X25519 identity keypair (see Security and Encryption). -
opendmsconfig::begin(),meshgroupconfig::begin(),radioregionconfig::begin()— load any field-provisioned secrets/region from flash. -
setupLoRaRadio()— initializes the radio with the (possibly region-overridden) parameters.
run(), called every loop iteration, does:
- Services LoRa interrupt flags.
- Polls for serial provisioning commands (
AT+OPENDMSKEY=,AT+MESHKEY=,AT+RADIOREGION=, see Security and Encryption and Radio and Regions). - If the device hasn't joined a CDP network yet, attempts network join (RREQ-based discovery) or times out into
NetworkState::PUBLICafterNET_JOIN_DELAY * 5 + 5000ms.DetectorDuckbypasses this entirely and goes straight toPUBLIC. - Once
PUBLIC, dispatches any received radio packet tohandleReceivedPacket().
All Duck subclasses inherit several send methods from Duck, each targeting a different trust boundary:
| Method | Purpose | Encrypted? |
|---|---|---|
sendData(topic, data, targetDevice) |
Plain CDP send (string or byte-buffer overloads) | No |
sendSealedData(topic, data, targetDevice) |
One-way seal to MeshBeacon Ops's static public key | Yes (sealed, ephemeral) |
sendEncryptedData(topic, data, targetDevice) |
Duck-to-Duck session encryption | Yes (peer session) |
sendGroupData(topic, data, targetDevice) |
Broadcast authenticated with a shared mesh group key | Yes, if configured (falls back to plaintext otherwise) |
announceIdentity(targetDevice) |
Broadcast this Duck's own public key (TOFU) | N/A (key is not secret) |
Encryption is opt-in per call site and off by default — see Security and Encryption for the full design and reasoning.
Every send ultimately builds a CdpPacket (see Packet Format and Topics), asks DuckRouter for the best next hop, assigns a unique message ID via the bloom filter, and transmits over the radio (see Routing and Mesh and Radio and Regions).
| Directory | Contents |
|---|---|
src/Ducks/ |
Duck.h (base), MamaDuck.h, PapaDuck.h, DuckLink.h, DetectorDuck.h, DuckTypes.h
|
src/routing/ |
DuckRouter, bloomfilter, Neighbor, SignalScore, RouteJSON
|
src/radio/ |
DuckLoRa (RadioLib-based SX12xx driver), RadioRegionConfig
|
src/security/ |
DuckIdentity, DuckCrypto, OpenDmsConfig, MeshGroupConfig, SecurityEventCounters
|
src/payloads/ |
duck_payloads.proto + generated nanopb code + DuckPayloads encode/decode helpers |
src/wifi/ |
DuckWifi, DuckWifiNone
|
src/utils/ |
Logging, error codes, misc helpers |
src/include/ |
cdpcfg.h (build-time configuration) and per-board headers |