// Legt in einer frischen Home-Assistant-Instanz einen Testnutzer an und gibt ein // langlebiges Zugriffstoken auf der Standardausgabe aus. Meldungen gehen auf die // Fehlerausgabe, damit das aufrufende Skript nur das Token einliest. // Aufruf: node einrichten.mjs http://localhost:18123 const BASIS = process.argv[2] ?? "http://localhost:18123" const CLIENT_ID = BASIS + "/" const BENUTZER = "test" const PASSWORT = "testtest123" const melden = (text) => process.stderr.write(` ${text}\n`) async function jsonPost(pfad, koerper, token) { const kopf = { "Content-Type": "application/json" } if (token) kopf.Authorization = `Bearer ${token}` const antwort = await fetch(BASIS + pfad, { method: "POST", headers: kopf, body: JSON.stringify(koerper), }) const text = await antwort.text() if (!antwort.ok) throw new Error(`${pfad} -> ${antwort.status}: ${text.slice(0, 200)}`) return text ? JSON.parse(text) : {} } // 1. Onboarding-Schritt "user" const { auth_code: authCode } = await jsonPost("/api/onboarding/users", { client_id: CLIENT_ID, name: "Test Nutzer", username: BENUTZER, password: PASSWORT, language: "de", }) melden("Nutzer angelegt") // 2. Auth-Code gegen ein kurzlebiges Zugriffstoken tauschen const tokenAntwort = await fetch(BASIS + "/auth/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", code: authCode, client_id: CLIENT_ID, }).toString(), }) const token = await tokenAntwort.json() if (!token.access_token) throw new Error("kein access_token: " + JSON.stringify(token)) melden("Zugriffstoken erhalten") // 3. Restliche Onboarding-Schritte abschliessen (Fehler sind unkritisch) for (const [pfad, koerper] of [ ["/api/onboarding/core_config", {}], ["/api/onboarding/analytics", {}], ["/api/onboarding/integration", { client_id: CLIENT_ID, redirect_uri: CLIENT_ID }], ]) { try { await jsonPost(pfad, koerper, token.access_token) } catch { // Schritt bereits erledigt oder in dieser Version nicht vorhanden } } // 4. Langlebiges Token ueber die WebSocket-API erzeugen const wsUrl = BASIS.replace(/^http/, "ws") + "/api/websocket" const llat = await new Promise((aufloesen, ablehnen) => { const ws = new WebSocket(wsUrl) const zeitgeber = setTimeout(() => { ablehnen(new Error("Zeitueberschreitung beim Erzeugen des Tokens")) ws.close() }, 20000) ws.onmessage = (nachricht) => { const daten = JSON.parse(nachricht.data) if (daten.type === "auth_required") { ws.send(JSON.stringify({ type: "auth", access_token: token.access_token })) } else if (daten.type === "auth_ok") { ws.send( JSON.stringify({ id: 1, type: "auth/long_lived_access_token", client_name: `DataMetric360 Test ${Date.now()}`, lifespan: 365, }), ) } else if (daten.type === "result") { clearTimeout(zeitgeber) if (daten.success) aufloesen(daten.result) else ablehnen(new Error(JSON.stringify(daten.error))) ws.close() } else if (daten.type === "auth_invalid") { clearTimeout(zeitgeber) ablehnen(new Error("auth_invalid")) ws.close() } } ws.onerror = () => { clearTimeout(zeitgeber) ablehnen(new Error("WebSocket-Verbindung fehlgeschlagen")) } }) melden("langlebiges Token erzeugt") process.stdout.write(llat)