Waterpump Example

Waterpump shows how to use Qt OPC UA to interact with an OPC UA server to build a QML-based HMI for a simple machine.

Building the Server

Before you can use the waterpump examples, you need to build the simulation server. The simulator server project resides next to the waterpump examples. You can open and build it in QtCreator or from the terminal as usual.

The Simulation

The OPC UA server included in this example runs a simulation of a machine containing two tanks, a water pump, and a valve. Water can be pumped from the first tank into the second tank and then be flushed from the second tank by opening the valve. Both operations have a user-configurable setpoint which controls how much water is pumped to or flushed from the second tank.

The following nodes exist on the server:

NodeId

Function

ns=2;s=Machine

The folder containing the method and variable nodes for the machine

ns=2;s=Machine.State

The state of the machine

ns=2;s=Machine.Tank1.PercentFilled

The current fill status of the first tank

ns=2;s=Machine.Tank2.PercentFilled

The current fill status of the second tank

ns=2;s=Machine.Tank2.TargetPercent

The setpoint for pumping and flushing

ns=2;s=Machine.Tank2.ValveState

The state of the valve of the second tank

ns=2;s=Machine.Designation

A human readable designation of the machine for display purposes

ns=2;s=Machine.Start

Call this method to start the pump

ns=2;s=Machine.Stop

Call this method to stop the pump

ns=2;s=Machine.FlushTank2

Call this method to flush tank 2

All methods return Good in case of success and BadUserAccessDenied if the operation is illegal (for example, trying to start the pump if the first tank is empty).

Client Features

This example uses read, write, method calls, and data change subscriptions and shows how to set up handlers for the asynchronous operations offered by QOpcUaClient and QOpcUaNode.

Implementation

A backend class is used to handle the communication with the OPC UA server and expose the content of this server by means of properties and Q_INVOKABLE methods wrapping the OPC UA method calls.

Member Variables

A pointer to QOpcUaClient is required for connection management. An additional pointer to a QOpcUaNode object is needed for each OPC UA node the HMI interacts with. For the values of these nodes, member variables containing the last value reported by the server are added.

 
Sélectionnez
    ...
    QScopedPointer<QOpcUaClient> m_client;
    QScopedPointer<QOpcUaNode> m_machineStateNode;
    QScopedPointer<QOpcUaNode> m_percentFilledTank1Node;
    QScopedPointer<QOpcUaNode> m_percentFilledTank2Node;
    QScopedPointer<QOpcUaNode> m_tank2TargetPercentNode;
    QScopedPointer<QOpcUaNode> m_tank2ValveStateNode;
    QScopedPointer<QOpcUaNode> m_machineNode;
    QScopedPointer<QOpcUaNode> m_machineDesignationNode;
    double m_percentFilledTank1;
    double m_percentFilledTank2;
    double m_tank2TargetPercent;
    bool m_tank2ValveState;
    MachineState m_machineState;
    QString m_machineDesignation;
    ...

For each value used in the HMI, a getter, a changed signal, and a property are added to enable property bindings in QML

 
Sélectionnez
    ...
    Q_PROPERTY(double percentFilledTank1 READ percentFilledTank1 NOTIFY percentFilledTank1Changed)
    Q_PROPERTY(double percentFilledTank2 READ percentFilledTank2 NOTIFY percentFilledTank2Changed)
    Q_PROPERTY(double tank2TargetPercent READ tank2TargetPercent NOTIFY tank2TargetPercentChanged)
    Q_PROPERTY(OpcUaMachineBackend::MachineState machineState READ machineState NOTIFY machineStateChanged)
    Q_PROPERTY(bool tank2ValveState READ tank2