- Aggiunto Step 1.5: query QPIGS prima del loop QPGS
- inv1 (master RS232): usa QPIGS DATA[19] = potenza PV misurata direttamente
dal controller MPPT (campo aggiunto nel firmware 'after_current_upgrade')
- inv2 (slave): formula DC-bus balance divisa per η_total (SCC+inverter losses)
- η calcolato dinamicamente da QPIGS quando batteria ferma (<2A carica/scarica)
altrimenti usa default 0.93 (~93.7% da misura reale su questo impianto)
- Corregge sottostima sistematica ~7% dovuta alle perdite DC→AC ignorate
Il protocollo QPGS non espone la corrente reale lato pannelli.
DATA[25] = corrente SCC→batteria SOLTANTO (0 quando batteria carica).
Formula corretta via conservazione energetica del DC bus:
P_pv = V_batt×DATA[25] + max(0, Load_W − V_batt×DATA[26])
Dove:
V_batt×DATA[25] = potenza SCC inviata alla batteria
Load_W = potenza consumata dal carico dal bus DC
V_batt×DATA[26] = potenza fornita dalla batteria in scarica
Casi coperti:
1. Bat. in carica (DATA[25]>0, DATA[26]=0): P = V_b×I_scc + Load
2. Bat. piena (DATA[25]=0, DATA[26]=0): P = Load
3. Bat. in scar. (DATA[25]=0, DATA[26]>0): P = max(0, Load−Pdisch)
Guard: calcolo solo quando SCC_charging (STATUS b5=1), altrimenti 0.
Aggiunto SCC_current (=DATA[25]) come campo separato per monitorare
la corrente SCC→batteria indipendentemente dalla produzione PV.
Aggiunto SCC_current al topic di discovery HA in mqtt-init-parallel.sh
- mqtt-push-parallel.sh: riscritto da 659 a 230 righe
* Rimosse tutte le meccaniche di serial discovery (VALID_SERIALS,
VALID_QPGS, PARALLEL_DISCOVERY, DIRECT_SERIALS, ecc.)
* Ora query direte QPGS0→inv1, QPGS1→inv2 senza discovery preliminare
* Numero inverter configurabile via CASCADE_COUNT env var (default 2)
* Fix PV_in_watts: quando DATA[25]=0 (batteria carica) e SCC_OK e
no AC grid (line_loss=1), usa Load_watt come proxy di produzione PV
* Aggiunto publish di PV_in_watthour e Load_watthour
* Aggiunto parsing corretto dei status flags dal byte di stato QPGS
- entrypoint.sh: riscritto da 240 a 131 righe
* Rimossa intera logica di auto-discovery buffer sizes
* Rimossi FORCE_DISCOVERY, SKIP_DISCOVERY, DISCOVERY_FLAG
* Rimossi run_discovery() e update_config_with_discovery()
* Startup immediato senza attese/tentativi di discovery
* CASCADE_COUNT env var propagata agli script
- healthcheck: corretto per processi effettivi del container
* Prima: cercava mqtt-subscriber + mosquitto_sub + watch (3 proc)
* watch non viene mai avviato → sempre unhealthy
* Ora: controlla mosquitto_sub (subscriber) + sleep (push loop cicla)
DATA[25] ('PV Input Current') nei reply QPGS è in realtà la corrente
in uscita dal SCC (Solar Charge Controller) verso la batteria, a tensione
batteria - NON la corrente ai pannelli PV a tensione PV.
Bug: PV_WATTS = DATA[14] (PV voltage ~246V) * DATA[25] (SCC current ~55A)
→ valore ~4-5x troppo alto (es. 246.8 * 55 = 13574W per inverter)
Fix: PV_WATTS = DATA[11] (battery voltage ~54V) * DATA[25] (SCC current)
→ valore corretto (es. 53.9 * 55 = 2964W per inverter)
Identico al comportamento di QPIGS in main.cpp:
pv_input_watts = scc_voltage * pv_input_current
con commento: 'input current is going to battery at battery voltage
(NOT at PV voltage)'
- Rimosso vecchio topic homeassistant/sensor/voltronic/config all'avvio
- Aggiunto flag -r (retain) a tutti i discovery topics
- MQTT init eseguito immediatamente all'avvio + ogni 5 minuti
- Aggiunto unique_id e device info a tutti i sensori per HA
- mqtt-subscriber ora ascolta su 3 topic:
- homeassistant/sensor/voltronic/command (legacy)
- homeassistant/sensor/voltronic_inv1_raw_cmd/command
- homeassistant/sensor/voltronic_inv2_raw_cmd/command
- Subscriber con output verbose e timestamp
- Discovery topics ora persistono dopo restart broker MQTT
Timing verificato:
- Init all'avvio: immediato
- Re-init periodico: ogni 5 minuti (300s)
- Data push: ogni 30 secondi
- Aggiunta funzione extractAndPublishAllData() con tutti i 33 parametri
- Parsing QPGS (19 params runtime) + QPIRI (8 params config) + PV_watts calcolato
- Fallback automatico a modalità standard se QPGS non disponibile
- Retry ridotto a 1 tentativo (2s delay) per performance
- Gestione errori NAK con messaggi informativi per utente
- Supporto bitmap status flags da QPGS (Load_on, SCC_on, AC_charge_on)
Note: Test mostrano che inverter attualmente in modalità Battery (QMOD=B)
risponde NAK a tutti i comandi eccetto QMOD. Necessaria verifica stato
fisico inverter o attivazione modalità parallela nel firmware.
FLUSSO IMPLEMENTATO:
1. All'avvio: registra discovery topics per 2 inverter (hardcoded)
2. Discovery topics ripetuti ogni 5 minuti (invece di 10)
3. Parallel discovery parametri con retry:
- Tenta discovery fino a 3 volte
- Se fallisce: attende 5s e riprova
- Se tutti i tentativi falliscono: assume 2 inverter
4. Estrazione dati ogni 30s per entrambi gli inverter
NAMING:
- Inverter 1: voltronic_inv1_*
- Inverter 2: voltronic_inv2_*
Discovery topics include tutti i 33 parametri per entrambi gli inverter
- Rimosso timeout e detection automatica
- Sempre modalità parallela forzata
- Default 2 inverter se parallel discovery fallisce
- Registra discovery per voltronic_inv1 e voltronic_inv2
NOTA: Se gli inverter non rispondono a QPGS, NON sono in modalità parallela.
Per gestire 2 inverter fisici separati, serve INVERTER_DEVICES=/dev/ttyUSB0:/dev/ttyUSB1
- Aggiunto timeout 15s al parallel discovery per evitare blocchi
- mqtt-init-parallel.sh in stile originale semplice
- Per ogni inverter scoperto: registra topic discovery (voltronic_inv1_*, inv2_*, ...)
- Discovery topics ogni 10 minuti invece di 5
- Fallback automatico a single-mode se timeout o count=0
- Mantiene la semplicità dello script originale
Il parallel discovery testa QPGS0-9 per trovare inverter configurati in parallelo.
Se timeout o nessun inverter trovato, usa modalità standard.
- Modificato entrypoint.sh per rilevare automaticamente inverter paralleli
- Usa flag -p per parallel discovery (testa QPGS0-9)
- Script mqtt-push-parallel.sh per pubblicare dati di ogni inverter
- Script mqtt-init-parallel.sh per discovery topics (ogni 10 min)
- Naming: voltronic_inv1, voltronic_inv2, ecc.
- Fallback automatico a single-mode se PARALLEL_COUNT=0
Nota: Il parallel discovery richiede che inverter supportino comandi QPGS
- Aggiornato mqtt-init.sh per supportare array INVERTER_DEVICES
- Registrazione discovery topics per ogni inverter (voltronic, voltronic2, ecc.)
- Aggiunto unique_id e device info per Home Assistant
- Flag retain sui config topics per persistenza
- Naming coerente con mqtt-push.sh (voltronic, voltronic2, voltronic3, ...)
- Echo output per debug registrazione topics
- Necessario configurare il runner per risolvere il dominio all'IP locale
- Evita problemi con pull dall'esterno usando tag con IP locale
- Mantiene compatibilità con accesso pubblico al registry
- Evita passaggio attraverso Cloudflare (413 Payload Too Large)
- Registry in rete locale: 192.168.1.37 invece di gitea.home-nas-ds.org
- Image name: 192.168.1.37/alessio/ha-voltronic-mqtt
- Sostituito GITEA_TOKEN con GITHUB_TOKEN (token standard Actions)
- Username: github.repository_owner invece di github.actor
- GITHUB_TOKEN è fornito automaticamente senza configurazione
- Sostituito DOCKER_USERNAME/PASSWORD con github.actor/GITEA_TOKEN
- Il token GITEA_TOKEN è fornito automaticamente dalle Actions
- Non richiede configurazione manuale dei secrets
- Implementato array parsing per INVERTER_DEVICES (separatore ':')
- Refactoring mqtt-push.sh con funzione process_inverter()
- Topic MQTT separati per ogni inverter (voltronic, voltronic2, voltronic3, ecc.)
- Aggiornate tutte le 33 metriche con devicename dinamico
- Fix parsing JSON con filtro grep per messaggi [POLL]
- Documentazione ENV variable INVERTER_DEVICES in docker-compose.yml
Esempio configurazione:
INVERTER_DEVICES=/dev/ttyUSB0:/dev/ttyUSB1:/dev/ttyUSB2
- Rimosso credenziali hardcoded da mqtt.json (devono essere fornite solo da ENV)
- Ottimizzato mqtt-push.sh: caricamento config MQTT una sola volta all'avvio
- Ridotto I/O con redirect stderr su /dev/null
- Fix errore sed con device path contenente slash
- Aggiunto controllo esecuzione update_mqtt_config solo se ENV impostate
- Ridotto consumo CPU da 25% a ~0-2%
Nuovo:
- Documentazione multi-inverter completa (MULTI_INVERTER.md)
- Aggiornato README con sezione performance e multi-inverter
- Aggiunto .gitignore per file cache/backup runtime
Fixes:
- Bug sed delimiter con device path /dev/ttyUSB*
- Letture ripetute mqtt.json con jq (30+ per ciclo)
- Credenziali non aggiornate da ENV se mqtt.json esiste
- Aggiunto check all'avvio per verificare esistenza inverter.conf e mqtt.json
- Se mancanti, crea file di default automaticamente
- Risolve problema volume mount che sovrascrive file copiati in build
- Config default con valori standard funzionanti
- ENV variables sovrascrivono comunque i default tramite update_mqtt_config()
Ora il container parte anche con directory ./config vuota
- Aggiunto quote all'output dei tag per evitare esecuzione come comando
- Risolve errore 'No such file or directory' quando tag contengono '/'
- Output ora corretto: echo "Tags:" && echo "${{ tags }}"
- Previene interpretazione shell dei tag come path/comandi
- Rimosse opzioni cache-from e cache-to type=gha
- GitHub Actions Cache non supportata da Gitea Actions
- Risolve errore 'dial tcp 172.16.8.2:36207: i/o timeout'
- Build ora procede senza cache (più lento ma funzionante)
- Possibile ottimizzazione futura: cache locale o registry
- Cambiato FROM debian:bullseye -> debian:bookworm
- Risolve errore 'no match for platform in manifest' per arm/v6
- Debian Bookworm (12) è la versione stable corrente
- Supporto multi-arch completo per linux/arm/v6,v7,arm64
- Bullseye è ora oldstable con supporto multi-arch limitato
- Aggiunto step 'Prepare image name' per gestire nome immagine dinamico
- Se secrets configurati: usa username/ha-voltronic-mqtt
- Se secrets mancanti: usa local/ha-voltronic-mqtt (build locale)
- Corretto flag SHOULD_PUSH basato su presenza secrets
- Risolto errore 'invalid tag' quando DOCKER_USERNAME è vuoto
Ora il workflow esegue build anche senza secrets configurati
- Aggiunto supporto ENV variables nel Dockerfile:
* INVERTER_DEVICE, MQTT_SERVER, MQTT_PORT, MQTT_TOPIC
* MQTT_DEVICENAME, MQTT_USERNAME, MQTT_PASSWORD
* FORCE_DISCOVERY, SKIP_DISCOVERY
- Implementata funzione update_mqtt_config() in entrypoint.sh
* Aggiorna automaticamente mqtt.json da ENV variables all'avvio
* Backup automatico configurazione originale
- Fix workflow Docker build:
* Login Docker Hub solo se secrets configurati
* Push solo se secrets disponibili (evita errori CI/CD)
* Build funziona anche senza secrets (utile per test locali)
- Aggiornato docker-compose.yml con esempio ENV variables
- Creata documentazione completa DOCKER_SETUP.md:
* Guida configurazione variabili d'ambiente
* Esempi docker-compose e docker run
* Guida configurazione secrets Gitea
* Troubleshooting e health check
Ora è possibile configurare completamente il container senza modificare file
- Aggiunto supporto lettura inverter paralleli tramite comandi QPGS0-QPGS9
- Implementato discovery automatico inverter con filtro duplicati e serial invalidi
- Risolti bug critici comunicazione seriale:
* Fix buffer ExecuteCmd da 7 a 200 bytes
* Supporto terminatori CR e LF
* Modalità blocking con delay 500ms
* Lettura byte-by-byte per terminatore affidabile
- Implementato script MQTT per pubblicazione dati multi-inverter:
* mqtt-push-parallel.sh con topic separati per ogni inverter
* Fix autenticazione MQTT con username/password
* Aggiunto flag retain (-r) per persistenza dati
- Creato test-loop-parallel.sh per simulazione completa container
- Aggiornata documentazione con compatibilità MKS IV e guida test loop
- Aggiornati profili debug VS Code per bash e parallel discovery
- Configurazione MQTT completa con server reale (192.168.1.37:1883)
Sistema testato e funzionante con 2 inverter Voltronic Axpert MKS IV
- Aggiunto id 'docker_build' allo step di build
- Quotato output tags per evitare errore 'command not found'
- Aggiunto output del digest dell'immagine
- Migliorato formato output con labels descrittivi
- Aggiunto env REGISTRY: 192.168.1.37:30008 per bypassare Cloudflare
- Configurato buildx per supportare HTTP insecure sul registry locale
- Aggiornato docker meta per usare registry IP diretto
- Modificato login per autenticarsi su 192.168.1.37:30008
- Risolto errore 413 Payload Too Large causato da Cloudflare
Il binario inverter_poller viene già compilato direttamente in bin/ da cmake/make, il comando 'mv inverter_poller bin/' causava errore perché il file non esisteva nella directory corrente.
- Debian Bullseye non supporta arm/v6 (solo Pi Zero W v1 e Pi 1)
- Mantenuti arm/v7 e arm64 (compatibili con Pi 3, 4, 5)
- Pi 5 a 64-bit usa linux/arm64
- Modificato docker-build.yml e docker-cleanup.yml
- Il token automatico github.token non ha permessi sufficienti
- Aggiunta guida SETUP_GITEA_TOKEN.md per configurazione
- Modificato docker-build.yml per usare gitea.home-nas-ds.org invece di Docker Hub
- Modificato docker-cleanup.yml per autenticazione con registry Gitea
- Usato github.token automatico invece di secrets esterni
- Aggiornata documentazione per riflettere i cambiamenti