Architecture
System Overview
casectl follows a daemon-first, plugin-driven architecture. All hardware access goes through a central daemon that exposes a REST API. The CLI, web dashboard, and any future interfaces are all API clients – they never touch hardware directly.
Hardware Layer
The Freenove Computer Case Kit Pro includes an STM32-based expansion board connected to the Pi via I2C. This board controls:
- 3 PWM fans with independent speed control (0-100%)
- 4 WS2812 RGB LEDs with colour and effect modes
- Temperature sensor on the expansion board itself
casectl communicates with the STM32 at I2C address 0x21 using the smbus2 library. All I2C calls run via asyncio.to_thread() to prevent blocking the FastAPI event loop.
The SSD1306 OLED display (128x64 pixels, I2C address 0x3C) is driven separately via the luma.oled library.
System metrics (CPU temperature, memory usage, disk space) come from psutil and sysfs reads.
Plugin System
Plugins are the core extensibility mechanism. casectl uses Python’s typing.Protocol for structural subtyping – your plugin doesn’t need to inherit from any base class. It just needs to implement the right methods:
class CasePlugin(Protocol):
async def setup(self, ctx: PluginContext) -> None: ...
async def start(self) -> None: ...
async def stop(self) -> None: ...
def get_status(self) -> dict[str, Any]: ...
Plugins are discovered automatically via Python entry points (casectl.plugins group). The PluginHost manages their lifecycle: discovery, loading, starting, stopping.
Built-in Plugins
| Plugin | What it does |
|---|---|
fan-control |
Temperature-curve PWM control with follow-temp/follow-rpi/manual/custom/off modes |
led-control |
Rainbow, breathing, follow-temp, manual colour, off |
oled-display |
4 cycling screens: clock, metrics, temperatures, fan duty |
system-monitor |
Periodic metrics collection + event bus emission |
prometheus |
/metrics endpoint in Prometheus text format |
mqtt |
Bidirectional MQTT with Home Assistant auto-discovery |
automation |
Event-driven rules engine with conditions, actions, priority, cooldown |
alerting |
Alert dispatch via webhook, ntfy.sh, and SMTP channels |
Event Bus
The EventBus provides async pub/sub within the daemon. Plugins publish events (e.g. temperature readings, fan speed changes) and other plugins or the WebSocket endpoint subscribe. The web dashboard uses WebSocket for real-time updates.
Graceful Degradation
casectl is designed to work without hardware. When the I2C bus or specific devices aren’t available, plugins report DEGRADED status instead of crashing. The daemon, API, monitoring, and web dashboard all continue to function – only the hardware control features are disabled.
This means you can develop and test plugins on any machine, not just a Pi with the case attached.
Testing
casectl has a comprehensive test suite using mock hardware fixtures at the I2C/bus level – all tests run without real hardware. Run pytest --cov=casectl for current coverage.
pytest # run all tests
pytest --cov=casectl # with coverage report