Skip to content

ogmueller/phritzbox

Repository files navigation

Phritzbox

CI Docker Security codecov ghcr.io License

A self-hosted smart home dashboard for smart devices connected to AVM Fritz!Box. Monitor temperatures, power consumption, and energy usage with interactive charts. Control smart outlets and radiator thermostats from your browser or the command line.

Built with Symfony 8, React 19, and FrankenPHP. Ships as a single Docker image.

Screenshots

Dashboard — live overview of all devices with status, temperature, power consumption, and toggle switches:

Dashboard

Device detail — product image, firmware info, and feature cards for switch state, power meter, and temperature sensor, followed by interactive 7-day charts (temperature, power, energy in kWh, and voltage) with rolling averages and a raw-XML view for diagnostics:

Device detail

Reports — query historical data for any device and date range, with selectable metric, configurable rolling averages, an optional second device overlaid for comparison, and markers where alert rules fired (hover a marker to see the rule and reading):

Reports — 30-day comparison Reports — alert event markers

Alerts (admin) — threshold, sustained, and device-to-device comparison rules with per-channel delivery, a manual re-arm, and an activity log of every firing and resolution:

Alerts

Channels (admin) — reusable notification destinations (e-mail, webhook, Pushover, Telegram, ntfy, Discord, Gotify, Slack/Mattermost) shared across alert rules:

Channels

Users (admin) — user management with role-based access: administrators configure everything, while regular users monitor and control devices and view reports:

Users

Features

  • Live device status with 30-second auto-refresh (and a fresh pull on every visit)
  • Interactive charts for temperature, power, energy, and voltage
  • Date-range reports with quick presets (today, last 7/30 days), rolling averages, a second device overlaid on the same chart for comparison, and alert events marked where rules fired — plus on-demand data refresh; your last selection is remembered and re-run when you come back
  • Rule-based alerting (threshold, sustained, or device-to-device comparison) via e-mail, webhook, Pushover, Telegram, ntfy, Discord, Gotify, or Slack/Mattermost — with an activity log that shows per-channel delivery status, current-rule state, and a manual re-arm
  • Sortable tables and global error notifications throughout the UI
  • 18 CLI commands for device control and monitoring
  • User management with role-based access (admin only)
  • German and English interface
  • Automated data collection every 30 minutes (via cronado)
  • Single Docker image — no PHP, Node.js, or Composer required

Quick Start

Requires Docker with Compose.

Option A — Download the release zip (recommended):

Download the latest phritzbox-*.zip from Releases, extract it, and copy .env.dist to .env:

unzip phritzbox-*.zip && cd phritzbox
cp .env.dist .env

Option B — Fetch files manually:

mkdir phritzbox && cd phritzbox
curl -L https://raw.githubusercontent.com/ogmueller/phritzbox/main/docker/compose.prod.yaml -o compose.yaml
curl -L https://raw.githubusercontent.com/ogmueller/phritzbox/main/docker/.env.dist -o .env

Edit .env with your Fritz!Box credentials, then start the application:

docker compose up -d

Visit http://localhost and log in with admin / admin.

Important: Change the default password immediately after your first login.

To use a specific version instead of latest, edit the image tag in compose.yaml:

image: ghcr.io/ogmueller/phritzbox:1.1.0   # tagged release
image: ghcr.io/ogmueller/phritzbox:nightly  # latest from main branch

Configuration

All settings are configured via environment variables in .env:

Variable Required Default Description
APP_API_USERNAME Yes Fritz!Box login username
APP_API_PASSWORD Yes Fritz!Box login password
APP_API_DOMAIN No http://fritz.box Fritz!Box address (or MyFRITZ! URL)
APP_SECRET No change-me... Symfony application secret
JWT_PASSPHRASE No change-me Passphrase for JWT key encryption
SERVER_NAME No localhost Server hostname for Caddy
PHRITZBOX_PORT No 80 Port to expose the web UI
MAILER_DSN No null://null Mail transport for e-mail alerts (e.g. smtp://user:pass@host:587); default discards mail
APP_ALERT_FROM No alerts@phritzbox.local Sender address for alert e-mails

CLI Commands

Using the release zip, run commands with the included console script:

./console COMMAND

Or via docker compose exec directly:

docker compose exec app php /application/app/bin/console COMMAND

Without Docker:

php app/bin/console COMMAND
Command Description
smart:device:list List all available SmartHome devices
smart:device:stats Show statistics of a SmartHome device
smart:switch:list List all known SmartHome outlets
smart:switch:on <ain> Turn on a SmartHome outlet
smart:switch:off <ain> Turn off a SmartHome outlet
smart:switch:toggle <ain> Toggle power state of a SmartHome outlet
smart:switch:power <ain> Read current power consumption [mW]
smart:switch:energy <ain> Read energy delivered over outlet [Wh]
smart:switch:present <ain> Check availability of a SmartHome outlet
smart:switch:name <ain> Get name of a SmartHome outlet
smart:temperature <ain> Read temperature of a SmartHome device [°C]
smart:src:on <ain> Turn on a smart radiator control
smart:src:off <ain> Turn off a smart radiator control
smart:src:setpoint <ain> Read or set target temperature [°C]
smart:src:comfort <ain> Read comfort temperature setpoint [°C]
smart:src:saving <ain> Read saving temperature setpoint [°C]
smart:template:list List all available SmartHome templates
cron:smart:savestats Collect and persist all device data
cron:smart:alerts Evaluate alert rules and send notifications

Data Collection

In the Docker setup, data collection runs automatically every 30 minutes via cronado.

For a bare-metal installation, set up a cron job:

*/30 * * * *   /path-to-phritzbox/app/bin/console cron:smart:savestats

The Fritz!Box caches device data. Temperature readings are available for up to 24 hours — if not fetched in time they are lost. Running every 30 minutes is recommended.

Keep the host awake. The scheduler (cronado) does not catch up missed runs, so if the machine sleeps (e.g. a laptop closing its lid), collection and alert evaluation simply pause until it wakes. Run Phritzbox on always-on hardware, or disable system sleep on the host. If data does go stale, the web UI shows a "live data may be stale" banner with how long ago the last collection succeeded.

Alerts

Define rules that notify you when something noteworthy happens — turning Phritzbox into a simple smart-temperature manager for your home.

Example — when to open or close the windows in summer: put one temperature sensor outdoors and one indoors, then create a comparison rule like “outdoor < indoor − 2 °C”. When the outside air drops below your indoor temperature you get a notification telling you it's time to open up and let the cool air in; the inverse rule (“outdoor > indoor”) tells you when to close the windows and keep the heat out.

Rule types:

  • Threshold — a metric crosses a value, e.g. temperature above 25 °C or power below 5 W (an appliance finished).
  • Sustained — a threshold holds for the last N minutes, e.g. power above 2000 W for 5 minutes.
  • Comparison — one device's metric relative to another's, ± an offset, e.g. outdoor temperature < indoor temperature − 2 °C.

Rules are edge-triggered: you're alerted once when the condition becomes true, and again only after it clears and re-occurs. Set an optional reminder interval if you'd rather be re-notified while it stays true. A message is sent only on the triggering edge — when the condition clears again the resolution is logged but not notified.

Each rule shows its current state (OK / Triggered) on the Alerts page. A rule with "alert once" stays triggered until the condition clears; if you want it to fire again sooner, use the Re-arm action to reset it to OK. The Recent activity log below the rules records every firing, resolution, and re-arm together with the readings and the per-channel delivery result (sent ✓ / failed ✗ with the error), so a misconfigured channel is easy to spot.

Channels are the delivery destinations, managed separately and reusable across rules. A rule can notify one or more channels. Supported types:

Channel You provide
E-mail recipient address (set MAILER_DSN to send)
Webhook a URL (receives a JSON payload)
Pushover user/group key + application token
Telegram chat ID + bot token
ntfy topic URL (+ optional auth token)
Discord channel webhook URL
Gotify server URL + app token
Slack / Mattermost / Rocket.Chat incoming-webhook URL

Set up channels under Channels, then reference them from Alerts (both are admin-only). Use a channel's Test button to verify delivery.

Alert rules are evaluated shortly after each data collection (the cron:smart:alerts command, scheduled automatically in the Docker setup). Because evaluation runs on collected data, alerts can lag real-time by up to the collection interval (~30 minutes). To check immediately, the Reports "Pull latest data" button collects fresh readings and evaluates the rules right away.

Development

Requirements

  • PHP 8.5+ with pdo_sqlite and simplexml
  • Node.js 22+ and npm
  • Composer 2
  • A Fritz!Box with smart home devices

Manual Installation

git clone https://github.com/ogmueller/phritzbox.git
cd phritzbox/app && composer install && cd ..
cp app/.env app/.env.local

Edit app/.env.local and set your Fritz!Box credentials:

APP_API_USERNAME=your-username
APP_API_PASSWORD=your-password
APP_API_DOMAIN=http://fritz.box
DATABASE_URL="sqlite:///%kernel.project_dir%/../data/database.sqlite"

Run the initial database migration:

php app/bin/console doctrine:migrations:migrate

Docker (Development)

cd docker && docker compose up

The container mounts app/, data/, and var/ as volumes for live code editing.

Note: The Docker dev setup only runs the PHP backend. To work on the frontend, you need to start the Vite dev server separately (see below) or uncomment the vite service in docker/compose.yaml.

Frontend

cd app/frontend && npm install
npm run dev     # dev server on :5173 (proxies /api to :80)
npm run build   # production build → app/public/frontend/

Tests

php app/vendor/bin/phpunit --configuration app/phpunit.xml.dist   # backend (PHPUnit)
cd app/frontend && npm test                                       # frontend (Vitest)

Code Style

./app/vendor/bin/php-cs-fixer fix --diff --dry-run -v --config app/.php-cs-fixer.dist.php   # check
./app/vendor/bin/php-cs-fixer fix --config app/.php-cs-fixer.dist.php                       # fix

Lint & Validate

cd app && composer phpstan                          # static analysis (PHPStan, level 6)
php app/bin/console lint:yaml app/config --parse-tags
php app/bin/console doctrine:schema:validate --skip-sync
cd app && composer audit                            # backend dependency audit
cd app/frontend && npm run lint                     # ESLint
cd app/frontend && npm run i18n:check               # en/de translation parity

These same checks run in CI on every push and pull request (PHPUnit + coverage, php-cs-fixer, PHPStan, PHPMD, YAML/Doctrine validation, and a frontend job: ESLint, Vitest, build, npm audit). Dependency updates are proposed automatically by Dependabot.

Building Docker Images Locally

docker build -f docker/Dockerfile.prod -t phritzbox .
CLI Screenshots

Device listing (smart:device:list):

Device listing

Statistics (smart:device:stats):

Temperature graph Voltage graph Power graph Energy per month over 1 year Energy per day over 1 month

About

A companion for AVM Fritz!Box smart home devices. Collects, stores and monitors data from smart outlets, thermostats and temperature sensors via the AHA HTTP API.

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors