A .NET global tool that connects to an OPC UA server and exports all custom namespaces into separate NodeSet2 XML files.
- 🔗 Connect to any OPC UA server
- 📦 Export namespaces to NodeSet2 XML format
- 🔒 Support for multiple security modes (None, Sign, SignAndEncrypt)
- 🔐 Multiple authentication methods (Anonymous, Username/Password, X.509 Certificate)
- 🔄 Automatic reconnection with configurable retry logic
- 🖥️ Cross-platform (Windows, Linux, macOS)
- 📝 Credential input via stdin for CI/CD pipelines
- 🩺 Optional attribute diagnostics (
--export-attributes): JSON sidecar with every standard attribute (incl.Value) and itsStatusCodeper node
dotnet tool install --global OpcUaNodesetExporter# Export namespaces with anonymous authentication
opcua-nodeset-export --endpoint opc.tcp://localhost:4840
# Export with username/password authentication
opcua-nodeset-export --endpoint opc.tcp://server:4840 --auth-mode UserName --username admin --password secret
# Export with environment variables
export OPCUA_ENDPOINT=opc.tcp://server:4840
export OPCUA_USERNAME=admin
export OPCUA_PASSWORD=secret
opcua-nodeset-export --auth-mode UserNameopcua-nodeset-export [options]
Options:
-e, --endpoint <endpoint> OPC UA server endpoint URL (e.g., opc.tcp://localhost:4840)
-s, --start-node <node> Export subtree from this ExpandedNodeId (e.g., nsu=example.com/opcua/;i=5)
-m, --security-mode <mode> Security mode: None, Sign, SignAndEncrypt [default: None]
-p, --security-policy <policy> Security policy: None, Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss [default: None]
-a, --auth-mode <mode> Authentication mode: Anonymous, UserName, Certificate [default: Anonymous]
-u, --username <username> Username for UserName authentication
--password <password> Password for UserName authentication
--password-from-stdin Read password from stdin (for piping)
-c, --certificate-path <path> Path to client X.509 certificate (PFX format)
--certificate-password <pwd> Password for the client certificate
--certificate-from-stdin Read certificate (base64 PFX) from stdin
-o, --output <directory> Output directory for NodeSet2 XML files [default: ./output]
--retry-count <count> Number of reconnection attempts on disconnect [default: 3]
--retry-delay <seconds> Delay between retries in seconds [default: 5]
--keep-alive <seconds> Keep-alive interval in seconds [default: 5]
--session-timeout <seconds> Session timeout in seconds [default: 120]
--keep-alive-threshold <count> Missed keep-alives before reconnect [default: 3]
--export-attributes Read all standard attributes (incl. Value) and write a JSON
sidecar per NodeSet2 file with attribute values and status codes
--log-file <path> Also append all log output to this file (Debug level when
--verbose is set, otherwise Information). Parent directories
are created on demand.
-v, --verbose Enable verbose logging
-?, -h, --help Show help and usage information
The following environment variables can be used to configure the tool:
| Variable | Description | CLI Equivalent |
|---|---|---|
OPCUA_ENDPOINT |
OPC UA server endpoint URL | --endpoint |
OPCUA_START_NODE |
ExpandedNodeId for subtree export | --start-node |
OPCUA_USERNAME |
Username for authentication | --username |
OPCUA_PASSWORD |
Password for authentication | --password |
OPCUA_CERTIFICATE_PATH |
Path to client certificate | --certificate-path |
OPCUA_CERTIFICATE_PASSWORD |
Client certificate password | --certificate-password |
OPCUA_LOG_FILE |
Optional log file path | --log-file |
# Export to default output directory (./output)
opcua-nodeset-export -e opc.tcp://localhost:4840
# Export to custom directory
opcua-nodeset-export -e opc.tcp://localhost:4840 -o ./my-nodesetsExport a specific subtree starting from a given node. Only type definitions in the same namespace as the start node are included; types from other namespaces are referenced but not exported.
# Export subtree starting from a specific node (ExpandedNodeId format)
opcua-nodeset-export -e opc.tcp://localhost:4840 -s "ns=4;i=5"
# Export subtree with custom output directory
opcua-nodeset-export -e opc.tcp://localhost:4840 -s "ns=4;i=5" -o ./subtree-export
# Export subtree using a string node ID
opcua-nodeset-export -e opc.tcp://localhost:4840 -s "ns=3;s=MyDevice"The output is a single NodeSet2 XML file containing:
- The start node and all its subnodes (via hierarchical references)
- Type definitions used by the subtree that are in the same namespace as the start node
- Supertypes of included types (if also in the same namespace)
By default the exporter populates only the attributes that the OPC UA Browse
service returns. Every other attribute (such as Value, ValueRank,
MinimumSamplingInterval, DataType, AccessLevel, ...) is re-read from
the server before serialization, so the produced NodeSet2 XML reflects the
real address space — ValueRank="-2" and MinimumSamplingInterval="-1" no
longer leak through as the SDK's in-memory defaults.
--export-attributes additionally:
- Reads the
Valueattribute of every Variable / VariableType node, so the NodeSet2 XML contains a<Value>element when the server returned data. - Writes a JSON diagnostic file alongside each NodeSet2 XML named
<namespace>_attributes.json. The file records every attribute relevant to each node'sNodeClasstogether with the OPC UAStatusCodereturned by the server. This makes it easy to spot variables that have an empty value, returnBadAttributeIdInvalid, or otherwise fail to read.
# Full export with attribute diagnostics
opcua-nodeset-export -e opc.tcp://localhost:4840 --export-attributes
# Subtree export with diagnostics (works in both modes)
opcua-nodeset-export -e opc.tcp://localhost:4840 -s "ns=4;i=5" --export-attributesExample excerpt of <namespace>_attributes.json:
{
"namespaceUri": "http://example.com/devices/",
"namespaceIndex": 4,
"exportedAt": "2026-06-10T18:42:00Z",
"nodes": [
{
"nodeId": "ns=4;i=1234",
"browseName": "4:MyVar",
"displayName": "MyVar",
"nodeClass": "Variable",
"attributes": {
"Value": { "status": "Good", "statusCode": "0x00000000", "value": 42 },
"DataType": { "status": "Int32", "statusCode": "0x00000000", "value": "i=6" },
"ValueRank": { "status": "Good", "statusCode": "0x00000000", "value": -1 },
"AccessLevel": { "status": "Good", "statusCode": "0x00000000", "value": 3 },
"MinimumSamplingInterval": { "status": "BadNotReadable", "statusCode": "0x803A0000", "value": null }
}
}
]
}# Sign messages
opcua-nodeset-export -e opc.tcp://localhost:4840 \
--security-mode Sign \
--security-policy Basic256Sha256
# Sign and encrypt messages
opcua-nodeset-export -e opc.tcp://localhost:4840 \
--security-mode SignAndEncrypt \
--security-policy Aes256_Sha256_RsaPss# Username and password
opcua-nodeset-export -e opc.tcp://localhost:4840 \
--auth-mode UserName \
--username admin \
--password secret
# X.509 certificate
opcua-nodeset-export -e opc.tcp://localhost:4840 \
--auth-mode Certificate \
--certificate-path ./client.pfx \
--certificate-password certpass# Password from stdin (Linux/macOS)
echo "$OPC_PASSWORD" | opcua-nodeset-export -e opc.tcp://server:4840 \
--auth-mode UserName \
--username admin \
--password-from-stdin
# Certificate from stdin (base64 encoded PFX)
cat client.pfx | base64 | opcua-nodeset-export -e opc.tcp://server:4840 \
--auth-mode Certificate \
--certificate-from-stdin \
--certificate-password certpass
# Using environment variables in GitHub Actions
env:
OPCUA_ENDPOINT: opc.tcp://server:4840
OPCUA_USERNAME: ${{ secrets.OPC_USERNAME }}
OPCUA_PASSWORD: ${{ secrets.OPC_PASSWORD }}
run: opcua-nodeset-export --auth-mode UserName# Password from stdin
$env:OPC_PASSWORD | opcua-nodeset-export -e opc.tcp://server:4840 `
--auth-mode UserName `
--username admin `
--password-from-stdin
# Using environment variables
$env:OPCUA_ENDPOINT = "opc.tcp://server:4840"
$env:OPCUA_USERNAME = "admin"
$env:OPCUA_PASSWORD = "secret"
opcua-nodeset-export --auth-mode UserNameThe tool creates one NodeSet2 XML file per namespace in the output directory:
./output/
├── my.company.com_machines_ns2.xml
├── my.company.com_sensors_ns3.xml
└── vendor.example.com_devices_ns4.xml
Notes:
- Namespace 0 (OPC UA base types) is excluded
- OPC Foundation companion specifications (
http://opcfoundation.org/UA/*) are excluded - File names are derived from namespace URIs with invalid characters replaced
The tool uses a directory-based certificate store for cross-platform compatibility:
~/.opcua-nodeset-export/pki/
├── own/
│ ├── certs/ # Application certificate
│ └── private/ # Private key
├── trusted/
│ └── certs/ # Trusted server certificates
├── rejected/ # Rejected certificates
└── issuers/ # CA certificates
Certificate Trust Policy:
- Server certificates are automatically trusted (for development/testing)
- SHA1 signatures and 1024-bit keys are accepted (for legacy server compatibility)
For production environments, consider implementing proper certificate validation.
The tool automatically handles connection interruptions:
- Retries on transient errors (network issues, server restarts)
- Exponential backoff between retry attempts
- Configurable retry count and delay
- Keep-alive monitoring with automatic reconnection on failure
# Custom retry settings
opcua-nodeset-export -e opc.tcp://server:4840 \
--retry-count 5 \
--retry-delay 10The client sends periodic keep-alive requests to detect connection issues early. If the server doesn't respond, the client automatically attempts to reconnect.
| Option | Default | Description |
|---|---|---|
--keep-alive |
5 | Interval between keep-alive requests (seconds) |
--session-timeout |
120 | Maximum time server keeps session alive without communication (seconds) |
--keep-alive-threshold |
3 | Number of missed keep-alives before triggering reconnection |
For slow or unreliable networks:
opcua-nodeset-export -e opc.tcp://server:4840 \
--session-timeout 300 \
--keep-alive 10 \
--keep-alive-threshold 5This configuration gives more tolerance for temporary network issues by extending the session timeout to 5 minutes and allowing up to 5 missed keep-alives (~50 seconds) before reconnecting.
# Clone the repository
git clone https://github.com/your-org/OpcUaNodesetExporter.git
cd OpcUaNodesetExporter
# Build
dotnet build
# Run tests
dotnet test
# Pack as tool
dotnet pack -c Release
# Install locally
dotnet tool install --global --add-source ./src/OpcUaNodesetExporter/nupkg OpcUaNodesetExporterIntegration tests use .NET Aspire to run an OPC UA server simulation:
# Run integration tests (requires Docker)
dotnet test --filter "Category=Integration"# Enable verbose logging
opcua-nodeset-export -e opc.tcp://server:4840 --verbose
# Capture verbose log output to a file (in addition to the console)
opcua-nodeset-export -e opc.tcp://server:4840 --verbose --log-file ./logs/export.logIf you see certificate-related errors:
- Check that the PKI directory exists:
~/.opcua-nodeset-export/pki/ - Verify the server certificate is accessible
- For secure connections, ensure your client certificate is valid
Increase retry settings for slow networks or large servers:
opcua-nodeset-export -e opc.tcp://server:4840 \
--retry-count 10 \
--retry-delay 30If you see errors like Keep-alive error: [80310000] 'Server not responding to keep alive requests.':
-
Increase session timeout for slow networks:
opcua-nodeset-export -e opc.tcp://server:4840 --session-timeout 300
-
Reduce keep-alive frequency if the server is overloaded:
opcua-nodeset-export -e opc.tcp://server:4840 --keep-alive 15
-
Increase failure tolerance for unstable connections:
opcua-nodeset-export -e opc.tcp://server:4840 --keep-alive-threshold 5
This project is licensed under the MIT License - see the LICENSE file for details.
- Built on the OPC Foundation UA .NET Standard stack
- Uses the SDK's verified
CoreClientUtils.ExportNodesToNodeSet2for NodeSet2 export functionality