// ************************************************************************** // // (C) Copyright 2009 Swiss SIMTEC AG // // ************************************************************************** // // $HeadURL$ // $LastChangedBy$ // $LastChangedDate$ // $LastChangedRevision$ // // ************************************************************************** #pragma once #include "logger.h" #include #include #include #include #include #include #include #include #include #include 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 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 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 &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 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> m_BroadcastMap; std::vector> m_broadcastTelegamsToSend; /** * Contains all telegrams which must only be stored once for nachforderungen */ std::map> m_LastTelegramMap; /** * Contains all wirkfeld-telegrams which must be stored for nachforderungen * ordered by wirkfeldkennung. */ std::multimap> m_WirkfeldTelegramMapByKennung; /** * Contains all wirkfeld-telegrams which must be stored for nachforderungen * ordered by expiration-time. */ std::multimap> m_WirkfeldTelegramMapByTime; /** * Contains all funktionsraum-telegrams which must be stored for nachforderungen * ordered by funktionsraumkennung. */ std::map> m_FunktionsraumTelegramMap; /** * Contains all technik-funktionsraum-telegrams which must be stored for nachforderungen * ordered by funktionsraumkennung. */ std::map> 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 &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 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 &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 &a_radioTelegram, const uint16_t a_newBroadcastIndex, const std::shared_ptr &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 &a_radioTelegram); void removeFromBroadcastMapFunc(const std::function &)> &pred); void removeDusMineDeactivationFromBroadcastMap(int dusMineId); std::shared_ptr createAccumulationTelegram(int curBcIndex, int startBcIndex, gef_telegramm_id_et telId, const QMap &bcIndex2Type, int maxIdsPerTelegram, int sizeOfSumField) const; bool removeFromDeactivatedAesArea(int aesAreaId); bool addToDeactivatedAesArea(int aesAreaId, int bcIndex); // QHash QHash m_deactivatedAesArea2bcIndex; // QMap, keep sorted! QMap m_deactivatedBcIndex2AesArea; std::shared_ptrcreateAccuTeleDeactivatedAesAreas(int curBcIndex, int startBcIndex) const; bool removeFromDeactivatedFuncArea(int aesAreaId); bool addToDeactivatedFuncArea(int aesAreaId, int bcIndex); // QHash QHash m_deactivatedFuncArea2bcIndex; // QHash, keep sorted! QMap m_deactivatedBcIndex2FuncArea; std::shared_ptrcreateAccuTeleDeactivatedFuncAreas(int curBcIndex, int startBcIndex) const; bool removeFromDeactivatedDusMine(int dusMineId); bool addToDeactivatedDusMine(int dusMineId, int bcIndex); // QHash QHash m_deactivatedDusMine2bcIndex; // QHash, keep sorted! QMap m_deactivatedBcIndex2DusMine; std::shared_ptr createAccuTeleDeactivatedDusMines(int curBcIndex, int startBcIndex) const; bool removeFromActivatedDusMine(int dusMineId); void addToActivatedDusMine(int dusMineId); QSet m_activatedDusMines; std::shared_ptr 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 &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 &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 &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 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 &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 &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>::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 &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 &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 evaluateNextNachforderungToSend(); Q_SIGNALS: void areaEffectSimulationActivated(int wirkfeldKennung); void areaEffectSimulationDeactivated(int wirkfeldKennung); private: /** * The logger object */ NGL::INGLLogger &m_logger; NGL::INGLLogger &m_loggerBcRequest; }; }