Hallo,
da ich nun das Skript nach langer Zeit wieder benutze, habe ich zwei Fehler (ack-flag; Race Condition) behoben. Danke an Mic für das originale Skript.
Spoiler
/*******************************************************************************
* VIS View PIN-Schutz
* -----------------------------------
* Original: Mic
* - 0.3 - ack-flag; Race Condition
* - 0.2 - Fix: 0 on keypad was not recognized
* - 0.1 - initial version
*
* Support: https://forum.iobroker.net/viewtopic.php?f=30&t=19871
******************************************************************************/
/*******************************************************************************
* KONFIGURATION
******************************************************************************/
const STATE_PATH = `0_userdata.${instance}.visViewPinSperre.`;
const LOGGING = true;
/*******************************************************************************
* PIN-VIEWS
******************************************************************************/
const PIN_VIEWS = {
'025_Wärmepumpe': {
project: 'main',
instance: 'e7.a5593',
pin: '1278'
},
'004_GastWlan-Skriptneustart': {
project: '1',
instance: '3d.fc183',
pin: '1278'
}
};
/*******************************************************************************
* INTERNE LAUFZEITDATEN
******************************************************************************/
const viewState = {};
/*******************************************************************************
* START
******************************************************************************/
init();
/*******************************************************************************
* INITIALISIERUNG
******************************************************************************/
function init() {
createScriptStates();
Object.keys(PIN_VIEWS).forEach(view => {
viewState[view] = {
buffer: '',
wildcards: ''
};
subscribeView(view);
});
setTimeout(() => {
Object.keys(PIN_VIEWS).forEach(view => resetPin(view));
if (LOGGING) log('VIS PIN-Schutz vollständig initialisiert');
}, 1000);
}
/*******************************************************************************
* STATE-ERZEUGUNG
******************************************************************************/
function createScriptStates() {
Object.keys(PIN_VIEWS).forEach(view => {
createState(`${STATE_PATH}${view}.CurrentKey`, {
name: 'Tasteneingabe aus VIS',
type: 'mixed',
read: true,
write: true,
role: 'state',
def: ''
});
createState(`${STATE_PATH}${view}.PinWildcards`, {
name: 'PIN-Anzeige (*)',
type: 'string',
read: true,
write: false,
role: 'text',
def: ''
});
createState(`${STATE_PATH}${view}.WrongPinEntered`, {
name: 'PIN falsch',
type: 'boolean',
read: true,
write: false,
role: 'indicator',
def: false
});
});
}
/*******************************************************************************
* EVENT-SUBSCRIPTION
******************************************************************************/
function subscribeView(view) {
on({ id: `${STATE_PATH}${view}.CurrentKey`, change: 'any' }, obj => {
const key = obj.state.val;
if (key === '' || key === null || key === undefined) return;
if (LOGGING) log(`Key "${key}" in View [${view}]`);
if (Number.isInteger(key)) {
handleNumber(view, key);
} else {
handleCommand(view, key);
}
safeSetState(`${STATE_PATH}${view}.CurrentKey`, '');
});
}
/*******************************************************************************
* EINGABEVERARBEITUNG
******************************************************************************/
function handleNumber(view, number) {
viewState[view].buffer += number.toString();
viewState[view].wildcards += ' *';
safeSetState(`${STATE_PATH}${view}.PinWildcards`, viewState[view].wildcards);
}
function handleCommand(view, command) {
switch (command) {
case 'Enter':
checkPin(view);
break;
case 'Reset':
resetPin(view);
break;
}
}
/*******************************************************************************
* PIN-PRÜFUNG
******************************************************************************/
function checkPin(view) {
if (viewState[view].buffer === PIN_VIEWS[view].pin) {
if (LOGGING) log(`PIN korrekt → Viewwechsel [${view}]`);
onSuccess(view);
setTimeout(() => resetPin(view), 3000);
} else {
if (LOGGING) log(`PIN falsch → View [${view}]`);
safeSetState(`${STATE_PATH}${view}.WrongPinEntered`, true);
resetPin(view);
}
}
/*******************************************************************************
* RESET
******************************************************************************/
function resetPin(view) {
viewState[view].buffer = '';
viewState[view].wildcards = '';
safeSetState(`${STATE_PATH}${view}.PinWildcards`, '');
setStateDelayed(`${STATE_PATH}${view}.WrongPinEntered`, false, true, 3000);
}
/*******************************************************************************
* ERFOLGSAKTION
******************************************************************************/
function onSuccess(view) {
setState('vis.0.control.instance', PIN_VIEWS[view].instance);
setState('vis.0.control.data', `${PIN_VIEWS[view].project}/${view}`);
setState('vis.0.control.command', 'changeView');
}
/*******************************************************************************
* HILFSFUNKTIONEN
******************************************************************************/
function safeSetState(id, value) {
if (existsState(id)) {
setState(id, { val: value, ack: true });
}
}
Vorher die alten Datenpunkte löschen, sonst kommt weiterhin der ack-flag Fehler.