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

575 lines
19 KiB
C++

// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "logger.h"
#include <CoPrtCnv/tetra_telegram_ids.h>
#include <nglsettings/nglsettings_settings.h>
#include <TrainingAreaBase/training_area_telegrams.h>
#include <QObject>
#include <QHash>
#include <QMap>
#include <QSet>
#include <map>
#include <memory>
#include <vector>
namespace N_CoPrtCnv
{
class CoPrtCnvRadioTelegram;
}
#define MAX_BROADCAST_INDEX 65535
namespace PrtCnv
{
class PrtCnvDbThread;
/**
* This class is responsible for handling all the broadcast stuff. This includes:
* - sending the broadcast 3 times
* - sending Broadcast-Nachforderungen to TNE
* - store and manage the broadcast-list
* - measure the Broadcast-Nachforderung-statistic
* @author wia
* @version 1.0
* @updated 30-Apr-2010 11:21:05
*/
class PrtCnvBroadcastMgr final : public QObject
{
Q_OBJECT
public:
/**
* The different states the broadcast-manager can be.
* @author wia
* @version 1.0
* @updated 30-Apr-2010 11:21:05
*/
enum E_State
{
e_ST_UNDEFINED,
e_ST_COLLECT,
e_ST_SEND_NACHFORDERUNG
};
PrtCnvBroadcastMgr();
/**
* returns true when the telegram should be sent to central
*
* @param a_radioTelegram
*/
bool handleRadioTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
/**
* Creates all subcomponents
*/
int32_t create(NGL::Settings *settings);
/**
* Initializes the variables.
*/
int32_t init();
/**
* returns the next normal broadcast to send.
* a_doDelete is true, when the caller has to delete the telegram when no longer
* using it.
* Use the same a_actualTime in one tick-loop.
*
* @param a_beginSearchWithBroadcastIndex
* @param a_actualTime
* @param a_doDelete true if telegram must be deleted after using it
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextBroadcastTelegramToSend(const uint16_t a_beginSearchWithBroadcastIndex,
const time_t a_currentTime);
/**
* sets the DbThread used for get the stored broadcast-telegrams
*
* @param a_dbThread
*/
void setDbThread(PrtCnvDbThread *a_dbThread);
/**
* Initializes the broadcast-manager. If a_deleteTelegrams is true, all stored
* telegrams and maps will be deleted.
*
* @param a_deleteTelegrams
*/
void cleanAndInit(const bool a_deleteTelegrams);
/**
* Removes all Nop out of broadcast-list and numerates the broadcast-index of kept
* broadcast-telegrams new.
*
* @param a_doRestore
*/
void handleOverrunOfBroadcastCounter(const bool a_doRestore = false);
/**
* returns the next broadcast to send for nachforderungen
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNextNachforderungTelegramToSend();
/**
* dumps important values, only for debugging
*/
void dump();
/**
* Restores data after crash for seamless proceeding of work.
*/
void restoreAfterCrash();
/**
* Returns the actual broadcast-index for normal broadcasts.
*/
uint16_t getBroadcastIndex() const;
/**
* Returns the broadcastindex for the next broadcast
*/
uint16_t getNextBroadcastIndex();
/**
* Adds the telegram a_broadcastOnlyTelegram (which must have set already the
* broadcast-index) to the broadcast-map. The telegram will be attached to an
* already existing broadcast-telegram with same broadcast-index in the map,
* otherwise it will be marked as broadcast-only.
* If the there is already an broadcast-only-telegram attached, nothing will be
* done.
*
* @param a_broadcastOnlyTelegram
*/
void addBroadcastOnlyTelegramToMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_broadcastOnlyTelegram);
/**
* Increments the tick-counter of broadcast-manager and informs the broadcast-
* manager about the traffic-load.
*
* @param a_isHighLoad
* @param a_isFullLoad
*/
void incTickAndSetTrafficLoad(const bool a_isHighLoad, const bool a_isFullLoad);
/**
* Checks if the given id is in m_deactivatedAesMine2bcIndex/m_deactivatedDusMine2bcIndex/m_deactivatedFuncAreaMine2bcIndex
*
* @brief isEffectSimulationIdDeactivated
* @param effectsimulationId
* @return
*/
bool isEffectSimulationIdDeactivated(const uint16_t effectsimulationId) const;
/**
* Adds the TNE to the nachforderungs-list
*
* @param a_radioTelegram
*/
void handleNachforderungBroadcastTelegram(int identity, int broadcastIndex, int resetCounter);
protected:
struct EquipNoBcIndex
{
int equipNo = 0;
int bcIndex = 0;
EquipNoBcIndex() = default;
EquipNoBcIndex(int e, int b) : equipNo(e), bcIndex(b) {}
};
/**
* Map of TNE, that sent a NachforderungBroadcast-Telegram.
* Key: identity of TNE; Value: broadcast-counter
*/
std::vector<EquipNoBcIndex> m_claimerArray;
/**
* Time (in SendGap-ticks) spent for collection NachforderungeBroadcast, before
* sending broadcasts begins
* This value will be used for normal load.
*/
uint16_t m_ClaimWindow;
/**
* the factor for widening claim-window before sending broadcasts when we have
* high load traffic
*/
uint16_t m_HighLoadFactor;
/**
* the number of TPUs needed for sending the broadcasts as broadcast instead
* directed
*/
uint16_t m_BroadcastLimit;
/**
* Used to get configuration-parameter.
*/
NGL::Settings *m_Config;
/**
* Actual time (in SendGap-ticks) spent for collection NachforderungeBroadcast,
* before sending broadcasts begins. This value changes depending on downlink-load.
*/
uint16_t m_ActClaimWindow;
/**
* The state of broadcast-manager.
*/
PrtCnvBroadcastMgr::E_State m_State;
uint16_t m_TickCounter;
/**
* The actual broadcast-index for sending nachforderungen
*/
PrtCnvDbThread *m_DbThread;
/**
* sorted by broadcast-index
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_BroadcastMap;
std::vector<std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_broadcastTelegamsToSend;
/**
* Contains all telegrams which must only be stored once for nachforderungen
*/
std::map<gef_telegramm_id_et, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_LastTelegramMap;
/**
* Contains all wirkfeld-telegrams which must be stored for nachforderungen
* ordered by wirkfeldkennung.
*/
std::multimap<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_WirkfeldTelegramMapByKennung;
/**
* Contains all wirkfeld-telegrams which must be stored for nachforderungen
* ordered by expiration-time.
*/
std::multimap<time_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_WirkfeldTelegramMapByTime;
/**
* Contains all funktionsraum-telegrams which must be stored for nachforderungen
* ordered by funktionsraumkennung.
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_FunktionsraumTelegramMap;
/**
* Contains all technik-funktionsraum-telegrams which must be stored for nachforderungen
* ordered by funktionsraumkennung.
*/
std::map<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>> m_TechnikFunktionsraumTelegramMap;
/**
* The actual broadcast-index for normal broadcast
*/
uint16_t m_BroadcastIndex;
/**
* True if send-traffic is on full-load => no nachforderungen will be sent
*/
bool m_IsFullLoad;
/**
* The highest broadcast-index of 3rd time sent broadcast-telegram (for optimize
* by time)
*/
uint16_t m_FinishedBroadcastIndex;
/**
* The broadcast-index of the 1st broadcast-telegram which has been sent 1 time
* only (for optimize by time)
*/
uint16_t m_FirstBroadcastIndexOfBc1;
/**
* adds the radio-telegram to the broadcast-map, or generates the sammeltelegramme
*
* @param a_radioTelegram
*/
void addToBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* returns the Nachforderungs-telegram with this broadcast-index from the
* broadcast-map with sammeltelegrams. If the telegram with a_broadcastIndex does
* not exist, a NOP-telegram will be returned, which must be consumed immediately
* and must never be deleted.
* The parameter a_broadcastIndex will be updated to the value of found telegram.
* ATTENTION: the returned a_broadcastIndex could be different from the value
* returned by getBroadcastIndex(), for example in NOP-telegrams
* getBroadcastIndex() returns the Anfang, but a_broadcastIndex will be the Ende.
*
* @param a_broadcastIndex
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNachforderungsTelegram(int curBcIndex, int startBcIndex, int &nextBcIndex);
/**
* searches the kennung within sammeltelegram.
* returns -1 when kennung not found
*
* @param a_sammelTelegram
* @param a_kennung
*/
int getSammeltelegramIndex(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_sammelTelegram,
const uint16_t a_kennung) const;
/**
* Moves a_radioTelegram to a_newBroadcastIndex in broadcast-map.
* If a_radioTelegram has an attached broadcast-only-telegram, the broadcastOnly-
* telegram will be detached and kept on the old broadcast-index position.
* If a_attachTelegram in not NULL, this telegram will be attached to
* a_radioTelegram.
*
* @param a_radioTelegram The radio-telegram to be moved
* @param a_newBroadcastIndex The new broadcast-index
* @param a_attachTelegram The telegram to be attached
*/
void moveTelegramInBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
const uint16_t a_newBroadcastIndex,
const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_attachTelegram = {});
/**
* Removes the telegram a_radioTelegram from the broadcast-map. If the
* a_radioTelegram has an attached telegram, the attached telegram will be
* detached and added to broadcast-map as broadcast-only telegram.
* If the telegram is an attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted when a_doDeleteTelegram is true.
* ATTENTION: iterators to m_BroadcastMap could be invalid after calling this
* function
*
* @param a_radioTelegram
* @param a_doDeleteTelegram
*/
void removeFromBroadcastMap(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
void removeFromBroadcastMapFunc(const std::function<bool(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &)> &pred);
void removeDusMineDeactivationFromBroadcastMap(int dusMineId);
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> createAccumulationTelegram(int curBcIndex,
int startBcIndex,
gef_telegramm_id_et telId,
const QMap<int, int> &bcIndex2Type,
int maxIdsPerTelegram,
int sizeOfSumField) const;
bool removeFromDeactivatedAesArea(int aesAreaId);
bool addToDeactivatedAesArea(int aesAreaId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedAesArea2bcIndex;
// QMap<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2AesArea;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>createAccuTeleDeactivatedAesAreas(int curBcIndex, int startBcIndex) const;
bool removeFromDeactivatedFuncArea(int aesAreaId);
bool addToDeactivatedFuncArea(int aesAreaId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedFuncArea2bcIndex;
// QHash<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2FuncArea;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>createAccuTeleDeactivatedFuncAreas(int curBcIndex, int startBcIndex) const;
bool removeFromDeactivatedDusMine(int dusMineId);
bool addToDeactivatedDusMine(int dusMineId, int bcIndex);
// QHash<mineId, broadcastIndexDeactivated>
QHash<int, int> m_deactivatedDusMine2bcIndex;
// QHash<broadcastIndexDeactivated, mineId>, keep sorted!
QMap<int, int> m_deactivatedBcIndex2DusMine;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> createAccuTeleDeactivatedDusMines(int curBcIndex, int startBcIndex) const;
bool removeFromActivatedDusMine(int dusMineId);
void addToActivatedDusMine(int dusMineId);
QSet<int> m_activatedDusMines;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> createAccuTeleActivatedDusMines(int curBcIndex);
/**
* Removes the kennung from the sammeltelegram.
* If the sammeltelegram is empty after remove of kennung, it will be taken out of
* broadcast-map (but not deleted) and a_sammelTelRemoved will be true. A attached
* braodcast-only-telegram will be deattached and inserted into broadcast-map.
* Returns true if kennung was successful removed, otherwise the kennung was not
* found within sammeltelegram
*
* @param a_sammelTelegram
* @param a_kennung
* @param a_anzahlPos
* @param a_anzahlSize
* @param a_sammelTelRemoved
*/
bool removeFromSammeltelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_sammelTelegram,
const uint16_t a_kennung,
const uint16_t a_anzahlPos,
const uint8_t a_anzahlSize,
bool &a_sammelTelRemoved);
/**
* used for telegrams that must only exists once in BC-list
*
* @param a_newRadioTelegram
*/
void replaceLastTelegramAndAddAtEnd(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_newRadioTelegram);
/**
* Small helper to dump all wf-ids from a sammeltelegramm
*/
std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegram *sammelTelegram);
/**
* Gets the braodcast-telegrams from Db, which were sent 1st time and adds them to
* the maps. Expired telegrams will be removed.
*
* @param a_doRestore
*/
void getAllFinishedBroadcastsFromDb(const bool a_doRestore = false);
/**
* Takes expired wirkfeld-telegrams out of maps.
*/
void removeExpiredTelegrams();
/**
* Removes the wirkfeld-telegrams with this kennung from the by time and by
* kennung maps.
* Replace this telegrams with Nop in BC-list.
* Finally the telegram will be deleted.
*
* @param a_kennung
*/
void removeWirkfeldTelegrams(const uint16_t a_kennung);
/**
* adds the wirkfeld-telegram to the by time and by kennung maps
*
* @param a_radioTelegram
* @param a_wirkfeldKennung
* @param a_telId
* @param a_minenKennung
*/
void addWirkfeldTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram,
const uint16_t a_wirkfeldKennung, const gef_telegramm_id_et a_telId = GEF_BESTAETIGUNG,
const uint16_t a_minenKennung = 0);
/**
* Deactivates the mine in the corresponding "WirkfeldstatusMinensperre"-telegram
* and moves the "WirkfeldstatusMinensperre"-telegram to the position of
* "DeactiviereEinzelmine"-telegram.
* Returns true if the "WirkfeldstatusMinensperre"-telegram was already sent 3
* times as normal broadcast.
*
* @param a_wirkfeldKennung
* @param a_minenKennung
* @param a_broadcastIndex
*/
bool deactivateEinzelmineFromMinensperre(const uint16_t a_wirkfeldKennung, const uint16_t a_minenKennung, const uint16_t a_broadcastIndex);
/**
* Returns a NOP-telegramm filled with the desired values.
*
* @param a_from
* @param a_to
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getNopTelegram(const uint16_t a_from, const uint16_t a_to);
/**
* Removes the telegram a_radioTelegram from all maps (broadcast-, wirkfeld-,
* funktionsraum- and lastTelegram-map).
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted when a_doDeleteTelegram is true.
* ATTENTION: iterators to all maps could be invalid after calling this function
*
* @param a_radioTelegram
* @param a_doDeleteTelegram
*/
void removeFromAllMaps(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Detaches an existing radio-telegram and adds it to the broadcast-map
*
* @param a_radioTelegram The telegram which could contain an attached telegram
*/
void detachTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Removes the telegram with a_funktionsraumKennung from funktionsraum-map and
* from the broadcast-map.
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted.
* ATTENTION: iterators to m_FunktionsraumTelegramMap could be invalid after
* calling this function
*
* @param a_funktionsraumKennung
*/
void removeFromFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung);
void removeFromTechnikFunktionsAndBroadcastMaps(const uint16_t a_funktionsraumKennung);
/**
* Removes the telegram where wirkfeldTelegramMapByKennungIterator points to from
* wirkfeld-maps and from the broadcast-map.
* If the telegram is a attached BC-only-telegram, it will be detached.
* The telegram itself will be deleted.
* ATTENTION: iterators to m_WirkfeldTelegramMapByKennung and
* m_WirkfeldTelegramMapByTime could be invalid after calling this function
*
* @param a_wirkfeldTelegramMapByKennungIterator
*/
void removeFromWirkfeldAndBroadcastMaps(const std::multimap<uint16_t, std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram>>::iterator &a_wirkfeldTelegramMapByKennungIterator);
/**
* Handles the REAKTIVIERUNG_DUS_MINE-telegram for normal-broadcasts and
* nachforderungen.
*
* @param a_radioTelegram The GEF_REAKTIVIERUNG_DUS_MINE-telegram
*/
void reactivateDusMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Handles the DEAKTIVIERUNG_EINZELMINE-telegram for normal-broadcasts and
* nachforderungen. This includes deactivation of mines from minen-sperre and DUS-
* mines.
*
* @param a_radioTelegram The GEF_REAKTIVIERUNG_DUS_MINE-telegram
*/
void deactivateSingleMine(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
/**
* Prepares values for start sending nachforderungen
*/
void prepareForSendNachforderungen();
/**
* returns the next nachforderung to send and prepares collecting window if no
* more nachforderungen are to be sent
*/
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> evaluateNextNachforderungToSend();
Q_SIGNALS:
void areaEffectSimulationActivated(int wirkfeldKennung);
void areaEffectSimulationDeactivated(int wirkfeldKennung);
private:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
NGL::INGLLogger &m_loggerBcRequest;
};
}