Files
docker-voltronic-homeassistant/.github/copilot-instructions.md
T
Pi Developer 6af9fcad7e
Build Docker Image for Raspberry Pi / build-and-push (push) Failing after 4m42s
feat(v2.0): Auto-discovery, correzione bug critici, e documentazione completa
🆕 Funzionalità Auto-Discovery
- Aggiunto metodo AutoDiscoverBufferSizes() per rilevamento automatico QPIGS/QPIRI/QMOD/QPIWS
- Supporto variabili d'ambiente (INVERTER_DEVICE, MQTT_SERVER, etc.)
- Caching persistente buffer sizes in /cache/inverter.conf.cache
- Flag -a/--auto-discover per modalità auto-detection

🐛 Bug Fixes Critici
- **Parsing interi**: Aggiunta attemptAddSettingInt() con stoi() invece di stof()
  - Fix: stof('98') = 98.0f → 97 (int), ora stoi('98') = 98 direttamente
  - Applicato a: qpiri, qpiws, qmod, qpigs
- **Thread sync**: Aggiunto ups_qpiws_changed a main loop e condizione exit poll()
  - Fix: loop principale controllava solo 3 flag su 4, causava hang
  - Fix: thread poll() non usciva in runOnce perché mancava controllo QPIWS
- **Config accuracy**: Corretti buffer sizes (qpiri: 98→103, qpiws: 36→40)
  - Rimosso sources/inverter-cli/inverter.conf che sovrascriveva config globale
  - Validato con test: inverter_poller -1 completa in 6s con JSON completo

📚 Documentazione Completa
- Creato documentation/CODE_ARCHITECTURE.md (38KB)
  - Mappa logica variabili globali
  - Flusso esecuzione main() con diagrammi ASCII
  - Sequence diagram classe cInverter (poll, query, auto-discovery)
  - Thread synchronization diagrams
  - MQTT integration bash scripts flow
  - Mappa concettuale 5-layer system architecture
  - Error handling e performance optimizations
- Organizzati file .md in documentation/ (AUTO_DISCOVERY, IMPLEMENTATION, QUICKSTART, DEBUG)
- Aggiornato README.md con sezione v2.0 e indice documentazione
- Aggiornato .github/copilot-instructions.md con novità v2.0

🔧 Miglioramenti Build & CI/CD
- Gitea Actions per build multi-arch (arm/v6, arm/v7, arm64, amd64, 386)
- Configurazione VS Code completa (tasks, launch, debug GDB)
- Script test-autodiscovery.sh e test-device.sh

 Testing Validato
- inverter_poller -1 completa in 6 secondi
- Output JSON completo con tutte le metriche
- Exit pulito senza timeout (exit code 0)
- Tutte le 4 query QMOD/QPIGS/QPIRI/QPIWS funzionanti
2026-01-25 15:00:48 +01:00

15 KiB

GitHub Copilot Instructions - Voltronic/Axpert MQTT Home Assistant Integration

Panoramica del Progetto

Questo progetto è un'applicazione Docker che monitora inverter solari Voltronic, Axpert, MPPSolar PIP, Voltacon, Effekta e altri inverter OEM basati su protocollo RS232. L'applicazione raccoglie dati telemetrici dall'inverter e li invia a Home Assistant tramite MQTT, permettendo anche di inviare comandi per controllare l'inverter remotamente.

🆕 Version 2.0 - Auto-Discovery Feature

La versione 2.0 introduce l'auto-discovery automatica dei buffer sizes dell'inverter, eliminando la necessità di configurazione manuale. Al primo avvio, l'applicazione:

  1. Rileva automaticamente le dimensioni corrette dei buffer per QPIGS, QPIRI, QMOD, QPIWS
  2. Salva i valori in /cache/inverter.conf.cache
  3. Nei successivi avvii, utilizza i valori cached per startup immediato

Novità tecniche principali:

  • 🔍 Auto-detection buffer sizes: Metodo AutoDiscoverBufferSizes() con iterazione 80-120 bytes
  • ⚙️ Configurazione ENV: Supporto variabili d'ambiente (INVERTER_DEVICE, MQTT_SERVER, etc.)
  • 💾 Caching persistente: Volume Docker /cache/ per persistenza tra restart
  • 🐛 Bug fixes critici:
    • Parsing interi: aggiunta attemptAddSettingInt() con stoi() invece di stof() che troncava valori
    • Thread sync: aggiunta ups_qpiws_changed al loop principale e condizione exit poll()
    • Config accuracy: corretti buffer sizes (qpiri=98→103, qpiws=36→40)

📖 Documentazione completa: documentation/CODE_ARCHITECTURE.md

Architettura

┌─────────────────┐
│   Inverter      │ ← RS232/USB
│   (Hardware)    │
└────────┬────────┘
         │
    ┌────▼────────┐
    │ inverter-cli│ (C++ - polling e parsing dati)
    │   poller    │ 🆕 + Auto-Discovery
    └────┬────────┘
         │ JSON output
    ┌────▼────────┐
    │ mqtt-push.sh│ (bash - push su MQTT)
    │   script    │
    └────┬────────┘
         │ MQTT
    ┌────▼────────┐
    │    Home     │
    │  Assistant  │
    └─────────────┘

Struttura del Progetto

Directory Principali

  • sources/inverter-cli/ - Applicazione C++ per la comunicazione con l'inverter

    • main.cpp - Entry point, parsing argomenti, loop principale, 🆕 auto-discovery
    • inverter.cpp/h - Classe per gestione comunicazione seriale e polling
    • tools.cpp/h - Utilities per logging
    • inputparser.cpp/h - Parser argomenti da riga di comando
    • CMakeLists.txt - Configurazione build CMake
  • sources/inverter-mqtt/ - Script bash per integrazione MQTT

    • entrypoint.sh - Entry point del container Docker
    • mqtt-init.sh - Inizializzazione sensori in Home Assistant
    • mqtt-push.sh - Invio dati MQTT e opzionalmente InfluxDB
    • mqtt-subscriber.sh - Ascolto comandi da Home Assistant
  • config/ - File di configurazione

    • inverter.conf - Configurazione device seriale, intervalli polling, fattori di correzione
    • mqtt.json - Configurazione MQTT server, credenziali, topic, mapping InfluxDB
  • documentation/ - Documentazione completa del progetto

    • CODE_ARCHITECTURE.md - 🆕 Mappa logica funzioni/variabili, flusso esecuzione, mappe concettuali
    • AUTO_DISCOVERY.md - Guida completa auto-discovery feature
    • IMPLEMENTATION.md - Changelog implementazione v2.0
    • QUICKSTART.md - Setup rapido e comandi essenziali
    • DEBUG.md - Guida completa debugging con GDB
    • README.md - Setup ambiente sviluppo VS Code
  • homeassistant/ - Template Lovelace dashboard

  • .gitea/workflows/ - Gitea Actions per build automatica multi-arch

Componenti Chiave

1. inverter-cli (C++)

Linguaggio: C++11
Build system: CMake
Dependencies: pthread

File principali:

  • main.cpp:

    • Legge configurazione da /etc/inverter/inverter.conf
    • Supporta flag: -d (debug), -1 (run-once), -r <command> (raw command), 🆕 -a (auto-discover)
    • Output JSON su stdout
    • Loop di polling con thread separati
    • 🆕 Funzione attemptAddSettingInt() per parsing interi (usa stoi() invece di stof())
    • 🆕 Correzione bug: aggiunto ups_qpiws_changed al loop principale
  • inverter.cpp:

    • Classe cInverter per comunicazione seriale
    • Configurazione porta seriale: 2400 baud, 8N1
    • Supporta comandi: QPIGS, QPIRI, QMOD, QPIWS
    • CRC checksum verification
    • Thread-safe con mutex
    • 🆕 Metodo AutoDiscoverBufferSizes() per rilevamento automatico
    • 🆕 Correzione bug: aggiunto ups_qpiws_changed alla condizione di exit del thread poll()
    • 🆕 Supporto ENV variables per configurazione runtime

Comandi supportati dall'inverter:

Query (lettura dati):

  • QPIGS - General Status Parameters (voltaggio, corrente, potenza, batteria)
  • QPIRI - Current Settings (rated voltages, currents, battery settings)
  • QMOD - Mode inquiry (Power On, Standby, Line, Battery, Fault, Power Saving)
  • QPIWS - Warning Status

Controllo (scrittura):

  • POP0x - Set output source priority (Utility/Solar/SBU)
  • PCP0x - Set charger priority
  • PBDV/PBCV/PBFT/PCVV - Battery voltage settings
  • PEx/PDx - Enable/Disable features (buzzer, bypass, power saving, etc.)

2. MQTT Integration (Bash)

mqtt-push.sh:

  • Esegue inverter_poller -1 per ottenere snapshot JSON
  • Parsa JSON con jq
  • Pubblica ogni metrica su topic separato
  • Formato topic: homeassistant/sensor/{devicename}_{metric}
  • Supporto opzionale InfluxDB

mqtt-subscriber.sh:

  • Ascolta topic command: homeassistant/sensor/{devicename}/command
  • Valida comandi con regex
  • Esegue inverter_poller -r <command> per inviarli

mqtt-init.sh:

  • Auto-discovery Home Assistant
  • Crea configurazione sensori MQTT
  • Definisce icone, unità di misura, device class

3. Docker Setup

Dockerfile.multiarch:

  • Base: debian:stretch
  • Architetture supportate: linux/arm/v6, linux/arm/v7, linux/arm64, linux/amd64, linux/386
  • Build cmake dell'applicazione C++
  • Healthcheck ogni 30s

docker-compose.yml:

  • Servizio voltronic-mqtt con privilegi per accesso device
  • Mapping device: /dev/ttyUSB0, /dev/ttyS0, /dev/hidraw0
  • Volume config: ./config/:/etc/inverter/
  • Watchtower opzionale per auto-update

Convenzioni di Codice

C++ (inverter-cli)

  • Standard: C++11 (--std=c++0x)

  • Stile nomi:

    • Classi: cNomeClasse (prefisso 'c')
    • Metodi: PascalCase (es. GetMode(), SetMode())
    • Variabili locali: snake_case (es. voltage_grid, batt_capacity)
    • Variabili globali: camelCase (es. devicename, runinterval)
    • Costanti: UPPER_CASE (es. LOG_FILE)
  • Threading:

    • Usare std::mutex per proteggere dati condivisi
    • Pattern detached thread per polling: thread t1(&cInverter::poll, this); t1.detach();
    • Usare atomic_bool per flag di stato
  • Logging:

    • Funzione lprintf() per debug condizionale
    • Scrive su stdout e file di log
    • Thread-safe con mutex
  • Error handling:

    • Try-catch per parsing configurazione
    • Controllo errno per operazioni file/seriale
    • Sleep e retry su errori apertura device

Bash Scripts

  • Stile:

    • Variabili uppercase per config (es. MQTT_SERVER)
    • Backtick o $() per command substitution
    • Controllo valori vuoti: [ ! -z "$var" ]
  • Pattern comuni:

    VAR=`cat /etc/inverter/mqtt.json | jq '.key' -r`
    [ ! -z "$VAR" ] && pushMQTTData "metric" "$VAR"
    

Configurazione

inverter.conf

device=/dev/ttyUSB0          # Device seriale (/dev/ttyS0, /dev/hidraw0)
run_interval=120             # Polling frequency (120 = ogni 30s)
amperage_factor=1.0          # Fattore correzione amperaggio
watt_factor=1.01             # Fattore correzione wattaggio
qpiri=103                    # 🆕 Buffer size comando QPIRI (corretto da 98)
qpiws=40                     # 🆕 Buffer size comando QPIWS (corretto da 36)
qmod=5                       # Buffer size comando QMOD
qpigs=110                    # Buffer size comando QPIGS

mqtt.json

{
  "server": "192.168.1.100",
  "port": "1883",
  "topic": "homeassistant",
  "devicename": "voltronic",
  "username": "",
  "password": "",
  "clientid": "voltronic_<random_hash>",
  "influx": {
    "enabled": "false",
    "host": "http://influxdb:8086",
    ...
  }
}

Build e Deployment

Build Locale (inverter-cli)

cd sources/inverter-cli
mkdir -p bin
cmake .
make
./bin/inverter_poller -h

Build Docker

# Single platform
docker build -f Dockerfile.multiarch -t voltronic-mqtt .

# Multi-platform (richiede buildx)
docker buildx build \
  --platform linux/arm/v6,linux/arm/v7,linux/arm64 \
  -f Dockerfile.multiarch \
  -t voltronic-mqtt:latest .

Debug

# Test diretto con debug
docker exec -it voltronic-mqtt bash -c '/opt/inverter-cli/bin/inverter_poller -d -1'

# Test comando raw
docker exec -it voltronic-mqtt bash -c '/opt/inverter-cli/bin/inverter_poller -r QPIGS'

# Logs container
docker logs -f voltronic-mqtt

Testing

Test Comunicazione Inverter

  1. Verifica device disponibile: ls -la /dev/tty*
  2. Test read-only: inverter_poller -d -1
  3. Test comando: inverter_poller -r QPIGS

Test MQTT

# Subscribe a tutti i topic
mosquitto_sub -h localhost -t "homeassistant/#" -v

# Pubblica comando test
mosquitto_pub -h localhost \
  -t "homeassistant/sensor/voltronic/command" \
  -m "QPIGS"

Metriche Principali

Dati Real-time (QPIGS)

  • AC Grid: Voltage, Frequency
  • AC Output: Voltage, Frequency, Load (VA/Watt/%),
  • PV Input: Voltage, Current, Watts, WattHour
  • Battery: Voltage, Capacity %, Charge Current, Discharge Current
  • System: Bus Voltage, Heatsink Temperature, Device Status
  • SCC: Voltage (Solar Charge Controller)

Configurazione Inverter (QPIRI)

  • Rated values (grid, output, battery)
  • Battery settings (recharge, under, bulk, float voltages)
  • Max charge currents
  • Priorities (output source, charger source)

Status (QMOD)

  1. Power_On
  2. Standby
  3. Line
  4. Battery
  5. Fault
  6. Power_Saving

Protocolli e Comunicazione

RS232 Protocol

  • Baud Rate: 2400
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • Flow control: None

Formato Messaggi

Query:

<command><CRC_HIGH><CRC_LOW><CR>
Esempio: QPIGS + CRC + \r

Response:

(<data> ... <data><CRC_HIGH><CRC_LOW><CR>
Esempio: (230.0 50.0 ... \r

CRC Calculation

  • CRC-16-CCITT modificato
  • Polynomiale: custom implementation in inverter.cpp
  • Verifica sia su TX che RX

Home Assistant Integration

Auto-Discovery

Il container pubblica automaticamente la configurazione dei sensori MQTT:

  • Topic: homeassistant/sensor/{devicename}_{metric}/config
  • Payload JSON con: name, state_topic, unit_of_measurement, device_class, icon

Invio Comandi

Pubblica su topic: homeassistant/sensor/{devicename}/command

Esempio automation:

automation:
  - alias: "Switch to Solar Priority Morning"
    trigger:
      platform: time
      at: "06:00:00"
    action:
      service: mqtt.publish
      data:
        topic: "homeassistant/sensor/voltronic/command"
        payload: "POP01"

Gitea Actions

Workflows

  1. docker-build.yml - Build e push multi-arch su tag/push
  2. docker-test.yml - Test build su PR
  3. docker-cleanup.yml - Pulizia immagini vecchie (schedulato)

Secrets Richiesti

  • DOCKER_USERNAME
  • DOCKER_PASSWORD

Troubleshooting

Problemi Comuni

"Unable to open device file":

  • Verificare permessi device: ls -la /dev/ttyUSB0
  • Verificare mapping in docker-compose.yml
  • Usare privileged: true nel container

"CRC error":

  • Controllare cablaggio RS232
  • Verificare buffer size in inverter.conf
  • Provare con debug: -d flag

"MQTT not connecting":

  • Verificare configurazione mqtt.json
  • Testare con mosquitto_pub/sub manualmente
  • Controllare firewall/rete

"Wrong values":

  • Calibrare amperage_factor e watt_factor
  • Confrontare con multimetro
  • Verificare versione firmware inverter

Note di Sicurezza

⚠️ ATTENZIONE:

  • Non inviare comandi senza comprendere l'effetto
  • Voltaggio batteria errato può danneggiare le batterie
  • Testare in ambiente sicuro prima di produzione
  • Backup configurazione inverter prima di modifiche
  • Usare voltage/temperature sensors per automazioni critiche

Risorse Utili

Suggerimenti per AI Coding

Quando lavori su questo progetto:

  1. Modifiche C++:

    • Sempre verificare thread-safety con mutex
    • Testare con -d -1 dopo modifiche
    • Controllare CRC per nuovi comandi
    • Mantenere compatibilità con buffer sizes configurabili
    • 🆕 Usare attemptAddSettingInt() per parsing interi, attemptAddSetting() per float
  2. Modifiche Bash:

    • Usare jq per parsing JSON
    • Verificare valori non vuoti prima di push MQTT
    • Mantenere pattern consistente con script esistenti
  3. Nuove metriche:

    • Aggiungere parsing in main.cpp
    • Aggiungere push in mqtt-push.sh
    • Aggiungere init in mqtt-init.sh
    • Documentare in README.md
  4. Testing:

    • Build prima di commit
    • Test con inverter reale se possibile
    • Verificare output JSON valido
    • Test MQTT end-to-end
    • 🆕 Testare sia con -1 (run-once) che loop continuo
  5. Docker:

    • Testare su architettura ARM prima di push
    • Verificare healthcheck funzionante
    • Mantenere immagine leggera
    • Documentare breaking changes
    • 🆕 Verificare volume /cache/ per persistenza config
  6. 🆕 Bug Fixes & Best Practices:

    • Integer parsing: Sempre usare stoi() per interi, mai stof() che tronca valori
    • Thread sync: Verificare che tutti i flag atomic siano inclusi nelle condizioni di exit
    • Config values: Usare auto-discovery -a per determinare buffer sizes corretti
    • Debug output: Usare fprintf(stderr, ...) per output incondizionato, lprintf() per debug
    • Documentazione: Consultare CODE_ARCHITECTURE.md per comprendere il flusso completo

Version History

  • v1.x - Supporto base Voltronic
  • v2.0 - 🆕 Multi-arch builds, Gitea Actions, Auto-discovery, Bug fixes critici
  • Future: Extended inverter models, WebUI, Grafana integration