Skip to content

m00sfett/fanctrl

Repository files navigation

fanctrl

Version: 1.0.0

A lightweight Python tool to control a fan based on system temperature, using libgpiod.

Tested Platforms

  • Core service tested in Docker on Raspberry Pi 3.
  • No verified results yet for other boards/architectures.

Quick Start

git clone https://github.com/m00sfett/fanctrl.git
cd fanctrl
docker compose up -d --build

Features

  • Backend: Uses strict libgpiod (modern Linux GPIO). no legacy RPi.GPIO dependency.
  • Configurable: Set thresholds, poll intervals, and GPIO lines via TOML config or environment variables.
  • Status API: Simple HTTP endpoint to monitor current state.
  • Safety: Failsafe defaults if config is invalid or sensor reading fails.

Home Assistant

If you are looking for the Home Assistant Add-on, find it here: ha-addon-fanctrl In current Home Assistant versions (2026.2+), add-ons are listed under Apps.

Installation

From Source

git clone https://github.com/m00sfett/fanctrl.git
cd fanctrl
pip install .

Docker (Raspberry Pi OS / Docker)

  1. Clone the repo and create a config:
git clone https://github.com/m00sfett/fanctrl.git
cd fanctrl
# Edit config/fanctrl.toml to match your hardware.
  1. Start with Docker Compose:
docker compose up -d --build
  1. Logs:
docker compose logs -f fanctrl

Notes

  • Ensure GPIO devices are passed through (/dev/gpiochip*, optionally /dev/gpiomem).
  • If your Pi exposes GPIO on a different chip, set gpio_chip in the config.
  • The status endpoint listens on 9101 inside the fanctrl container/network.
  • With the provided docker-compose.yml, no host port is published by default.

Usage

Run the tool directly:

fanctrl [path/to/config.toml]

Or via environment variables:

export FANCTRL_CONFIG="/path/to/config.toml"
fanctrl

Configuration

Example config.toml:

[fan]
# GPIO Settings
gpio_chip = "gpiochip0"  # The GPIO character device
gpio_pin = 33            # The line offset (BCM pin number usually, NOT physical pin)
active_high = true       # Set to false for active-low fans

# Temperature Thresholds (Celsius)
temp_on_c = 55.0
temp_off_c = 45.0
temp_path = "/sys/class/thermal/thermal_zone0/temp"

# Timing
poll_interval_s = 5.0    # How often to check temp
min_switch_s = 10.0      # Minimum time to stay in one state (hysteresis)
log_each_read = true     # Log every poll or just changes

PIN Mapping

Important: This tool uses libgpiod, which exclusively uses chip line offsets (often matching BCM numbers on RPi), not physical board pin numbers.

  • If you used RPi.GPIO "BOARD" mode pin 33 previously, find the corresponding BCM number (e.g. BCM 13) and use that as gpio_pin.

Status Endpoint

By default, a status server runs on port 9101 inside the container: GET http://fanctrl:9101/status (from another container on the same Docker network)

If you publish the port explicitly, host access is possible: GET http://<host-ip>:9101/status

Returns:

{
  "fan_on": true,
  "temp_c": 56.2,
  "temp_on_c": 55.0,
  "temp_off_c": 45.0,
  "version": "1.0.0"
}

Troubleshooting

  • gpiod import failed: ensure the runtime has Python gpiod bindings installed.
  • GPIO chip not found: verify the correct /dev/gpiochipX device is passed through.

About

Lightweight Python tool for temperature-based fan control on Raspberry Pi using modern libgpiod.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors