Skip to content
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. UNIFI API Voucher Skript

NEWS

  • Wartung am 15.11. – Forum ab 22:00 Uhr nicht erreichbar
    BluefoxB
    Bluefox
    12
    2
    277

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.0k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.7k

UNIFI API Voucher Skript

UNIFI API Voucher Skript

Scheduled Pinned Locked Moved JavaScript
1 Posts 1 Posters 125 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    paulkerl
    wrote on last edited by
    #1

    Hallo zusammen,

    ich habe mal GEMINI bemüht mir ein Voucher Skript für die Unifi API zu bauen, das in IOBROKER läuft. Vielleicht kanns wer brauchen.

    Funktionen deines WLAN-Voucher-Generierungs-Skripts

    Dieses ioBroker-Skript ist dein persönlicher Assistent zur automatischen Erstellung und Verwaltung von WLAN-Vouchern für dein UniFi-Netzwerk, direkt aus deiner ioBroker-Steuerungsoberfläche (VIS) heraus.


    Was das Skript macht:

    1. Vorbereitung und Einrichtung:

      • Beim Start sorgt das Skript dafür, dass alle notwendigen "Schalter" und "Anzeigefelder" in ioBroker existieren. Diese findest du unter 0_userdata.0.WIFIVoucher. Dazu gehören Felder, um einzustellen, wie viele Nutzer einen Voucher verwenden dürfen (max_users) und wie lange er gültig ist (valid_days), sowie ein "Start"-Knopf (generate) und ein Feld, das dir den fertigen Code anzeigt (actual_voucher).
    2. WLAN-Voucher generieren:

      • Wenn du in deiner ioBroker-Ansicht den "Start"-Knopf (0_userdata.0.WIFIVoucher.generate) betätigst, tritt das Skript in Aktion.
      • Es liest deine zuvor eingestellten Werte für die maximale Nutzerzahl und die Gültigkeitsdauer aus den entsprechenden Feldern.
      • Mit diesen Informationen sendet das Skript eine verschlüsselte und authentifizierte Anfrage an deine UniFi-Hardware (den UniFi Controller, z.B. deine USG Max). Dies geschieht direkt und sicher, ohne Umwege über externe Programme wie curl.
      • Deine UniFi-Hardware erstellt daraufhin einen neuen WLAN-Voucher.
    3. Voucher-Code anzeigen und formatieren:

      • Sobald der neue Voucher von UniFi generiert wurde, empfängt das Skript den Voucher-Code.
      • Es formatiert diesen Code sofort, sodass er leichter zu lesen ist – beispielsweise wird aus "1234567890" ein "12345-67890".
      • Der so formatierte Code wird dann in deinem ioBroker-Anzeigefeld (0_userdata.0.WIFIVoucher.actual_voucher) dargestellt, sodass du ihn direkt ablesen und weitergeben kannst.
    4. Automatische Code-Anzeige und Zurücksetzung:

      • Nachdem der Voucher-Code angezeigt wurde, startet das Skript einen 5-minütigen Countdown.
      • Während dieser Zeit bleibt der Code sichtbar. Wenn die 5 Minuten abgelaufen sind, wird der angezeigte Voucher-Code automatisch durch eine Reihe von Nullen ("00000-00000") ersetzt. Das sorgt dafür, dass nicht dauerhaft alte Codes sichtbar bleiben und du immer den aktuellen Code im Blick hast.
      • Wichtig: Solltest du einen neuen Voucher generieren, während der alte Code noch angezeigt wird, wird der Countdown sofort zurückgesetzt und ein neuer 5-Minuten-Zeitraum für den neuen Code gestartet. So wird sichergestellt, dass immer der aktuellste Code für 5 Minuten sichtbar ist.
    5. Bereitschaft für den nächsten Voucher:

      • Nachdem der Generierungsprozess abgeschlossen ist (egal ob erfolgreich oder mit einem Problem), setzt das Skript den "Start"-Knopf (0_userdata.0.WIFIVoucher.generate) in ioBroker automatisch wieder auf seine Ausgangsposition zurück. So ist er bereit für die nächste Voucher-Erstellung.
    // Direkte Nutzung des HTTPS-Moduls für API-Anfragen
    const https = require('https');
    
    // --- Konfiguration ---
    // API-Endpunkt für deine UniFi USG MAX und spezifische Site-ID
    const API_URL_BASE = "https://192.168.xxx.xxx/proxy/network/integration/v1/sites/*site-id*";
    // Dein UniFi API-Schlüssel
    const API_KEY = "*API Token*";
    // Fester Name für automatisch generierte Voucher im UniFi Controller
    const VOUCHER_NAME = "autogen";
    
    // --- Datenpunkte definieren ---
    const DP_BASE = "0_userdata.0.WIFIVoucher";
    const DP_GENERATE = DP_BASE + ".generate";       // Boolean: TRUE zum Generieren eines Vouchers
    const DP_ACTUAL_VOUCHER = DP_BASE + ".actual_voucher"; // String: Speichert den generierten Voucher-Code
    const DP_MAX_USERS = DP_BASE + ".max_users";     // Number: Maximale Nutzer pro Voucher
    const DP_VALID_DAYS = DP_BASE + ".valid_days";   // Number: Gültigkeitsdauer in Tagen
    
    // --- Timer-Variable für das automatische Überschreiben ---
    let voucherTimeout = null;
    
    // --- Funktion zum Erstellen oder Aktualisieren von Datenpunkten ---
    async function createDataPoints() {
        log("Prüfe und erstelle Datenpunkte...", "info");
    
        // Datenpunkt zum Triggern der Voucher-Generierung
        await createStateAsync(DP_GENERATE, false, {
            name: "WLAN Voucher generieren",
            desc: "Setzen Sie auf TRUE, um einen neuen WLAN Voucher zu generieren.",
            type: "boolean",
            role: "button",
            read: true,
            write: true
        });
    
        // Datenpunkt zum Speichern des generierten Voucher-Codes
        await createStateAsync(DP_ACTUAL_VOUCHER, "", {
            name: "Aktueller WLAN Voucher Code",
            desc: "Der zuletzt generierte WLAN Voucher Code.",
            type: "string",
            role: "value",
            read: true,
            write: false // Nur lesbar durch VIS, geschrieben vom Skript
        });
    
        // Datenpunkt für die maximale Anzahl der Nutzer pro Voucher
        await createStateAsync(DP_MAX_USERS, 1, { // Standardwert: 1 Nutzer
            name: "Max. Nutzer pro Voucher",
            desc: "Die maximale Anzahl von Geräten, die den Voucher nutzen können (UniFi-Max: 10).",
            type: "number",
            role: "value",
            read: true,
            write: true,
            min: 1,
            max: 10 // Übliches Maximum in UniFi für Guest Limit
        });
    
        // Datenpunkt für die Gültigkeitsdauer in Tagen
        // Beachte: UniFi API hat ein internes Limit für timeLimitMinutes (z.B. 43200 Stunden = 1800 Tage).
        // Ein höherer Wert wird vom Controller wahrscheinlich auf sein internes Maximum begrenzt.
        await createStateAsync(DP_VALID_DAYS, 1, { // Standardwert: 1 Tag
            name: "Gültigkeit des Vouchers (Tage)",
            desc: "Die Gültigkeitsdauer des Vouchers in Tagen (UniFi-Limit beachten).",
            type: "number",
            role: "value",
            read: true,
            write: true,
            min: 1,
            max: 128000 // Maximalwert laut deiner Anforderung
        });
    
        log("Datenpunkte geprüft/erstellt.", "info");
    }
    
    // --- Funktion zum Formatieren des Voucher-Codes (5 Ziffern - 5 Ziffern) ---
    function formatVoucherCode(code) {
        if (typeof code !== 'string' || code.length !== 10) {
            return code; // Gib den Code unverändert zurück, wenn er nicht 10 Ziffern lang ist
        }
        return code.substring(0, 5) + '-' + code.substring(5, 10);
    }
    
    // --- Funktion zum Zurücksetzen des Voucher-Codes nach Timeout ---
    function resetVoucherCode() {
        log("Setze Voucher-Code auf '00000-00000' zurück.", "info");
        setState(DP_ACTUAL_VOUCHER, "00000-00000", true); // Bestätigen, dass der Wert geschrieben wurde
    }
    
    // --- Hauptfunktion zum Generieren eines einzelnen Vouchers ---
    async function generateVoucher() {
        log("Starte Voucher-Generierung...", "info");
    
        // **WICHTIG:** Alten Timer stoppen, falls vorhanden
        if (voucherTimeout) {
            clearTimeout(voucherTimeout);
            log("Vorherigen Voucher-Timeout gestoppt.", "debug");
        }
    
        // Lese die aktuellen Werte aus den Datenpunkten
        const maxUsersState = await getStateAsync(DP_MAX_USERS);
        const validDaysState = await getStateAsync(DP_VALID_DAYS);
    
        // Prüfe, ob die Datenpunkte gültige Werte liefern
        if (!maxUsersState || maxUsersState.val === null || !validDaysState || validDaysState.val === null) {
            log("Fehler: Datenpunkte für max. Nutzer oder Gültigkeit konnten nicht gelesen werden.", "warn");
            setState(DP_GENERATE, false); // Setze Schalter zurück, da keine gültigen Daten
            return;
        }
    
        const maxUsers = maxUsersState.val;
        const validDays = validDaysState.val;
        // Umrechnung von Tagen in Minuten, wie von der UniFi API erwartet
        const timeLimitMinutes = validDays * 24 * 60;
    
        // Erstelle das JSON-Objekt für den POST-Request-Body
        const postDataObj = {
            name: VOUCHER_NAME,
            authorizedGuestLimit: maxUsers,
            timeLimitMinutes: timeLimitMinutes
        };
        const postData = JSON.stringify(postDataObj); // Konvertiere Objekt in JSON-String
    
        // Manuelle URL-Zerlegung für das https-Modul
        const fullUrl = API_URL_BASE + '/hotspot/vouchers';
        const parts = fullUrl.match(/^https?:\/\/([^/:]+)(:\d+)?(.*)$/);
    
        if (!parts) {
            log(`Fehler: Ungültige URL-Formatierung für ${fullUrl}. Bitte URL prüfen.`, "error");
            setState(DP_GENERATE, false);
            return;
        }
    
        const hostname = parts[1];
        const port = parts[2] ? parseInt(parts[2].substring(1)) : 443; // Standard-HTTPS-Port 443
        const path = parts[3];
    
        // Optionen für den HTTPS-Request
        const options = {
            hostname: hostname,
            port: port,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(postData), // Notwendig für POST-Requests
                'Accept': 'application/json',
                'X-API-Key': API_KEY // Dein API-Schlüssel zur Authentifizierung
            },
            rejectUnauthorized: false // Wichtig: Deaktiviert die Zertifikatsprüfung für selbstsignierte UniFi-Zertifikate
        };
    
        log(`Sende HTTP POST-Request an: ${fullUrl}`, "debug");
        log(`Post-Daten: ${postData}`, "debug");
    
        try {
            const responseData = await new Promise((resolve, reject) => {
                const req = https.request(options, (res) => {
                    let data = '';
    
                    res.on('data', (chunk) => {
                        data += chunk;
                    });
    
                    res.on('end', () => {
                        if (res.statusCode >= 200 && res.statusCode < 300) {
                            resolve(data);
                        } else {
                            reject(new Error(`Server responded with status code ${res.statusCode}: ${data}`));
                        }
                    });
                });
    
                req.on('error', (e) => {
                    reject(e);
                });
    
                req.write(postData);
                req.end();
            });
    
            // Verarbeitung der erfolgreichen API-Antwort
            log("API-Antwort erhalten: " + responseData, "debug");
            const result = JSON.parse(responseData);
    
            if (result && Array.isArray(result.vouchers) && result.vouchers.length > 0) {
                const rawVoucherCode = result.vouchers[0].code;
                const formattedVoucherCode = formatVoucherCode(rawVoucherCode); // Voucher-Code formatieren
    
                log(`Neuer Voucher erfolgreich generiert: ${formattedVoucherCode}`, "info");
                // Speichere den formatierten Code im ioBroker Datenpunkt
                setState(DP_ACTUAL_VOUCHER, formattedVoucherCode, true); // Bestätigen, dass der Wert geschrieben wurde
    
                // **Neuer Timer starten**
                voucherTimeout = setTimeout(resetVoucherCode, 5 * 60 * 1000); // 5 Minuten = 5 * 60 * 1000 ms
                log("Timeout für Voucher-Rücksetzung gestartet (5 Minuten).", "debug");
    
            } else {
                log("Unerwartete API-Antwort Struktur bei Voucher-Generierung: " + responseData, "warn");
                if (result && result.statusCode) {
                    log(`API Fehler-Code: ${result.statusCode}, Nachricht: ${result.message || 'Keine Nachricht'}`, "error");
                }
            }
    
        } catch (e) {
            log(`Ausnahme beim Generieren des Vouchers: ${e.message}. Stack: ${e.stack}`, "error");
        } finally {
            setState(DP_GENERATE, false, true); // Setzt den Trigger-Datenpunkt immer auf FALSE zurück
        }
    }
    
    // --- Skriptstart und Trigger-Definitionen ---
    
    // Dieser Listener sorgt dafür, dass die Datenpunkte initialisiert werden,
    // wenn das Skript aktiviert oder neu gestartet wird.
    on({ id: "javascript.0.scriptEnabled.script.js." + instance + ".WLAN_Voucher_Generator", change: "ne" }, async function (obj) {
        if (obj.state.val === true) {
            log("Skript gestartet. Datenpunkte werden initialisiert.", "info");
            await createDataPoints();
        }
    });
    
    // Dieser Trigger reagiert auf Änderungen des "generate"-Datenpunkts.
    // Wenn dieser auf TRUE gesetzt wird, startet die Voucher-Generierung.
    on({ id: DP_GENERATE, change: "ne", val: true }, async function (obj) {
        log("Datenpunkt " + DP_GENERATE + " auf TRUE gesetzt. Starte Voucher-Generierung...", "info");
        await generateVoucher();
    });
    
    // Initialer Aufruf zum Erstellen der Datenpunkte beim Skriptstart
    createDataPoints();
    
    1 Reply Last reply
    0
    Reply
    • Reply as topic
    Log in to reply
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes


    Support us

    ioBroker
    Community Adapters
    Donate

    200

    Online

    32.4k

    Users

    81.3k

    Topics

    1.3m

    Posts
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    ioBroker Community 2014-2025
    logo
    • Login

    • Don't have an account? Register

    • Login or register to search.
    • First post
      Last post
    0
    • Recent
    • Tags
    • Unread 0
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe