# Mapp View OPC UA "valueChanged" not firing unless additional subscription exists

**URL:** <https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375>\
**Category:** Programming\
**Tags:** mapp-view\
**Created:** [March 4, 2026, 9:09am UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375 "2026-03-04T09:09:44Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michal\_Malek](https://avatars.discourse-cdn.com/v4/letter/m/FF8800/32.png) [@Michal\_Malek](https://community.br-automation.com/u/Michal_Malek)\
**Post date:** [March 4, 2026, 9:09am UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/1 "2026-03-04T09:09:44Z")

</div>

Hello,

I am experiencing unexpected OPC UA subscription behavior in mappView.

I dynamically create subscriptions like this:

 ![obrázok](https://europe1.discourse-cdn.com/brcommunity/original/2X/9/9ef69622bc55d1502c1cd27d047298e0c0ee5ce2.png)

getValue() works reliably.  
However, valueChanged() only fires if I additionally create a separate “test” subscription outside this logic, for example:  
 ![obrázok](https://europe1.discourse-cdn.com/brcommunity/original/2X/7/7710e512fe0b8b546640d9f1371417c5728024c4.png)  
So, if this extra subscription is removed, no errors occur, PLC values change and valueChanged() callbacks inside my dynamic bindings never trigger.  
And adding a single external subscription makes all dynamic subscriptions work.

Has anybody encountered or solved this kind of problem?

It raises some fundamental questions:

- is the OPC UA client or monitored item creation in mapp View lazily initialized?
- does getValue() guarantee monitored item creation, or does it only perform a read service call?
- is there a known timing dependency between page/session initialization and subscription activation?
- what is the officially recommended way to ensure reliable dynamic valueChanged() subscription setup during initialization?

The behavior suggests lazy activation or a timing dependency during initialization, but I would like confirmation whether this is expected behavior by design or an unintended issue.

I’m not sure whether this is an appropriate topic for the community, but I would appreciate any insights or experiences you can share.  
Thank you.  
Regards  
Michal Malek

---

<div class="post-metadata">

**Author:** ![rafael.laury](https://avatars.discourse-cdn.com/v4/letter/r/FF8800/32.png) [@rafael.laury](https://community.br-automation.com/u/rafael.laury)\
**Post date:** [March 4, 2026, 5:17pm UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/2 "2026-03-04T17:17:03Z")

</div>

Hello Michal, in your mapp View Configuration, make sure you have “Initial ValueChanged events” set to “TRUE”.

 ![image](https://europe1.discourse-cdn.com/brcommunity/original/2X/4/4f849eb70c9426a8e4a9e693330307750a08faaa.png)  
Otherwise the mapp View OPC UA client will not trigger a “valueChanged” event for the initialization of the event bindings. See : [B&R Online Help](https://help.br-automation.com/#/en/6/visualization/mappview/engineering/organization/mappviewconfiguration/opcuasystemconfiguration.html)  
 ![image](https://europe1.discourse-cdn.com/brcommunity/original/2X/6/630c5d144da7ebb7317166abcc33011b630258ce.png)

---

<div class="post-metadata">

**Author:** ![Michal\_Malek](https://avatars.discourse-cdn.com/v4/letter/m/FF8800/32.png) [@Michal\_Malek](https://community.br-automation.com/u/Michal_Malek)\
**Post date:** [March 4, 2026, 5:55pm UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/3 "2026-03-04T17:55:58Z")

</div>

Hi Rafael,  
It is set to TRUE, but I don’t think this has any connection with dynamic subscriptions in .eventscript files.  
Thanks.  
Regards,  
Michal Malek

---

<div class="post-metadata">

**Author:** ![stephan.stricker](https://dub1.discourse-cdn.com/brcommunity/user_avatar/community.br-automation.com/stephan.stricker/32/105_2.png) [@stephan.stricker](https://community.br-automation.com/u/stephan.stricker)\
**Post date:** [March 5, 2026, 3:06pm UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/4 "2026-03-05T15:06:16Z")

</div>

Hi Malek,  
this sounds strange to me. If you post a complete sample eventscript file I can take a look at it.

Best regards

Stephan

---

<div class="post-metadata">

**Author:** ![Michal\_Malek](https://avatars.discourse-cdn.com/v4/letter/m/FF8800/32.png) [@Michal\_Malek](https://community.br-automation.com/u/Michal_Malek)\
**Post date:** [March 13, 2026, 6:51am UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/5 "2026-03-13T06:51:56Z")

</div>

Hi Stephan,  
I uploaded a file with code extracted from my project.  
[testCommunity.zip](https://community.br-automation.com/uploads/short-url/pHvj2HoP0SFMFP0ftwGuwea7lQU.zip) (1.1 KB)  
When you uncomment the last lines, the valueChange inside InitBindings starts to work.  
Thank you.  
Regards  
Michal Malek

---

<div class="post-metadata">

**Author:** ![stephan.stricker](https://dub1.discourse-cdn.com/brcommunity/user_avatar/community.br-automation.com/stephan.stricker/32/105_2.png) [@stephan.stricker](https://community.br-automation.com/u/stephan.stricker)\
**Post date:** [March 13, 2026, 10:30am UTC](https://community.br-automation.com/t/mapp-view-opc-ua-valuechanged-not-firing-unless-additional-subscription-exists/10375/6 "2026-03-13T10:30:41Z")

</div>

Claude and I had a long discussion and I think we figured it out 🙂 I tested the fix and works.

# mappView EventScript: `valueChanged` Not Firing Without Test Variable

## Symptom

`opcVariable.valueChanged(...)` registered inside an `async` function did not fire —  
unless an unrelated synchronous `testVar.valueChanged(...)` on the same node path was  
present in the script.

* * *

## Root Cause: `async/await` Breaks Synchronous Execution

When the script function is `async` and contains an `await`, JavaScript **returns control  
to the caller immediately** at the first `await` — the rest of the function body is  
scheduled as a microtask to run later.

```js
async function initBindings() {
    let opcVariable = opcua(fullPath); // ✓ synchronous — runs immediately

    var initialState = await opcVariable.getValue(); // ← function PAUSES here
                                                     // control returns to #initScript

    opcVariable.valueChanged(function(e) { ... }); // ✗ this line has NOT run yet
}

initBindings(); // starts executing, then pauses at await

// Framework continues:
opcuaScriptManager.activateMonitoredItems(); // fires NOW
// → #itemsToMonitor is EMPTY for this node → no subscription created on the server
// → valueChanged handler will never be triggered

```

The `await` essentially splits the function into two parts. The first part runs before  
`activateMonitoredItems`, the second part — containing the `valueChanged` call — runs  
after. By then the subscription window has already passed.

* * *

## Why the Test Variable “Fixed” It

```js
var testVar = opcua('::AsGlobalPV:gVisuMapp.safety.sN[0].S_State');

testVar.valueChanged(function(e) { // ← synchronous, runs immediately
    console.log("CHANGED:", e.detail.newValue);
});

```

`testVar` used the **identical node path** as `opcVariable` inside `initBindings`.  
`OpcuaScopeAdapter` caches node adapters in a `Map` keyed by `fullNodeId`:

```js
opcua(nodeId) {
    if (!this.#nodeAdapters.has(fullNodeId)) {
        let opcuaNode = new OpcuaNode(nodeId, options, this.#opcuaConnection);
        this.#nodeAdapters.set(fullNodeId, new OpcuaNodeAdapter(opcuaNode));
    }
    return this.#nodeAdapters.get(fullNodeId); // ← returns the SAME instance
}

```

Because `testVar.valueChanged()` ran **synchronously** , it added the node to  
`#itemsToMonitor` before `activateMonitoredItems` was called. When `initBindings()`  
eventually continued after its `await` and called `opcVariable.valueChanged()`, it  
received the same already-subscribed adapter instance from the cache. The subscription  
already existed on the server, so the handler started working — purely by accident.

* * *

## The Fix

Register `valueChanged` **before** any `await`, then read the initial value afterwards:

```js
// ✗ BROKEN — valueChanged is placed after await
async function initBindings() {
    let opcVariable = opcua(fullPath);

    var initialState = await opcVariable.getValue(); // pauses here → fn() returns
    setModuleState(sessionVarName, initialState);

    opcVariable.valueChanged(function(e) { // too late
        setModuleState(sessionVarName, e.detail.newValue);
    });
}

// ✓ FIXED — valueChanged is placed before await
async function initBindings() {
    let opcVariable = opcua(fullPath);

    opcVariable.valueChanged(function(e) { // ✓ synchronous, registered in time
        setModuleState(sessionVarName, e.detail.newValue);
    });

    try {
        var initialState = await opcVariable.getValue(); // initial sync after subscription
        setModuleState(sessionVarName, initialState);
    } catch (err) {
        console.log("OPC init error:", fullPath, err);
    }
}

```

* * *

## Rule of Thumb

> In a mappView EventScript, always call `opcua(...).valueChanged(...)` **synchronously**  
> before any `await`. The framework calls `activateMonitoredItems()` immediately after  
> the script function returns — any `valueChanged` registration that happens asynchronously  
> (after an `await`) will be too late and the OPC UA subscription will never be created.
