# Kao A minimalist system status monitor that uses ASCII emotes to display server health on an old phone. ![Status: Optimal]() ## Why? Turn an old phone (with its OLED screen) into a glanceable ambient display for your home server. Instead of graphs and numbers, see a happy face `( ^_^)` when things are good, and a worried face `( o_o)` when they're not. ## Features - **OLED-optimized** — Pure black background, saves battery - **Glanceable** — Know your server's status from across the room - **Extensible** — Add custom detectors for any metric - **Personality** — Rotating expressions, celebration animations, sleep mode - **Sound effects** — Optional audio cues for state changes (tap to enable) - **Home Assistant ready** — Webhook endpoints for notifications and automation ## Quick Start ```bash # Clone and setup git clone https://github.com/yourusername/kao.git cd kao python -m venv venv source venv/bin/activate # Windows: .\venv\Scripts\activate pip install -r requirements.txt # Run everything python kao.py ``` Open http://localhost:5100 on your phone (use Fully Kiosk Browser for best results). ## Activating the venv Two venvs exist — one for Windows, one for WSL: ```bash # WSL / Linux source venv-wsl/bin/activate # Windows (PowerShell) .\venv\Scripts\Activate.ps1 # Windows (cmd) .\venv\Scripts\activate.bat ``` Deactivate either with `deactivate`. ## Status Faces | State | Emote | Meaning | | ------------ | ----------- | ------------------------- | | Optimal | `( ^_^)` | All systems healthy | | Warning | `( o_o)` | Something needs attention | | Critical | `( x_x)` | Immediate action required | | Notify | `( 'o')` | Transient notification | | Sleeping | `( -_-)zzZ` | Sleep mode active | | Disconnected | `( ?.?)` | Can't reach server | ## Built-in Detectors | Detector | Monitors | | -------------- | ------------------------------------- | | **disk_space** | Disk usage on all drives | | **cpu** | CPU utilization | | **memory** | RAM usage | | **service** | Whether processes are running | | **network** | Host reachability (ping) | | **docker** | Container health and restart loops | ## Configuration Edit `config.json` to enable/disable detectors and set thresholds: ```json { "aggregator_url": "http://localhost:5100", "detectors": [ { "name": "disk_space", "enabled": true, "script": "detectors/disk_space.py", "env": { "CHECK_INTERVAL": "300", "THRESHOLD_WARNING": "85", "THRESHOLD_CRITICAL": "95" } } ] } ``` ## Custom Detectors Create your own detector by POSTing events to the aggregator: ```bash curl -X POST http://localhost:5100/event \ -H "Content-Type: application/json" \ -d '{"id": "my_check", "priority": 2, "message": "Something is wrong", "ttl": 120}' ``` - `id` — Unique identifier for this event - `priority` — 1 (critical), 2 (warning), 3 (notify), 4 (optimal) - `message` — What to display - `ttl` — Auto-expire after N seconds (for heartbeat pattern) Clear an event: ```bash curl -X POST http://localhost:5100/clear \ -d '{"id": "my_check"}' ``` ## Home Assistant Integration Add REST commands to your `configuration.yaml`: ```yaml rest_command: kao_notify: url: "http://YOUR_SERVER:5100/notify" method: POST content_type: "application/json" payload: > { "message": "{{ message | default('') }}", "duration": {{ duration | default(5) }}, "emote": "{{ emote | default('') }}", "color": "{{ color | default('') }}", "animation": "{{ animation | default('') }}", "sound": "{{ sound | default('') }}" } kao_sleep: url: "http://YOUR_SERVER:5100/sleep" method: POST kao_wake: url: "http://YOUR_SERVER:5100/wake" method: POST ``` Use in automations: ```yaml automation: - alias: "Doorbell Notification" trigger: platform: state entity_id: binary_sensor.doorbell to: "on" action: service: rest_command.kao_notify data: message: "Someone at the door" duration: 10 emote: "( °o°)" color: "#FF9900" sound: "chime" - alias: "Timer Complete" trigger: platform: event event_type: timer.finished action: service: rest_command.kao_notify data: message: "Timer done!" emote: "\\(^o^)/" animation: "celebrating" sound: "success" - alias: "Kao Sleep at Bedtime" trigger: platform: time at: "23:00:00" action: service: rest_command.kao_sleep - alias: "Kao Wake in Morning" trigger: platform: time at: "07:00:00" action: service: rest_command.kao_wake ``` **Notify options:** - `emote`: Any ASCII emote (e.g., `( °o°)`, `\\(^o^)/`) - `color`: Hex color (e.g., `#FF9900`) - `animation`: `breathing`, `shaking`, `popping`, `celebrating`, `floating`, `bouncing`, `swaying` - `sound`: `chime`, `alert`, `warning`, `critical`, `success`, `notify`, `doorbell`, `knock`, `ding`, `blip`, `siren`, `tada`, `ping`, `bubble`, `fanfare`, `alarm`, `none` ## Developer TUI `kao_tui.py` is a terminal UI for firing test events, faces, and sounds at a running Kao instance — no `curl` needed. ```bash python kao_tui.py # connect to http://localhost:5100 python kao_tui.py http://192.168.1.x:5100 # custom URL ``` Four tabs: - **Sounds** — fire any of the 17 sounds via `/notify` - **Faces** — send any preset emote/animation combo via `/notify` - **Events** — post Critical/Warning/Notify events (10s TTL) or clear all - **Controls** — Sleep, Wake, Clear all Navigate with `↑↓` or `Tab`, press `Enter` to fire, `Q` to quit. A toast confirms each action. ## API Reference | Endpoint | Method | Description | | --------- | ------ | ------------------------------------------------ | | `/` | GET | Web UI | | `/status` | GET | Current state as JSON | | `/events` | GET | List all active events | | `/event` | POST | Register an event | | `/clear` | POST | Clear an event by ID | | `/clear-all` | POST | Clear all active events | | `/notify` | POST | Simple notification `{"message": "", "duration": 5}` | | `/sleep` | POST | Enter sleep mode | | `/wake` | POST | Exit sleep mode | | `/docs` | GET | Interactive API documentation (Swagger UI) | Full API documentation available at [/docs](http://localhost:5100/docs) or in [openapi.yaml](openapi.yaml). ## Personality The emote has personality! In optimal state it: - Shows a stable face all day — set fresh each morning when `/wake` is called - Occasionally winks `( -_^)` or blinks `( ᵕ.ᵕ)` for a second or two on wake - Celebrates `\(^o^)/` when recovering from warnings - Each face has its own animation (floating, bouncing, swaying) - Reacts when tapped `( °o°)`, shows version info, and dismisses active alerts **Sound effects** (tap screen to enable, or use `?sound=on`): - Warning: soft double-beep - Critical: urgent descending tone - Notify: gentle ping - Recovery: happy ascending chirp - 10 additional synthesized sounds for `/notify`: `doorbell`, `knock`, `ding`, `blip`, `siren`, `tada`, `ping`, `bubble`, `fanfare`, `alarm` (alarm loops until tapped) ## License MIT