-
Notifications
You must be signed in to change notification settings - Fork 0
/
lenovo_x3650_m5_ipmi_fan_control.sh
165 lines (147 loc) · 4.78 KB
/
lenovo_x3650_m5_ipmi_fan_control.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/bash
# Fan speed levels (hexadecimal values)
FAN_SPEED_0=0x12 # 0% fan speed
FAN_SPEED_25=0x30 # 25% fan speed
FAN_SPEED_30=0x35 # 30% fan speed
FAN_SPEED_35=0x3A # 35% fan speed
FAN_SPEED_40=0x40 # 40% fan speed
FAN_SPEED_50=0x50 # 50% fan speed
FAN_SPEED_60=0x60 # 60% fan speed
FAN_SPEED_70=0x70 # 70% fan speed
FAN_SPEED_80=0x80 # 80% fan speed
FAN_SPEED_90=0x90 # 90% fan speed
FAN_SPEED_100=0xFF # 100% fan speed (maximum)
# Temperature thresholds (degrees Celsius)
TEMP_40=40
TEMP_45=45
TEMP_50=50
TEMP_55=55
TEMP_60=60
TEMP_65=65
TEMP_70=70
TEMP_75=75
TEMP_80=80
TEMP_85=85
TEMP_90=90
TEMP_95=95
TEMP_100=100
# Temporary file for caching IPMI data
IPMI_CACHE_FILE="/tmp/ipmi_temperature_cache.txt"
# Function to fetch and cache IPMI data (overwrite cache file)
fetch_ipmi_data() {
# Overwrite the cache file (use ">" to redirect and overwrite)
ipmitool sdr type temperature > "$IPMI_CACHE_FILE"
if [[ $? -ne 0 ]]; then
return 1
fi
return 0
}
# Function to get CPU temperature by name
get_cpu_temperature() {
local label=$1
# Extract temperature from the appropriate field using awk and sed
grep -w "$label" "$IPMI_CACHE_FILE" | awk -F'|' '{print $5}' | sed 's/[^0-9.]//g'
}
# Function to determine fan speed based on temperature
calculate_fan_speed() {
local temp=$1
if (( temp < TEMP_40 )); then
echo 0 # 0% fan speed
elif (( temp < TEMP_45 )); then
echo 25 # 25% fan speed
elif (( temp < TEMP_50 )); then
echo 30 # 30% fan speed
elif (( temp < TEMP_55 )); then
echo 35 # 35% fan speed
elif (( temp < TEMP_60 )); then
echo 40 # 40% fan speed
elif (( temp < TEMP_65 )); then
echo 50 # 50% fan speed
elif (( temp < TEMP_70 )); then
echo 60 # 60% fan speed
elif (( temp < TEMP_75 )); then
echo 70 # 70% fan speed
elif (( temp < TEMP_80 )); then
echo 80 # 80% fan speed
elif (( temp < TEMP_85 )); then
echo 90 # 90% fan speed
elif (( temp < TEMP_90 )); then
echo 95 # 95% fan speed
else
echo 100 # 100% fan speed (max)
fi
}
# Function to set fan speed
set_fan_speed() {
local fan_bank=$1
local speed=$2
# Convert percentage to hexadecimal fan speed value
case $speed in
0) hex_speed=0x12 ;;
25) hex_speed=0x30 ;;
30) hex_speed=0x35 ;;
35) hex_speed=0x3A ;;
40) hex_speed=0x40 ;;
50) hex_speed=0x50 ;;
60) hex_speed=0x60 ;;
70) hex_speed=0x70 ;;
80) hex_speed=0x80 ;;
90) hex_speed=0x90 ;;
95) hex_speed=0xA0 ;;
100) hex_speed=0xFF ;;
esac
ipmitool raw 0x3a 0x07 "$fan_bank" "$hex_speed" 0x01
}
# Function to display status (simple text output)
display_status() {
local cpu1_temp=$1
local cpu2_temp=$2
local fan1_speed=$3
local fan2_speed=$4
echo "----------------------------------"
echo "Fan Control Status"
echo "----------------------------------"
echo "CPU 1 Temperature: $cpu1_temp°C"
echo "CPU 2 Temperature: $cpu2_temp°C"
echo "Fan Bank CPU 1: Speed $fan1_speed%"
echo "Fan Bank CPU 2: Speed $fan2_speed%"
echo "----------------------------------"
echo "Last updated: $(date +"%Y-%m-%d %H:%M:%S")"
echo "----------------------------------"
}
# Main loop
while true; do
# Fetch IPMI data and cache it (overwrite the file each time)
echo "Fetching IPMI data..."
fetch_ipmi_data
if [[ $? -ne 0 ]]; then
echo "Failed to fetch IPMI data. Retrying..."
sleep 10
continue
fi
# Periodically print a status message every 10 seconds to indicate the script is running
echo "Processing... (fetching temperatures and adjusting fan speeds)"
sleep 10 # Simulate waiting time for the user to see the message
# Get temperatures for both CPUs
CPU1_TEMP=$(get_cpu_temperature "CPU 1 Temp")
CPU2_TEMP=$(get_cpu_temperature "CPU 2 Temp")
# Ensure valid temperature readings
if [[ -z "$CPU1_TEMP" || -z "$CPU2_TEMP" ]]; then
echo "Failed to read CPU temperatures. Retrying..."
sleep 10
continue
fi
# Calculate fan speeds for each bank in percentage
FAN_SPEED_CPU1=$(calculate_fan_speed "$CPU1_TEMP")
FAN_SPEED_CPU2=$(calculate_fan_speed "$CPU2_TEMP")
# Apply fan speeds to respective banks
echo "Adjusting fan speeds based on temperature readings..."
set_fan_speed 0x01 "$FAN_SPEED_CPU1" # CPU1 -> Fan Bank CPU 1
set_fan_speed 0x02 "$FAN_SPEED_CPU2" # CPU2 -> Fan Bank CPU 2
# Display status
display_status "$CPU1_TEMP" "$CPU2_TEMP" "$FAN_SPEED_CPU1" "$FAN_SPEED_CPU2"
# Indicate that the script will wait for the next cycle
echo "Waiting 30 seconds before the next probe..."
# Wait before checking again
sleep 30
done