Home Assistant Statistics
  • Python 99.4%
  • Shell 0.4%
  • Mako 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Stefano Bartaletti fdb36f25f7 Cooling duration
2026-08-13 15:06:49 +02:00
.nicegui Dev 2026-07-08 13:30:17 +02:00
automations Record automation trigger 2026-08-12 14:27:16 +02:00
common Cooling duration 2026-08-13 15:00:45 +02:00
config Cooling duration 2026-08-13 14:22:44 +02:00
docker Record automation trigger 2026-08-12 08:55:11 +02:00
settings/alembic Cooling duration 2026-08-13 14:22:44 +02:00
tests Telegram message on invoice import 2026-07-29 20:18:29 +02:00
tui Web ui 2026-08-09 15:34:25 +02:00
web_ui Record automation trigger 2026-08-12 21:09:08 +02:00
.env Dev 2026-07-05 08:10:23 +02:00
.gcloudignore Presence monitor fixes 2026-08-11 07:24:54 +02:00
.gitignore Presence monitor fixes 2026-08-11 07:24:54 +02:00
automation_trigger_monitor.py Cooling duration 2026-08-13 15:06:49 +02:00
babel.cfg Translations 2026-07-30 14:01:42 +02:00
build_and_push_docker.sh Dev 2026-07-04 10:50:58 +02:00
cmd.py TUYA discovery 2026-08-06 20:48:17 +02:00
config-local.yaml Presence monitor fixes 2026-08-11 07:21:30 +02:00
config-test.yaml Cooling duration 2026-08-13 14:22:44 +02:00
config.yaml Local DB 2026-08-13 07:15:15 +02:00
presence_monitor.py Presence monitor fixes 2026-08-11 07:21:30 +02:00
pyproject.toml TUYA discovery 2026-08-06 20:48:17 +02:00
README.md Dev 2026-07-05 14:06:32 +02:00
repomix-output.xml Cooling duration 2026-08-13 15:06:49 +02:00
run_container.sh Dev 2026-07-07 14:17:54 +02:00
run_container_local.sh Local docker build 2026-07-15 17:23:28 +02:00
uv.lock TUYA discovery 2026-08-06 20:48:17 +02:00

HA-Stats — Utility Bill Parser & Monitor

Questo progetto si occupa di scaricare, elaborare e memorizzare i consumi di Luce e Gas (Dual Utility) importando i dati su MongoDB. La configurazione Docker è ottimizzata per la massima leggerezza ed efficienza (Alpine Linux ~50MB) grazie a una compilazione multi-stage basata su uv. Il flusso prevede la generazione dell'immagine su una Macchina Prestazionale (PC Fisso/Portatile) e il rilascio su un MiniPC sempre attivo tramite un Docker Registry locale.


📌 Architettura di Rete e Rilascio

[ MACCHINA PRESTAZIONALE ]                  [ MINIPC (Sempre Acceso) ]
  (Compilazione AMD64)                          (Esecuzione Servizi)
           │                                             ▲
           ▼                                             │
 ┌──────────────────┐       LAN Push (Porta 5000)        │
 │  Local Registry  │ ───────────────────────────────────┤
 └──────────────────┘                                    ▼
                                                ┌──────────────────┐
                                                │  Docker Engine   │
                                                │  (Insecure Reg)  │
                                                └────────┬─────────┘
                                                         │
                                                         ▼
                                                ┌──────────────────┐
                                                │ Container Alpine │
                                                │   (BusyBox Cron) │
                                                └──────────────────┘

🚀 1. Configurazione Iniziale (Una Tantum)

A. Sulla Macchina Prestazionale

Avvia il registro locale che farà da storage temporaneo per le immagini compilate:

docker run -d -p 5000:5000 --restart=always --name local-registry registry:2

Se usi Docker Desktop (Windows/macOS), vai in Settings -> Docker Engine e assicurati che sia configurato l'accesso locale aggiungendo "insecure-registries": ["localhost:5000"] nel JSON.

B. Sul MiniPC (Linux)

Configura il motore Docker affinché accetti le connessioni HTTP dal registro della macchina potente senza richiedere certificati HTTPS.

  1. Verifica l'esistenza della cartella /etc/docker:
    sudo install -d -m 0755 /etc/docker
    
  2. Modifica o crea il file /etc/docker/daemon.json:
    {
      "insecure-registries": ["192.168.X.Y:5000"]
    }
    
    (Sostituisci 192.168.X.Y con l'IP locale reale della macchina prestazionale).
  3. Verifica che il formato sia corretto:
    sudo dockerd --validate --config-file /etc/docker/daemon.json
    
  4. Riavvia il demone Docker per applicare le modifiche:
    sudo systemctl restart docker
    

🛠️ 2. Workflow di Sviluppo e Rilascio

Ogni volta che effettui modifiche al codice, aggiungi librerie o aggiorni le dipendenze:

Passo 1: Compila e Pusha (Dalla Macchina Prestazionale)

Apri il terminale nella root del progetto sulla tua macchina potente ed esegui i seguenti comandi:

# 1. Compila forzando l'architettura Intel/AMD (AMD64) del MiniPC
docker build --platform linux/amd64 -t 192.168.X.Y:5000/ha-stats:latest -f docker/Dockerfile .

# 2. Pusha l'immagine nel registro locale via LAN
docker push 192.168.X.Y:5000/ha-stats:latest

Passo 2: Aggiorna ed Esegui (Sul MiniPC)

Spostati nella cartella docker/ del tuo MiniPC ed esegui il deploy:

cd docker
# Scarica la nuova immagine appena pushata dal PC potente
docker compose pull
# Riavvia il container aggiornato in background
docker compose up -d

📂 3. Configurazione dell'Ambiente Container

I seguenti file devono essere posizionati e configurati all'interno della cartella docker/ del tuo progetto.

File: docker/Dockerfile

# Stage 1: Build delle dipendenze con UV su Alpine
FROM ghcr.io/astral-sh/uv:alpine AS builder
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
WORKDIR /app

# Dipendenze di build necessarie per pacchetti C (es. moduli di pandas/pypdf)
RUN apk add --no-cache gcc musl-dev python3-dev

RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    uv sync --frozen --no-install-project --no-dev

# Stage 2: Immagine finale minimale di runtime basata su Alpine pura
FROM python:alpine
WORKDIR /app

RUN mkdir -p /app/logs

# Copiamo l'ambiente virtuale isolato generato da UV
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"

# Copiamo il codice applicativo core
COPY common/ /app/utils/
COPY cmd.py /app/cmd.py

# Configurazione del sistema di cron nativo di BusyBox (Alpine)
COPY docker/crontab /var/spool/cron/crontabs/root
RUN chmod 0600 /var/spool/cron/crontabs/root

# Avvia il demone cron di BusyBox in primo piano (-f) loggando su stdout (-l 2)
CMD ["crond", "-f", "-l", "2"]

File: docker/docker-compose.yml

version: '3.8'

services:
  ha-stats:
    container_name: ha-stats
    image: 192.168.X.Y:5000/ha-stats:latest
    volumes:
      - ../config.yaml:/app/config.yaml:ro
      - ../logs:/app/logs
    environment:
      - TZ=Europe/Rome
      - PYTHONUNBUFFERED=1
    restart: unless-stopped

File: docker/crontab

# Esegui il download delle bollette ogni giorno alle 03:00 del mattino
0 3 * * * /app/.venv/bin/python /app/cmd.py download-bills >> /app/logs/cron_download.log 2>&1

# Esegui l'importazione delle statistiche ogni domenica alle 04:00 del mattino
0 4 * * * 0 /app/.venv/bin/python /app/cmd.py import-statistics >> /app/logs/cron_stats.log 2>&1

Nota importante per Alpine: mantieni tassativamente una riga vuota alla fine del file crontab per conformità con lo standard POSIX di BusyBox, altrimenti l'ultimo comando verrà ignorato.


📊 4. Comandi Utili per la Gestione sul MiniPC

Tutti i seguenti comandi vanno eseguiti navigando all'interno della cartella docker/ del MiniPC:

  • Visualizzare i log del demone di Cron (Stato del container): Utile per verificar che il container stia girando e che i trigger temporali vengano intercettati.

    docker compose logs -f ha-stats
    
  • Eseguire un task manualmente al volo (Bypass di Cron): Se desideri forzare l'esecuzione immediata di un comando Typer (es. uno scaricamento straordinario) senza attendere l'orario pianificato:

    docker compose run --rm ha-stats download-bills
    
  • Controllare i log applicativi specifici degli script: I log generati dall'applicazione (compresi gli errori catturati da loguru o i tracciati del cron) rimangono persistenti sul file-system locale del MiniPC all'interno della cartella logs/ posizionata nella root del progetto:

    tail -f ../logs/cron_download.log
    

5. NiceGUI

Struttura:

    ./
    ├── README.md
    ├── .env
    ├── main.py                          # Entry point
    ├── app/
    │   ├── __init__.py
    │   ├── layout.py                    # Main layout (menu + tabs shell)
    │   ├── settings.py                  # App-wide settings/config
    │   ├── pages/
    │   │   ├── __init__.py
    │   │   ├── home.py                  # Home tab content
    │   │   ├── dashboard.py             # Dashboard tab content
    │   │   ├── settings_page.py         # Settings tab content
    │   │   └── about.py                 # About tab content
    │   ├── components/
    │   │   ├── __init__.py
    │   │   ├── menu.py                  # Side menu component
    │   │   ├── tabs_container.py        # Tabs container component
    │   │   ├── header.py                # Top header/navbar component
    │   │   └── footer.py                # Footer component
    │   └── styles/
    │       ├── __init__.py
    │       └── theme.py                 # Colors, fonts, shared styles
    └── static/                          # Static assets (images, icons, etc.)
        └── logo.png
    ```