Skip to content

Repository files navigation

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

About

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

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages