AsOpcUac: How to configure Client to read signals with Bad Quality Status?

Hello,

I’m having trouble reading OPC signals when they have a BadQuality status, which is required for my application.
I’m using X20CP0484-1 PLC, Automation Studio 4.12.6.106, and the AsOpcUac library.

In a third-party application that feeds data to the OPC server, there are two possible states for a signal:

  1. BadSensorFailure (0x808c 0000) - when the pressure transmitter is broken

  2. BadOutOfService (0x808d 0500) - when the transmitter is OK, but its value is “ignored” (this state can be set manually by a system engineer)

For the second case, the value is not involved in any logic (e.g., alarm limits are disabled), but the operator can still read measurements, which is important.
I need to implement the same functionality in my PLC program, but the value is not refreshed if there is any error status for the specific signal.

The OPC server supplier states that they tested “ignored” signals which have BadQuality, and the value was read without any problem. They used Softing OPC Client and ProSys OPC Client, and the value was read together with the signal quality without issues, which I have confirmed.

I know that according to the OPC Foundation, if the status is Bad, the results cannot be used. Is there any workaround to improve this? Any settings for FBs (e.g., UaClt_ReadBulk) or use different library etc.? I prefer to still use ReadBulk FB’s because PLC is reading a lot of OPC signals (~ 700 signals).

Hi @Pawel_Wojtaszczyk,

this might not be a solution, but you can try using the UA_MonitoredItemAddList and UA_MonitoredItemOperateList functionblock within a subscription.

There is a NodeQualityID available at UA_MonitoredItemAddList and also a NodeErrorID at UA_MonitoredItemOperateList.

NodeErrorID would indicate an issues when the data is processed by the functionblock.

NodeQualityID would indicate the status of the node after it was processed by the functionblock.

Since the variables are part of a subscription, all items can be monitored.

Maybe you can give it a try on a small scale to see if this works for you?

I’m not aware that the Read_Bulk functionblock has this kind of information.
Assuming the Read functionality only checks for the nodes on the rising edge of Execute it might not be able to create this kind of information.

BR,
Fabian

Hello Fabian,

Thank you for quick response.

I’ve tested communication on FB’s suggested by you but with no success.

  1. For quality “Good” value, I can read data with no issue (like with UaClt_ReadBulk):

  1. For quality “Bad” value, I can’t read data:

… node is on the server

…but on ItemOperate is “Bad” and I can’t read data.

So it’s seems even for monitoring / subscription FB’s we can’t read data from OPC UA server if quality is bad. May by I’m doing something wrong, but I tested it for couple good and bad values with no success.

On the other way, the same variable is read by ProSys Client with no problem:

Question is how the 3rd party opc clients do it? I assume it’s also some kind of monitoring / subscription mode, may by some “browsing” mode or any other method.

In my opinion there should be settings in OPC UA read FB’s:

  1. If quality is “Bad” value isn’t updated (default)

  2. If quality is “Bad” value is updated and also having quality status (DW), programmer can decode it and decide what do next.

Any other suggestions how to work around it?

Hi,

I’m quite surprised that an item is changing even though the Status is Bad_OutOfService.
I would expect that the last usable value is read since there has not been communication between Server and Client.
Regarding the Bad_SensorFailiure, the data might be transferred but considered invalid.

I agree with you that there might be room for improvement to give the programmer more freedom.

Initially I was thinking about the functionblock using the List functionality. There the NodeQualityID is available.
The ErrorID from the functionblocks is often used to reflect the status of the functionblock itself and the NodeQualityID (this is not available for the Read or “Single” MonitorItem functionblocks) from the UA_MonitoredItemAddList is used for the nodes itself.
https://help.br-automation.com/#/en/4/libraries/asopcuac/fbks/ua_monitoreditemoperatelist/ua_monitoreditemoperatelist.html
https://help.br-automation.com/#/en/4/libraries/asopcuac/fbks/ua_monitoreditemoperatelist/ua_monitoreditemoperatelist.html

One thing that I can think of is creating a user defined datatype by using the concept of UAVariantData and add the UADataValue the datatyp.
The target variable should then be of the newly defined type. It might be possible to get more information about the node using this concept.

UAVariantDataUser : STRUCT (* User type for variant data *)
VariantType : UAVariantType;
Double : LREAL;
DataValue : UADataValue
END_STRUCT;

Since it is not possible for me to test this and investigate further I might ask you to give me a hint how to reproduce this without the mentioned devices.
Overall this might also be some topic for the B&R support. :thinking:

BR
Fabian

Hi,

I’ve prepared (with AI) a simple test environment for an OPC UA server using Python. The variable value and quality change randomly every 2 seconds.

Could you please test it locally with a BR PLC client? If there’s no way to read a Bad Quality variable with the PLC client, I will probably have to write a Python proxy UA server, force the quality to Good, and then read the variable with the PLC. However, this is not a very robust solution for an industrial application.

Here’s the code for a simple OPC UA server in Python:

from opcua import Server, ua
import time
import random
from datetime import datetime

server = Server()
server.set_endpoint(“opc.tcp://localhost:4840/freeopcua/server/”)

uri = “http://examples.freeopcua.github.io
idx = server.register_namespace(uri)

objects = server.nodes.objects
myobj = objects.add_object(idx, “MyObject”)
myvar = myobj.add_variable(idx, “MyVariable”, 0.0)
myvar.set_writable()

server.start()
print(“Server started at opc.tcp://localhost:4840/freeopcua/server/”)

try:
while True:
new_value = round(random.uniform(0, 100), 2)
if new_value < 50:
status = ua.StatusCode(ua.StatusCodes.Good)
quality_text = “GOOD”
else:
status = ua.StatusCode(ua.StatusCodes.Bad)
quality_text = “BAD”
dv = ua.DataValue()
dv.Value = ua.Variant(new_value, ua.VariantType.Double)
dv.StatusCode = status
dv.SourceTimestamp = datetime.utcnow()
myvar.set_value(dv)
print(f"MyVariable updated to: {new_value} | Quality: {quality_text}")
time.sleep(2)

except KeyboardInterrupt:
print(“Stopping server…”)
server.stop()

And here’s an example showing that a different client can read this data without any problem:

2025-11-21_18-10-40

I hope I’m not bothering you too much but this is very important project and we have to finish it by the end of this year :(.

Hi,
thanks for providing the testcode. Could have thought about it on my own. :wink:

I did a test with Automation Software 4.12 and newest runtime version Q4.93.
The behavior could be reproduced as described.
In case of a Statuscode “BAD” the value is not transferred to the connected variable.

Same test with Automation Software 6, Automation Runtime 6.3 and OPC UA C/S TP 6.3. Here the value is written to the variable, also when the Statuscode of the node is “BAD”.
24-11-2025_13-45-19

I did not find any information on why the behavior was changed but it seems like ASW6 does the trick for you.
With ASW4 there won’t be any feature requests implemented since it is already in a kind of maintenance phase.

Best regards
Fabian

Hi (agian),

after some research an internal discussion it seems like the behavior of AsOpcUac from ASW4.12 is aligned with the OPC UA Specification.

Why AsOpcUac from ASW6 is working differently is currently under investigation.
But overall…

Since the AsOpcUac library is working according to the specification, this means that the sensor you are trying to implement is not working accordingly.

Currently there is nothing more I can do for you in Automation Software 4. Sorry.
As you wrote it might be worth looking at some workaround if this is really needed.

If you need something changed, please reach out to the local B&R office to check whether a feature request can be placed.
In my personal opinion the chances are quite low to get the request implemented since it would violate the specification.
The ASW6 AsOpcUac library might be also changed in future to comply with the specification again.

BR Fabian

Hi Fabian,

Thank you for the investigation!

I think to be on the safe side I’ll prepare a proxy OPC server in Python to transfer data. Like you said, in the future maybe we will have to upgrade the firmware and this feature will stop working.

The client app should change data quality to “Uncertain” (not “Bad”) when the signal is “ignored” to work properly, but they won’t change it.

Thanks again and have a nice week.

PW.

1 Like