c++opcopc-uasiemensopen62541

Writing value to PLC tag with open62541


I am trying to write bool value to PLC Tag (turn relay on or off) using OPC UA as Client writing to OPC UA Server running on Siemens S7-1512 PLC. The client must be implemented in c/c++

I have tried a few different GUI clients with no issues.

Also, I have tried Python SDK including freeopcua. I had slight issues but was able to write value after setting an attribute in the write request. But with open62541 I can't find any solution to that (status code is good but value is not changed I am able to read values):

Python working request:

node.set_attribute(ua.AttributeIds.Value, ua.DataValue(not node.get_value()))

C not working request code below:

    UA_WriteRequest request;
    UA_WriteRequest_init(&request);


    request.nodesToWrite = UA_WriteValue_new();
    request.nodesToWriteSize = 1;

    request.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(3, "\"VALUE\"");
    request.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE;
    request.nodesToWrite[0].value.hasValue = true;
    request.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
    request.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE;
    request.nodesToWrite[0].value.hasServerTimestamp = true;
    request.nodesToWrite[0].value.hasSourceTimestamp = true;
    request.nodesToWrite[0].value.sourceTimestamp = UA_DateTime_now();
    request.nodesToWrite[0].value.value.data = val;

    request.requestHeader.timestamp = UA_DateTime_now();
    request.requestHeader.authenticationToken = UA_NODEID_NUMERIC(0, UA_NS0ID_SESSIONAUTHENTICATIONTOKEN);

    //write to client service
    UA_WriteResponse wResp = UA_Client_Service_write(client, request);

I expect value for PLC tag to be changed to the opposite value or provide me with info on why it won't work.


Solution

  • Better use the client high level api:

    UA_NodeId nodeid = UA_NODEID_STRING_ALLOC(3, "\"VALUE\"");
    UA_Boolean value = true;
    UA_Variant *var= UA_Variant_new();
    UA_Variant_setScalarCopy(var, &value, &UA_TYPES[UA_TYPES_BOOLEAN]);
    UA_StatusCode ret = UA_Client_writeValueAttribute(client, nodeid, var);
    ....
    UA_Variant_delete(var);
    

    The reason it is rejected, is that you trie to set the Timestamp in your write request. Most server refuse that.