aranet-service 0.2.0

Background collector and HTTP REST API for Aranet sensors
Documentation

aranet-service

crates.io docs.rs

Background collector and HTTP REST API for Aranet sensors.

Full Documentation

A service daemon that continuously monitors Aranet devices and exposes sensor data via a REST API. Built with Axum for high-performance async HTTP handling. The embedded dashboard is served at / and /dashboard.

Features

  • Background collection - Automatically poll configured devices at regular intervals
  • REST API - Query current readings, history, and device information via HTTP
  • WebSocket support - Real-time streaming of sensor updates
  • Prometheus metrics - /metrics endpoint for Grafana dashboards and alerting
  • MQTT publisher - Broadcast readings to MQTT brokers for IoT integration and Home Assistant auto-discovery
  • Webhook notifications - Send HTTP alerts for CO2, radon, and battery thresholds
  • InfluxDB export - Stream readings to InfluxDB v2 using line protocol
  • mDNS discovery - Advertise _aranet._tcp.local. and _http._tcp.local. on the LAN
  • Embedded dashboard - Serve a built-in monitoring UI at / and /dashboard
  • Local persistence - Store readings in SQLite via aranet-store
  • Configurable - TOML-based configuration for devices, intervals, and server settings
  • Health endpoint - Monitor service status for integration with monitoring systems
  • Service management - Install as system service (launchd/systemd/Windows Service)

Installation

cargo install aranet-service --features full

Or build from source:

cargo build --release -p aranet-service

Usage

# Start the service with default configuration
aranet-service

# Specify a custom config file
aranet-service --config /path/to/config.toml

# Specify bind address and port
aranet-service --bind 0.0.0.0:8080

Configuration

Create a configuration file at ~/.config/aranet/server.toml:

[server]
bind = "127.0.0.1:8080"

[storage]
path = "~/.local/share/aranet/data.db"

[[devices]]
address = "AA:BB:CC:DD:EE:FF"
alias = "Living Room"
poll_interval = 60  # seconds

# Prometheus metrics (optional)
[prometheus]
enabled = true
# push_gateway = "http://localhost:9091"  # Optional push gateway
# push_interval = 60  # Push interval in seconds

# MQTT publishing (optional)
[mqtt]
enabled = true
broker = "mqtt://localhost:1883"  # or mqtts:// for TLS
topic_prefix = "aranet"
client_id = "aranet-service"
qos = 1  # 0=AtMostOnce, 1=AtLeastOnce, 2=ExactlyOnce
retain = true
homeassistant = true
ha_discovery_prefix = "homeassistant"
# username = "user"  # Optional authentication
# password = "secret"

[webhooks]
enabled = true
co2_threshold = 1000
radon_threshold = 300
battery_threshold = 10
cooldown_secs = 300

[[webhooks.endpoints]]
url = "https://hooks.slack.com/services/T00/B00/xxx"
events = ["co2_high", "radon_high", "battery_low"]

[influxdb]
enabled = true
url = "http://localhost:8086"
token = "your-influxdb-token"
org = "my-org"
bucket = "aranet"
measurement = "aranet"
precision = "s"

API Endpoints

Method Endpoint Description
GET /api/health Service health check
GET /api/health/detailed Detailed health with database, collector, and platform diagnostics
GET /api/status Full service status with collector state
GET /api/devices List devices known to the database
GET /api/devices/current List latest readings for all devices
GET /api/devices/:id Get device details
GET /api/devices/:id/current Get current reading (includes age_seconds, stale)
GET /api/devices/:id/readings Query stored readings
GET /api/devices/:id/history Query device history
GET /api/readings Query all readings across devices
POST /api/collector/start Start background collector
POST /api/collector/stop Stop background collector
GET /api/config Get current configuration
PUT /api/config Update configuration
POST /api/config/devices Add device to monitoring
PUT /api/config/devices/:id Update device config
DELETE /api/config/devices/:id Remove device
GET /metrics Prometheus metrics endpoint
WS /api/ws WebSocket for real-time updates

The dashboard shell routes / and /dashboard are public so browsers can load the UI. API, WebSocket, and metrics requests still honor the configured security settings.

If API key authentication is enabled, WebSocket clients can use X-API-Key or the token query parameter for /api/ws.

Query Parameters

For /readings and /history endpoints:

Parameter Type Description
since Unix timestamp Filter records after this time
until Unix timestamp Filter records before this time
limit Integer Maximum number of records
offset Integer Skip this many records (pagination)

Example Requests

# Check service health
curl http://localhost:8080/api/health

# List devices
curl http://localhost:8080/api/devices

# Latest readings for all devices
curl http://localhost:8080/api/devices/current

# Get current reading
curl http://localhost:8080/api/devices/Aranet4%2017C3C/current

# Query history with time range
curl "http://localhost:8080/api/devices/Aranet4%2017C3C/history?since=1705320000&limit=100"

# Get Prometheus metrics
curl http://localhost:8080/metrics

Prometheus Metrics

When enabled, the /metrics endpoint exports sensor data in Prometheus format:

Sensor readings (per device):

  • aranet_co2_ppm - CO2 concentration
  • aranet_temperature_celsius - Temperature
  • aranet_humidity_percent - Humidity
  • aranet_pressure_hpa - Pressure
  • aranet_battery_percent - Battery level
  • aranet_reading_age_seconds - Age of reading

Radon/radiation (if available):

  • aranet_radon_bqm3 - Radon concentration
  • aranet_radiation_rate_usvh - Radiation dose rate
  • aranet_radiation_total_msv - Total radiation dose

Collector statistics:

  • aranet_collector_running - Collector status (1=running, 0=stopped)
  • aranet_collector_uptime_seconds - Collector uptime
  • aranet_device_poll_success_total - Successful polls per device
  • aranet_device_poll_failure_total - Failed polls per device
  • aranet_device_poll_duration_ms - Duration of the last poll in milliseconds

Note: Sensor metrics are only emitted for capabilities a device actually has. For example, an Aranet2 (temperature/humidity only) will not emit aranet_co2_ppm or aranet_pressure_hpa.

MQTT Topics

When MQTT is enabled, readings are published to the following topics:

{prefix}/{device}/json           - Full reading as JSON
{prefix}/{device}/co2            - CO2 (ppm)
{prefix}/{device}/temperature    - Temperature (°C)
{prefix}/{device}/humidity       - Humidity (%)
{prefix}/{device}/pressure       - Pressure (hPa)
{prefix}/{device}/battery        - Battery level (%)
{prefix}/{device}/status         - Status (green/yellow/red/error)
{prefix}/{device}/radon          - Radon (Bq/m³, if available)
{prefix}/{device}/radon_avg_24h  - 24-hour radon average (if available)
{prefix}/{device}/radon_avg_7d   - 7-day radon average (if available)
{prefix}/{device}/radon_avg_30d  - 30-day radon average (if available)
{prefix}/{device}/radiation_rate - Radiation rate (µSv/h, if available)
{prefix}/{device}/radiation_total - Total radiation (mSv, if available)

Where {prefix} is the configured topic prefix (default: "aranet") and {device} is the device alias or address.

Service Management

Install and manage aranet-service as a system service:

# Install as user service
aranet-service service install --user

# Start/stop/status
aranet-service service start --user
aranet-service service stop --user
aranet-service service status --user

# Install as system service (requires root/admin)
sudo aranet-service service install

Related Crates

This crate is part of the aranet workspace:

Crate crates.io Description
aranet-core crates.io Core BLE library for device communication
aranet-types crates.io Shared types for sensor data
aranet-store crates.io Local data persistence
aranet-cli crates.io Command-line interface
aranet-tui crates.io Terminal UI dashboard
aranet-gui crates.io Desktop GUI application

License

MIT


Made with ❤️ by Cameron Rye