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