Skip to main content

Prometheus exporters for IoT and smart-home devices, including TP-Link Tapo plugs.

Project description

Python Prometheus Exporters for IoT Devices

Python Prometheus Exporters (pyprom-exporters) is a small Python package that exposes Prometheus metrics for IoT / smart-home devices.

The current concrete exporter targets TP-Link Tapo smart plugs via python-kasa.

What It Does

  • Discovers Tapo devices on your LAN (UDP broadcast) and/or monitors an explicit list of device IPs.
  • Updates device state on a background asyncio loop (or on scrape), with retries and backoff.
  • Exposes metrics via a Prometheus HTTP endpoint.

How It Works

  • prom-exporter starts an asyncio event loop on a background thread.
  • The Tapo exporter runs discovery, then chooses update mode from exporters.tapo.prometheus_options.refresh_interval:
    • Integer value: performs an initial update pass and periodic background updates, and scrapes read cached metrics.
    • null: disables background updates and refreshes metrics when Prometheus calls collect().

To reduce device/network traffic, set refresh_interval to match your Prometheus scrape interval (or higher). Set it to null when you want scrape-time freshness.

Project Layout

  • src/pyprom_exporters/prom_exporter.py: CLI entry point and runtime wiring.
  • src/pyprom_exporters/config.py: OmegaConf-compatible dataclass configuration models.
  • src/pyprom_exporters/exporters/tapo.py: Tapo smart plug exporter implementation.
  • src/pyprom_exporters/task_collector/async_task_collector.py: async retry runner used for device updates.
  • tests/: unit tests for config/exporter behavior.

Requirements

  • Python 3.11+ (uses asyncio.TaskGroup).
  • Network reachability from the exporter host to the devices.
  • Tapo credentials (provided via env vars or CLI; never written to config.yaml).

Installation

This repo is set up to use uv and a checked-in uv.lock.

# Development (includes the dev dependency group by default)
uv sync --frozen

# Minimal runtime environment
uv sync --frozen --no-dev

Running

  1. Provide credentials (default env keys):
export TP_LINK_USERNAME="you@example.com"
export TP_LINK_PASSWORD="your-password"
  1. Run the exporter:
uv run prom-exporter \
  --prometheus-port 8090 \
  --tapo-plug-devices 10.10.2.100,10.10.2.101

You can also reduce log verbosity:

uv run prom-exporter --log-level WARNING
  1. Scrape metrics:
  • http://localhost:8090/metrics

Environment Variable Overrides

The runtime supports a few convenience overrides:

  • Precedence: CLI flags override env vars; env vars override config.yaml.
  • PYPROM_EXPORTERS_LOG_LEVEL (or LOG_LEVEL): overrides log_level.
  • PROMETHEUS_PORT: overrides prometheus_port.
  • TAPO_PLUG_DEVICES: overrides exporters.tapo.devices (space or comma-separated).
  • TAPO_USERNAME / TAPO_PASSWORD: overrides credentials directly.

Configuration (config.yaml)

prom-exporter reads config.yaml from the working directory.

  • If config.yaml does not exist, it writes one with defaults.
  • If config.yaml exists, it writes back the merged configuration on startup so defaults are explicit.
  • Credentials are always scrubbed from the written YAML; provide them via env vars or CLI.
  • write_non_default_config: true writes only values that differ from defaults.

Important fields:

  • log_level: root logging level for the process.
  • prometheus_port: exporter listen port.
  • exporters.tapo.devices: list of device IPs to monitor (used in addition to discovery).
  • exporters.tapo.prometheus_options.refresh_interval: background update interval (seconds) and per-device minimum update interval. Set to null to disable background updates and refresh on scrape.
  • exporters.tapo.discovery_options.*: discovery parameters passed to python-kasa.
  • exporters.tapo.discovery_options.tapo_username_env_key / tapo_password_env_key: env var names used to populate python-kasa Credentials by default.
  • exporters.tapo.supported_device_families: currently only PLUG.
  • exporters.tapo.per_device_family_metrics.plug: plug metrics to export.

Polling Behavior Examples

Set the option internally (Python dataclass value):

# Background polling every 15 seconds.
app_config.exporters.tapo.prometheus_options.refresh_interval = 15

# Disable background polling; refresh on every Prometheus scrape.
app_config.exporters.tapo.prometheus_options.refresh_interval = None

When config.yaml is written back, those values appear as:

exporters:
  tapo:
    prometheus_options:
      refresh_interval: 15
exporters:
  tapo:
    prometheus_options:
      refresh_interval: null

Discovery note: broadcast discovery generally does not work across VLAN boundaries. If your devices are on a separate IoT VLAN, set exporters.tapo.devices (or use --tapo-plug-devices) to the device IPs.

Metrics

The Tapo plug exporter currently emits:

  • tapo_discovered_devices: number of discovered devices (gauge).
  • current_consumption{host,alias}: watts (gauge).
  • current_voltage{host,alias}: volts (gauge).
  • current_current{host,alias}: amps (gauge).
  • current_consumption_today{host,alias}: watt-hours (gauge).
  • current_month_consumption{host,alias}: watt-hours (gauge).
  • current_rssi{host,alias}: RSSI value reported by the device (gauge).

Only devices that report the current_consumption feature are exported.

Prometheus Scrape Config

Example prometheus.yml:

scrape_configs:
  - job_name: pyprom-exporters
    static_configs:
      - targets: ["<exporter-host>:8090"]

Docker

Build:

docker build -t pyprom-exporters:latest .

Run:

docker run --rm \
  -e TP_LINK_USERNAME="you@example.com" \
  -e TP_LINK_PASSWORD="your-password" \
  -e PROMETHEUS_PORT=8090 \
  -e TAPO_PLUG_DEVICES="10.10.2.100,10.10.2.101" \
  -p 8090:8090 \
  pyprom-exporters:latest

The container entrypoint runs uv run prom-exporter and forwards PROMETHEUS_PORT and TAPO_PLUG_DEVICES into CLI flags.

Troubleshooting

  • No devices discovered:
    • Set exporters.tapo.devices (or use --tapo-plug-devices) instead of relying on broadcast discovery.
    • Check firewall rules and IoT VLAN routing.
  • Metrics are missing for a device:
    • The exporter skips devices that do not report a current_consumption feature.
  • Authentication failures:
    • Ensure TP_LINK_USERNAME / TP_LINK_PASSWORD (or TAPO_USERNAME / TAPO_PASSWORD) are set.

Development

# pytest - for tests
uv run pytest
# ruff - for linting and formatting
uv run ruff check .
# format with ruff (or your editor integration)
uv run ruff format .
# pre-commit - for running all configured pre-commit hooks (ruff, isort, etc.)
uv run pre-commit run --all-files

Documentation

Documentation is generated with Sphinx using Markdown (MyST) sources in docs/.

# Build HTML docs locally with uv
uv run docs

# Build HTML docs locally with make
make docs

License

Apache-2.0 (see LICENSE).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyprom_exporters-0.1.0.tar.gz (123.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyprom_exporters-0.1.0-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file pyprom_exporters-0.1.0.tar.gz.

File metadata

  • Download URL: pyprom_exporters-0.1.0.tar.gz
  • Upload date:
  • Size: 123.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyprom_exporters-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8eb084c2a69a8355380419dbb3988251e266d17682f210c35d7a16dd31692cbe
MD5 db42e5420572c4daf457b95d41fd8dde
BLAKE2b-256 7e1f118e89b9168660a31fc2a1be6a56186e6738bf8fbb9b0566643dcee37ee9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyprom_exporters-0.1.0.tar.gz:

Publisher: release.yml on andylamp/pyprom-exporters

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyprom_exporters-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyprom_exporters-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6bb39e5cf690e9bccbe5612713732d6655f636037a8ef770999ce1986f6a966
MD5 a296c35b067b63e9c735945734fd3493
BLAKE2b-256 3017c0b1cd92a10d8670e8f571c7d175eafb575d01b5b4b3d2689d5a22f31c87

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyprom_exporters-0.1.0-py3-none-any.whl:

Publisher: release.yml on andylamp/pyprom-exporters

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page