Skip to content

Repository files navigation

Clevo/Tongfang Fan Control

A safety-focused Linux fan-control daemon and local web dashboard for compatible Clevo/Tongfang systems.

CI Platform Python Project status

Important

Unofficial community project. This software is not affiliated with, endorsed by, sponsored by, or supported by Clevo, Tongfang, any laptop reseller, or any kernel-driver vendor. Use it at your own risk.

Fan Control provides automatic temperature curves, direct manual control, live CPU/GPU telemetry, and a responsive local dashboard. It is deliberately small, dependency-free, and bound to localhost.

Dashboard

Live fan controls, CPU and GPU telemetry, and temperature history

Custom fan curve editor and thermal safety settings

Features

  • Silent, Balanced, Performance, custom-curve, manual, and firmware-auto modes
  • Independent or linked CPU/GPU fan targets
  • Critical-temperature override that bypasses the user noise cap
  • Curve hysteresis to prevent rapid speed hunting
  • Automatic handoff to firmware when temperature data becomes unavailable
  • Live hwmon sensors with an NVIDIA nvidia-smi fallback
  • Thirty-minute CPU temperature, GPU temperature, and fan-duty history
  • Persistent configuration with atomic writes
  • Responsive dark/light dashboard and optional browser alerts
  • Serialized EC access and clean daemon/dashboard ownership handoff
  • Hardware-free demo mode for safe evaluation and UI development

Compatibility

Fan Control supports two hardware backends on Linux. It auto-detects which one is present; use --backend or FAN_CONTROL_BACKEND to override.

Requirement Details
Hardware Clevo/Tongfang-based system with a compatible EC interface
Backend tuxedo_io (ioctls on a /dev/*_io device) or clevo_acpi (sysfs)
clevo_acpi Requires clevo-acpi-dkms with fan duty attributes
Runtime Python 3.10 or newer; standard library only
Privileges Root access for EC reads and writes
Service manager systemd for the included background service
NVIDIA telemetry Optional; requires a working nvidia-smi command

The tuxedo_io backend drives duty through ioctls on a character device matching /dev/*_io. The clevo_acpi backend drives per-fan duty through plain sysfs files under /sys/class/leds/clevo-acpi::kbd_backlight/device/, and relies on that driver's kernel-side watchdog to return control to firmware auto if the controlling process stops. The sysfs interface comes from clevo-acpi-dkms (GPL-2.0-or-later); its semantics were verified against that driver and the clevo-control-panel (GPL-3.0) reference daemon.

Hardware compatibility varies by model and firmware. Start with demo mode, then verify sensor readings and fan response before enabling the service.

Safety model

Fan Control treats thermal control as a safety-critical path:

  • Duty is authored as a percentage 0-100. The tuxedo_io backend maps this onto its native raw 0-198 domain at the edge, keeping the known-safe cap of 198; values near 200 are known to behave unpredictably on affected firmware.
  • At critical_temp, both fans are commanded to 100% even when a lower noise cap is configured.
  • After three invalid temperature readings, the daemon returns control to the system firmware until valid telemetry returns.
  • On the clevo_acpi backend, the kernel-side watchdog independently releases to firmware auto if the controlling process stops renewing a manual override, so a crashed or killed daemon cannot leave a fan stuck at a stale speed.
  • The dashboard and daemon never intentionally own the EC interface at the same time.

Caution

Confirm the reported temperatures and physical fan response on your exact machine. Incorrect low-level fan control can cause overheating or hardware damage.

Installation

Clone the repository and install the two executables, the backend module, and the service unit:

git clone https://github.com/vindeckyy/fan-control.git
cd fan-control

sudo install -Dm755 fan-daemon.py /usr/local/bin/fan-daemon
sudo install -Dm755 fan-gui.py /usr/local/bin/fan-gui
sudo install -Dm644 fan_backend.py /usr/local/bin/fan_backend.py
sudo install -Dm644 fan-daemon.service /etc/systemd/system/fan-daemon.service
sudo systemctl daemon-reload
sudo systemctl enable --now fan-daemon

Check the service after installation:

systemctl status fan-daemon
journalctl -u fan-daemon -n 50 --no-pager

Usage

Open the local dashboard:

sudo fan-gui

The dashboard listens only on http://127.0.0.1:4444. While it is open, it temporarily stops the daemon and takes ownership of the EC interface. Closing the dashboard releases control and restarts the daemon.

Run the daemon directly with a built-in profile:

sudo fan-daemon --profile balanced

Preview the complete dashboard without root or compatible hardware:

FAN_CONTROL_CONFIG=/tmp/fan-control-demo.json fan-gui --demo

Preview daemon decisions without opening an EC device:

fan-daemon --dry-run --profile silent

Configuration

Both programs read /etc/fan-control.json. The dashboard writes this file atomically when settings change.

{
  "profile": "balanced",
  "max_duty": 100,
  "hysteresis": 5,
  "critical_temp": 95
}
Key Default Purpose
profile balanced Active automatic curve
curve built-in Custom [temperature, duty] points
max_duty 100 Normal-operation noise cap, as a percentage
hysteresis 5 Minimum duty change before curve updates
critical_temp 95 Temperature that forces maximum safe duty

Backend selection is automatic: clevo-acpi sysfs is preferred when its fan attributes exist, otherwise tuxedo_io on the sole /dev/*_io device. Set FAN_CONTROL_BACKEND or pass --backend to override. For tuxedo_io, set FAN_CONTROL_DEVICE or pass --device when multiple candidates exist:

sudo FAN_CONTROL_BACKEND=clevo_acpi fan-gui
sudo FAN_CONTROL_DEVICE=/dev/example_io fan-gui

Architecture

hwmon / NVIDIA telemetry ──► temperature selection ──► curve + safety policy
                                                              │
                                                              ▼
        ┌────── clevo_acpi sysfs ───────┐  ◄── duty target ──┘
        │                                │
backend ┼──── tuxedo_io ioctls ─────────┤  ◄── percent duty
        │                                │
        └──── demo (simulated) ──────────┘
                         │
                         ▼
       firmware auto ◄── ownership handoff ◄── watchdog / release
  • fan_backend.py defines the backend abstraction and three implementations.
  • fan-daemon.py owns automatic background control.
  • fan-gui.py serves the local dashboard and interactive control API.
  • fan-daemon.service starts the daemon at boot.
  • test_fan_control.py covers interpolation, safety bounds, curve validation, backend discovery, duty conversion, legacy config migration, dashboard contracts, and NVIDIA parsing.

Troubleshooting

No fan-control hardware found

Run the built-in diagnostic to see which backend is available:

sudo fan-daemon --diagnose

For tuxedo_io, confirm a character device exists:

ls -l /dev/*_io

For clevo_acpi, confirm the fan attributes exist:

ls /sys/class/leds/clevo-acpi::kbd_backlight/device/fan*_manual_duty

Dashboard does not open

Check whether another process is using port 4444, then run the dashboard in a terminal to retain the error message:

ss -ltnp 'sport = :4444'
sudo fan-gui --no-browser

NVIDIA temperature is missing

Verify that the driver can report temperature:

nvidia-smi --query-gpu=index,temperature.gpu,name --format=csv,noheader,nounits

Development

The project intentionally uses only the Python standard library.

python3 -m py_compile fan_backend.py fan-daemon.py fan-gui.py test_fan_control.py
python3 -m unittest -v

See CONTRIBUTING.md before proposing hardware-facing changes. Security issues should follow SECURITY.md.

Unofficial project

Clevo and Tongfang names are used only to describe hardware compatibility. All product names and trademarks belong to their respective owners. This repository provides no manufacturer warranty, certification, or support.

About

Unofficial Linux fan control daemon and web dashboard for Clevo/Tongfang laptops

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages