Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing



  • Dear Community,

    currently I am in the process of setting up a small network which consists of the following components:

    • Raspberry Pi 4B with Codesys V3.5 SP16 Patch 4 Runtime --> role of the OPC UA Server

    • Raspberry Pi 4B with Qt 5.15.2 Cross Compilated Application --> role of the OPC UA Client

    I managed to get a connection between the two network participants.
    The Qt OPC UA Client receives the values of the Codesys OPC UA Server. That means, when I change the values within Codesys, my Qt Application displays the value changes right on time. My Problem is:
    If I want to change the Codesys Server value on the other way with the Qt Application as writing Client, nothing happens.
    I am only getting the following error message within the window of Qt Creator:

    [2021-01-28 20:00:41.096 (UTC+0100)] info/client	
    Received a ServiceFault response with StatusCode BadServiceUnsupported
    qt.opcua.plugins.open62541: Could not call method: BadServiceUnsupported
    

    Does anyone had the same problem with this kind of network?
    Is there a possibility to find the error side? Codesys or Qt Error?

    Thank you in Advance!



  • hi
    @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    If I want to change the Codesys Server value on the other way with the Qt Application as writing Client, nothing happens.

    How exactly did you do that ?
    It looks like you are trying to call an opcua method but your serrver does not support it (yet?), you could ask Codesys support for more informations.

    As an alternative, you can use QOpcUaNode::writeAttribute() if method calls are really unsuported



  • hi @LeLev

    I am using this Method Call:

    void OpcuaModuleBackend::WriteValueDriveActuatorSpeed2(double value)
    {
        if (m_DriveActuatorSpeed2Node)
            m_DriveActuatorSpeed2Node->writeAttribute(QOpcUa::NodeAttribute::Value, value);
    }
    

    I asked Codesys ... They are not supporting third party software.
    After that, I tried to explore the Codesys Server by using UA Expert from Unified Automation:

    It seems, Codesys is not supporting Method-Calls (refering to grey lines in the attribute mask)
    75d25281-6511-46be-a5c1-180bb1782d6a-grafik.png

    I will try to use OpcUaNode::writeAttribute(), because Method Calls are not supported, I guess.

    Thank you!



  • @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    I am using this Method Call:

    We misunderstood each other, i was asking if you using this method
    https://doc-snapshots.qt.io/qtopcua/qopcuanode.html#callMethod
    because of the output "qt.opcua.plugins.open62541: Could not call method: BadServiceUnsupported"

    but you are actually using writeAttribute() method in the code you show, i think the error/massage is not caused by the code you show.

    Are you using QOpcUaNode::callMethod() function somewhere in your program ?

    @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    if (m_DriveActuatorSpeed2Node)
    m_DriveActuatorSpeed2Node->writeAttribute(QOpcUa::NodeAttribute::Value, value);

    You can connect a slot to QOpcUaNode::attributeWritten signal of your m_DriveActuatorSpeed2Node and see the status for that call.



  • @LeLev

    yes, I missunderstood your answer. Sorry for that.

    I am using two functions for writing variables on the Codesys Server:

    void OpcuaModuleBackend::WriteValueDriveActuatorSpeed2(double value)
    {
        if (m_DriveActuatorSpeed2Node)
            m_DriveActuatorSpeed2Node->writeAttribute(QOpcUa::NodeAttribute::Value, value);
    }
    
    void OpcuaModuleBackend::StartModule()
    {
        if (m_ModuleNode)
            m_ModuleNode->callMethod("ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GlobaleVariablenliste.ModuleState");
    }
    

    The error message, that I posted is linked with the method call. That's right.
    On Codesys Server side unfortunatly I found nothing to implement method-calls.

    @LeLev said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    You can connect a slot to QOpcUaNode::attributeWritten signal of your m_DriveActuatorSpeed2Node and see the status for that call.

    I have done this by using this code to connect the signal "QOpcUaNode::attributeWritten" with the slot "AttributeWritten".

     QObject::connect(m_DriveActuatorSpeed1Node.data(), &QOpcUaNode::attributeWritten, this, &OpcuaModuleBackend::AttributeWritten);
    
    

    Here is the code of the slot:

    void OpcuaModuleBackend::AttributeWritten(QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode status)
    {
        if (attr == QOpcUa::NodeAttribute::Value && status == QOpcUa::UaStatusCode::Good)
            setMessage("Attribute successfully written");
        else if (attr == QOpcUa::NodeAttribute::Value && status != QOpcUa::UaStatusCode::Good)
            setMessage("Failed to write Attribute");
    }
    

    After trying this code, I had no status for the WriteAttribute() Call . What is wrong here ?

    Thank you in Advance!



  • @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    if (attr == QOpcUa::NodeAttribute::Value && status == QOpcUa::UaStatusCode::Good)
    setMessage("Attribute successfully written");

    What exactly that setMessage() function does ? Can you simply check what the actual status is ?



  • @LeLev I copied the slot code from the official waterpump example`s slot:

    void OpcuaModuleBackend::setpointWritten(QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode status)
    {
        if (attr == QOpcUa::NodeAttribute::Value && status == QOpcUa::UaStatusCode::Good)
            setMessage("Setpoint successfully set");
        else if (attr == QOpcUa::NodeAttribute::Value && status != QOpcUa::UaStatusCode::Good)
            setMessage("Failed to set setpoint");
    }
    

    But that did not help. After that I used qDebug:

    void OpcuaModuleBackend::AttributeWritten(QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode status)
    {
        qDebug() << Q_FUNC_INFO << "Attribute Written Status" << status;
    }
    

    After using qDebug I`ve got the following error:

    void OpcuaModuleBackend::AttributeWritten(QOpcUa::NodeAttribute, QOpcUa::UaStatusCode) Attribute Written Status QOpcUa::BadTypeMismatch
    

    So is that the right way to check the status of the WriteAttribute() Call?



  • @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    So is that the right way to check the status of the WriteAttribute() Call?

    Yes it is.

    you are trying to send a double value

    WriteValueDriveActuatorSpeed2(double value)
    

    but as the status code says
    @Mauda said in Qt OPC UA Client and Codesys OPC UA Server: Problems with Writing:

    Written Status QOpcUa::BadTypeMismatch

    it looks like you are sending wrong datatype, m_DriveActuatorSpeed2Node value type is not "double". Look with UaExpert what is the type of the value of that node and make sure your WriteValueDriveActuatorSpeed2() function takes/sends the matching type



  • @LeLev thank you for your fast answer!

    it looks like you are sending wrong datatype, m_DriveActuatorSpeed2Node value type is not "double". Look with UaExpert what is the type of the value of that node and make sure your WriteValueDriveActuatorSpeed2() function takes/sends the matching type

    You are totally right. I was sending the wrong datatype the whole time. After checking Qt-Documentation, I found this interesting table, which shows the matching combination of Qt-Datatypes and OPC UA Datatypes:

    https://doc-snapshots.qt.io/qtopcua/qopcuanode.html#writeValueAttribute
    08443165-6844-42c8-b150-1163fb8b42a1-grafik.png

    My server is using UInt32 Datatypes. I switched the Datatype within the following code from "double" to "uint" and it worked. Heureka :)

    void OpcuaModuleBackend::WriteValueDriveActuatorSpeed1(uint value)
    {
        if (m_DriveActuatorSpeed1Node)
            m_DriveActuatorSpeed1Node->writeAttribute(QOpcUa::NodeAttribute::Value, value);
    }
    

    @LeLev thank you very much for helping me to solve my problem !



  • You're welcome :)


Log in to reply