bbm 0.1.0

Async Rust client library for the German Breitbandmessung (broadband measurement) API
Documentation

bbmctl

Async Rust client library and CLI for the German Breitbandmessung broadband measurement API.

Test Crates.io License: MIT

Background

This project started during a road trip through Norway and Sweden in 2023. Even at the North Cape, I had better mobile internet than in my hometown in Germany. That frustration led me to build a tool for measuring and tracking broadband speeds against what ISPs actually promise in their contracts.

The original version was written in Go. I shelved it between 2024 and 2025, then rewrote the entire project in Rust with a focus on performance and clean architecture -- async everywhere, concurrent speed measurements, and a proper library/CLI split.

This project is not affiliated with the German government or the Bundesnetzagentur. For more information about the official Breitbandmessung project, visit breitbandmessung.de.

Features

Library (bbm crate):

  • Async HTTP client for the Breitbandmessung API
  • Tower retry middleware with exponential backoff (configurable)
  • Concurrent speed test runner using FuturesUnordered (configurable streams, default 8)
  • TCP latency measurement with jitter calculation
  • Plan comparison against contractual speed thresholds

CLI (bbmctl):

  • Query providers, plans, and speeds from the API
  • Run broadband speed tests with concurrent streams
  • Compare measured speeds against your ISP contract
  • Record measurements to a local SQLite database (SeaORM)
  • Manage BNetzA measurement campaigns (Nachweisverfahren)
  • Scheduled recurring tests (test --every 30m)
  • Speed trend sparkline charts (history trend)
  • Import/export measurement history as CSV
  • Multiple output formats: table, JSON, YAML, CSV
  • Config file with named profiles
  • Shell completions for bash, zsh, fish, powershell, elvish
  • Prometheus metrics exporter
  • Human-readable speed display with auto unit detection

Library usage

Add to your Cargo.toml:

[dependencies]
bbm = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
use bbm::BbmClient;

#[tokio::main]
async fn main() -> Result<(), bbm::BbmError> {
    let client = BbmClient::new();

    // List all providers
    let providers = client.get_providers().await?;
    for provider in &providers {
        println!("{}: {}", provider.key, provider.value);
    }

    // Fetch plans for a specific provider
    let plans = client.get_plans_by_provider_id(437).await?;
    for plan in &plans {
        println!("Plan {}: max {}kbit/s down", plan.plan_id, plan.maxdownload);
    }

    Ok(())
}

CLI installation

From GitHub releases

Download the latest binary from Releases.

Homebrew (macOS)

brew install timrabl/tap/bbmctl

From source

cargo install --git https://github.com/timrabl/bbmctl bbmctl

CLI usage

# List providers
bbmctl list providers --search telekom

# Run a speed test
bbmctl test --duration 10 --streams 8

# Compare against your contract
bbmctl compare --provider 437 --plan 8515 --test

# Record measurements over time
bbmctl test --every 30m --provider 437

# View speed trends
bbmctl history trend --last 7d

# Start a BNetzA measurement campaign
bbmctl campaign start --provider 437 --plan 8515
bbmctl campaign test
bbmctl campaign report

# Export/import data
bbmctl history export -o backup.csv
bbmctl history import backup.csv

# Generate shell completions
bbmctl completions zsh > ~/.zfunc/_bbmctl

Configuration

bbmctl looks for a config file at ~/.config/bbmctl/config.yaml or ~/.bbmctl/config.yaml:

database: "~/.bbmctl/measurements.db"

default:
  provider: 437
  plan: "8515"
  format: table
  streams: 8
  duration: 10
  speed_unit: auto

profiles:
  office:
    provider: 251
    plan: "9001"

Use profiles with --profile office.

Exit codes

Code Meaning
0 Success
1 Error
2 Threshold failure (compare/campaign test)

License

This project is licensed under the MIT License.

Links