C · recipe

Read a value from an OPC UA server in C

The high-level API gives you UA_Client_readValueAttribute for a bare value; use a full UA_ReadRequest when you need the status code and timestamps too. Always check the type before dereferencing the variant's data.

Stackopen62541
Version1.5.8

The code

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

int main(void) {
    UA_Client *client = UA_Client_new();
    UA_ClientConfig_setDefault(UA_Client_getConfig(client));
    if (UA_Client_connect(client, "opc.tcp://opcua.umati.app:4840") != UA_STATUSCODE_GOOD) {
        UA_Client_delete(client); return 1;
    }

    /* full read: value + status + both timestamps */
    UA_ReadValueId rvi;
    UA_ReadValueId_init(&rvi);
    rvi.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
    rvi.attributeId = UA_ATTRIBUTEID_VALUE;

    UA_ReadRequest req;
    UA_ReadRequest_init(&req);
    req.nodesToRead = &rvi;
    req.nodesToReadSize = 1;
    req.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH;

    UA_ReadResponse res = UA_Client_Service_read(client, req);

    if (res.resultsSize == 1) {
        UA_DataValue *dv = &res.results[0];
        printf("status : %s\n", UA_StatusCode_name(dv->status));
        printf("hasValue: %d  sourceTs: %d\n",
               dv->hasValue, dv->hasSourceTimestamp);
        if (dv->hasValue && dv->value.type == &UA_TYPES[UA_TYPES_DATETIME]) {
            UA_DateTimeStruct ts =
                UA_DateTime_toStruct(*(UA_DateTime *)dv->value.data);
            printf("value  : %04u-%02u-%02u %02u:%02u:%02u\n",
                   ts.year, ts.month, ts.day, ts.hour, ts.min, ts.sec);
        }
    }

    UA_ReadResponse_clear(&res);
    UA_Client_disconnect(client);
    UA_Client_delete(client);
    return 0;
}

What it prints

status : Good
hasValue: 1  sourceTs: 1
value  : 2026-09-08 03:44:59

Notes

  • Always compare variant.type against the expected UA_TYPES entry before casting data. A type assumption here is a segfault, not an exception.
  • The hasValue, hasStatus, hasSourceTimestamp flags on UA_DataValue exist because any of them may be absent. Check them.
  • UA_Client_readValueAttribute is the convenient form when you only want the value. Use the service call when the status and timestamps matter, which for stored data is always.
  • Batch multiple nodesToRead in one request. On a constrained device the round-trip saving is significant.

What breaks first

The process segfaults on a value that read fine yesterday BadTypeMismatch
The node's data type changed, or you assumed a type without checking. Compare variant.type before every cast.

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