-
-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Kanfei uses a two-process backend architecture with a shared SQLite database.
- Logger daemon (
backend/logger_main.py)
- Owns the hardware connection to the weather station
- Polls sensor data via the configured
StationDriver - Writes sensor rows to SQLite
- Exposes hardware/status commands over TCP IPC
- Web app (
backend/app/main.py)
- FastAPI app serving REST API + built frontend
- Relays live updates to browser clients via WebSocket
- Uses IPC client to request hardware actions from logger daemon
- Runs background services (nowcast, APRS-IS map collector, bot supervisors)
- The configured
StationDrivercommunicates with the weather station over serial, TCP, HTTP, or UDP depending on hardware type. -
Pollerreceives aSensorSnapshotfrom the driver, computes derived values (heat index, dew point, wind chill, feels-like, theta-e, pressure trend), and stores them insensor_readings. - Poller broadcasts
sensor_updatemessages through IPC subscriptions. - Web app WebSocket handler relays IPC messages to
/ws/livebrowser clients. - REST API reads from SQLite for current conditions, history, forecasts, config, and admin features.
All hardware drivers implement the StationDriver abstract base class (backend/app/protocol/base.py). Each driver's poll() method returns a SensorSnapshot — a canonical data class with all values in SI units (°C, m/s, hPa, etc.). The driver is responsible for converting from native hardware formats to SI before returning.
The logger daemon instantiates drivers via a factory function (_create_driver) based on the station_driver_type config key. This allows the rest of the system (poller, IPC, web API, dashboard) to work identically regardless of hardware.
Drivers declare their supported features via a capabilities set. The UI and services check capabilities before offering hardware-specific operations (archive sync, calibration, clock sync, rain reset, etc.). This prevents unsupported actions from being shown or attempted.
- Logger daemon runs an IPC server on configurable port (default
6514). - Web app creates an IPC client during lifespan startup.
- If logger is unavailable, web app remains up in degraded mode.
Primary database: SQLite (WAL mode enabled during initialization).
Key tables include:
sensor_readingsstation_config-
users,sessions,api_keys(authentication) - nowcast history/knowledge/verification tables
- spray product/schedule/outcome tables
- archive records
- React + TypeScript + Vite SPA
- Route-based pages (
Dashboard,History,Forecast,Astronomy,Map,Settings,About,Login) -
Nowcast,Spray, andMappages are feature-flag controlled - Setup wizard is shown until
setup_completeis true (includes admin account creation) -
AuthContextmanages session state; 401 responses redirect to Login - Weather data pages are public; Settings and admin actions require login
- Weather data context consumes REST + WebSocket updates
- Admin API endpoints require session cookie or API key authentication; public weather data endpoints are unauthenticated. See Security and Networking for details.
- CORS is restricted to a configurable allowlist (
KANFEI_CORS_ORIGINSenv var; empty = same-origin only). - OpenAPI/Swagger docs are disabled in production (no schema exposure).
- Hardware I/O is isolated to one process (logger daemon)
- Web app can continue serving UI/API even without station connectivity
- Many services reload config from DB dynamically so settings changes apply without full restart