Configuration
Config File
casectl stores configuration at ~/.config/casectl/config.yaml (follows XDG). The file is created with defaults on first run. Comments are preserved when editing via the API or CLI (uses ruamel.yaml).
casectl config get fan # view a section
casectl config set fan mode 0 # set a value (config stores integer enum values)
All settings have sensible defaults – edit only what you want to change.
Fan Config
| Key |
Type |
Default |
Description |
mode |
int |
0 |
Operating mode (see mode table below) |
manual_duty |
list[int] |
[75, 75, 75] |
Per-fan PWM duty (0-255) for manual mode |
thresholds.low_temp |
int |
30 |
Below this temp: use low_speed |
thresholds.high_temp |
int |
50 |
Above this temp: use high_speed |
thresholds.schmitt |
int |
3 |
Hysteresis band in °C |
thresholds.low_speed |
int |
75 |
PWM duty (0-255) for low temp range |
thresholds.mid_speed |
int |
125 |
PWM duty (0-255) for mid temp range |
thresholds.high_speed |
int |
175 |
PWM duty (0-255) for high temp range |
rpi_follow_min |
int |
0 |
Minimum duty when following RPi fan (0-255) |
rpi_follow_max |
int |
255 |
Maximum duty when following RPi fan (0-255) |
is_run_on_startup |
bool |
true |
Start fan control when daemon launches |
Fan Modes
| Value |
CLI Name |
Description |
| 0 |
follow-temp |
Automatic PWM based on CPU temperature curve |
| 1 |
follow-rpi |
Mirror the Raspberry Pi’s own fan PWM signal |
| 2 |
manual |
Fixed duty cycle from manual_duty |
| 3 |
custom |
Reserved for plugin-defined curves |
| 4 |
off |
Fans disabled (duty = 0) |
LED Config
| Key |
Type |
Default |
Description |
mode |
int |
0 |
Operating mode (see mode table below) |
red_value |
int |
0 |
Red channel (0-255) for manual mode |
green_value |
int |
0 |
Green channel (0-255) for manual mode |
blue_value |
int |
255 |
Blue channel (0-255) for manual mode |
is_run_on_startup |
bool |
true |
Start LED control when daemon launches |
LED Modes
| Value |
CLI Name |
Description |
| 0 |
rainbow |
Automatic colour cycling (STM32 firmware) |
| 1 |
breathing |
Pulsing brightness effect (STM32 firmware) |
| 2 |
follow-temp |
Colour follows CPU temperature |
| 3 |
manual |
Fixed colour from red/green/blue values |
| 4 |
custom |
Reserved for plugin-defined effects |
| 5 |
off |
LEDs disabled |
OLED Config
| Key |
Type |
Default |
Description |
rotation |
int |
180 |
Display rotation (0 or 180 degrees) |
is_run_on_startup |
bool |
true |
Start OLED display when daemon launches |
screens |
list |
4 entries |
Screen rotation cycle (see below) |
Per-Screen Options
Each entry in screens (index 0-3: clock, metrics, temperature, fan_duty):
| Key |
Type |
Default |
Description |
enabled |
bool |
true |
Show this screen in the rotation |
display_time |
float |
5.0 |
Seconds to display before advancing |
date_format |
int |
0 |
Date format variant (0 = YYYY-MM-DD) |
time_format |
int |
0 |
Time format (0 = 24h, 1 = 12h) |
interchange |
int |
0 |
Layout variant selector |
Service Config
| Key |
Type |
Default |
Description |
api_port |
int |
8420 |
REST API / web dashboard port |
api_host |
str |
127.0.0.1 |
Bind address. Use 0.0.0.0 for LAN access |
trust_proxy |
bool |
false |
Trust X-Forwarded-For for auth bypass (set true behind a reverse proxy) |
is_run_on_startup |
bool |
false |
Start API server when daemon launches |
Fan Curve Config
The fan.curve section defines a custom multi-point fan curve for custom mode. Points map temperature to PWM duty cycle with piecewise-linear interpolation between them.
| Key |
Type |
Default |
Description |
curve.name |
str |
"default" |
Curve profile name |
curve.points |
list |
2 points |
Temp-to-duty curve points (2-20, sorted by temp) |
curve.hysteresis |
float |
2.0 |
Temperature hysteresis in °C (0-10) |
Each point has temp (°C) and duty (0-255 PWM):
fan:
mode: 3 # custom mode
curve:
name: quiet
hysteresis: 3.0
points:
- temp: 30.0
duty: 50
- temp: 45.0
duty: 100
- temp: 60.0
duty: 175
- temp: 75.0
duty: 255
Below the lowest point, the lowest duty is used. Above the highest, the highest duty is used.
Alerts Config
Three channels can be used independently or together. Each channel is enabled implicitly when its required fields are non-empty. The enabled flag is a master switch that gates all channels.
| Key |
Type |
Default |
Description |
enabled |
bool |
false |
Master enable for alerting |
temp_threshold |
float |
80.0 |
CPU temperature (°C) alert threshold |
disk_threshold |
float |
90.0 |
Disk usage (%) alert threshold |
cooldown |
float |
300.0 |
Minimum seconds between repeated alerts (0-86400) |
Webhook Channel
| Key |
Type |
Default |
Description |
webhook_url |
str |
"" |
HTTP(S) webhook URL for alerts |
webhook_method |
str |
"POST" |
HTTP method (POST or PUT) |
webhook_headers |
dict |
{} |
Extra HTTP headers for webhook requests |
ntfy.sh Channel
| Key |
Type |
Default |
Description |
ntfy_url |
str |
"https://ntfy.sh" |
ntfy.sh server URL (cloud or self-hosted) |
ntfy_topic |
str |
"" |
ntfy.sh topic name (required to enable) |
ntfy_token |
str |
"" |
Access token for private topics |
ntfy_priority |
int |
3 |
Priority level (1=min, 3=default, 5=max) |
SMTP Channel
| Key |
Type |
Default |
Description |
smtp_host |
str |
"" |
SMTP server hostname |
smtp_port |
int |
587 |
SMTP server port |
smtp_user |
str |
"" |
SMTP username / sender address |
smtp_password |
str |
"" |
SMTP password (stored in plaintext, file is 0600) |
smtp_to |
str |
"" |
Recipient email address |
smtp_subject_prefix |
str |
"[casectl]" |
Subject line prefix for email alerts |
MQTT Config
Bidirectional MQTT integration with Home Assistant auto-discovery support. Requires a separate MQTT broker (e.g. Mosquitto).
| Key |
Type |
Default |
Description |
enabled |
bool |
false |
Master enable for MQTT integration |
broker_host |
str |
"localhost" |
MQTT broker hostname or IP |
broker_port |
int |
1883 |
Broker port (1883 plain, 8883 TLS) |
username |
str |
"" |
Broker username (empty for anonymous) |
password |
str |
"" |
Broker password |
client_id |
str |
"casectl" |
MQTT client ID (must be unique per broker) |
topic_prefix |
str |
"casectl" |
Base topic for all published messages |
ha_discovery_prefix |
str |
"homeassistant" |
Home Assistant discovery topic prefix |
qos |
int |
1 |
QoS level (0=at most once, 1=at least once, 2=exactly once) |
retain |
bool |
true |
Retain published state messages |
keepalive |
int |
60 |
Keepalive interval in seconds (5-3600) |
reconnect_min_delay |
float |
1.0 |
Min reconnect delay in seconds |
reconnect_max_delay |
float |
60.0 |
Max reconnect delay (exponential backoff cap) |
tls_enabled |
bool |
false |
Enable TLS |
tls_ca_cert |
str |
"" |
Path to CA certificate file |
tls_insecure |
bool |
false |
Skip TLS verification (not recommended) |
publish_interval |
float |
10.0 |
Seconds between metric publishing cycles (1-300) |
mqtt:
enabled: true
broker_host: 192.168.0.10
broker_port: 1883
username: casectl
password: secret
topic_prefix: casectl
ha_discovery_prefix: homeassistant
When enabled, casectl publishes fan/LED/OLED state and system metrics to MQTT, and accepts commands via MQTT topics for full Home Assistant integration.
Automation Config
Event-driven rules engine that reacts to system events (e.g. temperature changes) and triggers actions (e.g. set fan mode, send alert).
| Key |
Type |
Default |
Description |
enabled |
bool |
false |
Master enable for automation |
rules |
list |
[] |
Automation rules (max 100) |
Rule Structure
Each rule has:
| Key |
Type |
Description |
name |
str |
Unique rule name |
description |
str |
Optional description |
enabled |
bool |
Whether this rule is active (default: true) |
priority |
str |
safety > scheduled > user (default: user) |
event |
str |
EventBus event to listen for (e.g. metrics_updated) |
conditions |
list |
All must be true (AND logic) |
actions |
list |
Actions to execute when conditions are met |
cooldown |
float |
Min seconds between firings (0-3600) |
Conditions
| Field |
Description |
field |
Dot-path into event data (e.g. cpu_temp) |
operator |
gt, gte, lt, lte, eq, neq, in, not_in, between |
value |
Reference value for comparison |
Actions
| Field |
Description |
target |
Subsystem: fan, led, oled, emit, log, alert |
command |
Action command (e.g. set_duty, set_mode) |
params |
Parameters dict for the command |
automation:
enabled: true
rules:
- name: high-temp-turbo
event: metrics_updated
conditions:
- field: cpu_temp
operator: gt
value: 70
actions:
- target: fan
command: set_duty
params: {duty: [255, 255, 255]}
cooldown: 60
Plugin Config
Community plugins store their config under the plugins section:
plugins:
my-plugin:
interval: 30
log_path: /tmp/my-plugin.log
Plugins register a Pydantic schema via ctx.register_config(MyConfigModel) to validate their section. Access config in your plugin with await ctx.get_config().
Example config.yaml
fan:
mode: 0 # follow-temp
manual_duty: [75, 75, 75]
thresholds:
low_temp: 30
high_temp: 50
schmitt: 3
low_speed: 75
mid_speed: 125
high_speed: 175
led:
mode: 5 # off
red_value: 138
green_value: 170
blue_value: 196
oled:
rotation: 180
screens:
- enabled: true
display_time: 5.0
- enabled: true
display_time: 5.0
- enabled: true
display_time: 5.0
- enabled: true
display_time: 5.0
service:
api_port: 8420
api_host: 127.0.0.1 # change to 0.0.0.0 for LAN access
mqtt:
enabled: false
broker_host: localhost
broker_port: 1883
automation:
enabled: false
rules: []
alerts:
enabled: false
temp_threshold: 80.0
cooldown: 300.0