A high-performance, asynchronous Rust daemon for controlling Thermaltake Riing fans on Linux. It provides comprehensive fan speed control, RGB lighting management, and temperature monitoring through a modern, modular architecture.
Status: Active development - Core functionality stable, advanced features in progress.
- Features
- System Requirements
- Installation
- Configuration
- Usage
- Architecture
- Development
- Performance
- Contributing
- Roadmap
- Troubleshooting
- License
- Asynchronous Architecture - Built with Tokio for high-performance, non-blocking operations
- HID Driver Support - Native support for Thermaltake Riing controllers (PID 0x232B–0x232E)
- Hotplug Support - Automatic detection and management of USB device connect/disconnect events
- Temperature Monitoring - Integrated lm-sensors and NVIDIA GPU support with configurable polling
- Advanced Fan Curves - Support for constant, step-based, and smooth Bézier curves
- RGB Control - Full RGB lighting control with temperature-based color mapping
- Hot Configuration Reload - Dynamic configuration updates without daemon restart
- Hardware Fingerprinting - Stable controller identification across reconnections
-
D-Bus Interface - Complete D-Bus API for external integration:
- Bus name:
io.github.tt_riingd - Object path:
/io/github/tt_riingd - Interface:
io.github.tt_riingd1 - Methods:
GetActiveCurve,SwitchActiveCurve,UpdateCurveData,Stop - Properties:
Version - Signals:
Stopped,TemperatureChanged
- Bus name:
-
YAML Configuration - Human-readable configuration with validation
-
CLI Utility -
riingctlfor quick D-Bus operations -
Security - Udev rules for non-root access, systemd hardening
- Modular Service Architecture - Plugin-based service providers
- Event-Driven Design - Async event bus for inter-service communication
- Comprehensive Testing - 186+ tests (unit, integration, and documentation) with edge case coverage
- Performance Monitoring - Built-in metrics and health checks
- Zero Runtime Dependencies - Minimal dependency footprint
- OS: Linux (kernel 3.0+)
- Hardware: Thermaltake Riing controllers
- Rust: 1.70+ (for building from source)
- Dependencies:
libudev-dev,libhidapi-dev - Optional: NVIDIA drivers (for GPU temperature monitoring)
# Install system dependencies
sudo apt update && sudo apt install libudev-dev libhidapi-dev # Debian/Ubuntu
sudo dnf install systemd-devel hidapi-devel # Fedora
sudo pacman -S systemd hidapi # Arch Linux
# Clone and build
git clone https://github.com/At1ass/tt_riingd.git
cd tt_riingd
cargo build --release
# Install binary
sudo install -Dm755 target/release/tt-riingd /usr/local/bin/tt-riingd
sudo install -Dm755 riingctl /usr/local/bin/riingctl- AUR package
- Debian/Ubuntu packages
- Fedora RPM packages
Enable non-root access to Thermaltake devices:
sudo tee /etc/udev/rules.d/99-tt-riingd.rules << 'EOF'
# Thermaltake Riing controllers: PID 0x232B–0x232E
SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", ATTRS{idVendor}=="264a", ATTRS{idProduct}=="232?", TAG+="uaccess", TAG+="Thermaltake_Riing"
EOF
sudo udevadm control --reload
sudo udevadm triggerCreate ~/.config/tt-riingd/config.yml:
# Global settings
version: 1
tick_seconds: 2 # Temperature polling interval
enable_broadcast: true # Enable temperature broadcasts
broadcast_interval: 5 # Broadcast interval (seconds)
# Hardware controllers
controllers:
- kind: riing-quad
id: "main_controller"
usb:
vid: 0x264a
pid: 0x2330
# serial: "ABC123" # Optional: specific device serial
fans:
- idx: 1
name: "CPU Intake"
- idx: 2
name: "CPU Exhaust"
# Temperature sensors
sensors:
- kind: lm-sensors
id: "cpu_temp"
chip: "k10temp-pci-00c3"
feature: "Tctl"
# NVIDIA GPU temperature monitoring (optional, requires NVIDIA drivers)
- kind: nvidia
id: "gpu_temp"
gpu_index: 0 # First GPU (0-based indexing)
# Fan speed curves
curves:
- kind: constant
id: "silent"
speed: 30
- kind: step-curve
id: "performance"
tmps: [30.0, 50.0, 70.0, 85.0]
spds: [25, 40, 70, 100]
- kind: bezier
id: "smooth"
points:
- {x: 30.0, y: 20.0} # Control point 1
- {x: 45.0, y: 30.0} # Control point 2
- {x: 65.0, y: 70.0} # Control point 3
- {x: 80.0, y: 95.0} # Control point 4
# Sensor-to-fan mappings
mappings:
- sensor: "cpu_temp"
targets:
- controller_id: "main_controller"
fan_idx: 1
- controller_id: "main_controller"
fan_idx: 2
# Active curve assignments
active_curve_mappings:
- curve: "performance"
targets:
- controller_id: "main_controller"
fan_idx: 1
# RGB color definitions
colors:
- color: "cool_blue"
rgb: [0, 100, 255]
- color: "warm_red"
rgb: [255, 50, 0]
# Temperature-based color mappings
color_mappings:
- color: "cool_blue"
targets:
- controller_id: "main_controller"
fan_idx: 1export TT_RIINGD_CONFIG=/path/to/config.yml # Custom config location
export TT_RIINGD_LOG_LEVEL=debug # Logging level
export RUST_LOG=tt_riingd=debug # Rust logging# Create service file
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/tt-riingd.service << 'EOF'
[Unit]
Description=tt-riingd — Thermaltake Riing Fan Controller
Documentation=https://github.com/At1ass/tt_riingd
After=graphical-session.target
[Service]
Type=simple
ExecStart=/usr/local/bin/tt-riingd
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
# Security hardening
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
NoNewPrivileges=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=default.target
EOF
# Enable and start
systemctl --user daemon-reload
systemctl --user enable --now tt-riingd
# Monitor logs
journalctl --user -u tt-riingd -fsudo tee /etc/systemd/system/tt-riingd.service << 'EOF'
[Unit]
Description=tt-riingd — Thermaltake Riing Fan Controller
Documentation=https://github.com/At1ass/tt_riingd
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/bin/tt-riingd --config /etc/tt-riingd/config.yml
User=tt-riingd
Group=tt-riingd
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
# Security hardening
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
MemoryDenyWriteExecute=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target
EOF
# Create user and enable service
sudo useradd -r -s /bin/false tt-riingd
sudo systemctl daemon-reload
sudo systemctl enable --now tt-riingd# Foreground with debug logging
RUST_LOG=debug tt-riingd --config config.yml
# Background daemon
tt-riingd --config config.yml --daemon# Get daemon version
riingctl version
# Check active curve for main_controller, fan 1
riingctl get-active-curve main_controller 1
# Switch to performance curve
riingctl switch-active-curve main_controller 1 performance
# Update curve data (JSON format)
riingctl update-curve-data main_controller 1 custom '{"kind":"constant","speed":75}'
# Stop daemon gracefully
riingctl stop# Introspect the interface
busctl --user introspect io.github.tt_riingd /io/github/tt_riingd
# Call methods directly
busctl --user call io.github.tt_riingd /io/github/tt_riingd io.github.tt_riingd1 GetActiveCurve sy "main_controller" 1
# Monitor signals
busctl --user monitor io.github.tt_riingd# Send SIGHUP to reload configuration
sudo systemctl reload tt-riingd
# Or via D-Bus
busctl --user call io.github.tt_riingd /io/github/tt_riingd io.github.tt_riingd1 ReloadConfig┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────────────────────────────┤
│ SystemCoordinator │ TaskManager │ EventBus │ ConfigManager │
├─────────────────────────────────────────────────────────────┤
│ Service Providers │
│ • MonitoringService • BroadcastService │
│ • FanColorService • DBusService │
│ • ConfigWatcherService │
├─────────────────────────────────────────────────────────────┤
│ Hardware Abstraction │
│ • FanController • TemperatureSensors │
│ • TTRiingQuad Driver • LmSensors Integration │
│ • NVIDIA GPU Support │
└─────────────────────────────────────────────────────────────┘
- SystemCoordinator: Orchestrates service lifecycle and dependencies
- TaskManager: Manages async tasks with graceful shutdown
- EventBus: Pub/sub system for inter-service communication
- ConfigManager: Hot-reloadable configuration with validation
- Registry: Hardware detection and configuration management with caching
- UdevWatcher: Linux udev integration for hotplug device detection
- Service Providers: Modular, pluggable service architecture
Device Connect/Disconnect Event
↓
UdevWatcher
↓
EventBus
↓
SystemCoordinator
↓
ControllerManager
↓
Registry (Config Cache) ←→ Hardware Fingerprinting
↓
Controller Creation/Restoration
The system automatically detects when controllers are connected or disconnected, maintaining configuration state through hardware fingerprinting for seamless reconnection experience.
# Debug build
cargo build
# Release build with optimizations
cargo build --release
# Build with all features
cargo build --all-features# Run all tests (186+ tests total)
cargo test
# Run unit tests only (133 tests)
cargo test --lib
# Run integration tests (36 tests)
cargo test --test integration_controllers
cargo test --test integration_monitoring
cargo test --test integration_e2e
cargo test --test integration_config_reload
# Run documentation tests (17 tests)
cargo test --doc
# Run with coverage
cargo test --all-features
cargo tarpaulin --out html
# Run specific test module
cargo test config::tests
cargo test drivers::tests
# Run a single test
cargo test test_hotplug_functionality# Format code
cargo fmt --all
# Lint with clippy
cargo clippy --all-targets --all-features -- -D warnings
# Security audit
cargo audit
# Check documentation
cargo doc --no-deps --open# Run with debug logging
RUST_LOG=debug cargo run
# Run with specific module logging
RUST_LOG=tt_riingd::drivers=trace cargo run
# Use debugger
rust-gdb target/debug/tt-riingd- Memory Usage: ~2-5MB RSS
- CPU Usage: <1% on modern systems
- Response Time: <1ms for D-Bus calls
- Startup Time: <100ms cold start
# System resource usage
systemctl --user status tt-riingd
# Detailed metrics
journalctl --user -u tt-riingd | grep "METRICS"
# D-Bus performance
busctl --user monitor io.github.tt_riingdWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes with tests
- Run quality checks:
cargo fmt && cargo clippy && cargo test - Commit with conventional commits:
git commit -m "feat: add amazing feature" - Push and create a Pull Request
# Install development dependencies
cargo install cargo-tarpaulin cargo-audit cargo-outdated
# Set up pre-commit hooks
cp scripts/pre-commit .git/hooks/
chmod +x .git/hooks/pre-commitSee ROADMAP.md for planned features and milestones.
- Hotplug Support - Automatic USB device detection and management
- Hardware Fingerprinting - Stable controller identification across reconnections
- Enhanced Testing - Comprehensive test suite with 186+ tests
- Improved Architecture - Event-driven design with modular service providers
- GUI Application - GTK4/Libadwaita interface
- Plugin System - Extensible architecture for custom sensors/controllers
- Advanced Curves - PID controllers, machine learning optimization
- Packaging - Distribution packages for major Linux distros
- Advanced Hotplug - Configuration restoration and automatic fallback settings
Permission Denied
# Check udev rules are installed
ls -la /etc/udev/rules.d/99-tt-riingd.rules
# Verify device permissions
ls -la /dev/hidraw*
# Reload udev rules
sudo udevadm control --reload && sudo udevadm triggerConfiguration Errors
# Validate configuration
tt-riingd --config config.yml --validate
# Check logs for details
journalctl --user -u tt-riingd -n 50D-Bus Connection Issues
# Check if daemon is running
systemctl --user status tt-riingd
# Test D-Bus connectivity
busctl --user list | grep tt_riingdLicensed under the MIT License. See LICENSE for details.
- Thermaltake for hardware documentation
- The Rust community for excellent crates
- Linux kernel developers for HID subsystem
- Contributors and testers
Made with care by At1ass and contributors