|
1 | 1 | # |
2 | 2 | # fan2go.nix |
3 | 3 | # |
| 4 | +# Not controlling the Radeon Pro W5700, because lact is doing this |
| 5 | +# The config controls the corsair fan1 based on the temperatur of the Radeon Pro VII/MI50 |
| 6 | +# |
4 | 7 | # sudo systemctl status fan2go |
| 8 | +# sudo journalctl -u fan2go --follow |
5 | 9 | # sudo ls /var/lib/fan2go |
6 | 10 | # |
| 11 | +# CLEAN IMPLEMENTATION: |
| 12 | +# 1. setPwm: Converts 0-255 PWM to 0-100% for liquidctl |
| 13 | +# 2. getPwm: Uses pure bash string manipulation to extract fan speed and convert to PWM (0-255) |
| 14 | +# 3. getRpm: Uses pure bash string manipulation to extract RPM value for fan2go monitoring |
| 15 | +# 4. No external tools (grep, awk, jq, sed) - pure bash string operations |
| 16 | +# 5. Bash variables escaped with \$ to prevent Nix interpolation |
| 17 | +# 6. Uses bash parameter expansion: ${var#pattern} and ${var%%pattern} |
| 18 | +# 7. No temporary files or delays needed since fan2go is the only liquidctl user |
| 19 | +# |
7 | 20 | # See also: https://github.com/arnarg/config/blob/8de65cf5f1649a4fe6893102120ede4363de9bfa/hosts/terra/fan2go.nix |
8 | 21 | # |
| 22 | +# |
| 23 | +# [das@l:~/nixos/desktop/l]$ sudo liquidctl status |
| 24 | +# [sudo] password for das: |
| 25 | +# Corsair Commander Core XT (broken) |
| 26 | +# ├── Fan speed 1 1360 rpm |
| 27 | +# ├── Fan speed 2 0 rpm |
| 28 | +# ├── Fan speed 3 0 rpm |
| 29 | +# ├── Fan speed 4 0 rpm |
| 30 | +# ├── Fan speed 5 0 rpm |
| 31 | +# └── Fan speed 6 0 rpm |
| 32 | +# |
9 | 33 | { |
10 | 34 | lib, |
11 | 35 | config, |
12 | 36 | pkgs, |
13 | 37 | ... |
14 | 38 | }: |
15 | 39 | let |
| 40 | + |
16 | 41 | cfg = config.hardware.fan2go; |
17 | 42 |
|
| 43 | + # Create the bash scripts for fan control |
| 44 | + setPwmScript = pkgs.writeText "setPwm.bash" '' |
| 45 | + #!${pkgs.bash}/bin/bash |
| 46 | + # Convert fan2go PWM (0-255) to liquidctl percentage (0-100) |
| 47 | + percent=$((%pwm% * 100 / 255)) |
| 48 | + ${pkgs.liquidctl}/bin/liquidctl set fan1 speed $percent |
| 49 | + ''; |
| 50 | + |
| 51 | + getPwmScript = pkgs.writeText "getPwm.bash" '' |
| 52 | + #!${pkgs.bash}/bin/bash |
| 53 | + # Get current fan RPM and convert to PWM value |
| 54 | + output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) |
| 55 | + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then |
| 56 | + rpm=${BASH_REMATCH[1]} |
| 57 | + echo $((rpm * 255 / 2000)) |
| 58 | + else |
| 59 | + echo 0 |
| 60 | + fi |
| 61 | + ''; |
| 62 | + |
| 63 | + getRpmScript = pkgs.writeText "getRpm.bash" '' |
| 64 | + #!${pkgs.bash}/bin/bash |
| 65 | + # Get current fan RPM value |
| 66 | + output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) |
| 67 | + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then |
| 68 | + rpm=${BASH_REMATCH[1]} |
| 69 | + echo $rpm |
| 70 | + else |
| 71 | + echo 0 |
| 72 | + fi |
| 73 | + ''; |
| 74 | + |
| 75 | + # Create a shellcheck validation script |
| 76 | + shellcheckScript = pkgs.writeText "check-fan-scripts.sh" '' |
| 77 | + #!${pkgs.bash}/bin/bash |
| 78 | + # Shellcheck validation for fan control scripts |
| 79 | + echo "Running shellcheck on fan control scripts..." |
| 80 | +
|
| 81 | + echo "Checking setPwm script..." |
| 82 | + ${pkgs.shellcheck}/bin/shellcheck ${setPwmScript} || exit 1 |
| 83 | +
|
| 84 | + echo "Checking getPwm script..." |
| 85 | + ${pkgs.shellcheck}/bin/shellcheck ${getPwmScript} || exit 1 |
| 86 | +
|
| 87 | + echo "Checking getRpm script..." |
| 88 | + ${pkgs.shellcheck}/bin/shellcheck ${getRpmScript} || exit 1 |
| 89 | +
|
| 90 | + echo "All scripts passed shellcheck validation!" |
| 91 | + ''; |
| 92 | + |
18 | 93 | fan2goConfig = pkgs.writeText "fan2go.yaml" '' |
19 | 94 | # |
20 | 95 | # fan2go.yaml |
|
32 | 107 | # We use a shell command to convert the 0-255 PWM value from fan2go |
33 | 108 | # into a 0-100 percentage for liquidctl. |
34 | 109 | setPwm: |
35 | | - exec: "/run/current-system/sw/bin/bash" |
36 | | - args: ["-c", "percent=$((%pwm% * 100 / 255)); /run/current-system/sw/bin/liquidctl set fan1 speed $percent"] |
37 | | - # The `getPwm` command is optional but good practice. |
38 | | - # It should return a value from 0-255. |
| 110 | + exec: "${setPwmScript}" |
| 111 | + # The `getPwm` command should return the current PWM value. |
| 112 | + # Since liquidctl doesn't provide PWM directly, we convert from the RPM value. |
39 | 113 | getPwm: |
40 | | - exec: "/run/current-system/sw/bin/bash" |
41 | | - args: ["-c", "percent=$(/run/current-system/sw/bin/liquidctl status --json | ${pkgs.jq}/bin/jq '.[0].status[] | select(.key == \"Fan speed 1\").value | tonumber'); echo $((percent * 255 / 100))"] |
| 114 | + exec: "${getPwmScript}" |
| 115 | + # The `getRpm` command gets the current RPM value from liquidctl. |
| 116 | + # This helps fan2go understand the fan's current state. |
| 117 | + getRpm: |
| 118 | + exec: "${getRpmScript}" |
42 | 119 | # Fan speed is a percentage for liquidctl |
43 | | - min: 20 |
| 120 | + min: 10 |
44 | 121 | max: 100 |
45 | 122 | ## Ensures the fan never fully stops, maintaining minimum airflow. |
46 | 123 | #neverStop: true |
47 | 124 | # The curve ID that should be used to determine the speed of this fan. |
48 | 125 | curve: gpu_cooling_curve |
49 | 126 |
|
| 127 | + # # |
| 128 | + # # Define the fan for the Radeon Pro W5700 (amdgpu-pci-06300). |
| 129 | + # # This GPU has its own controllable fan via hwmon. |
| 130 | + # - id: gpu_w5700_fan |
| 131 | + # hwmon: |
| 132 | + # # From `fan2go detect`, this is the platform for the W5700. |
| 133 | + # platform: amdgpu-pci-06300 |
| 134 | + # # The channel for the fan's RPM sensor. |
| 135 | + # rpmChannel: 1 |
| 136 | + # # The PWM channel that controls this fan's speed. |
| 137 | + # pwmChannel: 1 |
| 138 | + # neverStop: true |
| 139 | + # curve: gpu_w5700_curve |
| 140 | +
|
50 | 141 | sensors: |
51 | 142 | # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50. |
52 | 143 | # From `fan2go detect`, this is platform `amdgpu-pci-04400`. |
|
57 | 148 | # Use the junction temperature (temp2_input) as it's a good indicator of core heat. |
58 | 149 | index: 2 |
59 | 150 |
|
| 151 | + # # |
| 152 | + # # Define the temperature sensor for the Radeon Pro W5700. |
| 153 | + # - id: gpu_w5700_temp |
| 154 | + # hwmon: |
| 155 | + # # From `fan2go detect`, this is the platform for the W5700. |
| 156 | + # platform: amdgpu-pci-06300 |
| 157 | + # # Use the junction temperature (temp2_input). |
| 158 | + # index: 2 |
| 159 | +
|
60 | 160 | curves: |
61 | 161 | # Link the GPU temperature to the case fan speed. |
62 | 162 | - id: gpu_cooling_curve |
|
73 | 173 | - [70, 80] # At 70°C, run fan at 80% |
74 | 174 | - [80, 100] # At 80°C and above, run fan at 100% |
75 | 175 |
|
| 176 | + # # |
| 177 | + # # Define the curve for the Radeon Pro W5700's own fan. |
| 178 | + # - id: gpu_w5700_curve |
| 179 | + # linear: |
| 180 | + # # The sensor ID to use as a temperature input for this curve. |
| 181 | + # sensor: gpu_w5700_temp |
| 182 | + # # Define the temperature-to-PWM-value mapping. |
| 183 | + # # Temps are in Celsius, output is a PWM value (0-255). |
| 184 | + # points: |
| 185 | + # - [45, 51] # At 45°C, run fan at ~20% (51/255) |
| 186 | + # - [55, 102] # At 55°C, run fan at 40% |
| 187 | + # - [65, 153] # At 65°C, run fan at 60% |
| 188 | + # - [75, 204] # At 75°C, run fan at 80% |
| 189 | + # - [85, 255] # At 85°C and above, run fan at 100% |
| 190 | +
|
76 | 191 | statistics: |
77 | | - # Whether to enable the prometheus exporter or not |
78 | 192 | enabled: true |
79 | | - # The port to expose the exporter on |
80 | 193 | port: 9900 |
81 | 194 | ''; |
82 | 195 | in |
|
98 | 211 | after = [ "lm_sensors.service" ]; |
99 | 212 |
|
100 | 213 | serviceConfig = { |
| 214 | + ExecStartPre = "${shellcheckScript}"; |
101 | 215 | ExecStart = lib.concatStringsSep " " [ |
102 | 216 | "${pkgs.fan2go}/bin/fan2go" |
103 | 217 | "-c" |
104 | 218 | "${fan2goConfig}" |
105 | 219 | "--no-style" |
106 | 220 | ]; |
| 221 | + |
| 222 | + MemoryHigh = "48M"; |
| 223 | + MemoryMax = "64M"; |
| 224 | + CPUQuota = "50%"; |
| 225 | + #RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; |
| 226 | + #Delegate = false; |
| 227 | + |
107 | 228 | LimitNOFILE = 8192; |
| 229 | + |
108 | 230 | }; |
109 | 231 | }; |
110 | 232 | }; |
|
0 commit comments