B&R OPC-UA Integration: Server Configuration, Address Mapping, Security, and Certificate Management
Overview
B&R Automation Runtime includes a built-in OPC-UA server that exposes PLC process variables to any OPC-UA compliant client. This is one of the most important diagnostic access points when working with undocumented B&R machines — OPC-UA allows reading and writing variables without needing the original Automation Studio project. This document covers how the OPC-UA server is configured, how address mapping works, namespace organization, security models, certificate management, and how to use OPC-UA for diagnostics on machines with no OEM documentation.
Architecture
The B&R OPC-UA server runs as a system task within Automation Runtime (priority 4–190 tier). It is integrated into the CPU firmware and requires no additional hardware. Key characteristics:
- Default port: 4840 (standard OPC-UA port, configurable)
- Runs on: Ethernet interface (IF2) — NOT on the POWERLINK interface (IF3)
- Configuration file:
OpcUa.Config.xmlon the CF card - Address configuration: Under
ServerConfiguration → BaseAddressesin the config file - Part of: mapp Technology framework (specifically mapp OPC-UA component)
Enabling the OPC-UA Server
Via Automation Studio (Normal Method)
- Open the project in Automation Studio
- Go to Physical View
- Right-click on the CPU (e.g., X20CP1584) → Configuration
- Expand OPC-UA System
- Set “Activate OPC-UA System” to On
- Configure server settings (port, endpoint, security policy)
- Add an OPC-UA Default View from the Toolbox to the Configuration View
- Enable specific variables as OPC-UA tags (right-click → Enable Tag)
- Set user role access rights for each tag (read, write, browse)
- Build & Transfer to the PLC
Critical: Variables Are NOT Automatically Exposed
Enabling the OPC-UA server does NOT automatically expose all process variables. Each variable must be explicitly enabled as an OPC-UA tag. This means:
- Grayed-out variables in the Default View = NOT accessible via OPC-UA
- Black/active variables = enabled and accessible
- The OEM had to deliberately enable each variable for external access
This is a major consideration for undocumented machines — if the OEM didn’t enable OPC-UA tags, you cannot access them via OPC-UA regardless of whether the server is running.
Without Automation Studio
If you have no project but the OPC-UA server is running:
- Scan for the server using UaExpert or any OPC-UA discovery client
- Browse the namespace to see what variables are exposed
- Read/write through the client
Namespace and Address Structure
B&R OPC-UA Namespace Layout
When connected to a B&R OPC-UA server, the namespace follows this structure:
Objects
└── PLC
├── Modules
│ ├── Default
│ │ ├── <TaskName1> (e.g., "Cyclic#1", "HMI_Inputs")
│ │ │ ├── Variable1
│ │ │ ├── Variable2
│ │ │ └── StructName
│ │ │ ├── Member1
│ │ │ └── Member2
│ │ └── <TaskName2>
│ │ └── ...
│ └── (additional modules)
├── System
│ └── (system diagnostics, status)
└── Server
└── (server configuration, status)
Node IDs
B&R OPC-UA Node IDs typically follow the format:
ns=2;s=PLC.Modules.Default.<TaskName>.<VariableName>(string-based)- Numeric namespace indices:
ns=0(OPC-UA standard),ns=1(B&R system),ns=2+(user application)
Variables are organized by the task class they belong to. Only variables within tasks that have been configured in the OPC-UA Default View are visible.
Custom Namespaces
You can create custom namespaces using a nodeset file (.xml), which provides more flexibility. A nodeset file can:
- Link OPC-UA nodes to specific PLC variables
- Create custom data types and structures
- Organize variables into logical groups (e.g., “Machine1”, “Conveyor”, “Press”)
- Add metadata (engineering units, descriptions, limits)
Security Model
Authentication Methods
| Method | Description | Default Availability |
|---|---|---|
| Anonymous | No authentication required | Enabled by default (role “Everyone”) |
| Username/Password | B&R user management | Configurable |
| Certificate-based | X.509 certificate validation | Configurable |
Important: If the “Anonymous” user is deleted from the user-role system, OPC-UA clients cannot connect without credentials. This is a common issue when OEMs tighten security.
User Roles and Access Rights
B&R implements OPC-UA role-based access control:
- Everyone — default role, typically browse + read
- Operator — read + limited write
- Engineer/Admin — full read/write access
- Custom roles — can be defined per installation
Each OPC-UA tag can have individual access rights configured:
- Visible — appears in browse
- Browse — node info can be read
- Read — current value can be read
- Write — value can be modified
- History — historical data can be accessed
Security Policies
B&R OPC-UA supports the standard OPC-UA security policies:
- None — no encryption, no signing (common on legacy machines)
- Basic128Rsa15 — basic encryption
- Basic256 — stronger encryption
- Basic256Sha256 — strongest commonly available
Certificate Management
Certificate Location
Certificates are stored on the CF card in the certificate store:
- Path: Accessible via Automation Studio → Configuration → Access and Security → Certificate Store
- Own certificates — the PLC’s server certificate
- Communication partner certificates — trusted client certificates
- CA certificates — certificate authority chains
Managed Certificate Store (AR 6.5+)
Starting with AR 6.5, B&R introduced the ManagedCertificateStore with the ArMcsRecreateCert function block for programmatic certificate recreation. In AR 6.5, the ManagedCertificateStore is extended to cover ANSL, FTP, HTTP, and SMTP libraries (not just OPC-UA). Additionally, the ArCert library now supports creating, exporting, viewing, and deleting certificate signing requests (CSRs), and the AsHttp httpsClient supports Server Name Indication (SNI). These features are not available on AR 4.x (CP1584 maximum), but are relevant for migration planning to newer B&R hardware.
Creating and Managing Certificates
- In Automation Studio: Configuration → Access & Security → Certificate Store → Own certificates
- Double-click New OPC UA certificate
- Configure: subject, validity, key size
- Transfer to PLC
Certificate-Only Access
For secure installations, certificate-based access can be configured:
- Create SSL configuration referencing the certificate
- Apply to OPC-UA server
- Add trusted client certificates to the communication partner store
- Disable anonymous access
Replacing Certificates Without Automation Studio
If you need to change certificates on a running PLC without the project:
- Access the CF card via FTP (user partition)
- The certificate store is typically at
F:\System\Certificates\or similar - Replace the server certificate file
- Cold restart the PLC to apply
Caution: Incorrect certificate replacement can lock you out of OPC-UA entirely.
Certificate Management Deep Dive
Certificate Creation Step-by-Step
When creating an OPC-UA certificate for a B&R PLC, the subject fields must be configured correctly for the PLC to accept and serve the certificate properly.
Recommended subject fields:
| Field | Value | Example |
|---|---|---|
| CN (Common Name) | PLC hostname or descriptive name | BR-PLC-001 or Line3-Controller |
| O (Organization) | Company or plant name | ACME Manufacturing |
| L (Locality) | City or site location | Detroit |
| S (State) | State or province | Michigan |
| C (Country) | Two-letter country code | US |
Key size: Minimum 2048-bit RSA. 4096-bit is supported on newer firmware but increases handshake latency.
Validity period: Typical production use is 1-3 years. Longer periods reduce renewal overhead but weaken the security boundary if the private key is compromised.
Certificate Renewal Workflow
- Generate a new certificate with the same subject fields and new validity period
- Replace the server certificate on the CF card (
System/Certificates/Own/) - Warm restart — the OPC-UA server reloads the certificate
- All connected clients receive
BadCertificateUntrustedand must re-accept the new certificate - Update any client certificate stores that pinned the old certificate
SHA1 Deprecation Issue
Older Automation Studio versions generated OPC-UA certificates using SHA1 signatures. Modern clients (UaExpert 1.5+, .NET OPC-UA stack, Python asyncua) reject SHA1 at the security layer.
Symptoms: BadCertificateUntrusted on any sign/encrypt policy; works with security None. Verify: openssl x509 -in cert.der -inform DER -text -noout | grep "Signature Algorithm".
Resolution: Regenerate the certificate with SHA256 via Automation Studio → Certificate Store. Ensure mapp version is 5.x+ (SHA256 native support). On firmware older than AR 4.30, use security None as a workaround.
Self-Signed vs CA-Signed Certificates
| Aspect | Self-Signed | CA-Signed |
|---|---|---|
| Trust model | Manual trust per client | Chain trust via CA root |
| Deployment | Simple, no external dependency | Requires CA infrastructure |
| Revocation | Not possible | CRL/OCSP supported |
| Scalability | Poor for many devices | Good for fleet management |
| Recommended for | Single-machine setups, development | Production lines, multi-PLC systems |
For production environments with multiple PLCs, use an internal CA (e.g., Smallstep CA, HashiCorp Vault PKI, or B&R’s own Automation Studio CA feature). This eliminates the need to manually trust each PLC’s certificate on every client.
Certificate Trust Chain Management
The B&R certificate store on the CF card maintains three categories under System/Certificates/:
- Own/ — server certificate + private key (DER format)
- Trusted/ — accepted client certificates from connecting clients
- CA/ — CA root and intermediate certificates
Trust validation order: check Trusted/ folder for direct match, then check CA/ for chain validation (intermediate to root), then verify validity period.
Adding a trusted CA: Export CA root cert in DER format, upload to System/Certificates/CA/ via FTP, warm restart. All certificates signed by that CA are automatically trusted.
SSL Configuration in Automation Studio
To bind a certificate to the OPC-UA server in Automation Studio:
- Configuration → Access & Security → SSL Configuration — create a new SSL Configuration object
- Set the Certificate Reference to the OPC-UA certificate in the Certificate Store
- Under OPC-UA System → Server Configuration, set the SSL Configuration reference
- Build and transfer
The SSL Configuration also controls TLS versions (TLS 1.2 minimum recommended), cipher suites, and whether the server requests client certificates.
mappView OPC-UA Client Certificate Configuration
When mappView acts as an OPC-UA client (connecting to another PLC or external server), it needs its own client certificate:
- In the mappView configuration, open mapp OPC-UA Client
- Set the Certificate reference to a client certificate from the Certificate Store
- The target server must trust this certificate (either directly or via CA chain)
- Configure the security policy to match what the server offers
Failure to configure the client certificate results in BadSecurityChecksFailed on the server side.
Certificate Backup and Restore Procedure
Backup: FTP to PLC, download the entire System/Certificates/ directory. Optionally convert to PEM: openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
Restore: Upload backup System/Certificates/ via FTP, cold restart to reload. Verify by connecting with UaExpert and checking the server certificate fingerprint. Always back up before firmware upgrades — upgrades may invalidate certificate bindings.
Connecting with OPC-UA Clients
Using UaExpert (Free OPC-UA Client)
- Install UaExpert (Unified Automation)
- Server → Add
- Enter the PLC IP address
- The Discovery URL will be:
opc.tcp://<PLC_IP>:4840 - Click Connect
- A certificate approval dialog appears — check “Trust Server Certificate”
- Browse: Objects → PLC → Modules → Default to find variables
- Set Authentication to Anonymous if no credentials configured
Python Client (asyncua)
import asyncio
from asyncua import Client
async def read_br_variables():
url = "opc.tcp://192.168.1.100:4840"
async with Client(url=url) as client:
# Browse available variables
root = client.nodes.root
objects = await root.get_child(["Objects", "PLC", "Modules", "Default"])
children = await objects.get_children()
for child in children:
name = await child.get_browse_name()
value = await child.get_value()
print(f"{name}: {value}")
# Read a specific variable by node ID
var = client.get_node("ns=2;s=PLC.Modules.Default.Cyclic#1.MyVariable")
value = await var.get_value()
print(f"MyVariable = {value}")
# Write a variable
await var.write_value(42.0)
asyncio.run(read_br_variables())
Node-RED Integration
Use the OPCUA-IIoT node in Node-RED:
- Configure OPC-UA server endpoint:
opc.tcp://<PLC_IP>:4840 - Security mode: None (for legacy machines)
- Browse to find variable node IDs
- Use Read/Write nodes for data exchange
Practical Client Examples
Python Subscription Example (asyncua)
Subscriptions are preferred over polled reads — the server pushes updates only when values change.
import asyncio
from asyncua import Client, ua
url = "opc.tcp://192.168.1.100:4840"
async def data_change_callback(node, val, data):
name = await node.get_browse_name()
print(f"[CHANGE] {name.Name} = {val}")
async def subscription_example():
async with Client(url=url) as client:
sub = await client.create_subscription(500, data_change_callback)
nodes = [
"ns=2;s=PLC.Modules.Default.Cyclic#1.Temperature",
"ns=2;s=PLC.Modules.Default.Cyclic#1.Pressure",
"ns=2;s=PLC.Modules.Default.Cyclic#1.Status",
]
for nid in nodes:
node = client.get_node(nid)
params = ua.MonitoringParameters(
ClientHandle=len(sub.monitored_items),
SamplingInterval=250,
QueueSize=10,
DiscardOldest=True
)
await sub.subscribe_data_change(node, params)
print("Subscribed. Press Ctrl+C to exit.")
try:
while True:
await asyncio.sleep(1)
except KeyboardInterrupt:
await sub.delete()
asyncio.run(subscription_example())
Python Write Example — B&R Gotcha
When writing to B&R OPC-UA variables, write_value() works for scalars. For complex structures with engineering unit scaling, you may need write_params or write individual members.
import asyncio
from asyncua import Client, ua
url = "opc.tcp://192.168.1.100:4840"
async def write_example():
async with Client(url=url) as client:
scalar = client.get_node("ns=2;s=PLC.Modules.Default.Cyclic#1.Setpoint")
await scalar.write_value(75.5)
print("Setpoint written: 75.5")
struct_node = client.get_node("ns=2;s=PLC.Modules.Default.Cyclic#1.RecipeData")
variant = ua.Variant(
{"Param1": 100, "Param2": 3.14, "Enable": True},
ua.VariantType.ExtensionObject
)
try:
await struct_node.write_value(variant)
except ua.UaError:
print("Structure write failed — writing individual members:")
await client.get_node(
"ns=2;s=PLC.Modules.Default.Cyclic#1.RecipeData.Param1"
).write_value(100)
await client.get_node(
"ns=2;s=PLC.Modules.Default.Cyclic#1.RecipeData.Param2"
).write_value(3.14)
await client.get_node(
"ns=2;s=PLC.Modules.Default.Cyclic#1.RecipeData.Enable"
).write_value(True)
asyncio.run(write_example())
UaExpert Workflow for Undocumented PLCs
- Launch UaExpert, add server: Server → Add → enter PLC IP
- Discovery: UaExpert queries
opc.tcp://<IP>:4840. If discovery fails, manually enter the endpoint URL - Certificate dialog: Check “Trust server certificate” on first connect
- Authentication: Start with Anonymous. If rejected, try common B&R credentials (admin/admin, operator/operator)
- Browse: Expand Objects → PLC → Modules → Default. Subfolders = task classes, contents = PLC variables
- Export: Right-click “Default” → Create Address Space Snapshot → saves CSV of all nodes
- Test: Drag a variable to Data Access View. Double-click value to attempt write
- System nodes: Objects → PLC → System shows CPU utilization, memory, task cycle times
Wireshark OPC-UA Capture and Decode
- Start Wireshark, set capture filter:
port 4840 - Connect with the OPC-UA client, then stop capture
- Install the OPC-UA dissector (Edit → Preferences → Protocols → OPC UA) if not present
- For encrypted traffic, set security to None for debugging — Wireshark cannot decrypt without session keys
- Key frames to inspect: Hello/ACK (TCP+OPC-UA handshake), CreateSession, Browse/Read/Write (node IDs visible in plaintext with security None), PublishResponse (subscription data)
C#/.NET OPC-UA Client Example
using Opc.Ua;
using Opc.Ua.Client;
var endpointUrl = "opc.tcp://192.168.1.100:4840";
var config = new ApplicationConfiguration()
{
ApplicationName = "B&R OPC-UA Client",
ApplicationUri = new Uri("urn:BROpcUaClient"),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true,
MinimumCertificateKeySize = 1024
}
};
config.CertificateValidator.CertificateValidation += (s, e) =>
{
if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted)
e.Accept = true;
};
var endpoint = CoreClientUtils.SelectEndpoint(endpointUrl, useSecurity: false);
using var session = Session.Create(config, endpoint, updateBeforeConnect: true,
"BROpcUaClient", 60000, null, null).Result;
var readNode = new NodeId("PLC.Modules.Default.Cyclic#1.Temperature", 2);
Console.WriteLine($"Temperature: {session.ReadValue(readNode).Value}");
session.WriteValue(
new NodeId("PLC.Modules.Default.Cyclic#1.Setpoint", 2),
new DataValue(72.5));
var subscription = new Subscription(session.DefaultSubscription)
{
PublishingInterval = 500, PublishingEnabled = true,
LifetimeCount = 1000, KeepAliveCount = 10
};
session.AddSubscription(subscription);
var item = new MonitoredItem(subscription.DefaultItem)
{
DisplayName = "Pressure",
StartNodeId = new NodeId("PLC.Modules.Default.Cyclic#1.Pressure", 2),
SamplingInterval = 250, QueueSize = 10, DiscardOldest = true
};
item.Notification += (_, e) =>
{
foreach (var c in e.NotificationList)
Console.WriteLine($"Pressure: {c.Value}");
};
subscription.AddItem(item);
subscription.Create();
Console.WriteLine("Subscribed. Press Enter to exit.");
Console.ReadLine();
session.Close();
Package: OPCFoundation.NetStandard.Opc.Ua (NuGet). Requires .NET Standard 2.0+ or .NET 6+.
Finding an Unknown OPC-UA Server
For machines with no documentation:
Step 1: Find the PLC IP Address
- Check the SDM (System Diagnostics Manager):
http://<IP>/sdm - Use Wireshark to capture B&R ANSL discovery packets
- Check network switch/router ARP table for B&R MAC OUI prefixes
- Try common B&R default IP ranges (192.168.100.x, 192.168.1.x)
Step 2: Check if OPC-UA is Active
## Scan for OPC-UA port 4840
nmap -p 4840 <PLC_IP>
## Or try connecting with openssl
openssl s_client -connect <PLC_IP>:4840
Step 3: Determine the OPC-UA Configuration
You cannot determine the OPC-UA configuration from the PLC alone without:
- The original project
- A system dump analyzed in Automation Studio
- The ability to browse the server
Key unknowns:
- Is OPC-UA activated at all?
- What port is it on? (default 4840, but configurable)
- What variables are enabled?
- What authentication is required?
- What encryption policy is used?
Step 4: Try Connection
Use UaExpert to attempt connection at the default port. If anonymous access is enabled and variables were configured, you’ll see them in the namespace. If not, you need to explore alternative access methods (PVI, FTP, direct I/O monitoring).
Performance Considerations
- OPC-UA runs as a system task (lower priority than cyclic tasks)
- Sampling interval is typically 100 ms minimum for standard OPC-UA subscriptions
- If the task idle time is too low, OPC-UA responses will time out
- The OPC-UA server can be a significant CPU load if many subscriptions are active
- For high-speed data collection, POWERLINK or direct I/O access is faster
Configuration File Deep Dive
OpcUa.Config.xml Structure
The OPC-UA server behavior is controlled by OpcUa.Config.xml on the CF card, generated by Automation Studio but editable via FTP.
OpcUa.Config.xml
├── ServerConfiguration
│ ├── ApplicationUri / ApplicationName / ProductUri / ServerName
│ ├── BaseAddresses (list of endpoint URLs)
│ ├── SecurityPolicies (uri + certificate per policy)
│ ├── MaxSessions / MaxSubscriptionsPerSession
│ ├── MaxMonitoredItemsPerSubscription
│ ├── RequestTimeout / ServiceLevel / AuditingEnabled
│ └── MaxResponseMessageSize
├── EndpointConfiguration
│ ├── TransportProfileUri / SecurityMode
│ ├── SecurityPolicyUri / SecurityLevel
├── UserTokenPolicies (anonymous, username, certificate)
├── CertificateConfiguration
│ ├── CertificateStorePath / IssuedCertificatesPath
│ └── TrustedCertificatesPath
└── NodeManager → BaseAddress
Editing the Config File via FTP
When you have no Automation Studio project and need to modify OPC-UA server settings:
- Connect to the PLC via FTP (default credentials: user/user or admin/admin depending on configuration)
- Navigate to the user partition (typically
F:\or the volume labeled “User”) - Locate
OpcUa.Config.xml— it may be at the root or under a project-specific directory - Download the file to your local machine
- Edit with a text editor (XML-aware editor recommended — notepad++ with XML plugin, VS Code)
- Backup the original file first (
OpcUa.Config.xml.bak) - Upload the modified file
- Perform a warm restart of the PLC to reload the configuration
Caution: Invalid XML will prevent the OPC-UA server from starting. Validate the XML before uploading. The server does not provide detailed parse error logs — it simply fails to start.
Key Configuration Parameters
| Parameter | Default | Description |
|---|---|---|
| MaxSessions | 100 | Maximum concurrent OPC-UA sessions (client connections) |
| MaxSubscriptionsPerSession | 100 | Maximum subscriptions per session |
| MaxMonitoredItemsPerSubscription | 1000 | Maximum monitored items (variables) per subscription |
| MaxBrowseContinuationPoints | 50 | Parallel browse operations |
| MaxHistoryContinuationPoints | 50 | Parallel history read operations |
| RequestTimeout | 10000 ms | Server-side request timeout |
| ServiceLevel | 100-255 | Server service level (100 = minimum) |
| MaxResponseMessageSize | 0 (unlimited) | Maximum response message size in bytes |
Endpoint Configuration
Endpoints define how clients connect. Each endpoint specifies:
- Transport Profile URI:
opc.tcpfor binary TCP transport (standard),httpfor SOAP/HTTP (legacy, rarely used) - Security Mode:
None,Sign,SignAndEncrypt - Security Policy URI: Maps to the actual encryption algorithm:
http://opcfoundation.org/UA/SecurityPolicy#Nonehttp://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15http://opcfoundation.org/UA/SecurityPolicy#Basic256http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
Changing the OPC-UA Port Without Automation Studio
- FTP to the PLC, download
OpcUa.Config.xml - Locate
<BaseAddresses>and change the port in the endpoint URI:<BaseAddresses> <EndpointUri>opc.tcp://192.168.1.100:4841</EndpointUri> </BaseAddresses> - Backup the original, upload the modified file, warm restart
- After changing the port, clients must use the new endpoint URL directly — auto-discovery will not find the server at the old port
Namespace and Variable Discovery Without Project
Recursive Python Namespace Browser
When working with an undocumented B&R PLC, the first task is discovering what variables are exposed. This script recursively browses the entire OPC-UA namespace and prints a tree of all nodes with their data types and current values.
import asyncio
from asyncua import Client
url = "opc.tcp://192.168.1.100:4840"
async def browse_recursive(client, node, indent=0):
name = await node.get_browse_name()
node_class = await node.read_node_class()
display_name = await node.get_display_name()
prefix = " " * indent
info = f"{prefix}[{node_class.name}] {display_name.Text}"
try:
value = await node.get_value()
data_type = await node.read_data_type()
info += f" = {value} ({data_type.Identifier})"
except Exception:
pass
try:
desc = await node.read_description()
if desc and desc.Text:
info += f" -- {desc.Text}"
except Exception:
pass
print(info)
try:
children = await node.get_children()
for child in children:
await browse_recursive(client, child, indent + 1)
except Exception:
pass
async def discover_namespace():
async with Client(url=url) as client:
print(f"=== OPC-UA Namespace Discovery: {url} ===")
root = client.nodes.root
objects = client.nodes.objects
await browse_recursive(client, objects, indent=0)
asyncio.run(discover_namespace())
Usage notes:
- On large namespaces, this can take several minutes — the B&R OPC-UA server has a default browse limit and may require continuation point handling
- Redirect output to a file:
python discover.py > namespace_dump.txt - The output can be cross-referenced with any partial documentation or PLC I/O lists
Mapping Discovered Variables to IO Points
After discovering the namespace, map variables back to physical I/O:
- Task class names in OPC-UA correspond to Automation Studio task classes:
Cyclic#1/Cyclic#2(I/O processing),HMI_Inputs/HMI_Outputs(HMI interface),Alarm/Recipe/DataLogger(mapp components),IO_.../DI_.../DO_.../AI_.../AO_...(digital/analog I/O) - Variable naming patterns:
gMachine_State(global state),stAxis_<Name>(axis structure),rSensor_<Location>(sensor reading),bSwitch_<Function>(boolean input) - Struct members map directly to Automation Studio variable names (
bEnable,rActualValue,rSetpoint)
Reconstructing IO Mapping via OPC-UA Browse
For a completely undocumented machine:
- Start with
Systemnode: CPU diagnostics, firmware version, task cycle times - Browse
Modules → Default → <task classes>: application variables by task - Look for variables with engineering units metadata — often correspond to physical sensors
- Look for structures named after hardware:
Axis_Drive1,IoModule_Terminal1 - Compare with physical I/O module count on the hardware to validate coverage
Limitations: What You Cannot Discover via OPC-UA
- Internal program logic: You cannot see ladder logic, ST code, or function block implementations
- Communication parameters: POWERLINK node assignments, MODBUS register mappings, or serial port configurations are not exposed
- Disabled variables: Any variable the OEM did not explicitly enable as an OPC-UA tag is invisible
- Array dimensions: B&R OPC-UA may expose arrays but with limited dimension metadata
- User-defined types: Complex user-defined data types may appear as generic structures without meaningful member descriptions
- Timing information: Task cycle times are visible, but internal timing (delays, timer configurations) is not
- Hardware configuration: The physical I/O topology (which terminal is in which slot) is not directly exposed — only the logical variable names
- Alarm/event history: Unless mapp AlarmX was configured to publish through OPC-UA, alarm data is not available via standard variable browsing
OPC-UA Troubleshooting
Common Connection Failures
| Symptom | Likely Cause | Resolution |
|---|---|---|
| Connection refused (TCP RST) | OPC-UA server not running | Check if OPC-UA is activated in the PLC configuration. Warm restart. Verify port via nmap |
| Connection timeout | Network firewall blocking port 4840 | Check firewall rules. Open TCP 4840 inbound on the PLC network segment |
| Certificate rejection | Server cert untrusted by client | Trust the server certificate in the client. In UaExpert: check “Trust Server Certificate” on first connect |
| BadCertificateUntrusted | SHA1-signed certificate | Regenerate certificate with SHA256. See Certificate Management Deep Dive |
| BadSecurityChecksFailed | Security policy mismatch | Client and server must share at least one common security policy. Check server endpoints |
| BadSessionClosed | Session timeout | Increase client keep-alive interval. Check PLC CPU load — high load causes OPC-UA timeouts |
| BadUserAccessDenied | Insufficient permissions | Verify user role assignment. Check if anonymous access was disabled |
| BadNodeIdUnknown | Variable node does not exist | Verify the node ID against a fresh namespace browse. Variable names are case-sensitive |
| No endpoints discovered | Discovery service not responding | Try direct connection with the endpoint URL opc.tcp://<IP>:4840 |
| Connection drops intermittently | Network instability or CPU overload | Check network cabling, switch port errors, and PLC task idle time |
Certificate Trust Issues
Scenario: Client connects successfully with security=None but fails with any signing or encryption policy.
- Verify the server certificate is not expired:
openssl x509 -in cert.der -inform DER -dates -noout - Verify the signature algorithm:
openssl x509 -in cert.der -inform DER -text -noout | grep "Signature Algorithm" - Check if the client certificate is in the PLC’s trusted store:
- FTP to PLC → browse
System/Certificates/Trusted/ - If the client certificate is missing, upload it
- FTP to PLC → browse
- For CA-signed certificates, ensure the CA root is in
System/Certificates/CA/
Authentication Failures
- Anonymous rejected: The OEM removed the “Everyone” role. You must authenticate with a configured username/password. Check the B&R User Management for valid accounts.
- Username/password rejected: Verify credentials against the B&R user management (accessible via Automation Studio or the SDM web interface). Passwords are case-sensitive.
- Certificate authentication rejected: The client certificate is not in the trusted store, or the SSL Configuration on the PLC requires a specific certificate that was not presented by the client.
Timeout Issues
OPC-UA timeouts on B&R systems are almost always caused by insufficient task idle time:
- Check CPU utilization:
PLC.System.CPU.Utilizationand per-task cycle times via OPC-UA System nodes - If task idle time is below 10%, the OPC-UA system task cannot respond within the request timeout
- Reduce active subscriptions, increase sampling intervals, or optimize cyclic task code
- Increase client-side timeout (UaExpert: Tools → Options → Advanced → Operation Timeout)
Variable Not Found / Namespace Issues
- Node IDs in B&R OPC-UA are case-sensitive:
PLC.Modules.Default.Cyclic#1is not the same asplc.modules.default.cyclic#1 - The namespace index (
ns=X) can change between firmware upgrades or configuration rebuilds — always verify with a fresh browse - If variables disappear after a PLC update, the OEM may have modified the OPC-UA Default View configuration
- Empty namespaces under
Objects → PLC → Modules → Defaultmean no variables were enabled for that task class
Port Conflicts
- Another service on the PLC may be using port 4840 (unlikely but possible with custom configurations)
- A firewall between the client and PLC may be blocking the port
- If the OPC-UA port was changed from the default, the discovery URL will not match — always try direct endpoint connection
- Multiple OPC-UA servers on the same network segment with the same ApplicationUri can cause client confusion
Security Policy Mismatch
If the client and server have no overlapping security policies:
- Use UaExpert to connect and check the server’s offered endpoints (shown in the connection dialog before connecting)
- Ensure the client supports at least one of the server’s offered security policies
- If the server only offers
Basic256Sha256and the client only supportsNone, upgrade the client or reconfigure the server’s security policies inOpcUa.Config.xml - For legacy B&R firmware, the server may only offer
NoneandBasic128Rsa15— modern clients that reject SHA1 may only haveNoneas an option
OPC-UA Performance Tuning
Subscription vs Polled Reads
| Approach | Network Traffic | Server Load | Data Freshness | Recommended Use |
|---|---|---|---|---|
| Subscription | Low (push on change) | Lower | Near real-time | Continuous monitoring, alarming, dashboards |
| Polled Read | High (periodic request) | Higher | Periodic (poll interval) | One-time reads, data logging, batch processing |
| Batched Read | Medium | Medium | Periodic | Reading many variables at once |
Recommendation: Always prefer subscriptions over polled reads. A single subscription with 100 monitored items generates significantly less network traffic than polling 100 variables every 250 ms.
Dead Band Settings for Analog Values
Dead bands prevent unnecessary notifications for insignificant analog value changes. Set the absolute dead band to match sensor resolution — a temperature sensor with 0.1C resolution does not need notifications for 0.001C changes. Dead bands are not applicable to integers and booleans.
Queue Size and Sampling Rate Optimization
- QueueSize=1: Only the latest value is kept. Intermediate values are lost. Use for dashboards where only the current value matters.
- QueueSize=10+: Multiple intermediate values are queued. Use for data logging or trend analysis. Client receives all intermediate values on each publish cycle.
- SamplingInterval: The minimum practical interval on B&R OPC-UA is typically 50-100 ms. Intervals below 50 ms may be rounded up by the server.
- PublishingInterval: The server sends queued notifications at this interval. Set to 500-1000 ms for normal operation. Lower values increase CPU and network load.
Impact on Cyclic Task Performance
The OPC-UA server runs as a system task at a priority between 4 and 190. If cyclic tasks are consuming most of the CPU cycle, the OPC-UA server task gets starved:
- Monitor task idle time: Via OPC-UA, read
PLC.System.Tasks.<TaskName>.IdleTime. If below 10%, expect OPC-UA response degradation - Correlation: When cyclic task cycle time spikes (e.g., from 5 ms to 15 ms), OPC-UA publish intervals will stretch proportionally
- Mitigation: Reduce the number of monitored items, increase sampling intervals, or optimize the cyclic task code
- Diagnostic: If you notice OPC-UA latency increasing during machine operation, check which cyclic task is consuming CPU and when
Monitoring Task Idle Time with OPC-UA Active
When OPC-UA is active, monitor task idle time to detect performance impact. Key node IDs:
PLC.System.Cyclic#1.IdleTime— idle time in microsecondsPLC.System.Cyclic#1.CycleTime— total cycle time in microseconds
Health thresholds:
- Idle > 20% of cycle time: healthy, OPC-UA is not starving
- Idle 10-20%: warning, reduce subscriptions or increase sampling intervals
- Idle < 10%: critical, OPC-UA responses will timeout; optimize cyclic tasks first
If idle time drops when OPC-UA subscriptions are active, the OPC-UA system task is competing for CPU time. Reduce the number of monitored items or increase sampling intervals to relieve pressure.
OPC-UA History (Historical Access)
Historical Data Access
If the B&R OEM configured mapp DataLogger or mapp History with OPC-UA historical access enabled, you can read historical variable values from the OPC-UA server:
- The historical data is exposed through the OPC-UA Historical Data Access (HDA) service
- Not all B&R OPC-UA configurations include HDA — it must be explicitly configured in Automation Studio
- Available historical nodes appear in the namespace with the
AccessLevelHistoryReadflag set
Reading Historical Data with Python
import asyncio
from asyncua import Client, ua
url = "opc.tcp://192.168.1.100:4840"
async def read_history():
async with Client(url=url) as client:
node = client.get_node("ns=2;s=PLC.Modules.Default.DataLogger.Temperature")
start = ua.DateTime.utcfromisoformat("2025-12-01T00:00:00Z")
end = ua.DateTime.utcfromisoformat("2025-12-31T23:59:59Z")
details = ua.ReadRawModifiedDetails(
IsReadModified=False, StartTime=start, EndTime=end,
NumValuesPerNode=0, ReturnBounds=True
)
result = await node.read_history(
history_read_details=details,
timestamps_to_return=ua.TimestampsToReturn.Both
)
if result.StatusCode.is_good():
for item in result.HistoryData.Values:
print(f"{item.SourceTimestamp}: {item.Value.Value} [{item.Status}]")
else:
print(f"Failed: {result.StatusCode}")
asyncio.run(read_history())
Reading Historical Alarms via OPC-UA
If mapp AlarmX is configured to publish through OPC-UA, alarms appear as condition nodes with properties: EnabledState, AckedState, ActiveState, Severity. Query historical alarm events using the Event History service.
import asyncio
from asyncua import Client, ua
url = "opc.tcp://192.168.1.100:4840"
async def read_alarm_history():
async with Client(url=url) as client:
alarms = client.get_node("ns=2;s=PLC.Modules.Default.AlarmX")
start = ua.DateTime.utcfromisoformat("2025-12-01T00:00:00Z")
end = ua.DateTime.utcfromisoformat("2025-12-31T23:59:59Z")
event_filter = await alarms.get_event_filter(
evtype=client.get_node(ua.ObjectIds.AlarmConditionType)
)
details = ua.ReadEventDetails(
StartTime=start, EndTime=end,
MaxValuesPerNode=1000, Filter=event_filter
)
result = await alarms.read_event_history(details)
if result and result.Events:
for ev in result.Events:
msg = ev.Message.Text if ev.Message else "No message"
sev = ev.Severity if hasattr(ev, "Severity") else "N/A"
print(f"{ev.Time}: [{sev}] {msg}")
else:
print("No alarm history or HDA not configured")
asyncio.run(read_alarm_history())
Time-Based Data Retrieval Constraints
- Time zone: B&R OPC-UA uses UTC. If the PLC clock is not NTP-synchronized, timestamps may be inaccurate (see time-sync.md)
- Resolution: Depends on mapp DataLogger config — typically 100 ms to 60 seconds
- Retention: Stored on CF card or SRAM; old data is overwritten when the buffer fills
- Aggregate functions: If supported, use
ReadProcessedDetailsfor server-side aggregates (average, min, max, count, stddev) — more efficient than reading all raw values
Security Considerations for OPC-UA on B&R Systems
Known OPC-UA Vulnerabilities
| CVE | Advisory | Product | CVSS | Impact | Mitigation |
|---|---|---|---|---|---|
| CVE-2025-11482 | SA25P006 (2026-05-26) | PPT30 OS < 1.8.0 | v4.0 8.7 / v3.1 7.5 | Permanent DoS on OPC-UA server via resource exhaustion from concurrent connections | Update PPT30 OS to 1.8.0; firewall port 4840 if OPC-UA not needed |
| CVE-2025-11044 | SA25P005 (2026-01-19) | AR < 6.5 / R4.93 | v4.0 8.9 | ANSL flooding DoS (impacts OPC-UA indirectly by exhausting AR resources) | Patched in R4.93; rate-limit at firewall |
| CVE-2026-0936 | SA26P001 (2026-01-29) | PVI client | N/A | PVI logs credentials in plaintext (affects OPC-UA connections made via PVI) | Update PVI to 6.5; see pvi-api.md |
OPC-UA Hardening Checklist
- Disable anonymous access if possible — require username/password or certificate authentication
- Use security policy Basic256Sha256 or higher — never run production with security None
- Firewall port 4840 to allow only known OPC-UA clients and HMIs
- Monitor OPC-UA connection attempts — unexpected clients may indicate scanning
- Regenerate self-signed certificates with SHA256 and set reasonable validity (1-3 years)
- Replace self-signed certs with CA-signed when possible — see SA25P001 guidance in cybersecurity-hardening.md
- PPT30 HMI panels: If OPC-UA is enabled on a PPT30, verify OS version >= 1.8.0 (SA25P006)
CVE-2025-11482: PPT30 OPC-UA Server DoS
The PPT30 OPC-UA server has a resource exhaustion vulnerability (CWE-770). An unauthenticated network attacker can send messages that cause the OPC-UA server to become permanently unresponsive. A reboot is required to restore service. The vulnerability is scored CVSS v4.0 8.7 because:
- No authentication required
- Network-based exploitation
- Permanent availability impact (reboot needed)
- Affects safety-related HMI interactions when PPT30 is used as the operator interface
If your CP1584 system uses a PPT30 panel with OPC-UA:
- Check PPT30 OS version: Settings → System Information → OS Version
- Update to PPT30 OS 1.8.0 via B&R Update Tool
- If update is not immediately possible, restrict OPC-UA access to trusted IP addresses via firewall
- OPC-UA is not enabled by default on PPT30 — if you never explicitly enabled it, you are not affected
Cross-References
- execution-model.md — How task priority affects OPC-UA system task performance
- pvi-api.md — Alternative programmatic access method
- ftp-web-interface.md — FTP access to CF card for certificate/config files
- iiot-retrofit.md — OPC-UA to MQTT bridges for modern monitoring
- python-diagnostics.md — Building Python diagnostic scripts with OPC-UA
- time-sync.md — Timestamp handling for OPC-UA historical data
- network-architecture.md — Network requirements for OPC-UA
- access-recovery.md — Accessing OPC-UA when credentials are lost
- alarm-logging.md — OPC-UA alarm integration
- cybersecurity-hardening.md — OPC-UA security hardening, CVE-2025-11482, SA25P006
Key Findings
- OPC-UA server is built into AR firmware but must be explicitly activated and variables individually enabled
- Not all variables are automatically exposed — each must be enabled as an OPC-UA tag by the developer
- Default port is 4840 on the standard Ethernet interface
- Namespace structure:
Objects → PLC → Modules → Default → <TaskName> → <Variables> - Three authentication methods: anonymous (default), username/password, certificate
- Certificates stored on CF card in the certificate store
- For undocumented machines: OPC-UA is the best diagnostic access point if it was configured, but useless if the OEM never enabled it
- The
OpcUa.Config.xmlfile on the CF card contains server configuration - OPC-UA runs as a lower-priority system task — it can be starved by long-running cyclic tasks
Community OPC-UA Tools for B&R
| Tool | URL | Purpose |
|---|---|---|
| OpcUaSamples | github.com/br-automation-community/OpcUaSamples-sample-AS | Comprehensive OPC-UA configuration and coding samples in Ansi-C and ST, spanning AS4.1 through the newest AS version, with detailed explanations |
| easyuaclient-as-project | github.com/br-automation-community/easyuaclient-as-project-dev | EasyUaClnt — a simplicity wrapper library based on AsOpcUac for a clear OPC-UA client interface |
| demo-br-asyncua | github.com/hilch/demo-br-asyncua | Minimal Python example accessing a B&R PLC via asyncua (asyncio-based OPC-UA stack). Alternative to the Python OPC-UA client examples in python-diagnostics.md |
| mappRemoteShell | github.com/br-automation-community/mappRemoteShell | Sample project executing shell commands on a remote PC via OPC-UA + Python — demonstrates bidirectional OPC-UA communication for remote diagnostics |
| mappPanel | github.com/br-automation-community/mappPanel | Sample for PLC to T-Panel communication over OPC-UA — useful for understanding panel integration patterns |
Document updated: July 2026 (added security considerations section §13 with CVE-2025-11482/PPT30 OPC-UA DoS, OPC-UA hardening checklist; added community OPC-UA tools section)