// --- KONFIGURATION DER DATENPUNKTE --- const PREFIX = '0_userdata.0.vis.Alarmanlage.Keypad.'; const ID_TASTE_GEKLICKT = PREFIX + 'Zahl1'; // Input der Tasten (Ziffern) aus VIS-2 -> Erwartet STRING const ID_PIN_VIS_PUNKTE = PREFIX + 'Zahl2'; // Das Display für VIS (zeigt Punkte oder Text) -> Erwartet STRING const ID_RESET_TASTE = PREFIX + 'Zahl3'; // Löschen-Taste (Del) aus VIS-2 -> Erwartet NUMBER const ID_WUNSCH_PIN = '0000'; // Deine feste Geheim-PIN // HIER DEINE ALARMANLAGEN-LISTE EINTRAGEN: const ID_ALARM_STATUS = 'alarm.0.use.list'; // TELEGRAM INSTANZ const ID_TELEGRAM_1 = 'telegram.0'; // PARAMETER FÜR DIE SPERRE const MAX_FEHLVERSUCHE = 3; const SPERR_ZEIT_MS = 300000; // 5 Minuten Sperre bei 3 Fehlversuchen (5 * 60 * 1000 ms) // INTERNE VARIABLEN let fehlerZaehler = 0; let istGesperrt = false; let sperrTimer = null; let internerKlartext = ''; // Speichert den eingegebenen Code unsichtbar im RAM // Initialisierung beim Skriptstart (Typen exakt angepasst) setState(ID_TASTE_GEKLICKT, ''); // Als String initialisieren setState(ID_RESET_TASTE, 0); // Als Zahl (Number) initialisieren setState(ID_PIN_VIS_PUNKTE, 'Code'); // ========================================== // 1. TRIGGER: ZIFFERN-EINGABE AUS VIS-2 (Zahl1) // ========================================== on({ id: ID_TASTE_GEKLICKT, change: "any" }, async function (obj) { let taste = obj.state.val; // Abbrechen, wenn das Feld geleert wurde oder ungültig ist if (taste === '' || taste === null || taste === undefined || taste === false || taste === 0 || taste === '0') return; // Falls das Keypad gesperrt ist, Eingabe blockieren und Feld leeren if (istGesperrt) { setState(ID_PIN_VIS_PUNKTE, "GESPERRT"); setState(ID_TASTE_GEKLICKT, ''); return; } // Ziffer an den internen Klartext anhängen internerKlartext += taste.toString(); console.debug('Interner Code-Stand: ' + internerKlartext); // Punkte für das VIS-Display generieren let punkteString = "•".repeat(internerKlartext.length); setState(ID_PIN_VIS_PUNKTE, punkteString); // Eingang direkt wieder als Leerstring nullen, damit dieselbe Taste erneut gedrückt werden kann setState(ID_TASTE_GEKLICKT, ''); // Sofort prüfen, wenn die Länge der Wunsch-PIN erreicht ist (4 Stellen) if (internerKlartext.length >= ID_WUNSCH_PIN.length) { pruefePin(internerKlartext); } }); // ========================================== // 2. TRIGGER: LÖSCHEN-TASTE AUS VIS-2 (Zahl3) // ========================================== on({ id: ID_RESET_TASTE, change: 'ne' }, async function (obj) { if (istGesperrt) return; // Auslösen, wenn die Löschen-Taste gedrückt wird (Wert wird 1 oder true) if (obj.state && (obj.state.val == 1 || obj.state.val === true || obj.state.val === '1')) { internerKlartext = ''; // Internen Speicher leeren setState(ID_PIN_VIS_PUNKTE, 'Eingabe gelöscht'); console.debug('Alarmanlage: PIN-Eingabe manuell zurückgesetzt.'); // Nach kurzer Zeit das Display wieder auf "Code" stellen setTimeout(function() { if (!istGesperrt && internerKlartext === '') { setState(ID_PIN_VIS_PUNKTE, 'Code'); } }, 1500); // Löschen-Taste im ioBroker wieder auf die Zahl 0 (ohne Anführungszeichen) zurücksetzen setStateDelayed(ID_RESET_TASTE, 0, 1000, false); } }); // ========================================== // 3. FUNKTION: PIN-PRÜFUNG // ========================================== function pruefePin(eingabe) { if (istGesperrt) return; // FALL A: PIN ist korrekt if (eingabe === ID_WUNSCH_PIN) { console.debug('Alarmanlage: PIN korrekt!'); fehlerZaehler = 0; // Telegram-Nachricht bei Erfolg (Text wunschgemäß angepasst) sendTo(ID_TELEGRAM_1, 'send', { text: '🔑 Alarmanlage deaktiviert: Erfolgreiche PIN-Eingabe am Keypad.' }); // Status der Alarmanlage umschalten (0 = aus, 1 = an) let currentStatus = getState(ID_ALARM_STATUS).val; if (currentStatus == 1 || currentStatus == 2 || currentStatus == 3) { setState(ID_ALARM_STATUS, 0); } else { setState(ID_ALARM_STATUS, 1); } setState(ID_PIN_VIS_PUNKTE, 'Code o.k.'); // Nach 3 Sekunden Display zurücksetzen und Zwischenspeicher leeren setTimeout(function() { internerKlartext = ''; setState(ID_PIN_VIS_PUNKTE, 'Code'); }, 3000); } // FALL B: PIN ist falsch else { fehlerZaehler++; internerKlartext = ''; // Code sofort wieder löschen console.warn("Alarmanlage: Falsche PIN! Fehlversuch " + fehlerZaehler + " von " + MAX_FEHLVERSUCHE); // Keypad komplett sperren bei zu vielen Fehlversuchen if (fehlerZaehler >= MAX_FEHLVERSUCHE) { istGesperrt = true; setState(ID_PIN_VIS_PUNKTE, "GESPERRT"); // Kritischer Telegram-Alarm sendTo(ID_TELEGRAM_1, 'send', { text: '🚨 ALARM: Das Keypad der Alarmanlage wurde nach ' + MAX_FEHLVERSUCHE + ' Fehlversuchen für 5 Minuten GESPERRT!' }); // Timer für automatische Entsperrung starten if (sperrTimer) clearTimeout(sperrTimer); sperrTimer = setTimeout(function() { entsperreKeypad("Automatische Zeitfreigabe"); }, SPERR_ZEIT_MS); } else { // Normale Telegram-Warnung, solange noch Versuche übrig sind sendTo(ID_TELEGRAM_1, 'send', { text: '⚠ Warnung: Falscher Code an der Alarmanlage! (Versuch ' + fehlerZaehler + '/' + MAX_FEHLVERSUCHE + ')' }); setState(ID_PIN_VIS_PUNKTE, 'Falscher Code!'); setTimeout(function() { if (!istGesperrt && internerKlartext === '') { setState(ID_PIN_VIS_PUNKTE, 'Code'); } }, 2000); } } } // ========================================== // 4. HILFSFUNKTION: ENTSPERREN // ========================================== function entsperreKeypad(grund) { if (istGesperrt) { istGesperrt = false; fehlerZaehler = 0; internerKlartext = ''; if (sperrTimer) clearTimeout(sperrTimer); setState(ID_PIN_VIS_PUNKTE, "Code"); console.log("Alarmanlage: Keypad wurde entsperrt (" + grund + ").", "info"); sendTo(ID_TELEGRAM_1, 'send', { text: '✅ Alarmanlage: Keypad wurde wieder freigegeben. (' + grund + ')' }); } }