Reinserts original comments

This commit is contained in:
torsten committed 2026-10-14 12:56:16 +00:00
1 parent 1dd1e86355
commit b662e4daf9
112 files changed
+7113 -5131

No files matched your search

@@ -1,16 +1,16 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvCentralThread
// **************************************************************************
#include "PrtCnvCentralThread.hpp"
#include "PrtCnvRadioThread.hpp"
@@ -35,7 +35,7 @@
namespace PrtCnv
{
// ---------------------------------------------------------------
PrtCnvCentralThread::PrtCnvCentralThread(PrtCnv::PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvCentralThread")
, m_webSocket(nullptr)
@@ -66,9 +66,9 @@ PrtCnvCentralThread::~PrtCnvCentralThread()
destroy();
}
// ---------------------------------------------------------------
// Creates all subcomponents and connects signals to slots
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::create(NGL::Settings *settings)
{
PrtCnvThread::create(settings);
@@ -115,9 +115,9 @@ int32_t PrtCnvCentralThread::create(NGL::Settings *settings)
}
// ---------------------------------------------------------------
// Deallocates subcomponents.
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::destroy()
{
INFO_LOG(m_logger) << "Destroy";
@@ -129,9 +129,9 @@ int32_t PrtCnvCentralThread::destroy()
return 0;
}
// ---------------------------------------------------------------
// Initializes the variables.
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::init()
{
INFO_LOG(m_logger) << "Init";
@@ -143,7 +143,7 @@ int32_t PrtCnvCentralThread::init()
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);
m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000); //or max unsigned short 65535
return 0;
}
@@ -155,9 +155,9 @@ int32_t PrtCnvCentralThread::deinit()
return 0;
}
// ---------------------------------------------------------------
// Starts the thread and connects to TCP-server
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::start()
{
INFO_LOG(m_logger) << "Start";
@@ -176,9 +176,9 @@ int32_t PrtCnvCentralThread::start()
return 0;
}
// ---------------------------------------------------------------
// Stops the thread
// ---------------------------------------------------------------
int32_t PrtCnvCentralThread::stop()
{
INFO_LOG(m_logger) << "Stop";
@@ -188,31 +188,31 @@ int32_t PrtCnvCentralThread::stop()
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::connected()
{
INFO_LOG(m_logger) << "Central-Socket connected m_Socket=" << m_webSocket;
m_SendCounter = 0;
m_SendCounter = 0; // we reset this counter after every connect to 0 => next telegram to send has counter 1 (preincrement)
m_LastSendCounter = 0;
m_ReceiveCounter = 0;
m_ReceiveCounter = 0; // send 0 until we get a telegram, we reset this counter after every connect to 0 => the next telegram from central must be 1
m_ReceiveAckCounter = 0;
m_aliveTimer->start();
if (m_bRadioThreadInitDone)
m_sendAckTimer->start();
m_State = PrtCnvSocketThread::e_WORKING;
emit checkSendToCentral();
emit checkSendToCentral(); // start sending telegrams for central still in list (reconnection)
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::disconnected()
{
INFO_LOG(m_logger) << "disconnected m_Socket=" << m_webSocket;
// for the case central is disconnecting, we have to disconnect also, otherwise
// we could send rubish (still resisting in buffers) after a reconnection
if (PrtCnvSocketThread::e_WORKING == m_State && m_webSocket)
m_webSocket->close();
@@ -233,10 +233,10 @@ void PrtCnvCentralThread::disconnected()
}
// ---------------------------------------------------------------
// Stores that radio-thread has stopped. Cleans the Db and
// reinitializes when central-thread has also stopped.
// ---------------------------------------------------------------
void PrtCnvCentralThread::radioStopped()
{
m_RadioStopped = true;
@@ -245,25 +245,25 @@ void PrtCnvCentralThread::radioStopped()
}
// ---------------------------------------------------------------
// Calls clean of radio-thread and Db-thread and initializes
// the variables for rework.
// ---------------------------------------------------------------
void PrtCnvCentralThread::cleanAndReinit()
{
INFO_LOG(m_logger) << "cleanAndReinit";
emit cleanRadio();
// reinit mit sicherung und löschung der datenbestände
m_ReceiveAckCounter = 0;
m_DbThread->cleanAndInit();
m_DoCleanup = false;
}
// ---------------------------------------------------------------
// Starts radio-thread and itself for proceeding work after
// cleaning the Db.
// ---------------------------------------------------------------
void PrtCnvCentralThread::radioCleant()
{
if (!m_DoCleanup)
@@ -280,16 +280,16 @@ void PrtCnvCentralThread::radioCleant()
}
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::onTextMessageReceived(const QString &msg)
{
// eat all pending readyReadyRead
if (m_DoCleanup)
return;
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
return; // do nothing when we are not in working state
onDirectTextMessageReceived(msg.toUtf8());
}
@@ -298,7 +298,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
try
{
if (baJson.isEmpty())
throw std::exception();
throw std::exception(); // FIXME: use own exception
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
const QJsonValue typeId = obj.value(QStringLiteral("typeId"));
@@ -311,16 +311,16 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
m_aliveTimer->start();
// which kind of telegram is it?
if (telegram.telegramId() == TrainingAreaBase::TetraIcd::BESTAETIGUNG)
{
// it is an ack-telegram
handleAck(&telegram);
}
else
{
DEBUG_LOG(m_logger) << "Received telegram '" << baJson << "'";
// a payload-telegram
handleTelegram(&telegram);
}
}
@@ -328,7 +328,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
{
ERROR_LOG(m_logger) << "JSon conversion error happenend. Error:"
<< e.what() << ", msg: " << baJson;
// inform central about the failure
TrainingAreaBase::TetraIcd::CtaDataError tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
@@ -339,21 +339,21 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson)
}
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::stateChanged(QAbstractSocket::SocketState newState)
{
INFO_LOG(m_logger) << "Websocket changed to state " << newState;
}
// ---------------------------------------------------------------
// Stores a telegram to be sent to radio in volatile radio-
// list and permanent in DB.
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
// => check with receive-counter if we lost a telegram or we get a telegram twice.
// => in this cases neither store the telegram nor send an ack (just ignore and read the next telegram)
// => the receive-counter will be hold on the last correct received telegram
DEBUG_LOG(m_logger) << "Receive Central-Telegram with telId=" << a_telegram->telegramId()
<< "; rcounter=" << a_telegram->counter();
if (checkAndUpdateReceiveCounter(a_telegram->counter()))
@@ -383,7 +383,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
case AreaEffectSimulationType::GasPipeDetonation:
case AreaEffectSimulationType::SpecialArea:
case AreaEffectSimulationType::Unknown:
Q_ASSERT(false);
Q_ASSERT(false); // should not happen but who knows
break;
case AreaEffectSimulationType::BeStillWarning:
case AreaEffectSimulationType::DangerZoneExplosion:
@@ -400,7 +400,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
bool bSomethingChanged = false;
for (int i = 0; i < msms.mineCount; ++i)
{
if (!LtsUtils::BitArray::testBit(msms.mineState, i))
if (!LtsUtils::BitArray::testBit(msms.mineState, i)) // 0 = triggered
{
INFO_LOG(m_logger) << "Testing bit " << i << " ... not set = triggered";
if (!oldTriggeredMines.contains(i))
@@ -419,7 +419,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
return;
}
INFO_LOG(m_logger) << "MineState telegram contains new informations... " << msms.aesDdsId;
oldTriggeredMines = newTriggeredMines;
oldTriggeredMines = newTriggeredMines; // update in m_alreadyTriggeredMines[]
}
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>
@@ -427,7 +427,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
if (radioTelegram)
{
if (radioTelegram->getIdentity() <= m_maxEqID) {
// save data in persistent database
m_DbThread->storeRadioTelegram(radioTelegram, a_telegram->counter());
} else {
WARNING_LOG(m_logger) << "Central telegram with telId=" << a_telegram->telegramId()
@@ -445,20 +445,20 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_
emit checkSendToRadio();
}
// ---------------------------------------------------------------
// The counter will be set to a_startCounter if a_maxCounter
// is reached
// returns true if receive-counter is ok
// returns false if a telegram is repeated or lost
// ---------------------------------------------------------------
bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter)
{
TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter;
// check for wrap
if (std::numeric_limits<int32_t>::max() == ++m_ReceiveCounter)
m_ReceiveCounter = 0;
// has the counter the expected value?
if (m_ReceiveCounter != a_counter)
{
if (m_ReceiveCounter > a_counter)
@@ -473,30 +473,43 @@ bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter)
}
#if 0
m_ReceiveCounter--;
return false;
return false; // failure
#else
m_ReceiveCounter = a_counter;
return true;
#endif
}
return true;
return true; // all ok
}
// ---------------------------------------------------------------
// used to send periodically an ack to central
// ---------------------------------------------------------------
void PrtCnvCentralThread::timeoutTick()
{
//NOTICE_LOG(m_logger) << "timeoutTick, " << m_DoCleanup << ", " << m_State;
if (m_DoCleanup)
return;
return; // eat all pending timeouts
if (PrtCnvSocketThread::e_WORKING != m_State)
return;
return; // do nothing when we are not in working state
/*
// Das bringt nur noch mehr Traffic wenn zskskp die gesendeten Daten
// nicht schnell genug abarbeiten kann - deshalb ersteinmal auskommentiert
// do we have to resend unacked telegrams
if (m_DbThread->resendCentralTelegrams(m_LastSendCounter))
{
emit checkSendToCentral(); // resend
}
else
{
// nothing has to be resent => update m_LastSendCounter
m_LastSendCounter = m_SendCounter;
}
*/
// do we have to inject a central-telegram?
try
{
N_CoPrtCnv::CoPrtCnvCentralTelegram *centralInjectTelegram;
@@ -512,13 +525,13 @@ void PrtCnvCentralThread::timeoutTick()
<< " => could not inject radio-telegram, but we proceed...";
}
// send the periodically ack-telegram to central
sendAck();
}
// ---------------------------------------------------------------
// see base-class
// ---------------------------------------------------------------
void PrtCnvCentralThread::timeoutAliveAndConnection()
{
INFO_LOG(m_logger) << "timeoutAliveAndConnection socketState="
@@ -543,16 +556,16 @@ void PrtCnvCentralThread::timeoutAliveAndConnection()
}
}
// ---------------------------------------------------------------
// Sends a ack-telegram to central.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendAck()
{
TrainingAreaBase::TetraIcd::Acknowledge ack;
ack.timeStamp = time(nullptr) * 1000;
ack.ackCounter = m_ReceiveAckCounter;
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(ack);
// send to socket
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(tele.data()));
else
@@ -562,10 +575,10 @@ void PrtCnvCentralThread::sendAck()
}
// ---------------------------------------------------------------
// Sends a central-telegram to socket or file, depending on
// configuration. Before sending, the send-counter will be set.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
PrtCnvStoredCentralTelegram *handle = nullptr;
@@ -573,11 +586,11 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te
}
// ---------------------------------------------------------------
// Sends a central-telegram to socket or file, depending on
// configuration. Before sending, the send-counter will be set.
// After sending the Db will be updated.
// ---------------------------------------------------------------
void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram,
PrtCnvStoredCentralTelegram *a_handle)
{
@@ -585,43 +598,43 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te
if (a_telegram->telegramId() == TelegramId::DEAKTIVIERUNG_EINZELMINE)
{
const MineTriggered tele(MineTriggered::fromJson(a_telegram->jsonData()));
m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1);
m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1); // starts at 1 ...
INFO_LOG(m_logger) << "Adding triggered mine with id " << tele.mineIndex << " to area id " << tele.mineAreaId;
}
// set the counter, but keep old counter if we resend the telegram
const int writeCounter = a_handle ? a_handle->writeCounter() : 0;
if (writeCounter != 0)
a_telegram->setCounter(writeCounter);
else
a_telegram->setCounter(++m_SendCounter);
// send telegram to central
DEBUG_LOG(m_logger) << "Send telegram to central: telId=" << a_telegram->telegramId()
<< " wcounter=" << a_telegram->counter();
// send to socket
if (m_webSocket)
m_webSocket->sendTextMessage(QString::fromUtf8(a_telegram->data()));
else
emit directTextMessage(a_telegram->data());
// mark in Db telegram as sent
if (a_handle)
m_DbThread->centralTelegramSent(a_telegram->counter(), a_handle);
m_LogThread->writeCentralTelegramLog(a_telegram, true, 1);
}
// ---------------------------------------------------------------
// Processes the telegram
// AnforderungStatistikBroadcastNachforderugen. The function
// fills the answer telegram StatistikBroadNachforderungen
// with the actual statistic.
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen()
{
const auto nachforderungsStat = m_DbThread->getClaimStatistics();
// inform central about the failure
TrainingAreaBase::TetraIcd::BroadcastStatistics tele;
tele.header.equipmentNumber = m_VirtualTeilnehmerId;
tele.header.timeStamp = time(nullptr) * 1000LL;
@@ -638,14 +651,14 @@ void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen()
sendTelegram(&telegram);
}
// ---------------------------------------------------------------
// Checks whether a telegram must be sent and sends it.
// ---------------------------------------------------------------
void PrtCnvCentralThread::checkSend()
{
// eat all pending checkSend-signals, if we have to cleanup
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state
PrtCnvStoredCentralTelegram *handle = nullptr;
auto *centralTelegram = m_DbThread->getNextCentralTelegram(handle);
if (centralTelegram)
@@ -656,26 +669,26 @@ void PrtCnvCentralThread::checkSend()
}
}
// ---------------------------------------------------------------
// Removes telegrams from ToCentral-table, if the central
// acknowledges their reception
// ---------------------------------------------------------------
void PrtCnvCentralThread::handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
TrainingAreaBase::TetraIcd::Acknowledge ack(TrainingAreaBase::TetraIcd::Acknowledge::fromJson(a_telegram->jsonData()));
// INFO_LOG(m_logger) << "Got Central-Ack with wcounter=" << a_ackTelegram.zaehler();
m_DbThread->ackCentralTelegrams(ack.ackCounter);
}
// ---------------------------------------------------------------
// Will be called from Db-thread when telegrams were stored
// permanent. This function will then send the ack to central
// (socket-based) or delete the telegramfiles (file-based)
// ---------------------------------------------------------------
void PrtCnvCentralThread::permanentStored(int32_t a_centralCounter)
{
if (m_DoCleanup) return;
if (PrtCnvSocketThread::e_WORKING != m_State) return;
if (m_DoCleanup) return; // eat all pending permanentStored
if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state
DEBUG_LOG(m_logger) << "got permanentStored a_centralCounter=" << a_centralCounter;
if (0 != a_centralCounter && a_centralCounter > m_ReceiveAckCounter)
{
@@ -732,10 +745,10 @@ void PrtCnvCentralThread::onRadioThreadInitDone()
m_sendAckTimer->start();
}
// ---------------------------------------------------------------
// returns true if telegram should be converted, stored and
// sent to radio
// ---------------------------------------------------------------
bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram)
{
using namespace TrainingAreaBase::TetraIcd;
@@ -750,17 +763,17 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
case ExerciseStateData::ExerciseState::Terminated:
{
INFO_LOG(m_logger) << "Got Betriebszustandsmeldung Uebung_Aufraeumen => disconnect, cleanup and reconnect";
m_DbThread->setMachineState(1);
m_DbThread->setMachineState(1); // store permanent that we cleanup now, so we will proceed cleanup, after a crash
// send ack before disconnecting
permanentStored(a_telegram->counter());
m_DoCleanup = true;
m_CentralStopped = false;
m_RadioStopped = false;
// INFO_LOG(m_logger) << "stop timer";
m_sendAckTimer->stop();
m_DbThread->waitUntilDbWritten();
disconnectSocket();
m_RadioThread->prepareCleanUp();
m_RadioThread->prepareCleanUp(); // this makes empty the message-queue of radio-thread faster
emit stopRadio();
m_reconnectTimer->start();
break;
@@ -779,7 +792,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
return false;
}
case Constraints<RequestBroadcastStatistics>::id():
// here we must not use sendAck(), because it could be that we ack central-telegrams which are not yet stored permanent
m_DbThread->centralCounterReadyForAck(a_telegram->counter());
handleAnforderungStatistikBroadcastNachforderungen();
return false;
@@ -796,7 +809,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
return true;
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::connectSocket()
{
const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01"));
@@ -827,7 +840,7 @@ void PrtCnvCentralThread::connectSocket()
m_State = PrtCnvSocketThread::e_CONNECTING;
}
// ---------------------------------------------------------------
void PrtCnvCentralThread::disconnectSocket()
{
m_State = PrtCnvSocketThread::e_INITIAL;
@@ -841,4 +854,4 @@ void PrtCnvCentralThread::disconnectSocket()
m_webSocket = nullptr;
}
}
} // namespace PrtCnv