1710 lines
49 KiB
C++
1710 lines
49 KiB
C++
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "PrtCnvBroadcastMgr.hpp"
|
|
#include "PrtCnvDbThread.hpp"
|
|
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
|
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
|
|
#include <time.h>
|
|
#include <TrainingAreaBase/training_area_telegrams.h>
|
|
|
|
namespace PrtCnv
|
|
{
|
|
|
|
PrtCnvBroadcastMgr::PrtCnvBroadcastMgr()
|
|
: m_ClaimWindow(0)
|
|
, m_HighLoadFactor(0)
|
|
, m_BroadcastLimit(0)
|
|
, m_Config(nullptr)
|
|
, m_ActClaimWindow(0)
|
|
, m_State(e_ST_UNDEFINED)
|
|
, m_TickCounter(0)
|
|
, m_DbThread(nullptr)
|
|
, m_BroadcastIndex(0)
|
|
, m_IsFullLoad(false)
|
|
, m_FinishedBroadcastIndex(0)
|
|
, m_FirstBroadcastIndexOfBc1(0)
|
|
, m_logger(getLogger("PrtCnvBroadcastMgr"))
|
|
, m_loggerBcRequest(getLogger("PrtCnvBroadcastMgr.BcRequest"))
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t PrtCnvBroadcastMgr::create(NGL::Settings *settings)
|
|
{
|
|
m_Config = settings;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t PrtCnvBroadcastMgr::init()
|
|
{
|
|
const QString broadcastGroup(QStringLiteral("Broadcast"));
|
|
N_CoPrtCnv::CoPrtCnvRadioTelegram::setBroadcastDelayTimes(
|
|
m_Config->getInteger(broadcastGroup, QStringLiteral("BroadcastDelay2"), 60),
|
|
m_Config->getInteger(broadcastGroup, QStringLiteral("BroadcastDelay3"), 60));
|
|
N_CoPrtCnv::CoPrtCnvRadioTelegram::setMaxBroadcastSendCnt(m_Config->getInteger(broadcastGroup, QStringLiteral("MaxBroadcastSendCount"), 1));
|
|
|
|
const int sendGap = m_Config->getInteger(broadcastGroup, QStringLiteral("SendGap"), 500);
|
|
m_ClaimWindow = (m_Config->getInteger(broadcastGroup, QStringLiteral("ClaimWindow"), 30) * 1000) / sendGap;
|
|
m_HighLoadFactor = m_Config->getInteger(broadcastGroup, QStringLiteral("HighLoadFactor"), 3);
|
|
m_BroadcastLimit = m_Config->getInteger(broadcastGroup, QStringLiteral("BroadcastLimit"), 10);
|
|
|
|
cleanAndInit(true);
|
|
|
|
INFO_LOG(m_loggerBcRequest) << "m_ActClaimWindow=" << m_ActClaimWindow << " m_State=" << m_State;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::setDbThread(PrtCnvDbThread *a_dbThread)
|
|
{
|
|
m_DbThread = a_dbThread;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::cleanAndInit(const bool a_deleteTelegrams)
|
|
{
|
|
if (a_deleteTelegrams)
|
|
{
|
|
m_deactivatedAesArea2bcIndex.clear();
|
|
m_deactivatedBcIndex2AesArea.clear();
|
|
|
|
m_deactivatedDusMine2bcIndex.clear();
|
|
m_deactivatedBcIndex2DusMine.clear();
|
|
|
|
m_deactivatedFuncArea2bcIndex.clear();
|
|
m_deactivatedBcIndex2FuncArea.clear();
|
|
|
|
m_BroadcastMap.clear();
|
|
|
|
m_LastTelegramMap.clear();
|
|
m_FunktionsraumTelegramMap.clear();
|
|
m_WirkfeldTelegramMapByKennung.clear();
|
|
m_WirkfeldTelegramMapByTime.clear();
|
|
|
|
m_BroadcastIndex = 0;
|
|
}
|
|
|
|
m_claimerArray.clear();
|
|
|
|
m_ActClaimWindow = m_ClaimWindow;
|
|
m_IsFullLoad = false;
|
|
m_TickCounter = 0;
|
|
m_State = e_ST_COLLECT;
|
|
|
|
m_FinishedBroadcastIndex = 0;
|
|
m_FirstBroadcastIndexOfBc1 = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PrtCnvBroadcastMgr::handleRadioTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram)
|
|
{
|
|
switch (a_radioTelegram.getTelID())
|
|
{
|
|
case GEF_NACHFORDERUNG_BROADCAST_TELEGRAMME:
|
|
handleNachforderungBroadcastTelegram(a_radioTelegram.getIdentity(),
|
|
a_radioTelegram.getPayloadDataUInt32(8, 2) + 1,
|
|
a_radioTelegram.getPayloadDataUInt8(7));
|
|
return false;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::handleNachforderungBroadcastTelegram(int identity, int broadcastIndex, int resetCounter)
|
|
{
|
|
INFO_LOG(m_loggerBcRequest) << "Got NachforderungBroadcast from TNE with id=" << identity
|
|
<< " resetCounter=" << resetCounter
|
|
<< " broadcastIndex=" << broadcastIndex - 1
|
|
<< " m_TickCounter=" << m_TickCounter << " m_State=" << m_State;
|
|
if (resetCounter == m_DbThread->getResetCounter())
|
|
{
|
|
m_DbThread->incClaimCount(identity);
|
|
|
|
for (auto &ebi : m_claimerArray)
|
|
{
|
|
if (ebi.equipNo == identity)
|
|
{
|
|
ebi.bcIndex = broadcastIndex;
|
|
return;
|
|
}
|
|
}
|
|
m_claimerArray.emplace_back(identity, broadcastIndex);
|
|
return;
|
|
}
|
|
WARNING_LOG(m_logger) << "NachforderungBroadcast from TNE with id=" << identity
|
|
<< ": resetCounter different we have: " << int(m_DbThread->getResetCounter())
|
|
<< "; TNE has: " << resetCounter << " => discarded";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::getNextBroadcastTelegramToSend(const uint16_t a_beginSearchWithBroadcastIndex,
|
|
const time_t a_currentTime)
|
|
{
|
|
|
|
|
|
|
|
|
|
DEBUG_LOG(m_logger) << "getNextBroadcastTelegramToSend, startIdx: " << a_beginSearchWithBroadcastIndex;
|
|
auto iter = m_BroadcastMap.upper_bound(0 == a_beginSearchWithBroadcastIndex ? m_FinishedBroadcastIndex : a_beginSearchWithBroadcastIndex);
|
|
while (iter != m_BroadcastMap.end())
|
|
{
|
|
auto broadcastTelegram = iter->second;
|
|
gef_telegramm_id_et telId = broadcastTelegram->getTelID();
|
|
|
|
if (GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM == telId
|
|
|| GEF_WF_SAMMELDEAKTIVIERUNG == telId
|
|
|| GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN == telId)
|
|
{
|
|
|
|
if (!broadcastTelegram->getBroadcastonlyTelegram())
|
|
{
|
|
++iter;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
bool isBcOnly = false;
|
|
if (broadcastTelegram->getBroadcastonlyTelegram())
|
|
{
|
|
broadcastTelegram = broadcastTelegram->getBroadcastonlyTelegram();
|
|
isBcOnly = true;
|
|
}
|
|
|
|
bool wasLast = false;
|
|
if (broadcastTelegram->mustBeSentAsBroadcast(a_currentTime, wasLast))
|
|
{
|
|
|
|
if (wasLast)
|
|
{
|
|
if (isBcOnly || broadcastTelegram->isBroadcastOnly())
|
|
{
|
|
removeFromAllMaps(broadcastTelegram);
|
|
}
|
|
else
|
|
{
|
|
|
|
m_FinishedBroadcastIndex = broadcastTelegram->getBroadcastIndex();
|
|
}
|
|
}
|
|
|
|
broadcastTelegram->setIdentity(0);
|
|
return broadcastTelegram;
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t bcCounter = broadcastTelegram->getBroadcastCounter();
|
|
if (2 == bcCounter)
|
|
{
|
|
|
|
|
|
if (m_FirstBroadcastIndexOfBc1 > iter->first)
|
|
{
|
|
iter = m_BroadcastMap.lower_bound(m_FirstBroadcastIndexOfBc1);
|
|
continue;
|
|
}
|
|
}
|
|
else if (1 == bcCounter)
|
|
{
|
|
m_FirstBroadcastIndexOfBc1 = broadcastTelegram->getBroadcastIndex();
|
|
return nullptr;
|
|
}
|
|
}
|
|
++iter;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::getNextNachforderungTelegramToSend()
|
|
{
|
|
removeExpiredTelegrams();
|
|
switch (m_State)
|
|
{
|
|
case e_ST_COLLECT:
|
|
|
|
if (m_TickCounter >= m_ActClaimWindow && !m_IsFullLoad)
|
|
{
|
|
|
|
prepareForSendNachforderungen();
|
|
}
|
|
else
|
|
{
|
|
|
|
getAllFinishedBroadcastsFromDb();
|
|
}
|
|
break;
|
|
|
|
|
|
case e_ST_SEND_NACHFORDERUNG:
|
|
return evaluateNextNachforderungToSend();
|
|
default:
|
|
break;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeExpiredTelegrams()
|
|
{
|
|
const time_t now = time(nullptr);
|
|
auto iter = m_WirkfeldTelegramMapByTime.begin();
|
|
while (iter != m_WirkfeldTelegramMapByTime.end())
|
|
{
|
|
|
|
|
|
if (iter->first + 5 > now)
|
|
return;
|
|
|
|
auto radioTelegram = iter->second;
|
|
INFO_LOG(m_logger) << "Remove expired telegram with telId=" << radioTelegram->getTelID()
|
|
<< " and BC=" << radioTelegram->getBroadcastIndex() << " from BC-list";
|
|
uint16_t wirkfeldKennung = radioTelegram->getPayloadDataUInt32(5, 2);
|
|
removeWirkfeldTelegrams(wirkfeldKennung);
|
|
iter = m_WirkfeldTelegramMapByTime.begin();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::prepareForSendNachforderungen()
|
|
{
|
|
|
|
m_TickCounter = 0;
|
|
if (!m_claimerArray.empty())
|
|
{
|
|
dump();
|
|
|
|
|
|
|
|
m_State = e_ST_SEND_NACHFORDERUNG;
|
|
|
|
|
|
std::swap(m_claimerArray, m_claimerArray);
|
|
std::sort(m_claimerArray.begin(), m_claimerArray.end(),
|
|
[] (const EquipNoBcIndex &a, const EquipNoBcIndex &b)
|
|
{
|
|
if (a.bcIndex != b.bcIndex)
|
|
return a.bcIndex < b.bcIndex;
|
|
return a.equipNo < b.equipNo;
|
|
});
|
|
|
|
|
|
INFO_LOG(m_loggerBcRequest) << "BroadcastLimit: " << m_BroadcastLimit;
|
|
if (m_claimerArray.size() > m_BroadcastLimit)
|
|
{
|
|
m_claimerArray.clear();
|
|
m_claimerArray.emplace_back(0, m_claimerArray.begin()->bcIndex);
|
|
}
|
|
|
|
|
|
for (const EquipNoBcIndex &enbi : m_claimerArray)
|
|
{
|
|
int curBcIndex = enbi.bcIndex;
|
|
int nextBcIndex = -1;
|
|
|
|
while (true)
|
|
{
|
|
auto tel = getNachforderungsTelegram(curBcIndex, enbi.bcIndex, nextBcIndex);
|
|
curBcIndex = nextBcIndex;
|
|
if (tel)
|
|
{
|
|
auto copy(std::make_shared<N_CoPrtCnv::CoPrtCnvRadioTelegram>(*tel));
|
|
copy->setIdentity(enbi.equipNo);
|
|
m_broadcastTelegamsToSend.push_back(copy);
|
|
}
|
|
else
|
|
break;
|
|
};
|
|
|
|
std::sort(m_broadcastTelegamsToSend.begin(), m_broadcastTelegamsToSend.end(),
|
|
[] (const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a, const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &b)
|
|
{
|
|
const int bcIndexA = a->getTelID() == GEF_NOP ? a->getPayloadDataUInt32(3, 2) : a->getBroadcastIndex();
|
|
const int bcIndexB = b->getTelID() == GEF_NOP ? b->getPayloadDataUInt32(3, 2) : b->getBroadcastIndex();
|
|
if (bcIndexA != bcIndexB)
|
|
return bcIndexA > bcIndexB;
|
|
return a->getIdentity() < b->getIdentity();
|
|
});
|
|
|
|
if (m_loggerBcRequest.isDebugEnabled())
|
|
{
|
|
DEBUG_LOG(m_loggerBcRequest) << "Created broadcast list:";
|
|
for (const auto &tele : m_broadcastTelegamsToSend)
|
|
DEBUG_LOG(m_loggerBcRequest) << "Identity: " << tele->getIdentity()
|
|
<< ", bc: " << tele->getBroadcastIndex()
|
|
<< ", type: " << tele->getTelID();
|
|
}
|
|
}
|
|
m_claimerArray.clear();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::evaluateNextNachforderungToSend()
|
|
{
|
|
if (m_broadcastTelegamsToSend.empty())
|
|
{
|
|
m_State = e_ST_COLLECT;
|
|
return nullptr;
|
|
}
|
|
auto tel = m_broadcastTelegamsToSend.back();
|
|
m_broadcastTelegamsToSend.pop_back();
|
|
return tel;
|
|
}
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::createAccumulationTelegram(int curBcIndex,
|
|
int startBcIndex,
|
|
gef_telegramm_id_et telId,
|
|
const QMap<int, int> &bcIndex2Type,
|
|
int maxIdsPerTelegram,
|
|
int sizeOfSumField) const
|
|
{
|
|
if (bcIndex2Type.isEmpty())
|
|
return nullptr;
|
|
|
|
auto itLastBcTele = m_BroadcastMap.end();
|
|
--itLastBcTele;
|
|
const int endBcIndex = itLastBcTele->second->getBroadcastIndex();
|
|
|
|
DEBUG_LOG(m_loggerBcRequest) << "createAccumulationTelegram for telId " << telId
|
|
<< ", begin: " << startBcIndex
|
|
<< ", cur: " << curBcIndex << ", end: " << endBcIndex
|
|
<< ", #elements in container: " << bcIndex2Type.size();
|
|
DEBUG_LOG(m_loggerBcRequest) << "Given broadcast list for " << telegramId2String(telId);
|
|
for (auto it = bcIndex2Type.begin(); it != bcIndex2Type.end(); ++it)
|
|
DEBUG_LOG(m_loggerBcRequest) << " bcIndex: " << it.key()
|
|
<< ", id: " << it.value();
|
|
|
|
|
|
auto itStart = bcIndex2Type.lowerBound(startBcIndex);
|
|
if (itStart == bcIndex2Type.end())
|
|
{
|
|
Q_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
auto itEnd = bcIndex2Type.lowerBound(endBcIndex);
|
|
if (itEnd == bcIndex2Type.end())
|
|
--itEnd;
|
|
|
|
const int completeTelegrams = std::distance(itStart, itEnd) + 1;
|
|
if (completeTelegrams <= 0)
|
|
{
|
|
Q_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
const auto itCur = bcIndex2Type.find(curBcIndex);
|
|
if (itCur == bcIndex2Type.end())
|
|
{
|
|
Q_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
const int telegramsStillSendable = std::distance(itCur, itEnd) + 1;
|
|
if (telegramsStillSendable <= 0)
|
|
{
|
|
Q_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
|
|
const int telegramsToSend = (completeTelegrams / maxIdsPerTelegram) + 1;
|
|
if (telegramsStillSendable > telegramsToSend)
|
|
{
|
|
INFO_LOG(m_loggerBcRequest) << telId << ": sending nop since accuTelegram is sent later (" << telegramsStillSendable
|
|
<< ", need only " << telegramsToSend << ")";
|
|
return nullptr;
|
|
}
|
|
|
|
const int curIdStart = (telegramsToSend - telegramsStillSendable) * maxIdsPerTelegram;
|
|
const int idsToSendNow = (curIdStart + maxIdsPerTelegram <= completeTelegrams ? maxIdsPerTelegram : completeTelegrams % maxIdsPerTelegram);
|
|
INFO_LOG(m_loggerBcRequest) << telId << ": creating accuTelegram from index " << curIdStart << ", count: " << idsToSendNow;
|
|
|
|
itStart += curIdStart;
|
|
|
|
|
|
auto tele(std::make_shared<N_CoPrtCnv::CoPrtCnvRadioTelegram>(telId, 3 + 2 + sizeOfSumField + sizeof(uint16_t) * idsToSendNow, 0));
|
|
tele->setPayload2Byte(curBcIndex);
|
|
if (sizeOfSumField == 1)
|
|
tele->setPayload1Byte(idsToSendNow);
|
|
else if (sizeOfSumField == 2)
|
|
tele->setPayload2Byte(idsToSendNow);
|
|
else
|
|
{
|
|
Q_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
for (int i = 0; i < idsToSendNow; ++i)
|
|
{
|
|
tele->setPayload2Byte(itStart.value());
|
|
++itStart;
|
|
}
|
|
return tele;
|
|
}
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::createAccuTeleDeactivatedAesAreas(int curBcIndex,
|
|
int startBcIndex) const
|
|
{
|
|
return createAccumulationTelegram(curBcIndex, startBcIndex, GEF_WF_SAMMELDEAKTIVIERUNG,
|
|
m_deactivatedBcIndex2AesArea, 100, 1);
|
|
}
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::createAccuTeleDeactivatedFuncAreas(int curBcIndex,
|
|
int startBcIndex) const
|
|
{
|
|
return createAccumulationTelegram(curBcIndex, startBcIndex, GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM,
|
|
m_deactivatedBcIndex2FuncArea, 100, 1);
|
|
}
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::createAccuTeleDeactivatedDusMines(int curBcIndex,
|
|
int startBcIndex) const
|
|
{
|
|
return createAccumulationTelegram(curBcIndex, startBcIndex, GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN,
|
|
m_deactivatedBcIndex2DusMine, 500, 2);
|
|
}
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::createAccuTeleActivatedDusMines(int curBcIndex)
|
|
{
|
|
if (m_activatedDusMines.isEmpty())
|
|
return {};
|
|
|
|
const int idsToSendNow = m_activatedDusMines.size();
|
|
if (idsToSendNow > 500)
|
|
{
|
|
WARNING_LOG(m_logger) << "More than 500 activated DUS mines in system - this is not allowed!";
|
|
Q_ASSERT(false);
|
|
return {};
|
|
}
|
|
auto tele(std::make_shared<N_CoPrtCnv::CoPrtCnvRadioTelegram>(GEF_REAKTIVIERUNG_DUS_MINE, 5 + 2 + sizeof(uint16_t) * idsToSendNow, 0));
|
|
tele->setPayload2Byte(curBcIndex);
|
|
tele->setPayload2Byte(idsToSendNow);
|
|
for (int dusMineId : qAsConst(m_activatedDusMines))
|
|
tele->setPayload2Byte(dusMineId);
|
|
|
|
return tele;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>PrtCnvBroadcastMgr::getNachforderungsTelegram(int curBcIndex,
|
|
int startBcIndex,
|
|
int &nextBcIndex)
|
|
{
|
|
DEBUG_LOG(m_loggerBcRequest) << "getNachforderungsTelegram - curBcIndex: " << curBcIndex
|
|
<< ", startBcIndex: " << startBcIndex;
|
|
if (curBcIndex == 0) curBcIndex++;
|
|
DEBUG_LOG(m_loggerBcRequest) << "getNachforderungsTelegram - curBcIndex after Ssnity: " << curBcIndex
|
|
<< ", startBcIndex: " << startBcIndex;
|
|
|
|
nextBcIndex = curBcIndex;
|
|
bool doSendNop = false;
|
|
|
|
while (true)
|
|
{
|
|
auto iter = m_BroadcastMap.lower_bound(nextBcIndex);
|
|
if (iter == m_BroadcastMap.end())
|
|
break;
|
|
|
|
auto radioTelegram = iter->second;
|
|
DEBUG_LOG(m_loggerBcRequest) << "getNachforderungsTelegram - cur tel id is " << radioTelegram->getTelID()
|
|
<< ", bcIndex: " << radioTelegram->getBroadcastIndex()
|
|
<< ", send nop: " << doSendNop;
|
|
|
|
if (nextBcIndex < iter->first)
|
|
{
|
|
|
|
|
|
doSendNop = true;
|
|
nextBcIndex = iter->first;
|
|
}
|
|
else if (radioTelegram->isBroadcastOnly())
|
|
{
|
|
doSendNop = true;
|
|
nextBcIndex = iter->first + 1;
|
|
}
|
|
else
|
|
{
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> retTele;
|
|
switch (radioTelegram->getTelID())
|
|
{
|
|
case GEF_DEAKTIVIERUNG_WIRKFELD:
|
|
retTele = createAccuTeleDeactivatedAesAreas(radioTelegram->getBroadcastIndex(), startBcIndex);
|
|
break;
|
|
case GEF_DEAKTIVIEREN_FUNKTIONSRAUM:
|
|
retTele = createAccuTeleDeactivatedFuncAreas(radioTelegram->getBroadcastIndex(), startBcIndex);
|
|
break;
|
|
case GEF_DEAKTIVIERUNG_EINZELMINE:
|
|
retTele = createAccuTeleDeactivatedDusMines(radioTelegram->getBroadcastIndex(), startBcIndex);
|
|
break;
|
|
case GEF_REAKTIVIERUNG_DUS_MINE:
|
|
retTele = createAccuTeleActivatedDusMines(radioTelegram->getBroadcastIndex());
|
|
break;
|
|
default:
|
|
retTele = radioTelegram;
|
|
break;
|
|
}
|
|
|
|
|
|
if (retTele && doSendNop)
|
|
break;
|
|
++nextBcIndex;
|
|
if (retTele)
|
|
return retTele;
|
|
doSendNop = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!doSendNop && nextBcIndex <= m_BroadcastIndex)
|
|
{
|
|
nextBcIndex = m_BroadcastIndex + 1;
|
|
doSendNop = true;
|
|
}
|
|
|
|
if (doSendNop)
|
|
{
|
|
|
|
INFO_LOG(m_loggerBcRequest) << "Returning NOP: " << curBcIndex << " to " << nextBcIndex - 1;
|
|
return getNopTelegram(curBcIndex, nextBcIndex - 1);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::getAllFinishedBroadcastsFromDb(const bool a_doRestore)
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t broadcastIndex = 0;
|
|
while (true)
|
|
{
|
|
auto radioTelegram = m_DbThread->getNextBroadcastTelegram();
|
|
if (!radioTelegram)
|
|
break;
|
|
broadcastIndex = radioTelegram->getBroadcastIndex();
|
|
INFO_LOG(m_logger) << "Move Broadcast-telegram from DbThread>BroadcastMgr with telId="
|
|
<< radioTelegram->getTelID() << " BC=" << broadcastIndex;
|
|
dumpTelegram(m_logger, broadcastIndex, radioTelegram.get());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
addToBroadcastMap(radioTelegram);
|
|
}
|
|
|
|
if (a_doRestore && MAX_BROADCAST_INDEX == broadcastIndex)
|
|
handleOverrunOfBroadcastCounter(a_doRestore);
|
|
}
|
|
|
|
if (m_logger.isDebugEnabled())
|
|
{
|
|
static int iBroadcastDumpCounter = 0;
|
|
if ((iBroadcastDumpCounter++ % 30) == 0)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Dumping broadcast map:";
|
|
for (const auto &it : m_BroadcastMap)
|
|
dumpTelegram(m_logger, it.first, it.second.get());
|
|
}
|
|
}
|
|
|
|
|
|
if (a_doRestore)
|
|
{
|
|
m_BroadcastIndex = broadcastIndex;
|
|
m_FinishedBroadcastIndex = m_BroadcastIndex;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
INFO_LOG(m_logger) << "Move from radioList to bcList: BC=" << a_radioTelegram->getBroadcastIndex()
|
|
<< " telID=" << a_radioTelegram->getTelID();
|
|
switch (a_radioTelegram->getTelID())
|
|
{
|
|
|
|
case GEF_INIT:
|
|
case GEF_UMGEBUNGS_MELDUNG2:
|
|
ERROR_LOG(m_logger) << "Internal error: telegram with telId=" << a_radioTelegram->getTelID() << " should never be a normal broadcast";
|
|
break;
|
|
|
|
case GEF_DATENVERKEHR_TDS_SRT:
|
|
case GEF_DATENVERKEHR_TDS_DMF:
|
|
case GEF_TREFFER_AUSLOESUNG:
|
|
case GEF_ALLGEMEINE_NACHRICHT:
|
|
addBroadcastOnlyTelegramToMap(a_radioTelegram);
|
|
break;
|
|
|
|
|
|
case GEF_SPRACHAUSWAHL:
|
|
case GEF_KONFIGURATION_WIRKMODELL:
|
|
case GEF_TEILNEHMERMODE_SETZEN:
|
|
case GEF_TEILNEHMER_KONFIG_SETZEN:
|
|
replaceLastTelegramAndAddAtEnd(a_radioTelegram);
|
|
break;
|
|
|
|
case GEF_WIRKFELD_EINZELGESCHOSS:
|
|
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER:
|
|
case GEF_WIRKFELD_MINENSPERRE:
|
|
case GEF_WIRKFELD_A_KAMPFMITTEL:
|
|
case GEF_WIRKFELD_C_KAMPFMITTEL:
|
|
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP:
|
|
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN:
|
|
case GEF_WIRKFELD_STATUS_MINENSPERRE:
|
|
case GEF_WIRKFELD_EINZELMINENSIMULATOR:
|
|
{
|
|
|
|
const uint16_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
|
|
INFO_LOG(m_logger) << "Adding to braodcast map, Telegram Id: " << a_radioTelegram->getTelID()
|
|
<< ", kennung: " << wirkfeldKennung;
|
|
if (isEffectSimulationIdDeactivated(wirkfeldKennung))
|
|
{
|
|
INFO_LOG(m_logger) << "Got tele with tel id " << telegramId2String(a_radioTelegram->getTelID())
|
|
<< ", wirkfeldkennung: " << wirkfeldKennung << ", bcIndex: " << a_radioTelegram->getBroadcastIndex()
|
|
<< " but this effect simulation is already deactivated... ignoring";
|
|
dumpTelegram(m_logger, a_radioTelegram->getBroadcastIndex(), a_radioTelegram.get());
|
|
emit areaEffectSimulationActivated(wirkfeldKennung);
|
|
}
|
|
else if (0 != wirkfeldKennung && wirkfeldKennung <= std::numeric_limits<int16_t>::max())
|
|
{
|
|
switch (a_radioTelegram->getTelID())
|
|
{
|
|
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP:
|
|
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung, GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN);
|
|
break;
|
|
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN:
|
|
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung, GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP);
|
|
break;
|
|
case GEF_WIRKFELD_AENDERUNG_BEZEICHNER:
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung);
|
|
break;
|
|
case GEF_WIRKFELD_STATUS_MINENSPERRE:
|
|
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung, GEF_DEAKTIVIERUNG_EINZELMINE);
|
|
break;
|
|
default:
|
|
removeWirkfeldTelegrams(wirkfeldKennung);
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung);
|
|
removeFromDeactivatedAesArea(wirkfeldKennung);
|
|
emit areaEffectSimulationActivated(wirkfeldKennung);
|
|
break;
|
|
}
|
|
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
}
|
|
else
|
|
{
|
|
|
|
ERROR_LOG(m_logger) << "Internal error: Got invalid kennung: " << wirkfeldKennung;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GEF_WIRKFELD_AENDERUNG_BEZEICHNER:
|
|
{
|
|
auto wirkfeldTyp = static_cast<TrainingAreaBase::TetraIcd::AreaEffectSimulationType>(a_radioTelegram->getPayloadDataUInt32(5, 1));
|
|
uint16_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(6, 2);
|
|
INFO_LOG(m_logger) << "addToBroadcastMap - Wirkfeld Aenderung Bezeichner for type "
|
|
<< wirkfeldTyp2Str(wirkfeldTyp) << " - kennung: "
|
|
<< wirkfeldKennung;
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung);
|
|
break;
|
|
}
|
|
case GEF_DEAKTIVIERUNG_WIRKFELD:
|
|
{
|
|
auto wirkfeldTyp = static_cast<TrainingAreaBase::TetraIcd::AreaEffectSimulationType>(a_radioTelegram->getPayloadDataUInt32(5, 1));
|
|
uint16_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(6, 2);
|
|
INFO_LOG(m_logger) << "Deaktivierung Wirkfeld for type "
|
|
<< wirkfeldTyp2Str(wirkfeldTyp) << " - kennung: "
|
|
<< wirkfeldKennung << ", bc: " << a_radioTelegram->getBroadcastIndex();
|
|
switch (wirkfeldTyp)
|
|
{
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::MineArea:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionArea:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionSingle:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::NContamination:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::CContamination:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DusSingleMineSimulator:
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DangerZoneExplosion:
|
|
if (0 != wirkfeldKennung && wirkfeldKennung <= 32767)
|
|
{
|
|
emit areaEffectSimulationDeactivated(wirkfeldKennung);
|
|
|
|
removeWirkfeldTelegrams(wirkfeldKennung);
|
|
if (addToDeactivatedAesArea(wirkfeldKennung, a_radioTelegram->getBroadcastIndex()))
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung);
|
|
}
|
|
else
|
|
{
|
|
|
|
ERROR_LOG(m_logger) << "Internal error: Got invalid kennung: " << wirkfeldKennung;
|
|
}
|
|
break;
|
|
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::FunctionalArea:
|
|
default:
|
|
|
|
ERROR_LOG(m_logger) << "Internal error: WirkfeldTyp " << wirkfeldTyp2Str(wirkfeldTyp) << " in GEF_DEAKTIVIERUNG_WIRKFELD not implemented";
|
|
}
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
break;
|
|
}
|
|
|
|
case GEF_DEAKTIVIERUNG_EINZELMINE:
|
|
{
|
|
deactivateSingleMine(a_radioTelegram);
|
|
break;
|
|
}
|
|
|
|
case GEF_REAKTIVIERUNG_DUS_MINE:
|
|
{
|
|
reactivateDusMine(a_radioTelegram);
|
|
break;
|
|
}
|
|
|
|
case GEF_TECHNIK_FUNKTIONSRAUM:
|
|
{
|
|
|
|
uint16_t funktionsraumkennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
|
|
|
|
removeFromTechnikFunktionsAndBroadcastMaps(funktionsraumkennung);
|
|
|
|
|
|
m_TechnikFunktionsraumTelegramMap.insert(std::make_pair(funktionsraumkennung, a_radioTelegram));
|
|
|
|
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
break;
|
|
}
|
|
|
|
case GEF_FUNKTIONSRAUM:
|
|
{
|
|
|
|
uint16_t funktionsraumkennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
|
|
|
|
removeFromFunktionsAndBroadcastMaps(funktionsraumkennung);
|
|
removeFromDeactivatedFuncArea(funktionsraumkennung);
|
|
|
|
|
|
m_FunktionsraumTelegramMap.insert(std::make_pair(funktionsraumkennung, a_radioTelegram));
|
|
|
|
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
break;
|
|
}
|
|
|
|
case GEF_DEAKTIVIEREN_FUNKTIONSRAUM:
|
|
{
|
|
uint16_t funktionsraumkennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
|
|
emit areaEffectSimulationDeactivated(funktionsraumkennung);
|
|
|
|
removeFromFunktionsAndBroadcastMaps(funktionsraumkennung);
|
|
if (addToDeactivatedFuncArea(funktionsraumkennung, a_radioTelegram->getBroadcastIndex()))
|
|
m_FunktionsraumTelegramMap.insert(std::make_pair(funktionsraumkennung, a_radioTelegram));
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
break;
|
|
}
|
|
|
|
default:
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
template <typename T, typename S>
|
|
bool removeFromContainers(T &id2bcIndex, S &BcIndex2id, int aesAreaId)
|
|
{
|
|
auto it = id2bcIndex.find(aesAreaId);
|
|
if (it == id2bcIndex.end())
|
|
return false;
|
|
BcIndex2id.remove(it.value());
|
|
id2bcIndex.erase(it);
|
|
return true;
|
|
}
|
|
|
|
template <typename T, typename S>
|
|
bool addToContainers(T &id2bcIndex, S &BcIndex2id, int aesAreaId, int bcIndex)
|
|
{
|
|
auto it = id2bcIndex.find(aesAreaId);
|
|
if (it != id2bcIndex.end())
|
|
{
|
|
if (it.value() == bcIndex)
|
|
return false;
|
|
BcIndex2id.remove(it.value());
|
|
}
|
|
id2bcIndex[aesAreaId] = bcIndex;
|
|
BcIndex2id[bcIndex] = aesAreaId;
|
|
return true;
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::removeFromDeactivatedAesArea(int aesAreaId)
|
|
{
|
|
return removeFromContainers(m_deactivatedAesArea2bcIndex, m_deactivatedBcIndex2AesArea, aesAreaId);
|
|
}
|
|
|
|
|
|
bool PrtCnvBroadcastMgr::addToDeactivatedAesArea(int aesAreaId, int bcIndex)
|
|
{
|
|
return addToContainers(m_deactivatedAesArea2bcIndex, m_deactivatedBcIndex2AesArea, aesAreaId, bcIndex);
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::removeFromDeactivatedFuncArea(int aesAreaId)
|
|
{
|
|
return removeFromContainers(m_deactivatedFuncArea2bcIndex, m_deactivatedBcIndex2FuncArea, aesAreaId);
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::addToDeactivatedFuncArea(int aesAreaId, int bcIndex)
|
|
{
|
|
return addToContainers(m_deactivatedFuncArea2bcIndex, m_deactivatedBcIndex2FuncArea, aesAreaId, bcIndex);
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::removeFromDeactivatedDusMine(int dusMineId)
|
|
{
|
|
return removeFromContainers(m_deactivatedDusMine2bcIndex, m_deactivatedBcIndex2DusMine, dusMineId);
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::addToDeactivatedDusMine(int dusMineId, int bcIndex)
|
|
{
|
|
return addToContainers(m_deactivatedDusMine2bcIndex, m_deactivatedBcIndex2DusMine, dusMineId, bcIndex);
|
|
}
|
|
|
|
bool PrtCnvBroadcastMgr::removeFromActivatedDusMine(int dusMineId)
|
|
{
|
|
return (m_activatedDusMines.remove(dusMineId));
|
|
}
|
|
|
|
void PrtCnvBroadcastMgr::addToActivatedDusMine(int dusMineId)
|
|
{
|
|
m_activatedDusMines.insert(dusMineId);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int PrtCnvBroadcastMgr::getSammeltelegramIndex(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_sammelTelegram,
|
|
const uint16_t a_kennung) const
|
|
{
|
|
|
|
uint16_t nbrLength = 0;
|
|
switch (a_sammelTelegram->getTelID())
|
|
{
|
|
case GEF_WF_SAMMELDEAKTIVIERUNG:
|
|
case GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM:
|
|
nbrLength = 1;
|
|
break;
|
|
case GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN:
|
|
case GEF_REAKTIVIERUNG_DUS_MINE:
|
|
nbrLength = 2;
|
|
break;
|
|
default:
|
|
ERROR_LOG(m_logger) << "Unknown Sammeltelegram with telId=" << a_sammelTelegram->getTelID();
|
|
return -1;
|
|
}
|
|
|
|
const int cntAesIds = a_sammelTelegram->getPayloadDataUInt32(5, nbrLength);
|
|
for (int i = 0; i < cntAesIds; i++)
|
|
{
|
|
if (a_kennung == a_sammelTelegram->getPayloadDataUInt32(5 + nbrLength + i * 2, 2))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::deactivateSingleMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
uint32_t wirkfeldkennung = a_radioTelegram->getPayloadDataUInt32(9, 2);
|
|
uint32_t minenkennung = a_radioTelegram->getPayloadDataUInt32(11, 2);
|
|
|
|
if (0 == wirkfeldkennung)
|
|
{
|
|
removeFromActivatedDusMine(minenkennung);
|
|
addToDeactivatedDusMine(minenkennung, a_radioTelegram->getBroadcastIndex());
|
|
DEBUG_LOG(m_logger) << "Deactivating DUS-Mine: " << minenkennung << ", #deactivated mines: " << m_deactivatedBcIndex2DusMine.size();
|
|
removeDusMineDeactivationFromBroadcastMap(minenkennung);
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
}
|
|
else
|
|
{
|
|
|
|
bool sentAsNormalBroadcastFinished = deactivateEinzelmineFromMinensperre(wirkfeldkennung, minenkennung, a_radioTelegram->getBroadcastIndex());
|
|
if (sentAsNormalBroadcastFinished)
|
|
{
|
|
|
|
addWirkfeldTelegram(a_radioTelegram, wirkfeldkennung, GEF_BESTAETIGUNG, minenkennung);
|
|
addBroadcastOnlyTelegramToMap(a_radioTelegram);
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PrtCnvBroadcastMgr::deactivateEinzelmineFromMinensperre(const uint16_t a_wirkfeldKennung,
|
|
const uint16_t a_minenKennung,
|
|
const uint16_t a_broadcastIndex)
|
|
{
|
|
|
|
auto iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung);
|
|
while (iter != m_WirkfeldTelegramMapByKennung.end())
|
|
{
|
|
if (iter->first != a_wirkfeldKennung) break;
|
|
|
|
auto radioTelegram = iter->second;
|
|
if (radioTelegram->getTelID() == GEF_WIRKFELD_STATUS_MINENSPERRE && a_wirkfeldKennung == radioTelegram->getPayloadDataUInt32(5, 2))
|
|
{
|
|
|
|
uint16_t nbrOfMines = radioTelegram->getPayloadDataUInt32(7, 2);
|
|
if (nbrOfMines >= a_minenKennung && a_minenKennung != 0)
|
|
{
|
|
|
|
|
|
uint16_t bytePos = 9 + (a_minenKennung - 1) / 8;
|
|
if (bytePos < radioTelegram->getPayloadSize())
|
|
{
|
|
uint8_t mask = 0x80 >> ((a_minenKennung - 1) % 8);
|
|
|
|
|
|
radioTelegram->setPayloadDataWithIndex(bytePos, (uint8_t)(radioTelegram->getPayloadDataUInt8(bytePos) & (~mask)), 1);
|
|
moveTelegramInBroadcastMap(radioTelegram, a_broadcastIndex);
|
|
|
|
|
|
|
|
|
|
|
|
bool dummy;
|
|
if (radioTelegram->mustBeSentAsBroadcast(std::numeric_limits<time_t>::max(), dummy, false))
|
|
{
|
|
INFO_LOG(m_logger) << "A normal broadcast-telegram WirkfeldStatusMinensperre still exists";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
ERROR_LOG(m_logger) << "Got corrupt telegram WirkfeldstatusMinensperre with nbrOfMines=" << nbrOfMines << " and payloadSize=" << radioTelegram->getPayloadSize();
|
|
}
|
|
else
|
|
{
|
|
|
|
ERROR_LOG(m_logger) << "Mine with kennung=" << a_minenKennung << " does not fit into status (nbrOfMines=" << nbrOfMines << ")";
|
|
}
|
|
return true;
|
|
}
|
|
++iter;
|
|
}
|
|
ERROR_LOG(m_logger) << "Did not find the WirkfeldStatusMinensperre with kennung=" << a_wirkfeldKennung
|
|
<< ", therefore deactivated mine with kennung=" << a_minenKennung << " could not be updated.";
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::reactivateDusMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
|
|
const uint32_t nbrOfMines = a_radioTelegram->getPayloadDataUInt32(5, 2);
|
|
|
|
DEBUG_LOG(m_logger) << "Reactivating DUS-Mines, #mines: " << nbrOfMines;
|
|
if (0 == nbrOfMines)
|
|
{
|
|
|
|
for (int dusMineId : qAsConst(m_deactivatedBcIndex2DusMine))
|
|
{
|
|
removeDusMineDeactivationFromBroadcastMap(dusMineId);
|
|
addToActivatedDusMine(dusMineId);
|
|
}
|
|
m_deactivatedDusMine2bcIndex.clear();
|
|
m_deactivatedBcIndex2DusMine.clear();
|
|
}
|
|
else
|
|
{
|
|
|
|
for (uint32_t i = 0; i < nbrOfMines; i++)
|
|
{
|
|
const int dusMineId = a_radioTelegram->getPayloadDataUInt32(7 + 2 * i, 2);
|
|
DEBUG_LOG(m_logger) << "Reactivating DUS-Mines, mindId: " << dusMineId;
|
|
removeDusMineDeactivationFromBroadcastMap(dusMineId);
|
|
removeFromDeactivatedDusMine(dusMineId);
|
|
addToActivatedDusMine(dusMineId);
|
|
}
|
|
}
|
|
|
|
auto pred = [](const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &tele) -> bool
|
|
{
|
|
return (tele->getTelID() == GEF_REAKTIVIERUNG_DUS_MINE);
|
|
};
|
|
removeFromBroadcastMapFunc(pred);
|
|
m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::addWirkfeldTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
|
|
const uint16_t a_wirkfeldKennung,
|
|
const gef_telegramm_id_et a_telId,
|
|
const uint16_t a_minenKennung)
|
|
{
|
|
|
|
auto iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung);
|
|
while (iter != m_WirkfeldTelegramMapByKennung.end())
|
|
{
|
|
if (iter->first != a_wirkfeldKennung)
|
|
break;
|
|
auto radioTelegram = iter->second;
|
|
|
|
bool isSameMine = true;
|
|
if (0 != a_minenKennung)
|
|
{
|
|
if (GEF_DEAKTIVIERUNG_EINZELMINE == a_radioTelegram->getTelID())
|
|
{
|
|
if (GEF_DEAKTIVIERUNG_EINZELMINE == radioTelegram->getTelID())
|
|
{
|
|
uint16_t mineIndex = radioTelegram->getPayloadDataUInt32(11, 2);
|
|
isSameMine = mineIndex == a_minenKennung;
|
|
INFO_LOG(m_logger) << "Mine with kennung=" << a_minenKennung << " found: " << isSameMine;
|
|
}
|
|
}
|
|
else
|
|
ERROR_LOG(m_logger) << "Internal error: Only telegrams 'Deaktivierung_Einzelmine' must be called with a_mineKennung. I proceed without respecting mine-kennung...";
|
|
}
|
|
|
|
if ((radioTelegram->getTelID() == a_radioTelegram->getTelID() || radioTelegram->getTelID() == a_telId) && isSameMine)
|
|
{
|
|
|
|
removeFromWirkfeldAndBroadcastMaps(iter);
|
|
iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung);
|
|
}
|
|
else
|
|
++iter;
|
|
}
|
|
|
|
|
|
INFO_LOG(m_logger) << "Add kennung: " << a_wirkfeldKennung
|
|
<< " telId=" << a_radioTelegram->getTelID()
|
|
<< " BC=" << a_radioTelegram->getBroadcastIndex();
|
|
m_WirkfeldTelegramMapByKennung.insert(std::make_pair(a_wirkfeldKennung, a_radioTelegram));
|
|
time_t expireTime = a_radioTelegram->getExpireTime();
|
|
if (expireTime > 0)
|
|
m_WirkfeldTelegramMapByTime.insert(std::make_pair(expireTime, a_radioTelegram));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeWirkfeldTelegrams(const uint16_t a_kennung)
|
|
{
|
|
INFO_LOG(m_logger) << "Removing all Wirkfeld-Telegrams with kennung=" << a_kennung;
|
|
|
|
auto iter = m_WirkfeldTelegramMapByKennung.find(a_kennung);
|
|
while (iter != m_WirkfeldTelegramMapByKennung.end())
|
|
{
|
|
if (iter->first != a_kennung)
|
|
break;
|
|
|
|
removeFromWirkfeldAndBroadcastMaps(iter);
|
|
|
|
iter = m_WirkfeldTelegramMapByKennung.find(a_kennung);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeFromFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung)
|
|
{
|
|
auto iter = m_FunktionsraumTelegramMap.find(a_funktionsraumKennung);
|
|
if (iter != m_FunktionsraumTelegramMap.end())
|
|
{
|
|
auto radioTelegram = iter->second;
|
|
|
|
|
|
INFO_LOG(m_logger) << "Removing Funktionsraum-telegram with kennung=" << a_funktionsraumKennung
|
|
<< " and BC=" << radioTelegram->getBroadcastIndex();
|
|
m_FunktionsraumTelegramMap.erase(iter);
|
|
|
|
removeFromBroadcastMap(radioTelegram);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeFromTechnikFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung)
|
|
{
|
|
auto iter = m_TechnikFunktionsraumTelegramMap.find(a_funktionsraumKennung);
|
|
if (iter != m_TechnikFunktionsraumTelegramMap.end())
|
|
{
|
|
auto radioTelegram = iter->second;
|
|
|
|
|
|
INFO_LOG(m_logger) << "Removing Funktionsraum-telegram with kennung=" << a_funktionsraumKennung
|
|
<< " and BC=" << radioTelegram->getBroadcastIndex();
|
|
m_TechnikFunktionsraumTelegramMap.erase(iter);
|
|
|
|
removeFromBroadcastMap(radioTelegram);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeFromWirkfeldAndBroadcastMaps(const std::multimap<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>>::iterator &a_wirkfeldTelegramMapByKennungIterator)
|
|
{
|
|
auto radioTelegram = a_wirkfeldTelegramMapByKennungIterator->second;
|
|
|
|
INFO_LOG(m_logger) << "Removing wirkfeld-telegram with telId=" << radioTelegram->getTelID()
|
|
<< ", kennung=" << a_wirkfeldTelegramMapByKennungIterator->first
|
|
<< " and BC=" << radioTelegram->getBroadcastIndex()
|
|
<< " from byWirkfeldKennung-map";
|
|
|
|
|
|
m_WirkfeldTelegramMapByKennung.erase(a_wirkfeldTelegramMapByKennungIterator);
|
|
|
|
|
|
time_t expireTime = radioTelegram->getExpireTime();
|
|
if (0 != expireTime)
|
|
{
|
|
auto iter = m_WirkfeldTelegramMapByTime.find(expireTime);
|
|
while (iter != m_WirkfeldTelegramMapByTime.end())
|
|
{
|
|
if (iter->second == radioTelegram)
|
|
{
|
|
INFO_LOG(m_logger) << "Removing wirkfeld-telegram with telId=" << radioTelegram->getTelID()
|
|
<< " also from byTime-map";
|
|
m_WirkfeldTelegramMapByTime.erase(iter);
|
|
break;
|
|
}
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
removeFromBroadcastMap(radioTelegram);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeFromBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
|
|
if (!a_radioTelegram)
|
|
return;
|
|
|
|
auto iter = m_BroadcastMap.find(a_radioTelegram->getBroadcastIndex());
|
|
if (iter != m_BroadcastMap.end())
|
|
{
|
|
if (iter->second == a_radioTelegram)
|
|
{
|
|
m_BroadcastMap.erase(iter);
|
|
detachTelegram(a_radioTelegram);
|
|
}
|
|
else if (iter->second->getBroadcastonlyTelegram() == a_radioTelegram)
|
|
iter->second->setBroadcastonlyTelegram(nullptr);
|
|
}
|
|
}
|
|
|
|
void PrtCnvBroadcastMgr::removeFromBroadcastMapFunc(const std::function<bool(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &)> &pred)
|
|
{
|
|
auto it = m_BroadcastMap.begin();
|
|
while (it != m_BroadcastMap.end())
|
|
{
|
|
const auto &p = *it;
|
|
if (pred(p.second))
|
|
it = m_BroadcastMap.erase(it);
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void PrtCnvBroadcastMgr::removeDusMineDeactivationFromBroadcastMap(int dusMineId)
|
|
{
|
|
auto pred = [dusMineId](const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &tele) -> bool
|
|
{
|
|
return (tele->getTelID() == GEF_DEAKTIVIERUNG_EINZELMINE &&
|
|
0 == tele->getPayloadDataUInt32(9, 2) &&
|
|
uint32_t(dusMineId) == tele->getPayloadDataUInt32(11, 2));
|
|
};
|
|
removeFromBroadcastMapFunc(pred);
|
|
}
|
|
|
|
template <typename T>
|
|
void removeFromMap(T &cont, const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
auto iter = cont.begin();
|
|
while (iter != cont.end())
|
|
{
|
|
if (iter->second == a_radioTelegram)
|
|
iter = cont.erase(iter);
|
|
else
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::removeFromAllMaps(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
INFO_LOG(m_logger) << "Remove telegram with telId=" << a_radioTelegram->getTelID() << " BC=" << a_radioTelegram->getBroadcastIndex();
|
|
|
|
removeFromBroadcastMap(a_radioTelegram);
|
|
|
|
|
|
removeFromMap(m_WirkfeldTelegramMapByKennung, a_radioTelegram);
|
|
|
|
|
|
removeFromMap(m_WirkfeldTelegramMapByTime, a_radioTelegram);
|
|
|
|
|
|
removeFromMap(m_FunktionsraumTelegramMap, a_radioTelegram);
|
|
|
|
|
|
removeFromMap(m_LastTelegramMap, a_radioTelegram);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::replaceLastTelegramAndAddAtEnd(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_newRadioTelegram)
|
|
{
|
|
|
|
auto iter = m_LastTelegramMap.find(a_newRadioTelegram->getTelID());
|
|
if (iter != m_LastTelegramMap.end())
|
|
{
|
|
auto lastRadioTelegram = iter->second;
|
|
|
|
INFO_LOG(m_logger) << "remove last telegram with telId=" << lastRadioTelegram->getTelID()
|
|
<< " and BC=" << lastRadioTelegram->getBroadcastIndex();
|
|
removeFromBroadcastMap(lastRadioTelegram);
|
|
m_LastTelegramMap.erase(iter);
|
|
}
|
|
|
|
m_BroadcastMap.insert(std::make_pair(a_newRadioTelegram->getBroadcastIndex(), a_newRadioTelegram));
|
|
|
|
m_LastTelegramMap.insert(std::make_pair(a_newRadioTelegram->getTelID(), a_newRadioTelegram));
|
|
INFO_LOG(m_logger) << "New last telegram with with telId=" << a_newRadioTelegram->getTelID()
|
|
<< " and BC=" << a_newRadioTelegram->getBroadcastIndex();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::moveTelegramInBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
|
|
const uint16_t a_newBroadcastIndex,
|
|
const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_attachTelegram)
|
|
{
|
|
|
|
INFO_LOG(m_logger) << "Move telId=" << a_radioTelegram->getTelID()
|
|
<< " from BC=" << a_radioTelegram->getBroadcastIndex()
|
|
<< " to BC=" << a_newBroadcastIndex;
|
|
removeFromBroadcastMap(a_radioTelegram);
|
|
|
|
a_radioTelegram->setBroadcastIndex(a_newBroadcastIndex);
|
|
m_BroadcastMap.insert(std::make_pair(a_newBroadcastIndex, a_radioTelegram));
|
|
|
|
if (a_attachTelegram && (a_attachTelegram->getTelID() != GEF_REAKTIVIERUNG_DUS_MINE))
|
|
{
|
|
INFO_LOG(m_logger) << "Attach telID=" << a_attachTelegram->getTelID()
|
|
<< " to telID=" << a_radioTelegram->getTelID()
|
|
<< " BC=" << a_newBroadcastIndex;
|
|
a_radioTelegram->setBroadcastonlyTelegram(a_attachTelegram);
|
|
a_attachTelegram->setBroadcastIndex(a_newBroadcastIndex);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t PrtCnvBroadcastMgr::getBroadcastIndex() const
|
|
{
|
|
return m_BroadcastIndex;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t PrtCnvBroadcastMgr::getNextBroadcastIndex()
|
|
{
|
|
return ++m_BroadcastIndex;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> PrtCnvBroadcastMgr::getNopTelegram(const uint16_t a_from, const uint16_t a_to)
|
|
{
|
|
auto nopTelegram(std::make_shared<N_CoPrtCnv::CoPrtCnvRadioTelegram>(GEF_NOP, 7, 0));
|
|
nopTelegram->setPayloadDataWithIndex(3, a_from, 2);
|
|
nopTelegram->setPayloadDataWithIndex(5, a_to, 2);
|
|
return nopTelegram;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::addBroadcastOnlyTelegramToMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_broadcastOnlyTelegram)
|
|
{
|
|
uint16_t broadcastIndex = a_broadcastOnlyTelegram->getBroadcastIndex();
|
|
auto iter = m_BroadcastMap.find(broadcastIndex);
|
|
if (m_BroadcastMap.end() == iter)
|
|
{
|
|
|
|
INFO_LOG(m_logger) << "Insert telId=" << a_broadcastOnlyTelegram->getTelID()
|
|
<< " as broadcastonly telegram with BC=" << broadcastIndex;
|
|
a_broadcastOnlyTelegram->setBroadcastOnly();
|
|
m_BroadcastMap.insert(std::make_pair(broadcastIndex, a_broadcastOnlyTelegram));
|
|
}
|
|
else
|
|
{
|
|
|
|
INFO_LOG(m_logger) << "Add telId=" << a_broadcastOnlyTelegram->getTelID()
|
|
<< " as broadcastonly telegram to telegramm with BC=" << iter->second->getBroadcastIndex();
|
|
iter->second->setBroadcastonlyTelegram(a_broadcastOnlyTelegram);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::detachTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram)
|
|
{
|
|
auto broadcastOnlyTelegram = a_radioTelegram->getBroadcastonlyTelegram();
|
|
if (broadcastOnlyTelegram)
|
|
{
|
|
uint16_t broadcastIndex = a_radioTelegram->getBroadcastIndex();
|
|
|
|
INFO_LOG(m_logger) << "detach bconly-telegram : telId=" << a_radioTelegram->getTelID() << " BC=" << broadcastIndex;
|
|
if (broadcastOnlyTelegram->getBroadcastIndex() != broadcastIndex)
|
|
ERROR_LOG(m_logger) << "Internal error: BC=" << broadcastOnlyTelegram->getBroadcastIndex() << " of attached telegram is not equal BC=" << broadcastIndex;
|
|
auto iter = m_BroadcastMap.find(broadcastIndex);
|
|
if (iter != m_BroadcastMap.end())
|
|
ERROR_LOG(m_logger) << "Internal error: m_BroadcastMap-entry with BC=" << broadcastIndex << " must not exists";
|
|
else
|
|
{
|
|
INFO_LOG(m_logger) << "Insert broadcast-only BC=" << broadcastOnlyTelegram->getBroadcastIndex();
|
|
broadcastOnlyTelegram->setBroadcastOnly();
|
|
m_BroadcastMap.insert(std::make_pair(broadcastIndex, broadcastOnlyTelegram));
|
|
}
|
|
a_radioTelegram->setBroadcastonlyTelegram(nullptr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::handleOverrunOfBroadcastCounter(const bool a_doRestore)
|
|
{
|
|
WARNING_LOG(m_logger) << "Broadcast-counter reaches maximum => reduce broadcast-list and increment reset-counter";
|
|
|
|
|
|
|
|
if (!a_doRestore)
|
|
{
|
|
m_DbThread->waitUntilDbWritten();
|
|
getAllFinishedBroadcastsFromDb();
|
|
}
|
|
|
|
|
|
uint16_t newBroadcastCounter = 0;
|
|
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> newBroadcastMap;
|
|
auto iter = m_BroadcastMap.begin();
|
|
while (iter != m_BroadcastMap.end())
|
|
{
|
|
auto radioTelegram = iter->second;
|
|
if (radioTelegram->isBroadcastOnly())
|
|
{
|
|
|
|
++iter;
|
|
removeFromAllMaps(radioTelegram);
|
|
}
|
|
else
|
|
{
|
|
radioTelegram->setBroadcastIndex(++newBroadcastCounter);
|
|
auto broadcastOnlyTelegram = radioTelegram->getBroadcastonlyTelegram();
|
|
if (broadcastOnlyTelegram)
|
|
{
|
|
radioTelegram->setBroadcastonlyTelegram(nullptr);
|
|
++iter;
|
|
removeFromAllMaps(broadcastOnlyTelegram);
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
bool wasLast;
|
|
if (radioTelegram->mustBeSentAsBroadcast(std::numeric_limits<time_t>::max(), wasLast, false))
|
|
{
|
|
do
|
|
{
|
|
radioTelegram->mustBeSentAsBroadcast(std::numeric_limits<time_t>::max(), wasLast, true);
|
|
}
|
|
while (!wasLast);
|
|
}
|
|
++iter;
|
|
}
|
|
INFO_LOG(m_logger) << "New BC-index for broadcast-telegram with telId=" << radioTelegram->getTelID() << " BC=" << newBroadcastCounter;
|
|
newBroadcastMap.insert(std::make_pair(newBroadcastCounter, radioTelegram));
|
|
}
|
|
}
|
|
m_BroadcastMap.clear();
|
|
m_BroadcastMap = newBroadcastMap;
|
|
|
|
|
|
cleanAndInit(false);
|
|
if (!a_doRestore) m_DbThread->setResetCounter(m_DbThread->getResetCounter() + 1);
|
|
|
|
WARNING_LOG(m_logger) << "New broadcast-counter=" << newBroadcastCounter << " new reset-counter=" << (int)m_DbThread->getResetCounter();
|
|
m_BroadcastIndex = newBroadcastCounter;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::restoreAfterCrash()
|
|
{
|
|
getAllFinishedBroadcastsFromDb(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::dump()
|
|
{
|
|
|
|
for (const auto &it : m_BroadcastMap)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_BroadcastMap, ");
|
|
|
|
for (const auto &it : m_WirkfeldTelegramMapByKennung)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_WirkfeldTelegramMapByKennung, ");
|
|
|
|
for (const auto &it : m_WirkfeldTelegramMapByTime)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_WirkfeldTelegramMapByTime, ");
|
|
|
|
for (const auto &it : m_FunktionsraumTelegramMap)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_FunktionsraumTelegramMap, ");
|
|
|
|
for (const auto &it : m_TechnikFunktionsraumTelegramMap)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_TechnikFunktionsraumTelegramMap, ");
|
|
|
|
for (const auto &it : m_LastTelegramMap)
|
|
dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_LastTelegramMap, ");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvBroadcastMgr::incTickAndSetTrafficLoad(const bool a_isHighLoad, const bool a_isFullLoad)
|
|
{
|
|
if (e_ST_COLLECT == m_State)
|
|
++m_TickCounter;
|
|
m_IsFullLoad = a_isFullLoad;
|
|
if (a_isHighLoad)
|
|
m_ActClaimWindow = m_HighLoadFactor * m_ClaimWindow;
|
|
else
|
|
m_ActClaimWindow = m_ClaimWindow;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PrtCnvBroadcastMgr::isEffectSimulationIdDeactivated(const uint16_t effectsimulationId) const
|
|
{
|
|
INFO_LOG(m_logger) << "Checking deactivation for Id " << effectsimulationId;
|
|
return m_deactivatedAesArea2bcIndex.contains(effectsimulationId);
|
|
}
|
|
|
|
}
|