C · recipe

Write a value to an OPC UA server in C

Build a variant with the scalar type the node declares and write it. Read the DataType attribute first rather than assuming, and check the returned status, a write that is refused returns a code, not a crash.

Stackopen62541
Version1.5.8

The code

#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <stdio.h>

/* umati is read-only. Run a local server:
     ./examples/server_ctt   (from an open62541 build)   */
int main(void) {
    UA_Client *client = UA_Client_new();
    UA_ClientConfig_setDefault(UA_Client_getConfig(client));
    if (UA_Client_connect(client, "opc.tcp://localhost:4840") != UA_STATUSCODE_GOOD) {
        UA_Client_delete(client); return 1;
    }

    UA_NodeId target = UA_NODEID_STRING(1, "the.answer");

    /* check what the node expects before writing */
    UA_NodeId dataType;
    UA_NodeId_init(&dataType);
    UA_StatusCode rc = UA_Client_readDataTypeAttribute(client, target, &dataType);
    if (rc == UA_STATUSCODE_GOOD)
        printf("declared datatype: ns=%d;i=%d\n",
               dataType.namespaceIndex, dataType.identifier.numeric);
    UA_NodeId_clear(&dataType);

    UA_Int32 value = 42;
    UA_Variant v;
    UA_Variant_init(&v);
    UA_Variant_setScalar(&v, &value, &UA_TYPES[UA_TYPES_INT32]);

    rc = UA_Client_writeValueAttribute(client, target, &v);
    printf("write: %s\n", UA_StatusCode_name(rc));

    /* read back - a Good status does not prove the value stuck */
    UA_Variant back;
    UA_Variant_init(&back);
    if (UA_Client_readValueAttribute(client, target, &back) == UA_STATUSCODE_GOOD &&
        back.type == &UA_TYPES[UA_TYPES_INT32])
        printf("read back: %d\n", *(UA_Int32 *)back.data);
    UA_Variant_clear(&back);

    UA_Client_disconnect(client);
    UA_Client_delete(client);
    return 0;
}

What it prints

declared datatype: ns=0;i=6
write: Good
read back: 42

Notes

  • UA_Variant_setScalar does not copy: the variant points at your stack variable. Keep it alive until the write returns, or use UA_Variant_setScalarCopy.
  • Read the DataType attribute. UA_TYPES_INT32 is not UA_TYPES_INT16, and the server will refuse the mismatch.
  • Read back in tests. Some servers, including the umati sample server, accept writes and discard them.
  • For arrays use UA_Variant_setArray and match ValueRank. A scalar into an array node is a type mismatch.

What breaks first

The write returns Good but the value never changes GoodClamped
Either the server clamped your value into range, or it accepted and discarded the write. Read back, and check AccessLevel and EURange.

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login