# 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](../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 ` (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 ` 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:** ```bash VAR=`cat /etc/inverter/mqtt.json | jq '.key' -r` [ ! -z "$VAR" ] && pushMQTTData "metric" "$VAR" ``` ## Configurazione ### inverter.conf ```properties 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 ```json { "server": "192.168.1.100", "port": "1883", "topic": "homeassistant", "devicename": "voltronic", "username": "", "password": "", "clientid": "voltronic_", "influx": { "enabled": "false", "host": "http://influxdb:8086", ... } } ``` ## Build e Deployment ### Build Locale (inverter-cli) ```bash cd sources/inverter-cli mkdir -p bin cmake . make ./bin/inverter_poller -h ``` ### Build Docker ```bash # 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 ```bash # 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 ```bash # 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:** ``` Esempio: QPIGS + CRC + \r ``` **Response:** ``` ( ... 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: ```yaml 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 - **Protocol Manual:** `/manual/` directory - **Forum AEVA:** http://forums.aeva.asn.au/viewtopic.php?t=4332 - **Skyboo Original:** https://skyboo.net/2017/03/monitoring-voltronic-power-axpert-mex-inverter-under-linux/ - **Docker Hub:** bushrangers/ha-voltronic-mqtt - **Home Assistant MQTT:** https://www.home-assistant.io/integrations/mqtt/ ## 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](../documentation/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