feat: Ottimizzazione performance e gestione credenziali MQTT
Build Docker Image for Raspberry Pi / build-and-push (push) Successful in 6m49s
Build Docker Image for Raspberry Pi / build-and-push (push) Successful in 6m49s
- 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
This commit is contained in:
@@ -18,6 +18,10 @@ sources/inverter-cli/Makefile
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
|
|
||||||
|
# Runtime cache and backup files
|
||||||
|
config/.discovery_done
|
||||||
|
config/*.backup
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
# IDE files
|
# IDE files
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ ADD sources/ /opt/
|
|||||||
ADD config/ /etc/inverter/
|
ADD config/ /etc/inverter/
|
||||||
|
|
||||||
RUN cd /opt/inverter-cli && \
|
RUN cd /opt/inverter-cli && \
|
||||||
mkdir bin && cmake . && make
|
mkdir -p bin && cmake . && make
|
||||||
|
|
||||||
# Environment variables for runtime configuration
|
# Environment variables for runtime configuration
|
||||||
ENV INVERTER_DEVICE="/dev/ttyUSB0" \
|
ENV INVERTER_DEVICE="/dev/ttyUSB0" \
|
||||||
|
|||||||
@@ -101,7 +101,66 @@ environment:
|
|||||||
- SKIP_DISCOVERY=false # Skip discovery, use inverter.conf values
|
- SKIP_DISCOVERY=false # Skip discovery, use inverter.conf values
|
||||||
```
|
```
|
||||||
|
|
||||||
**📖 See [AUTO_DISCOVERY.md](AUTO_DISCOVERY.md) for complete documentation** including:
|
**📖 See [AUTO_DISCOVERY.md](documentation/AUTO_DISCOVERY.md) for complete documentation** including:
|
||||||
|
- How auto-discovery works
|
||||||
|
- Environment variable reference
|
||||||
|
- Multi-inverter setups
|
||||||
|
- Troubleshooting guide
|
||||||
|
- Migration from older versions
|
||||||
|
|
||||||
|
### 🔌 Multi-Inverter Support
|
||||||
|
|
||||||
|
Il sistema supporta il monitoraggio di **più inverter in parallelo**. Ogni inverter richiede un container separato con:
|
||||||
|
- Device seriale dedicato (`/dev/ttyUSB0`, `/dev/ttyUSB1`, ecc.)
|
||||||
|
- Nome device MQTT unico (`inverter1`, `inverter2`, ecc.)
|
||||||
|
- Directory config separata per ogni inverter
|
||||||
|
|
||||||
|
**📖 Guida completa:** [MULTI_INVERTER.md](documentation/MULTI_INVERTER.md)
|
||||||
|
|
||||||
|
**Esempio configurazione 2 inverter:**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
voltronic-inverter1:
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB0
|
||||||
|
- MQTT_DEVICENAME=inverter1
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=your_password
|
||||||
|
volumes:
|
||||||
|
- ./config/inverter1/:/etc/inverter/
|
||||||
|
devices:
|
||||||
|
- /dev/ttyUSB0:/dev/ttyUSB0:rwm
|
||||||
|
|
||||||
|
voltronic-inverter2:
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB1
|
||||||
|
- MQTT_DEVICENAME=inverter2
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=your_password
|
||||||
|
volumes:
|
||||||
|
- ./config/inverter2/:/etc/inverter/
|
||||||
|
devices:
|
||||||
|
- /dev/ttyUSB1:/dev/ttyUSB1:rwm
|
||||||
|
```
|
||||||
|
|
||||||
|
**Topic MQTT risultanti:**
|
||||||
|
- Inverter 1: `homeassistant/sensor/inverter1_Battery_voltage`, `inverter1_PV_in_watts`, ecc.
|
||||||
|
- Inverter 2: `homeassistant/sensor/inverter2_Battery_voltage`, `inverter2_PV_in_watts`, ecc.
|
||||||
|
|
||||||
|
### ⚡ Performance Optimization (v2.0+)
|
||||||
|
|
||||||
|
Il container è stato ottimizzato per ridurre il consumo di risorse:
|
||||||
|
- **CPU**: ~0-2% per inverter (spike durante polling ogni 30s)
|
||||||
|
- **RAM**: ~10-15 MB per inverter
|
||||||
|
- **Network**: ~1-2 KB/s per inverter
|
||||||
|
|
||||||
|
**Ottimizzazioni implementate:**
|
||||||
|
- Caricamento configurazione MQTT una sola volta all'avvio
|
||||||
|
- Eliminazione letture ripetute file con `jq`
|
||||||
|
- Redirect stderr per ridurre I/O
|
||||||
|
- Timeout su operazioni inverter per evitare hang
|
||||||
|
|
||||||
|
**📖 See [AUTO_DISCOVERY.md](documentation/AUTO_DISCOVERY.md) for complete documentation** including:
|
||||||
- How auto-discovery works
|
- How auto-discovery works
|
||||||
- Environment variable reference
|
- Environment variable reference
|
||||||
- Multi-inverter setups
|
- Multi-inverter setups
|
||||||
|
|||||||
+47
-47
@@ -1,52 +1,52 @@
|
|||||||
{
|
{
|
||||||
"server": "192.168.1.37",
|
"server": "192.168.1.37",
|
||||||
"port": "1883",
|
"port": "1883",
|
||||||
"topic": "homeassistant",
|
"topic": "homeassistant",
|
||||||
"devicename": "voltronic",
|
"devicename": "voltronic",
|
||||||
|
"username": "mqtt_user",
|
||||||
|
"password": "3tUhCpuDs43e#@k",
|
||||||
|
"clientid": "voltronic_bd8041d0cdf131a6ba4e5b3360b8bc5a",
|
||||||
|
"influx": {
|
||||||
|
"enabled": "false",
|
||||||
|
"host": "http://[INFLUX_IP_OR_URL]:8086",
|
||||||
"username": "",
|
"username": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"clientid": "voltronic_bd8041d0cdf131a6ba4e5b3360b8bc5a",
|
"device": "voltronic",
|
||||||
"influx": {
|
"prefix": "solar",
|
||||||
"enabled": "false",
|
"database": "solar",
|
||||||
"host": "http://[INFLUX_IP_OR_URL]:8086",
|
"namingMap": {
|
||||||
"username": "",
|
"Inverter_mode": "output_mode",
|
||||||
"password": "",
|
"AC_grid_voltage": "grid_voltage",
|
||||||
"device": "voltronic",
|
"AC_grid_frequency": "grid_frecuency",
|
||||||
"prefix": "solar",
|
"AC_out_voltage": "ac_output_voltage",
|
||||||
"database": "solar",
|
"AC_out_frequency": "ac_output_frecuency",
|
||||||
"namingMap": {
|
"PV_in_voltage": "pv_input_voltage_1",
|
||||||
"Inverter_mode": "output_mode",
|
"PV_in_current": "pv_input_current_for_battery",
|
||||||
"AC_grid_voltage": "grid_voltage",
|
"PV_in_watts": "pv_input_watts",
|
||||||
"AC_grid_frequency": "grid_frecuency",
|
"PV_in_watthour": "pv_input_watthour",
|
||||||
"AC_out_voltage": "ac_output_voltage",
|
"SCC_voltage": "battery_voltage_from_scc",
|
||||||
"AC_out_frequency": "ac_output_frecuency",
|
"Load_pct": "output_load_percent",
|
||||||
"PV_in_voltage": "pv_input_voltage_1",
|
"Load_watt": "output_load_watt",
|
||||||
"PV_in_current": "pv_input_current_for_battery",
|
"Load_watthour": "outpu_load_watthour",
|
||||||
"PV_in_watts": "pv_input_watts",
|
"Load_va": "ac_output_power_va",
|
||||||
"PV_in_watthour": "pv_input_watthour",
|
"Bus_voltage": "bus_voltage",
|
||||||
"SCC_voltage": "battery_voltage_from_scc",
|
"Heatsink_temperature": "inverter_heat_sink_temperature",
|
||||||
"Load_pct": "output_load_percent",
|
"Battery_capacity": "battery_capacity",
|
||||||
"Load_watt": "output_load_watt",
|
"Battery_voltage": "battery_voltage",
|
||||||
"Load_watthour": "outpu_load_watthour",
|
"Battery_charge_current": "battery_charging_current",
|
||||||
"Load_va": "ac_output_power_va",
|
"Battery_discharge_current": "battery_discharge_current",
|
||||||
"Bus_voltage": "bus_voltage",
|
"Load_status_on": "load_status_on",
|
||||||
"Heatsink_temperature": "inverter_heat_sink_temperature",
|
"SCC_charge_on": "scc_charge_on",
|
||||||
"Battery_capacity": "battery_capacity",
|
"AC_charge_on": "ac_charge_on",
|
||||||
"Battery_voltage": "battery_voltage",
|
"Battery_recharge_voltage": "battery_recharge_voltage",
|
||||||
"Battery_charge_current": "battery_charging_current",
|
"Battery_under_voltage": "battery_under_voltage",
|
||||||
"Battery_discharge_current": "battery_discharge_current",
|
"Battery_bulk_voltage": "battery_bulk_voltage",
|
||||||
"Load_status_on": "load_status_on",
|
"Battery_float_voltage": "battery_float_voltage",
|
||||||
"SCC_charge_on": "scc_charge_on",
|
"Max_grid_charge_current": "max_grid_charge_current",
|
||||||
"AC_charge_on": "ac_charge_on",
|
"Max_charge_current": "max_charge_current",
|
||||||
"Battery_recharge_voltage": "battery_recharge_voltage",
|
"Out_source_priority": "output_source_priority",
|
||||||
"Battery_under_voltage": "battery_under_voltage",
|
"Charger_source_priority": "charger_source_priority",
|
||||||
"Battery_bulk_voltage": "battery_bulk_voltage",
|
"Battery_redischarge_voltage": "battery_re_discharge_voltage"
|
||||||
"Battery_float_voltage": "battery_float_voltage",
|
|
||||||
"Max_grid_charge_current": "max_grid_charge_current",
|
|
||||||
"Max_charge_current": "max_charge_current",
|
|
||||||
"Out_source_priority": "output_source_priority",
|
|
||||||
"Charger_source_priority": "charger_source_priority",
|
|
||||||
"Battery_redischarge_voltage": "battery_re_discharge_voltage"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -1,14 +1,12 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
voltronic-mqtt:
|
voltronic-mqtt:
|
||||||
# Immagine custom da Gitea registry
|
# Build locale per test
|
||||||
image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.multiarch
|
||||||
|
|
||||||
# Uncomment if you want to build your own local version.
|
# Immagine custom da Gitea registry (decommentare quando pronta)
|
||||||
#build:
|
# image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
||||||
# context: .
|
|
||||||
# dockerfile: Dockerfile.multiarch
|
|
||||||
|
|
||||||
container_name: voltronic-mqtt
|
container_name: voltronic-mqtt
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,353 @@
|
|||||||
|
# Configurazione Multi-Inverter
|
||||||
|
|
||||||
|
## Panoramica
|
||||||
|
|
||||||
|
Il sistema supporta **un inverter per container**. Per monitorare più inverter, devi eseguire più istanze del container, ciascuna configurata con:
|
||||||
|
- Device seriale diverso (`/dev/ttyUSB0`, `/dev/ttyUSB1`, ecc.)
|
||||||
|
- Nome device MQTT unico (`voltronic1`, `voltronic2`, ecc.)
|
||||||
|
- Topic MQTT dedicato (opzionale)
|
||||||
|
|
||||||
|
## Configurazione Docker Compose per Due Inverter
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# Primo Inverter - /dev/ttyUSB0
|
||||||
|
voltronic-inverter1:
|
||||||
|
image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
||||||
|
container_name: voltronic-inverter1
|
||||||
|
privileged: true
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB0
|
||||||
|
- MQTT_SERVER=192.168.1.37
|
||||||
|
- MQTT_PORT=1883
|
||||||
|
- MQTT_TOPIC=homeassistant
|
||||||
|
- MQTT_DEVICENAME=inverter1 # Nome unico per primo inverter
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=your_password_here
|
||||||
|
- FORCE_DISCOVERY=false
|
||||||
|
- SKIP_DISCOVERY=false
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./config/inverter1/:/etc/inverter/
|
||||||
|
- voltronic-cache1:/cache/
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/bus/usb:/dev/bus/usb:rwm
|
||||||
|
- /dev/ttyUSB0:/dev/ttyUSB0:rwm
|
||||||
|
|
||||||
|
# Secondo Inverter - /dev/ttyUSB1
|
||||||
|
voltronic-inverter2:
|
||||||
|
image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
||||||
|
container_name: voltronic-inverter2
|
||||||
|
privileged: true
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB1
|
||||||
|
- MQTT_SERVER=192.168.1.37
|
||||||
|
- MQTT_PORT=1883
|
||||||
|
- MQTT_TOPIC=homeassistant
|
||||||
|
- MQTT_DEVICENAME=inverter2 # Nome unico per secondo inverter
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=your_password_here
|
||||||
|
- FORCE_DISCOVERY=false
|
||||||
|
- SKIP_DISCOVERY=false
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./config/inverter2/:/etc/inverter/
|
||||||
|
- voltronic-cache2:/cache/
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/bus/usb:/dev/bus/usb:rwm
|
||||||
|
- /dev/ttyUSB1:/dev/ttyUSB1:rwm
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
voltronic-cache1:
|
||||||
|
voltronic-cache2:
|
||||||
|
```
|
||||||
|
|
||||||
|
## Struttura Directory Config
|
||||||
|
|
||||||
|
Ogni inverter deve avere la propria directory di configurazione:
|
||||||
|
|
||||||
|
```
|
||||||
|
config/
|
||||||
|
├── inverter1/
|
||||||
|
│ ├── inverter.conf # Configurazione inverter 1
|
||||||
|
│ ├── mqtt.json # Template MQTT (credenziali vuote)
|
||||||
|
│ └── .discovery_done # Cache discovery (creato automaticamente)
|
||||||
|
└── inverter2/
|
||||||
|
├── inverter.conf # Configurazione inverter 2
|
||||||
|
├── mqtt.json # Template MQTT (credenziali vuote)
|
||||||
|
└── .discovery_done # Cache discovery (creato automaticamente)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Topic MQTT Risultanti
|
||||||
|
|
||||||
|
Con la configurazione sopra, i sensori verranno pubblicati su:
|
||||||
|
|
||||||
|
**Inverter 1:**
|
||||||
|
- `homeassistant/sensor/inverter1_Battery_voltage`
|
||||||
|
- `homeassistant/sensor/inverter1_PV_in_watts`
|
||||||
|
- `homeassistant/sensor/inverter1_Load_watt`
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Inverter 2:**
|
||||||
|
- `homeassistant/sensor/inverter2_Battery_voltage`
|
||||||
|
- `homeassistant/sensor/inverter2_PV_in_watts`
|
||||||
|
- `homeassistant/sensor/inverter2_Load_watt`
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## Identificazione Device Seriali
|
||||||
|
|
||||||
|
Per identificare quale inverter è connesso a quale porta USB:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lista tutti i device USB seriali
|
||||||
|
ls -la /dev/ttyUSB*
|
||||||
|
|
||||||
|
# Mostra info dettagliate device
|
||||||
|
udevadm info --name=/dev/ttyUSB0 | grep ID_SERIAL
|
||||||
|
|
||||||
|
# Test comunicazione con inverter
|
||||||
|
docker run --rm --device=/dev/ttyUSB0:/dev/ttyUSB0 \
|
||||||
|
gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest \
|
||||||
|
/opt/inverter-cli/bin/inverter_poller -d -1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creazione File di Configurazione
|
||||||
|
|
||||||
|
### inverter.conf (per ogni inverter)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Crea directory config per ogni inverter
|
||||||
|
mkdir -p config/inverter1 config/inverter2
|
||||||
|
|
||||||
|
# Crea inverter.conf per inverter1
|
||||||
|
cat > config/inverter1/inverter.conf << 'EOF'
|
||||||
|
device=/dev/ttyUSB0
|
||||||
|
run_interval=120
|
||||||
|
amperage_factor=1.0
|
||||||
|
watt_factor=1.01
|
||||||
|
qpiri=103
|
||||||
|
qpiws=40
|
||||||
|
qmod=5
|
||||||
|
qpigs=110
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Crea inverter.conf per inverter2
|
||||||
|
cat > config/inverter2/inverter.conf << 'EOF'
|
||||||
|
device=/dev/ttyUSB1
|
||||||
|
run_interval=120
|
||||||
|
amperage_factor=1.0
|
||||||
|
watt_factor=1.01
|
||||||
|
qpiri=103
|
||||||
|
qpiws=40
|
||||||
|
qmod=5
|
||||||
|
qpigs=110
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### mqtt.json (template per ogni inverter)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Crea mqtt.json per inverter1
|
||||||
|
cat > config/inverter1/mqtt.json << 'EOF'
|
||||||
|
{
|
||||||
|
"server": "192.168.1.37",
|
||||||
|
"port": "1883",
|
||||||
|
"topic": "homeassistant",
|
||||||
|
"devicename": "inverter1",
|
||||||
|
"username": "",
|
||||||
|
"password": "",
|
||||||
|
"clientid": "inverter1_auto",
|
||||||
|
"influx": {
|
||||||
|
"enabled": "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Crea mqtt.json per inverter2
|
||||||
|
cat > config/inverter2/mqtt.json << 'EOF'
|
||||||
|
{
|
||||||
|
"server": "192.168.1.37",
|
||||||
|
"port": "1883",
|
||||||
|
"topic": "homeassistant",
|
||||||
|
"devicename": "inverter2",
|
||||||
|
"username": "",
|
||||||
|
"password": "",
|
||||||
|
"clientid": "inverter2_auto",
|
||||||
|
"influx": {
|
||||||
|
"enabled": "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** Le credenziali MQTT vengono fornite tramite ENV variables e aggiornate automaticamente all'avvio del container.
|
||||||
|
|
||||||
|
## Avvio Container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Avvia entrambi i container
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Verifica stato
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# Verifica log primo inverter
|
||||||
|
docker logs -f voltronic-inverter1
|
||||||
|
|
||||||
|
# Verifica log secondo inverter
|
||||||
|
docker logs -f voltronic-inverter2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Discovery Automatica
|
||||||
|
|
||||||
|
Al primo avvio, ogni container:
|
||||||
|
1. Rileva automaticamente i buffer sizes dell'inverter connesso
|
||||||
|
2. Salva la configurazione in `.discovery_done`
|
||||||
|
3. Nei successivi restart, usa i valori cached
|
||||||
|
|
||||||
|
Per forzare re-discovery:
|
||||||
|
```bash
|
||||||
|
# Primo inverter
|
||||||
|
docker exec voltronic-inverter1 rm /etc/inverter/.discovery_done
|
||||||
|
docker restart voltronic-inverter1
|
||||||
|
|
||||||
|
# Secondo inverter
|
||||||
|
docker exec voltronic-inverter2 rm /etc/inverter/.discovery_done
|
||||||
|
docker restart voltronic-inverter2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Home Assistant Integration
|
||||||
|
|
||||||
|
Entrambi gli inverter verranno rilevati automaticamente in Home Assistant tramite MQTT Discovery. I sensori appariranno come dispositivi separati:
|
||||||
|
|
||||||
|
- **Device: inverter1**
|
||||||
|
- Sensori: Battery Voltage, PV Watts, Load, ecc.
|
||||||
|
- **Device: inverter2**
|
||||||
|
- Sensori: Battery Voltage, PV Watts, Load, ecc.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Problema: Container non riesce ad accedere al device
|
||||||
|
|
||||||
|
**Soluzione:** Verifica permessi device e gruppo utente
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Aggiungi utente al gruppo dialout
|
||||||
|
sudo usermod -aG dialout $USER
|
||||||
|
|
||||||
|
# Verifica permessi device
|
||||||
|
ls -la /dev/ttyUSB*
|
||||||
|
|
||||||
|
# Dovrebbe mostrare: crw-rw---- 1 root dialout ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problema: Discovery fallisce per un inverter
|
||||||
|
|
||||||
|
**Causa:** Buffer sizes incompatibili o device non risponde
|
||||||
|
|
||||||
|
**Soluzione:** Esegui discovery manuale con debug
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it voltronic-inverter1 \
|
||||||
|
/opt/inverter-cli/bin/inverter_poller -d -a
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problema: Topic MQTT sovrapposti
|
||||||
|
|
||||||
|
**Causa:** Entrambi i container usano lo stesso `MQTT_DEVICENAME`
|
||||||
|
|
||||||
|
**Soluzione:** Verifica che ogni container abbia nome unico:
|
||||||
|
- inverter1: `MQTT_DEVICENAME=inverter1`
|
||||||
|
- inverter2: `MQTT_DEVICENAME=inverter2`
|
||||||
|
|
||||||
|
### Problema: Alto consumo CPU
|
||||||
|
|
||||||
|
**Causa:** Intervallo polling troppo frequente
|
||||||
|
|
||||||
|
**Soluzione:** Aumenta `run_interval` in `inverter.conf`:
|
||||||
|
```bash
|
||||||
|
# Default: 120 (ogni 30s)
|
||||||
|
# Meno frequente: 240 (ogni 60s)
|
||||||
|
run_interval=240
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance e Risorse
|
||||||
|
|
||||||
|
**Consumo per singolo container:**
|
||||||
|
- CPU: ~0-2% (spike ogni 30s durante polling)
|
||||||
|
- RAM: ~10-15 MB
|
||||||
|
- Network: ~1-2 KB/s (MQTT messages)
|
||||||
|
|
||||||
|
**Consumo totale per 2 inverter:**
|
||||||
|
- CPU: ~0-4%
|
||||||
|
- RAM: ~20-30 MB
|
||||||
|
- Network: ~2-4 KB/s
|
||||||
|
|
||||||
|
## Sicurezza
|
||||||
|
|
||||||
|
⚠️ **IMPORTANTE:**
|
||||||
|
- Non committare credenziali MQTT in `mqtt.json` (devono rimanere vuote)
|
||||||
|
- Le credenziali vengono fornite solo tramite ENV variables
|
||||||
|
- Usa password forti per l'accesso MQTT broker
|
||||||
|
- Considera l'uso di Docker secrets per ambienti production
|
||||||
|
|
||||||
|
## Esempio Completo: Due Inverter in Parallelo
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
inverter-garage:
|
||||||
|
image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
||||||
|
container_name: inverter-garage
|
||||||
|
privileged: true
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB0
|
||||||
|
- MQTT_SERVER=192.168.1.37
|
||||||
|
- MQTT_DEVICENAME=garage
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=${MQTT_PASSWORD} # Da .env file
|
||||||
|
volumes:
|
||||||
|
- ./config/garage/:/etc/inverter/
|
||||||
|
- voltronic-garage:/cache/
|
||||||
|
devices:
|
||||||
|
- /dev/ttyUSB0:/dev/ttyUSB0:rwm
|
||||||
|
|
||||||
|
inverter-cantina:
|
||||||
|
image: gitea.home-nas-ds.org/alessio/docker-voltronic-homeassistant:latest
|
||||||
|
container_name: inverter-cantina
|
||||||
|
privileged: true
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- INVERTER_DEVICE=/dev/ttyUSB1
|
||||||
|
- MQTT_SERVER=192.168.1.37
|
||||||
|
- MQTT_DEVICENAME=cantina
|
||||||
|
- MQTT_USERNAME=mqtt_user
|
||||||
|
- MQTT_PASSWORD=${MQTT_PASSWORD} # Da .env file
|
||||||
|
volumes:
|
||||||
|
- ./config/cantina/:/etc/inverter/
|
||||||
|
- voltronic-cantina:/cache/
|
||||||
|
devices:
|
||||||
|
- /dev/ttyUSB1:/dev/ttyUSB1:rwm
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
voltronic-garage:
|
||||||
|
voltronic-cantina:
|
||||||
|
```
|
||||||
|
|
||||||
|
**.env file:**
|
||||||
|
```bash
|
||||||
|
MQTT_PASSWORD=your_secure_password_here
|
||||||
|
```
|
||||||
|
|
||||||
|
Questo setup permette di monitorare due inverter in parallelo con nomi descrittivi e gestione centralizzata delle credenziali.
|
||||||
@@ -68,10 +68,17 @@ echo ""
|
|||||||
# Function to update MQTT configuration
|
# Function to update MQTT configuration
|
||||||
update_mqtt_config() {
|
update_mqtt_config() {
|
||||||
local mqtt_conf="/etc/inverter/mqtt.json"
|
local mqtt_conf="/etc/inverter/mqtt.json"
|
||||||
|
|
||||||
|
# Solo aggiorna se le ENV variables sono impostate
|
||||||
|
if [ -z "$MQTT_USERNAME" ] && [ -z "$MQTT_PASSWORD" ]; then
|
||||||
|
echo "ℹ MQTT credentials not provided via ENV, using values from mqtt.json"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Updating MQTT configuration from environment variables..."
|
echo "Updating MQTT configuration from environment variables..."
|
||||||
|
|
||||||
# Backup original
|
# Backup original
|
||||||
cp $mqtt_conf ${mqtt_conf}.backup
|
cp $mqtt_conf ${mqtt_conf}.backup 2>/dev/null || true
|
||||||
|
|
||||||
# Update MQTT settings using jq
|
# Update MQTT settings using jq
|
||||||
jq --arg server "$MQTT_SERVER" \
|
jq --arg server "$MQTT_SERVER" \
|
||||||
@@ -87,6 +94,13 @@ update_mqtt_config() {
|
|||||||
echo " Server: $MQTT_SERVER:$MQTT_PORT"
|
echo " Server: $MQTT_SERVER:$MQTT_PORT"
|
||||||
echo " Topic: $MQTT_TOPIC/sensor/$MQTT_DEVICENAME"
|
echo " Topic: $MQTT_TOPIC/sensor/$MQTT_DEVICENAME"
|
||||||
[ ! -z "$MQTT_USERNAME" ] && echo " Auth: Enabled (username: $MQTT_USERNAME)"
|
[ ! -z "$MQTT_USERNAME" ] && echo " Auth: Enabled (username: $MQTT_USERNAME)"
|
||||||
|
|
||||||
|
# Verifica che le credenziali siano state scritte
|
||||||
|
local check_user=$(jq -r '.username' $mqtt_conf)
|
||||||
|
local check_pass=$(jq -r '.password' $mqtt_conf)
|
||||||
|
if [ -z "$check_user" ] || [ -z "$check_pass" ]; then
|
||||||
|
echo "⚠ WARNING: MQTT credentials were not properly written to config file!"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +216,7 @@ else
|
|||||||
if [[ $line =~ ^(device|qmod|qpigs|qpiri|qpiws)= ]]; then
|
if [[ $line =~ ^(device|qmod|qpigs|qpiri|qpiws)= ]]; then
|
||||||
key=$(echo "$line" | cut -d= -f1)
|
key=$(echo "$line" | cut -d= -f1)
|
||||||
value=$(echo "$line" | cut -d= -f2)
|
value=$(echo "$line" | cut -d= -f2)
|
||||||
sed -i "s/^$key=.*/$key=$value/g" $CONF_FILE
|
sed -i "s|^$key=.*|$key=$value|g" $CONF_FILE
|
||||||
fi
|
fi
|
||||||
done < "$DISCOVERY_FLAG"
|
done < "$DISCOVERY_FLAG"
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,51 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
INFLUX_ENABLED=`cat /etc/inverter/mqtt.json | jq '.influx.enabled' -r`
|
|
||||||
|
# Carica configurazione MQTT una sola volta all'inizio (ottimizzazione performance)
|
||||||
|
MQTT_CONFIG_FILE="/etc/inverter/mqtt.json"
|
||||||
|
MQTT_SERVER=$(jq -r '.server' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_PORT=$(jq -r '.port' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_TOPIC=$(jq -r '.topic' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_DEVICENAME=$(jq -r '.devicename' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_USERNAME=$(jq -r '.username' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_PASSWORD=$(jq -r '.password' "$MQTT_CONFIG_FILE")
|
||||||
|
MQTT_CLIENTID=$(jq -r '.clientid' "$MQTT_CONFIG_FILE")
|
||||||
|
INFLUX_ENABLED=$(jq -r '.influx.enabled' "$MQTT_CONFIG_FILE")
|
||||||
|
|
||||||
pushMQTTData () {
|
pushMQTTData () {
|
||||||
MQTT_SERVER=`cat /etc/inverter/mqtt.json | jq '.server' -r`
|
# Usa variabili già caricate invece di rileggere il file ogni volta
|
||||||
MQTT_PORT=`cat /etc/inverter/mqtt.json | jq '.port' -r`
|
|
||||||
MQTT_TOPIC=`cat /etc/inverter/mqtt.json | jq '.topic' -r`
|
|
||||||
MQTT_DEVICENAME=`cat /etc/inverter/mqtt.json | jq '.devicename' -r`
|
|
||||||
MQTT_USERNAME=`cat /etc/inverter/mqtt.json | jq '.username' -r`
|
|
||||||
MQTT_PASSWORD=`cat /etc/inverter/mqtt.json | jq '.password' -r`
|
|
||||||
MQTT_CLIENTID=`cat /etc/inverter/mqtt.json | jq '.clientid' -r`
|
|
||||||
|
|
||||||
mosquitto_pub \
|
mosquitto_pub \
|
||||||
-h $MQTT_SERVER \
|
-h "$MQTT_SERVER" \
|
||||||
-p $MQTT_PORT \
|
-p "$MQTT_PORT" \
|
||||||
-u "$MQTT_USERNAME" \
|
-u "$MQTT_USERNAME" \
|
||||||
-P "$MQTT_PASSWORD" \
|
-P "$MQTT_PASSWORD" \
|
||||||
-i $MQTT_CLIENTID \
|
-i "$MQTT_CLIENTID" \
|
||||||
-t "$MQTT_TOPIC/sensor/"$MQTT_DEVICENAME"_$1" \
|
-t "$MQTT_TOPIC/sensor/${MQTT_DEVICENAME}_$1" \
|
||||||
-m "$2"
|
-m "$2" \
|
||||||
|
2>/dev/null
|
||||||
|
|
||||||
if [[ $INFLUX_ENABLED == "true" ]] ; then
|
if [[ $INFLUX_ENABLED == "true" ]] ; then
|
||||||
pushInfluxData $1 $2
|
pushInfluxData "$1" "$2"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
pushInfluxData () {
|
pushInfluxData () {
|
||||||
INFLUX_HOST=`cat /etc/inverter/mqtt.json | jq '.influx.host' -r`
|
# Carica configurazione InfluxDB solo se necessario (lazy loading)
|
||||||
INFLUX_USERNAME=`cat /etc/inverter/mqtt.json | jq '.influx.username' -r`
|
local INFLUX_HOST=$(jq -r '.influx.host' "$MQTT_CONFIG_FILE")
|
||||||
INFLUX_PASSWORD=`cat /etc/inverter/mqtt.json | jq '.influx.password' -r`
|
local INFLUX_USERNAME=$(jq -r '.influx.username' "$MQTT_CONFIG_FILE")
|
||||||
INFLUX_DEVICE=`cat /etc/inverter/mqtt.json | jq '.influx.device' -r`
|
local INFLUX_PASSWORD=$(jq -r '.influx.password' "$MQTT_CONFIG_FILE")
|
||||||
INFLUX_PREFIX=`cat /etc/inverter/mqtt.json | jq '.influx.prefix' -r`
|
local INFLUX_DEVICE=$(jq -r '.influx.device' "$MQTT_CONFIG_FILE")
|
||||||
INFLUX_DATABASE=`cat /etc/inverter/mqtt.json | jq '.influx.database' -r`
|
local INFLUX_PREFIX=$(jq -r '.influx.prefix' "$MQTT_CONFIG_FILE")
|
||||||
INFLUX_MEASUREMENT_NAME=`cat /etc/inverter/mqtt.json | jq '.influx.namingMap.'$1'' -r`
|
local INFLUX_DATABASE=$(jq -r '.influx.database' "$MQTT_CONFIG_FILE")
|
||||||
|
local INFLUX_MEASUREMENT_NAME=$(jq -r ".influx.namingMap.$1" "$MQTT_CONFIG_FILE")
|
||||||
|
|
||||||
curl -i -XPOST "$INFLUX_HOST/write?db=$INFLUX_DATABASE&precision=s" -u "$INFLUX_USERNAME:$INFLUX_PASSWORD" --data-binary "$INFLUX_PREFIX,device=$INFLUX_DEVICE $INFLUX_MEASUREMENT_NAME=$2"
|
curl -s -XPOST "$INFLUX_HOST/write?db=$INFLUX_DATABASE&precision=s" \
|
||||||
|
-u "$INFLUX_USERNAME:$INFLUX_PASSWORD" \
|
||||||
|
--data-binary "$INFLUX_PREFIX,device=$INFLUX_DEVICE $INFLUX_MEASUREMENT_NAME=$2" \
|
||||||
|
> /dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
INVERTER_DATA=`timeout 10 /opt/inverter-cli/bin/inverter_poller -1`
|
# Esegui polling inverter con timeout per evitare hang
|
||||||
|
INVERTER_DATA=$(timeout 10 /opt/inverter-cli/bin/inverter_poller -1 2>/dev/null)
|
||||||
|
|
||||||
#####################################################################################
|
#####################################################################################
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user