584 lines
17 KiB
C++
584 lines
17 KiB
C++
// **************************************************************************
|
|
//
|
|
// (C) Copyright 2009 Swiss SIMTEC AG
|
|
//
|
|
// **************************************************************************
|
|
//
|
|
// $HeadURL$
|
|
// $LastChangedBy$
|
|
// $LastChangedDate$
|
|
// $LastChangedRevision$
|
|
//
|
|
// Implementation of the Class PrtCnvRadioThread
|
|
// **************************************************************************
|
|
#pragma once
|
|
|
|
#include "PrtCnvSocketThread.hpp"
|
|
#include "PrtCnvBroadcastMgr.hpp"
|
|
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
|
#include <set>
|
|
#include <QList>
|
|
#include <QMutex>
|
|
#include <TrainingAreaBase/training_area_telegrams.h>
|
|
|
|
#define MAX_IDENTITY 65535
|
|
|
|
namespace PrtCnv
|
|
{
|
|
struct BiteError
|
|
{
|
|
int errorNumber = 0;
|
|
int canDeviceNumber = 0;
|
|
int subdeviceNumber = 0;
|
|
int uniqueId = 0;
|
|
};
|
|
|
|
class PrtCnvCentralThread;
|
|
class PrtCnvMember;
|
|
class PrtCnvRadioTrafficThread;
|
|
class PrtCnvStoredRadioTelegram;
|
|
/**
|
|
* This class handles the protocol to radio. This includes:
|
|
* - handle login and licensing of TNEs
|
|
* - send and receive normal telegrams
|
|
* - send normal broadcasts and nachforderungen
|
|
* - optimize bandwith usage
|
|
*
|
|
* @author
|
|
* @version 1.0
|
|
* @created 05-Jan-2006 13:34:41
|
|
*/
|
|
class PrtCnvRadioThread : public PrtCnv::PrtCnvSocketThread
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
PrtCnvRadioThread(int exerciseId, PrtCnvThreadStarter* a_parent);
|
|
/**
|
|
* Creates all subcomponents and connects signals to slots
|
|
*/
|
|
int32_t create(NGL::Settings *settings) override;
|
|
/**
|
|
* Deallocates subcomponents.
|
|
*/
|
|
int32_t destroy() override;
|
|
/**
|
|
* Initializes the variables.
|
|
*/
|
|
int32_t init() override;
|
|
/**
|
|
* Starts the thread and connects to TCP-server
|
|
*/
|
|
int32_t start() override;
|
|
|
|
/**
|
|
* Makes empty the message-queue faster, because the messages will be consumed
|
|
* without action.
|
|
*/
|
|
void prepareCleanUp();
|
|
|
|
/**
|
|
* Immediatelly send the environment telegramm to inform the players
|
|
* about the new state
|
|
*/
|
|
void sendEnvironmentTelegramTimerNow();
|
|
|
|
void exerciseEquipmentChanged(const TrainingAreaBase::TetraIcd::ExerciseEquipmentAssignmentComplete &data);
|
|
protected:
|
|
void onCheckMemberForValidLogin(int identity, int issi);
|
|
void sendLoginAccept(int identity, int issi, int exerciseId, bool bWithMastering);
|
|
bool isIdentityInCurrentExercise(int identity) const;
|
|
int exerciseIdForIdentity(int identity) const;
|
|
void removeMasteringMember(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_loginTelegram, PrtCnvMember *member,
|
|
PrtCnvMember *issiMember,
|
|
int masterIdentity,
|
|
int masterIssi);
|
|
|
|
protected:
|
|
/**
|
|
* Pointer to central-thread
|
|
*/
|
|
PrtCnvCentralThread *m_CentralThread;
|
|
|
|
/**
|
|
* Pointer to radio traffic counter thread
|
|
*/
|
|
PrtCnvRadioTrafficThread *m_radioTrafficThread;
|
|
|
|
public:
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* Signal to start sending a telegram to central
|
|
*/
|
|
void checkSendToCentral();
|
|
/**
|
|
* Signal to start sending a telegram to radio
|
|
*/
|
|
void checkSendToRadio();
|
|
/**
|
|
* Signal to indicate thread has finished the cleaning-phase
|
|
*/
|
|
void cleant();
|
|
/**
|
|
* Signal to indicate thread has stopped work
|
|
*/
|
|
void stopped();
|
|
|
|
/**
|
|
* a new equipment exercise mapping was received, check if member (all when identiy = -1)
|
|
* is still in this exercise
|
|
*/
|
|
void checkMemberForValidLogin(int identity, int issi);
|
|
|
|
|
|
// emitted when the tetra connection state changes
|
|
void tetraConnectionState(bool connected);
|
|
|
|
// an effect siumlation was (de)activated
|
|
void areaEffectSimulationActivated(int wirkfeldKennung);
|
|
void areaEffectSimulationDeactivated(int wirkfeldKennung);
|
|
|
|
// initialization of the thread is finished
|
|
void initDone();
|
|
|
|
// a player was (un)licensed
|
|
void playerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind);
|
|
void warehouseMessageFromPtrCnv(const QByteArray &jsonData);
|
|
protected:
|
|
/**
|
|
* Counts the sended telegrams
|
|
*/
|
|
uint32_t m_SendCounter;
|
|
/**
|
|
* The ISSI of the protocol-converter
|
|
*/
|
|
uint32_t m_HostISSI;
|
|
/**
|
|
* The lowest vaild value for the counter
|
|
*/
|
|
const uint32_t START_COUNTER;
|
|
/**
|
|
* One more than the highest vaild value for the counter
|
|
*/
|
|
const uint32_t END_COUNTER;
|
|
/**
|
|
* This timer will be used for periodically send the Umgebungsmeldung to TNEs
|
|
*/
|
|
QTimer *m_EnvironmentTelegramTimer;
|
|
/**
|
|
* The ISSI used for broadcast-telegrams
|
|
*/
|
|
uint32_t m_BroadcastISSI;
|
|
/**
|
|
* The directory and prefix for the login-log-file
|
|
*/
|
|
QString m_LoginPathWithPrefix;
|
|
/**
|
|
* Übungskennung (used for login-logfile name)
|
|
*/
|
|
int m_ExerciseId;
|
|
/**
|
|
* Bit-map for evaluating whether a playerid is valid
|
|
*/
|
|
std::set<uint16_t> m_AllowedIdentities;
|
|
/**
|
|
* true => TPU will be licensed whether selftest and configtest fails or not
|
|
*/
|
|
bool m_DoLicenseDespiteSelftestOrConfigFailure;
|
|
/**
|
|
* true => identify of TPU will be checked, whether allowed
|
|
*/
|
|
bool m_DoCheckIdentity;
|
|
PrtCnvBroadcastMgr m_BroadcastManager;
|
|
/**
|
|
* True => received telegrams will be dumped to common log-file
|
|
*/
|
|
bool m_DoDumpReceivedTelegrams;
|
|
/**
|
|
* True => sent telegrams will be dumped to common log-file
|
|
*/
|
|
bool m_DoDumpSentTelegrams;
|
|
/**
|
|
* True => radio-telegrams will be sent in SDS-TL-format
|
|
*/
|
|
bool m_DoUseSDSTL;
|
|
|
|
/**
|
|
* Identities that need an active position response after licensing
|
|
*/
|
|
std::set<uint16_t> m_DoNeedActPosResp;
|
|
|
|
/**
|
|
* The ISSI used for emergency call-telegrams
|
|
*/
|
|
uint32_t m_EmergencyCallISSI;
|
|
|
|
/**
|
|
* Sends a telegram to radio. It will be fragmented if needed. It will be checked,
|
|
* whether the receiver is logged in, licensed, the content is valid and the
|
|
* telegram is not expired and an error-message will be sent to central if needed.
|
|
* It will be tested, whether the maximal broadcast-counter is reached and if it
|
|
* is, the needed action will be done.
|
|
*
|
|
* @param a_telegram
|
|
* @param a_handle
|
|
* @param a_doCheckWhetherExpired
|
|
*/
|
|
void sendTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram,
|
|
PrtCnvStoredRadioTelegram *a_handle,
|
|
const bool a_doCheckWhetherExpired = true);
|
|
|
|
|
|
/**
|
|
* Sends the register-indication to TETRA
|
|
*/
|
|
void doRegister();
|
|
|
|
/**
|
|
* Send a register group message to TETRA
|
|
*/
|
|
void registerGroups();
|
|
|
|
/**
|
|
* Processes the register-response-telegram
|
|
*
|
|
* @param a_regsitrationStatus
|
|
*/
|
|
void handleRegisterRsp(const uint8_t a_regsitrationStatus);
|
|
|
|
public:
|
|
|
|
/**
|
|
* @author alois.wismer
|
|
* @version 1.0
|
|
* @updated 06-Apr-2010 16:01:59
|
|
*/
|
|
enum class E_TrafficLoad
|
|
{
|
|
Unknown = -1,
|
|
NormalLoad = 0,
|
|
HighLoad,
|
|
FullLoad
|
|
};
|
|
protected:
|
|
/**
|
|
* Holds the radio-telegram for sending Umgebungsmeldung periodically
|
|
*/
|
|
N_CoPrtCnv::CoPrtCnvRadioTelegram *m_EnvironmentTelegram;
|
|
|
|
/**
|
|
* load of traffic from Protocolconverter to TETRA
|
|
*/
|
|
E_TrafficLoad m_SendLoad;
|
|
|
|
uint32_t m_SendQueueFullLoad;
|
|
uint32_t m_SendQueueHighLoad;
|
|
uint32_t m_SendTelegramsNormalLoad;
|
|
uint32_t m_SendTelegramsHighLoad;
|
|
uint32_t m_SendTelegramsFullLoad;
|
|
/**
|
|
* The number of telegrams sent within the last second
|
|
*/
|
|
uint32_t m_SentTelegrams;
|
|
/**
|
|
* The number of bytes sent within last second
|
|
*/
|
|
uint32_t m_SentBytes;
|
|
/**
|
|
* how many times tick must be called until 1 second has elapsed
|
|
*/
|
|
uint32_t m_TickCounter;
|
|
/**
|
|
* how many times tick was called (used for knowing when 1 second has elapsed,
|
|
* which we use for sent-bytes and receive-bytes statistics)
|
|
*/
|
|
uint32_t m_TicksPerSecond;
|
|
/**
|
|
* How many values we use for computing average
|
|
*/
|
|
static const int AVERAGE_COUNT = 10;
|
|
/**
|
|
* The last few number of bytes sent, used for calculating the average
|
|
*/
|
|
uint32_t m_SentBytesAverage[AVERAGE_COUNT];
|
|
/**
|
|
* index for writing into aveage-array
|
|
*/
|
|
uint8_t m_AverageIndex;
|
|
/**
|
|
* The number of telegrams sent within the last second
|
|
*/
|
|
uint32_t m_ReceivedTelegrams;
|
|
/**
|
|
* The number of bytes sent within last second
|
|
*/
|
|
uint32_t m_ReceivedBytes;
|
|
/**
|
|
* The last few number of bytes sent, used for calculating the average
|
|
*/
|
|
uint32_t m_ReceivedBytesAverage[AVERAGE_COUNT];
|
|
|
|
/**
|
|
* The groups which should be listened to
|
|
*/
|
|
std::set<uint32_t> m_ListenGroups;
|
|
|
|
/**
|
|
* @brief use scrambling yes/no (Radio/UseScrambling)
|
|
*/
|
|
bool m_bUseScrambling;
|
|
/**
|
|
* The logger object for statistics
|
|
*/
|
|
NGL::INGLLogger &m_loggerStats;
|
|
|
|
// mapping which equipNos are in which exercise
|
|
std::unordered_map<int, std::unordered_set<int>> m_exerciseEquipmentAssignments;
|
|
std::unordered_map<int, TrainingAreaBase::TetraIcd::GroupIssiInformation> m_groupIssiInformation;
|
|
mutable QMutex m_exerciseEquipmentAssignmentMutex;
|
|
|
|
private:
|
|
/**
|
|
* generates an answer to TNE from protocoll-converter for some special radio-
|
|
* telegrams (i.e. NachforderungBroadcast, BITE-Meldung)
|
|
* returns true when the telegram must be sent to central
|
|
*
|
|
* @param a_centralTelegram
|
|
* @param a_radioTelegram
|
|
*/
|
|
bool sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram);
|
|
/**
|
|
* After calling this function, the caller must no longer use a_data, because this
|
|
* function 'consumes' a_data and will delete a_data, when no longer needed.
|
|
*
|
|
* @param a_data A pointer to the telegram-data, including frame-header.
|
|
* Control over a_data will be lost (see description of function itself)
|
|
*/
|
|
void handleReceivedTelegram(const QByteArray &data);
|
|
/**
|
|
* Processes the data-indication-telegram
|
|
*
|
|
* @param a_data
|
|
* @param bDoDeleteData is set to true when the caller can properly delete the data
|
|
*/
|
|
void handleDataIndReq(const QByteArray &data, bool bIsMaybeScrambled);
|
|
/**
|
|
* Processes the login-telegram
|
|
*
|
|
* @param a_loginTelegram
|
|
*/
|
|
void handleLoginTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_loginTelegram);
|
|
/**
|
|
* Processes a fragment of a telegram
|
|
*
|
|
* @param a_fragmentedTelegram
|
|
*/
|
|
void handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_fragmentedTelegram);
|
|
/**
|
|
* Sends a telegram "FehlermeldungGefechtsfeld" to central
|
|
*
|
|
* @param a_identity
|
|
* @param a_errorCause
|
|
* @param a_telegramId
|
|
*/
|
|
void sendFehlermeldungGefechtsfeldToCentral(const uint16_t a_identity,
|
|
const TrainingAreaBase::TetraIcd::CtaDataError::Reason a_errorCause,
|
|
const gef_telegramm_id_et a_telegramId = GEF_BESTAETIGUNG);
|
|
/**
|
|
* Returns the ISSI of TNE with a_TNE_Id
|
|
*
|
|
* @param a_TNE_Id
|
|
*/
|
|
uint32_t getDestinationISSI(const uint16_t a_TNE_Id) const;
|
|
/**
|
|
* Processes the BITE/BITE extended-telegram
|
|
*
|
|
* @param a_BITE_CentralTelegram
|
|
*/
|
|
bool handleBITEEXT_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_BITE_RadioTelegram);
|
|
bool handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_BITE_RadioTelegram,
|
|
TrainingAreaBase::TetraIcd::BiteReport::LoginType anmeldeart,
|
|
uint32_t ergebnisCAN,
|
|
uint32_t ergebnisAusstattung,
|
|
uint32_t aktuelleKonfiguration,
|
|
uint32_t konfigurationsvergleich,
|
|
const QList<PrtCnv::BiteError> &fehlerListe
|
|
);
|
|
|
|
/**
|
|
* Sends a login-telegram to radio
|
|
*
|
|
* @param a_loginTelegramStatus
|
|
* @param a_identity
|
|
* @param a_ISSI
|
|
*/
|
|
void sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegram::E_LoginStatus a_loginTelegramStatus, const uint16_t a_identity, const uint32_t a_ISSI);
|
|
void sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegram::E_LoginStatus a_loginTelegramStatus,
|
|
const uint16_t a_identity, const uint32_t a_ISSI, const TrainingAreaBase::TetraIcd::GroupIssiInformation &group);
|
|
|
|
/**
|
|
* Sends a telegram "LizenzierungTNE" to radio
|
|
*
|
|
* @param a_identity AusstattungsId
|
|
* @param a_issi
|
|
* @param a_licensingKind
|
|
* @param a_errorCause
|
|
*/
|
|
void sendLizenzierungTneToRadio(const uint16_t a_identity, const uint32_t a_issi,
|
|
const N_CoPrtCnv::E_LicensingKind a_licensingKind,
|
|
const N_CoPrtCnv::E_LicensingErrorCode a_errorCause);
|
|
|
|
/**
|
|
* Writes the login of a TNE to the login-logfile
|
|
*
|
|
* @param a_radioTelegram
|
|
* @param a_prosaText
|
|
*/
|
|
void writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram, const QString &a_prosaText);
|
|
void writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram, const QString &a_prosaText);
|
|
void writeLoginLog(uint32_t identity, uint32_t issi, const QString &a_prosaText);
|
|
/**
|
|
* Receives the file with allowed playerId, or the lowest and hightest allowed
|
|
* playerIds
|
|
*/
|
|
void initIdentityArray();
|
|
/**
|
|
* Reads one line of the playerId-file.
|
|
* Aborts when not successful
|
|
*
|
|
* @param a_idAsText
|
|
* @param a_line
|
|
* @param a_fileName
|
|
*/
|
|
uint16_t readIdentity(const QByteArray& a_idAsText, const uint32_t a_line, const QString& a_fileName);
|
|
/**
|
|
* Checks whether the playerId is allowd.
|
|
*
|
|
* @param a_identity
|
|
*/
|
|
bool isIdentityValid(uint16_t a_identity) const;
|
|
|
|
/**
|
|
* Allows this playerId.
|
|
*
|
|
* @param a_identity
|
|
*/
|
|
void setIdentityVaild(uint16_t a_identity);
|
|
|
|
/**
|
|
* Fragment a telegram and sends the fragments to radio.
|
|
*
|
|
* @param a_telegram
|
|
*/
|
|
void sendFragmentedTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram);
|
|
|
|
/**
|
|
* sends the telegram to radio-socket
|
|
* returns the broadcastIndex (0 if it was no broadcast)
|
|
*
|
|
* @param a_telegram
|
|
*/
|
|
uint16_t sendToSocket(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram);
|
|
|
|
/**
|
|
* Processes the report-indication-telegram
|
|
*
|
|
* @param a_data
|
|
*/
|
|
void handleReportIndReq(const QByteArray &data);
|
|
void prepareWareHouseMessage(qint32 equipNr,
|
|
bool doLicence,
|
|
qint64 ergebnisCAN,
|
|
qint64 ergebnisAusstattung,
|
|
qint64 aktuelleKonfiguration,
|
|
qint64 konfigurationsvergleich,
|
|
const QList<PrtCnv::BiteError> &fehlerListe);
|
|
|
|
protected Q_SLOTS:
|
|
/**
|
|
* @brief oslot to handle call to sendEnvironmentTelegramTimerNow in correct thread
|
|
*/
|
|
void onSendEnvironmentTelegramTimerNow();
|
|
/**
|
|
* see base-class
|
|
*/
|
|
void timeoutAliveAndConnection() override;
|
|
/**
|
|
* Processes the periodical stuff, like broadcasts and nachforderungen
|
|
*/
|
|
void timeoutTick() override;
|
|
/**
|
|
* Checks whether a normal telegram must be sent and sends it.
|
|
*/
|
|
void checkSend();
|
|
/**
|
|
* see base-class
|
|
*/
|
|
void readyRead() override;
|
|
/**
|
|
* see base-class
|
|
*/
|
|
void disconnected() override;
|
|
/**
|
|
* see base-class
|
|
*/
|
|
void connected() override;
|
|
/**
|
|
* Processes the periodical sending of Umgebungsmeldung
|
|
*/
|
|
void timeoutEnvironmentTelegram();
|
|
/**
|
|
* Clean the DB.
|
|
*/
|
|
void doClean();
|
|
/**
|
|
* Restart work after cleaning Db
|
|
*/
|
|
void doStart();
|
|
/**
|
|
* Stops work for cleaning DB
|
|
*/
|
|
void doStop();
|
|
|
|
|
|
// a broadcastTelegrams request was received from EXCON (e.g. through Wls)
|
|
void onBroadcastTelegramsRequestFromCentral(int equipmentNumber, int broadcastIndex, int resetCounter);
|
|
|
|
private:
|
|
/**
|
|
* Processes the status-telegram
|
|
*
|
|
* @param data
|
|
*/
|
|
void handleStatusIndReq(const QByteArray &data);
|
|
|
|
/**
|
|
* Processes the air-interface-report-telegram
|
|
*
|
|
* @param a_data
|
|
*/
|
|
void handleAirInterfaceLoadReq(const QByteArray &data);
|
|
|
|
/**
|
|
* Computes and logs the sent- and receive-statistics
|
|
*/
|
|
void computeAndLogTrafficStatistics();
|
|
|
|
/**
|
|
* returns true, if at the moment no more telegrams should be sent
|
|
*/
|
|
bool isSendLimitReached() const;
|
|
|
|
|
|
void sendScrambledContent(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram) const;
|
|
bool unscrambleContent(N_CoPrtCnv::CoPrtCnvRadioTelegram &a_telegram) const;
|
|
|
|
|
|
friend class PrtCnvCentralThread;
|
|
};
|
|
|
|
std::ostream &operator<<(std::ostream &os, const PrtCnvRadioThread::E_TrafficLoad tl);
|
|
}
|