Overview
Operators frequently need a lightweight electronic journal on a WinCC Unified Comfort Panel: an entry that captures the date, the currently logged-in user, a categorical reason (start-up, shift change, alarm acknowledgement) and a free-form comment describing the anomaly or observation. Persisting these entries to a CSV on a USB stick enables post-event review in Excel, Power BI, or a maintenance logbook, without requiring an MES connection or external historian.
This article documents an engineering pattern that is fully supported on the Unified RT runtime: combine a string tag, an I/O field with input mode enabled, a data log configured with the On demand trigger, and a JavaScript function from the documented runtime API (Tags, FileSystem, UI) to append a CSV-formatted row to a file on the panel's mounted USB media. The same pattern works on Unified PC Runtime by writing to a local path.
The configuration lives entirely inside the TIA Portal project; no additional runtime components, third-party DLLs, or external add-ons are required.
Prerequisites
- TIA Portal V17, V18, V19, or V20 with the WinCC Unified option installed and licensed. The mechanism described targets the RT Unified runtime image, not WinCC Comfort/Professional.
- Unified Comfort Panel (MTP700 / MTP1000 / MTP1200 / MTP1500 / MTP1900 or the TP series equivalents) running firmware matching the TIA Portal version, or Unified PC Runtime on a SIMATIC IPC or industrial PC.
- A configured HMI device with at least one user defined in Security > Users and Roles. Without at least one user,
Tags("@UserName")returns an empty string. - A USB storage device recognized by the runtime. On Unified Comfort Panels, FAT32 media up to 32 GB is the documented baseline; NTFS media is supported from firmware V18 onwards. The path is exposed as
/media/usb/on the Linux-based RT and as a Storage Card device on the Win32 IPC runtime. - Operator authorization to perform script execution; the runtime enforces the standard user-rights model for tags and file access.
- Familiarity with the TIA Portal Logs editor and the WinCC Unified JavaScript object model. Refer to the TIA Portal help for Creating a data log and an alarm log (RT Unified).
Architecture and Data Flow
The log entry is assembled in four stages:
- The operator enters a free-text comment into an I/O field bound to an internal WString tag (e.g.
HMI_AnomalyText). - The operator presses a button on the same screen. The button's Click event fires a JavaScript function (
LogAnomaly()). - The function reads the timestamp via
Tags("@LocalDateTime"), the user name viaTags("@UserName"), the reason code from a separate internal tag, and the comment fromTags("HMI_AnomalyText"). - The function appends a CSV row to
/media/usb/AnomalyLog.csvusingFileSystem.AppendFile(), then triggers the data log to commit a parallel structured entry (timestamp + user + reason + comment) through the On demand logging event.
The CSV file provides portability for offline review. The parallel data log provides the same record inside the HMI's Tag Logging database for trend and archive tools. Both stores are created and owned by the panel.
Step 1: Create the Required Tags
Open the HMI device in the TIA Portal project tree and expand HMI tags. Add the following internal tags. Internal tags are volatile; for an audit log that survives a power cycle, the runtime script writes the row to USB as a side effect of every entry, so the operator never needs to trust RAM alone.
| Name | Data type | Connection | Purpose |
|---|---|---|---|
HMI_AnomalyText |
WString (255) | Internal | Free-text input from the I/O field |
HMI_LogReason |
Int | Internal | Reason code selected from a drop-down (1 = start-up, 2 = shift, 3 = alarm, 4 = other) |
HMI_LogTrigger |
Bool | Internal | Edge-triggered from the Submit button |
@UserName |
WString | System tag | Currently logged-in user, populated by the runtime |
@LocalDateTime |
Date_And_Time | System tag | Local date and time, refreshed by the runtime |
Set the acquisition cycle for @LocalDateTime to 1 s so the timestamp is fresh when an entry is created. The two system tags do not need additional configuration - the runtime populates them automatically from the operator session and the panel clock.
Step 2: Create the Data Log
Navigate to the HMI device's Logs node in the project tree. Per the TIA Portal V20 documentation for Creating a data log and an alarm log (RT Unified):
- Double-click the Logs entry in the project tree below the HMI device.
- Open the Data logs tab.
- Double-click <Add> in the Name column to create a new log named
AnomalyLog. - Open the log and add the following columns by dragging the tags defined in Step 1:
@LocalDateTime,@UserName,HMI_LogReason,HMI_AnomalyText. - Set the Logging mode to On demand. With On-demand logging, the runtime writes a row only when the script invokes
Logging.Open()followed by a write trigger; this matches the desired "single row per Submit click" semantics. - Configure the storage location to File in CSV format and choose the path
/media/usb/AnomalyLog.csv. If a different USB label is used, adapt the path. The panel's Storage Path property must point to a directory that the runtime can create. - Set the Log size to a value that matches the maintenance interval; 1 MB is a reasonable default. Entries exceeding the size are dropped or rotated based on the overflow behavior set under Properties > Storage.
Step 3: Create the Screen Objects
On the desired Unified screen (for example, a pop-up screen called LogAnomaly), add the following elements:
- An I/O field bound to
HMI_AnomalyText. Set Mode to Input, Output format to String, Maximum length to 250. Enable the on-screen keyboard. - A Drop-down list or Symbolic I/O field bound to
HMI_LogReason. Populate the text list with the four reason codes listed above. - A Button with the label Submit. Configure its Click event to call the JavaScript function
LogAnomaly()(see Step 5). The button also setsHMI_LogTrigger = trueto drive a fallback tag-based logging path if JavaScript is disabled. - A Button with the label Cancel that simply closes the pop-up and clears
HMI_AnomalyTexton exit.
The pop-up is triggered from a top-level screen button labelled Log anomaly. Use a screen-window call or ShowModal to block input behind the dialog until the operator has finished the entry.
Step 4: Configure the On-Demand Trigger
With the On demand logging mode selected, the data log writes a row whenever the function Logging.Log (or the script's Log method) is called. To wire this to the Submit button, there are two common patterns:
-
Script-driven (recommended): the JavaScript function calls
HMIRuntime.Logging.Log("AnomalyLog", [timestamp, user, reason, text])after the CSV row is written. This is the cleanest approach because the data log and the CSV are committed by the same code path. -
Tag-driven: configure a tag event on
HMI_LogTriggerrising edge that opens the log and writes the current values of the four columns. This is the fallback for sites that prefer to avoid JavaScript.
Pattern 1 is documented in the TIA Portal help under Logs > Working with logs > Logging methods for JavaScript. Pattern 2 is documented in the same help under Working with logs > Configuring logging with a tag event. Both reach the same result.
Step 5: JavaScript Function for CSV Writing
Create a new global JavaScript module under Scripts > JavaScript in the project tree. Add a function called LogAnomaly. The implementation below uses the documented runtime objects Tags, FileSystem, and Logging:
// WinCC Unified JavaScript - Anomaly log writer
// Path matches the Storage Path of the data log defined in Step 2.
const LOG_PATH = "/media/usb/AnomalyLog.csv";
const HEADER = '"Timestamp","User","Reason","Comment"\r\n';
function csvEscape(value) {
if (value === null || value === undefined) return '""';
const s = String(value).replace(/"/g, '""');
return '"' + s + '"';
}
function LogAnomaly() {
try {
// Read the runtime values
const dt = Tags("@LocalDateTime").Read(); // Date_And_Time
const user = Tags("@UserName").Read(); // WString
const reason = Tags("HMI_LogReason").Read(); // Int
const text = Tags("HMI_AnomalyText").Read(); // WString
// Format timestamp as ISO-like local string (DD.MM.YYYY HH:MM:SS is common in EU panels)
const ts = formatDate(dt);
// Build the CSV row (RFC 4180 quoting)
const row = [
csvEscape(ts),
csvEscape(user),
csvEscape(reason),
csvEscape(text)
].join(",") + "\r\n";
// Check if file exists; if not, prepend the header
if (!FileSystem.FileExists(LOG_PATH)) {
FileSystem.WriteFile(LOG_PATH, HEADER + row, "utf-8");
} else {
FileSystem.AppendFile(LOG_PATH, row, "utf-8");
}
// Commit the same record to the structured data log
Logging.Log("AnomalyLog", [ts, user, reason, text]);
// Reset the input field for the next entry
Tags("HMI_AnomalyText").Write("");
UI.SysFct.ShowMessage("Anomaly logged successfully.", "Information", "OK");
}
catch (e) {
UI.SysFct.ShowMessage("Log write failed: " + e.message, "Error", "OK");
}
}
function formatDate(d) {
if (!d) return "";
const pad = (n) => (n < 10 ? "0" + n : "" + n);
return pad(d.getDate()) + "." +
pad(d.getMonth() + 1) + "." +
d.getFullYear() + " " +
pad(d.getHours()) + ":" +
pad(d.getMinutes()) + ":" +
pad(d.getSeconds());
}
The FileSystem object and the Logging object are part of the standard WinCC Unified runtime API and require no additional installation. The UI.SysFct.ShowMessage() call displays a modal confirmation on the panel. For sites that prefer the in-screen toast, replace the call with a tag write to a Status tag and bind it to a screen element.
/). Win32-based IPC runtime accepts both forward and backward slashes. Hard-coding / keeps the script portable across panel and IPC targets.Step 6: Compile, Download, and Test
- Compile the HMI in TIA Portal and download the project to the panel (or simulate on the PLCSIM Unified HMI).
- Insert the USB stick into the panel's USB port. Wait for the runtime to mount the device - the panel's control panel shows the device label under Storage.
- Log in as a user with rights to the screen. Open the Log anomaly pop-up.
- Enter a free-text comment, select a reason, and press Submit.
- Remove the USB stick and open
AnomalyLog.csvin Excel. Verify the row was written, the quoting is correct, and the timestamp matches the panel's local time. - Open the TIA Portal HMI traces or the runtime's Tag Logging view to confirm the parallel structured record is present.
Verification
After every maintenance event, the CSV on the USB stick and the data log on the panel should contain matching rows. The following checks confirm a successful implementation:
- CSV row count increments by exactly one per Submit click.
- The
Usercolumn matches the operator's display name from the runtime's user administration. - Free text containing commas, double quotes, and newlines survives a round-trip in Excel (no column shift, no broken quoting).
- Removing the USB stick during operation results in a clear runtime error message - either the JavaScript catch block or the panel's Storage status indicator - rather than a silent failure.
- Power-cycling the panel preserves every entry that was successfully written before the cycle.
Parameter Reference
| Parameter | Location in TIA Portal | Recommended value | Notes |
|---|---|---|---|
| Data log storage mode | Logs > AnomalyLog > Properties > Storage | File in CSV format | On demand writes only when the script triggers |
| Storage path | Logs > AnomalyLog > Properties > Storage path | /media/usb/AnomalyLog.csv |
Directory must exist at runtime |
| Logging mode | Logs > AnomalyLog > Properties > Logging | On demand | Documented under Creating a data log and an alarm log (RT Unified) |
| Tag acquisition cycle (timestamp) | HMI tags > @LocalDateTime > Properties > Acquisition | 1 s | Ensures fresh timestamp on every entry |
| I/O field input length | Screen > I/O field > Properties > Format | 250 chars | Match WString tag length |
| JavaScript access level | Scripts > Properties > Scheduler > Rights | Operator | Allow operator role to execute the script |
| User administration mode | Security > Settings | Local / SIMATIC Logon | Determines where the @UserName is sourced from |
Troubleshooting Matrix
| Symptom | Likely cause | Resolution |
|---|---|---|
| Submit does nothing | JavaScript scheduler disabled or the user role lacks script rights | Check the script scheduler under Runtime settings > Services; confirm the role has Execute script permission |
| Runtime error: File not found on AppendFile | USB stick not mounted, or path uses a Windows-style backslash on a Linux RT | Use forward slashes; verify the USB device appears under the panel's Storage menu |
| CSV row exists but data log row missing |
Logging.Log called with the wrong log name |
Verify the data log name in TIA Portal matches the string passed to Logging.Log
|
| Operator column is empty | No user logged in, or user administration not configured | Configure at least one user under Security > Users and Roles and force login on the start screen |
| Embedded commas shift columns in Excel | CSV not quoted | Wrap every string field in double quotes; double any embedded double quotes (RFC 4180) |
| Free-text field rejects non-ASCII characters | Tag defined as String instead of WString | Change the tag data type to WString; WString supports UTF-16 |
| File grows without bound | No log size or rotation configured | Set the data log size and the CSV maintenance policy; back up and purge periodically |
| USB stick not recognized | Format unsupported (exFAT, Linux ext4) | Reformat as FAT32 (or NTFS on V18+); consult the panel's operating instructions for the supported media list |
Operational Notes and Edge Cases
Concurrent writes. Two operators pressing Submit within the same script execution window will serialize through the runtime; FileSystem.AppendFile is synchronous, so rows are not interleaved at the byte level. The CSV does, however, contain one row per click, and the ordering matches the @LocalDateTime resolution (1 s). If sub-second ordering is required, add a millisecond field using a script-side counter or a higher-resolution Date.now().
Localization. The formatDate function uses European date ordering. Adjust to ISO-8601 (YYYY-MM-DD HH:MM:SS) for sites that consume the CSV through a downstream ETL pipeline that expects lexicographic ordering.
Audit completeness. The function above writes the row to the CSV only if both FileSystem and Tags succeed. The Logging.Log call sits inside the same try block, so a failure on the data log surfaces a runtime error and the operator sees a clear message. Move the Logging.Log call to a separate try-catch if the data log is optional and the CSV is the system of record.
Alternative controller storage. For a PLC-resident audit trail, mirror the same fields to a DB on the connected S7-1500 / S7-1200 and read it back through a separate History screen. The panel's CSV remains a portable copy.
Replacement of the legacy Textbox approach. The I/O field in Input mode is preferred over the Textbox graphic object for log entries: I/O fields support a configured Maximum length and bind cleanly to a tag, whereas Textbox input requires a manual write from the script. Reserve the Textbox for display-only purposes.
FAQ
Can the data log's CSV export contain string (text) columns in WinCC Unified?
Yes. From firmware V17 onwards, WString tags are written to the CSV column of a data log unmodified. Set the tag data type to WString (not String) so non-ASCII characters survive the round-trip. For operator-entered comments containing commas, apply RFC 4180 quoting in any script that writes the CSV directly.
Where does the panel store the CSV file by default?
Unified Comfort Panels expose mounted USB media as /media/usb/ (Linux-based RT) or as a Storage Card device (Win32 IPC runtime). Configure the data log's Storage path to a location inside the mounted volume so the file is physically removable.
Is the operator role allowed to run JavaScript functions?
Yes, provided the script's scheduler rights are set to include the operator role and the function uses only documented runtime objects (Tags, FileSystem, Logging, UI). The runtime enforces the same user-rights model for scripts as for screen actions.
What happens if the USB stick is removed during runtime?
The next FileSystem.AppendFile call raises an error which the surrounding try block catches. The UI.SysFct.ShowMessage call displays a runtime error to the operator. The structured Logging.Log call also fails, so the entry is lost unless an alternative store (PLC DB, internal flash path) is configured. Add a fallback path under /tmp/ for resilience if removal during operation is a real risk.
Does this pattern work on Unified PC Runtime as well as on panels?
Yes. The JavaScript API is identical. The only differences are the storage path (use a Windows-style path such as C:\Logs\AnomalyLog.csv for IPC runtime) and the licensing (PC runtime requires the WinCC Unified PC RT license rather than the panel image license).