From 519b6ef703e7793805360f9fd9cfc48cf5c0dba8 Mon Sep 17 00:00:00 2001 From: Pi Developer Date: Sat, 31 Jan 2026 18:19:06 +0100 Subject: [PATCH] feat: Supporto multi-inverter nello stesso container - 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 --- docker-compose.yml | 5 + sources/inverter-mqtt/mqtt-push.sh | 144 ++++++++++++++++++----------- 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a91d28d..6132cfa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,11 @@ services: # Device configuration - INVERTER_DEVICE=/dev/ttyUSB0 + # Multi-inverter support: separare device con ':' + # Esempio: INVERTER_DEVICES=/dev/ttyUSB0:/dev/ttyUSB1 + # Se non specificato, usa INVERTER_DEVICE sopra + # - INVERTER_DEVICES=/dev/ttyUSB0:/dev/ttyUSB1 + # MQTT Broker configuration (questi valori sovrascrivono mqtt.json all'avvio) - MQTT_SERVER=192.168.1.37 - MQTT_PORT=1883 diff --git a/sources/inverter-mqtt/mqtt-push.sh b/sources/inverter-mqtt/mqtt-push.sh index 90e5635..5f42bb9 100755 --- a/sources/inverter-mqtt/mqtt-push.sh +++ b/sources/inverter-mqtt/mqtt-push.sh @@ -5,149 +5,189 @@ 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_BASE_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") +# Supporto multi-inverter: leggi lista device da ENV o usa default +# Formato ENV: INVERTER_DEVICES="/dev/ttyUSB0:/dev/ttyUSB1" (separati da :) +if [ ! -z "$INVERTER_DEVICES" ]; then + IFS=':' read -ra DEVICE_ARRAY <<< "$INVERTER_DEVICES" +else + # Fallback: usa device da inverter.conf + DEFAULT_DEVICE=$(grep "^device=" /etc/inverter/inverter.conf | cut -d= -f2) + DEVICE_ARRAY=("${DEFAULT_DEVICE:-/dev/ttyUSB0}") +fi + pushMQTTData () { - # Usa variabili giĆ  caricate invece di rileggere il file ogni volta + # $1 = devicename, $2 = metric name, $3 = value + local device_name="$1" + local metric_name="$2" + local metric_value="$3" + mosquitto_pub \ -h "$MQTT_SERVER" \ -p "$MQTT_PORT" \ -u "$MQTT_USERNAME" \ -P "$MQTT_PASSWORD" \ - -i "$MQTT_CLIENTID" \ - -t "$MQTT_TOPIC/sensor/${MQTT_DEVICENAME}_$1" \ - -m "$2" \ + -i "${MQTT_CLIENTID}_${device_name}" \ + -t "$MQTT_TOPIC/sensor/${device_name}_${metric_name}" \ + -m "$metric_value" \ 2>/dev/null if [[ $INFLUX_ENABLED == "true" ]] ; then - pushInfluxData "$1" "$2" + pushInfluxData "$device_name" "$metric_name" "$metric_value" fi } pushInfluxData () { - # Carica configurazione InfluxDB solo se necessario (lazy loading) + # $1 = devicename, $2 = metric name, $3 = value + local device_name="$1" + local metric_name="$2" + local metric_value="$3" + local INFLUX_HOST=$(jq -r '.influx.host' "$MQTT_CONFIG_FILE") local INFLUX_USERNAME=$(jq -r '.influx.username' "$MQTT_CONFIG_FILE") local INFLUX_PASSWORD=$(jq -r '.influx.password' "$MQTT_CONFIG_FILE") - local INFLUX_DEVICE=$(jq -r '.influx.device' "$MQTT_CONFIG_FILE") local INFLUX_PREFIX=$(jq -r '.influx.prefix' "$MQTT_CONFIG_FILE") local INFLUX_DATABASE=$(jq -r '.influx.database' "$MQTT_CONFIG_FILE") - local INFLUX_MEASUREMENT_NAME=$(jq -r ".influx.namingMap.$1" "$MQTT_CONFIG_FILE") + local INFLUX_MEASUREMENT_NAME=$(jq -r ".influx.namingMap.${metric_name}" "$MQTT_CONFIG_FILE") 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" \ + --data-binary "$INFLUX_PREFIX,device=$device_name $INFLUX_MEASUREMENT_NAME=$metric_value" \ > /dev/null 2>&1 } -# Esegui polling inverter con timeout per evitare hang -INVERTER_DATA=$(timeout 10 /opt/inverter-cli/bin/inverter_poller -1 2>/dev/null) - -##################################################################################### - -Inverter_mode=`echo $INVERTER_DATA | jq '.Inverter_mode' -r` - - # 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown - -[ ! -z "$Inverter_mode" ] && pushMQTTData "Inverter_mode" "$Inverter_mode" +# Funzione per processare un singolo inverter +process_inverter() { + local device="$1" + local device_index="$2" + + # Determina nome device univoco (voltronic, voltronic2, voltronic3, ecc.) + local devicename="${MQTT_BASE_DEVICENAME}" + if [ $device_index -gt 0 ]; then + devicename="${MQTT_BASE_DEVICENAME}$((device_index + 1))" + fi + + # Crea config temporaneo con device specifico + local temp_conf="/tmp/inverter_${device_index}.conf" + cp /etc/inverter/inverter.conf "$temp_conf" + sed -i "s|^device=.*|device=$device|g" "$temp_conf" + + # Esegui polling per questo inverter specifico + INVERTER_DATA=$(/opt/inverter-cli/bin/inverter_poller -1 2>&1 | grep -v '^\[POLL\]') + + # Verifica dati validi + if [ -z "$INVERTER_DATA" ] || ! echo "$INVERTER_DATA" | jq -e . >/dev/null 2>&1; then + return 0 # Skip questo inverter, retry al prossimo ciclo + fi + + # Pubblica tutti i parametri per questo inverter + Inverter_mode=`echo $INVERTER_DATA | jq '.Inverter_mode' -r` + [ ! -z "$Inverter_mode" ] && pushMQTTData "$devicename" "$devicename" "Inverter_mode" "$Inverter_mode" AC_grid_voltage=`echo $INVERTER_DATA | jq '.AC_grid_voltage' -r` -[ ! -z "$AC_grid_voltage" ] && pushMQTTData "AC_grid_voltage" "$AC_grid_voltage" +[ ! -z "$AC_grid_voltage" ] && pushMQTTData "$devicename" "AC_grid_voltage" "$AC_grid_voltage" AC_grid_frequency=`echo $INVERTER_DATA | jq '.AC_grid_frequency' -r` -[ ! -z "$AC_grid_frequency" ] && pushMQTTData "AC_grid_frequency" "$AC_grid_frequency" +[ ! -z "$AC_grid_frequency" ] && pushMQTTData "$devicename" "AC_grid_frequency" "$AC_grid_frequency" AC_out_voltage=`echo $INVERTER_DATA | jq '.AC_out_voltage' -r` -[ ! -z "$AC_out_voltage" ] && pushMQTTData "AC_out_voltage" "$AC_out_voltage" +[ ! -z "$AC_out_voltage" ] && pushMQTTData "$devicename" "AC_out_voltage" "$AC_out_voltage" AC_out_frequency=`echo $INVERTER_DATA | jq '.AC_out_frequency' -r` -[ ! -z "$AC_out_frequency" ] && pushMQTTData "AC_out_frequency" "$AC_out_frequency" +[ ! -z "$AC_out_frequency" ] && pushMQTTData "$devicename" "AC_out_frequency" "$AC_out_frequency" PV_in_voltage=`echo $INVERTER_DATA | jq '.PV_in_voltage' -r` -[ ! -z "$PV_in_voltage" ] && pushMQTTData "PV_in_voltage" "$PV_in_voltage" +[ ! -z "$PV_in_voltage" ] && pushMQTTData "$devicename" "PV_in_voltage" "$PV_in_voltage" PV_in_current=`echo $INVERTER_DATA | jq '.PV_in_current' -r` -[ ! -z "$PV_in_current" ] && pushMQTTData "PV_in_current" "$PV_in_current" +[ ! -z "$PV_in_current" ] && pushMQTTData "$devicename" "PV_in_current" "$PV_in_current" PV_in_watts=`echo $INVERTER_DATA | jq '.PV_in_watts' -r` -[ ! -z "$PV_in_watts" ] && pushMQTTData "PV_in_watts" "$PV_in_watts" +[ ! -z "$PV_in_watts" ] && pushMQTTData "$devicename" "PV_in_watts" "$PV_in_watts" PV_in_watthour=`echo $INVERTER_DATA | jq '.PV_in_watthour' -r` -[ ! -z "$PV_in_watthour" ] && pushMQTTData "PV_in_watthour" "$PV_in_watthour" +[ ! -z "$PV_in_watthour" ] && pushMQTTData "$devicename" "PV_in_watthour" "$PV_in_watthour" SCC_voltage=`echo $INVERTER_DATA | jq '.SCC_voltage' -r` -[ ! -z "$SCC_voltage" ] && pushMQTTData "SCC_voltage" "$SCC_voltage" +[ ! -z "$SCC_voltage" ] && pushMQTTData "$devicename" "SCC_voltage" "$SCC_voltage" Load_pct=`echo $INVERTER_DATA | jq '.Load_pct' -r` -[ ! -z "$Load_pct" ] && pushMQTTData "Load_pct" "$Load_pct" +[ ! -z "$Load_pct" ] && pushMQTTData "$devicename" "Load_pct" "$Load_pct" Load_watt=`echo $INVERTER_DATA | jq '.Load_watt' -r` -[ ! -z "$Load_watt" ] && pushMQTTData "Load_watt" "$Load_watt" +[ ! -z "$Load_watt" ] && pushMQTTData "$devicename" "Load_watt" "$Load_watt" Load_watthour=`echo $INVERTER_DATA | jq '.Load_watthour' -r` -[ ! -z "$Load_watthour" ] && pushMQTTData "Load_watthour" "$Load_watthour" +[ ! -z "$Load_watthour" ] && pushMQTTData "$devicename" "Load_watthour" "$Load_watthour" Load_va=`echo $INVERTER_DATA | jq '.Load_va' -r` -[ ! -z "$Load_va" ] && pushMQTTData "Load_va" "$Load_va" +[ ! -z "$Load_va" ] && pushMQTTData "$devicename" "Load_va" "$Load_va" Bus_voltage=`echo $INVERTER_DATA | jq '.Bus_voltage' -r` -[ ! -z "$Bus_voltage" ] && pushMQTTData "Bus_voltage" "$Bus_voltage" +[ ! -z "$Bus_voltage" ] && pushMQTTData "$devicename" "Bus_voltage" "$Bus_voltage" Heatsink_temperature=`echo $INVERTER_DATA | jq '.Heatsink_temperature' -r` -[ ! -z "$Heatsink_temperature" ] && pushMQTTData "Heatsink_temperature" "$Heatsink_temperature" +[ ! -z "$Heatsink_temperature" ] && pushMQTTData "$devicename" "Heatsink_temperature" "$Heatsink_temperature" Battery_capacity=`echo $INVERTER_DATA | jq '.Battery_capacity' -r` -[ ! -z "$Battery_capacity" ] && pushMQTTData "Battery_capacity" "$Battery_capacity" +[ ! -z "$Battery_capacity" ] && pushMQTTData "$devicename" "Battery_capacity" "$Battery_capacity" Battery_voltage=`echo $INVERTER_DATA | jq '.Battery_voltage' -r` -[ ! -z "$Battery_voltage" ] && pushMQTTData "Battery_voltage" "$Battery_voltage" +[ ! -z "$Battery_voltage" ] && pushMQTTData "$devicename" "Battery_voltage" "$Battery_voltage" Battery_charge_current=`echo $INVERTER_DATA | jq '.Battery_charge_current' -r` -[ ! -z "$Battery_charge_current" ] && pushMQTTData "Battery_charge_current" "$Battery_charge_current" +[ ! -z "$Battery_charge_current" ] && pushMQTTData "$devicename" "Battery_charge_current" "$Battery_charge_current" Battery_discharge_current=`echo $INVERTER_DATA | jq '.Battery_discharge_current' -r` -[ ! -z "$Battery_discharge_current" ] && pushMQTTData "Battery_discharge_current" "$Battery_discharge_current" +[ ! -z "$Battery_discharge_current" ] && pushMQTTData "$devicename" "Battery_discharge_current" "$Battery_discharge_current" Load_status_on=`echo $INVERTER_DATA | jq '.Load_status_on' -r` -[ ! -z "$Load_status_on" ] && pushMQTTData "Load_status_on" "$Load_status_on" +[ ! -z "$Load_status_on" ] && pushMQTTData "$devicename" "Load_status_on" "$Load_status_on" SCC_charge_on=`echo $INVERTER_DATA | jq '.SCC_charge_on' -r` -[ ! -z "$SCC_charge_on" ] && pushMQTTData "SCC_charge_on" "$SCC_charge_on" +[ ! -z "$SCC_charge_on" ] && pushMQTTData "$devicename" "SCC_charge_on" "$SCC_charge_on" AC_charge_on=`echo $INVERTER_DATA | jq '.AC_charge_on' -r` -[ ! -z "$AC_charge_on" ] && pushMQTTData "AC_charge_on" "$AC_charge_on" +[ ! -z "$AC_charge_on" ] && pushMQTTData "$devicename" "AC_charge_on" "$AC_charge_on" Battery_recharge_voltage=`echo $INVERTER_DATA | jq '.Battery_recharge_voltage' -r` -[ ! -z "$Battery_recharge_voltage" ] && pushMQTTData "Battery_recharge_voltage" "$Battery_recharge_voltage" +[ ! -z "$Battery_recharge_voltage" ] && pushMQTTData "$devicename" "Battery_recharge_voltage" "$Battery_recharge_voltage" Battery_under_voltage=`echo $INVERTER_DATA | jq '.Battery_under_voltage' -r` -[ ! -z "$Battery_under_voltage" ] && pushMQTTData "Battery_under_voltage" "$Battery_under_voltage" +[ ! -z "$Battery_under_voltage" ] && pushMQTTData "$devicename" "Battery_under_voltage" "$Battery_under_voltage" Battery_bulk_voltage=`echo $INVERTER_DATA | jq '.Battery_bulk_voltage' -r` -[ ! -z "$Battery_bulk_voltage" ] && pushMQTTData "Battery_bulk_voltage" "$Battery_bulk_voltage" +[ ! -z "$Battery_bulk_voltage" ] && pushMQTTData "$devicename" "Battery_bulk_voltage" "$Battery_bulk_voltage" Battery_float_voltage=`echo $INVERTER_DATA | jq '.Battery_float_voltage' -r` -[ ! -z "$Battery_float_voltage" ] && pushMQTTData "Battery_float_voltage" "$Battery_float_voltage" +[ ! -z "$Battery_float_voltage" ] && pushMQTTData "$devicename" "Battery_float_voltage" "$Battery_float_voltage" Max_grid_charge_current=`echo $INVERTER_DATA | jq '.Max_grid_charge_current' -r` -[ ! -z "$Max_grid_charge_current" ] && pushMQTTData "Max_grid_charge_current" "$Max_grid_charge_current" +[ ! -z "$Max_grid_charge_current" ] && pushMQTTData "$devicename" "Max_grid_charge_current" "$Max_grid_charge_current" Max_charge_current=`echo $INVERTER_DATA | jq '.Max_charge_current' -r` -[ ! -z "$Max_charge_current" ] && pushMQTTData "Max_charge_current" "$Max_charge_current" +[ ! -z "$Max_charge_current" ] && pushMQTTData "$devicename" "Max_charge_current" "$Max_charge_current" Out_source_priority=`echo $INVERTER_DATA | jq '.Out_source_priority' -r` -[ ! -z "$Out_source_priority" ] && pushMQTTData "Out_source_priority" "$Out_source_priority" +[ ! -z "$Out_source_priority" ] && pushMQTTData "$devicename" "Out_source_priority" "$Out_source_priority" Charger_source_priority=`echo $INVERTER_DATA | jq '.Charger_source_priority' -r` -[ ! -z "$Charger_source_priority" ] && pushMQTTData "Charger_source_priority" "$Charger_source_priority" +[ ! -z "$Charger_source_priority" ] && pushMQTTData "$devicename" "Charger_source_priority" "$Charger_source_priority" Battery_redischarge_voltage=`echo $INVERTER_DATA | jq '.Battery_redischarge_voltage' -r` -[ ! -z "$Battery_redischarge_voltage" ] && pushMQTTData "Battery_redischarge_voltage" "$Battery_redischarge_voltage" +[ ! -z "$Battery_redischarge_voltage" ] && pushMQTTData "$devicename" "Battery_redischarge_voltage" "$Battery_redischarge_voltage" Warnings=`echo $INVERTER_DATA | jq '.Warnings' -r` -[ ! -z "$Warnings" ] && pushMQTTData "Warnings" "$Warnings" +[ ! -z "$Warnings" ] && pushMQTTData "$devicename" "Warnings" "$Warnings" +} + +# Loop su tutti i device configurati +for i in "${!DEVICE_ARRAY[@]}"; do + process_inverter "${DEVICE_ARRAY[$i]}" "$i" +done