Reading Multiple Bits in WinCC Unified Faceplates via JavaScript
WinCC Unified (TIA Portal V17 and later) removed the legacy "Multiple bits" evaluation type that engineers used in WinCC Comfort/Advanced faceplates. In a Unified faceplate container, the tag configuration dialog only exposes the full INT or DINT value, not individual bit selections. This guide shows how to recover that capability using the WinCC Unified JavaScript runtime API, bitwise masking against the tag value, and a script-driven faceplate property. The approach works on Unified Comfort Panels, Unified Basic Panels (V18+), and PC Runtime.
1. Problem: Why "Multiple Bits" Is Missing in Unified Faceplates
In WinCC Comfort / Advanced (TIA Portal V13–V16) the tag dynamization dialog for a faceplate instance offered three evaluation modes: Single bit, Multiple bits, and Range. The Multiple bits mode let the engineer assign each faceplate variant to a specific bit position of a 16-bit INT status word. The configuration was stored in the faceplate container properties and the runtime evaluator generated the matching background color, visibility, or text automatically.
When Siemens introduced the Unified HMI architecture in TIA Portal V16 and matured it through V17 / V18 / V19 / V20, the Multiple bits evaluation type survived on top-level screen objects (rectangles, buttons, IO fields) but was intentionally dropped from the faceplate container interface. The faceplate configuration schema in Unified only accepts:
- One PLC tag per faceplate interface property (data type matching the interface tag).
- An optional Single bit dynamization at the interface-property level, but only if the interface tag is a
Bool, not anInt/DInt/Word. - Scripted dynamization through the integrated JavaScript editor.
For engineers migrating a Comfort Panel project that used status-word encoding (a common pattern for valve manifolds, motor starters, or I/O diagnostics), this gap blocks a direct port. The official Siemens documentation for the "Multiple bits" evaluation type still describes the screen-object variant, but it does not apply to the faceplate container's interface tags.
Bool from the faceplate interface and drive it from script.2. Prerequisites
| Item | Requirement | Notes |
|---|---|---|
| TIA Portal | V17, V18, V19, or V20 | V16 lacks the full JavaScript tag API used here. V20 is recommended. |
| WinCC Unified | Runtime V17 Update 4 or later | Earlier updates have incomplete Tags() method coverage. |
| HMI device | Comfort Unified Panel MTP / TP / KTP series, or Unified PC Runtime | Unified Basic panels (V18+) support the same script API but limit script length. |
| PLC tag | One Int (16-bit) or DInt (32-bit) status word |
Bound to a faceplate interface tag of the same type. |
| Engineering PC | JavaScript syntax checking enabled in TIA options | Project → Settings → WinCC Unified → Script runtime. |
| Reference manual | WinCC Unified Engineering V20 manual | Provides the full tag-method signature table. |
3. The WinCC Unified JavaScript Tag API
WinCC Unified exposes the HMI tag system to the script engine through the global Tags object. The relevant methods for bit extraction (documented in Siemens Support entry ID 109773780 - Methods of "Tag") are:
| Method | Signature | Purpose |
|---|---|---|
Tags(...).Read() |
async Read(): Promise<any> |
Returns the current value of the tag. |
Tags(...).Write() |
async Write(value): Promise<void> |
Sets the tag value; only valid for writable tags. |
Tags(...).AddObserver() |
AddObserver(fn): Promise<number> (returns an observer handle) |
Registers a callback fired on every value change in runtime. |
Tags(...).RemoveObserver() |
RemoveObserver(handle): Promise<void> |
Detaches a previously registered observer. |
Tag references are created with the Tags() factory function, which accepts either the fully qualified tag name as a string or an item object. The qualified name is formed by concatenating the connection name and tag name with a double backslash, for example:
Tags("HMI_Connection_1\\StatusWord_ValveBank")
When the tag name is stored in a string variable, use the square-bracket form:
var t = Tags(["HMI_Connection_1\\", tagName].join(""));
4. Architecture: Bit Extraction in Three Layers
To drive a faceplate from individual bits of an INT, separate the concerns:
- PLC layer — packs the status flags into a single INT or DINT (one bit per diagnostic, e.g., bit 0 = running, bit 1 = fault, bit 2 = warning).
-
Faceplate interface — declares one
Inttag (the source status word) plus a configurable bit index property of typeUInt8. The faceplate script reads the source and isolates the requested bit. -
Visualization — the isolated
Boolis used to drive the background color, visibility, animation, or text of any object inside the faceplate.
This pattern keeps the faceplate reusable: every instance points to the same status word but a different bit index.
5. Implementing the Bit-Extraction Script
Open the faceplate in the WinCC Unified editor, then in the Scripts area add the following JavaScript. This is the core routine that reads the configured status tag and returns the value of a single bit:
// Faceplate script: GetBitFromStatusWord.js
// Properties referenced:
// - StatusTag (string, full tag path incl. connection)
// - BitIndex (UInt8, 0..31)
// - BitValue (Bool, output — bind to the visual property)
export function GetBitFromStatusWord() {
let statusTag = Faceplate.Properties.StatusTag;
let bitIndex = Faceplate.Properties.BitIndex;
if (!statusTag || bitIndex === undefined) {
return;
}
if (bitIndex < 0 || bitIndex > 31) {
// 32-bit mask ceiling; INT is 16-bit but the same code covers DINT
HMIRuntime.Trace("BitIndex out of range: " + bitIndex);
return;
}
let tag = Tags(statusTag);
tag.Read().then(function(value) {
// Treat the value as a 32-bit unsigned integer for masking
let numeric = (value >>> 0);
let mask = (1 << bitIndex);
let result = ((numeric & mask) !== 0);
Faceplate.Properties.BitValue = result;
}).catch(function(err) {
HMIRuntime.Trace("Tag read error: " + err);
});
}
Key points:
-
(>>> 0)coerces the result ofRead()to an unsigned 32-bit integer; without it, negative DINT values (sign bit set) produce incorrect masks. -
(1 << bitIndex)creates the mask; safe for bit indices 0–31. -
Faceplate.Properties.BitValueis an output property; bind any faceplate object property to it.
>>> 0 coercion before masking.6. Priority-Based Multi-Bit Evaluation (Status Colors)
When several bits of the status word are interpreted as priority levels (for example, bit 14 = critical alarm, bit 12 = warning, bit 9 = running), use a single script that returns a numeric state code, then map the state to a color:
// EvaluateStatusPriority.js — assigns the highest-priority bit set
// Returns 0=Idle, 1=Running, 2=Warning, 3=Critical
export function EvaluateStatusPriority() {
let statusTag = Faceplate.Properties.StatusTag;
let tag = Tags(statusTag);
tag.Read().then(function(value) {
let v = (value >>> 0);
// Priority is highest first — if/else-if chain
if ((v & (1 << 14)) !== 0) { // Bit 14: critical
Faceplate.Properties.StatusState = 3;
} else if ((v & (1 << 12)) !== 0) { // Bit 12: warning
Faceplate.Properties.StatusState = 2;
} else if ((v & (1 <> 0)) !== 0) { // Bit 0: running
Faceplate.Properties.StatusState = 1;
} else {
Faceplate.Properties.StatusState = 0; // Idle
}
});
}
The order of the if/else-if clauses is the priority order: the first matching bit wins. This replaces the comfort-panel "Multiple bits" assignment where each priority level was mapped to a specific background color directly.
7. Triggering the Script on Tag Change
Reading the tag only once when the screen loads is insufficient. The script must run whenever the status word changes. Two reliable trigger mechanisms are supported:
7.1 Scheduled Trigger
Configure a faceplate scheduled task with a 100–500 ms cycle. This is the simplest method and is sufficient for non-critical HMI status. Open the faceplate → Schedules → add a new task with interval 200 ms and action GetBitFromStatusWord.
7.2 Event-Based Trigger (Observer)
For higher update rates without polling overhead, attach a tag observer from the script:
// Attach once on faceplate initialization
export function OnStart() {
let statusTag = Faceplate.Properties.StatusTag;
let tag = Tags(statusTag);
Faceplate.Internal.ObsHandle = tag.AddObserver(function(value) {
let numeric = (value >>> 0);
let bitIndex = Faceplate.Properties.BitIndex;
let mask = (1 << bitIndex);
Faceplate.Properties.BitValue = ((numeric & mask) !== 0);
});
}
export function OnStop() {
let statusTag = Faceplate.Properties.StatusTag;
let tag = Tags(statusTag);
if (Faceplate.Internal.ObsHandle !== undefined) {
tag.RemoveObserver(Faceplate.Internal.ObsHandle);
Faceplate.Internal.ObsHandle = undefined;
}
}
Use the Events section of the faceplate to map the lifecycle (Loaded, Unloaded) to OnStart / OnStop. The observer is automatically removed when the faceplate instance unloads, but calling RemoveObserver explicitly prevents leaks if the same instance is dynamically re-loaded with new property values.
8. Binding the Extracted Bit to a Visual Property
Once the script populates a faceplate output property (e.g. BitValue or StatusState), bind it to any object inside the faceplate:
- Select the rectangle, button, or text element inside the faceplate.
- Open the Properties → Appearance pane.
- Click the small dynamization icon (lightning bolt) next to Background color.
- Choose Script → select the script that returns the
StatusStateproperty. - Map the integer result to a color using the value-to-color table (0 → gray, 1 → green, 2 → yellow, 3 → red).
For a Bool output property such as BitValue, bind it to Visibility or to the Single bit evaluation of a numeric color property. The Single bit evaluation type documentation explains the bit-position-to-state mapping inside a single property.
9. Adding the Faceplate Container to a Screen
On the process screen, drag a Faceplate Container from the toolbox. In the configuration dialog:
- Pick the faceplate type (e.g.
FP_ValveStatus). - Set the StatusTag property to the fully qualified HMI tag path, for example
HMI_Connection_1\Status_Word. - Set the BitIndex property to the bit position the instance should display (0–15 for INT, 0–31 for DINT).
- Click Apply. The faceplate is now bound.
To replicate the same faceplate across 16 valves reading the same status word, copy the faceplate container, change only the BitIndex property of each instance, and link every instance to the same StatusTag. This is the closest equivalent of the Comfort Panel Multiple bits setup.
For an overview of all faceplate container properties, see the Faceplate container (RT Unified) reference.
10. Alternative: Multiple Single-Bit Evaluations on One Object
If the source tag is a Bool in the PLC and you need only one bit per faceplate, the simpler route is still available in Unified. Bind the faceplate interface property directly to a Bool tag, then in the faceplate object use the Single bit evaluation type to map 0/1 to colors or visibility. This is the most efficient route when the PLC already provides a Bool and does not require any script. The script-based approach (Sections 5–7) is only needed when the status information is packed into an INT or DINT and the engineer cannot restructure the PLC tags.
11. Verification
- Compile check: In TIA Portal, right-click the HMI device → Compile > Software (full). No errors in the Messages pane confirm the script syntax is valid.
- RT simulation: Start the WinCC Unified Runtime on the engineering PC. Open the screen containing the faceplate container.
-
Tag write test: In the HMI tag table, set the connected PLC tag to a known value, e.g.
16#8001for bits 0 and 15 set. Confirm the faceplate colors / visibility update. - PLC simulation: With PLCSIM or a connected S7-1500, force the status word in the watch table. Each bit transition should reflect in the faceplate within one scheduler interval (200 ms typical) or one observer tick (typically < 50 ms).
-
Edge cases to verify:
- Bit 31 of a DINT with the sign bit set — confirm
>>> 0coercion is in place. - Disconnecting the PLC — the observer should not throw an unhandled exception;
BitValueshould hold its last value or revert to false depending on tag quality. - Loading the screen while the tag is offline — initial
Read()call must complete before the first visual update.
- Bit 31 of a DINT with the sign bit set — confirm
12. Troubleshooting Matrix
| Symptom | Likely Cause | Remedy |
|---|---|---|
| Script never fires | Event mapping missing or wrong lifecycle hook | Bind the function to Loaded, not Property Changed. |
| Bit value always false | Tag name string is missing the connection prefix | Use the form Tags("HMI_Connection_1\\Status") with a double backslash. |
| Bit 15 of a negative INT returns wrong state | Missing >>> 0 coercion |
Apply unsigned 32-bit coercion before masking. |
| Performance lag with many faceplate instances | Each instance polls the same tag via a scheduled task | Switch to one global observer feeding shared internal tags, or use event-based observer per instance (limit ~50). |
| Observer fires twice per change | Observer registered on both OnStart and a property change |
Remove the duplicate call; keep the observer attached only on Loaded. |
| Compile error "Tags is not defined" | Runtime version older than V17 Update 4 | Update the HMI image or use a wrapper function from the manual. |
| Faceplate property does not appear in container config | Property missing in the faceplate interface definition | Add the property to the faceplate type under Interface; rebuild the type. |
| Color stays gray after script runs | Color mapping configured for 0/1 only, but script returns 2/3 | Extend the value-to-color mapping; verify with the Watch view in the script debugger. |
13. Performance and Sizing Notes
- On a Unified Comfort Panel MTP1500, 100 faceplate instances each using a 200 ms scheduled task generate approximately 500 tag reads per second. Modern panels (MTP2200, IPC227G) handle this comfortably, but older Unified Basic panels (KTP400 to KTP1200) should use the observer-based approach to avoid overloading the small JS heap.
- Limit observer count to the active screen. Detach observers on
Unloadedevents; orphaned observers keep the GC from freeing the closed faceplate instance. - If the same bit is required in multiple visual elements inside one faceplate, compute the bit once in a scheduled or observer script and store the
Boolin a faceplate internal tag. Other elements bind to that internal tag with no additional script.
14. Migrating from Comfort to Unified
For projects originally built in WinCC Comfort V15/V16:
- Inventory every faceplate container that used Multiple bits on an Int tag.
- For each instance, record: source tag, bit index, resulting color/visibility.
- Add to the Unified faceplate: a StatusTag (String) interface property, a BitIndex (UInt8) interface property, and a BitValue (Bool) output property.
- Move the bit-index value from the Comfort faceplate container's Bit selection dropdown to the new BitIndex interface property of every Unified instance.
- Replicate the color/visibility behavior with a script-driven dynamization as described in Sections 6–8.
- Compile and test each migrated screen before going online with the PLC.
Does WinCC Unified support the legacy "Multiple bits" mode at all?
Only on top-level screen objects (buttons, rectangles, IO fields) under the property dynamization, not inside faceplate containers. For faceplates, use the JavaScript Tags(...).Read() method combined with a bitwise mask to isolate a single bit from an INT or DINT status word.
Which TIA Portal version is required for the tag observer API?
The AddObserver and RemoveObserver methods are documented in WinCC Engineering V16 (Siemens Support ID 109773780) and are fully stable in V17 Update 4 and later. V20 is recommended for new projects.
Can I read multiple bits in one script call to reduce overhead?
Yes. Read the tag once with Tags(...).Read(), then evaluate as many bits as needed with separate mask expressions and assign each to its own faceplate output property. This is more efficient than calling Read() per bit and is the recommended pattern for status words of 4–16 bits.
Why does my bit 15 indicator show the wrong state for negative values?
JavaScript treats integers as signed 32-bit by default. When the status word is interpreted as INT and is negative, a simple & mask on the raw value still works because the lower 16 bits are unchanged, but shifting right with >> (signed) corrupts the result. Use the unsigned right-shift >>> 0 coercion to convert to an unsigned 32-bit integer before any mask calculation.
Is there a limit on the number of faceplate instances that can read the same status word?
No hard limit, but each instance that polls the tag in a scheduled task consumes runtime resources. For more than ~50 instances on a single screen, switch to a single global observer that writes to internal faceplate tags shared by the visual elements, or use the event-based observer per instance and ensure each observer is detached on unload.