296 lines
9.7 KiB
Bash
Executable File
296 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
||
export TERM=xterm
|
||
|
||
echo "=== Voltronic MQTT Bridge Starting ==="
|
||
echo "Version: 2.0 with Auto-Discovery"
|
||
echo ""
|
||
|
||
# Configuration paths
|
||
CONF_FILE="/etc/inverter/inverter.conf"
|
||
MQTT_CONF="/etc/inverter/mqtt.json"
|
||
DISCOVERY_FLAG="/etc/inverter/.discovery_done"
|
||
TEMP_CONF="/tmp/inverter_discovered.conf"
|
||
|
||
# Ensure config files exist (copy defaults if missing due to empty volume mount)
|
||
if [ ! -f "$CONF_FILE" ]; then
|
||
echo "⚠ inverter.conf not found, creating default..."
|
||
cat > "$CONF_FILE" << 'EOF'
|
||
# Basic configuration options for the actual inverter polling process...
|
||
device=/dev/ttyUSB0
|
||
run_interval=120
|
||
amperage_factor=1.0
|
||
watt_factor=1.01
|
||
qpiri=103
|
||
qpiws=40
|
||
qmod=5
|
||
qpigs=110
|
||
EOF
|
||
fi
|
||
|
||
if [ ! -f "$MQTT_CONF" ]; then
|
||
echo "⚠ mqtt.json not found, creating default..."
|
||
cat > "$MQTT_CONF" << 'EOF'
|
||
{
|
||
"server": "192.168.1.37",
|
||
"port": "1883",
|
||
"topic": "homeassistant",
|
||
"devicename": "voltronic",
|
||
"username": "",
|
||
"password": "",
|
||
"clientid": "voltronic_default",
|
||
"influx": {
|
||
"enabled": "false"
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
# Environment variables with defaults
|
||
INVERTER_DEVICE="${INVERTER_DEVICE:-/dev/ttyUSB0}"
|
||
FORCE_DISCOVERY="${FORCE_DISCOVERY:-false}"
|
||
SKIP_DISCOVERY="${SKIP_DISCOVERY:-false}"
|
||
MQTT_SERVER="${MQTT_SERVER:-192.168.1.37}"
|
||
MQTT_PORT="${MQTT_PORT:-1883}"
|
||
MQTT_TOPIC="${MQTT_TOPIC:-homeassistant}"
|
||
MQTT_DEVICENAME="${MQTT_DEVICENAME:-voltronic}"
|
||
MQTT_USERNAME="${MQTT_USERNAME:-}"
|
||
MQTT_PASSWORD="${MQTT_PASSWORD:-}"
|
||
|
||
echo "Configuration:"
|
||
echo " Device: $INVERTER_DEVICE"
|
||
echo " Force Discovery: $FORCE_DISCOVERY"
|
||
echo " Skip Discovery: $SKIP_DISCOVERY"
|
||
echo " MQTT Server: $MQTT_SERVER:$MQTT_PORT"
|
||
echo " MQTT Topic: $MQTT_TOPIC"
|
||
echo " MQTT Device: $MQTT_DEVICENAME"
|
||
echo ""
|
||
|
||
# Function to update MQTT configuration
|
||
update_mqtt_config() {
|
||
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..."
|
||
|
||
# Backup original
|
||
cp $mqtt_conf ${mqtt_conf}.backup 2>/dev/null || true
|
||
|
||
# Update MQTT settings using jq
|
||
jq --arg server "$MQTT_SERVER" \
|
||
--arg port "$MQTT_PORT" \
|
||
--arg topic "$MQTT_TOPIC" \
|
||
--arg devicename "$MQTT_DEVICENAME" \
|
||
--arg username "$MQTT_USERNAME" \
|
||
--arg password "$MQTT_PASSWORD" \
|
||
'.server = $server | .port = $port | .topic = $topic | .devicename = $devicename | .username = $username | .password = $password' \
|
||
$mqtt_conf > ${mqtt_conf}.tmp && mv ${mqtt_conf}.tmp $mqtt_conf
|
||
|
||
echo "✓ MQTT configuration updated"
|
||
echo " Server: $MQTT_SERVER:$MQTT_PORT"
|
||
echo " Topic: $MQTT_TOPIC/sensor/$MQTT_DEVICENAME"
|
||
[ ! -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 ""
|
||
}
|
||
|
||
# Update MQTT config from ENV on startup
|
||
update_mqtt_config
|
||
|
||
# Function to update config file with discovered values
|
||
update_config_with_discovery() {
|
||
local qmod=$1
|
||
local qpigs=$2
|
||
local qpiri=$3
|
||
local qpiws=$4
|
||
|
||
echo "Updating configuration with discovered values..."
|
||
|
||
# Backup original config
|
||
cp $CONF_FILE ${CONF_FILE}.backup
|
||
|
||
# Update device
|
||
sed -i "s|^device=.*|device=$INVERTER_DEVICE|g" $CONF_FILE
|
||
|
||
# Update buffer sizes
|
||
sed -i "s/^qmod=.*/qmod=$qmod/g" $CONF_FILE
|
||
sed -i "s/^qpigs=.*/qpigs=$qpigs/g" $CONF_FILE
|
||
sed -i "s/^qpiri=.*/qpiri=$qpiri/g" $CONF_FILE
|
||
sed -i "s/^qpiws=.*/qpiws=$qpiws/g" $CONF_FILE
|
||
|
||
echo "✓ Configuration updated successfully"
|
||
echo ""
|
||
grep -E "^(device|qmod|qpigs|qpiri|qpiws)=" $CONF_FILE
|
||
}
|
||
|
||
# Function to run auto-discovery
|
||
run_discovery() {
|
||
echo "=== Running Auto-Discovery ==="
|
||
echo "This will take about 10-15 seconds..."
|
||
echo ""
|
||
|
||
# Temporarily set device in config for discovery
|
||
cp $CONF_FILE $TEMP_CONF
|
||
sed -i "s|^device=.*|device=$INVERTER_DEVICE|g" $TEMP_CONF
|
||
cp $TEMP_CONF $CONF_FILE
|
||
|
||
# Run discovery and capture output
|
||
DISCOVERY_OUTPUT=$(/opt/inverter-cli/bin/inverter_poller -d -a 2>&1)
|
||
|
||
echo "$DISCOVERY_OUTPUT"
|
||
echo ""
|
||
|
||
# Parse discovery output
|
||
QMOD=$(echo "$DISCOVERY_OUTPUT" | grep "DISCOVERY_QMOD=" | cut -d= -f2)
|
||
QPIGS=$(echo "$DISCOVERY_OUTPUT" | grep "DISCOVERY_QPIGS=" | cut -d= -f2)
|
||
QPIRI=$(echo "$DISCOVERY_OUTPUT" | grep "DISCOVERY_QPIRI=" | cut -d= -f2)
|
||
QPIWS=$(echo "$DISCOVERY_OUTPUT" | grep "DISCOVERY_QPIWS=" | cut -d= -f2)
|
||
SUCCESS=$(echo "$DISCOVERY_OUTPUT" | grep "DISCOVERY_SUCCESS=" | cut -d= -f2)
|
||
|
||
if [ "$SUCCESS" = "true" ]; then
|
||
echo "✓ Auto-discovery completed successfully!"
|
||
update_config_with_discovery $QMOD $QPIGS $QPIRI $QPIWS
|
||
|
||
# Mark discovery as done
|
||
echo "device=$INVERTER_DEVICE" > $DISCOVERY_FLAG
|
||
echo "qmod=$QMOD" >> $DISCOVERY_FLAG
|
||
echo "qpigs=$QPIGS" >> $DISCOVERY_FLAG
|
||
echo "qpiri=$QPIRI" >> $DISCOVERY_FLAG
|
||
echo "qpiws=$QPIWS" >> $DISCOVERY_FLAG
|
||
echo "timestamp=$(date -Iseconds)" >> $DISCOVERY_FLAG
|
||
|
||
echo "✓ Discovery results saved to $DISCOVERY_FLAG"
|
||
return 0
|
||
else
|
||
echo "✗ Auto-discovery failed!"
|
||
echo "Please check:"
|
||
echo " 1. Inverter is powered on"
|
||
echo " 2. Cable is properly connected"
|
||
echo " 3. Device path is correct: $INVERTER_DEVICE"
|
||
echo ""
|
||
echo "Falling back to default configuration..."
|
||
|
||
# Update device but keep default buffer sizes
|
||
sed -i "s|^device=.*|device=$INVERTER_DEVICE|g" $CONF_FILE
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Check if we need to run discovery
|
||
NEED_DISCOVERY=false
|
||
|
||
if [ "$FORCE_DISCOVERY" = "true" ]; then
|
||
echo "⚠ Force discovery requested via environment variable"
|
||
rm -f $DISCOVERY_FLAG
|
||
NEED_DISCOVERY=true
|
||
elif [ "$SKIP_DISCOVERY" = "true" ]; then
|
||
echo "⚠ Discovery skipped via environment variable"
|
||
# Just update device in config
|
||
sed -i "s|^device=.*|device=$INVERTER_DEVICE|g" $CONF_FILE
|
||
NEED_DISCOVERY=false
|
||
elif [ ! -f "$DISCOVERY_FLAG" ]; then
|
||
echo "ℹ No previous discovery found, will run auto-discovery"
|
||
NEED_DISCOVERY=true
|
||
else
|
||
# Check if device changed
|
||
SAVED_DEVICE=$(grep "^device=" $DISCOVERY_FLAG 2>/dev/null | cut -d= -f2)
|
||
if [ "$SAVED_DEVICE" != "$INVERTER_DEVICE" ]; then
|
||
echo "⚠ Device changed from $SAVED_DEVICE to $INVERTER_DEVICE"
|
||
echo " Running new discovery..."
|
||
rm -f $DISCOVERY_FLAG
|
||
NEED_DISCOVERY=true
|
||
else
|
||
echo "✓ Using previous discovery results from $DISCOVERY_FLAG"
|
||
# Restore saved config
|
||
while IFS= read -r line; do
|
||
if [[ $line =~ ^(device|qmod|qpigs|qpiri|qpiws)= ]]; then
|
||
key=$(echo "$line" | cut -d= -f1)
|
||
value=$(echo "$line" | cut -d= -f2)
|
||
sed -i "s|^$key=.*|$key=$value|g" $CONF_FILE
|
||
fi
|
||
done < "$DISCOVERY_FLAG"
|
||
|
||
echo "Current configuration:"
|
||
grep -E "^(device|qmod|qpigs|qpiri|qpiws)=" $CONF_FILE
|
||
fi
|
||
fi
|
||
|
||
# Run discovery if needed
|
||
if [ "$NEED_DISCOVERY" = "true" ]; then
|
||
if ! run_discovery; then
|
||
echo "⚠ Continuing with default configuration..."
|
||
echo " You can manually run discovery later with:"
|
||
echo " docker exec -it <container> /opt/inverter-cli/bin/inverter_poller -a"
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
echo "=== Starting MQTT Bridge Services ==="
|
||
if [ -n "$INVERTER_DEVICES" ]; then
|
||
echo "Using multi-device mode (INVERTER_DEVICES=${INVERTER_DEVICES})"
|
||
else
|
||
echo "Using parallel inverter mode (2 inverters)"
|
||
fi
|
||
echo ""
|
||
|
||
# Wait a bit for the device to be ready
|
||
sleep 2
|
||
|
||
# Always use parallel scripts
|
||
MQTT_PUSH_SCRIPT="/opt/inverter-mqtt/mqtt-push-parallel.sh"
|
||
MQTT_INIT_SCRIPT="/opt/inverter-mqtt/mqtt-init-parallel.sh"
|
||
|
||
# Remove old single-inverter discovery topics (legacy cleanup)
|
||
echo "Cleaning up legacy MQTT topics..."
|
||
MQTT_SERVER=$(jq -r '.server' /etc/inverter/mqtt.json)
|
||
MQTT_PORT=$(jq -r '.port' /etc/inverter/mqtt.json)
|
||
MQTT_USERNAME=$(jq -r '.username' /etc/inverter/mqtt.json)
|
||
MQTT_PASSWORD=$(jq -r '.password' /etc/inverter/mqtt.json)
|
||
MQTT_DEVICENAME=$(jq -r '.devicename' /etc/inverter/mqtt.json)
|
||
|
||
mosquitto_pub -h $MQTT_SERVER -p $MQTT_PORT -u "$MQTT_USERNAME" -P "$MQTT_PASSWORD" \
|
||
-t "$MQTT_TOPIC/sensor/$MQTT_DEVICENAME/config" -n -r > /dev/null 2>&1
|
||
|
||
echo "✓ Legacy topics cleaned"
|
||
|
||
# Run MQTT initialization immediately on startup
|
||
echo "Initializing MQTT discovery topics for both inverters..."
|
||
"$MQTT_INIT_SCRIPT"
|
||
echo "✓ MQTT discovery topics initialized"
|
||
|
||
# Init the mqtt server every 5 minutes (300 seconds)
|
||
# This will re-create the auto-created topics in the MQTT server if HA is restarted...
|
||
echo "Starting MQTT initialization service (every 5 minutes)..."
|
||
(
|
||
while true; do
|
||
"$MQTT_INIT_SCRIPT" > /dev/null 2>&1
|
||
sleep 300
|
||
done
|
||
) &
|
||
|
||
# Run the MQTT Subscriber process in the background (so that way we can change the configuration on the inverter from home assistant)
|
||
echo "Starting MQTT subscriber for commands..."
|
||
/opt/inverter-mqtt/mqtt-subscriber.sh > /dev/null 2>&1 &
|
||
|
||
# execute exactly every 30 seconds...
|
||
echo "Starting MQTT data push service (every 30 seconds)..."
|
||
echo ""
|
||
echo "✓ All services started successfully!"
|
||
echo " Logs will appear below..."
|
||
echo ""
|
||
|
||
while true; do
|
||
"$MQTT_PUSH_SCRIPT" > /dev/null 2>&1
|
||
sleep 30
|
||
done
|