7.4 KiB
Home Automation API Client
Wiederverwendbare JavaScript-API-Client-Bibliothek für das Home Automation UI.
Installation
Füge die folgenden Script-Tags in deine HTML-Seiten ein:
<script src="/static/types.js"></script>
<script src="/static/api-client.js"></script>
Konfiguration
Der API-Client nutzt window.API_BASE, das vom Backend gesetzt wird:
window.API_BASE = '{{ api_base }}'; // Jinja2 template
Verwendung
Globale Instanz
Der API-Client erstellt automatisch eine globale Instanz window.apiClient:
// Layout abrufen
const layout = await window.apiClient.getLayout();
// Geräte abrufen
const devices = await window.apiClient.getDevices();
// Gerätestatus abrufen
const state = await window.apiClient.getDeviceState('kitchen_light');
// Gerätesteuerung
await window.apiClient.setDeviceState('kitchen_light', 'light', {
power: true,
brightness: 80
});
Verfügbare Methoden
getLayout(): Promise<Layout>
Lädt die Layout-Daten (Räume und ihre Geräte).
const layout = await window.apiClient.getLayout();
// { rooms: [{name: "Küche", devices: ["kitchen_light", ...]}, ...] }
getDevices(): Promise<Device[]>
Lädt alle Geräte mit ihren Features.
const devices = await window.apiClient.getDevices();
// [{device_id: "...", name: "...", type: "light", features: {...}}, ...]
getDeviceState(deviceId): Promise<DeviceState>
Lädt den aktuellen Status eines Geräts.
const state = await window.apiClient.getDeviceState('kitchen_light');
// {power: true, brightness: 80, ...}
getAllStates(): Promise<Object>
Lädt alle Gerätestatus auf einmal.
const states = await window.apiClient.getAllStates();
// {"kitchen_light": {power: true, ...}, "thermostat_1": {...}, ...}
setDeviceState(deviceId, type, payload): Promise<void>
Sendet einen Befehl an ein Gerät.
// Licht einschalten
await window.apiClient.setDeviceState('kitchen_light', 'light', {
power: true,
brightness: 80
});
// Thermostat einstellen
await window.apiClient.setDeviceState('thermostat_1', 'thermostat', {
target_temp: 22.5
});
// Rollladen steuern
await window.apiClient.setDeviceState('cover_1', 'cover', {
position: 50
});
getDeviceRoom(deviceId): Promise<{room: string}>
Ermittelt den Raum eines Geräts.
const { room } = await window.apiClient.getDeviceRoom('kitchen_light');
// {room: "Küche"}
getScenes(): Promise<Scene[]>
Lädt alle verfügbaren Szenen.
const scenes = await window.apiClient.getScenes();
activateScene(sceneId): Promise<void>
Aktiviert eine Szene.
await window.apiClient.activateScene('evening');
Realtime-Updates (SSE)
connectRealtime(onEvent, onError): EventSource
Verbindet sich mit dem SSE-Stream für Live-Updates.
window.apiClient.connectRealtime(
(event) => {
console.log('Update:', event.device_id, event.state);
// event = {device_id: "...", type: "state", state: {...}}
},
(error) => {
console.error('Connection error:', error);
}
);
onDeviceUpdate(deviceId, callback): Function
Registriert einen Listener für spezifische Geräte-Updates.
// Für ein bestimmtes Gerät
const unsubscribe = window.apiClient.onDeviceUpdate('kitchen_light', (event) => {
console.log('Kitchen light changed:', event.state);
updateUI(event.state);
});
// Für alle Geräte
const unsubscribeAll = window.apiClient.onDeviceUpdate(null, (event) => {
console.log('Any device changed:', event.device_id, event.state);
});
// Später: Listener entfernen
unsubscribe();
disconnectRealtime(): void
Trennt die SSE-Verbindung und entfernt alle Listener.
window.apiClient.disconnectRealtime();
Helper-Methoden
findDevice(devices, deviceId): Device|null
Findet ein Gerät in einem Array.
const devices = await window.apiClient.getDevices();
const device = window.apiClient.findDevice(devices, 'kitchen_light');
findRoom(layout, roomName): Room|null
Findet einen Raum im Layout.
const layout = await window.apiClient.getLayout();
const room = window.apiClient.findRoom(layout, 'Küche');
getDevicesForRoom(layout, devices, roomName): Device[]
Gibt alle Geräte eines Raums zurück.
const layout = await window.apiClient.getLayout();
const devices = await window.apiClient.getDevices();
const kitchenDevices = window.apiClient.getDevicesForRoom(layout, devices, 'Küche');
api(path): string
Konstruiert eine vollständige API-URL.
const url = window.apiClient.api('/devices');
// "http://172.19.1.11:8001/devices"
Backward Compatibility
Die globale api() Funktion ist weiterhin verfügbar:
function api(url) {
return window.apiClient.api(url);
}
Typen (JSDoc)
Die Datei types.js enthält JSDoc-Definitionen für alle API-Typen:
Room- Raum mit GerätenLayout- Layout-StrukturDevice- GerätedatenDeviceFeatures- Geräte-FeaturesDeviceState- Gerätestatus (Light, Thermostat, Contact, etc.)RealtimeEvent- SSE-Event-FormatScene- Szenen-Definition*Payload- Command-Payloads für verschiedene Gerätetypen
Diese ermöglichen IDE-Autocomplete und Type-Checking in modernen Editoren (VS Code, WebStorm).
Beispiel: Vollständige Seite
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>My Page</title>
<script src="/static/types.js"></script>
<script src="/static/api-client.js"></script>
</head>
<body>
<div id="status"></div>
<button id="toggle">Toggle Light</button>
<script>
window.API_BASE = 'http://172.19.1.11:8001';
const deviceId = 'kitchen_light';
async function init() {
// Load initial state
const state = await window.apiClient.getDeviceState(deviceId);
updateUI(state);
// Listen for updates
window.apiClient.onDeviceUpdate(deviceId, (event) => {
updateUI(event.state);
});
// Connect to realtime
window.apiClient.connectRealtime((event) => {
console.log('Event:', event);
});
// Handle button clicks
document.getElementById('toggle').onclick = async () => {
const currentState = await window.apiClient.getDeviceState(deviceId);
await window.apiClient.setDeviceState(deviceId, 'light', {
power: !currentState.power
});
};
}
function updateUI(state) {
document.getElementById('status').textContent =
state.power ? 'ON' : 'OFF';
}
init();
</script>
</body>
</html>
Error Handling
Alle API-Methoden werfen Exceptions bei Fehlern:
try {
const state = await window.apiClient.getDeviceState('invalid_id');
} catch (error) {
console.error('API error:', error);
showErrorMessage(error.message);
}
Auto-Reconnect
Der SSE-Client versucht automatisch, nach 5 Sekunden wieder zu verbinden, wenn die Verbindung abbricht.
Verwendete Technologien
- Fetch API - Für HTTP-Requests
- EventSource - Für Server-Sent Events
- JSDoc - Für Type Definitions
- ES6+ - Modern JavaScript (Class, async/await, etc.)