Files
qt6-migration-pipeline/TetraIF/PrtCnv/PrtCnvCentralThread.cpp
T
2026-07-14 12:07:36 +02:00

843 lines
23 KiB
C++

#include "PrtCnvCentralThread.hpp"
#include "PrtCnvRadioThread.hpp"
#include "PrtCnvDbThread.hpp"
#include "PrtCnvStoredCentralTelegram.hpp"
#include "PrtCnvTelegramLogThread.hpp"
#include "PrtCnvInjectionThread.hpp"
#include "PrtCnvThreadStarter.hpp"
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
#include <LtsUtilsCore/dds_bitarray.h>
#include <QTimer>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <time.h>
#include <TrainingAreaBase/training_area_telegrams.h>
namespace PrtCnv
{
PrtCnvCentralThread::PrtCnvCentralThread(PrtCnv::PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvCentralThread")
, m_webSocket(nullptr)
, m_SendCounter(0)
, m_RadioThread(nullptr)
, m_RadioStopped(false)
, m_CentralStopped(false)
, m_LastSendCounter(0)
, m_VirtualTeilnehmerId(0)
, m_maxEqID(50000)
, m_aliveTimer(nullptr)
, m_sendAckTimer(nullptr)
, m_reconnectTimer(nullptr)
, m_DbThread(nullptr)
, m_LogThread(nullptr)
, m_InjectionThread(nullptr)
, m_ReceiveCounter(0)
, m_ReceiveAckCounter(0)
, m_State(PrtCnvSocketThread::e_INITIAL)
, m_bDirectConnection(false)
, m_bRadioThreadInitDone(false)
{
m_Name = QStringLiteral("Central");
}
PrtCnvCentralThread::~PrtCnvCentralThread()
{
destroy();
}
int32_t PrtCnvCentralThread::create(NGL::Settings *settings)
{
PrtCnvThread::create(settings);
INFO_LOG(m_logger) << "Create";
m_RadioThread = qobject_cast<PrtCnvRadioThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Radio));
m_DbThread = qobject_cast<PrtCnvDbThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Db));
m_LogThread = qobject_cast<PrtCnvTelegramLogThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Log));
m_InjectionThread = qobject_cast<PrtCnvInjectionThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Injection));
connect(m_DbThread, &PrtCnvDbThread::playerLicencedChanged,
this, &PrtCnvCentralThread::onPlayerLicencedChanged, Qt::QueuedConnection);
connect(this, &PrtCnvCentralThread::checkSendToCentral, this, &PrtCnvCentralThread::checkSend, Qt::QueuedConnection);
connect(this, &PrtCnvCentralThread::checkSendToRadio, m_RadioThread, &PrtCnvRadioThread::checkSend, Qt::QueuedConnection);
connect(this, &PrtCnvCentralThread::stopRadio, m_RadioThread, &PrtCnvRadioThread::doStop, Qt::QueuedConnection);
connect(this, &PrtCnvCentralThread::cleanRadio, m_RadioThread, &PrtCnvRadioThread::doClean, Qt::QueuedConnection);
connect(this, &PrtCnvCentralThread::startRadio, m_RadioThread, &PrtCnvRadioThread::doStart, Qt::QueuedConnection);
connect(m_RadioThread, &PrtCnvRadioThread::initDone,
this, &PrtCnvCentralThread::onRadioThreadInitDone);
connect(m_RadioThread, &PrtCnvRadioThread::areaEffectSimulationActivated,
this, &PrtCnvCentralThread::onAreaEffectSimulationActivated, Qt::QueuedConnection);
connect(m_RadioThread, &PrtCnvRadioThread::areaEffectSimulationDeactivated,
this, &PrtCnvCentralThread::onAreaEffectSimulationDeactivated, Qt::QueuedConnection);
auto mainApp = m_Parent->getMainApp();
connect(this, &PrtCnvCentralThread::directTextMessage,
mainApp, &PrtCnvApplication::textMessageFromPrtCnvToCentral);
connect(mainApp, &PrtCnvApplication::textMessageFromCentralToPrtCnv,
this, &PrtCnvCentralThread::onDirectTextMessageReceived);
m_aliveTimer = new QTimer(this);
connect(m_aliveTimer, &QTimer::timeout, this, &PrtCnvCentralThread::timeoutAliveAndConnection);
m_sendAckTimer = new QTimer(this);
connect(m_sendAckTimer, &QTimer::timeout, this, &PrtCnvCentralThread::timeoutTick);
const int disconnectTimeout = m_Config->getInteger(getName(), QStringLiteral("DisconnectTimeout"), 10000);
m_reconnectTimer = new QTimer(this);
m_reconnectTimer->setInterval(disconnectTimeout);
m_reconnectTimer->setSingleShot(true);
connect(m_reconnectTimer, &QTimer::timeout, this, &PrtCnvCentralThread::connectSocket);
return 0;
}
int32_t PrtCnvCentralThread::destroy()
{
INFO_LOG(m_logger) << "Destroy";
PrtCnvThread::destroy();
delete m_webSocket; m_webSocket = nullptr;
delete m_aliveTimer; m_aliveTimer = nullptr;
delete m_sendAckTimer; m_sendAckTimer = nullptr;
delete m_reconnectTimer; m_reconnectTimer = nullptr;
return 0;
}
int32_t PrtCnvCentralThread::init()
{
INFO_LOG(m_logger) << "Init";
PrtCnvThread::init();
m_CentralStopped = false;
m_RadioStopped = false;
m_aliveTimer->setInterval(m_Config->getInteger(getName(), QStringLiteral("AliveTimeout"), 3000));
m_sendAckTimer->setInterval(m_Config->getInteger(getName(), QStringLiteral("AckTimeout"), 900));
m_VirtualTeilnehmerId = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("VirtualIdPrtCnv"), 90);
m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000);
return 0;
}
int32_t PrtCnvCentralThread::deinit()
{
INFO_LOG(m_logger) << "Deinit";
PrtCnvThread::deinit();
return 0;
}
int32_t PrtCnvCentralThread::start()
{
INFO_LOG(m_logger) << "Start";
PrtCnvThread::start();
if (m_DbThread->mustProceedCleanup())
{
INFO_LOG(m_logger) << "Proceed cleanup DB after crash...";
m_CentralStopped = true;
emit stopRadio();
}
else
{
connectSocket();
}
return 0;
}
int32_t PrtCnvCentralThread::stop()
{
INFO_LOG(m_logger) << "Stop";
PrtCnvThread::stop();
return 0;
}
void PrtCnvCentralThread::connected()
{
INFO_LOG(m_logger) << "Central-Socket connected m_Socket=" << m_webSocket;
m_SendCounter = 0;
m_LastSendCounter = 0;
m_ReceiveCounter = 0;
m_ReceiveAckCounter = 0;
m_aliveTimer->start();
if (m_bRadioThreadInitDone)
m_sendAckTimer->start();
m_State = PrtCnvSocketThread::e_WORKING;
emit checkSendToCentral();
}
void PrtCnvCentralThread::disconnected()
{
INFO_LOG(m_logger) << "disconnected m_Socket=" << m_webSocket;
if (PrtCnvSocketThread::e_WORKING == m_State && m_webSocket)
m_webSocket->close();
m_State = PrtCnvSocketThread::e_DISCONNECTING;
if (m_DoCleanup)
{
INFO_LOG(m_logger) << "cleanup while disconnection";
m_sendAckTimer->stop();
m_CentralStopped = true;
if (m_RadioStopped)
cleanAndReinit();
}
else
{
m_DbThread->prepareCentralTelegramsForReconnection();
connectSocket();
}
}
void PrtCnvCentralThread::radioStopped()
{
m_RadioStopped = true;
if (m_CentralStopped)
cleanAndReinit();
}
void PrtCnvCentralThread::cleanAndReinit()
{
INFO_LOG(m_logger) << "cleanAndReinit";
emit cleanRadio();
m_ReceiveAckCounter = 0;
m_DbThread->cleanAndInit();
m_DoCleanup = false;
}
void PrtCnvCentralThread::radioCleant()
{
if (!m_DoCleanup)
{
m_DbThread->setMachineState(0);
m_RadioStopped = false;
m_CentralStopped = false;
emit startRadio();
connectSocket();
}
else
{
ERROR_LOG(m_logger) << "Internal error: radioCleant, but central still cleaning up.";
}
}
void PrtCnvCentralThread::onTextMessageReceived(const QString &msg)
{
if (m_DoCleanup)
return;
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
onDirectTextMessageReceived(msg.toUtf8());
}
void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
{
try
{
if (baJson.isEmpty())
throw std::exception();
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
const QJsonValue typeId = obj.value(QStringLiteral("typeId"));
if (!typeId.isDouble())
throw TrainingAreaBase::TetraIcd::JsonException(obj, QStringLiteral("typeId"));
N_CoPrtCnv::CoPrtCnvCentralTelegram telegram(baJson, obj, static_cast<TrainingAreaBase::TetraIcd::TelegramId>(typeId.toInt()));
m_LogThread->writeCentralTelegramLog(&telegram, false, 1);
m_aliveTimer->start();
if (telegram.telegramId() == TrainingAreaBase::TetraIcd::BESTAETIGUNG)
{
handleAck(&telegram);
}
else
{
DEBUG_LOG(m_logger) << "Received telegram '" << baJson << "'";
handleTelegram(&telegram);
}
}
catch (const std::exception &e)
{
ERROR_LOG(m_logger) << "JSon conversion error happenend. Error:"
<< e.what() << ", msg: " << baJson;
TrainingAreaBase::TetraIcd::CtaDataError tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
tele.reason = TrainingAreaBase::TetraIcd::CtaDataError::Reason::JsonDecodeFailure;
tele.originTelegramId = 0;
N_CoPrtCnv::CoPrtCnvCentralTelegram telegram(tele);
sendTelegram(&telegram);
}
}
void PrtCnvCentralThread::stateChanged(QAbstractSocket::SocketState newState)
{
INFO_LOG(m_logger) << "Websocket changed to state " << newState;
}
void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
DEBUG_LOG(m_logger) << "Receive Central-Telegram with telId=" << a_telegram->telegramId()
<< "; rcounter=" << a_telegram->counter();
if (checkAndUpdateReceiveCounter(a_telegram->counter()))
{
if (handleSpecialTelegram(a_telegram))
{
using namespace TrainingAreaBase::TetraIcd;
if (a_telegram->telegramId() == TelegramId::DEAKTIVIERUNG_WIRKFELD)
{
const DeactivateEffectSimulation des(DeactivateEffectSimulation::fromJson(a_telegram->jsonData()));
switch (des.aesType)
{
case AreaEffectSimulationType::MineArea:
case AreaEffectSimulationType::ExplosionArea:
case AreaEffectSimulationType::ExplosionSingle:
case AreaEffectSimulationType::NContamination:
case AreaEffectSimulationType::CContamination:
case AreaEffectSimulationType::FunctionalArea:
case AreaEffectSimulationType::DusSingleMineSimulator:
if (m_deactivatedAreaEffectSimulations.contains(des.aesDdsId))
{
INFO_LOG(m_logger) << "AES with id " << des.aesDdsId << " already deactivated - ignoring new deactivation telegram";
return;
}
break;
case AreaEffectSimulationType::TechnicalArea:
case AreaEffectSimulationType::GasPipeDetonation:
case AreaEffectSimulationType::SpecialArea:
case AreaEffectSimulationType::Unknown:
Q_ASSERT(false);
break;
case AreaEffectSimulationType::BeStillWarning:
break;
}
}
else if (a_telegram->telegramId() == TelegramId::WIRKFELD_STATUS_MINENSPERRE)
{
const MineAreaSingleMineState msms(MineAreaSingleMineState::fromJson(a_telegram->jsonData()));
QSet<int> &oldTriggeredMines = m_alreadyTriggeredMines[msms.aesDdsId];
QSet<int> newTriggeredMines;
newTriggeredMines.reserve(oldTriggeredMines.size() + 5);
bool bSomethingChanged = false;
for (int i = 0; i < msms.mineCount; ++i)
{
if (!LtsUtils::BitArray::testBit(msms.mineState, i))
{
INFO_LOG(m_logger) << "Testing bit " << i << " ... not set = triggered";
if (!oldTriggeredMines.contains(i))
{
INFO_LOG(m_logger) << "not in old one";
bSomethingChanged = true;
}
newTriggeredMines.insert(i);
}
}
if (!bSomethingChanged)
bSomethingChanged = newTriggeredMines.size() != oldTriggeredMines.size();
if (!bSomethingChanged)
{
INFO_LOG(m_logger) << "MineState telegram contains no new informations - skipping " << msms.aesDdsId;
return;
}
INFO_LOG(m_logger) << "MineState telegram contains new informations... " << msms.aesDdsId;
oldTriggeredMines = newTriggeredMines;
}
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>
radioTelegram(N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToRadio(a_telegram));
if (radioTelegram)
{
if (radioTelegram->getIdentity() <= m_maxEqID) {
m_DbThread->storeRadioTelegram(radioTelegram, a_telegram->counter());
} else {
WARNING_LOG(m_logger) << "Central telegram with telId=" << a_telegram->telegramId()
<< " has invalid identity:" << radioTelegram->getIdentity();
}
}
else
{
m_DbThread->centralCounterReadyForAck(a_telegram->counter());
WARNING_LOG(m_logger) << "Central telegram with telId=" << a_telegram->telegramId()
<< " could not be converted";
}
}
}
emit checkSendToRadio();
}
bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter)
{
TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter;
if (std::numeric_limits<int32_t>::max() == ++m_ReceiveCounter)
m_ReceiveCounter = 0;
if (m_ReceiveCounter != a_counter)
{
if (m_ReceiveCounter > a_counter)
{
ERROR_LOG(m_logger) << "It seems, the telegram with counter " << a_counter << " was resent from "
<< getName() << "! Expected: " << m_ReceiveCounter;
}
else
{
ERROR_LOG(m_logger) << "It seems, we lost one or several telegrams from " << getName()
<< ": receive-counter of received telegram: " << a_counter << "; Expected: " << m_ReceiveCounter;
}
#if 0
m_ReceiveCounter--;
return false;
#else
m_ReceiveCounter = a_counter;
return true;
#endif
}
return true;
}
void PrtCnvCentralThread::timeoutTick()
{
if (m_DoCleanup)
return;
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
try
{
N_CoPrtCnv::CoPrtCnvCentralTelegram *centralInjectTelegram;
while ((centralInjectTelegram = m_InjectionThread->getNextCentralInjectionTelegram()))
{
sendTelegram(centralInjectTelegram);
delete centralInjectTelegram;
}
}
catch (std::exception& e)
{
ERROR_LOG(m_logger) << "Catched an unexpected exception: " << e.what()
<< " => could not inject radio-telegram, but we proceed...";
}
sendAck();
}
void PrtCnvCentralThread::timeoutAliveAndConnection()
{
INFO_LOG(m_logger) << "timeoutAliveAndConnection socketState="
<< int(m_webSocket ? m_webSocket->state() : -1)
<< " m_State=" << m_State << " m_Socket=" << m_webSocket;
switch (m_State)
{
case PrtCnvSocketThread::e_CONNECTING:
connectSocket();
break;
case PrtCnvSocketThread::e_WORKING:
if (!m_bDirectConnection)
{
disconnectSocket();
m_reconnectTimer->start();
}
break;
case PrtCnvSocketThread::e_DISCONNECTING:
break;
default:
ERROR_LOG(m_logger) << "timeoutAlive for m_State=" << m_State << " not implemented";
}
}
void PrtCnvCentralThread::sendAck()
{
TrainingAreaBase::TetraIcd::Acknowledge ack;
ack.timeStamp = time(nullptr) * 1000;
ack.ackCounter = m_ReceiveAckCounter;
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(ack);
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(tele.data()));
else
emit directTextMessage(tele.data());
TRACE_LOG(m_logger) << "Wrote ack: " << tele.data();
}
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
PrtCnvStoredCentralTelegram *handle = nullptr;
sendTelegram(a_telegram, handle);
}
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram,
PrtCnvStoredCentralTelegram *a_handle)
{
using namespace TrainingAreaBase::TetraIcd;
if (a_telegram->telegramId() == TelegramId::DEAKTIVIERUNG_EINZELMINE)
{
const MineTriggered tele(MineTriggered::fromJson(a_telegram->jsonData()));
m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1);
INFO_LOG(m_logger) << "Adding triggered mine with id " << tele.mineIndex << " to area id " << tele.mineAreaId;
}
const int writeCounter = a_handle ? a_handle->writeCounter() : 0;
if (writeCounter != 0)
a_telegram->setCounter(writeCounter);
else
a_telegram->setCounter(++m_SendCounter);
DEBUG_LOG(m_logger) << "Send telegram to central: telId=" << a_telegram->telegramId()
<< " wcounter=" << a_telegram->counter();
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(a_telegram->data()));
else
emit directTextMessage(a_telegram->data());
if (a_handle)
m_DbThread->centralTelegramSent(a_telegram->counter(), a_handle);
m_LogThread->writeCentralTelegramLog(a_telegram, true, 1);
}
void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen()
{
const auto nachforderungsStat = m_DbThread->getClaimStatistics();
TrainingAreaBase::TetraIcd::BroadcastStatistics tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
tele.information.reserve(nachforderungsStat.size());
for (const auto &it : nachforderungsStat)
{
TrainingAreaBase::TetraIcd::BroadcastInformation bi;
bi.equipmentNumber = it.first;
bi.broadcastRequests = it.second;
tele.information.push_back(std::move(bi));
}
N_CoPrtCnv::CoPrtCnvCentralTelegram telegram(tele);
sendTelegram(&telegram);
}
void PrtCnvCentralThread::checkSend()
{
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
PrtCnvStoredCentralTelegram *handle = nullptr;
auto *centralTelegram = m_DbThread->getNextCentralTelegram(handle);
if (centralTelegram)
{
sendTelegram(centralTelegram, handle);
delete centralTelegram;
emit checkSendToCentral();
}
}
void PrtCnvCentralThread::handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
TrainingAreaBase::TetraIcd::Acknowledge ack(TrainingAreaBase::TetraIcd::Acknowledge::fromJson(a_telegram->jsonData()));
m_DbThread->ackCentralTelegrams(ack.ackCounter);
}
void PrtCnvCentralThread::permanentStored(int32_t a_centralCounter)
{
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
DEBUG_LOG(m_logger) << "got permanentStored a_centralCounter=" << a_centralCounter;
if (0 != a_centralCounter && a_centralCounter > m_ReceiveAckCounter)
{
m_ReceiveAckCounter = a_centralCounter;
sendAck();
}
}
void PrtCnvCentralThread::onTetraConnectionState(bool bConnected)
{
TrainingAreaBase::TetraIcd::ProxyConnectionState connState;
connState.connectedToSystem = bConnected;
N_CoPrtCnv::CoPrtCnvCentralTelegram telegram(connState);
sendTelegram(&telegram);
}
void PrtCnvCentralThread::onPlayerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind)
{
TrainingAreaBase::TetraIcd::ParticipantLicenseChange lc;
lc.equipmentNumber = equipNo;
lc.licenseState = TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unknown;
switch (kind)
{
case N_CoPrtCnv::E_LicensingKind::Success:
lc.licenseState = TrainingAreaBase::TetraIcd::ParticipantLicenseState::Licensed;
break;
case N_CoPrtCnv::E_LicensingKind::Rejected:
lc.licenseState = TrainingAreaBase::TetraIcd::ParticipantLicenseState::Rejected;
break;
case N_CoPrtCnv::E_LicensingKind::Unlicense:
lc.licenseState = TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unlicense;
break;
}
Q_ASSERT(lc.licenseState != TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unknown);
N_CoPrtCnv::CoPrtCnvCentralTelegram telegram(lc);
sendTelegram(&telegram);
}
void PrtCnvCentralThread::onAreaEffectSimulationDeactivated(int wirkfeldKennung)
{
m_deactivatedAreaEffectSimulations.insert(wirkfeldKennung);
m_alreadyTriggeredMines.remove(wirkfeldKennung);
}
void PrtCnvCentralThread::onAreaEffectSimulationActivated(int wirkfeldKennung)
{
m_deactivatedAreaEffectSimulations.remove(wirkfeldKennung);
}
void PrtCnvCentralThread::onRadioThreadInitDone()
{
m_bRadioThreadInitDone = true;
if (!m_sendAckTimer->isActive())
m_sendAckTimer->start();
}
bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
using namespace TrainingAreaBase::TetraIcd;
switch (a_telegram->telegramId())
{
case Constraints<ExerciseStateData>::id():
{
ExerciseStateData tele(ExerciseStateData::fromJson(a_telegram->jsonData()));
switch(tele.exerciseState)
{
case ExerciseStateData::ExerciseState::Terminated:
{
INFO_LOG(m_logger) << "Got Betriebszustandsmeldung Uebung_Aufraeumen => disconnect, cleanup and reconnect";
m_DbThread->setMachineState(1);
permanentStored(a_telegram->counter());
m_DoCleanup = true;
m_CentralStopped = false;
m_RadioStopped = false;
m_sendAckTimer->stop();
m_DbThread->waitUntilDbWritten();
disconnectSocket();
m_RadioThread->prepareCleanUp();
emit stopRadio();
m_reconnectTimer->start();
break;
}
case ExerciseStateData::ExerciseState::Started:
m_DbThread->setPause(false);
m_RadioThread->sendEnvironmentTelegramTimerNow();
break;
case ExerciseStateData::ExerciseState::Paused:
m_DbThread->setPause(true);
m_RadioThread->sendEnvironmentTelegramTimerNow();
break;
default:
break;
}
return false;
}
case Constraints<RequestBroadcastStatistics>::id():
m_DbThread->centralCounterReadyForAck(a_telegram->counter());
handleAnforderungStatistikBroadcastNachforderungen();
return false;
case Constraints<ExerciseEquipmentAssignmentComplete>::id():
{
const ExerciseEquipmentAssignmentComplete tele(ExerciseEquipmentAssignmentComplete::fromJson(a_telegram->jsonData()));
m_RadioThread->exerciseEquipmentChanged(tele);
return false;
}
default:
break;
}
return true;
}
void PrtCnvCentralThread::connectSocket()
{
const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01"));
if (host == QLatin1String("directConnection"))
{
m_bDirectConnection = true;
connected();
return;
}
m_bDirectConnection = false;
disconnectSocket();
m_webSocket = new QWebSocket;
connect(m_webSocket, &QWebSocket::stateChanged,
this, &PrtCnvCentralThread::stateChanged);
connect(m_webSocket, &QWebSocket::textMessageReceived,
this, &PrtCnvCentralThread::onTextMessageReceived);
connect(m_webSocket, &QWebSocket::connected,
this, &PrtCnvCentralThread::connected);
connect(m_webSocket, &QWebSocket::disconnected,
this, &PrtCnvCentralThread::disconnected);
const uint16_t port = static_cast<uint16_t>(m_Config->getInteger(getName(), QStringLiteral("Port"), 4934));
const QUrl scmUrl(QStringLiteral("ws://%1:%2").arg(host).arg(port));
m_webSocket->open(scmUrl);
m_State = PrtCnvSocketThread::e_CONNECTING;
}
void PrtCnvCentralThread::disconnectSocket()
{
m_State = PrtCnvSocketThread::e_INITIAL;
if (!m_webSocket)
return;
m_State = PrtCnvSocketThread::e_DISCONNECTING;
m_webSocket->disconnect(this);
m_webSocket->close();
m_webSocket->deleteLater();
m_webSocket = nullptr;
}
}