⚠️ NOTE: This project is currently in early stages of development and can change rapidly. Expect breakage between releases.
This is meant to be a universal controller for anything that can be read
and writen from hwmon sysfs filesystem.
Originally designed for handhelds but can be configured for anything that has
sensors and fans exposed via hwmon sysfs exclusively
(i.e. /sys/class/hwmon/hwmon?/*)
On ArchLinux (and derivatives) there is hhfc-git package in the
AUR.
For installing from sources you'll need some python packages first:
buildinstallerwheelsetuptoolspyyaml
Then clone sources and build/install
$ git clone git+https://github.com/Samsagax/hhfc.git
$ cd hhfc
$ python -m build --wheel
# python -m installer dist/*.whlFor system daemon use copy the systemd unit:
# cp -v systemd/hhfc.service /usr/lib/systemd/system/hhfc.serviceRun hhfc with a given configuration file:
$ hhfc -c fan_control.yaml:info: You may need root privileges (i.e. sudo) to write to hwmon attribute files.
There are some examples under config directory in the repo.
See Configuration for writing your own for your machine
The most common usecase once configured is to run it as a system daemon.
Write a configuration file for your machine and place it in
/etc/hhfc/fan_control.yaml (create directories if appropriate). Then enable
the systemd unit if not already. It will look for the system configuration and
start the daemon:
# systemctl enable hhfc.serviceYou can also run the controller in "monitor mode" by usign the -m flag.
This way the controller won't write to fan handles but can monitor sensor
readings and fan speeds.
# hhfc -m -c fan_control.yamlThe driver uses FANS and SENSORS as the configuration units defined on
a yaml file.
Sensors are read from hwmon drivers given it's name and temperature input. Often the sensors need to be scaled and offset to have a readable value.
Example SENSORS section:
SENSORS:
- name: "cpu"
driver_name: "k10temp"
temp_input: "temp1_input"
divisor: 1000
offset: 20
- name: "gpu"
driver_name: "amdgpu"
temp_input: "temp1_input"
divisor: 1000
offset: 20namedefines how the sensor will be referenced by fansdriver_nameis the name of the hwmon driver to watch (i.e./sys/class/hwmon?/nameattribute)temp_inputname of the attribute file to read temperatures from.divisorthe value to divide the readtemp_input. This is an optional parameter, if not set it will default to1000.offsetthe value to add to the readtemp_inputafter the division. Most chips expose the temperature with an offset of 20°C. This parameter is optional and will default to0if not set.
Each sensor needs to be prepended with a list marker (i.e. -)
Any fan can watch one or more sensors. It needs at least one to function. Fans need to be defined by a name, the hwmon driver name and hwmon attribute to handle and read its input.
Example FANS section:
FANS:
- name: "fan1"
driver_name: "oxpec"
handle: "pwm1"
max_control_value: 255
min_control_value: 0
fan_input: "fan1_input"
allow_shutoff: yes
minimum_duty_cycle: 30
sensors:
- name: "cpu"
curve: [
[60, 0],
[80, 50],
[90, 100]
]
- name: "gpu"
curve: [
[60, 0],
[80, 50],
[90, 100]
]nameis the name to reference this fan.driver_nameis the name of the hwmon driver to write to (i.e./sys/class/hwmon?/nameattribute)handleis the hwmon attribute file to write to (i.e./sys/class/hwmon?/pwm1in this case)max_control_valueandmin_control_valueare the min and max value the controller will write to thehandle. Duty cycles are defined and used in the [0-100] interval, written values will be mapped to [min-max] values before writting. This parameters are optional, if not set they will default to the range [0-255].fan_inputis the hwmon attribute to read fan speed from.allow_shutoffdetermines if the fan is allowed to be shut off. The value should be "yes" or "no" (default). If the fan is allowed to shut off completely the value ofminimum_duty_cyclewill be used to turn it on and the lowest value in the fan curve will shut it off. If the value is "no", the value ofminimum_duty_cyclewill be used as the lowest value for the fan.sensorsdefine a list of sensors and its curves this fan will monitor. Each sensor curve definition needs to start with a list marker.nameis the sensor name that will be matched from theSENSORSsectioncurvedefines points with temperatures and corresponding duty cycles. The lowest and higher points will also work as cutoffs. Any temperature value reading below the lowest or higher than highest will be set to the corresponding duty cycle value. Duty cycle is on the range [0, 100].
If you have written configurations for some device that can be generic enough and safe to use, please add it as a Gist link in this issue or as a Pull Request for inclusion.
The project is under the GPLv3 license and all kinds of contributions are welcome.