Compare commits
2 Commits
8ad86d1c6e
...
5e76ce9597
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e76ce9597 | |||
| 4262865520 |
@@ -80,6 +80,7 @@ All detectors support: `AGGREGATOR_URL`, `CHECK_INTERVAL`, `THRESHOLD_WARNING`,
|
|||||||
| `/wake` | POST | Exit sleep mode |
|
| `/wake` | POST | Exit sleep mode |
|
||||||
| `/status` | GET | Current state JSON |
|
| `/status` | GET | Current state JSON |
|
||||||
| `/events` | GET | List active events |
|
| `/events` | GET | List active events |
|
||||||
|
| `/docs` | GET | Interactive API documentation (Swagger UI) |
|
||||||
|
|
||||||
### `/notify` Endpoint
|
### `/notify` Endpoint
|
||||||
|
|
||||||
@@ -176,6 +177,7 @@ Use in automations:
|
|||||||
├── aggregator.py # Event broker/API server
|
├── aggregator.py # Event broker/API server
|
||||||
├── index.html # OLED-optimized frontend
|
├── index.html # OLED-optimized frontend
|
||||||
├── config.json # Runtime configuration
|
├── config.json # Runtime configuration
|
||||||
|
├── openapi.yaml # API documentation (OpenAPI 3.0)
|
||||||
├── detectors/
|
├── detectors/
|
||||||
│ ├── disk_space.py
|
│ ├── disk_space.py
|
||||||
│ ├── cpu.py
|
│ ├── cpu.py
|
||||||
|
|||||||
@@ -191,6 +191,9 @@ automation:
|
|||||||
| `/notify` | POST | Simple notification `{"message": "", "duration": 5}` |
|
| `/notify` | POST | Simple notification `{"message": "", "duration": 5}` |
|
||||||
| `/sleep` | POST | Enter sleep mode |
|
| `/sleep` | POST | Enter sleep mode |
|
||||||
| `/wake` | POST | Exit 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
|
## Personality
|
||||||
|
|
||||||
|
|||||||
@@ -326,6 +326,35 @@ def list_events():
|
|||||||
return jsonify({"events": dict(active_events)}), 200
|
return jsonify({"events": dict(active_events)}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/docs")
|
||||||
|
def docs():
|
||||||
|
"""Serve interactive API documentation via Swagger UI."""
|
||||||
|
return """<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Kao API Documentation</title>
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
||||||
|
<style>
|
||||||
|
body { margin: 0; background: #fafafa; }
|
||||||
|
.swagger-ui .topbar { display: none; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
||||||
|
<script>
|
||||||
|
SwaggerUIBundle({
|
||||||
|
url: '/openapi.yaml',
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
||||||
|
layout: 'BaseLayout'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
port = int(os.environ.get("PORT", 5100))
|
port = int(os.environ.get("PORT", 5100))
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@
|
|||||||
const emoteEl = document.getElementById("emote");
|
const emoteEl = document.getElementById("emote");
|
||||||
const messageEl = document.getElementById("message");
|
const messageEl = document.getElementById("message");
|
||||||
const POLL_INTERVAL = 2000;
|
const POLL_INTERVAL = 2000;
|
||||||
const VERSION = "v1.3.0";
|
const VERSION = "v1.3.2";
|
||||||
|
|
||||||
// Sound system
|
// Sound system
|
||||||
let audioCtx = null;
|
let audioCtx = null;
|
||||||
|
|||||||
400
openapi.yaml
Normal file
400
openapi.yaml
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Kao API
|
||||||
|
description: |
|
||||||
|
Kao is a minimalist system status monitor that uses ASCII emotes to represent system health.
|
||||||
|
|
||||||
|
## Priority System
|
||||||
|
Events use a priority system where lower numbers indicate higher priority:
|
||||||
|
- **1 (Critical)**: System failure - red, shaking
|
||||||
|
- **2 (Warning)**: Degraded state - yellow, breathing
|
||||||
|
- **3 (Notify)**: Informational alert - blue, popping
|
||||||
|
- **4 (Optimal)**: All systems healthy - green, varies
|
||||||
|
|
||||||
|
## TTL/Heartbeat Pattern
|
||||||
|
Events can have a TTL (time-to-live) that auto-expires them. Detectors typically send
|
||||||
|
heartbeat events that expire if not refreshed, indicating loss of communication.
|
||||||
|
version: 1.3.0
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:5100
|
||||||
|
description: Local development server
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/event:
|
||||||
|
post:
|
||||||
|
summary: Register an event
|
||||||
|
description: |
|
||||||
|
Register or update a system event. Events are identified by their ID and will
|
||||||
|
overwrite any existing event with the same ID. Use TTL for heartbeat-style
|
||||||
|
monitoring where absence of updates indicates a problem.
|
||||||
|
operationId: postEvent
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventRequest'
|
||||||
|
examples:
|
||||||
|
critical:
|
||||||
|
summary: Critical event
|
||||||
|
value:
|
||||||
|
id: "disk_root"
|
||||||
|
priority: 1
|
||||||
|
message: "Root disk 98% full"
|
||||||
|
heartbeat:
|
||||||
|
summary: Heartbeat with TTL
|
||||||
|
value:
|
||||||
|
id: "cpu_monitor"
|
||||||
|
priority: 4
|
||||||
|
message: "CPU nominal"
|
||||||
|
ttl: 60
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Event registered successfully
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventResponse'
|
||||||
|
'400':
|
||||||
|
description: Invalid request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
/clear:
|
||||||
|
post:
|
||||||
|
summary: Clear an event
|
||||||
|
description: Remove an event by its ID. Use this when a condition has resolved.
|
||||||
|
operationId: clearEvent
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: Event identifier to clear
|
||||||
|
example: "disk_root"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Event cleared successfully
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ClearResponse'
|
||||||
|
'400':
|
||||||
|
description: Missing required field
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
'404':
|
||||||
|
description: Event not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
/notify:
|
||||||
|
post:
|
||||||
|
summary: Send a notification
|
||||||
|
description: |
|
||||||
|
Send a temporary notification with optional custom display properties.
|
||||||
|
Designed for Home Assistant integration. Notifications auto-expire after
|
||||||
|
the specified duration.
|
||||||
|
operationId: notify
|
||||||
|
requestBody:
|
||||||
|
required: false
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NotifyRequest'
|
||||||
|
examples:
|
||||||
|
simple:
|
||||||
|
summary: Simple notification
|
||||||
|
value:
|
||||||
|
message: "Doorbell rang"
|
||||||
|
duration: 10
|
||||||
|
custom:
|
||||||
|
summary: Custom notification
|
||||||
|
value:
|
||||||
|
message: "Welcome home!"
|
||||||
|
duration: 10
|
||||||
|
emote: "(`-´)ゞ"
|
||||||
|
color: "#00FF88"
|
||||||
|
animation: "celebrating"
|
||||||
|
sound: "chime"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Notification sent
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NotifyResponse'
|
||||||
|
|
||||||
|
/sleep:
|
||||||
|
post:
|
||||||
|
summary: Enter sleep mode
|
||||||
|
description: |
|
||||||
|
Put Kao into sleep mode. The display will show a sleeping emote with
|
||||||
|
dimmed colors. All events are preserved but not displayed until wake.
|
||||||
|
operationId: sleep
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Entered sleep mode
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SleepResponse'
|
||||||
|
|
||||||
|
/wake:
|
||||||
|
post:
|
||||||
|
summary: Exit sleep mode
|
||||||
|
description: Wake Kao from sleep mode and resume normal status display.
|
||||||
|
operationId: wake
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Exited sleep mode
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/WakeResponse'
|
||||||
|
|
||||||
|
/status:
|
||||||
|
get:
|
||||||
|
summary: Get current status
|
||||||
|
description: |
|
||||||
|
Returns the current display state including the active emote, color,
|
||||||
|
animation, and list of active events. The frontend polls this endpoint.
|
||||||
|
operationId: getStatus
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Current status
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
/events:
|
||||||
|
get:
|
||||||
|
summary: List all active events
|
||||||
|
description: Returns all currently active events with their full details.
|
||||||
|
operationId: listEvents
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: List of active events
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventList'
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
EventRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- priority
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: Unique identifier for this event
|
||||||
|
example: "cpu_high"
|
||||||
|
priority:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maximum: 4
|
||||||
|
description: |
|
||||||
|
Event priority (1=Critical, 2=Warning, 3=Notify, 4=Optimal)
|
||||||
|
example: 2
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
description: Optional message to display
|
||||||
|
example: "CPU at 90%"
|
||||||
|
ttl:
|
||||||
|
type: integer
|
||||||
|
description: Time-to-live in seconds. Event auto-expires after this duration.
|
||||||
|
example: 60
|
||||||
|
|
||||||
|
EventResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "ok"
|
||||||
|
current_state:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
ClearResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "cleared"
|
||||||
|
current_state:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
NotifyRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
description: Text to display below the emote
|
||||||
|
example: "Someone at the door"
|
||||||
|
duration:
|
||||||
|
type: integer
|
||||||
|
description: Seconds before auto-expire
|
||||||
|
default: 5
|
||||||
|
example: 10
|
||||||
|
emote:
|
||||||
|
type: string
|
||||||
|
description: Custom emote to display (overrides default)
|
||||||
|
example: "( °o°)"
|
||||||
|
color:
|
||||||
|
type: string
|
||||||
|
description: Custom color in hex format
|
||||||
|
pattern: '^#[0-9A-Fa-f]{6}$'
|
||||||
|
example: "#FF9900"
|
||||||
|
animation:
|
||||||
|
type: string
|
||||||
|
description: Animation style
|
||||||
|
enum:
|
||||||
|
- breathing
|
||||||
|
- shaking
|
||||||
|
- popping
|
||||||
|
- celebrating
|
||||||
|
- floating
|
||||||
|
- bouncing
|
||||||
|
- swaying
|
||||||
|
example: "popping"
|
||||||
|
sound:
|
||||||
|
type: string
|
||||||
|
description: Sound effect to play
|
||||||
|
enum:
|
||||||
|
- chime
|
||||||
|
- alert
|
||||||
|
- warning
|
||||||
|
- critical
|
||||||
|
- success
|
||||||
|
- notify
|
||||||
|
- none
|
||||||
|
example: "chime"
|
||||||
|
|
||||||
|
NotifyResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "ok"
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: Generated event ID
|
||||||
|
example: "ha_notify_1704067200000"
|
||||||
|
current_state:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
SleepResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "sleeping"
|
||||||
|
current_state:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
WakeResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "awake"
|
||||||
|
current_state:
|
||||||
|
$ref: '#/components/schemas/Status'
|
||||||
|
|
||||||
|
Status:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
current_state:
|
||||||
|
type: string
|
||||||
|
description: Current state name
|
||||||
|
enum:
|
||||||
|
- critical
|
||||||
|
- warning
|
||||||
|
- notify
|
||||||
|
- optimal
|
||||||
|
- sleeping
|
||||||
|
example: "optimal"
|
||||||
|
active_emote:
|
||||||
|
type: string
|
||||||
|
description: ASCII emote to display
|
||||||
|
example: "( ^_^)"
|
||||||
|
color:
|
||||||
|
type: string
|
||||||
|
description: Display color in hex
|
||||||
|
example: "#00FF00"
|
||||||
|
animation:
|
||||||
|
type: string
|
||||||
|
description: Current animation
|
||||||
|
example: "breathing"
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
description: Status message
|
||||||
|
example: "Optimal"
|
||||||
|
sound:
|
||||||
|
type: string
|
||||||
|
description: Sound to play (only present when triggered)
|
||||||
|
example: "chime"
|
||||||
|
active_events:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ActiveEvent'
|
||||||
|
last_updated:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
description: ISO 8601 timestamp
|
||||||
|
example: "2024-01-01T12:00:00"
|
||||||
|
|
||||||
|
ActiveEvent:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
example: "cpu_monitor"
|
||||||
|
priority:
|
||||||
|
type: integer
|
||||||
|
example: 4
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
example: "CPU nominal"
|
||||||
|
|
||||||
|
EventList:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
events:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
priority:
|
||||||
|
type: integer
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: number
|
||||||
|
ttl:
|
||||||
|
type: number
|
||||||
|
|
||||||
|
Error:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
example: "Missing required fields: id, priority"
|
||||||
Reference in New Issue
Block a user