Overview
WinCC Unified (TIA Portal V17) exposes the system tag @UserName, which returns the currently logged-in user as a WString. When no user is authenticated, the tag returns an empty WString of length zero; it never returns the literal text "null". This article documents how to display either the username or the placeholder text "No User" in an I/O field, and how to drive a Boolean status tag that mirrors the login state for use by the PLC.
Two complementary approaches are covered:
- A JavaScript dynamization triggered on a 1-second cycle (T1s) that combines string formatting and status-bit updates in a single function.
- An event-driven approach tied to system alarms raised on user login and logout, which removes polling latency.
"No User" state therefore occurs only during the initial login dialog or after explicit logout. PC Runtime can operate without any logged-in user for extended periods, so the "No User" display is far more common on PC-based systems.Prerequisites
- TIA Portal V17 Update 4 or later (V18 and V19 are compatible with the same syntax; minor differences in system alarm numbering may apply).
- WinCC Unified Runtime V17 or higher installed on the target device (Comfort Panel, MTP, or Unified PC).
- Configured user administration on the HMI device: Security → Users and Roles with at least one user defined.
- A test screen containing an I/O field (or a Text field, if display-only).
- An internal HMI Bool tag, or a Bool tag mapped to a PLC address, used as the
UserLoggedInstatus bit.
Understanding the @UserName System Tag
The @UserName tag is part of the WinCC Unified system namespace. It is generated automatically when a project is compiled and cannot be edited or deleted. Its properties are fixed by the runtime:
| Property | Value |
|---|---|
| Tag name | @UserName |
| Data type | WString (UTF-16) |
| Maximum length | 254 characters |
| Access | Read-only |
| Update mechanism | Updated by the runtime on login, logout, and user-switch events |
| Empty state | WString of length 0 when no user is logged in |
| Initial value | Empty WString (length 0) |
Because the empty state is a zero-length WString and not the JavaScript value null or undefined, a simple .length === 0 test reliably distinguishes the two cases. This is the foundation of the detection logic in the script below.
.length directly on the result of Read(), coerce explicitly with String(Tags("@UserName").Read()).length. Older WinCC versions sometimes return a variant wrapper around the WString; explicit coercion eliminates the ambiguity.I/O Field Configuration
Configure the I/O field in Output mode so it functions as a read-only display and cannot be modified by the operator. Open the I/O field properties in TIA Portal:
- Select the I/O field on the screen canvas.
- In the Properties pane, expand General.
- Set Mode to
Output. - Confirm the Format setting is
StringorWString; the I/O field in RT Unified supports String display modes only.
The I/O field RT Unified element supports Mode, Process value, and Format properties per the official documentation. Refer to the IO field RT Unified reference for the complete property matrix.
Property Reference
| Property | Setting | Notes |
|---|---|---|
| Mode | Output | Disables operator input; field is display-only |
| Process value | (none, dynamic via script) | Direct tag binding is optional; script dynamization on Text replaces it |
| Format | String | No numeric formatting required |
| Hidden input | Not supported | RT Unified I/O field does not expose a hidden-input option |
| Clear on invalid input | Disabled | Only relevant in Input mode |
JavaScript Dynamization for Username Display
To display either the username or the literal placeholder "No User", dynamize the Text property of the I/O field with a JavaScript function and trigger it on a 1-second cycle.
Configuration Steps
- Select the I/O field on your screen.
- Open the Properties pane and navigate to Appearance → Text.
- Click the dynamization icon (lightning bolt) next to the Text property.
- Select Script as the dynamization type.
- Set the trigger to Cyclic with an interval of
T1s(1 second). - Paste the function below into the script editor.
function DisplayUserName() {
let userName = Tags("@UserName").Read();
if (userName.length === 0) {
return "No User";
}
return userName;
}
The function returns the placeholder when the read value has zero length and returns the username otherwise. Because @UserName is updated automatically on login and logout, a 1-second cycle is sufficient for human-perceptible display updates.
Why the Original .length Call Failed
Two common mistakes cause the original approach to fail:
-
Calling
.lengthoutside a function. The WinCC Unified dynamization evaluator expects a function with an explicitreturnstatement. A bare expression likeTags("@UserName").Read().lengthreturns a number, but the dynamization framework looks for a string result when bound to the Text property. -
Missing return statement. Without a return value, the dynamization evaluates to
undefined, and the I/O field displays the last cached value or an empty string.
Wrapping the read in a named function and returning a resolved string fixes both issues.
Setting a Status Bit
To drive a Boolean tag that mirrors the login state, extend the script to write to an internal HMI tag or a tag mapped to a PLC address. The same script can handle both the display text and the status bit, ensuring they stay synchronized.
Internal HMI Tag Setup
- In the project tree, open HMI Tags.
- Create a new tag named
UserLoggedIn. - Set the data type to
Bool. - Set the connection to
<Internal tag>if the bit stays on the HMI, or to a PLC connection with a target address if the PLC needs to read it.
Combined Script for Display and Status Bit
function UpdateUserState() {
let userName = Tags("@UserName").Read();
let statusTag = Tags("UserLoggedIn");
if (userName.length === 0) {
statusTag.Write(0);
return "No User";
}
statusTag.Write(1);
return userName;
}
Wire this single script to both:
- The Text dynamization of the I/O field.
- The Value dynamization of the
UserLoggedIntag (via a tag trigger or a separate script dynamization on a hidden element).
Reading the Bit in the PLC
If UserLoggedIn is mapped to a PLC address, the controller reads the bit through standard input instructions. Typical address formats for S7 controllers:
| Controller | Address syntax | Example |
|---|---|---|
| S7-1500 | %DB<n>.DBX<byte>.<bit> | %DB5.DBX0.0 |
| S7-1200 | %DB<n>.DBX<byte>.<bit> | %DB10.DBX2.3 |
| S7-300/400 | %DB<n>.DBX<byte>.<bit> | %DB20.DBX1.5 |
| ET 200SP CPU | %DB<n>.DBX<byte>.<bit> | %DB100.DBX4.7 |
In the PLC program, evaluate the bit with a normal contact, for example:
// SCL example for S7-1500
IF "HMI_UserLoggedIn" THEN
// any user is logged on
END_IF;
Event-Driven Approach via System Alarms
WinCC Unified raises system alarms on user login, logout, and authentication failure. Configuring an event on these alarms runs the script immediately, eliminating the 1-second polling delay and reducing CPU load.
Identifying the System Alarm Numbers
Open HMI Alarms → System Alarms and filter by category System with a substring search for "User". Typical alarm numbers in V17 fall in these ranges:
| Alarm number range | Trigger | Source |
|---|---|---|
| 1100001 - 1100999 | User login successful | User administration |
| 1101001 - 1101999 | User logout | User administration |
| 1102001 - 1102999 | Login failed (wrong password) | Authentication |
| 1103001 - 1103999 | User locked / unlocked | User administration |
Configuring the Alarm Event
- Open HMI Alarms → System Alarms and locate the "User logged out" alarm.
- Select the alarm and open its Events tab in the Properties pane.
- Add a Coming event (raised when the alarm becomes active).
- Configure the event to call the
UpdateUserState()function defined above. - Optionally, repeat the configuration on the "User logged in" alarm with a Going event or its own Coming event so the bit transitions are immediate in both directions.
With the event-driven approach, the display updates within one scan of the alarm event, typically under 100 ms, and no cyclic script is required.
Verification Procedure
After compiling and downloading the project to the HMI device, validate the implementation with the following checks:
-
Initial state: With no user logged in, the I/O field should display
"No User"and theUserLoggedIntag should equal 0. - Successful login: Log in as a test user via the user view. Within 1 second (cyclic) or immediately (event-driven), the field should update to the username and the status bit should transition to 1.
-
Logout: Log out from the user view. The field should return to
"No User"and the bit should transition to 0. -
Failed login: Attempt login with an incorrect password. The state should remain
"No User"and 0, because no successful authentication occurred. - PLC visibility: If the status bit is mapped to a PLC address, use TIA Portal online watch or a trace to confirm the bit transitions match the HMI events with the expected timing.
- Multi-screen consistency: If the username appears on multiple screens, verify all instances update simultaneously and that no screen retains a stale cached value.
Troubleshooting Matrix
| Symptom | Possible cause | Resolution |
|---|---|---|
| I/O field always shows empty string | Mode set to Input but no operator input occurring | Set Mode to Output in the I/O field properties |
| Script does not run | Dynamization not linked or trigger missing | Verify the dynamization icon is active and the trigger is set to T1s or the system alarm event |
| Field shows literal text "@UserName" | Process value bound directly without script dynamization | Remove direct tag binding; use script dynamization on the Text property |
| .length returns unexpected value | Variant coercion issue with WString | Wrap with explicit string conversion: String(Tags("@UserName").Read())
|
| Status bit does not update | Tag trigger not configured or PLC connection offline | Check the HMI connection in the Connections editor and confirm the tag is mapped |
| JavaScript syntax error in script editor | Missing return statement or unclosed brace | Use the script editor's syntax checker before compiling |
| Display updates lag login by several seconds | Cyclic trigger interval too long | Reduce to T1s or switch to the event-driven alarm approach |
| Comfort Panel rejects login attempt | User administration not configured | Configure users and roles under Security settings and download to the panel |
| Status bit remains at 1 after logout | Script trigger not fired on logout alarm | Verify the event is attached to the Coming transition of the logout alarm |
| Field shows "No User" even when a user is logged in | Stale tag cache after project download | Restart the WinCC Unified Runtime or recompile and redownload the project |
Performance and Security Notes
The 1-second cyclic script adds negligible load on Comfort Panels, typically under 0.5% CPU on an MTP1500. For multi-screen projects where the username appears on several screens, consider placing the script on a global screen template or in a scheduled task to avoid redundant triggers per screen. The event-driven approach scales better on large projects because the script runs only when the login state actually changes.
Security-wise, displaying the username in clear text on the operator screen is acceptable for standard HMI applications but should not be used as an authentication mechanism. Use the WinCC Unified user administration API for access control decisions, and never rely on @UserName alone for security-critical logic in the PLC. The status bit derived from this method is informational; enforce access control at the user administration level, not by reading the displayed username from the panel.
FAQ
Why does .length not work directly on Tags("@UserName").Read() in WinCC Unified?
The Read() call can return a variant wrapper around the WString in some runtime contexts, and the dynamization evaluator expects a function with a return value. Wrap the call in a function and convert explicitly with String(Tags("@UserName").Read()).length before comparing against 0.
Can I use a Text field instead of an I/O field for the username display?
Yes. WinCC Unified Text fields support the same script dynamization on the Text property and have no Mode setting to configure. The script logic is identical; only the screen element type changes.
How do I drive a PLC bit from the @UserName state on an S7-1500?
Create an HMI Bool tag (e.g., UserLoggedIn) with the PLC connection set to the target address such as %DB5.DBX0.0. Write to this tag from the same script that updates the I/O field display. The PLC reads the bit using standard input instructions and evaluates it as a normal boolean contact.
Does this work on WinCC Unified Comfort Panels and PC Runtime the same way?
The script logic is identical. Comfort Panels enforce a logged-in user before screens become visible, so the "No User" state appears only briefly during initial login or after logout. PC Runtime can run with no logged-in user for extended periods, making the placeholder display more frequent in PC-based systems.
What happens to @UserName if the configured user is deleted at runtime?
The tag returns the last cached value until the next login or logout event, then transitions to an empty WString. Plan for this by triggering the script on the corresponding system alarm or by polling at T1s so the display and status bit always reflect the current authentication state.