RIVR is een minimalistische stream-verwerkingstaal en -runtime voor ingebedde LoRa-meshnodes. Schrijf declaratieve pijplijnen in een opgemaakte DSL; de compiler zet ze om naar een toestandsloze DAG die zonder heap-allocatie draait op microcontrollers.
| Praktisch probleem | RIVR-oplossing |
|---|---|
| LoRa verplicht ≤ 1% duty-cycle | budget.toa_us en budget.airtime operatoren op elke pijplijn |
| Embedded MCU heeft geen heap | Anonieme pijplijnen worden statisch opgeslagen in BSS (ENGINE_SLOT) |
| Geen RTOS-threads beschikbaar | Ééntraps poll-lus: rivr_engine_run() elke 10 ms |
| Binair LoRa-frameformaat | filter.pkt_type(N) inspecteert headeroffset 3 van ruwe bytes |
| Lamport-klok voor logisch tijdstip | Tweedeklokinject via clock_id = 1 (@lmp-bronnen) |
Rivr/
├── rivr_core/ # Rust — parser + compiler + runtime + FFI
│ └── src/
│ ├── lib.rs # feature-gates & herexports
│ ├── ast.rs # AST-typen (PipeOp enum, enz.)
│ ├── parser.rs # handgeschreven recursive-descent parser
│ ├── compiler.rs # AST → opcode-bytes
│ └── runtime/
│ ├── engine.rs # Engine struct, injection, run
│ ├── node.rs # uitvoering per operator/node
│ └── value.rs # Value enum (Int, Bool, Str, Bytes, Window, …)
├── rivr_host/ # Rust (std) — desktop-demo's, Replay 2.0, rivrc CLI
│ └── src/
│ ├── main.rs # 8 demo's: window, budget, debounce, pkt_type, …
│ ├── replay.rs # Replay 2.0 — record / replay / assert (JSONL)
│ └── bin/
│ └── rivrc.rs # CLI: parseer + compileer .rivr-bestanden
├── firmware_core/ # C — ESP32 stuurprogramma's + protocol + routing
│ ├── main.c # app_main, main-lus, SIM-frame-injectie
│ ├── platform_esp32.c/h # klokken, SPI, GPIO-pinnen
│ ├── radio_sx1262.c/h # SX1262 LoRa driver, TX-wachtrij, ring-buffer
│ ├── display/display.c/h # OLED-weergavetaak
│ ├── protocol.c/h # binaire frame-encode/decode met CRC-16
│ ├── routing.c/h # dedupe-cache, TTL, jitter, doorstuurbudget, lusbewaker
│ ├── route_cache.c/h # unicast reverse-path-cache; route_cache_best_hop() drietraps
│ ├── neighbor_table.c/h # 16-slot EWMA koppelkwaliteitstabel; neighbor_update/best/expire
│ ├── pending_queue.c/h # 16-slot wachtrij voor ACK-afwachtende unicastframes
│ ├── rivr_policy.c/h # @PARAMS beleid, rolhandhaving, oorsprongspoort, HMAC-handtekening
│ ├── rivr_ota.c/h # ondertekende PKT_PROG_PUSH-poort (Ed25519 + anti-replay)
│ └── crypto/ # zelfstandige SHA-256 + HMAC-SHA-256 (geen heap)
├── rivr_layer/ # C — lijmlaag RIVR↔firmware
│ ├── rivr_embed.c/h # engine_init, tick, NVS opslaan/laden, hot-reload
│ ├── rivr_sources.c/h # bronregistratie (rf, usb, timer…); stap-5d service-dispatch
│ ├── rivr_sinks.c/h # sink-callbacks (rf_tx, usb_print, beacon)
│ ├── rivr_svc.c/h # applicatieservice-handlers (CHAT, TELEMETRY, MAILBOX, ALERT)
│ ├── rivr_cli.c/h # seriële CLI-chatinterface (alleen cliënt-builds)
│ └── default_program.h # selecteerbare RIVR-programma's via #define
└── tools/
└── vscode-rivr/ # VS Code-extensie (syntaxis + snippets)
Elk event draagt een (clock_id, timestamp) stempel:
(0, 1 234 567) → clock 0 (mono), 1 234,567 seconden na opstart
(1, 9) → clock 1 (lmp), Lamport-tik 9
Pijplijnen verwerken getypte waarden:
| Type | Gebruik |
|---|---|
Str |
UTF-8 chatberichten |
Bytes |
Ruwe LoRa-frames (binair protocol) |
Int |
Tellers, TTL-waarden |
Bool |
Filtervlaggen |
Window |
Gebufferde verzameling events (na window.*) |
Unit |
Leeg signaal |
let chat = rf_rx
|> filter.pkt_type(1)
|> budget.toa_us(360000, 0.10, 360000)
|> throttle.ticks(1);
Elke |>-operatie wordt één knoop in de DAG.
Geen threads, geen kanalen — elke rivr_inject_event() doorloopt de keten synchroon.
emit {
rf_tx(chat);
usb_print(chat);
}
emit-clausules verbinden pijplijnen met C-sink-callbacks.
| Onderdeel | Taal | Rol |
|---|---|---|
rivr_core |
Rust (no_std+alloc) |
Parser, compiler, runtime, FFI-exports |
rivr_host |
Rust (std) | Desktop-demo's, Replay 2.0, rivrc CLI |
firmware_core |
C | ESP32 drivers, protocol, routing, OLED-display |
rivr_layer |
C | Lijmlaag: bronnen, sinks, embedAPI, NVS |
rivr_svc |
C | Applicatiediensten — CHAT, TELEMETRY, MAILBOX, ALERT handlers |
tools/vscode-rivr |
JSON/TS | VS Code syntaxisaccentuering + snippets |
cargo run -p rivr_host# Druk knoop-grafiek af
cargo run -p rivr_host --bin rivrc -- mijn_programma.rivr
# CI-modus
cargo run -p rivr_host --bin rivrc -- --check mijn_programma.rivr# Stap 1: bouw de Rust-bibliotheek
cd e:\Projects\Rivr\rivr_core
cargo build --features ffi
# Stap 2: bouw en flash via PlatformIO
cd ..
pio run -e esp32_sim -t upload
pio device monitor --baud 115200Zie bouwhandleiding.md voor een volledige installatie op hardware.