Skip to Content

← Node-RED Admin Login on a Touchscreen HMI (TouchBerry Pi)

Industrial mixing (touch HMI)TouchBerry PiHTTPSafety

Node-RED Admin Login on a Touchscreen HMI (TouchBerry Pi) — full example

Protect Node-RED dashboard settings with an admin password, on-screen keyboard and session timeout on a TouchBerry Pi touchscreen HMI panel.

Complete, runnable program for the TouchBerry Pi (admin-auth-virtual-keyboard-timeout.js): wiring header, requirements and integration notes included.

Download the full project pack — freeThis example + the related ones + bill of materials

Read-only preview.

/*
 * COMPLETE EXAMPLE — Administrator authentication with virtual keyboard and timeout
 *
 * Hardware:  TouchBerry Pi (Raspberry Pi + Industrial Shields PLC, touch screen)
 * Based on:  industrial mixing project (Node-RED touch HMI)
 *
 * Requirements:
 *   - Node-RED with @flowfuse/node-red-dashboard (Dashboard 2.0 / UI v2)
 *   - No physical keyboard: the password is entered with an on-screen keyboard
 *
 * Flow wiring (left to right):
 *
 *   [ui-button "Settings"] ──> [function 1: checkSession] ──┬─(valid session)──> [ui-control: go to page /settings]
 *                                                           └─(expired)────────> [ui-template: virtual keyboard popup]
 *
 *   [ui-template keyboard] ──> [function 2: validatePassword] ──┬─(ok)────> [ui-control: go to /settings] + [ui-notification "Access granted"]
 *                                                               └─(wrong)─> [ui-notification "Incorrect password"]
 *
 *   [inject "on deploy" once=true] ──> [function 3: initCredentials]
 *
 * Node configuration:
 *   - ui-button "Settings": sends no relevant payload, it only triggers the check.
 *   - ui-template: form with input type=password and on-screen keyboard
 *     (on Raspberry Pi OS you can use 'matchbox-keyboard' or your own HTML keyboard);
 *     pressing OK emits msg.input with the typed text and msg.payload = true.
 *   - The two output paths are split with a switch node on msg.auth.
 */

// ============================================================
// function 3: initCredentials  (runs once on deploy)
// ------------------------------------------------------------
// Stores the password and the session timeout in the global context.
// In production, load them from a file or environment variable,
// never in plain text inside the exported flow.
// ============================================================
global.set("adminPwd", env.get("ADMIN_PWD") || "CAMBIAR_PASSWORD");
global.set("adminLoginTimeout", 10 * 60 * 1000);   // 10 minutes in ms
global.set("lastAdminLoginDate", null);            // nobody logged in at startup
return msg;


// ============================================================
// function 2: validatePassword  (receives msg from the virtual keyboard)
// ------------------------------------------------------------
// msg.payload == true  -> the operator pressed OK
// msg.input            -> text entered on the on-screen keyboard
// Output 1: access granted / Output 2: rejected
// ============================================================
if (msg.payload) {
    if (msg.input == global.get("adminPwd")) {
        // Access granted: record the instant for the session timeout
        global.set("lastAdminLoginDate", new Date());
        msg.auth = true;
        msg.payload = "Administrator access granted";
        return [msg, null];
    }
    // Incorrect password: do not reveal hints in the message
    msg.auth = false;
    msg.payload = "Incorrect password";
    return [null, msg];
}
return [null, null];   // popup cancelled: do nothing


// ============================================================
// function 1: checkSession  (runs when "Settings" is pressed)
// ------------------------------------------------------------
// If the last login is more recent than adminLoginTimeout,
// the user goes straight in without being asked for the password again.
// Output 1: valid session / Output 2: ask for password
// ============================================================
const last    = global.get("lastAdminLoginDate");
const timeout = global.get("adminLoginTimeout") || 600000;

if (last && (new Date() - new Date(last)) < timeout) {
    // Session still valid: renew it and let the user through
    global.set("lastAdminLoginDate", new Date());
    msg.auth = true;
    return [msg, null];
}

// Session expired (or never started): open the keyboard popup
global.set("lastAdminLoginDate", null);
msg.auth = false;
return [null, msg];


// ============================================================
// (Optional) function 4: manualLogout
// ------------------------------------------------------------
// Connected to a "Log out" ui-button inside /settings:
// invalidates the session immediately without waiting for the timeout.
// ============================================================
global.set("lastAdminLoginDate", null);
msg.payload = "Administrator session closed";
return msg;
Download the full project pack — freeThis example + the related ones + bill of materials