#!/bin/sh

# Dell R730xd Fan Controller # Include start-fancontrol.sh Launcher
# Uses local IPMI. No iDRAC username/password required.

FAN_NORMAL="0x14"    # 20%
FAN_WARM="0x19"      # 25%
FAN_HOT="0x1E"       # 30%

CPU_WARM=55
CPU_HOT=65
CPU_AUTO=75

INLET_WARM=30
INLET_HOT=35

EXHAUST_AUTO=50

CHECK_INTERVAL=60

CURRENT=""

log()
{
    logger "R730xd Fan Controller: $1"
}

set_manual()
{
    ipmitool raw 0x30 0x30 0x01 0x00 >/dev/null 2>&1
}

set_auto()
{
    ipmitool raw 0x30 0x30 0x01 0x01 >/dev/null 2>&1
}

set_fans()
{
    set_manual
    ipmitool raw 0x30 0x30 0x02 0xff "$1" >/dev/null 2>&1
}

get_temps()
{
    SDR="$(ipmitool sdr list 2>/dev/null)"

    INLET="$(echo "$SDR" | awk -F'|' '/Inlet Temp/ {gsub(/ /,"",$2); sub(/degreesC/,"",$2); print int($2)}')"
    EXHAUST="$(echo "$SDR" | awk -F'|' '/Exhaust Temp/ {gsub(/ /,"",$2); sub(/degreesC/,"",$2); print int($2)}')"

    CPU_MAX="$(echo "$SDR" | awk -F'|' '
        /^Temp[[:space:]]*\|/ {
            gsub(/ /,"",$2);
            sub(/degreesC/,"",$2);
            if (int($2) > max) max=int($2)
        }
        END { print max }
    ')"
}

cleanup()
{
    log "Stopping - returning fan control to Dell Auto"
    set_auto
    exit 0
}

trap cleanup INT TERM

log "Starting"

until ipmitool mc info >/dev/null 2>&1
do
    sleep 2
done

log "IPMI ready"

# Set fans immediately after boot
set_fans "$FAN_NORMAL"
CURRENT="$FAN_NORMAL"
log "Initial fan speed set to $FAN_NORMAL"

while true
do
    get_temps

    if [ -z "$CPU_MAX" ] || [ -z "$INLET" ] || [ -z "$EXHAUST" ]; then
        log "Sensor read failed - returning to Dell Auto"
        set_auto
        exit 1
    fi

    if [ "$CPU_MAX" -ge "$CPU_AUTO" ] || [ "$EXHAUST" -ge "$EXHAUST_AUTO" ]; then
        NEW="AUTO"

    elif [ "$CPU_MAX" -ge "$CPU_HOT" ] || [ "$INLET" -ge "$INLET_HOT" ]; then
        NEW="$FAN_HOT"

    elif [ "$CPU_MAX" -ge "$CPU_WARM" ] || [ "$INLET" -ge "$INLET_WARM" ]; then
        NEW="$FAN_WARM"

    else
        NEW="$FAN_NORMAL"
    fi

    if [ "$NEW" != "$CURRENT" ]; then
        log "CPU=${CPU_MAX}C Inlet=${INLET}C Exhaust=${EXHAUST}C Fan=${NEW}"

        if [ "$NEW" = "AUTO" ]; then
            set_auto
        else
            set_fans "$NEW"
        fi

        CURRENT="$NEW"
    fi

    sleep "$CHECK_INTERVAL"
done
