Files
qt5-legatus-legacy/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.cpp
T
2026-08-13 18:33:10 +02:00

209 lines
7.2 KiB
C++

// **************************************************************************
//
// @RDE_HEADER@
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// Implementation of the Class PrtCnvRadioTrafficThread
// **************************************************************************
#include "PrtCnvRadioTrafficThread.hpp"
#include "PrtCnvDbThread.hpp"
#include "PrtCnvThreadStarter.hpp"
#include <QtCore/QTimer>
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
#include <time.h>
namespace PrtCnv
{
PrtCnvRadioTrafficThread::PrtCnvRadioTrafficThread(PrtCnvThreadStarter* a_parent)
: PrtCnvThread(a_parent, "PrtCnvRadioTrafficThread")
, m_receiveLoad(PrtCnvRadioThread::E_TrafficLoad::Unknown)
, m_fullLoad(100)
, m_highLoad(50)
, m_hystLoad(5)
, m_calcTimeout(1000)
, m_cleanupTimeout(5000)
, m_mutex(QMutex::Recursive)
{}
void PrtCnvRadioTrafficThread::newTelegramArrived(unsigned int size)
{
time_t curTime = time(nullptr);
QMutexLocker l(&m_mutex);
DEBUG_LOG(m_logger) << "newTelegramArrived with size " << size << " at " << curTime;
m_data[curTime] += size;
m_telegrams[curTime]++;
}
int32_t PrtCnvRadioTrafficThread::start()
{
// read data from m_Config
const QString trafficControlGroup(QStringLiteral("TrafficControl"));
int highLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueHighLoad"), 60);
int fullLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueFullLoad"), 80);
int hystLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueHysteresis"), 5);
int avgTime = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveAveragingTime"), 5);
float trafficPerReceiverKB = m_Config->getFloat(trafficControlGroup, QStringLiteral("ReceiveThroughput"), 3.6f);
int cntTransceiver = m_Config->getInteger(trafficControlGroup, QStringLiteral("TransceiverCount"), 6);
// sanity checks
if (highLoad < 0 || highLoad > 100)
highLoad = 60;
if (fullLoad < highLoad || fullLoad > 100)
fullLoad = 80;
if (hystLoad < 0 || hystLoad > 10)
hystLoad = 5;
if (avgTime <= 0 || avgTime > 60)
avgTime = 5;
if (trafficPerReceiverKB < 1 || trafficPerReceiverKB > 1000)
trafficPerReceiverKB = 3.6f;
if (cntTransceiver < 1 || cntTransceiver > 100)
cntTransceiver = 6;
float maxTrafficBytes = trafficPerReceiverKB * cntTransceiver * 1024;
m_fullLoad = maxTrafficBytes * fullLoad / 100.f;
m_highLoad = maxTrafficBytes * highLoad / 100.f;
m_hystLoad = maxTrafficBytes * hystLoad / 100.f;
m_cleanupTimeout = avgTime * 1000; // ms
DEBUG_LOG(m_logger) << "Read config ReceiveQueueHighLoad: " << highLoad;
DEBUG_LOG(m_logger) << "Read config ReceiveQueueFullLoad: " << fullLoad;
DEBUG_LOG(m_logger) << "Read config ReceiveQueueHysteresis: " << hystLoad;
DEBUG_LOG(m_logger) << "Read config ReceiveAveragingTime: " << avgTime;
DEBUG_LOG(m_logger) << "Read config ReceiveThroughput: " << trafficPerReceiverKB;
DEBUG_LOG(m_logger) << "Read config TransceiverCount: " << cntTransceiver;
INFO_LOG(m_logger) << "Using to following limits: high - " << m_highLoad
<< " full - " << m_fullLoad
<< " hyst - " << m_hystLoad
<< " avg. time - " << m_cleanupTimeout / 1000;
QTimer::singleShot(m_calcTimeout, this, &PrtCnvRadioTrafficThread::onCalculateTrafficLoad);
QTimer::singleShot(m_cleanupTimeout, this, &PrtCnvRadioTrafficThread::onCleanupTimeout);
return 0;
}
void PrtCnvRadioTrafficThread::onCalculateTrafficLoad()
{
const time_t curTime = time(nullptr);
unsigned int payload = 0;
{
QMutexLocker l(&m_mutex);
// fuer aktuelle Sekunde haben wir noch nicht alle Daten
for (int i = 1; i <= m_cleanupTimeout / 1000; ++i)
payload += m_data.value(curTime - i);
}
// Durchschnitt ...
payload /= (m_cleanupTimeout / 1000);
INFO_LOG(m_logger) << "Average Payload in the last "
<< m_cleanupTimeout << " Milliseconds: "
<< payload << " Bytes/sec, last sec: "
<< m_data[curTime - 1] << " Bytes, #telegrams: " << m_telegrams[curTime - 1];
PrtCnvRadioThread::E_TrafficLoad newReceiveLoad;
if (payload >= m_fullLoad)
{
// full load
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad;
// Hysterese nach oben
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad)
{
// wenn cnt in Bereich m_fullLoad ... m_fullLoad + m_hystLoad
// -> noch warten
if(payload < m_fullLoad + m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
}
}
else if (payload >= m_highLoad)
{
// high load
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
// Hysterese nach oben
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::NormalLoad)
{
// wenn cnt in Bereich m_highLoad ... m_highLoad + m_hystLoad
// -> noch warten
if (payload < m_highLoad + m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad;
}
// Hysterese nach unten
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::FullLoad)
{
// wenn cnt in Bereich m_fullLoad ... m_fullLoad - m_hystLoad
// -> noch warten
if (payload >= m_fullLoad - m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad;
}
}
else
{
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad;
// Hysterese nach unten
if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad)
{
// wenn cnt in Bereich m_highLoad ... m_highLoad - m_hystLoad
// -> noch warten
if(payload >= m_highLoad - m_hystLoad)
newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad;
}
}
if (m_receiveLoad != newReceiveLoad)
{
m_receiveLoad = newReceiveLoad;
// Achtung: Nicht mehr als 31 Sekunden erlaubt
unsigned int wartezeit_posmldg = (static_cast<unsigned int>(m_receiveLoad) * 10) + 1;
INFO_LOG(m_logger) << "New traffic load: " << m_receiveLoad;
PrtCnvDbThread *dbThread = qobject_cast<PrtCnvDbThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Db));
if (dbThread)
{
dbThread->setAirLoad(m_receiveLoad);
dbThread->setPositionSendTime(wartezeit_posmldg);
Q_ASSERT(QThread::currentThreadId() == m_currentThreadId);
}
else
ERROR_LOG(m_logger) << "Could not get PrtCnvDbThread!";
}
QTimer::singleShot(m_calcTimeout, this, &PrtCnvRadioTrafficThread::onCalculateTrafficLoad);
}
void PrtCnvRadioTrafficThread::onCleanupTimeout()
{
const time_t curTime = time(nullptr);
{
QMutexLocker l(&m_mutex);
QMap<time_t, unsigned int>::iterator it = m_data.begin();
while (it != m_data.end())
{
const time_t key = it.key();
// 10 als Puffer (siehe auch onCalculateTrafficLoad())
if (key < curTime - m_cleanupTimeout - 10)
{
m_data.erase(it++);
m_telegrams.remove(key);
continue;
}
break; // arbitrarily ordered
}
}
QTimer::singleShot(m_cleanupTimeout, this, &PrtCnvRadioTrafficThread::onCleanupTimeout);
}
} // namespace PrtCnv