Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. UNIFI API Voucher Skript

NEWS

  • Neuer ioBroker-Blog online: Monatsrückblick März/April 2026
    BluefoxB
    Bluefox
    8
    1
    1.6k

  • Verwendung von KI bitte immer deutlich kennzeichnen
    HomoranH
    Homoran
    10
    1
    671

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    18
    1
    1.2k

UNIFI API Voucher Skript

Geplant Angeheftet Gesperrt Verschoben JavaScript
2 Beiträge 2 Kommentatoren 249 Aufrufe 2 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • P Offline
    P Offline
    paulkerl
    schrieb am zuletzt editiert von
    #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 Antwort Letzte Antwort
    0
    • Elektrofix-OLE Offline
      Elektrofix-OLE Offline
      Elektrofix-OL
      schrieb am zuletzt editiert von Elektrofix-OL
      #2

      Ein gutes Skript und genau das was ich suchte. Jedoch hatte Ich Schwierigkeiten mein site-ID herauszufinden und daher funktionierte das Skript nicht.
      Ich habe dann ein kleines Blockly geschrieben und dann folgendes in den auszuführenden Befehl geschrieben: curl -k -X GET "https://192.168.x.y/proxy/network/integration/v1/sites" -H "X-API-KEY: API Token" -H 'Accept: application/json'
      image.png
      Zurück kommt dann im Log ein String: {...[{"id":"site-id",...]}
      Jetzt tut es das was es soll.

      Gruß aus dem Norden und danke für's Posten

      Ps: Zeile 194 kann die Verschwindezeit geändert werden und in Zeile 86 kann auch ein " " eingegeben werden um alle auszublenden.

      1 Antwort Letzte Antwort
      0

      Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

      Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

      Mit deinem Input könnte dieser Beitrag noch besser werden 💗

      Registrieren Anmelden
      Antworten
      • In einem neuen Thema antworten
      Anmelden zum Antworten
      • Älteste zuerst
      • Neuste zuerst
      • Meiste Stimmen


      Support us

      ioBroker
      Community Adapters
      Donate

      538

      Online

      32.9k

      Benutzer

      83.0k

      Themen

      1.3m

      Beiträge
      Community
      Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
      ioBroker Community 2014-2025
      logo
      • Anmelden

      • Du hast noch kein Konto? Registrieren

      • Anmelden oder registrieren, um zu suchen
      • Erster Beitrag
        Letzter Beitrag
      0
      • Home
      • Aktuell
      • Tags
      • Ungelesen 0
      • Kategorien
      • Unreplied
      • Beliebt
      • GitHub
      • Docu
      • Hilfe