No description
  • TypeScript 77.6%
  • CSS 17%
  • Dockerfile 3.2%
  • JavaScript 1.8%
  • HTML 0.4%
Find a file
Freydis Mende 24dbe92497
All checks were successful
CI / Frontend – typecheck, lint & build (push) Successful in 42s
CI / Backend – typecheck, lint & build (push) Successful in 44s
CI / Docker – build image (push) Successful in 2s
CI / deploy (push) Successful in 0s
Connect pv-monitor to external redis-shared network
Enables the Redis-backed cache (added in 4f40afa) to reach a Redis instance running on a shared external Docker network.
2026-08-15 17:56:00 +02:00
.forgejo/workflows Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
.github Split into independent frontend/backend projects, add /api/health + /api/version, harmonize CI 2026-08-14 10:23:21 +02:00
.husky Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
backend Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
frontend Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
.dockerignore Split into independent frontend/backend projects, add /api/health + /api/version, harmonize CI 2026-08-14 10:23:21 +02:00
.env.example Add optional Redis-backed cache for dashboard/chart data 2026-08-15 11:17:37 +02:00
.gitignore Split into independent frontend/backend projects, add /api/health + /api/version, harmonize CI 2026-08-14 10:23:21 +02:00
.prettierignore rewrite 2026-06-05 17:30:12 +02:00
.prettierrc rewrite 2026-06-05 17:30:12 +02:00
docker-compose.yml Connect pv-monitor to external redis-shared network 2026-08-15 17:56:00 +02:00
Dockerfile Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
lint-staged.config.mjs Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
package.json Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
pnpm-lock.yaml Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
pnpm-workspace.yaml Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00
README.md Migrate to pnpm workspace, add husky pre-commit hook 2026-08-15 17:41:59 +02:00

PV Monitor

A self-hosted photovoltaic (solar) monitoring dashboard that reads live and historical data from Home Assistant and displays it in a React web UI.

Features

  • Live power chart PV generation, grid import/export, and battery charge/discharge over the last 24 hours
  • Yield cards today, this month, this year, and all-time totals
  • Daily & monthly bar charts production history with optional autarky overlay
  • Battery status state of charge, current power, and charge/discharge totals for today
  • EV card state of charge, charging power, odometer, energy charged, and solar share percentage
  • Earnings estimated revenue from feed-in and savings from self-consumption
  • Auto-refresh every 30 seconds with a manual refresh button

All sections are optional — if the corresponding environment variables are not set, that section is silently disabled.

Architecture

Browser  ←→  React + Vite SPA (port 3000 in prod)
                 ↕
          Express API server  ←→  Home Assistant REST / WebSocket API

The Express server proxies requests to Home Assistant so that the HA token is never exposed to the browser. In development, Vite's dev server proxies /api/* to the Express server.

Quick Start (Docker)

  1. Copy .env.example to .env and fill in your values (see Configuration below).
  2. Run:
    docker compose up -d
    
  3. Open http://localhost:3000.

Development

This is a pnpm workspace containing the backend and frontend packages, with a single lockfile at the repo root.

pnpm install

# terminal 1 - backend (API on :3000)
pnpm --filter backend dev

# terminal 2 - frontend (dev server on :5173, proxies /api to :3000)
pnpm --filter frontend dev

The Vite dev server runs on http://localhost:5173 and proxies /api/* to http://localhost:3000.

Git hooks

pnpm install sets up a pre-commit hook (via husky + lint-staged) that lints and formats staged backend/frontend files automatically.

Other scripts

Run with pnpm --filter backend <script> / pnpm --filter frontend <script>, or cd into the package first:

Script Description
build Build for production
typecheck Run tsc --noEmit
lint Run ESLint
format Format with Prettier

backend's production build compiles to backend/dist/index.js (pnpm --filter backend start runs it); frontend's production build outputs to frontend/dist/, served as static files by the backend.

API

Method Path Description
GET /api/health Health check ({"status":"ok"})
GET /api/version Git commit hash baked in at build time ({"version":"<hash>"}, "unknown" outside Docker)
GET /api/dashboard Current dashboard snapshot
GET /api/charts/daily Daily production history
GET /api/charts/monthly Monthly production history
GET /api/charts/power Live power chart data

Configuration

Set environment variables (e.g. in a .env file for docker compose, or in .env.local for pnpm --filter backend dev).

Required

Variable Description
HA_URL Base URL of your Home Assistant instance, e.g. http://homeassistant.local:8123
HA_TOKEN Long-lived access token from your HA user profile

Optional — Pricing

Variable Description
FEED_IN_TARIFF Feed-in tariff in €/kWh (used to calculate feed-in earnings)
GRID_PRICE Grid electricity price in €/kWh (used to calculate self-consumption savings)

Optional — Sign Inversion

Some inverters/meters report power with the opposite sign convention. Set these to true to invert.

Variable Default Description
INVERT_GRID false Invert grid power sign
INVERT_BATT false Invert battery power sign

Optional — Entity IDs

All entity IDs support a comma-separated list of IDs whose values are summed (useful for multi-inverter setups).

Variable Description
ENTITY_PV_POWER Real-time PV generation power (W)
ENTITY_PV_TODAY Energy generated today (kWh)
ENTITY_PV_MONTH Energy generated this month (kWh)
ENTITY_PV_YEAR Energy generated this year (kWh)
ENTITY_PV_ALLTIME Total energy generated all time (kWh)
ENTITY_GRID Grid power — positive = export/feed-in, negative = import (W)
ENTITY_BATT_SOC Battery state of charge (%)
ENTITY_BATT_POWER Battery power — positive = charging, negative = discharging (W)
ENTITY_BATT_CHARGE_TODAY Energy charged to battery today (kWh)
ENTITY_BATT_DISCHARGE_TODAY Energy discharged from battery today (kWh)
ENTITY_FEED_IN_TODAY Energy fed into the grid today (kWh)
ENTITY_FEED_IN_TOTAL Total energy fed into the grid (kWh)
ENTITY_GRID_IMPORT_TODAY Energy imported from grid today (kWh)
ENTITY_EV_SOC EV state of charge (%)
ENTITY_EV_POWER EV charging power (W)
ENTITY_EV_ODOMETER EV odometer
ENTITY_EV_CHARGED Total energy charged to EV (kWh)
ENTITY_EV_CHARGING Binary sensor — EV currently charging
ENTITY_EV_CONNECTED Binary sensor — EV connected to charger

Tech Stack

  • Frontend (frontend/): React 18, TypeScript, Vite, Recharts
  • Backend (backend/): Node.js, Express, TypeScript
  • Deployment: Docker (multi-stage build), Docker Compose

Project Structure

frontend/     React + Vite SPA (src/, index.html, vite.config.ts)
backend/      Express API server (index.ts, haApi.ts — Home Assistant client)
Dockerfile    Multi-stage build: git hash, frontend build, backend build, runtime