diff options
Diffstat (limited to 'src/OpcUaClient.h')
| -rw-r--r-- | src/OpcUaClient.h | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/OpcUaClient.h b/src/OpcUaClient.h new file mode 100644 index 0000000..1476911 --- /dev/null +++ b/src/OpcUaClient.h @@ -0,0 +1,193 @@ +/** + * @file OpcUaClient.h + * @brief QML singleton managing the OPC UA connection lifecycle. + * + * Wraps QOpcUaClient into a declarative interface: LDS discovery, + * endpoint selection, PKI, and certificate trust flow. + * Single connection at a time (app-wide singleton). + */ +#ifndef OPCUACLIENT_H +#define OPCUACLIENT_H + +#include <QEventLoop> +#include <QObject> +#include <QOpcUaApplicationDescription> +#include <QOpcUaClient> +#include <QOpcUaEndpointDescription> +#include <QOpcUaErrorState> +#include <QOpcUaProvider> +#include <QQmlEngine> +#include <QTimer> + +class OpcUaAuth; + +class OpcUaClient : public QObject +{ + Q_OBJECT + QML_SINGLETON + QML_NAMED_ELEMENT (Bobink) + + /* -- Connection -- */ + Q_PROPERTY (bool connected READ connected NOTIFY connectedChanged) + Q_PROPERTY (QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY + serverUrlChanged) + Q_PROPERTY (OpcUaAuth *auth READ auth WRITE setAuth NOTIFY authChanged) + + /* -- Discovery -- */ + Q_PROPERTY (QString discoveryUrl READ discoveryUrl WRITE setDiscoveryUrl + NOTIFY discoveryUrlChanged) + Q_PROPERTY (bool discovering READ discovering NOTIFY discoveringChanged) + Q_PROPERTY (QVariantList servers READ servers NOTIFY serversChanged) + + /* -- PKI -- */ + Q_PROPERTY (QString pkiDir READ pkiDir WRITE setPkiDir NOTIFY pkiDirChanged) + Q_PROPERTY ( + QString certFile READ certFile WRITE setCertFile NOTIFY certFileChanged) + Q_PROPERTY ( + QString keyFile READ keyFile WRITE setKeyFile NOTIFY keyFileChanged) + +public: + /// OPC UA message security mode (values match MessageSecurityMode). + enum SecurityMode + { + SignAndEncrypt = 3, + Sign = 2, + None = 1, + }; + Q_ENUM (SecurityMode) + + /// OPC UA security policy for encryption algorithms. + enum SecurityPolicy + { + Basic256Sha256, + Aes128_Sha256_RsaOaep, + Aes256_Sha256_RsaPss, + }; + Q_ENUM (SecurityPolicy) + + OpcUaClient (QObject *parent = nullptr); + + /* -- Connection -- */ + + bool connected () const; + + QString serverUrl () const; + void setServerUrl (const QString &url); + + OpcUaAuth *auth () const; + void setAuth (OpcUaAuth *auth); + + /** @brief Discover endpoints, pick the most secure, connect. */ + Q_INVOKABLE void connectToServer (); + /** @brief Connect directly without endpoint discovery. */ + Q_INVOKABLE void connectDirect (SecurityPolicy policy, SecurityMode mode); + Q_INVOKABLE void disconnectFromServer (); + + /** @brief Accept the pending server certificate. */ + Q_INVOKABLE void acceptCertificate (); + /** @brief Reject the pending server certificate. */ + Q_INVOKABLE void rejectCertificate (); + + /* -- Discovery -- */ + + QString discoveryUrl () const; + void setDiscoveryUrl (const QString &url); + + bool discovering () const; + + const QList<QOpcUaApplicationDescription> &discoveredServers () const; + QVariantList servers () const; + + Q_INVOKABLE void startDiscovery (); + Q_INVOKABLE void stopDiscovery (); + + /* -- PKI -- */ + + QString pkiDir () const; + void setPkiDir (const QString &path); + + QString certFile () const; + void setCertFile (const QString &path); + + QString keyFile () const; + void setKeyFile (const QString &path); + + /** @brief Auto-detect cert/key from the PKI directory and apply. */ + Q_INVOKABLE void autoDetectPki (); + /** @brief Apply PKI dirs and cert/key. Call before connecting. */ + Q_INVOKABLE void applyPki (); + + /* -- C++ only -- */ + + static OpcUaClient *instance (); + QOpcUaClient *opcuaClient () const; + +signals: + /* -- Connection -- */ + void connectedChanged (); + void serverUrlChanged (); + void authChanged (); + /** + * @brief Emitted when the server presents an untrusted cert. + * + * The connection blocks until acceptCertificate() or + * rejectCertificate() is called (30 s timeout, auto-rejects). + */ + void certificateTrustRequested (const QString &certInfo); + void connectionError (const QString &message); + void statusMessage (const QString &message); + + /* -- Discovery -- */ + void discoveryUrlChanged (); + void discoveringChanged (); + void serversChanged (); + + /* -- PKI -- */ + void pkiDirChanged (); + void certFileChanged (); + void keyFileChanged (); + +private slots: + /* -- Connection -- */ + void handleStateChanged (QOpcUaClient::ClientState state); + void + handleEndpointsReceived (const QList<QOpcUaEndpointDescription> &endpoints, + QOpcUa::UaStatusCode statusCode, + const QUrl &requestUrl); + void handleConnectError (QOpcUaErrorState *errorState); + void handleClientError (QOpcUaClient::ClientError error); + + /* -- Discovery -- */ + void handleFindServersFinished ( + const QList<QOpcUaApplicationDescription> &servers, + QOpcUa::UaStatusCode statusCode, const QUrl &requestUrl); + void doDiscovery (); + +private: + void setupClient (); + + /* -- Connection -- */ + QOpcUaProvider *m_provider = nullptr; + QOpcUaClient *m_client = nullptr; + OpcUaAuth *m_auth = nullptr; + QString m_serverUrl; + bool m_connected = false; + QEventLoop *m_certLoop = nullptr; + bool m_certAccepted = false; + + /* -- Discovery -- */ + QString m_discoveryUrl; + QTimer m_discoveryTimer; + bool m_discovering = false; + QList<QOpcUaApplicationDescription> m_discoveredServers; + QVariantList m_serversCache; + + /* -- PKI -- */ + QString m_pkiDir; + QString m_certFile; + QString m_keyFile; + + static inline OpcUaClient *s_instance = nullptr; +}; + +#endif // OPCUACLIENT_H |
