Skip to main content

QR-Image – JavaScript

// QR-Image V25.12.009 -> optional festes Gast-WLAN-Passwort ergänzt, täglicher Cron nur bei Zufallspasswort aktiv.
// Da die FRITZ!Box weiterhin kein VLAN bietet, kann das Gast-WLAN fest als Workaround genutzt werden.
//
// Nach jedem Neustart des TR-064 Adapter und ersten Start des Skripts war der DP "wlanGuestPassword" leer.
// Der Fehler war ein Timing-Problem. Das Passwort wurde gesetzt, aber der TR-064 Adapter verarbeitete es zu langsam.
// Durch den setState-Callback wird sichergestellt, dass der QR-Code erst nach erfolgreichem Speichern des Passworts generiert wird.
//
// Quelle:
// https://www.npmjs.com/package/qr-image
// https://forum.iobroker.net/topic/4574/fritzbox-wlan-passwort-%C3%A4ndern/49
// Das Modul 'qr-image' muss in den JS Adapter (Instanzen) eingetragen werden!
//
// Der ioBroker TR-064 Adapter bietet keine Möglichkeit, die Verschlüsselungsmethode des Gast-WLANs (z.B. "WPA2" oder "WPA2 + WPA3") zu ändern.
// Die Konfiguration der Verschlüsselung erfolgt über die Weboberfläche der FRITZ!Box.

var MySSID = "HalloGast";                            // SSID Name
var MyVisibility = "n";                              // Hidden SSID?
var cronStr = "1 4 * * *";                           // Script wird jeden Tag um 04:01 ausgeführt (nur bei Zufallspasswort)
// var cronStr = "1 4 * * 1";                        // Einmal je Woche  um 04:01 | 1 = Montag (0 = Sonntag, 6 = Samstag)
// var cronStr = "1 4 1 * *";                        // Am 1. Tag jedes Monats um 04:01

var idQRZiel = "javascript.0.QR-Code.Gast";          // Zieldatenpunkt für QR-Code
var IdGPasswd = "tr-064.0.states.wlanGuestPassword"; // Datenpunkt für WLAN-Gastpasswort
var passwordLength = 12;                             // Länge des Passworts (mind. 8 Zeichen, weniger nimmt die FRITZ!Box nicht an!)

// Festes Passwort (leer lassen => Zufallspasswort wird erstellt)
var fixedGuestPassword = "";                         // z.B. "MeinDauerPasswort123!"

if (MyVisibility === "y") {
    var MyHidden = "H:true";
} else {
    MyHidden = "";
}

// Erstelle den Datenpunkt für den QR-Code, falls nicht vorhanden
createState(idQRZiel, "", {
    name: 'QR-Code für Gastpasswort',
    desc: 'QR-Code für Gastpasswort',
    type: 'string',
    role: 'value'
});

// Methode zur Erstellung eines zufälligen Passworts (keine Sonderzeichen am Anfang oder Ende)
function randomString(length) {
    var result = '';
    var lowerChars = 'abcdefghijklmnopqrstuvwxyz';
    var upperChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var digits = '0123456789';
    var specialChars = '!?._-';
    var allChars = lowerChars + upperChars + digits + specialChars;

    // Ersten und letzten Charakter setzen (keine Sonderzeichen)
    result += lowerChars.charAt(Math.floor(Math.random() * lowerChars.length)); // Kleinbuchstabe am Anfang

    // Mittelteil auffüllen (inkl. Sonderzeichen)
    for (var i = 1; i < length - 1; i++) {
        var char = allChars.charAt(Math.floor(Math.random() * allChars.length));
        result += char;
    }

    // Letztes Zeichen (keine Sonderzeichen, aber Klein-/Großbuchstabe oder Zahl)
    result += lowerChars.concat(upperChars, digits).charAt(
        Math.floor(Math.random() * (lowerChars.length + upperChars.length + digits.length))
    );

    // Stelle sicher, dass mindestens ein Sonderzeichen enthalten ist (außer am Anfang und Ende)
    var specialIndex = Math.floor(Math.random() * (length - 2)) + 1;
    var specialChar = specialChars.charAt(Math.floor(Math.random() * specialChars.length));
    result = result.substring(0, specialIndex) + specialChar + result.substring(specialIndex + 1);

    return result;
}

// Methode zur Erstellung des QR-Codes
var qr;
try {
    qr = require('qr-image');
} catch (err) {
    log('Modul qr-image konnte nicht geladen werden: ' + err);
}

function createQRcode() {
    if (!qr) return;

    var NewPasswd;
    if (fixedGuestPassword !== null && fixedGuestPassword !== undefined && String(fixedGuestPassword).trim() !== "") {
        NewPasswd = String(fixedGuestPassword);
    } else {
        NewPasswd = randomString(passwordLength);
    }

    setState(IdGPasswd, NewPasswd, false, function(err) {
        if (err) {
            log('Fehler beim Setzen des Passworts: ' + err);
        } else {
            setTimeout(function() {
                setState(IdGPasswd, NewPasswd, true);
            }, 2000);

            var svg_string = qr.imageSync(
                'WIFI:S:' + MySSID + ';T:WPA2;P:' + NewPasswd + ';' + MyHidden + ';',
                { type: 'svg' }
            );
            setState(idQRZiel, svg_string, true);
        }
    });
}

// Erstelle den QR-Code einmalig beim ersten Start des Scripts
createQRcode();

// Planmäßige Wiederholungen nur bei Zufallspasswort
// Der Cron-Job wird nur registriert, wenn kein festes Passwort gesetzt ist:
if (fixedGuestPassword === null || fixedGuestPassword === undefined || String(fixedGuestPassword).trim() === "") {
    schedule(cronStr, createQRcode);
}