- Python 99.4%
- Shell 0.4%
- Mako 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .nicegui | ||
| automations | ||
| common | ||
| config | ||
| docker | ||
| settings/alembic | ||
| tests | ||
| tui | ||
| web_ui | ||
| .env | ||
| .gcloudignore | ||
| .gitignore | ||
| automation_trigger_monitor.py | ||
| babel.cfg | ||
| build_and_push_docker.sh | ||
| cmd.py | ||
| config-local.yaml | ||
| config-test.yaml | ||
| config.yaml | ||
| presence_monitor.py | ||
| pyproject.toml | ||
| README.md | ||
| repomix-output.xml | ||
| run_container.sh | ||
| run_container_local.sh | ||
| uv.lock | ||
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.
- Verifica l'esistenza della cartella
/etc/docker:sudo install -d -m 0755 /etc/docker - Modifica o crea il file
/etc/docker/daemon.json:
(Sostituisci{ "insecure-registries": ["192.168.X.Y:5000"] }192.168.X.Ycon l'IP locale reale della macchina prestazionale). - Verifica che il formato sia corretto:
sudo dockerd --validate --config-file /etc/docker/daemon.json - 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
loguruo i tracciati del cron) rimangono persistenti sul file-system locale del MiniPC all'interno della cartellalogs/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
```