opc.tcp · UA Binary
OPC UA Server
Put an in-memory OPC UA server into your application. Register variables, expose them on secure endpoints and answer clients while you call poll.
What it does
- opc.tcp and UA Binary with the Basic256Sha256, Aes128_Sha256_RsaOaep and Aes256_Sha256_RsaPss policies.
- Browse, Read, Write and Call, plus Subscriptions and MonitoredItems.
- Add variables and set or read their values.
- Public variables, including for anonymous users, and variables for authenticated users only.
- Build the server from C, C++ or .NET.
Example
Each binding shows code from a real example file in the examples folder of the PDComm SDK. The source file and line range appear above the code.
OPC UA C server
bind.data = (const uint8_t *)argv[1];
bind.size = strlen(argv[1]);
status = pdcomm_opcua_server_create(bind, &options, &server);
example_wipe(key, key_size); /* The SDK copied the identity. */
key = NULL;
if (status != PDCOMM_OPCUA_OK) { print_error("create", status); goto done; }
status = add(server, 1001, "Value", 42, PDCOMM_OPCUA_VARIABLE_WRITABLE | PDCOMM_OPCUA_VARIABLE_PUBLIC);
if (status == PDCOMM_OPCUA_OK) status = add(server, 1002, "Limit", 100, PDCOMM_OPCUA_VARIABLE_PUBLIC);
if (status == PDCOMM_OPCUA_OK) status = add(server, 1003, "Protected", 7, PDCOMM_OPCUA_VARIABLE_WRITABLE);
if (status != PDCOMM_OPCUA_OK) {
print_error("add_variable", status);
goto done;
}
status = pdcomm_opcua_server_local_address(server, &address);
if (status == PDCOMM_OPCUA_OK)
status = pdcomm_opcua_buffer_copy(address, text, sizeof(text) - 1, &size);
if (status != PDCOMM_OPCUA_OK) { print_error("local_address", status); goto done; }
text[size] = 0;
/* Install the stop handlers before announcing readiness. */
signal(SIGINT, on_signal);
signal(SIGTERM, on_signal);
#ifdef SIGBREAK
signal(SIGBREAK, on_signal); /* Windows Ctrl+Break, e.g. from a service manager */
#endif
printf("Listening on %s\n", (const char *)text);
started = time(NULL);
while (!stop_requested && (!seconds || difftime(time(NULL), started) < (double)seconds)) {
status = pdcomm_opcua_server_poll(server);
if (status != PDCOMM_OPCUA_OK) { print_error("poll", status); goto done; }
example_sleep_ms(1);
}From the C example: create a secure-only server from the server certificate, private key and trusted client certificate, add three Int32 variables, then serve requests by calling pdcomm_opcua_server_poll() in a loop.
OPC UA C++ server
const std::string endpoint = argv[2];
const auto certificate = load(argv[3]);
auto key = load(argv[4]);
const auto trust = load(argv[5]);
auto config = ua::server_options();
config.endpoint = ua::bytes(endpoint);
config.certificate_der = ua::bytes(certificate);
config.private_key_pem = ua::bytes(key);
config.trusted_client_der = ua::bytes(trust);
auto server = ua::server::create(argv[1], config);
std::fill(key.begin(), key.end(), static_cast<unsigned char>(0)); // The SDK copied the identity.
server.add_variable(node_id(1001), "Value", int32_variant(42),
PDCOMM_OPCUA_VARIABLE_WRITABLE | PDCOMM_OPCUA_VARIABLE_PUBLIC);
server.add_variable(node_id(1002), "Limit", int32_variant(100), PDCOMM_OPCUA_VARIABLE_PUBLIC);
server.add_variable(node_id(1003), "Protected", int32_variant(7), PDCOMM_OPCUA_VARIABLE_WRITABLE);
const auto address = server.local_address().copy();
// Install the stop handlers before announcing readiness.
std::signal(SIGINT, on_signal);
std::signal(SIGTERM, on_signal);
#ifdef SIGBREAK
std::signal(SIGBREAK, on_signal); // Windows Ctrl+Break, e.g. from a service manager
#endif
std::cout << "Listening on " << std::string(address.begin(), address.end()) << std::endl;
const auto started = std::chrono::steady_clock::now();
while (!stop_requested &&
(!seconds || std::chrono::steady_clock::now() - started < std::chrono::seconds(seconds))) {
server.poll();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
const auto snapshot = server.read_value(node_id(1001)).copy();
ua_value value;
if (ua_decode_data_value(snapshot.data(), snapshot.size(), &value) || !value.has_int32)
throw std::runtime_error("Unexpected DataValue");
server.close();
std::cout << "Final Value=" << value.int32 << "\nServer stopped" << std::endl;From the C++ example: ua::server::create builds the server, add_variable adds a public writable, a public read-only and an authenticated-only variable, and poll() runs in a loop. At the end it reads the final value locally.
OPC UA .NET server
byte[] key = Load(a[3]);
Server server;
try
{
server = Server.Create(a[0], new ServerOptions
{
Endpoint = a[1], CertificateDer = Load(a[2]), PrivateKeyPem = key, TrustedClientDer = Load(a[4]),
});
}
finally { CryptographicOperations.ZeroMemory(key); } // The SDK copied the identity.
using (server)
{
server.AddVariable(UaBinary.NodeId(1001), "Value", UaBinary.Int32Variant(42), VariableFlags.Writable | VariableFlags.Public);
server.AddVariable(UaBinary.NodeId(1002), "Limit", UaBinary.Int32Variant(100), VariableFlags.Public);
server.AddVariable(UaBinary.NodeId(1003), "Protected", UaBinary.Int32Variant(7), VariableFlags.Writable);
// Register the stop signals before announcing readiness.
using var stop = new ManualResetEventSlim();
using var interrupt = PosixSignalRegistration.Create(PosixSignal.SIGINT, c => { c.Cancel = true; stop.Set(); });
using var terminate = PosixSignalRegistration.Create(PosixSignal.SIGTERM, c => { c.Cancel = true; stop.Set(); });
// Windows Ctrl+Break (SIGQUIT in .NET), e.g. from a service manager.
using var breakSignal = OperatingSystem.IsWindows()
? PosixSignalRegistration.Create(PosixSignal.SIGQUIT, c => { c.Cancel = true; stop.Set(); }) : null;
using (var address = server.LocalAddress())
Console.WriteLine($"Listening on {Encoding.UTF8.GetString(address.Copy())}");
var clock = Stopwatch.StartNew();
while (!stop.IsSet && (seconds == 0 || clock.Elapsed < TimeSpan.FromSeconds(seconds)))
{
server.Poll();
stop.Wait(1);
}The server mode of the .NET example: Server.Create builds the server, three variables are added, and Poll runs until a stop signal arrives.
Related modules
MQTT 5.0 · UADP
MQTT for OPC UA PubSub
MQTT 5.0 as the broker transport of OPC UA PubSub. The OPC UA simulator's GUI, headless program and MCP server publish and subscribe UADP messages through a broker.
Learn moreopc.tcp · UA Binary
OPC UA Client
Put an OPC UA client into your application. The SDK handles secure channels, sessions and certificate validation.
Learn more