File: C:/Redmine-4.x/redmine-4.2.9/files/2025/07/250731163113_mainwindow.cpp
#include "mainwindow.h"
#include <QMessageBox>
#include <QApplication>
#include <QDateTime>
#include <QHeaderView>
#include <QTableWidgetItem>
#include <QSplitter>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_hApplication(OpcUa_Null)
, m_hSession(OpcUa_Null)
, m_isConnected(false)
, m_isInitialized(false)
{
setupUI();
// Initialiser OPC UA
if (initializeOpcUa()) {
logTextEdit->append("OPC UA initialisé avec succès");
m_isInitialized = true;
} else {
logTextEdit->append("ERREUR : Échec de l'initialisation OPC UA");
}
// Timer pour vérifier l'état de la connexion
connectionTimer = new QTimer(this);
connect(connectionTimer, &QTimer::timeout, this, &MainWindow::onConnectionTimer);
connectionTimer->start(1000); // Vérifier chaque seconde
}
MainWindow::~MainWindow()
{
if (m_isConnected) {
disconnectFromServer();
}
cleanupOpcUa();
}
void MainWindow::setupUI()
{
centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// Splitter principal
QSplitter *mainSplitter = new QSplitter(Qt::Horizontal, this);
QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
mainLayout->addWidget(mainSplitter);
// Partie gauche - Configuration
QWidget *leftWidget = new QWidget();
QVBoxLayout *leftLayout = new QVBoxLayout(leftWidget);
// Groupe Connexion
connectionGroup = new QGroupBox("Connexion au serveur OPC UA", this);
QGridLayout *connectionLayout = new QGridLayout(connectionGroup);
connectionLayout->addWidget(new QLabel("URL du serveur:"), 0, 0);
urlEdit = new QLineEdit("opc.tcp://Billy:2602/SimulationBasic", this);
connectionLayout->addWidget(urlEdit, 0, 1);
connectionLayout->addWidget(new QLabel("Politique de sécurité:"), 1, 0);
securityEdit = new QLineEdit("http://opcfoundation.org/UA/SecurityPolicy#None", this);
connectionLayout->addWidget(securityEdit, 1, 1);
connectButton = new QPushButton("Se connecter", this);
disconnectButton = new QPushButton("Se déconnecter", this);
disconnectButton->setEnabled(false);
QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addWidget(connectButton);
buttonLayout->addWidget(disconnectButton);
connectionLayout->addLayout(buttonLayout, 2, 0, 1, 2);
statusLabel = new QLabel("Déconnecté", this);
statusLabel->setStyleSheet("color: red; font-weight: bold;");
connectionLayout->addWidget(statusLabel, 3, 0, 1, 2);
leftLayout->addWidget(connectionGroup);
// Groupe Configuration historique
historyGroup = new QGroupBox("Configuration lecture historique", this);
historyGroup->setEnabled(false);
QGridLayout *historyLayout = new QGridLayout(historyGroup);
// NodeId
historyLayout->addWidget(new QLabel("Namespace:"), 0, 0);
namespaceSpinBox = new QSpinBox(this);
namespaceSpinBox->setRange(0, 255);
namespaceSpinBox->setValue(2);
historyLayout->addWidget(namespaceSpinBox, 0, 1);
historyLayout->addWidget(new QLabel("Node ID:"), 0, 2);
nodeIdSpinBox = new QSpinBox(this);
nodeIdSpinBox->setRange(0, 65535);
nodeIdSpinBox->setValue(16);
historyLayout->addWidget(nodeIdSpinBox, 0, 3);
// Période de temps
historyLayout->addWidget(new QLabel("Début:"), 1, 0);
startTimeEdit = new QDateTimeEdit(this);
startTimeEdit->setDateTime(QDateTime::currentDateTime().addSecs(-3600)); // 1 heure avant
startTimeEdit->setDisplayFormat("dd/MM/yyyy hh:mm:ss");
historyLayout->addWidget(startTimeEdit, 1, 1, 1, 3);
historyLayout->addWidget(new QLabel("Fin:"), 2, 0);
endTimeEdit = new QDateTimeEdit(this);
endTimeEdit->setDateTime(QDateTime::currentDateTime());
endTimeEdit->setDisplayFormat("dd/MM/yyyy hh:mm:ss");
historyLayout->addWidget(endTimeEdit, 2, 1, 1, 3);
// Paramètres
historyLayout->addWidget(new QLabel("Max valeurs:"), 3, 0);
maxValuesSpinBox = new QSpinBox(this);
maxValuesSpinBox->setRange(1, 10000);
maxValuesSpinBox->setValue(1000);
historyLayout->addWidget(maxValuesSpinBox, 3, 1);
includeModifiedCheckBox = new QCheckBox("Inclure modifiées", this);
includeModifiedCheckBox->setChecked(true);
historyLayout->addWidget(includeModifiedCheckBox, 3, 2);
includeBoundsCheckBox = new QCheckBox("Inclure limites", this);
includeBoundsCheckBox->setChecked(true);
historyLayout->addWidget(includeBoundsCheckBox, 3, 3);
readHistoryButton = new QPushButton("Lire historique", this);
historyLayout->addWidget(readHistoryButton, 4, 0, 1, 4);
leftLayout->addWidget(historyGroup);
// Zone de log
QLabel *logLabel = new QLabel("Journal des événements:", this);
leftLayout->addWidget(logLabel);
logTextEdit = new QTextEdit(this);
logTextEdit->setMinimumHeight(300);
leftLayout->addWidget(logTextEdit);
mainSplitter->addWidget(leftWidget);
// Partie droite - Résultats
QWidget *rightWidget = new QWidget();
QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
// Groupe Résultats
resultsGroup = new QGroupBox("Données historiques", this);
resultsGroup->setEnabled(false);
QVBoxLayout *resultsLayout = new QVBoxLayout(resultsGroup);
QHBoxLayout *resultsHeaderLayout = new QHBoxLayout();
resultsCountLabel = new QLabel("Aucune donnée", this);
resultsCountLabel->setStyleSheet("font-weight: bold; color: blue;");
clearResultsButton = new QPushButton("Effacer résultats", this);
resultsHeaderLayout->addWidget(resultsCountLabel);
resultsHeaderLayout->addStretch();
resultsHeaderLayout->addWidget(clearResultsButton);
resultsLayout->addLayout(resultsHeaderLayout);
resultsTable = new QTableWidget(0, 4, this);
resultsTable->setHorizontalHeaderLabels(QStringList() << "Timestamp" << "Valeur" << "Qualité" << "Source");
resultsTable->horizontalHeader()->setStretchLastSection(true);
resultsTable->setAlternatingRowColors(true);
resultsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
resultsTable->setSortingEnabled(true);
resultsLayout->addWidget(resultsTable);
rightLayout->addWidget(resultsGroup);
mainSplitter->addWidget(rightWidget);
// Définir les tailles du splitter (50% - 50%)
mainSplitter->setSizes(QList<int>() << 500 << 500);
// Connexions des signaux
connect(connectButton, &QPushButton::clicked, this, &MainWindow::connectToServer);
connect(disconnectButton, &QPushButton::clicked, this, &MainWindow::disconnectFromServer);
connect(readHistoryButton, &QPushButton::clicked, this, &MainWindow::readHistoricalData);
connect(clearResultsButton, &QPushButton::clicked, this, &MainWindow::clearResults);
setWindowTitle("Client OPC UA - Lecture des données historiques");
resize(1200, 800);
}
bool MainWindow::initializeOpcUa()
{
OpcUa_StatusCode uStatus = OpenOpcUa_InitializeAbstractionLayer(
(OpcUa_CharA*)"BasicOpcUaClient", &m_hApplication, 15000, 100, 500);
if (uStatus != OpcUa_Good) {
return false;
}
// Initialiser la sécurité
OpcUa_String szCertificateStore;
OpcUa_String_Initialize(&szCertificateStore);
OpcUa_String_AttachCopy(&szCertificateStore, (OpcUa_CharA*)"CertificateStore");
uStatus = OpenOpcUa_InitializeSecurity(m_hApplication, szCertificateStore);
OpcUa_String_Clear(&szCertificateStore);
return (uStatus == OpcUa_Good);
}
void MainWindow::cleanupOpcUa()
{
if (m_hApplication != OpcUa_Null) {
OpenOpcUa_ClearAbstractionLayer(m_hApplication);
m_hApplication = OpcUa_Null;
logTextEdit->append("OPC UA nettoyé");
}
}
void MainWindow::connectToServer()
{
if (!m_isInitialized) {
QMessageBox::warning(this, "Erreur", "OPC UA n'est pas initialisé");
return;
}
QString url = urlEdit->text();
QString security = securityEdit->text();
if (url.isEmpty()) {
QMessageBox::warning(this, "Erreur", "Veuillez saisir une URL de serveur");
return;
}
connectButton->setEnabled(false);
logTextEdit->append(QString("=== TENTATIVE DE CONNEXION ==="));
logTextEdit->append(QString("URL: %1").arg(url));
logTextEdit->append(QString("Politique de sécurité: %1").arg(security));
logTextEdit->append(QString("Heure: %1").arg(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss")));
OpcUa_StatusCode uStatus = createSession(url, security);
if (uStatus == OpcUa_Good) {
m_isConnected = true;
statusLabel->setText("Connecté");
statusLabel->setStyleSheet("color: green; font-weight: bold;");
disconnectButton->setEnabled(true);
historyGroup->setEnabled(true);
resultsGroup->setEnabled(true);
logTextEdit->append("Connexion réussie !");
logTextEdit->append(QString("Session Handle: 0x%1").arg((qintptr)m_hSession, 0, 16));
} else {
connectButton->setEnabled(true);
logTextEdit->append(QString("Erreur de connexion : 0x%1").arg(uStatus, 0, 16));
QMessageBox::critical(this, "Erreur de connexion",
QString("Impossible de se connecter au serveur.\nCode d'erreur: 0x%1").arg(uStatus, 0, 16));
}
logTextEdit->append("================================");
}
void MainWindow::disconnectFromServer()
{
logTextEdit->append(QString("=== DÉCONNEXION ==="));
logTextEdit->append(QString("Heure: %1").arg(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss")));
if (m_hSession != OpcUa_Null) {
OpcUa_StatusCode uStatus = OpenOpcUa_CloseSession(m_hApplication, m_hSession);
if (uStatus == OpcUa_Good) {
logTextEdit->append("Session fermée correctement");
} else {
logTextEdit->append(QString("Erreur lors de la fermeture de session: 0x%1").arg(uStatus, 0, 16));
}
m_hSession = OpcUa_Null;
}
m_isConnected = false;
statusLabel->setText("Déconnecté");
statusLabel->setStyleSheet("color: red; font-weight: bold;");
connectButton->setEnabled(true);
disconnectButton->setEnabled(false);
historyGroup->setEnabled(false);
resultsGroup->setEnabled(false);
logTextEdit->append("Déconnexion terminée");
logTextEdit->append("====================");
}
void MainWindow::readHistoricalData()
{
if (!m_isConnected) {
QMessageBox::warning(this, "Erreur", "Non connecté au serveur");
return;
}
int namespaceIndex = namespaceSpinBox->value();
int nodeId = nodeIdSpinBox->value();
QDateTime startTime = startTimeEdit->dateTime();
QDateTime endTime = endTimeEdit->dateTime();
int maxValues = maxValuesSpinBox->value();
bool includeModified = includeModifiedCheckBox->isChecked();
bool includeBounds = includeBoundsCheckBox->isChecked();
if (startTime >= endTime) {
QMessageBox::warning(this, "Erreur", "La date de début doit être antérieure à la date de fin");
return;
}
logTextEdit->append(QString("=== LECTURE DONNÉES HISTORIQUES ==="));
logTextEdit->append(QString("NodeId: ns=%1;i=%2").arg(namespaceIndex).arg(nodeId));
logTextEdit->append(QString("Période: %1 à %2").arg(startTime.toString("dd/MM/yyyy hh:mm:ss"))
.arg(endTime.toString("dd/MM/yyyy hh:mm:ss")));
logTextEdit->append(QString("Max valeurs: %1").arg(maxValues));
logTextEdit->append(QString("Inclure modifiées: %1").arg(includeModified ? "Oui" : "Non"));
logTextEdit->append(QString("Inclure limites: %1").arg(includeBounds ? "Oui" : "Non"));
readHistoryButton->setEnabled(false);
OpcUa_StatusCode uStatus = readOpcHistoricalData(namespaceIndex, nodeId, startTime, endTime,
maxValues, includeModified, includeBounds);
readHistoryButton->setEnabled(true);
if (uStatus == OpcUa_Good) {
logTextEdit->append("LECTURE HISTORIQUE RÉUSSIE !");
} else {
logTextEdit->append(QString("ERREUR LECTURE HISTORIQUE : 0x%1").arg(uStatus, 0, 16));
QMessageBox::warning(this, "Erreur de lecture historique",
QString("Impossible de lire les données historiques.\nCode d'erreur: 0x%1").arg(uStatus, 0, 16));
}
logTextEdit->append("====================================");
}
void MainWindow::clearResults()
{
resultsTable->setRowCount(0);
resultsCountLabel->setText("Aucune donnée");
resultsCountLabel->setStyleSheet("font-weight: bold; color: blue;");
logTextEdit->append("=== RÉSULTATS EFFACÉS ===");
logTextEdit->append(QString("Heure: %1").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
logTextEdit->append("==========================");
}
void MainWindow::onConnectionTimer()
{
// Vérifier si la connexion est toujours active
if (m_isConnected && m_hSession != OpcUa_Null) {
// Optionnel: afficher un heartbeat dans le log toutes les 30 secondes
static int heartbeatCounter = 0;
heartbeatCounter++;
if (heartbeatCounter >= 30) { // 30 secondes
logTextEdit->append(QString("Heartbeat - Connexion active (%1)")
.arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
heartbeatCounter = 0;
}
}
}
OpcUa_StatusCode MainWindow::readOpcHistoricalData(int namespaceIndex, int nodeId,
QDateTime startTime, QDateTime endTime,
int maxValues, bool includeModified, bool includeBounds)
{
OpcUa_StatusCode uStatus = OpcUa_Good;
OpenOpcUa_HistoryReadValueId* pNodesToRead = nullptr;
OpenOpcUa_HistoryReadResult* pHistoryResults = nullptr;
OpcUa_Int32 iNoOfResults = 0;
OpcUa_Int32 iNoOfNodesToRead = 1;
logTextEdit->append("Préparation de la lecture historique...");
// Allouer la structure pour le nœud à lire
pNodesToRead = (OpenOpcUa_HistoryReadValueId*)OpcUa_Alloc(sizeof(OpenOpcUa_HistoryReadValueId));
if (!pNodesToRead) {
logTextEdit->append("Erreur: Mémoire insuffisante");
return OpcUa_BadOutOfMemory;
}
memset(pNodesToRead, 0, sizeof(OpenOpcUa_HistoryReadValueId));
// Créer le NodeId
OpcUa_NodeId_Initialize(&pNodesToRead->NodeId);
pNodesToRead->NodeId.NamespaceIndex = namespaceIndex;
pNodesToRead->NodeId.IdentifierType = OpcUa_IdentifierType_Numeric;
pNodesToRead->NodeId.Identifier.Numeric = nodeId;
// Initialiser les autres champs
OpcUa_String_Initialize(&pNodesToRead->IndexRange);
OpcUa_ByteString_Initialize(&pNodesToRead->ContinuationPoint);
logTextEdit->append("Configuration des paramètres temporels...");
// Convertir les dates
OpcUa_DateTime opcStartTime = qDateTimeToOpcDateTime(startTime);
OpcUa_DateTime opcEndTime = qDateTimeToOpcDateTime(endTime);
logTextEdit->append("Envoi de la requête de lecture historique...");
// Appeler la fonction de lecture historique
uStatus = OpenOpcUa_HistoryReadRaw(
m_hApplication,
m_hSession,
opcStartTime,
opcEndTime,
includeModified ? OpcUa_True : OpcUa_False,
(OpcUa_UInt32)maxValues,
includeBounds ? OpcUa_True : OpcUa_False,
iNoOfNodesToRead,
pNodesToRead,
&iNoOfResults,
&pHistoryResults
);
if (uStatus == OpcUa_Good) {
logTextEdit->append("Requête envoyée avec succès");
logTextEdit->append(QString("Nombre de résultats reçus: %1").arg(iNoOfResults));
if (pHistoryResults && iNoOfResults > 0) {
// Traiter les résultats
for (OpcUa_Int32 i = 0; i < iNoOfResults; i++) {
logTextEdit->append(QString("Résultat %1 - StatusCode: 0x%2").arg(i).arg(pHistoryResults[i].StatusCode, 0, 16));
if (pHistoryResults[i].StatusCode == OpcUa_Good && pHistoryResults[i].ppHistoryData) {
OpcUa_HistoryData* pHistoryData = *(pHistoryResults[i].ppHistoryData);
if (pHistoryData->NoOfDataValues > 0) {
logTextEdit->append(QString("Nombre de valeurs historiques: %1").arg(pHistoryData->NoOfDataValues));
// Effacer les résultats précédents
resultsTable->setRowCount(0);
// Ajouter chaque valeur au tableau
for (OpcUa_Int32 j = 0; j < pHistoryData->NoOfDataValues; j++) {
int row = resultsTable->rowCount();
resultsTable->insertRow(row);
// Timestamp
QDateTime timestamp = opcDateTimeToQDateTime(pHistoryData->DataValues[j].SourceTimestamp);
QTableWidgetItem* timestampItem = new QTableWidgetItem(timestamp.toString("dd/MM/yyyy hh:mm:ss.zzz"));
resultsTable->setItem(row, 0, timestampItem);
// Valeur
OpcUa_String* pStrValue = (OpcUa_String*)OpcUa_Alloc(sizeof(OpcUa_String));
OpcUa_String_Initialize(pStrValue);
QString valueStr = "N/A";
if (OpenOpcUa_VariantToString(m_hApplication, m_hSession,
pHistoryData->DataValues[j].Value, &pStrValue) == OpcUa_Good) {
valueStr = QString::fromUtf8(OpcUa_String_GetRawString(pStrValue));
}
QTableWidgetItem* valueItem = new QTableWidgetItem(valueStr);
resultsTable->setItem(row, 1, valueItem);
// Qualité
QString qualityStr = QString("0x%1").arg(pHistoryData->DataValues[j].StatusCode, 0, 16);
QTableWidgetItem* qualityItem = new QTableWidgetItem(qualityStr);
resultsTable->setItem(row, 2, qualityItem);
// Source
QDateTime sourceTime = opcDateTimeToQDateTime(pHistoryData->DataValues[j].SourceTimestamp);
QTableWidgetItem* sourceItem = new QTableWidgetItem(sourceTime.toString("hh:mm:ss.zzz"));
resultsTable->setItem(row, 3, sourceItem);
OpcUa_String_Clear(pStrValue);
OpcUa_Free(pStrValue);
}
// Mettre à jour le compteur
resultsCountLabel->setText(QString("%1 valeur(s) historique(s)").arg(pHistoryData->NoOfDataValues));
resultsCountLabel->setStyleSheet("font-weight: bold; color: green;");
// Ajuster les colonnes
resultsTable->resizeColumnsToContents();
logTextEdit->append(QString("Données affichées dans le tableau: %1 valeurs").arg(pHistoryData->NoOfDataValues));
} else {
logTextEdit->append("Aucune donnée historique dans la période demandée");
resultsCountLabel->setText("Aucune donnée dans la période");
resultsCountLabel->setStyleSheet("font-weight: bold; color: orange;");
}
} else {
logTextEdit->append(QString("Erreur pour le résultat %1: 0x%2").arg(i).arg(pHistoryResults[i].StatusCode, 0, 16));
}
}
} else {
logTextEdit->append("Aucun résultat reçu");
}
} else {
logTextEdit->append(QString("Erreur d'envoi de la requête: 0x%1").arg(uStatus, 0, 16));
}
// Nettoyer la mémoire
if (pHistoryResults) {
OpcUa_Free(pHistoryResults);
}
if (pNodesToRead) {
OpcUa_NodeId_Clear(&pNodesToRead->NodeId);
OpcUa_String_Clear(&pNodesToRead->IndexRange);
OpcUa_ByteString_Clear(&pNodesToRead->ContinuationPoint);
OpcUa_Free(pNodesToRead);
}
return uStatus;
}
OpcUa_DateTime MainWindow::qDateTimeToOpcDateTime(const QDateTime& dt)
{
// Version simplifiée - utiliser OpcUa_DateTime_UtcNow() comme base
OpcUa_DateTime current = OpcUa_DateTime_UtcNow();
// Calculer la différence en secondes
QDateTime now = QDateTime::currentDateTimeUtc();
qint64 diffSeconds = now.secsTo(dt.toUTC());
// Ajouter/soustraire la différence (en supposant que + et - fonctionnent)
// Si cette approche ne fonctionne pas, nous devrons utiliser une approche différente
if (diffSeconds != 0) {
// Conversion approximative - 1 seconde = 10,000,000 ticks de 100ns
// Cette partie pourrait nécessiter un ajustement selon votre SDK
logTextEdit->append(QString("Conversion temporelle - Différence: %1 secondes").arg(diffSeconds));
}
return current; // Temporaire - utiliser l'heure actuelle pour tester
}
QDateTime MainWindow::opcDateTimeToQDateTime(const OpcUa_DateTime& opcDt)
{
// Version simplifiée - retourner l'heure actuelle pour le moment
// Cette fonction devra être ajustée selon la structure réelle d'OpcUa_DateTime
return QDateTime::currentDateTime();
}
OpcUa_StatusCode MainWindow::createSession(const QString& url, const QString& securityPolicy)
{
OpcUa_StatusCode uStatus = OpcUa_BadInvalidState;
OpcUa_EndpointDescription* pEndpointDescription = OpcUa_Null;
OpcUa_UInt32 uiNbOfEndpointDescription = 0;
// Convertir l'URL QString en OpcUa_String
OpcUa_String opcUrl;
OpcUa_String_Initialize(&opcUrl);
OpcUa_String_AttachCopy(&opcUrl, url.toUtf8().data());
logTextEdit->append("Récupération des endpoints...");
// Obtenir les endpoints
uStatus = OpenOpcUa_GetEndpoints(m_hApplication, &opcUrl,
&uiNbOfEndpointDescription, &pEndpointDescription);
if (uStatus == OpcUa_Good) {
logTextEdit->append(QString("%1 endpoint(s) trouvé(s)").arg(uiNbOfEndpointDescription));
OpcUa_String aSessionName;
OpcUa_String_Initialize(&aSessionName);
OpcUa_String_AttachCopy(&aSessionName, (OpcUa_CharA*)"BasicOpcUaClient");
OpcUa_String strSecurity;
OpcUa_String_Initialize(&strSecurity);
OpcUa_String_AttachCopy(&strSecurity, securityPolicy.toUtf8().data());
// Chercher l'endpoint correspondant
bool endpointFound = false;
for (OpcUa_UInt32 i = 0; i < uiNbOfEndpointDescription; i++) {
if (OpcUa_String_Compare(&(pEndpointDescription[i].SecurityPolicyUri), &strSecurity) == 0) {
endpointFound = true;
logTextEdit->append(QString("Endpoint correspondant trouvé (index %1)").arg(i));
logTextEdit->append("Création de la session...");
uStatus = OpenOpcUa_CreateSession(m_hApplication, &pEndpointDescription[i],
600000, aSessionName, &m_hSession);
if (uStatus == OpcUa_Good) {
logTextEdit->append("Session créée avec succès");
logTextEdit->append("Activation de la session...");
// Activer la session
uStatus = OpenOpcUa_ActivateSession(m_hApplication, m_hSession,
OpcUa_UserTokenType_Anonymous,
OpcUa_Null, OpcUa_Null, OpcUa_Null, OpcUa_Null);
if (uStatus == OpcUa_Good) {
logTextEdit->append("Session activée avec succès");
} else {
logTextEdit->append(QString("Erreur d'activation de session: 0x%1").arg(uStatus, 0, 16));
}
} else {
logTextEdit->append(QString("Erreur de création de session: 0x%1").arg(uStatus, 0, 16));
}
break;
}
}
if (!endpointFound) {
logTextEdit->append("Aucun endpoint correspondant à la politique de sécurité");
uStatus = OpcUa_Bad;
}
OpcUa_String_Clear(&strSecurity);
OpcUa_String_Clear(&aSessionName);
// Nettoyer les endpoints
if (pEndpointDescription) {
for (OpcUa_UInt32 i = 0; i < uiNbOfEndpointDescription; i++) {
OpcUa_EndpointDescription_Clear(&pEndpointDescription[i]);
}
OpcUa_Free(pEndpointDescription);
}
} else {
logTextEdit->append(QString("Erreur lors de la récupération des endpoints: 0x%1").arg(uStatus, 0, 16));
}
OpcUa_String_Clear(&opcUrl);
return uStatus;
}