Skip to Content

← All functionalities

Industrial mixing (touch HMI)TouchBerry PiFicherosDatalogging

One-tap USB export of the activation history

Quality departments still love a pendrive. This example adds a one-tap USB export button to a Node-RED dashboard on a TouchBerry Pi: an exec node lists /media/pi to detect a mounted drive, a function builds a dated copy command for the activation CSV log, and on-screen notifications confirm success or explain the failure. It comes from a real deployment on an industrial mixing line, where supervisors collect the history without touching the network.

Detecting the pendrive with an exec node

Raspberry Pi OS automounts USB drives under /media/pi/

A dated copy plus sync

The function builds the full shell command for a second exec node: cp of the CSV to log_activaciones_YYYY-MM-DD.csv on the drive, followed by sync. That sync matters — it flushes the write cache so the file is really on the stick before the operator pulls it out two seconds later. The mount point is quoted in case the drive label contains spaces.

Tell the operator what happened

cp is silent on success, so the flow speaks for it: the stdout branch raises a green notification with the destination path and a clear "you may now remove the drive", while the stderr branch shows the raw error message (read-only stick, no space left on device) for quick diagnosis. The original file stays untouched on the panel, where it keeps feeding the live history table.

A snippet from the implementation

Straight from the example as deployed on the TouchBerry Pi — copy it freely:

const SOURCE = "/home/pi/logs/log_activaciones.csv";

const devices = (msg.payload || "")
    .split("\n")
    .map(d => d.trim())
    .filter(d => d.length > 0);

if (devices.length === 0) {
    msg.payload = "Insert a USB drive and try again";
    return [null, msg];
}

// Use the first mounted device; quotes in case the USB
// label contains spaces.
const destDir = "/media/pi/" + devices[0];

// Dated file name: log_activaciones_2026-06-12.csv
const today = new Date().toISOString().slice(0, 10);
const destination = destDir + "/log_activaciones_" + today + ".csv";

// 'sync' guarantees the data is written before the operator
// pulls out the USB stick.
msg.payload = `cp ${SOURCE} "${destination}" && sync`;
msg.destination = destination;         // reused by the notification
return [msg, null];


// ============================================================
// function 2: notifyOk  (stdout of exec 2)
// ------------------------------------------------------------

The full example is a complete program — wiring header, setup and main loop — ready to adapt to your application.

Frequently asked questions

How does Node-RED detect a USB drive on Raspberry Pi?

The simplest way is an exec node running "ls /media/pi", since Raspberry Pi OS automounts drives there. Each line of output is a mounted device.

Can the operator corrupt the USB drive by removing it too early?

Appending "&& sync" to the copy command flushes buffers before the success notification appears, so removing the drive after the green message is safe.

What if two USB drives are plugged in?

The example uses the first mount point returned. You can instead present the list in a dashboard dropdown and let the operator choose the destination.

Related functionalities