diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.cpp index dffa78207..7b89d8c7c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.cpp @@ -1,5 +1,10 @@ - - +/** + * Thin wrapper around json telegram data + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-22 + */ #include "CoPrtCnvCentralTelegram.hpp" #include @@ -79,4 +84,4 @@ void CoPrtCnvCentralTelegram::ensureByteArray() } -} +} // namespace N_CoPrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.hpp index 2973a476b..55e1362e7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvCentralTelegram.hpp @@ -1,5 +1,10 @@ - - +/** + * Thin wrapper around json telegram data + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-22 + */ #pragma once @@ -10,8 +15,11 @@ namespace N_CoPrtCnv { - - + /** + * The central-telegram, an subclass of XDR_Wrapper_it used for creation of + * telegrams with telegramId. It also contains the deletion of dynamic allocated + * space within central-telegrams. + */ class COPRTCNV_EXPORT CoPrtCnvCentralTelegram final { public: @@ -42,8 +50,8 @@ namespace N_CoPrtCnv void setData(const QByteArray &data); QByteArray data(); - QJsonObject json(); - QJsonObject jsonData(); + QJsonObject json(); // complete json + QJsonObject jsonData(); // json()["data"] TrainingAreaBase::TetraIcd::TelegramId telegramId(); void setCounter(qint32 counter); qint32 counter(); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.cpp index dc57421df..6e3e39720 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// @RDE_HEADER@ +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Helper to dump the data in hex +// ************************************************************************** #include "CoPrtCnvHexDumpHelper.hpp" #include "CoPrtCnvRadioTelegram.hpp" @@ -24,9 +24,9 @@ static std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegr const int SIZE_POS = sammelTelegram->getTelID() == GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN ? 2 : 1; std::stringstream sstream; - unsigned int cnt = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS, SIZE_POS); + unsigned int cnt = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS, SIZE_POS); // anzahl for (unsigned int i = 0; i < cnt; ++i) { - uint16_t telId = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS + SIZE_POS + 2 * i, 2); + uint16_t telId = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS + SIZE_POS + 2 * i, 2); // add kennung sstream << telId << " "; } return sstream.str(); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.hpp index b6c5e5d24..817895dc8 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvHexDumpHelper.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// @RDE_HEADER@ +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Helper to dump the data in hex +// ************************************************************************** #pragma once #include diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvInjectionHeader.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvInjectionHeader.hpp index 885ca9d99..97a28c953 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvInjectionHeader.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvInjectionHeader.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,26 +17,38 @@ namespace N_CoPrtCnv { - - + /** + * The header used for injection-data + * + * @author alois.wismer + * @version 1.0 + * @created 06-Aug-2010 10:27:55 + */ struct CoPrtCnvInjectionHeader { - - + /** + * The m_Id1 and m_Id2 are used to detect rubish data. + */ uint32_t m_Id1; - - + /** + * The m_Id1 and m_Id2 are used to detect rubish data. + */ uint32_t m_Id2; - - + /** + * 0 => unknown + * 1 => central-telegram + * 2 => radio-telegram + * all others: unknown + */ enum Destination { eUnknown = 0, eCentral = 1, eRadio = 2 } m_Kind; - - + /** + * The size of following data + */ uint16_t m_Size; CoPrtCnvInjectionHeader() diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvLogHeader.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvLogHeader.hpp index 6da5e4811..5afc9fb29 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvLogHeader.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvLogHeader.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,12 +17,18 @@ namespace N_CoPrtCnv { - - + /** + * @author alois.wismer + * @version 1.0 + * @created 12-Mrz-2010 16:07:19 + */ struct CoPrtCnvLogHeader { - - + /** + * @author alois.wismer + * @version 1.0 + * @created 12-Mrz-2010 16:04:42 + */ enum E_CoPrtCnvProtocol { e_DestProtocolCentral = 0, @@ -34,19 +40,24 @@ namespace N_CoPrtCnv e_DestReceive = 0x40000000, e_DestSend = 0xC0000000 }; - - + /** + * length of data, including length of this header + */ short m_Length = 0; short m_Version = 0; int m_Priority = 0; - - + /** + * We do not use E_CoPrtCnvProtocol here, because we want a size of 4 bytes + */ int m_Protocol = 0; - - + /** + * needed for correct alignment when compiling on 64-bit systems + */ int m_Reserved = 0; - - + /** + * Upper 4 bytes => seconds + * Lower 4 byte => microseconds + */ uint64_t m_Time = 0; }; } diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvRadioTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvRadioTelegram.hpp index e73953c6e..5d0a55b7f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvRadioTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvRadioTelegram.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -28,23 +28,28 @@ class INGLLogger; namespace N_CoPrtCnv { - - +/** + * used for telegram "LizenzierungTNE" to Radio + */ enum class E_LicensingKind { - - + /** + * Anmeldung erfolgreich + */ Success = 0, - - + /** + * Anmeldung abgelehnt + */ Rejected = 1, - - + /** + * Abmeldung + */ Unlicense = 2 }; - - +/** + * used for telegram "LizenzierungTNE" to Radio + */ enum class E_LicensingErrorCode { Ok = 0, @@ -55,14 +60,25 @@ enum class E_LicensingErrorCode IdentityDenied = 5 }; - - +/** + * The radio-telegram, holds the data of telegram and additiional data for filling + * and sending as braodcast. + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:37:23 + */ class COPRTCNV_EXPORT CoPrtCnvRadioTelegram { public: - - + /** + * The radio-telegram flags + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ enum E_Flags { e_FlagsNone = 0x00, @@ -72,21 +88,32 @@ public: e_ConsumedConfirmationRequested = 0x80 }; - - + /** + * The transmission-protocoll to be used for radio-telegram + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ enum E_ProtocolIdentifier { e_SimpleTextMessagingWithoutSDS_TL = 0x02, e_SimpleGPS_WithoutSDS_TL = 0x03, - e_TDSMessageWithoutSDS_TL = 0x50, + e_TDSMessageWithoutSDS_TL = 0x50, // 80dec e_UsingSDS_TL = 0x80, e_SimpleTextMessagingUsingSDS_TL = 0x82, e_SimpleGPS_UsingSDS_TL = 0x83, e_LoginTest = 0x1D }; - - + /** + * The telegram-type: + * Fragmented, normal or login-telegram. + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ enum E_FragmentStatus { e_NotFragmented = 0x00, @@ -101,24 +128,37 @@ public: e_DgpsTelegram = 0x03 }; - - + /** + * The header of a radio-telegram + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ struct PrtCnvRadioGwHeader { - - + /** + * The first byte must be the magic number A5 + */ uint8_t m_MagicNumber; - - + /** + * The telegram-counter + */ uint8_t m_Counter; - - + /** + * length of the following message in bytes + */ uint16_t m_Length; }; - - + /** + * The PDU-type of radio-telegram + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ enum E_PDU_Type { e_RegisterInd = 0, @@ -131,8 +171,11 @@ public: e_AirLoadHyterra = 19 }; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 17-Mrz-2010 13:06:40 + */ enum E_RegistrationStatus { e_IssiSuccessfulRegistered = 0, @@ -141,8 +184,13 @@ public: e_InvalidIpAddress = 3 }; - - + /** + * The delivery-status (only for SDS-TL) + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:39:54 + */ enum E_DeliveryStatusForTL_Report { e_SDS_ReceiptAcknowledgedByDestination = 0x00, @@ -160,8 +208,13 @@ public: e_DestinationNotReachable = 0x5A }; - - + /** + * The status of the login-telegram + * + * @author wia + * @version 1.0 + * @created 12-Mrz-2010 16:41:22 + */ enum E_LoginStatus { e_LoginRequest = 0x40, @@ -170,389 +223,592 @@ public: e_LoginStatusMask = 0xC0, e_LoginMastering = 0x20, - - e_LoginNoExerciseAssignment = 0x00, - e_LoginOtherEqId = 0x02, - e_LoginOtherISSI = 0x04, - e_LoginOtherExercise = 0x06, + // Bits 2 & 3 + e_LoginNoExerciseAssignment = 0x00, // none set + e_LoginOtherEqId = 0x02, // bit2 set + e_LoginOtherISSI = 0x04, // bit3 set + e_LoginOtherExercise = 0x06, // bit2+3 set }; - - + /** + * The first byte of the radio-telegram. Must be A5 + */ static constexpr uint8_t MAGIC_NUMBER = 0xA5; - - + /** + * length of a data-ind/req-telegram-header with TL and without the 4-byte frame- + * header. + * It contains PDUtype, SourceISSI, DestinationISSI, ProtocolIdentifier, + * LengthInBits and LengthInBytes. Payload-status is not included. + */ static constexpr uint16_t DATA_IND_REQ_WITH_TL_HEADER_LENGTH = 22; - - + /** + * frameheader (4) + tetra-header (22) + payloadheader (1) + */ static constexpr uint16_t DATA_IND_REQ_HEADER_LENGTH = 27; - - + /** + * frameheader (4) + tetra-header (22) + */ static constexpr uint16_t DATA_IND_REQ_HEADER_LENGTH_WITHOUT_PAYLOAD_HEADER = DATA_IND_REQ_HEADER_LENGTH -1; - - + /** + * length of a data-ind/req-telegram-header without TL and without the 4-byte + * frame-header. + * It contains PDUtype, SourceISSI, DestinationISSI, ProtocolIdentifier, + * LengthInBits and LengthInBytes. + */ static constexpr uint16_t DATA_IND_REQ_NO_TL_HEADER_LENGTH = 14; - - - static constexpr uint16_t MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH = 249; - - + /** + * the maximum length of payload-data (including payload-status-byte) of a radio- + * telegram. If payload-data is larger, fragmentation must be made. + */ + static constexpr uint16_t MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH = 249; // 256: 1 Byte Protokoll-ID + 255 Byte Daten + /** + * frameheader (4) + tetra-header (22) + payloadheader (1) + */ static constexpr uint16_t PAYLOAD_STATUS_LENGTH = 1; - - + /** + * The protocol allows a max of 16 fragments, but due to definitions in file + * zsksxdit.x it could be less. + */ static constexpr uint8_t MAX_NBR_OF_FRAGMENTS = 16; - - + /** + * constructor for a Register-Ind telegram + * + * @param a_sourceISSI + */ explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI); - - + /** + * constructor for a Group-Monitoring-Ind telegram + * + * @param a_sourceISSI + */ explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI, const std::set &groups); - - + /** + * constructor for a Report-Ind telegram + * + * @param a_sourceISSI + * @param a_delivery + */ explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI, const E_DeliveryStatusForTL_Report a_delivery); - - + /** + * Constructor for received telegrams (Data-Ind/Req, PDU type = 2) + * + * @param a_data + */ explicit CoPrtCnvRadioTelegram(const QByteArray &a_data); - - + /** + * the telegraminformation will be set + * + * @param a_telegramId + * @param a_payloadSize inclusive 3 byte telegraminformation + * @param a_identity + */ explicit CoPrtCnvRadioTelegram(const gef_telegramm_id_et a_telegramId, const uint16_t a_payloadSize, const uint16_t a_identity); - - + /** + * for login-telegram + * + * @param a_loginTelegramStatus + * @param a_identity + * @param a_issi + */ explicit CoPrtCnvRadioTelegram(const E_LoginStatus a_loginTelegramStatus, const uint16_t a_identity, uint32_t a_issi); - + // set this issis for a login repsone e_LoginReject | e_LoginOtherExercise void setLoginIssis(int hostIssi, int groupIssi1, int groupIssi2); - - + /** + * for generating fragmented telegrams. + * a_error will be true, if the fragmented telegrams cannot be generated. + * + * @param a_bigTelegram + * @param a_fragmentIndex + * @param a_error + */ explicit CoPrtCnvRadioTelegram(const std::shared_ptr &a_bigTelegram, const uint8_t a_fragmentIndex, bool &a_error); virtual ~CoPrtCnvRadioTelegram(); - - + /** + * ETS Hack due to +/-1 telegram id on tetra ... + */ void fixupTelegramIdForEts(bool convertToEtsId); static void setEtsMode(bool bIsEtsMode); - - + /** + * Sets the paylaod-data. + * + * @param a_value + * @param a_size + */ void setPayload1Byte(uint8_t a_value); void setPayload2Byte(uint16_t a_value); void setPayload3Byte(uint32_t a_value); void setPayload4Byte(uint32_t a_value); void setPayloadData(uint32_t a_value, const uint8_t a_size); - - + /** + * Sets the paylaod-data. + * + * @param a_value + */ void setPayloadData(const uint8_t a_value) { return setPayload1Byte(a_value); } - - + /** + * Sets the paylaod-data. + * + * @param a_data + * @param a_size + */ void setPayloadData(const uint8_t *a_data, const uint16_t a_size); - - + /** + * Returns a pointer to data of radio-telegram. + */ const char *getData() const { return m_data.data(); } char *getData() { return m_data.data(); } QByteArray data() const { return m_data; } - - + /** + * the overall size of telegram, including all headers + */ int getSize() const { return m_data.size(); } - - + /** + * Returns the telegramId of radio-telegram. + */ gef_telegramm_id_et getTelID() const; - - + /** + * Returns the counter. + */ uint8_t zaehler() const; - - + /** + * Sets the counter. + * + * @param a_counter + */ void setZaehler(const uint8_t a_counter); - - + /** + * Returns a paylaod-value. Its size depends on a_size. + * + * @param a_offset + * @param a_size + */ uint32_t getPayloadDataUInt32(size_t a_offset, uint16_t a_size) const; - - + /** + * Returns a 1-byte paylaod-value. + * + * @param a_offset + */ uint8_t getPayloadDataUInt8(size_t a_offset) const; - - + /** + * Returns the destISSI of radio-telegram. + */ uint32_t getDestISSI() const; - - + /** + * Returns the identiy of radio-telegram. + */ uint16_t getIdentity() const; - - + /** + * Sets the srcISSI. + * + * @param a_ISSI + */ void setSrcISSI(const uint32_t a_ISSI); - - + /** + * Returns true if it is broadcast-telegram, which has not yet set a broadcast- + * index. + */ bool mustBroadcastBeSet() const; - - + /** + * Sets the broadcast-index. + * + * @param a_broadcastIndex + */ void setBroadcastIndex(const uint16_t a_broadcastIndex); - - + /** + * Set the dstISSI. + * + * @param a_ISSI + */ void setDestISSI(const uint32_t a_ISSI); - - + /** + * Returns the PDU-type of radio-telegram. + */ CoPrtCnvRadioTelegram::E_PDU_Type getPDU_Type() const; - - + /** + * Returns the fragment-status of radio-telegram. + */ CoPrtCnvRadioTelegram::E_FragmentStatus getFragmentStatus() const; - - + /** + * Returns the fragment-counter of radio-telegram. + */ uint8_t getFragmentCounter() const; - - + /** + * If CRC-bit is set, it checks the CRC and removes CRC-stuff from telegram. + * If CRC-bit is not set, simply true will be returned + */ bool isCrcOk() const; - - + /** + * Returns the srcISSI of radio-telegram. + */ uint32_t getSrcISSI() const; - - + /** + * returns true if the it is a special login telegram + */ bool isLoginTelegram() const; - - + /** + * returns true if the it is a special login telegram + */ bool mustBeFragmented() const; - - + /** + * Returns a pointer to payload-data on a certain position of radio-telegram. + * + * @param a_offset + */ const uint8_t *getPayloadDataPtr(uint16_t a_offset) const; uint8_t *getPayloadDataPtr(uint16_t a_offset); - - + /** + * the size of payload-data without payload-status-header + */ virtual uint16_t getPayloadSize() const; - - + /** + * Converts the list of fragmented telegrams into 1 big radio-telegram. + * The function allocates a block of data. The caller is responsible to delete + * this block of data, when no longer used. + * If conversion fails NULL will be returned + * + * @param a_fragTelegramList + */ static QByteArray getUnfragmentedData(const std::multimap &a_fragTelegramList); - - + /** + * length without frame-header (4 byte) + * + * @param a_lengthWithoutFrame + */ static bool isTelegramLengthOk(const uint16_t a_lengthWithoutFrame); - - + /** + * returns true if the it is a normal, unfragmented telegram (but not a login- + * telegram) + */ bool isNormalTelegram() const; - - + /** + * Returns the priority of radio-telegram. + */ uint8_t getPriority() const; - - + /** + * Returns the broadcast-index of radio-telegram. + */ uint16_t getBroadcastIndex() const; - - + /** + * Sets the paylaod-data based on a_index with size a_size. + * + * @param a_index the payload-based position where the byte should be written + * @param a_value + * @param a_size + */ void setPayloadDataWithIndex(const uint16_t a_index, const uint32_t a_value, const uint16_t a_size); - - + /** + * Sets the complete paylaod-data. + * + * @param a_data + * @param a_length + */ void setPayloadDataComplete(const QByteArray &payload); - - + /** + * ATTENTION with use of this function, because it is a (little) dirty trick to + * resize the sammel-telegrams without memory-allocation. + * It is the responsibity of the user to not overwrite memory!!! + * + * @param a_newPayloadSize + */ void resetPayloadSize(const uint16_t a_newPayloadSize); - - + /** + * Set the identity. + * + * @param a_identity + */ void setIdentity(const uint16_t a_identity); - - + /** + * Sets the protocol-identifier. + * + * @param a_ProtocolIdentifier + */ void setProtocolIdentifier(const E_ProtocolIdentifier a_ProtocolIdentifier); - - + /** + * Sets the message-reference. + * + * @param a_MessageReference + */ void setMessageReference(const uint8_t a_MessageReference); - - + /** + * returns true if the it is a SDS/TL telegram + */ bool isSDSTL() const; - - + /** + * Returns the registration-status of TETRA-header of SdsGw-Register-Rsp telegram + */ CoPrtCnvRadioTelegram::E_RegistrationStatus getRegistrationStatus() const; - - + /** + * Returns the registration-status of TETRA-header of SdsGw-Register-Rsp telegram + * in text-form + */ std::string getRegistrationStatusAsText() const; - - + /** + * Returns the protocolIdentifier of radio-telegram. + */ CoPrtCnvRadioTelegram::E_ProtocolIdentifier getProtocolIdentifier() const; - - + /** + * Returns the protocolIdentifier of radio-telegram in text-form + */ std::string getProtocolIdentifierAsText() const; - - + /** + * Returns the message-reference of radio-telegram. + */ uint8_t getMessageReference() const; - - + /** + * Returns the area selection of TETRA-Header + */ uint8_t getAreaSelection() const; - - + /** + * Returns the validity period of radio-telegram. + */ uint8_t getValidityPeriod() const; - - + /** + * Returns the forward-address of TETRA-Header + */ uint32_t getForwardAddress() const; - - + /** + * Returns the flags of TETRA-Header + */ CoPrtCnvRadioTelegram::E_Flags getFlags() const; - - + /** + * Returns the flags of TETRA-Header as text + */ std::string getFlagsAsText() const; - - + /** + * Returns the length in bits-field of TETRA-Header + */ uint16_t getLengthInBits() const; - - + /** + * Returns the length in bytes-field of TETRA-Header + */ uint16_t getLengthInBytes() const; - - + /** + * Returns true when the Telegram has a crc checksum. + */ bool getWithCrc() const; - - + /** + * Returns the delivery-field of TETRA-Header of SdsGw-Report-Ind/Req telegrams. + */ CoPrtCnvRadioTelegram::E_DeliveryStatusForTL_Report getDelivery() const; - - + /** + * Returns the delivery-field of TETRA-Header of SdsGw-Report-Ind/Req telegrams as + * text. + */ std::string getDeliveryAsText() const; - - + /** + * Converts a signed 3-byte value into a signed 4-byte-value. I.e. used for + * positions (north and east). + * + * @param a_offset + */ int32_t getPayloadDataSInt24(uint16_t a_offset) const; - - + /** + * Returns true if the telegram needs licensing. + */ bool needsLicensing() const; - - + /** + * returns true when the telegram has an expiry-date and is expired. + * Returns false if the telegram has no expiry-date + */ bool hasExpired() const; - - + /** + * Returns the expire-time of the telegram. + * Returns 0 if the telegram has not expire-time. + */ uint32_t getExpireTime() const; - - + /** + * checks whether the content of telegram is valid, but only a few data will be + * checked, i.e. the kennung of wirkfeld and funktionsraum. + * Returns true if content of telegram is vaild (or will not be checked) + */ bool isContentValid(); - - + /** + * returns true if it is time to send this telegram as normal broadcast. + * + * @param a_currentTime + * @param a_wasLastBroadcast + * @param a_updateBroadcastCounter + */ bool mustBeSentAsBroadcast(time_t a_currentTime, bool &a_wasLastBroadcast, const bool a_updateBroadcastCounter = true); - - + /** + * Set the delay-times for 2nd and 3rd broadcast. + * + * @param a_2ndDelay + * @param a_3rdDelay + */ static void setBroadcastDelayTimes(int a_2ndDelay, int a_3rdDelay); - - + /** + * Set the max count of how often a Broadcasttelegram will be send (0 is ignored, the telegram is send at least one time. + * + * @brief setMaxBroadcastSendCnt + * @param a_maxSendCnt + */ static void setMaxBroadcastSendCnt(int a_maxSendCnt); - - + /** + * returns true if it is a broadcast-telegram and it is moved to broadcast-list + */ bool isMovedToBroadcastList() const; - - + /** + * Sets the broadcast-only-flag. + * + * @param a_doSet + */ void setBroadcastOnly(const bool a_doSet = true); - - + /** + * Returns the broadcast-only-flag. + */ bool isBroadcastOnly() const; - - + /** + * Defines the telegram which will be sent as normal broadcast instead a + * Sammeltelegram. + * + * @param a_radioTelegram + */ void setBroadcastonlyTelegram(const std::shared_ptr &a_radioTelegram); - - + /** + * Returns the telegram which will be sent as normal broadcast instead a + * Sammeltelegram. + */ std::shared_ptr getBroadcastonlyTelegram() const; - - + /** + * nbr of times already sent this normal broadcast (only used for broadcast- + * telegrams) + */ uint16_t getBroadcastCounter() const; - - + //begin_public_{ACFD8558-E5A4-4877-B503-41FCB730B678} + //end_public_{ACFD8558-E5A4-4877-B503-41FCB730B678} protected: - - + /** + * The telegram-data, including header + */ QByteArray m_data; - - + /** + * The internal index for filling telegram with setPayloadData() + */ uint16_t m_PayloadIndex; - - + /** + * nbr of times already sent this normal broadcast (only used for broadcast- + * telegrams) + */ uint16_t m_BroadcastCounter; - - + /** + * time when sending next normal broadcast (only used for broadcast-telegrams) + */ time_t m_NextSendTime; - - + /** + * The delay between 1st and 2nd normal broadcast + */ static int s_2ndDelay; - - + /** + * The delay between 2nd and 3rd normal broadcast + */ static int s_3rdDelay; - - + /** + * The delay between 2nd and 3rd normal broadcast + */ static int s_maxBroadcastSendCnt; - - + /** + * True if the telegram is used only as normal broadcast, not as nachforderung + */ bool m_IsBroadcastOnly; - - + /** + * Contains the normal broadcast-telegram, which will be sent instead of + * sammeltelegram for Nachfoderung + */ std::shared_ptr m_BroadcastOnlyTelegram; - - + /** + * For ETS - there al telgram ids are +1, therefore we have to remove 1 to be able + * to work with our ids. + */ static bool s_etsMode; - - + /** + * checks the payload-length of telegram. Returns true if the length is ok. + * Logs an error if length not ok. + */ bool isPayloadLengthOk(uint16_t a_minLength, const uint16_t a_dataAmountOffset, const uint8_t a_variableDataElementSize) const; @@ -561,16 +817,19 @@ protected: bool isPayloadLengthOk(uint16_t a_length) const; bool isPayloadLengthOk(const std::vector &a_lengths) const; - - + /** + * Set a 1-byte value at offset a_offset. + */ static void set1Byte(QByteArray &a_data, uint16_t a_offset, uint8_t a_value); - - + /** + * Set a 2-byte value at offset a_offset. + */ static void set2Byte(QByteArray &a_data, uint16_t a_offset, uint16_t a_value); - - + /** + * Set a 4-byte value at offset a_offset. + */ static void set4Byte(QByteArray &a_data, uint16_t a_offset, uint32_t a_value); @@ -578,20 +837,38 @@ protected: uint16_t getUInt16(const uint16_t a_offset) const; uint32_t getUInt32(const uint16_t a_offset) const; - - + /** + * Sets the header with magic-number and size. The length will be 0. + * + * @param a_data + * @param a_size The overall-size including all headers + */ static void setHeader(QByteArray &data, E_PDU_Type pduType); - - + /** + * Fills the header with SrcISSI, DstISSI, length in bits and length in bytes. PDU + * will be set for DataIndicationRequest. + * ProtocolIdentifier, message reference, area selection, forward address, flags + * will be filled with default-values. + * + * @param a_data + */ static void fillDataIndReqHeader(QByteArray &a_data); - - + /** + * Internal function to set the srcISSI. + * + * @param a_data + * @param a_ISSI + */ static void setSrcISSI_Internal(QByteArray &data, const uint32_t issi); - - + /** + * Internal function to set the dstISSI. + * + * @param a_data + * @param a_ISSI + */ static void setDestISSI_Internal(QByteArray &data, const uint32_t issi); private: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvTelegramConverter.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvTelegramConverter.hpp index 5ba075e1e..b6d41780c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvTelegramConverter.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/CoPrtCnvTelegramConverter.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -28,27 +28,42 @@ class CoPrtCnvRadioTelegram; class CoPrtCnvCentralTelegram; - - +/** + * This class is responsible to convert radio-telegrams into central-telegrams and + * vice versa. + * @author alois.wismer + * @version 1.0 + * @created 19-Mrz-2010 13:32:40 + */ namespace CoPrtCnvTelegramConverter { - - +/** + * Converts central-telegrams to radio-telegrams. + * Returns NULL if conversion was failed. + * + * @param a_telegram + */ COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(CoPrtCnvCentralTelegram *a_telegram); COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *a_telegram); - - +/** + * converts a radiotelegram into a central. + * returns nullptr if conversion failed + * + * @param a_radioTelegram + */ COPRTCNV_EXPORT CoPrtCnvCentralTelegram *convertToCentral(const CoPrtCnvRadioTelegram *a_radioTelegram); COPRTCNV_EXPORT TrainingAreaBase::TetraIcd::TrainingAreaTelegram *convertToTabTele(const CoPrtCnvRadioTelegram *a_radioTelegram); - - +/** + * Set the text codec to use for string send to/received from tetra + */ COPRTCNV_EXPORT void setTetraTextCodec(const char *codecName); - - +/** + * Set to trueif single fire (WIRKFELD_EINZELGESCHOSS) has two bytes for diameter, otherwise only one byte is used + */ COPRTCNV_EXPORT void setUse2BytesForSingleFireDiameter(bool bUse); COPRTCNV_EXPORT void setUsePvSan(bool bUse); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/tetra_telegram_ids.h b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/tetra_telegram_ids.h index f2a03acf8..a0080340f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/tetra_telegram_ids.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/CoPrtCnv/tetra_telegram_ids.h @@ -1,5 +1,10 @@ - - +/** + * Telegram IDs used in ICD52 + * $Id$ + * $HeadURL$ + * $Author$ + * Created by hjl, SLSE, 2016-11-14 + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/Console/main.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/Console/main.cpp index a04437a52..3ac38ac9f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/Console/main.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/Console/main.cpp @@ -39,7 +39,7 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); - + // Check alle 30 Sekunden NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false); NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()); @@ -79,21 +79,21 @@ int main(int argc, char **argv) s_eqIds += eqId; } - + //fprintf(stdout, "Counter;EqID;TelID;TelTime;LogTime;Diff\n"); while (true) { - + // read the header of telegram-entry N_CoPrtCnv::CoPrtCnvLogHeader lh; if (sizeof(lh) == telegramFile.read((char *)&lh, sizeof(lh))) { if (lh.m_Version == 3) { - + // read the telegram itself qint64 telegramLength = lh.m_Length - sizeof(lh); QByteArray telegramData(telegramLength, Qt::Uninitialized); if (telegramLength == telegramFile.read(telegramData.data(), telegramLength)) { - + // add the telegram to telegram-list N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol) (lh.m_Protocol & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.cpp index a31e417e0..bd4d14a0f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.cpp @@ -1,17 +1,17 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - +// manual class headers #include "IntegerCalculator.hpp" #include @@ -27,35 +27,35 @@ IntegerCalculator::IntegerCalculator() { } - - - - - - - +// --------------------------------------------------------------- +// Converts the expressen in a_calcText into a signed value. +// Returns whether an error happend in the variable a_error. +// If an error happend, the variable a_addErrorText can +// contain more informaition about the error (see E_Error for +// more information about errors). +// --------------------------------------------------------------- int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText) { std::string calcText = a_calcText; - + // separate operations from variables for (auto iter = m_OperationList.begin(); iter != m_OperationList.end(); ++iter) replace(calcText, iter->first, " "+iter->first+" "); - + // separate paranthesis from variables replace(calcText, "(", " ( "); replace(calcText, ")", " ) "); - + // now calculate the expression m_ParanthesisCount = 0; m_Error = e_Ok; m_AdditionalErrorText = ""; size_t pos = 0; bool dummy; - int64_t value = calc(calcText, pos, dummy, "", 0, "+"); - + int64_t value = calc(calcText, pos, dummy, "", 0, "+"); // todo: use member-variable m_CalcText + //M_INFO("calc: " << calcText << " value: " << value); - + // check the paranthesis if (m_Error == e_Ok) { if (m_ParanthesisCount > 0) @@ -72,7 +72,7 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, } } - + // actions if a failure happens a_error = m_Error; if (a_error != e_Ok) { @@ -85,9 +85,9 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, return value; } - - - +// --------------------------------------------------------------- +// Adds or changes a case-sensitive variable to the calculator. +// --------------------------------------------------------------- void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_value) { std::map::iterator iter = m_VariableList.find(a_name); @@ -97,9 +97,9 @@ void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_v } - - - +// --------------------------------------------------------------- +// Removes a case-sensitive variable from the calculator. +// --------------------------------------------------------------- void IntegerCalculator::removeVariable(const std::string& a_name) { std::map::iterator iter = m_VariableList.find(a_name); @@ -108,9 +108,9 @@ void IntegerCalculator::removeVariable(const std::string& a_name) } - - - +// --------------------------------------------------------------- +// Calculates the expression (recursive) +// --------------------------------------------------------------- int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis, const std::string& a_prevOp, const int64_t a_prevValue, const std::string& a_initOp) @@ -134,12 +134,12 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo int64_t value2 = calcSign(calc(calcText, ++a_pos, dummy), isNegative); value1 = doOperation(value1, operation, value2); - - size_t tmpPos = a_pos; + // get next operation to check priority of operation + size_t tmpPos = a_pos; // do not change the position, we only pre-read std::string nextOp = getToken(a_calcText, tmpPos); if (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp)) { - + // end of higher priority operation return value1; } @@ -154,19 +154,19 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo } else if (isDigit(calcText[a_pos])) { - - + // value + // ----- int64_t value2 = calcSign(convertValue(calcText, a_pos), isNegative); if (calcWithPriority(calcText, a_pos, value1, operation, value2, a_prevOp)) return value1; } else { - - + // operation or variable + // --------------------- std::string oldOperation = operation; operation = getToken(calcText, a_pos); - + // is it a variable? if (!isOperation(operation)) { int64_t value2 = 0; @@ -178,14 +178,14 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo } else { - + // error m_Error = e_UnknownOperationOrVariable; m_AdditionalErrorText = operation; } } else { - + // do we have a sign? if (oldOperation != "") { if (operation == "+") @@ -211,25 +211,25 @@ int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bo } - - - - +// --------------------------------------------------------------- +// Calculates an operation with respecting the priority of +// operations. This will be done with recursion. +// --------------------------------------------------------------- bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1, std::string& a_operation, int64_t a_value2, const std::string& a_prevOp) { bool isParaEnd = false; - - size_t tmpPos = a_pos; + // get next operation to check priority of operation + size_t tmpPos = a_pos; // only pre-read std::string nextOp = getToken(a_calcText, tmpPos); if (isOperation(a_operation) && isOperation(nextOp) && isOperationPriorityHigher(nextOp, a_operation)) { - + // next operation has higher priority => calc the next operation first a_value2 = calc(a_calcText, a_pos, isParaEnd, a_operation, a_value2); } a_value1 = doOperation(a_value1, a_operation, a_value2); if (isParaEnd || (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp))) { - + // end of higher priority operation return true; } a_operation = ""; @@ -237,12 +237,12 @@ bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t& } - - - - - - +// --------------------------------------------------------------- +// Returns the inverted a_value if a_isNegative is true. +// a_isNegative will be false after calling this function. +// If a_isNegative is true, the NOT inverted a_value will be +// returned. +// --------------------------------------------------------------- int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative) { if (a_isNegative) @@ -254,16 +254,16 @@ int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative) } - - - - +// --------------------------------------------------------------- +// Converts the value in form of text to a number. The Text +// can be decimal, hex (0x) or binary (0b). +// --------------------------------------------------------------- int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& a_pos) { std::string valueText = a_valueText.substr(a_pos); int base = 10; size_t startpos = 0; - + // hex- and binary-stuff bool isHex = (0 == valueText.find("0X")) || (0 == valueText.find("0x")); bool isBin = (0 == valueText.find("0B")) || (0 == valueText.find("0b")); if (isHex) @@ -276,7 +276,7 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& base = 2; startpos = 2; } - + // search end of value size_t i; for (i=startpos; i i && valueText[i] != ' ') { m_Error = e_InvalidOperand; @@ -299,7 +299,7 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& stream.str(valueText.substr(startpos, i-startpos)); if (2 == base) { - + // our stl is not able to read in binary-values, therefore we have to implement it ourself const std::string binValueAsText = stream.str(); for (const char c : binValueAsText) { @@ -317,20 +317,20 @@ int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& } - - - - +// --------------------------------------------------------------- +// Returns the next token (with space as separator). Heading +// spaces will be ignored. +// --------------------------------------------------------------- std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a_pos) { - + // skip spaces at begin while (a_pos < a_calcText.length()) { if (a_calcText[a_pos] == ' ') a_pos++; else break; } - + // search until next space (or end) size_t startPos = a_pos; while (a_pos < a_calcText.length()) { @@ -341,9 +341,9 @@ std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a } - - - +// --------------------------------------------------------------- +// returns true if a_operation is a known operation. +// --------------------------------------------------------------- bool IntegerCalculator::isOperation(const std::string& a_operation) const { std::map::const_iterator iter = m_OperationList.find(a_operation); @@ -351,13 +351,13 @@ bool IntegerCalculator::isOperation(const std::string& a_operation) const } - - - - +// --------------------------------------------------------------- +// Calculates the opeation a_operations with a_value1 as first +// and a_value2 as second operand. +// --------------------------------------------------------------- int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2) { - +// M_INFO("" << a_value1 << " " << a_operation << " " << a_value2); if (("+" == a_operation) || a_operation.empty()) { return a_value1 + a_value2; @@ -409,23 +409,23 @@ int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string } - - - - +// --------------------------------------------------------------- +// returns true if priority of a_opeation1 is higher than +// priority of a_operation2. +// --------------------------------------------------------------- bool IntegerCalculator::isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const { return (getPriority(a_operation1) > getPriority(a_operation2)); } - - - - - - - +// --------------------------------------------------------------- +// Returns true if the variable named a_variableName is known +// and a_value will be filled with its value. If the variable +// is not found false will be returned. +// Overload this virtual function if you want to implement +// your own variable-list. +// --------------------------------------------------------------- bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int64_t& a_value) const { auto iter = m_VariableList.find(a_variableName); @@ -435,37 +435,37 @@ bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int6 return true; } - + // error return false; } - - - - - +// --------------------------------------------------------------- +// Returns true if a_char is a digit. When a_isHex is true, +// also the charactes a-f will be accepted as digits. When +// a_isBin is true, only 0 and 1 will be treated as digit. +// --------------------------------------------------------------- bool IntegerCalculator::isDigit(const char a_char, const bool a_isHex, const bool a_isBin) { if (a_isHex) { - + // for hex-values also A..F are 'digits' return (a_char >= '0' && a_char <= '9') || (a_char >= 'A' && a_char <= 'F') || (a_char >= 'a' && a_char <= 'f'); } else if (a_isBin) { - + // for binary-values only 0 and 1 are allowed return (a_char >= '0' && a_char <= '1'); } - + // normal digits return (a_char >= '0' && a_char <= '9'); } - - - - +// --------------------------------------------------------------- +// Returns the priority of the operation. A higher value means +// more priority. +// --------------------------------------------------------------- int16_t IntegerCalculator::getPriority(const std::string& a_operation) const { std::map::const_iterator iter = m_OperationList.find(a_operation); @@ -476,10 +476,10 @@ int16_t IntegerCalculator::getPriority(const std::string& a_operation) const } - - - - +// --------------------------------------------------------------- +// replaces in a_haystack all a_searchText with a_replaceText +// (not greedy). +// --------------------------------------------------------------- void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_searchText, const std::string &a_replaceText) { std::string::size_type searchSize = a_searchText.length(); @@ -494,4 +494,4 @@ void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_se } } -} +} // namespace N_SST diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.hpp index 22fbf2db7..1c9088eb4 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/IntegerCalculator.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,39 +18,66 @@ namespace N_SST { - - + /** + * This class calculates algebraic texts with integer values and returns its + * result as a signed value. It handles the operations - +, -, *, /, %, <<, >>. It + * understands the paranthesis and priorities of operations, like * before -. It + * also computes with variables, which names are case-sensitive. The values can be + * decimal, hexadecimal (0x) or binary (0b). The variable-system implemented + * virtual, so you can implement your own variable system (see getVariableValue()). + * + * + * @author alois.wismer + * @version 1.0 + * @created 12-Mai-2010 16:26:43 + */ class IntegerCalculator { public: - - + /** + * Describes the error happend while calculation of an expression + * + * @author alois.wismer + * @version 1.0 + * @created 17-Mai-2010 16:38:24 + */ enum E_Error { - - + /** + * No error happend + */ e_Ok, - - + /** + * The divisor is 0 + */ e_DivisionByZero, - - + /** + * The operation/variable is not known. a_addErrorText will contain the unknown + * operation/variable. + */ e_UnknownOperationOrVariable, - - + /** + * Between to operators no variable/operand exists. a_addErrorText contains the 2 + * operations. + */ e_NoOperandBetweenOperators, - - + /** + * The operand contains invalid characters. a_addErrorText contains the invalid + * operand. + */ e_InvalidOperand, - - + /** + * There are more ) than ( + */ e_MissingLeftParanthesis, - - + /** + * There are more ) than ( + */ e_MissingRightParanthesis, - - + /** + * Something else went wrong + */ e_UnknownError }; @@ -58,84 +85,171 @@ namespace N_SST IntegerCalculator(); virtual ~IntegerCalculator() = default; - - + /** + * Converts the expressen in a_calcText into a signed value. Returns whether an + * error happend in the variable a_error. If an error happend, the variable + * a_addErrorText can contain more informaition about the error (see E_Error for + * more information about errors). + * + * @param a_calcText + * @param a_error + * @param a_addErrorText + */ int64_t calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText = nullptr); - - + /** + * Adds or changes a case-sensitive variable to the calculator. + * + * @param a_name + * @param a_value + */ void addVariable(const std::string& a_name, const int64_t a_value); - - + /** + * Removes a case-sensitive variable from the calculator. + * + * @param a_name + */ void removeVariable(const std::string& a_name); protected: - - + /** + * Contains all supported operations + */ const std::map m_OperationList; - - + /** + * Contains all variables + */ std::map m_VariableList; - - + /** + * The additional text for errors + */ std::string m_AdditionalErrorText; - - + /** + * The number of open paranthesis + */ int32_t m_ParanthesisCount; E_Error m_Error; - - + /** + * Calculates the expression (recursive) + * + * @param a_calcText + * @param a_pos + * @param a_IsEndParanthesis + * @param a_prevOp + * @param a_prevValue + * @param a_initOp + */ int64_t calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis, const std::string& a_prevOp = std::string(), const int64_t a_prevValue = 0, const std::string& a_initOp = std::string()); - - + /** + * Calculates an operation with respecting the priority of operations. This will + * be done with recursion. + * + * @param a_calcText + * @param a_pos + * @param a_value1 + * @param a_operation + * @param a_value2 + * @param a_prevOp + */ bool calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1, std::string& a_operation, int64_t a_value2, const std::string& a_prevOp); - - + /** + * Returns the inverted a_value if a_isNegative is true. a_isNegative will be + * false after calling this function. + * If a_isNegative is true, the NOT inverted a_value will be returned. + * + * @param a_value + * @param a_isNegative + */ static int64_t calcSign(const int64_t a_value, bool& a_isNegative); - - + /** + * Converts the value in form of text to a number. The Text can be decimal, hex + * (0x) or binary (0b). + * + * @param a_valueText + * @param a_pos + */ int64_t convertValue(const std::string& a_valueText, size_t& a_pos); - - + /** + * Returns the next token (with space as separator). Heading spaces will be + * ignored. + * + * @param a_calcText + * @param a_pos + */ static std::string getToken(const std::string& a_calcText, size_t& a_pos); - - + /** + * returns true if a_operation is a known operation. + * + * @param a_operation + */ bool isOperation(const std::string& a_operation) const; - - + /** + * Calculates the opeation a_operations with a_value1 as first and a_value2 as + * second operand. + * + * @param a_value1 + * @param a_operation + * @param a_value2 + */ int64_t doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2); - - + /** + * returns true if priority of a_opeation1 is higher than priority of a_operation2. + * + * + * @param a_operation1 + * @param a_operation2 + */ bool isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const; - - + /** + * Returns true if the variable named a_variableName is known and a_value will be + * filled with its value. If the variable is not found false will be returned. + * Overload this virtual function if you want to implement your own variable-list. + * + * @param a_variableName + * @param a_value + */ virtual bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const; - - + /** + * Returns true if a_char is a digit. When a_isHex is true, also the charactes a-f + * will be accepted as digits. When a_isBin is true, only 0 and 1 will be treated + * as digit. + * + * @param a_char + * @param a_isHex + * @param a_isBin + */ static bool isDigit(const char a_char, const bool a_isHex = false, const bool a_isBin = false); - - + /** + * Returns the priority of the operation. A higher value means more priority. + * + * @param a_operation + */ int16_t getPriority(const std::string& a_operation) const; - - + /** + * replaces in a_haystack all a_searchText with a_replaceText (not greedy). + * + * @param a_haystack + * @param a_searchText + * @param a_replaceText + */ static void replace(std::string& a_haystack, const std::string& a_searchText, const std::string& a_replaceText); }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.cpp index 4b3ec1b6b..4ec34f960 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Edit boolean values + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "LogViewBooleanEdit.hpp" #include "LogViewField.hpp" @@ -8,7 +13,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly) : QCheckBox (a_parent) , LogViewWidget(a_field, this, a_parent, a_readonly) @@ -19,7 +24,7 @@ LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, setEnabled(!a_readonly); } - +// --------------------------------------------------------------- bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram) { if (m_Valid) @@ -33,4 +38,4 @@ bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram) return false; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.hpp index abcba5c04..3cb68a018 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewBooleanEdit.hpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Edit boolean values + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.cpp index b3af104e4..096538f11 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.cpp @@ -1,17 +1,17 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewDateTimeEdit.hpp" #include #include "LogViewField.hpp" @@ -20,7 +20,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly) : QDateTimeEdit(a_parent) , LogViewWidget(a_field, this, a_parent, a_readonly) @@ -31,7 +31,7 @@ LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_paren setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft); } - + // date-time-field qint64 unixTime = 0; if (a_field->hasContent()) { @@ -40,34 +40,34 @@ LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_paren else unixTime = a_field->value(0, true).toInt() * 1000LL; } - + // take actual date and time if time is 0 if (0 == unixTime && !a_readonly) unixTime = ::time(nullptr) * 1000LL; - + //valueWidget = new QDateTimeEdit(dateTime); setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime)); setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss")); setCalendarPopup(true); updateToolTip(QString::number(unixTime)); - - + //setToolTip(a_field->getToolTipText()); + // checkAndOvertakeContent(); connect(this, &LogViewDateTimeEdit::editingFinished, this, &LogViewDateTimeEdit::checkAndOvertakeContent); } - +// --------------------------------------------------------------- void LogViewDateTimeEdit::checkAndOvertakeContent() { updateToolTip(QString::number(dateTime().toMSecsSinceEpoch() / 1000)); } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram) { if (a_telegram->isJsonTelegram()) @@ -76,11 +76,11 @@ bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram) } else { - a_telegram->setNextFieldAsGpsTimeField(); + a_telegram->setNextFieldAsGpsTimeField(); // fixme: muss noch der feldname auf GPS Zeit geprüft werden? a_telegram->setUIntX(getSize(), dateTime().toMSecsSinceEpoch() / 1000); } return true; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.hpp index 94ec4e521..cb1f297c9 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewDateTimeEdit.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,18 +18,31 @@ namespace N_LogView { - - + /** + * Used for date & time + * + * @author alois.wismer + * @version 1.0 + * @created 20-Mai-2010 17:41:28 + */ class LogViewDateTimeEdit : public QDateTimeEdit, public LogViewWidget { Q_OBJECT public: - - + /** + * + * @param a_field + * @param a_parent + * @param a_readonly + */ LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly); - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; public slots: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.cpp index 8f8da7b96..477914745 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.cpp @@ -1,17 +1,17 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewEnumEdit.hpp" #include "LogViewXdrStruct.hpp" #include "LogViewXdrValue.hpp" @@ -23,17 +23,17 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index) : QComboBox(a_parent) , LogViewWidget(a_field, this, a_parent, a_readonly) { QString value = a_field->value(a_index); - + // show the tool-tip with special-case for TETRA bitfields setToolTip(a_field->toolTipText()); - + // fill combobox bool bCurrentIndexSet = false; int i = 0; while (LogViewXdrValue* child = (static_cast(a_field->xdrElement()))->getChildAsValue(i++)) @@ -61,32 +61,32 @@ LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const setCurrentIndex(findText(value)); } - + // connect signals connect(this, QOverload::of(&LogViewEnumEdit::currentIndexChanged), this, &LogViewEnumEdit::checkAndOvertakeContent); } - +// --------------------------------------------------------------- uint16_t LogViewEnumEdit::getSize() const { - + // todo: check ob wirklich ein struct const LogViewXdrStruct* xdrStruct = static_cast(m_Field->xdrElement()); return xdrStruct->getEnumSize(); } - +// --------------------------------------------------------------- void LogViewEnumEdit::checkAndOvertakeContent() { updateToolTip(itemData(currentIndex()).toString()); } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram) { bool ok; @@ -99,7 +99,7 @@ bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram) a_telegram->setUIntX(getSize(), value); return true; } - return false; + return false; // failure while conversion } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.hpp index eb2b708af..8bb05b8f0 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewEnumEdit.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,21 +18,35 @@ namespace N_LogView { - - + /** + * Used for enums + * + * @author alois.wismer + * @version 1.0 + * @created 21-Mai-2010 09:31:16 + */ class LogViewEnumEdit : public QComboBox, public LogViewWidget { Q_OBJECT public: - - + /** + * + * @param a_field + * @param a_parent + * @param a_readonly + * @param a_index the array-index + */ LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index); uint16_t getSize() const override; - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; protected slots: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.cpp index 5c9d87098..d62d7244b 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewField.hpp" #include @@ -20,7 +20,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement) : m_logger(getLogger("LogViewField")), m_Name(a_name), @@ -36,7 +36,7 @@ LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, cons { } - +// --------------------------------------------------------------- LogViewField::~LogViewField() { for (LogViewField *f : std::as_const(m_Child)) @@ -70,14 +70,14 @@ LogViewField *LogViewField::clone(int arrayIdx) const } - +// --------------------------------------------------------------- void LogViewField::addChild(LogViewField* a_child) { if (a_child) m_Child.push_back(a_child); } - +// --------------------------------------------------------------- void LogViewField::removeLastChild() { if (m_Child.empty()) @@ -86,7 +86,7 @@ void LogViewField::removeLastChild() } - +// --------------------------------------------------------------- LogViewField* LogViewField::child(int arrayIdx) { if (m_Child.size() > arrayIdx) @@ -94,13 +94,13 @@ LogViewField* LogViewField::child(int arrayIdx) return nullptr; } - +// --------------------------------------------------------------- void LogViewField::addValue(const QString &value) { m_ValueList.append(value); } - +// --------------------------------------------------------------- void LogViewField::addValueBinaryHex(const QString &value) { const QByteArray ba = QByteArray::fromHex(value.toLatin1()); @@ -109,13 +109,13 @@ void LogViewField::addValueBinaryHex(const QString &value) } - - - - - - - +// --------------------------------------------------------------- +// Returns the value at position a_index converted to a string. +// If the field is a date-time-field, the returned value is +// converted to a string containing date and time, execpt when +// a_doNotMakeSpecialConversions is set to true, the unix-time +// will be returned as value. +// --------------------------------------------------------------- QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversions) const { if (m_ValueList.size() > arrayIdx) @@ -133,7 +133,7 @@ QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversio return QString(); } - +// --------------------------------------------------------------- int64_t LogViewField::getHighestValue() const { switch (m_XdrElement->getKind()) @@ -141,9 +141,9 @@ int64_t LogViewField::getHighestValue() const case LogViewXdrElement::e_KindStandardType: { int64_t highest = 1; - + //const LogViewXdrStandardType* xdrStandardType = static_cast(m_XdrElement); uint16_t bitSize = 8*static_cast(m_XdrElement)->getEditSize(); - + // fixme: mache configurierbar if ((0 == m_Name.compare(QLatin1String("utm nordwert"), Qt::CaseInsensitive)) || (0 == m_Name.compare(QLatin1String("utm ostwert"), Qt::CaseInsensitive))) bitSize -= 8; @@ -172,7 +172,7 @@ int64_t LogViewField::getHighestValue() const } - +// --------------------------------------------------------------- int64_t LogViewField::getLowestValue() const { switch (m_XdrElement->getKind()) @@ -180,7 +180,7 @@ int64_t LogViewField::getLowestValue() const case LogViewXdrElement::e_KindStandardType: { int64_t lowest = 0; - + //const LogViewXdrStandardType* xdrStandardType = static_cast(a_field->getXdrElement()); switch (static_cast(m_XdrElement)->getValueKind()) { case LogViewXdrStandardType::e_Boolean: return 0; @@ -201,12 +201,12 @@ int64_t LogViewField::getLowestValue() const } - +// --------------------------------------------------------------- void LogViewField::dump(const QString &a_indent) const { INFO_LOG(m_logger) << a_indent << "["; INFO_LOG(m_logger) << a_indent << "Field[" << m_Name << "]: m_Kind=" << m_Kind << " m_Offset=" << m_Offset << " m_Size=" << m_Size << " m_MaxArraySize=" << m_MaxArraySize << " m_IsRightAligned=" << m_IsRightAligned << " m_IsDynamicArray=" << m_IsDynamicArray << " m_ToolTipText=" << m_ToolTipText; - +// m_XdrElement->dump(); for (int i=0; i pos) { @@ -250,9 +250,9 @@ QString LogViewField::makeClean(const QString &text) } - - - +// --------------------------------------------------------------- +// returns true if the field is a date-time +// --------------------------------------------------------------- bool LogViewField::isDateTimeField() const { QString name = m_Name.toLower(); @@ -266,11 +266,11 @@ bool LogViewField::isMSecsField() const } - +// --------------------------------------------------------------- void LogViewField::setMaxArraySize(uint16_t newVal, const bool a_isDynamic) { m_MaxArraySize = newVal; m_IsDynamicArray = a_isDynamic; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.hpp index 6c9bd42a6..6f38965d1 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewField.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -57,8 +57,15 @@ namespace N_LogView void addValue(const QString &value); void addValueBinaryHex(const QString &value); - - + /** + * Returns the value at position a_index converted to a string. If the field is a + * date-time-field, the returned value is converted to a string containing date + * and time, execpt when a_doNotMakeSpecialConversions is set to true, the unix- + * time will be returned as value. + * + * @param a_index + * @param a_doNotMakeSpecialConversions + */ QString value(int arrayIdx, const bool a_doNotMakeSpecialConversions = false) const; int valueListSize() const { return m_ValueList.size(); } @@ -74,12 +81,21 @@ namespace N_LogView int64_t getHighestValue() const; int64_t getLowestValue() const; - - + /** + * + * @param a_indent + */ void dump(const QString &a_indent = QString()) const; - - + /** + * Makes the text pretty for human readable. It does following: + * - generates umlaute (ä, ö, ü) + * - removes _rt at end + * - replaces _ with space + * - uppercase of every word + * + * @param a_uncleanText + */ static QString makeClean(const QString &text); @@ -89,8 +105,9 @@ namespace N_LogView const LogViewXdrElement* xdrElement() const { return m_XdrElement; } - - + /** + * returns true if the field is a date-time + */ bool isDateTimeField() const; bool isMSecsField() const; @@ -98,8 +115,9 @@ namespace N_LogView uint16_t maxArraySize() const { return m_MaxArraySize; } void setMaxArraySize(uint16_t newVal, const bool a_isDynamic); - - + /** + * True if the array is dynamic. + */ bool isDynamicArray() const { return m_IsDynamicArray; } @@ -124,8 +142,9 @@ namespace N_LogView uint16_t m_Offset; int m_Size; uint16_t m_MaxArraySize; - - + /** + * True if the array is dynamic. + */ bool m_IsDynamicArray; bool m_HasContent; bool m_bDeleteXdr; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.cpp index 3f0055b84..951c01bc7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.cpp @@ -1,17 +1,17 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - +// manual class headers #include "LogViewGui.hpp" #include "LogViewTelegram.hpp" @@ -50,7 +50,7 @@ namespace N_LogView { - +// static member initialization const QLatin1String LogViewGui::WINDOW_GROUP("MainWindow"); const QLatin1String LogViewGui::SIZE("Size"); const QLatin1String LogViewGui::SCREEN("Screen"); @@ -59,9 +59,9 @@ const QLatin1String LogViewGui::SPLITTPOS("SplittPos"); const QLatin1String LogViewGui::TOOLBOXINDEX("ToolBoxIndex"); +// --------------------------------------------------------------- - - +// --------------------------------------------------------------- LogViewGui::LogViewGui(QWidget* a_parent) : QMainWindow(a_parent) , RADIO_BUTTON_ICON_SIZE(16, 16) @@ -79,7 +79,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) QSettings settings; settings.beginGroup(WINDOW_GROUP); - + // status-bar m_InjectionStatus = new QLabel(this); m_InjectionStatus->setFrameStyle(QFrame::Panel | QFrame::Sunken); statusBar()->addPermanentWidget(m_InjectionStatus); @@ -90,11 +90,11 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_TelegramStatus->setFrameStyle(QFrame::Panel | QFrame::Sunken); statusBar()->addPermanentWidget(m_TelegramStatus); - - + // tool-bar + // -------- QToolBar* toolBar = addToolBar(tr("Datei")); toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); - + // tool-bar: new logfile QString tipText; QAction* action = new QAction(tr("Neue Log-Datei"), this); action->setIcon(QIcon(QLatin1String(":icons/16x16/document-new.png"))); @@ -104,7 +104,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) action->setToolTip(tipText); connect(action, &QAction::triggered, this, &LogViewGui::newTelegramFile); toolBar->addAction(action); - + // tool-bar: add logfile action = new QAction(tr("Log-Datei hinzu"), this); action->setIcon(QIcon(QLatin1String(":icons/16x16/document-import.png"))); action->setShortcut(tr("Ctrl+O")); @@ -113,7 +113,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) action->setToolTip(tipText); connect(action, &QAction::triggered, this, &LogViewGui::loadTelegramFile); toolBar->addAction(action); - + // tool-bar: reload m_reloadAction = new QAction(tr("&Reload"), this); m_reloadAction->setCheckable(true); m_reloadAction->setChecked(m_DoReload); @@ -124,7 +124,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_reloadAction->setToolTip(tipText); connect(m_reloadAction, &QAction::triggered, this, &LogViewGui::reloadOnOff); toolBar->addAction(m_reloadAction); - + // tool-bar: settings action = new QAction(tr("&Einstellungen"), this); action->setIcon(QIcon(QLatin1String(":icons/16x16/configure.png"))); action->setShortcut(tr("Ctrl+E")); @@ -133,7 +133,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) action->setToolTip(tipText); connect(action, &QAction::triggered, this, &LogViewGui::changeSettings); toolBar->addAction(action); - + // tool-bar: exit toolBar->addSeparator(); action = new QAction(tr("&Beenden"), this); action->setIcon(QIcon(QLatin1String(":icons/16x16/edit-delete.png"))); @@ -148,8 +148,8 @@ LogViewGui::LogViewGui(QWidget* a_parent) createTetraSelectionWidget(); createWlsSelectionWidget(); - - + // participant-selection + // --------------------- m_ParticipantTableView = new QTableView(this); m_participantProxyModel = new QSortFilterProxyModel(this); m_participantModel = new ParticipantModel(this); @@ -175,7 +175,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_ParticipantSelectionGroup->setLayout(participantBox); connect(m_ParticipantSelectionGroup, &QGroupBox::toggled, this, &LogViewGui::selectedParticipantChanged); - + // left side (filters) m_ToolBox = new QToolBox(this); m_ToolBox->addItem(m_CentralSelectionGroup, QIcon(QLatin1String(":/image/Central.png")), tr("&Zentral-Telegramm-Filter")); m_ToolBox->addItem(m_TetraSelectionGroup, QIcon(QLatin1String(":/image/Tetra.png")), tr("TET&RA-Telegramm-Filter")); @@ -184,8 +184,8 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_ToolBox->addItem(m_EditTelegramController->tableView(), QIcon(QLatin1String(":icons/16x16/document-edit.png")), tr("&Edit && Sende Telegramme")); m_ToolBox->setCurrentIndex(settings.value(TOOLBOXINDEX).toInt()); - - + // right side (logged telegrams) + // ----------------------------- m_logTelegramView = new QTableView(this); m_logTelegramView->setAlternatingRowColors(true); m_logTelegramView->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -194,9 +194,9 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_logTelegramView->verticalHeader()->setMinimumSectionSize(QApplication::font().pointSize() * 2.5); m_logTelegramView->verticalHeader()->setDefaultSectionSize(QApplication::font().pointSize() * 2.5); m_logTelegramView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); - m_logTelegramView->setContextMenuPolicy(Qt::CustomContextMenu); + m_logTelegramView->setContextMenuPolicy(Qt::CustomContextMenu); //Custom Contextmenu enabled connect(m_logTelegramView, &QTableView::customContextMenuRequested, - this, &LogViewGui::customMenuRequested); + this, &LogViewGui::customMenuRequested); //connect table to contextmenu m_telegramModel = new TelegramModel(m_logTelegramView); m_telegramProxyModel = new TelegramProxyModel(m_logTelegramView); m_telegramProxyModel->setSourceModel(m_telegramModel); @@ -212,7 +212,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) QGroupBox* telegramGroup = new QGroupBox(tr("&Log-Telegramme"), this); telegramGroup->setLayout(telegramBox); - + // splitter between toolbox and log-telegram-list m_Splitter = new QSplitter(Qt::Horizontal, this); m_Splitter->addWidget(m_ToolBox); m_Splitter->addWidget(telegramGroup); @@ -231,8 +231,8 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_Splitter->setSizes(splitterSizes); setCentralWidget(m_Splitter); - - + // initialize the telegram-filters (this should be done before load of telegrams, otherwise the telegram-list + // will be shown several times and this could be slow when the telegram-list is slow) m_CentralSelectionGroup->setChecked(true); m_ackCentralTelCheckBox->setChecked(true); m_ackCentralTelCheckBox->setChecked(false); @@ -258,7 +258,7 @@ LogViewGui::LogViewGui(QWidget* a_parent) m_SentWlsTelCheckBox->setChecked(true); m_ReceivedWlsTelCheckBox->setChecked(true); - + // set the size and position of main-window QSize size = settings.value(SIZE, sizeHint()).toSize(); resize(size.isNull() ? QSize(1280, 768) : size); move(settings.value(POS, QPoint(0, 0)).toPoint()); @@ -273,13 +273,13 @@ LogViewGui::LogViewGui(QWidget* a_parent) void LogViewGui::createCentralSelectionWidget() { - + // send-checkbox m_SentCentralTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2C.png")); - + // received-checkbox m_ReceivedCentralTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/C2P.png")); - + // pos-checkbox m_PosCentralTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/CentralPos.png")); - + // ack-checkbox m_ackCentralTelCheckBox = createRadioButton(tr("&Bestaetigungstelegramme"), QLatin1String(":/image/CentralAck.png")); QVBoxLayout* centralFilterBox = new QVBoxLayout; @@ -298,21 +298,21 @@ void LogViewGui::createCentralSelectionWidget() void LogViewGui::createTetraSelectionWidget() { - + // sent-checkbox m_SentTetraTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/T2P.png")); - + // received-checkbox m_ReceivedTetraTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/P2T.png")); - + // pos-checkbox m_PosTetraTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/TetraPos.png")); - + // fragmented-checkbox m_FragmentedTetraTelCheckBox = createRadioButton(tr("&Fragmentierte Meldungen"), QLatin1String(":/image/TetraFragmented.png")); - + // login-checkbox m_LoginTetraTelCheckBox = createRadioButton(tr("&Loginmeldungen"), QLatin1String(":/image/TetraLogin.png")); - + // register-checkbox m_RegisterTetraTelCheckBox = createRadioButton(tr("&Registermeldungen"), QLatin1String(":/image/TetraRegister.png")); - + // report-checkbox m_ReportTetraTelCheckBox = createRadioButton(tr("&Reportmeldungen"), QLatin1String(":/image/TetraReport.png")); - + // air-interface-load-checkbox m_AirInterfaceLoadTetraTelCheckBox = createRadioButton(tr("&Air-Load Meldungen"), QLatin1String(":/image/TetraAirInterface.png")); QVBoxLayout* tetraFilterBox = new QVBoxLayout; @@ -335,11 +335,11 @@ void LogViewGui::createTetraSelectionWidget() void LogViewGui::createWlsSelectionWidget() { - + // send-checkbox m_SentWlsTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2W.png")); - + // received-checkbox m_ReceivedWlsTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/W2P.png")); - + // pos-checkbox m_PosWlsTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/WlsPos.png")); QVBoxLayout* wlsFilterBox = new QVBoxLayout; @@ -356,10 +356,10 @@ void LogViewGui::createWlsSelectionWidget() } - +// --------------------------------------------------------------- void LogViewGui::customMenuRequested(const QPoint &pos) { - + //create Menu with Actions QMenu menu(this); menu.addAction(tr("Add Telegram to EditList"), this, &LogViewGui::addTelegramToEdit); menu.addAction(tr("Show HexData"), this, &LogViewGui::showHexData); @@ -376,7 +376,7 @@ void LogViewGui::customMenuRequested(const QPoint &pos) } - +// --------------------------------------------------------------- void LogViewGui::addTelegramToEdit() { for (const QModelIndex &orig: m_logTelegramView->selectionModel()->selectedRows()) @@ -390,7 +390,7 @@ void LogViewGui::addTelegramToEdit() } - +// --------------------------------------------------------------- void LogViewGui::showHexData() { const QModelIndex idx = m_telegramProxyModel->mapToSource(m_logTelegramView->currentIndex()); @@ -402,7 +402,7 @@ void LogViewGui::showHexData() showTelegramDialog->showDataDump(tele, false); } - +// --------------------------------------------------------------- void LogViewGui::exportAsCsv() { const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.')); @@ -441,7 +441,7 @@ void LogViewGui::exportAsCsv() f.write("\n"); } f.close(); -} +}// --------------------------------------------------------------- void LogViewGui::exportAsJson() { @@ -468,7 +468,7 @@ void LogViewGui::exportAsJson() f.close(); } - +// --------------------------------------------------------------- void LogViewGui::onStartLogReplay() { #ifndef LTS_DEBUG @@ -526,7 +526,7 @@ void LogViewGui::onReplayTimerTimeout() if (!checkTele()) return; - uint64_t nextSendTime = (tele->getLogTimeMsec() - curSendTime); + uint64_t nextSendTime = (tele->getLogTimeMsec() - curSendTime); // micro -> milli DEBUG_LOG(m_logger) << "Next SendTime: " << nextSendTime << ", telId: " << tele->getTelId() << ", next row: " << m_currentReplayRow @@ -536,13 +536,13 @@ void LogViewGui::onReplayTimerTimeout() m_replayTimer->start(nextSendTime); } - +// --------------------------------------------------------------- void LogViewGui::loadSpecificationFiles() { QSettings settings; settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP); - + // load central-protocol spezification QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h"); QString filename = settings.value(LogViewOptionDialog::P0_FILENAME, defString).toString(); INFO_LOG(m_logger) << "Load central-protocol spezification-file: " << filename.toStdString(); @@ -553,7 +553,7 @@ void LogViewGui::loadSpecificationFiles() } LogViewTelegram::jsonParser()->parse(filename); - + // load tetra-protocol spezification defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x"); filename = settings.value(LogViewOptionDialog::P5_FILENAME, defString).toString(); INFO_LOG(m_logger) << "Load tetra-protocol spezification-file: " << filename.toStdString(); @@ -570,29 +570,29 @@ void LogViewGui::loadSpecificationFiles() } - +// --------------------------------------------------------------- void LogViewGui::newTelegramFile() { if (m_TailTimer) m_TailTimer->stop(); - + // delete all participants m_participantModel->clearParticipants(); m_telegramModel->clearTelegrams(); m_participantListTelCount.clear(); m_participantListIssi.clear(); m_ParticipantStatus->setText(tr("0 Teilnehmer")); - + // load a telegram-file loadTelegramFile(); } - +// --------------------------------------------------------------- void LogViewGui::loadTelegramFile() { const QLatin1String DIR("Dir"); QSettings settings; settings.beginGroup(QLatin1String("LogFiles")); - QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES); + QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES/*tr("Log-Dateien (*.krlog)")*/); if (filename.isEmpty()) return; @@ -605,7 +605,7 @@ void LogViewGui::loadTelegramFile() m_logTelegramView->resizeColumnsToContents(); m_ParticipantTableView->resizeColumnsToContents(); - + // start the time for checking whether new entries were added to the log-file if (!m_TailTimer) m_TailTimer = new QTimer(this); connect(m_TailTimer, &QTimer::timeout, this, &LogViewGui::updateLogfile, Qt::QueuedConnection); @@ -614,11 +614,11 @@ void LogViewGui::loadTelegramFile() } - - - - - +// --------------------------------------------------------------- +// Checks whether the size of actual logfile has changed. If +// yes, the new log-entries will be read and shown within +// table. +// --------------------------------------------------------------- void LogViewGui::updateLogfile() { if(!m_DoReload) @@ -636,12 +636,12 @@ void LogViewGui::updateLogfile() catch (const std::exception& e) { WARNING_LOG(m_logger) << "Error: " << e.what(); - + // simply read the telegram in the next update } } else { - + //check if one newer file exists and load it QString dateFromFile; const QString format = QStringLiteral("yyMMdd_hh"); for (int iterator = fileInfo.baseName().size() - format.size(); iterator < fileInfo.baseName().size(); ++iterator) @@ -677,10 +677,10 @@ void LogViewGui::updateLogfile() } - +// --------------------------------------------------------------- void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos) { - + // open the log-file QFile telegramFile(a_fileName); if (telegramFile.open(QIODevice::ReadOnly)) { @@ -690,7 +690,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6 m_logTelegramView->blockSignals(true); m_logTelegramView->setUpdatesEnabled(false); QVector > newTelegrams; - + // read the header of telegram-entry N_CoPrtCnv::CoPrtCnvLogHeader lh; while (true) { @@ -698,7 +698,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6 { if (lh.m_Version == 3 || lh.m_Version == 4) { - + // read the telegram itself qint64 telegramLength = lh.m_Length - sizeof(lh); QByteArray buf(telegramLength, Qt::Uninitialized); if (telegramLength == telegramFile.read(buf.data(), telegramLength)) @@ -708,11 +708,11 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6 if (lh.m_Version == 4) buf = qUncompress(buf); - + // add the telegram to telegram-list N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol protocol = static_cast(lh.m_Protocol); QSharedPointer telegram(new LogViewTelegram(protocol, lh.m_Time, buf)); - + // this checks the telegram and raises a messagebox if the telegram is wrong if (!telegram->isValid()) { ERROR_LOG(m_logger) << "Trying to read/parse unknown data from logfile '" << a_fileName @@ -721,7 +721,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6 } newTelegrams.push_back(telegram); - + // add the pariticipant to the participant-list addToParticipantList(telegram); } } @@ -754,7 +754,7 @@ void LogViewGui::readTelegramsFromLogFile(const QString& a_fileName, const qint6 } - +// --------------------------------------------------------------- void LogViewGui::selectedParticipantChanged() { std::set selectedParticipantIds; @@ -762,7 +762,7 @@ void LogViewGui::selectedParticipantChanged() const QModelIndexList selectedParticipants = m_ParticipantTableView->selectionModel()->selectedRows(0); for (const QModelIndex &participantIdx : selectedParticipants) { - + // row 0 -> eqId const QModelIndex idx = m_participantProxyModel->mapToSource(participantIdx); selectedParticipantIds.insert(m_participantModel->data(idx).toInt()); } @@ -788,7 +788,7 @@ static void updateFilteredPosTelegramIds(std::set &teleIds, bool bEnable) } } - +// --------------------------------------------------------------- void LogViewGui::showTelegramTable() { updateFilteredPosTelegramIds(m_CentralTelegramFilterList, m_PosCentralTelCheckBox->isChecked()); @@ -872,7 +872,7 @@ void LogViewGui::syncParticipantList() m_participantModel->addUpdateParticipants(eqIds, issis, numberOfTelegrams); } - +// --------------------------------------------------------------- void LogViewGui::changeSettings() { LogViewOptionDialog optionDialog(this); @@ -883,7 +883,7 @@ void LogViewGui::changeSettings() } - +// --------------------------------------------------------------- QCheckBox* LogViewGui::createRadioButton(const QString& a_buttonName, const QString& a_iconName) { QCheckBox* checkBox = new QCheckBox(a_buttonName, this); @@ -894,10 +894,10 @@ QCheckBox* LogViewGui::createRadioButton(const QString& a_buttonName, const QStr } - - - - +// --------------------------------------------------------------- +// starts the thread, which trys to connect to the injection- +// server of PrtCnv +// --------------------------------------------------------------- void LogViewGui::startInjectionThread() { if (m_InjectionThread) @@ -933,26 +933,26 @@ void LogViewGui::startInjectionThread() } - - - - +// --------------------------------------------------------------- +// Toggles whether the logfile must be periodically checked +// for changes +// --------------------------------------------------------------- void LogViewGui::reloadOnOff() { m_DoReload = !m_DoReload; } - +// --------------------------------------------------------------- void LogViewGui::closeEvent(QCloseEvent* a_closeEvent) { QSettings settings; settings.beginGroup(WINDOW_GROUP); - + // store the actual toolbox selection settings.setValue(TOOLBOXINDEX, m_ToolBox->currentIndex()); - + // store the actual size settings.setValue(SIZE, size()); QPoint position = pos(); settings.setValue(POS, position); @@ -960,7 +960,7 @@ void LogViewGui::closeEvent(QCloseEvent* a_closeEvent) int screenNbr = QGuiApplication::screens().indexOf(scr); settings.setValue(SCREEN, screenNbr); - + // store the splitter-position const QList splitterSizes = m_Splitter->sizes(); QList splitterSizesAsVariant; splitterSizesAsVariant.reserve(splitterSizes.size()); @@ -974,14 +974,14 @@ void LogViewGui::closeEvent(QCloseEvent* a_closeEvent) QMainWindow::closeEvent(a_closeEvent); } - +// --------------------------------------------------------------- void LogViewGui::updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText) { m_InjectionStatus->setPixmap(QPixmap(a_picName)); m_InjectionStatus->setToolTip(a_toopTipText); } - +// --------------------------------------------------------------- void LogViewGui::onLogTelegramViewDoubleClicked(const QModelIndex &index) { if (!m_telegramProxyModel || !m_telegramModel) @@ -1005,4 +1005,4 @@ void LogViewGui::onSettingsChanged(uint32_t changedFlags) startInjectionThread(); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.hpp index 88901a404..dacb75b18 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewGui.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -41,8 +41,11 @@ namespace N_LogView class LogViewInjectionThread; class TelegramEdit; - - +/** + * @author alois.wismer + * @version 1.0 + * @created 03-Feb-2010 16:44:53 + */ class LogViewGui : public QMainWindow { Q_OBJECT @@ -60,14 +63,14 @@ protected: static const QLatin1String POS; static const QLatin1String SPLITTPOS; static const QLatin1String TOOLBOXINDEX; - + // Central QGroupBox *m_CentralSelectionGroup; std::set m_CentralTelegramFilterList; QCheckBox* m_SentCentralTelCheckBox; QCheckBox* m_ReceivedCentralTelCheckBox; QCheckBox* m_PosCentralTelCheckBox; QCheckBox* m_ackCentralTelCheckBox; - + // Tetra QGroupBox *m_TetraSelectionGroup; std::set m_TetraTelegramFilterList; QCheckBox* m_SentTetraTelCheckBox; @@ -78,7 +81,7 @@ protected: QCheckBox* m_ReportTetraTelCheckBox; QCheckBox* m_FragmentedTetraTelCheckBox; QCheckBox* m_AirInterfaceLoadTetraTelCheckBox; - + // Wls QGroupBox *m_WlsSelectionGroup; std::set m_WlsTelegramFilterList; QCheckBox* m_SentWlsTelCheckBox; @@ -114,9 +117,9 @@ protected: QLabel *m_InjectionStatus; - + // ausstg, telcount QHash m_participantListTelCount; - + // ausstg, issi QHash m_participantListIssi; QAction *m_reloadAction; @@ -125,14 +128,16 @@ protected: protected: void readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos = 0); - - + /** + * returns true if the participant was added to the list + */ void addToParticipantList(const QSharedPointer &a_telegram); void syncParticipantList(); QCheckBox* createRadioButton(const QString& a_buttonName, const QString& a_iconName); - - + /** + * starts the thread, which trys to connect to the injection-server of PrtCnv + */ void startInjectionThread(); void closeEvent(QCloseEvent* a_closeEvent) override; @@ -157,25 +162,31 @@ protected slots: void loadTelegramFile(); - - + /** + * Checks whether the size of actual logfile has changed. If yes, the new log- + * entries will be read and shown within table. + */ void updateLogfile(); void selectedParticipantChanged(); void showTelegramTable(); - + //SLOT for creating the ContextMenu void customMenuRequested(const QPoint &pos); void changeSettings(); - - + /** + * Toggles whether the logfile must be periodically checked for changes + */ void reloadOnOff(); - - + /** + * + * @param a_picName + * @param a_toopTipText + */ void updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText); void onLogTelegramViewDoubleClicked(const QModelIndex &index); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.cpp index 673903d79..e2979c490 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.cpp @@ -1,17 +1,17 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewInjectionThread.hpp" #include "LogViewTelegram.hpp" @@ -30,13 +30,13 @@ LogViewInjectionThread::LogViewInjectionThread() , m_Socket(nullptr) , m_Timer(nullptr) { - + // load the settings (and write default-values if not defined) QSettings settings; settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP); m_Hostname = settings.value(LogViewOptionDialog::INJECTION_HOSTNAME).toString(); if (m_Hostname.isEmpty()) { - + // set default-hostname if nothing was set m_Hostname = QLatin1String("localhost"); settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname); } @@ -48,7 +48,7 @@ LogViewInjectionThread::LogViewInjectionThread() } } - +// --------------------------------------------------------------- void LogViewInjectionThread::run() { emit updateStatus(QLatin1String(":/image/RedLamp.png"), @@ -59,7 +59,7 @@ void LogViewInjectionThread::run() } - +// --------------------------------------------------------------- void LogViewInjectionThread::setPort(uint16_t port) { m_Port = port; @@ -69,17 +69,17 @@ void LogViewInjectionThread::setPort(uint16_t port) } - +// --------------------------------------------------------------- bool LogViewInjectionThread::isSendingPossible() const { return m_SendingPossible; } - +// --------------------------------------------------------------- void LogViewInjectionThread::tryToConnect() { - + //m_Timer->setInterval(3000); if (!m_Socket) { m_Socket = new QTcpSocket(this); @@ -87,7 +87,7 @@ void LogViewInjectionThread::tryToConnect() connect(m_Socket, &QTcpSocket::disconnected, this, &LogViewInjectionThread::doDisconnect); } - + // we need a timer for retrying connection if (!m_Timer) { m_Timer = new QTimer(this); @@ -101,7 +101,7 @@ void LogViewInjectionThread::tryToConnect() } - +// --------------------------------------------------------------- void LogViewInjectionThread::doConnect() { INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If"; @@ -112,7 +112,7 @@ void LogViewInjectionThread::doConnect() } - +// --------------------------------------------------------------- void LogViewInjectionThread::doDisconnect() { INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If"; @@ -123,7 +123,7 @@ void LogViewInjectionThread::doDisconnect() } - +// --------------------------------------------------------------- void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram) { INFO_LOG(m_logger) << "inject " << (a_doSendAsCentralTelegram ? "central" : "Tetra") << " telegram"; @@ -140,4 +140,4 @@ void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const boo m_Socket->write(data); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.hpp index 6b821e06c..ab42ae4dc 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewInjectionThread.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -24,8 +24,11 @@ namespace N_LogView { class LogViewTelegram; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 05-Aug-2010 16:02:15 + */ class LogViewInjectionThread : public QThread { Q_OBJECT @@ -39,8 +42,11 @@ namespace N_LogView bool isSendingPossible() const; - - + /** + * + * @param a_telegram + * @param a_doSendAsCentralTelegram + */ void sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram); protected: @@ -67,8 +73,11 @@ namespace N_LogView public: signals: - - + /** + * + * @param a_picName + * @param a_toolTipText + */ void updateStatus(const QString& a_picName, const QString& a_toolTipText); }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewMain.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewMain.cpp index d2f75ceb7..5841c9c1e 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewMain.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewMain.cpp @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) buf[len] = '\0'; dir = buf; } else { - + // fallback dir = argv[0]; } #endif diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.cpp index 6e444b569..2e7bc24f0 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "LogViewModels.hpp" @@ -10,20 +15,20 @@ namespace N_LogView { - - +// --------------------------------------------------------------- +// --------------------------------------------------------------- int ParticipantModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_particpants.size(); } - +// --------------------------------------------------------------- int ParticipantModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 3; } - +// --------------------------------------------------------------- QVariant ParticipantModel::data(const QModelIndex &index, int role) const { if (index.isValid() && index.row() < m_particpants.size()) @@ -58,7 +63,7 @@ QVariant ParticipantModel::data(const QModelIndex &index, int role) const if (role == Qt::BackgroundRole) { if (p.first == 0) - return QVariant(); + return QVariant(); // 0 aussen vor lassen if (m_participantHeatmap.isEmpty()) updateHeatMap(); return m_participantHeatmap.value(p.first); @@ -67,7 +72,7 @@ QVariant ParticipantModel::data(const QModelIndex &index, int role) const return QVariant(); } - +// --------------------------------------------------------------- QVariant ParticipantModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -89,7 +94,7 @@ QVariant ParticipantModel::headerData(int section, return QAbstractTableModel::headerData(section, orientation, role); } - +// --------------------------------------------------------------- void ParticipantModel::clearParticipants() { beginResetModel(); @@ -99,7 +104,7 @@ void ParticipantModel::clearParticipants() endResetModel(); } - +// --------------------------------------------------------------- bool ParticipantModel::addUpdateParticipants(const QVector &eqIds, const QVector &issis, const QVector &numberOfTelegrams) @@ -130,13 +135,13 @@ bool ParticipantModel::addUpdateParticipants(const QVector &eqIds, return true; } - +// --------------------------------------------------------------- void ParticipantModel::updateHeatMap() const { int maxNumberOfTelegrams = 0; for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it) { - if (it.key() == 0) + if (it.key() == 0) // EqId 0 aussen vor lassen continue; maxNumberOfTelegrams = std::max(it.value(), maxNumberOfTelegrams); } @@ -146,7 +151,7 @@ void ParticipantModel::updateHeatMap() const for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it) { const int eqId = it.key(); - if (eqId == 0) + if (eqId == 0) // EqId 0 aussen vor lassen continue; const int nbrTelegrams = it.value(); @@ -159,20 +164,20 @@ void ParticipantModel::updateHeatMap() const } } - - +// --------------------------------------------------------------- +// --------------------------------------------------------------- int TelegramModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_telegrams.size(); } - +// --------------------------------------------------------------- int TelegramModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 6; } - +// --------------------------------------------------------------- QVariant TelegramModel::data(const QModelIndex &index, int role) const { if (index.isValid() && index.row() < m_telegrams.size()) @@ -226,7 +231,7 @@ QVariant TelegramModel::data(const QModelIndex &index, int role) const return QVariant(); } - +// --------------------------------------------------------------- QVariant TelegramModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -257,7 +262,7 @@ QVariant TelegramModel::headerData(int section, return QAbstractTableModel::headerData(section, orientation, role); } - +// --------------------------------------------------------------- void TelegramModel::clearTelegrams() { beginResetModel(); @@ -265,7 +270,7 @@ void TelegramModel::clearTelegrams() endResetModel(); } - +// --------------------------------------------------------------- void TelegramModel::appendTelegrams(const QVector > &telegrams) { if (telegrams.isEmpty()) @@ -275,7 +280,7 @@ void TelegramModel::appendTelegrams(const QVector &telegram) { beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size()); @@ -283,7 +288,7 @@ void TelegramModel::appendTelegram(const QSharedPointer &telegr endInsertRows(); } - +// --------------------------------------------------------------- QSharedPointer TelegramModel::telegram(int row) const { if (row >= 0 && row < m_telegrams.size()) @@ -291,8 +296,8 @@ QSharedPointer TelegramModel::telegram(int row) const return QSharedPointer(); } - - +// --------------------------------------------------------------- +// --------------------------------------------------------------- void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds) { if (m_bFilterByEquipmentIds == bFilterByEquipmentIds) @@ -304,7 +309,7 @@ void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds) endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setAllowedEquipmentIds(const std::set &allowedEquipmentIds) { if (m_allowedEquipmentIds == allowedEquipmentIds) @@ -316,7 +321,7 @@ void TelegramProxyModel::setAllowedEquipmentIds(const std::set &allowedEqui endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set &filteredCentralTelegramIds) { if (m_filteredCentralTelegramIds == filteredCentralTelegramIds) @@ -328,7 +333,7 @@ void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set &filt endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set &filteredTetraTelegramIds) { if (m_filteredTetraTelegramIds == filteredTetraTelegramIds) @@ -340,7 +345,7 @@ void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set &filter endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set &filteredWlsTelegramIds) { if (m_filteredWlsTelegramIds == filteredWlsTelegramIds) @@ -353,7 +358,7 @@ void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set &filtered } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter) { @@ -371,7 +376,7 @@ void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter) { @@ -389,7 +394,7 @@ void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader:: endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType, bool bFilter) { @@ -424,7 +429,7 @@ void TelegramProxyModel::setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_ endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilterTetraLogin(bool bFilter) { if (m_bFilterLoginTelegrams == bFilter) @@ -436,7 +441,7 @@ void TelegramProxyModel::setFilterTetraLogin(bool bFilter) endFilterChange(); } - +// --------------------------------------------------------------- void TelegramProxyModel::setFilterTetraFragmented(bool bFilter) { if (m_bFilterFragmentedTelegrams == bFilter) @@ -448,7 +453,7 @@ void TelegramProxyModel::setFilterTetraFragmented(bool bFilter) endFilterChange(); } - +// --------------------------------------------------------------- QSharedPointer TelegramProxyModel::telegram(int row) const { const TelegramModel *tm = qobject_cast(sourceModel()); @@ -458,7 +463,7 @@ QSharedPointer TelegramProxyModel::telegram(int row) const return tm->telegram(srcRow); } - +// --------------------------------------------------------------- bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { if (left.column() != right.column()) @@ -489,10 +494,10 @@ bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri return QSortFilterProxyModel::lessThan(left, right); } - +// --------------------------------------------------------------- bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - + // TODO: optimize const TelegramModel *tm = qobject_cast(sourceModel()); if (!tm) return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); @@ -578,4 +583,4 @@ bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &sou } return true; } -} +} // namespace N_LogView; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.hpp index 3e0419915..53ca4c133 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewModels.hpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once @@ -37,11 +42,11 @@ public: protected: void updateHeatMap() const; protected: - + // eqId , issi QVector > m_particpants; - + // eqid, count telegrams QHash m_particpantMap; - + // eqId, QColor for heatmap mutable QHash m_participantHeatmap; }; @@ -106,4 +111,4 @@ protected: std::set m_filterTetraPDU; }; -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.cpp index 59edcb395..8f0c06752 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewOptionDialog.hpp" #include @@ -28,7 +28,7 @@ namespace N_LogView { - +// static member initialization const QString LogViewOptionDialog::SPEC_FILES = tr("Spezifikations-Dateien (*.x)"); const QString LogViewOptionDialog::KRLOG_FILES = tr("Log-Dateien (*.krlog)"); const QLatin1String LogViewOptionDialog::SPEC_FILES_GROUP("SpecFiles"); @@ -44,13 +44,13 @@ const QLatin1String LogViewOptionDialog::INJECTION_HOSTNAME("InjectionHostname") const QLatin1String LogViewOptionDialog::INJECTION_PORT("InjectionPort"); - +// --------------------------------------------------------------- LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent) : QDialog(a_parent) { QVBoxLayout* layout = new QVBoxLayout(this); - + // telegram specification files m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP); QGroupBox* groupBox = new QGroupBox(tr("Telegramm-Spezifikations-Dateien"), this); layout->addWidget(groupBox); @@ -81,7 +81,7 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent) groupBox->setLayout(groupLayout); m_Settings.endGroup(); - + // injection m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP); groupBox = new QGroupBox(tr("Telegram Injection Server"), this); layout->addWidget(groupBox); @@ -102,18 +102,18 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent) groupBox->setLayout(injectLayout); m_Settings.endGroup(); - + // buttons layout->addStretch(); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, &QDialogButtonBox::accepted, this, &LogViewOptionDialog::save); connect(buttonBox, &QDialogButtonBox::rejected, this, &LogViewOptionDialog::reject); layout->addWidget(buttonBox); - + //setLayout(layout); } - +// --------------------------------------------------------------- void LogViewOptionDialog::browseP0File() { QString newFilename = QFileDialog::getOpenFileName(this, @@ -131,7 +131,7 @@ void LogViewOptionDialog::browseP0File() } - +// --------------------------------------------------------------- void LogViewOptionDialog::browseP5File() { QString newFilename = QFileDialog::getOpenFileName(this, tr("Protokollkonverter - TETRA Spezifikations-Datei"), m_Settings.value(DIR).toString(), SPEC_FILES); @@ -145,13 +145,13 @@ void LogViewOptionDialog::browseP5File() } } - +// --------------------------------------------------------------- void LogViewOptionDialog::save() { uint32_t changedFlags = 0; - - + // check group wise for changes + // specification files m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP); QString string = m_Settings.value(P0_FILENAME).toString(); if ((string != m_P0Edit->text()) || @@ -163,7 +163,7 @@ void LogViewOptionDialog::save() } m_Settings.endGroup(); - + // injection settings m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP); if ((m_Settings.value(INJECTION_HOSTNAME).toString() != m_InjectHostnameEdit->text()) || (m_Settings.value(INJECTION_PORT).toString() != m_InjectPortEdit->text())) @@ -179,4 +179,4 @@ void LogViewOptionDialog::save() accept(); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.hpp index bea0b03a4..d891bfb7a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewOptionDialog.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -20,8 +20,13 @@ class QLineEdit; namespace N_LogView { - - +/** + * This class lets the user view and change the settings of the application + * + * @author alois.wismer + * @version 1.0 + * @created 09-Mrz-2010 14:49:40 + */ class LogViewOptionDialog : public QDialog { Q_OBJECT @@ -50,12 +55,14 @@ public: static const QLatin1String INJECTION_PORT; - - + /** + * + * @param a_parent a_parent + */ explicit LogViewOptionDialog(QWidget* a_parent); signals: - void settingsChanged(uint32_t changed); + void settingsChanged(uint32_t changed); // bitfield of SettingsChangedFlag enum protected: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.cpp index 904caa08c..fce5a09c6 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewSpinBox.hpp" #include "LogViewField.hpp" @@ -17,43 +17,43 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewSpinBox::LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value) : QSpinBox(a_parent) , LogViewWidget(a_field, this, a_parent, false) { - + // set range uint16_t maxArraySize = a_field->maxArraySize(); setRange(0, maxArraySize); - + // set the actual value setValue(a_value); - + // set tooltip-text setToolTip(tr("Wertebereich: 0..%1").arg(maxArraySize)); - + // connect connect(this, &LogViewSpinBox::editingFinished, this, &LogViewSpinBox::finishEditing); } - +// --------------------------------------------------------------- void LogViewSpinBox::finishEditing() { emit valueEditingFinished(text().toInt()); } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewSpinBox::saveContent(LogViewTelegram* a_telegram) { Q_UNUSED(a_telegram); - + // not yet implemented return false; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.hpp index 8cf3d0e94..98c7fcee9 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewSpinBox.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,26 +18,41 @@ namespace N_LogView { - - + /** + * Used for changing size of dyn. arrays. + * + * @author alois.wismer + * @version 1.0 + * @created 25-Mai-2010 10:39:45 + */ class LogViewSpinBox : public QSpinBox, public LogViewWidget { Q_OBJECT public: - - + /** + * + * @param a_field + * @param a_parent + * @param a_value + */ LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value); - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; protected slots: void finishEditing(); signals: - - + /** + * + * @param a_newValue + */ void valueEditingFinished(int a_newValue); }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.cpp index 09de6be70..61b8a7352 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewTabWidget.hpp" #include @@ -36,14 +36,14 @@ LogViewTabWidget::LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog* } - +// --------------------------------------------------------------- void LogViewTabWidget::changeSize(const int a_newSize) { - + // add new tabs for (int i = count(); i < a_newSize; i++) addTab(m_Field, true, i); - + // remove old tabs while (count() > a_newSize) { QStringList path = m_Field->jsonPath(); @@ -56,19 +56,19 @@ void LogViewTabWidget::changeSize(const int a_newSize) setVisible(a_newSize > 0); - m_TelegramDialog->makePretty(); + m_TelegramDialog->makePretty(); // fixme: funktioniert so nicht, muss als signal realisiert werden } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram) { if (a_telegram->isJsonTelegram()) return true; - + // if m_SpinBox is NULL, we have a static array => no size has to be stored if (m_SpinBox) { if (!isValid()) @@ -79,7 +79,7 @@ bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram) } - +// --------------------------------------------------------------- void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx) { if (arrayIdx < 0) @@ -122,11 +122,11 @@ void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int a } m_TelegramDialog->showTree(childTree, box); - - - + // todo: sind nach dem dyn. array noch weitere Felder, so wird addTab nicht richtig funktionieren, weil die + // neuen Felder des Tabs am Ende von m_EditInfoList hinzugefügt werden => diese müssen mittendrin (an der richtigen + // position) eingefügt werden. - + // update spinbox if (m_SpinBox) { int spinValue = m_SpinBox->value(); @@ -137,4 +137,4 @@ void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int a setVisible(true); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.hpp index e4af1f644..a957a066d 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTabWidget.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -23,8 +23,13 @@ namespace N_LogView class LogViewTelegramDialog; class LogViewSpinBox; - - + /** + * Used for arrays of structures + * + * @author alois.wismer + * @version 1.0 + * @created 26-Mai-2010 17:12:30 + */ class LogViewTabWidget : public QTabWidget, public LogViewWidget { Q_OBJECT @@ -36,8 +41,10 @@ namespace N_LogView void addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx); public slots: - - + /** + * + * @param a_newSize + */ void changeSize(const int a_newSize); protected: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.cpp index 969a0d01d..2f7383408 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.cpp @@ -1,17 +1,17 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewTableWidget.hpp" #include "LogViewField.hpp" #include @@ -55,18 +55,18 @@ LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, } setAlternatingRowColors(true); - - + // make pretty +// horizontalHeader()->setResizeMode(2, QHeaderView::Stretch); updateToolTip(); - + // for debugging only +// INFO_LOG(m_logger) << "type=" << static_cast(a_field->getXdrElement())->getValueKind(); +// INFO_LOG(m_logger) << "name=" << static_cast(a_field->getXdrElement())->getName().toStdString(); +// a_field->getXdrElement()->dump(); - - - - - + // fill in the values + // fixme: implementiere den Fall isHasContent() false int nbrOfRows = a_field->valueListSize(); setRowCount(nbrOfRows); for (int i = 0; i < nbrOfRows; i++) @@ -74,20 +74,20 @@ LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, makePretty(); - + // connect signals connect(this, &LogViewTableWidget::itemChanged, this, &LogViewTableWidget::checkAndOvertakeContent); } - +// --------------------------------------------------------------- void LogViewTableWidget::changeSize(const int a_newSize) { setRowCount(a_newSize); disconnect(this, &LogViewTableWidget::itemChanged, this, &LogViewTableWidget::checkAndOvertakeContent); - + // check and set the new fields for (int i = 0; i < a_newSize; i++) changeRow(i, QLatin1String("0")); @@ -100,14 +100,14 @@ void LogViewTableWidget::changeSize(const int a_newSize) } - +// --------------------------------------------------------------- void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value) { - +// INFO_LOG(m_logger) << "a_rowIndex=" << a_rowIndex << " a_value=" << a_value.toStdString(); if (m_IsEnum) { - + // enum QWidget* enumItem = cellWidget(a_rowIndex, 0); if (!enumItem) setCellWidget(a_rowIndex, 0, new LogViewEnumEdit(m_Field, this, m_Readonly, a_rowIndex)); @@ -117,12 +117,12 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value) QFont font; font.setStyleHint(QFont::TypeWriter); font.setFamily(QString()); - + // decimal QTableWidgetItem* decItem = item(a_rowIndex, 0); if (!decItem) { decItem = new QTableWidgetItem(); - + //decItem->setData(Qt::DisplayRole, 0); decItem->setText(a_value); decItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); if (!m_Readonly) @@ -134,7 +134,7 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value) setItem(a_rowIndex, 0, decItem); } - + // hexadecimal QTableWidgetItem* hexItem = item(a_rowIndex, 1); if (!hexItem) { @@ -145,7 +145,7 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value) setItem(a_rowIndex, 1, hexItem); } - + // binary if (!m_IsFloat) { QTableWidgetItem* binItem = item(a_rowIndex, 2); @@ -159,14 +159,14 @@ void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value) } } - + // set the values checkAndOvertakeContent(decItem); makePretty(); } } - +// --------------------------------------------------------------- void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem) { if (a_changedItem->column() != 0) return; @@ -179,30 +179,30 @@ void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem int64_t intValue = 0; double floatValue = 0.0; - + // get the calculated and checked value if (m_IsFloat) floatValue = getFloat(text, (uint64_t&)intValue, ok, true); else intValue = getInteger(text, ok); - + // handle errors if (!ok) { setFocus(); - - setCurrentCell(row, 0); +// selectAll(); + setCurrentCell(row, 0); // todo: funktioniert nicht return; } - + // set the decimal value QTableWidgetItem* decField = item(row, 0); if (decField) decField->setText(QString::number(m_IsFloat ? floatValue : intValue)); - + // set the hex value QTableWidgetItem* hexField = item(row, 1); if (hexField) hexField->setText(toHex(intValue)); - + // set the binary value if (!m_IsFloat) { QTableWidgetItem* binField = item(row, 2); @@ -211,33 +211,33 @@ void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem } - +// --------------------------------------------------------------- void LogViewTableWidget::makePretty() { - + //horizontalHeader()->setResizeMode(2, QHeaderView::Stretch); resizeColumnsToContents(); resizeRowsToContents(); - - - - - - - - - - - - - + // set the height of table-widget +//// QWidget* cellWdg = tableWidget->cellWidget(0, 0); +// int showRows = 7; +// if (m_Field->getValueListSize() < (showRows-1)) +// { +// showRows = m_Field->getValueListSize()+1; +// setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +// } +// else +// { +// setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); +// } +// setFixedHeight(showRows*tableWidget->rowHeight(0)); } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram) { if (!isValid()) @@ -271,14 +271,14 @@ bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram) { arraySize = rowCount(); a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize); - + // fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren } else { - + // todo: teste mit opaque[] arraySize = m_Field->maxArraySize(); } - + // copy the data INFO_LOG(m_logger) << "arraySize=" << arraySize; for (int i = 0; i < arraySize; i++) { @@ -309,4 +309,4 @@ bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram) return true; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.hpp index 4b39794a2..5eccbef8f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTableWidget.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -19,16 +19,25 @@ namespace N_LogView { - - + /** + * Used for arrays of data (opaque) + * + * @author alois.wismer + * @version 1.0 + * @created 25-Mai-2010 09:34:24 + */ class LogViewTableWidget : public QTableWidget, public LogViewWidget { Q_OBJECT public: LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, NGL::INGLLogger& logger); - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; public slots: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.cpp index 3473c792e..2c5878a8f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewTelegram.hpp" @@ -36,7 +36,7 @@ namespace N_LogView { - +// static member initialization const LogViewXdrParser* LogViewTelegram::m_Parser = nullptr; const uint16_t LogViewTelegram::START_OFFSET_CENTRAL = 12; const uint16_t LogViewTelegram::POS_CENTRAL_COUNTER = 4; @@ -49,9 +49,9 @@ const uint16_t LogViewTelegram::START_OFFSET_TETRA_LOGIN = 27; const uint16_t LogViewTelegram::START_OFFSET_TETRA_FRAGMENT = 26; const uint16_t LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE = 4; - - - +// --------------------------------------------------------------- +// Copy ctor +// --------------------------------------------------------------- LogViewTelegram::LogViewTelegram(const LogViewTelegram &o) : m_Name(o.m_Name) , m_ToolTipText(o.m_ToolTipText) @@ -80,10 +80,10 @@ LogViewTelegram::LogViewTelegram(const LogViewTelegram &o) m_TetraTelegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(m_data); } - - - - +// --------------------------------------------------------------- +// Constructor for new telegrams (only receive central- +// telegrams are allowed), which will be edited +// --------------------------------------------------------------- LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination, int telegramId) : m_WaitTime(1000) @@ -123,9 +123,9 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv } - - - +// --------------------------------------------------------------- +// Constructor for existing telegrams +// --------------------------------------------------------------- LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination, const quint64 a_unixTime, const QByteArray &a_telegramData) @@ -152,25 +152,25 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv if (waitTime > 0) m_WaitTime = waitTime; m_ToolTipText.resize(e_ColMax); - + // log-time switch (m_Protocol) { case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls: { m_json = QJsonDocument::fromJson(a_telegramData).object(); - m_TelId = m_json.value(QLatin1String("typeId")).toInt(); - - + m_TelId = m_json.value(QLatin1String("typeId")).toInt();//getUInt32(POS_CENTRAL_TELID); +// INFO_LOG(m_logger) << "m_TelId=" << m_TelId; + //m_Name = m_Parser[m_Protocol]->getTelegramName(getTelId()); m_Name = m_json.value(QLatin1String("type")).toString(); switch (getTelId()) { case TrainingAreaBase::TetraIcd::BESTAETIGUNG: break; default: - - - + // the participant-id can not be taken out of xyData.header.identitaet without knowing the exact Wrapper, + // because in some (unclear) cases an unknown 4-byte value is on expected position (maybe some C++ alignment stuff) + //m_ParticipantId = getUInt32(POS_CENTRAL_PARTICIPANTID); m_ParticipantId = m_json.value(QLatin1String("data")) .toObject().value(QLatin1String("header")) .toObject().value(QLatin1String("equipmentNumber")).toInt(); @@ -182,7 +182,7 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra: { m_TetraTelegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(m_data); - +// NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Info, m_Data, m_Size); switch (m_TetraTelegram->getPDU_Type()) { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd: @@ -201,29 +201,29 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv } else if (m_TetraTelegram->isNormalTelegram()) { - + // unfragmented telegram m_TelId = m_TetraTelegram->getTelID(); m_Name = tetraParser()->getTelegramName(m_TelId); m_ParticipantId = m_TetraTelegram->getIdentity(); - + // get the GPS-time if (getDirection() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend) { - - uint16_t gpsTimeOffset = 2; + // fixme: mache dies konfigurierbar + uint16_t gpsTimeOffset = 2; // without telID switch (m_TelId) { case GEF_DEAKTIVIERUNG_EINZELMINE: - gpsTimeOffset = 4; + gpsTimeOffset = 4; // without telID break; default: - gpsTimeOffset = 2; + gpsTimeOffset = 2; // without telID } m_GpsTime = getUInt32(START_OFFSET_TETRA_DATA+gpsTimeOffset); } } else { - + // fragmented telegram switch (m_TetraTelegram->getFragmentStatus()) { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment: @@ -232,18 +232,18 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv break; case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment: m_Name = QObject::tr("%1.-letztes Fragment eines TETRA-Telegrammes").arg(m_TetraTelegram->getFragmentCounter()+1); - + // fixme: get participantid over ISSI break; case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment: m_Name = QObject::tr("Letztes Fragment eines TETRA-Telegrammes"); - + // fixme: get participantid over ISSI break; default: m_Name = QObject::tr("TETRA-Telegramm mit Fragment-Status=%1 ist nicht implementiert").arg(m_TetraTelegram->getFragmentStatus()); break; } } - + // set the ISSI if ((m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask) == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive) { m_ISSI = m_TetraTelegram->getDestISSI(); @@ -272,9 +272,11 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv break; default: - - - + // Commented because of annoying message for Type 240 + /* QMessageBox::warning(NULL, + QObject::tr("Unknown PDU-Type"), + QObject::tr("Handling for TETRA-Telegram mit PDU-Type=%1 is not implemented!").arg(m_TetraTelegram->getPDU_Type())); + */ m_Name = QObject::tr("PDU-Type=%1").arg(m_TetraTelegram->getPDU_Type()); break; } @@ -294,20 +296,20 @@ LogViewTelegram::~LogViewTelegram() delete m_TetraTelegram; } - - - - - - - +// --------------------------------------------------------------- +// Writes a_value with size a_size at actual position of +// m_Data (given with m_ActOffset). m_ActOffset will be +// updated after writing data. +// If the size of m_Data is not big enough, it will be made +// bigger. +// --------------------------------------------------------------- void LogViewTelegram::setUIntX(const uint8_t a_size, quint64 a_value, const LogViewXdrStandardType::E_ByteOrder a_byteOrder) { - + // check whether m_Data is big enough if (m_ActOffset + a_size > m_data.size()) m_data.resize(m_ActOffset + a_size); - + // write the data if (a_byteOrder == LogViewXdrStandardType::e_ByteOrderBigEndian) { for (int i = a_size - 1; i >= 0; i--) @@ -328,11 +330,11 @@ void LogViewTelegram::setUIntX(const uint8_t a_size, quint64 a_value, const LogV } - - - - - +// --------------------------------------------------------------- +// Returns true if a_data could be written. +// Returns false if a_offset is outside of range and therefore +// a_data could not be written. +// --------------------------------------------------------------- bool LogViewTelegram::setData(const uint16_t a_offset, const uint8_t a_data) { if (a_offset < m_data.size()) @@ -351,10 +353,10 @@ quint64 LogViewTelegram::getLogTimeMsec() const return (logTimeSec * 1000 + logTimeMicroSec / 1000); } - - - - +// --------------------------------------------------------------- +// Returns the log-time of the telegram as pretty formatted +// text +// --------------------------------------------------------------- QString LogViewTelegram::getLogTimeText() const { if (m_logTimeText.isEmpty()) @@ -365,7 +367,7 @@ QString LogViewTelegram::getLogTimeText() const return m_logTimeText; } - +// --------------------------------------------------------------- QString LogViewTelegram::getDestinationText() const { auto protocol = static_cast @@ -414,11 +416,11 @@ QString LogViewTelegram::getDestinationText() const } - - - - - +// --------------------------------------------------------------- +// Returns the GPS-time of the telegram as pretty formatted +// text. Only telegrams from TETRA to central have a GPS-time, +// for all other telegrams an empty string will be returned. +// --------------------------------------------------------------- QString LogViewTelegram::getGpsTimeText() const { if (m_GpsTime != 0) @@ -428,13 +430,13 @@ QString LogViewTelegram::getGpsTimeText() const } - - - - - - - +// --------------------------------------------------------------- +// Returns the difference between GPS-time and log-time in +// seconds. Only telegrams from TETRA to central have a GPS- +// time (and therefore only for this telegrams a time- +// difference can be calculated), for all other telegrams 0 +// will be returned. +// --------------------------------------------------------------- int32_t LogViewTelegram::getDelay() const { if (m_GpsTime != 0) @@ -446,11 +448,11 @@ int32_t LogViewTelegram::getDelay() const } - - - - - +// --------------------------------------------------------------- +// Returns the tool-tip text for the with a_col defined column +// for this telegram. Its content depends on the type and +// subtype of telegram. +// --------------------------------------------------------------- QString LogViewTelegram::getToolTipText(const E_Column a_col) { if (a_col < e_ColMax) @@ -466,7 +468,7 @@ QString LogViewTelegram::getToolTipText(const E_Column a_col) } if(a_col == e_ColGpsTime && m_ToolTipText[e_ColGpsTime].isNull()) { if(m_GpsTime == 0) { - m_ToolTipText[e_ColGpsTime] = QLatin1String(""); + m_ToolTipText[e_ColGpsTime] = QLatin1String(""); // wichtig damit isNull() false ist! } else { const QDateTime dtGpsTime(QDateTime::fromMSecsSinceEpoch(m_GpsTime * 1000LL)); m_ToolTipText[e_ColGpsTime] = QStringLiteral("%1
Unixzeit: %2 0x%3") @@ -481,7 +483,7 @@ QString LogViewTelegram::getToolTipText(const E_Column a_col) } - +// --------------------------------------------------------------- void LogViewTelegram::createToolTipTextForColName() { switch (m_Protocol) @@ -490,7 +492,7 @@ void LogViewTelegram::createToolTipTextForColName() case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls: { const QString jsonStr = QString::fromUtf8(QJsonDocument(m_json).toJson(QJsonDocument::JsonFormat::Indented)); - + // set the tool-tip-text m_ToolTipText[e_ColName] = QLatin1String("") + formatToolTipLine(QObject::tr("Telegram Id"), getTelId()) + formatToolTipLine(QObject::tr("Counter"), getUInt32(POS_CENTRAL_COUNTER)) @@ -505,7 +507,7 @@ void LogViewTelegram::createToolTipTextForColName() switch (m_TetraTelegram->getPDU_Type()) { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd: - + // set the tool-tip-text m_ToolTipText[e_ColName] = QLatin1String("
") + formatToolTipLine(QObject::tr("Host ISSI"), m_TetraTelegram->getSrcISSI()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) @@ -612,7 +614,7 @@ uint32_t LogViewTelegram::floatToXdr(float in) } - +// --------------------------------------------------------------- void LogViewTelegram::resetOffset() { switch (m_Protocol) @@ -626,10 +628,10 @@ void LogViewTelegram::resetOffset() } - +// --------------------------------------------------------------- LogViewField* LogViewTelegram::getFieldTree() { - +// INFO_LOG(m_logger) << "type=" << getStructName().toStdString(); switch (m_Protocol) { case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral: @@ -668,11 +670,11 @@ LogViewField* LogViewTelegram::getFieldTree() structName = getStructName(); if (structName == QLatin1String("gef_automatic_conversion_rt")) { - + // use the central-structure for telegrams which information on tetra and central-side are identical auto centralTelegram = N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(m_TetraTelegram); if (centralTelegram) { - + // create a temporary central-telegram for getting the field-tree LogViewTelegram* tmpCentralTelegram = new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral, m_LogTime, centralTelegram->data()); @@ -684,14 +686,14 @@ LogViewField* LogViewTelegram::getFieldTree() } else { - + // conversion to central-telegram was not successful => use tetra-structure m_ActOffset = START_OFFSET_TETRA_DATA; structName = getStructName(); } } else { - + // fragmented telegram switch (m_TetraTelegram->getFragmentStatus()) { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment: @@ -728,7 +730,7 @@ LogViewField* LogViewTelegram::getFieldTree() break; default: - m_ActOffset = 0; + m_ActOffset = 0; // data begins at 0 structName = QLatin1String("TETRA_unknown_PDU_rt"); break; } @@ -819,7 +821,7 @@ void LogViewTelegram::addFieldTreeStruct(const QJsonObject &parentObject, { xdr = new LogViewXdrStruct(mi.name, LogViewXdrElement::e_KindEnum, 16); } - else + else // isPod { const PodInformation pod = jsonParser()->podFromType(innerType); @@ -848,9 +850,9 @@ void LogViewTelegram::addFieldTreeStruct(const QJsonObject &parentObject, const QString path(QStringLiteral("index: %1")); if (isStruct) { - auto si = parser->structFromType(mi.type); + auto si = parser->structFromType(mi.type); // custom struct if (si.type.isEmpty()) - si = parser->structFromType(innerType); + si = parser->structFromType(innerType); // pod? for (int i = 0; i < arr.size(); ++i) { LogViewField *tc = new LogViewField(mi.name + QStringLiteral("TabChild"), LogViewField::e_FieldKindTabChild, xdr); @@ -871,7 +873,7 @@ void LogViewTelegram::addFieldTreeStruct(const QJsonObject &parentObject, } else { - + // assume string for (int i = 0; i < arr.size(); ++i) addFieldTreeJsonString(arr.at(i), f, QString(), false, path.arg(i), LogViewField::e_FieldKindPodArrayChild, logger); } @@ -880,7 +882,7 @@ void LogViewTelegram::addFieldTreeStruct(const QJsonObject &parentObject, } } - +// --------------------------------------------------------------- void LogViewTelegram::addFieldTreeJsonString(const QJsonValue &val, LogViewField *parent, const QString &name, @@ -907,7 +909,7 @@ void LogViewTelegram::addFieldTreeJsonString(const QJsonValue &val, parent->addChild(f); } - +// --------------------------------------------------------------- void LogViewTelegram::addFieldTreeJsonPod(const QJsonValue &val, LogViewField *parent, const QString &name, @@ -943,7 +945,7 @@ void LogViewTelegram::addFieldTreeJsonPod(const QJsonValue &val, parent->addChild(f); } - +// --------------------------------------------------------------- void LogViewTelegram::addFieldTreeJsonEnum(const QJsonValue &val, LogViewField *parent, const QString &name, @@ -984,13 +986,13 @@ void LogViewTelegram::addFieldTreeJsonEnum(const QJsonValue &val, } - +// --------------------------------------------------------------- QString LogViewTelegram::typeFromStructInformation(const StructInformation &si, const QString &name) { return memberFromStructInformation(si, name).type; } - +// --------------------------------------------------------------- MemberInformation LogViewTelegram::memberFromStructInformation(const StructInformation &si, const QString &name) { for(const MemberInformation &mi : si.member) @@ -1001,7 +1003,7 @@ MemberInformation LogViewTelegram::memberFromStructInformation(const StructInfor return {}; } - +// --------------------------------------------------------------- LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString& a_name, uint16_t a_arraySize, const LogViewXdrType* a_parentElement, const bool a_hasContent) { DEBUG_LOG(m_logger) << "a_type=" << a_type << " a_name=" << a_name << " a_arraySize=" << a_arraySize; @@ -1009,32 +1011,32 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString if (!xdrElement) return nullptr; - - + // xdrElement->dump(); + //INFO_LOG(m_logger) << "name=" << xdrElement->getName().toStdString() << " type=" << xdrElement->getType().toStdString() << " value=" << xdrElement->getValue() << " kind=" << xdrElement->getKind() << " hasChilds=" << xdrElement->hasChilds() << " arraySize=" << xdrElement->getArraySize(); uint16_t maxArraySize = 0; LogViewField* fieldTree = nullptr; switch (xdrElement->getKind()) { case LogViewXdrElement::e_KindStruct: { - + // add tab for arrays or border for normal structure if (a_arraySize == 1) { - + // border for normal structure fieldTree = new LogViewField(a_name, LogViewField::e_FieldKindBorder, xdrElement); } else { - + // static or dynamic array of structures => make tabs fieldTree = new LogViewField(a_name, LogViewField::e_FieldKindTab, xdrElement); if (0 != a_arraySize) { - + // static array of structures fieldTree->setMaxArraySize(0, false); } } - + // add the childs as struct-elements uint32_t i = 0; while (LogViewXdrType* child = static_cast(xdrElement)->getChildAsType(i++)) { @@ -1048,28 +1050,28 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString } else { - + // do not iterate scalar types if (isScalar(child)) { arraySize = 1; } m_MaxArraySize = child->getMaxArraySize(); } - + // INFO_LOG(m_logger) << "struct-element: name=" << child->getName().toStdString() << " arraySize=" << arraySize << " maxArraySize=" << m_DynArrayOffset; - + // handle specialcase: dyn. array of structures with actual count of 0 elements if (0 == arraySize) { LogViewField* field = getFieldTree(child->getType(), child->getName(), child->getArraySize(), child); field->setHasContent(false); - if (isDynArray) field->setMaxArraySize(child->getMaxArraySize(), true); + if (isDynArray) field->setMaxArraySize(child->getMaxArraySize(), true); // fixme: kommt weiter unten nochmals fieldTree->addChild(field); } - + // now the normal-case begins for (int k=0; kgetType(), child->getName(), child->getArraySize(), child); - if (isDynArray) field->setMaxArraySize(child->getMaxArraySize(), true); + LogViewField* field = getFieldTree(child->getType(), /*childName*/child->getName(), child->getArraySize(), child); + if (isDynArray) field->setMaxArraySize(child->getMaxArraySize(), true); // fixme: kommt weiter oben auch schon fieldTree->addChild(field); } } @@ -1077,23 +1079,23 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString } case LogViewXdrElement::e_KindTypedef: - - if (a_arraySize != 0) + // get the size of the element (with iterating down until we get a standard-type) + if (a_arraySize != 0) // fixme: dies wird nur bei dyn. arrays von skalaren typen funktionieren { - + // INFO_LOG(m_logger) << "typedef statisch"; a_arraySize = static_cast(xdrElement)->getArraySize(); } else { - + // fixme INFO_LOG(m_logger) << "typedef dynamisch"; } - maxArraySize = static_cast(xdrElement)->getMaxArraySize(); + maxArraySize = static_cast(xdrElement)->getMaxArraySize(); // fixme: vielleicht funktioniert das nicht in allen Fällen, funktioniert für allgemeine_nachricht while (xdrElement->getKind() != LogViewXdrElement::e_KindStandardType) { xdrElement = tetraParser()->getElement(static_cast(xdrElement)->getType()); - - + // xdrElement->dump(); + // INFO_LOG(m_logger) << "====> typedef name=" << a_name.toStdString() << " type=" << a_type.toStdString() << " a_arraySize=" << a_arraySize << " xdr.name=" << xdrElement->getName().toStdString() << " xdr.isLeaf=" << xdrElement->isLeaf() << " kind=" << xdrElement->getKind(); if (LogViewXdrElement::e_KindEnum == xdrElement->getKind()) { return getFieldTree(xdrElement->getName(), a_name, a_arraySize); @@ -1102,7 +1104,7 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString Q_FALLTHROUGH(); case LogViewXdrElement::e_KindStandardType: { - + //INFO_LOG(m_logger) << "standardtype: add edit-field a_name=" << a_name.toStdString() << " a_arraySize=" << a_arraySize << " maxArraySize=" << maxArraySize << " m_DynArrayOffset=" << m_DynArrayOffset << " <==========================="; if (a_hasContent) { fieldTree = getContent(static_cast(xdrElement), m_ActOffset, a_arraySize); @@ -1112,17 +1114,17 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString { fieldTree = new LogViewField(a_name, LogViewField::e_FieldKindEdit, xdrElement); fieldTree->setHasContent(false); - + // todo: mache test mit telegramm, welches ein dyn. array von strukture mit anzahl 0 enthält (z.B. statistik-nachforderung mit 0 teilnehmern) } - + // set the maximal size of array: static arrays => a_arraySize; dyn. arrays => maxArraySize if (0 == a_arraySize) { - + // dynamic array fieldTree->setMaxArraySize(0 == maxArraySize ? m_MaxArraySize : maxArraySize, true); } else { - + // static array or no array (== [1]) fieldTree->setMaxArraySize(a_arraySize, false); } break; @@ -1130,7 +1132,7 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString case LogViewXdrElement::e_KindEnum: { - + // evaluate the size uint16_t size = static_cast(xdrElement)->getEnumSize(); uint16_t arraySize = a_arraySize; if (0 == arraySize) @@ -1146,51 +1148,51 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString tooltipText = QStringLiteral("%1 0x%2 0b%3").arg(enumValue) .arg(enumValue, 2, 16, QLatin1Char('0')) .arg(enumValue, 8, 2, QLatin1Char('0')); - + // only for Tetra and not for arrays: mask out unneeded bits (used for different bitfields within one value) if (a_parentElement) { isLast = a_parentElement->maskValue(enumValue, size, tooltipText); } } - + // allocate a new field fieldTree = new LogViewField(a_name, LogViewField::e_FieldKindEdit, xdrElement); fieldTree->setToolTipText(tooltipText); - + // get the enums for (int i=0; imaskValue(enumValue, size, tmp); - + // get the enum-text QString enumText = QStringLiteral("<%1>").arg(enumValue); int j=0; while (LogViewXdrValue* child = (static_cast(xdrElement))->getChildAsValue(j++)) { - + //INFO_LOG(m_logger) << "child name=" << child->getName().toStdString() << " type=" << child->getType().toStdString() << " value=" << child->getValue(); if (child->getValue() == enumValue) { enumText = LogViewField::makeClean(child->getName()); break; } } - + // add the enum-array-element fieldTree->addValue(enumText); if (isLast) m_ActOffset += size; } - + // set the maximal size of array: static arrays => a_arraySize; dyn. arrays => maxArraySize if (0 == a_arraySize) { - + // dynamic array fieldTree->setMaxArraySize(0 == maxArraySize ? m_MaxArraySize : maxArraySize, true); } else { - + // static array or no array (== [1]) fieldTree->setMaxArraySize(a_arraySize, false); } break; @@ -1202,15 +1204,15 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString } - +// --------------------------------------------------------------- void LogViewTelegram::dump() const { - + //INFO_LOG(m_logger) << "m_ActOffset=" << m_ActOffset; NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Info, m_data.data(), m_data.size()); } - +// --------------------------------------------------------------- QString LogViewTelegram::getStructName() const { return isJsonTelegram() ? jsonParser()->nameFromTelegramId(getTelId()) @@ -1218,31 +1220,31 @@ QString LogViewTelegram::getStructName() const } - +// --------------------------------------------------------------- uint16_t LogViewTelegram::getUInt16(const uint16_t a_offset) const { return (uint16_t)getUIntX(a_offset, 2); } - +// --------------------------------------------------------------- uint32_t LogViewTelegram::getUInt32(const uint16_t a_offset) const { return getUIntX(a_offset, 4); } - +// --------------------------------------------------------------- int32_t LogViewTelegram::getInt32(const uint16_t a_offset) const { return getUInt32(a_offset); } - +// --------------------------------------------------------------- quint64 LogViewTelegram::getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder) const { - quint64 factor = 1; + quint64 factor = 1; // used for little endian quint64 value = getData(a_offset); for (int i=1; i(m_TetraTelegram->getData()[0]); if (magicNumber != 0xA5) { @@ -1321,7 +1323,7 @@ bool LogViewTelegram::isValid() m_Validity = e_Invalid; return false; } - + // check telegram-length int length = m_TetraTelegram->getSize(); if (length != m_data.size()) { @@ -1347,27 +1349,27 @@ bool LogViewTelegram::isValid() } - +// --------------------------------------------------------------- LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize) { +// INFO_LOG(m_logger) << "name=" << a_standardType->getName() << " valueKind=" << a_standardType->getValueKind() << " valueSize=" << a_standardType->getValueSize() << " a_offset=" << a_offset << " a_arraySize=" << a_arraySize; - - + // allocate a new field LogViewField* field = new LogViewField(QString(), LogViewField::e_FieldKindEdit, a_standardType); field->setIsRightAligned(false); - + // evaluate the size const int size = a_standardType->getValueSize(); field->setSize(size); uint16_t arraySize = a_arraySize; if (0 == arraySize) arraySize = getDynArraySize(a_offset); - +// INFO_LOG(m_logger) << "name=" << a_standardType->getName().toStdString() << " size=" << size << " arraySize=" << arraySize; switch (a_standardType->getValueKind()) { case LogViewXdrStandardType::e_Unsigned: - + // get the values { const LogViewXdrStandardType::E_ByteOrder byteOrder = a_standardType->getByteOrder(); uint32_t value = 0; @@ -1376,14 +1378,14 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa value = getUIntX(i*size+a_offset, size, byteOrder); field->addValue(QString::number(value)); } - + // generate the tool-tip-text if (arraySize <= 1) { if (a_standardType->getDynArraySizeMethod() == LogViewXdrStandardType::e_DynArrayIndex || a_standardType->getDynArraySizeMethod() == LogViewXdrStandardType::e_DynArrayIndexDiv8) { m_DynArraySizeMethod = a_standardType->getDynArraySizeMethod(); - m_LastUnsignedValue = value; + m_LastUnsignedValue = value; // used for dyn. array in TETRA-Protocol } } field->setIsRightAligned(true); @@ -1391,7 +1393,7 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa break; case LogViewXdrStandardType::e_Signed: - + // get the signed values { const LogViewXdrStandardType::E_ByteOrder byteOrder = a_standardType->getByteOrder(); for (int i = 0; i < arraySize; i++) @@ -1404,7 +1406,7 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa break; case LogViewXdrStandardType::e_Float: - + // get the floating-point value { const LogViewXdrStandardType::E_ByteOrder byteOrder = a_standardType->getByteOrder(); for (int i = 0; i < arraySize; i++) @@ -1418,12 +1420,12 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa INFO_LOG(m_logger) << "value=" << xdrToFloat(value); } } - field->setIsRightAligned(true); + field->setIsRightAligned(true); // fixme: vielleicht wird isRightAligned gar nicht benötigt... } break; case LogViewXdrStandardType::e_Character: - + // generate the text { QByteArray text; for (int i = 0; i < arraySize; i++) @@ -1438,7 +1440,7 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa break; case LogViewXdrStandardType::e_Data: - + // generate the data-field for (int i = 0; i < arraySize; i++) field->addValue(QString::number(getData(a_offset+i))); break; @@ -1449,14 +1451,14 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa } uint16_t sizeOfContent = arraySize * size; a_offset += sizeOfContent; - + // dynamic arrays must have an overall size which is 4-byte aligned if (0 == a_arraySize) { uint16_t rest = sizeOfContent % 4; if (0 != rest) { a_offset += (4 - rest); - +// INFO_LOG(m_logger) << "align offset to " << a_offset << " because it was an dyn. array content."; } } @@ -1464,13 +1466,13 @@ LogViewField* LogViewTelegram::getContent(const LogViewXdrStandardType* a_standa } - +// --------------------------------------------------------------- N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol LogViewTelegram::getDirection() const { return static_cast(m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask); } - +// --------------------------------------------------------------- void LogViewTelegram::setJsonValue(const QStringList &path, const QJsonValue &val) { m_data.clear(); @@ -1481,7 +1483,7 @@ void LogViewTelegram::setJsonValue(const QStringList &path, const QJsonValue &va .toObject().value(QLatin1String("equipmentNumber")).toInt(); } - +// --------------------------------------------------------------- void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonObject &obj) { if (path.isEmpty()) @@ -1515,7 +1517,7 @@ void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue } } - +// --------------------------------------------------------------- void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonArray &arr) { if (path.isEmpty()) @@ -1544,7 +1546,7 @@ void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue } } - +// --------------------------------------------------------------- QIcon LogViewTelegram::getIcon() const { static const QIcon c2p(QLatin1String(":/image/C2P.png")); @@ -1598,7 +1600,7 @@ QIcon LogViewTelegram::getIcon() const return unk; } - +// --------------------------------------------------------------- bool LogViewTelegram::isScalar(const LogViewXdrType* a_xdrType) const { const LogViewXdrElement* xdrElement = tetraParser()->getElement(a_xdrType->getType()); @@ -1613,8 +1615,10 @@ bool LogViewTelegram::isScalar(const LogViewXdrType* a_xdrType) const return false; case LogViewXdrElement::e_KindTypedef: return isScalar(static_cast(xdrElement)); - - + /* + e_KindStructElement, + e_KindEnumElement, + e_KindDefine*/ default: ERROR_LOG(m_logger) << "name=" << xdrElement->getName().toStdString() << " kind=" << xdrElement->getKind() << " case not implemented!"; return false; @@ -1624,7 +1628,7 @@ bool LogViewTelegram::isScalar(const LogViewXdrType* a_xdrType) const } - +// --------------------------------------------------------------- void LogViewTelegram::showMessageBox(const QString& a_errorText, const QString& a_title) const { quint64 logTimeSec = m_LogTime >> 32; @@ -1638,7 +1642,7 @@ void LogViewTelegram::showMessageBox(const QString& a_errorText, const QString& } - +// --------------------------------------------------------------- uint16_t LogViewTelegram::getDynArraySize(uint16_t& a_offset) const { uint16_t arraySize; @@ -1660,7 +1664,7 @@ uint16_t LogViewTelegram::getDynArraySize(uint16_t& a_offset) const } else { - + // dynamic array => get the next 4 bytes, which contain the lengths of the dynamic array arraySize = getUIntX(a_offset, SIZE_CENTRAL_DYN_ARRAY_SIZE); a_offset += SIZE_CENTRAL_DYN_ARRAY_SIZE; } @@ -1668,7 +1672,7 @@ uint16_t LogViewTelegram::getDynArraySize(uint16_t& a_offset) const } - +// --------------------------------------------------------------- QString LogViewTelegram::formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value) { static const QString s1(QLatin1String("")); @@ -1681,31 +1685,31 @@ QString LogViewTelegram::formatToolTipLine(const QString& a_name, const QString& } - +// --------------------------------------------------------------- const N_CoPrtCnv::CoPrtCnvRadioTelegram* LogViewTelegram::getTetraTelegram() const { return m_TetraTelegram; } - +// --------------------------------------------------------------- LogViewTetraTelegramsParser *LogViewTelegram::jsonParser() { static LogViewTetraTelegramsParser s_parser; return &s_parser; } - +// --------------------------------------------------------------- LogViewXdrParser *LogViewTelegram::tetraParser() { static LogViewXdrParser s_parser; return &s_parser; } - - - - +// --------------------------------------------------------------- +// returns the data-byte at a_offset. Returns 0 if a_offset is +// outside of range. +// --------------------------------------------------------------- uint8_t LogViewTelegram::getData(const uint16_t a_offset) const { if (a_offset < m_data.size()) @@ -1714,7 +1718,7 @@ uint8_t LogViewTelegram::getData(const uint16_t a_offset) const return 0; } - +// --------------------------------------------------------------- QByteArray LogViewTelegram::getData(QJsonDocument::JsonFormat format) const { if (m_data.isEmpty() && !m_json.isEmpty()) @@ -1724,13 +1728,13 @@ QByteArray LogViewTelegram::getData(QJsonDocument::JsonFormat format) const } - +// --------------------------------------------------------------- void LogViewTelegram::setNextFieldAsGpsTimeField() { m_GpsFieldOffset.append(m_ActOffset); } - +// --------------------------------------------------------------- void LogViewTelegram::actualizeGpsTime() { if (m_GpsFieldOffset.size() > 0) @@ -1741,7 +1745,7 @@ void LogViewTelegram::actualizeGpsTime() for (QVector::const_iterator i = m_GpsFieldOffset.cbegin(); i < m_GpsFieldOffset.cend(); ++i) { m_ActOffset = *i; - setUIntX(4, ::time(nullptr)); + setUIntX(4, ::time(nullptr)); // todo nicht 4 sondern size des typs } m_ActOffset = savedOffset; } @@ -1766,4 +1770,4 @@ void LogViewTelegram::actualizeGpsTime() } } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.hpp index e9a1de161..4f93e04f7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegram.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -32,14 +32,29 @@ namespace N_LogView class LogViewTetraTelegramsParser; class LogViewXdrParser; class LogViewXdrType; - - + /** + * The header and the data of a logged or a edited telegram. + * + * Writing telegrams: + * 1. allocate a telegram with the constructor LogViewTelegram(N_CoPrtCnv:: + * CoPrtCnvLogHeader::e_DestProtocolCentral, telegramId) + * 2. prepare with resetOffset() + * 3. write data with setUIntX() + * 4. finish with setNewSize(); + * + * @author alois.wismer + * @version 1.0 + * @created 04-Feb-2010 13:15:43 + */ class LogViewTelegram final { public: - - + /** + * @author alois.wismer + * @version 1.0 + * @created 12-Mrz-2010 11:04:14 + */ enum E_Validity { e_NotYetEvaluated, @@ -47,8 +62,11 @@ namespace N_LogView e_Invalid }; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 05-Mai-2010 09:07:22 + */ enum E_Column { e_ColName, @@ -61,55 +79,88 @@ namespace N_LogView ~LogViewTelegram(); - - + /** + * The size of the field which defines the size of the dyn. array for central- + * telegrams + */ static const uint16_t SIZE_CENTRAL_DYN_ARRAY_SIZE; - - + /** + * Copy ctor + */ LogViewTelegram(const LogViewTelegram &o); - + // no assignment (needed) LogViewTelegram &operator=(const LogViewTelegram &o) = delete; - - + /** + * Constructor for new telegrams (only receive central-telegrams are allowd), + * which will be edited + * + * @param a_destination + * @param a_telId + */ LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination, int telegramId); - - + /** + * Constructor for existing telegrams + * + * @param a_destination + * @param a_unixTime + * @param a_telegramData + * @param a_telegramSize + */ LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination, const quint64 a_unixTime, const QByteArray &a_telegramData); - - + /** + * Writes a_value with size a_size at actual position of m_Data (given with + * m_ActOffset). m_ActOffset will be updated after writing data. + * If the size of m_Data is not big enough, it will be made bigger. + * + * @param a_size + * @param a_value + * @param a_byteOrder + */ void setUIntX(const uint8_t a_size, quint64 a_value, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian); - - + /** + * Returns true if a_data could be written. + * Returns false if a_offset is outside of range and therefore a_data could not be + * written. + * + * @param a_offset + * @param a_data + */ bool setData(const uint16_t a_offset, const uint8_t a_data); - - + /** + * Returns the log-time of the telegram + */ quint64 getLogTime() const { return m_LogTime; } quint64 getLogTimeMsec() const; - - + /** + * Returns the log-time of the telegram as pretty formatted text + */ QString getLogTimeText() const; QString getDestinationText() const; - - + /** + * Returns the gps-time of the telegram + */ quint64 getGpsTime() const { return m_GpsTime; } - - + /** + * Returns the GPS-time of the telegram as pretty formatted text. Only telegrams + * from TETRA to central have a GPS-time, for all other telegrams an empty string + * will be returned. + */ QString getGpsTimeText() const; @@ -118,12 +169,19 @@ namespace N_LogView int getParticipantId() const { return m_ParticipantId; } - - + /** + * Returns the difference between GPS-time and log-time in seconds. Only telegrams + * from TETRA to central have a GPS-time (and therefore only for this telegrams a + * time-difference can be calculated), for all other telegrams 0 will be returned. + */ int32_t getDelay() const; - - + /** + * Returns the tool-tip text for the with a_col defined column for this telegram. + * Its content depends on the type and subtype of telegram. + * + * @param a_col + */ QString getToolTipText(const E_Column a_col); @@ -172,20 +230,28 @@ namespace N_LogView QByteArray getData(QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Compact) const; - - + /** + * The time to wait after sending this telegram in milliseconds. + */ uint32_t getWaitTime() const { return m_WaitTime; } - - + /** + * The time to wait after sending this telegram in milliseconds. + * + * @param newVal + */ void setWaitTime(uint32_t newVal) { m_WaitTime = newVal; } - - + /** + * The name of the telegram, shown in edit-list + */ QString getName() const { return m_Name; } - - + /** + * The name of the telegram, shown in edit-list + * + * @param newVal + */ void setName(const QString &newVal) { m_Name = newVal; } @@ -197,8 +263,9 @@ namespace N_LogView void actualizeGpsTime(); - - + /** + * Create the tooltip text for the column 'Name' + */ void createToolTipTextForColName(); @@ -209,31 +276,40 @@ namespace N_LogView protected: - - + /** + * The name of the telegram, shown in edit-list + */ QString m_Name; - - + /** + * The tooltip text for caching purposes + */ std::vector m_ToolTipText; - - + /** + * The time to wait after sending this telegram in milliseconds. + */ uint32_t m_WaitTime; int m_ParticipantId; - - + /** + * The ISSI of TETRA-Protocol + */ uint32_t m_ISSI; - - + /** + * The allocated size of m_Data. (Used for optimizing of speed) + */ int m_AllocatedSize; static const LogViewXdrParser* m_Parser; uint16_t m_ActOffset; QVector m_GpsFieldOffset; int m_TelId; - - + /** + * used for dyn. array in TETRA-Protocol + */ uint32_t m_LastUnsignedValue; - - + /** + * This value will be used for the dyn-array-method e_DynArrayMsgLength. This + * value will be subtracted from the message-length to get the size of the dynamic + * array. + */ uint16_t m_MaxArraySize; static const uint16_t START_OFFSET_CENTRAL; static const uint16_t POS_CENTRAL_COUNTER; @@ -302,55 +378,90 @@ namespace N_LogView static QString typeFromStructInformation(const StructInformation &si, const QString &name); static MemberInformation memberFromStructInformation(const StructInformation &si, const QString &name); - - + /** + * + * @param a_offset + */ uint16_t getUInt16(const uint16_t a_offset) const; - - + /** + * + * @param a_offset + */ uint32_t getUInt32(const uint16_t a_offset) const; - - + /** + * + * @param a_offset + */ int32_t getInt32(const uint16_t a_offset) const; - - + /** + * + * @param a_offset + * @param a_size + * @param a_byteOrder + */ quint64 getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const; - - + /** + * + * @param a_offset + * @param a_size + * @param a_byteOrder + */ int32_t getSIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const; - - + /** + * + * @param a_offset + * @param a_size + */ char getChar(const uint16_t a_offset, const uint8_t a_size) const; - - + /** + * + * @param a_standardType + * @param a_offset + * @param a_arraySize + */ LogViewField* getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize); - - + /** + * + * @param a_xdrType + */ bool isScalar(const LogViewXdrType* a_xdrType) const; - - + /** + * + * @param a_errorText + * @param a_title + */ void showMessageBox(const QString& a_errorText, const QString& a_title = QObject::tr("Invalid telegram")) const; - - + /** + * + * @param a_offset + */ uint16_t getDynArraySize(uint16_t& a_offset) const; - - + /** + * + * @param a_name + * @param a_value + */ static QString formatToolTipLine(const QString& a_name, const uint32_t a_value) { return formatToolTipLine(a_name, QString::number(a_value), a_value); } - - + /** + * + * @param a_name + * @param a_text + * @param a_value + */ static QString formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value); static QString formatToolTipLine(const QString& a_name, const std::string& a_text, const uint32_t a_value) @@ -358,8 +469,11 @@ namespace N_LogView return formatToolTipLine(a_name, QString::fromStdString(a_text), a_value); } - - + /** + * returns the data-byte at a_offset. Returns 0 if a_offset is outside of range. + * + * @param a_offset + */ uint8_t getData(const uint16_t a_offset) const; private: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.cpp index 2a0d3acc4..67aa056a1 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewTelegramDialog.hpp" #include @@ -42,6 +42,9 @@ namespace N_LogView { +// todo: +// - feld einfärben wenn geändert, wenn falsch +// - mache hartcodierte oder konfigurierbare ranges für spezielle Werte wie GPS-Position: signed 24-bit @@ -55,7 +58,7 @@ LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_rea setAttribute(Qt::WA_DeleteOnClose); } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showDialog(const QSharedPointer &a_telegram) { delete layout(); @@ -71,13 +74,13 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer &a_ QGridLayout *dialogLayout = new QGridLayout; if (!m_ReadOnly) { - + // edit wait-time QLabel *waitTimeLabel = new QLabel(tr("Wartezeit [ms]"), this); dialogLayout->addWidget(waitTimeLabel, dialogLayout->rowCount(), 0); m_WaitTimeEdit = new QLineEdit(QString::number(a_telegram->getWaitTime()), this); dialogLayout->addWidget(m_WaitTimeEdit, dialogLayout->rowCount() - 1, 1); - + // edit name QLabel *nameLabel = new QLabel(tr("Name"), this); dialogLayout->addWidget(nameLabel, dialogLayout->rowCount(), 0); m_NameEdit = new QLineEdit(a_telegram->getName(), this); @@ -89,16 +92,16 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer &a_ dialogLayout->addWidget(f, dialogLayout->rowCount(), 0, 1, 2); } - - + //INFO_LOG(m_logger) << "--------------- create dialog " << fieldTree->getName().toStdString() << "--------------"; + //m_fieldTree->dump(); showTree(m_fieldTree.data(), dialogLayout); if (this->findChild() == nullptr) dialogLayout->setRowStretch(dialogLayout->rowCount(), 1); - + // build the dialog QVBoxLayout *mainLayout = new QVBoxLayout(this); - + // make dialog scrollable m_contentsWidget = new QWidget; m_contentsWidget->setLayout(dialogLayout); @@ -108,7 +111,7 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer &a_ mainLayout->addWidget(m_ScrollArea); - + // buttons QHBoxLayout *btnLayout = new QHBoxLayout; btnLayout->addStretch(); showButtons(btnLayout); @@ -127,19 +130,19 @@ void LogViewTelegramDialog::showDialog(const QSharedPointer &a_ } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showDataDump(const QSharedPointer &a_telegram, bool showErrorMessage) { QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(new QLabel(tr("Telegramm-Dump"))); if (showErrorMessage) - + // show error-message in dialog layout->addWidget(new QLabel(tr("Konnte Dialog basierend auf Struktur \'%1\' nicht generieren!").arg(a_telegram->getStructName()))); else layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName()))); - + // generate the telegram-dump QString theDump = QLatin1String(""); const QByteArray &data = a_telegram->getData(); for (int i = 0; i < data.size(); i++) @@ -167,11 +170,11 @@ void LogViewTelegramDialog::showDataDump(const QSharedPointer & } - +// --------------------------------------------------------------- void LogViewTelegramDialog::makePretty() { return; - + // set the size and position of dialog int sbWidth = m_ScrollArea->width() - m_ScrollArea->viewport()->width(); int wDiff = m_contentsWidget->width() - m_ScrollArea->width(); int hDiff = m_contentsWidget->height() - m_ScrollArea->viewport()->height(); @@ -179,15 +182,15 @@ void LogViewTelegramDialog::makePretty() int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10); int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10); - - + //setGeometry(winGeo); + //QSize size = settings.value(SIZE, sizeHint()).toSize(); resize(QSize(newWidth, newHeight)); - - + //move(settings.value(POS, QPoint(0, 0)).toPoint()); + // -------------------------------------------------------------------- } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_box) { int i = 0; @@ -227,7 +230,7 @@ void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_b } - +// --------------------------------------------------------------- void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram) { INFO_LOG(m_logger) << "******************************************"; @@ -239,12 +242,12 @@ void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram) if (!ptr->isValid()) { INFO_LOG(m_logger) << ptr->field()->name() << " is invalid"; - return; + return; // abort when a value is not vaild } } - - + // now save the values + // ------------------- a_telegram->resetOffset(); a_telegram->clearJsonData(); for (auto ptr : std::as_const(m_EditInfoList)) @@ -258,12 +261,12 @@ void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram) } - +// --------------------------------------------------------------- void LogViewTelegramDialog::saveTelegram() { fillTelegram(m_Telegram.data()); - + // save wait-time and name N_SST::IntegerCalculator calculator; N_SST::IntegerCalculator::E_Error error; m_Telegram->setWaitTime(calculator.calc(m_WaitTimeEdit->text().toStdString(), error)); @@ -272,19 +275,19 @@ void LogViewTelegramDialog::saveTelegram() accept(); } - +// --------------------------------------------------------------- void LogViewTelegramDialog::sendCurrentTelegram() { emit sendTelegram(m_Telegram); } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showButtons(QLayout *a_layout) { if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol()) { QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send")); - btnSend->setEnabled(true); + btnSend->setEnabled(true); // TODO: Status ob wirklich möglich ggf. überprüfen connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram); a_layout->addWidget(btnSend); } @@ -304,48 +307,48 @@ void LogViewTelegramDialog::showButtons(QLayout *a_layout) QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK")); btnOk->setDefault(true); - + // fixme: absturz, wenn feld ungültiger wert enthält und ok gedrückt wird connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram); a_layout->addWidget(btnOk); } } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box) { - - - - - - + // INFO_LOG(m_logger) << a_logViewField->getName() << + // << " a_logViewField->getValueListSize()=" << a_logViewField->getValueListSize() + // << " a_logViewField->isIsDynamicArray()=" << a_logViewField->isIsDynamicArray() + // << " a_logViewField->getValue(0)=" << a_logViewField->getValue(0).toStdString() + // << " a_logViewField->getXdrElement())->getValueKind()=" << (int)(static_cast(a_logViewField->getXdrElement())->getValueKind()) + // ; switch (a_logViewField->valueListSize()) { case 1: - + // 1 field (single or multi-line) if (m_ReadOnly || !a_logViewField->isDynamicArray() || (LogViewXdrStandardType::e_Character == static_cast(a_logViewField->xdrElement())->getValueKind())) { QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); LogViewWidget *valueWidget = nullptr; - - + //QString value = a_logViewField->getValue(0); + // if (-1 == value.indexOf("
") && value.length() < 80) { - - + // single line + // ----------- if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind()) { - - + // enum => combobox + // ---------------- valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0); } else { if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField()) { - - + // date-time-field + // --------------- valueWidget = new LogViewDateTimeEdit(a_logViewField, this, m_ReadOnly); } else @@ -361,7 +364,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay case LogViewXdrStandardType::e_Data: valueWidget = new LogViewValueEdit(a_logViewField, this, m_ReadOnly); break; - case LogViewXdrStandardType::e_Character: + case LogViewXdrStandardType::e_Character: // Text valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly); break; } @@ -370,21 +373,21 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay if (valueWidget) m_EditInfoList.push_back(valueWidget); } - - - - - - - - - - - - - - - + // else + // { + // // ---------------------------------------------------------------- + // // fixme: not used => take away + // // multi-line + // valueWidget = new QTextEdit(value); + // static_cast(valueWidget)->setReadOnly(true); + // // make proper width of widget + // QFontMetrics fm(valueWidget->font()); + // // the 0 (at end) are here, because QFontMetrics does not understand the and tags. + // // So not the correct font will be used for calculating the width. + // // The solution here is suboptimal, but will hopefully work with a lot of fonts... + // valueWidget->setMinimumWidth(fm.width("0000: 00 00 00 00 00 00 00")*1.7); + // // ---------------------------------------------------------------- + // } QWidget *w = dynamic_cast(valueWidget); if (w) a_box->addWidget(w, a_box->rowCount() - 1, 1); @@ -392,24 +395,24 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay WARNING_LOG(m_logger) << "Internal error - LogViewWidget is not derived from QWidget... !?"; break; } - + // fall through for not read-only and dyn. array Q_FALLTHROUGH(); case 0: if (m_ReadOnly) { - + // no field a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName()))); break; } - + // fall through for not read-only Q_FALLTHROUGH(); default: { - + // show the title of table QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); - + // show the spin-box for changing the dyn. array-size LogViewSpinBox *spinBox = nullptr; if (!m_ReadOnly && a_logViewField->isDynamicArray()) { @@ -422,7 +425,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay m_EditInfoList.push_back(tableWidget); a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2); - + // connect signals if (spinBox) { connect(spinBox, &LogViewSpinBox::valueEditingFinished, @@ -434,13 +437,13 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay } - +// --------------------------------------------------------------- void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a_box) { LogViewSpinBox *spinBox = nullptr; if (!m_ReadOnly && a_logViewField->isDynamicArray()) { - + // show the spin-box for changing the dyn. array-size QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); spinBox = new LogViewSpinBox(a_logViewField, this, 0); @@ -451,14 +454,14 @@ void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a m_EditInfoList.push_back(dynamic_cast(a_tabWidget)); a_box->addWidget(a_tabWidget, a_box->rowCount(), 0, 1, 2); - + // connect signals if (spinBox) { connect(spinBox, &LogViewSpinBox::valueEditingFinished, a_tabWidget, &LogViewTabWidget::changeSize); } - + // add the tab if (a_logViewField->hasContent()) { for (int i = 0; i < a_logViewField->childCount(); ++i) @@ -466,7 +469,7 @@ void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a } } - +// --------------------------------------------------------------- bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonPath) { if (m_EditInfoList.empty()) @@ -496,4 +499,4 @@ bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonP } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.hpp index 945776535..c87372698 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramDialog.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -29,8 +29,11 @@ class LogViewWidget; class LogViewTelegram; class LogViewField; - - +/** + * @author alois.wismer + * @version 1.0 + * @created 09-Feb-2010 15:05:05 + */ class LogViewTelegramDialog : public QDialog { Q_OBJECT @@ -42,8 +45,9 @@ public: void makePretty(); void showTree(LogViewField *a_fieldTree, QGridLayout *a_box); - - + /** + * Removes the elements from m_EditInfoList matching the path + */ bool removeItemsFromEditInfoList(const QStringList &jsonPath); Q_SIGNALS: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.cpp index cde907d8f..0ed763c7e 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "LogViewTelegramEdit.hpp" @@ -125,16 +130,16 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos) { QMenu menu; - - + // add, edit and remove telegrams + // ------------------------------ menu.addAction(m_addTeleAction); menu.addAction(m_editTeleAction); menu.addAction(m_copyTeleAction); menu.addAction(m_pasteTeleAction); menu.addAction(m_deleteTeleAction); - - + // move telegram up/down + // --------------------- menu.addSeparator(); menu.addAction(m_moveTeleUpAction); menu.addAction(m_moveTeleDownAction); @@ -142,32 +147,32 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos) menu.addSeparator(); const bool itemSelected = m_tableView->currentIndex().isValid(); - + // is it a central-telegram? bool isCentral = false; QSharedPointer tele = m_EditModel->telegram(m_tableView->currentIndex().row()); if (tele) isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral); - - + // inject telegram + // --------------- if (isInjectionPossible()) { QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm")); - + // only central-telegrams can be injected action->setEnabled(itemSelected && isCentral); connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram); action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm")); - + // only central-telegrams can be injected action->setEnabled(itemSelected && isCentral); connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram); menu.addSeparator(); - - + // send and loop telegrams + // ----------------------- action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm")); - + // only central-telegrams can be sent action->setEnabled(itemSelected && isCentral); connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram); @@ -184,8 +189,8 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos) action->setEnabled(itemSelected); connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams); - - + // load/save telegram-list + // ----------------------- menu.addSeparator(); } @@ -196,17 +201,17 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos) menu.exec(m_tableView->viewport()->mapToGlobal(pos)); } - - - - - - - - +// --------------------------------------------------------------- +// Adds a_telegram at a_row in table. If there is already a +// telegram it will be overwritten. +// If a_row is -1, the telegram will be added at end. +// If false is false, a_telegram will be ignored, a +// dialog for selecting an empty telegram will be shown +// instead. +// --------------------------------------------------------------- void TelegramEdit::addTelegram() { - + // add telegram for editing LogViewTelegramSelectionDialog telegramSelectionDialog(m_tableView); if (QDialog::Accepted == telegramSelectionDialog.exec()) { @@ -214,7 +219,7 @@ void TelegramEdit::addTelegram() telegramSelectionDialog.getSelectedTelegramId())); m_curEditTelegramRow = m_EditModel->appendTelegram(newTelegram); - + // show the edit-telegram-dialog LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false); connect(editTelegramDialog, &LogViewTelegramDialog::finished, this, &TelegramEdit::editTelegramDialogFinished); @@ -238,13 +243,13 @@ QModelIndex TelegramEdit::currentSelectedIndex() const void TelegramEdit::editTelegramDialogFinished() { - + //model über geänderte Daten informieren m_EditModel->emitDataChanged(m_curEditTelegramRow); } - - - +// --------------------------------------------------------------- +// shows a telegram-dialog, where the telegram can be changed. +// --------------------------------------------------------------- void TelegramEdit::editTelegram() { m_curEditTelegramRow = currentSelectedIndex().row(); @@ -255,18 +260,18 @@ void TelegramEdit::editTelegram() editTelegramDialog->showDialog(currentSelectedTelegram()); } - - - +// --------------------------------------------------------------- +// shows a non-editable telegram-dialog +// --------------------------------------------------------------- void TelegramEdit::showTelegram() { LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true); showTelegramDialog->showDialog(currentSelectedTelegram()); - - - - - +// +// qulonglong dataPtr = m_TelegramTableWidget->item(a_tableWidget->row(), 0)->data(Qt::UserRole).toULongLong(); +// LogViewTelegram* telegram = (LogViewTelegram*)dataPtr; +// LogViewTelegramDialog* telegramDialog = new LogViewTelegramDialog(this); +// telegramDialog->showDialog(telegram); } void TelegramEdit::deleteTelegram() @@ -324,7 +329,7 @@ void TelegramEdit::sendTelegram(const QSharedPointer &a_telegra void TelegramEdit::loopTelegrams() { - + //gucken ob loop schon gestartet oder nicht if (m_DoLoop) { m_DoLoop = false; @@ -348,7 +353,7 @@ void TelegramEdit::loopNextTelegram() if (!m_DoLoop) return; ++m_currentRowToSend; - + // am Ende ? if (m_currentRowToSend >= m_tableView->model()->rowCount()) m_currentRowToSend = 0; @@ -363,7 +368,7 @@ void TelegramEdit::loopNextTelegram() void TelegramEdit::sequenceTelegrams() { m_currentRowToSend = currentSelectedIndex().row(); - if (m_currentRowToSend < 0) + if (m_currentRowToSend < 0) // invalid index return; QSharedPointer tele = currentSelectedTelegram(); sendTelegram(tele); @@ -432,7 +437,7 @@ void TelegramEdit::moveDown() void TelegramEdit::saveTelegramList() { - + // get the filename QSettings settings; QString newFilename = QFileDialog::getSaveFileName(m_tableView, tr("Dateiname der Telegrammliste"), @@ -443,22 +448,22 @@ void TelegramEdit::saveTelegramList() if (!newFilename.contains(QLatin1Char('.'))) newFilename += QLatin1String(".tgl"); - + // save the actual directory QDir dir; settings.beginGroup(s_EDIT_TELEGRAM_GROUP()); settings.setValue(s_DIR(), dir.filePath(newFilename)); settings.endGroup(); - + // save the telegram-list QFile telegramFile(newFilename); (void)telegramFile.open(QIODevice::WriteOnly); QDataStream stream(&telegramFile); - + // write the header uint32_t version = 1; stream << s_TELEGRAMLIST_FILE_ID() << version; - + // write the telegrams int rows = m_tableView->model()->rowCount(); stream << rows; for (int i = 0; i < rows; i++) @@ -493,7 +498,7 @@ void TelegramEdit::loadTelegramListReplace() void TelegramEdit::loadTelegramList(bool checkAppend) { - + // get the filename QSettings settings; QString newFilename = QFileDialog::getOpenFileName(m_tableView, tr("Dateiname der Telegrammliste"), @@ -501,24 +506,24 @@ void TelegramEdit::loadTelegramList(bool checkAppend) s_TELEGRAMLIST_FILES()); if (!newFilename.isEmpty()) { - + // save the actual directory QDir dir; settings.beginGroup(s_EDIT_TELEGRAM_GROUP()); settings.setValue(s_DIR(), dir.filePath(newFilename)); settings.endGroup(); - + // delete the actual telegram-list { if (!checkAppend) m_EditModel->clearTelegrams(); } - + // load the telegram-list QFile telegramFile(newFilename); (void)telegramFile.open(QIODevice::ReadOnly); QDataStream stream(&telegramFile); - + // read the header QString id; stream >> id; if (id != s_TELEGRAMLIST_FILE_ID()) @@ -534,7 +539,7 @@ void TelegramEdit::loadTelegramList(bool checkAppend) return; } - + // read the telegrams int rows = 0; QVector gpsFieldOffset; stream >> rows; @@ -565,13 +570,13 @@ void TelegramEdit::loadTelegramList(bool checkAppend) } } - +// --------------------------------------------------------------- bool TelegramEdit::isInjectionPossible() const { return m_InjectionThread ? m_InjectionThread->isSendingPossible() : false; } - +// --------------------------------------------------------------- void TelegramEdit::onSelectionChanged() { const QModelIndex idx = currentSelectedIndex(); @@ -583,4 +588,4 @@ void TelegramEdit::onSelectionChanged() m_moveTeleDownAction->setEnabled(idx.isValid() && idx.row() < m_EditModel->rowCount() - 1); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.hpp index 5472eac87..f9ecf70d7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEdit.hpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.cpp index e6cba4fc5..39ab476ad 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "LogViewTelegramEditModel.hpp" #include @@ -7,19 +12,19 @@ namespace N_LogView { - +// --------------------------------------------------------------- int TelegramEditModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_telegrams.size(); } - +// --------------------------------------------------------------- int TelegramEditModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 3; } - +// --------------------------------------------------------------- QVariant TelegramEditModel::data(const QModelIndex &index, int role) const { if (index.isValid() && index.row() < m_telegrams.size()) @@ -47,7 +52,7 @@ QVariant TelegramEditModel::data(const QModelIndex &index, int role) const return QVariant(); } - +// --------------------------------------------------------------- QVariant TelegramEditModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -69,7 +74,7 @@ QVariant TelegramEditModel::headerData(int section, return QAbstractTableModel::headerData(section, orientation, role); } - +// --------------------------------------------------------------- void TelegramEditModel::clearTelegrams() { beginResetModel(); @@ -77,7 +82,7 @@ void TelegramEditModel::clearTelegrams() endResetModel(); } - +// --------------------------------------------------------------- void TelegramEditModel::appendTelegrams(const QVector > &telegrams) { if (telegrams.isEmpty()) @@ -87,17 +92,17 @@ void TelegramEditModel::appendTelegrams(const QVector &telegram) { beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size()); m_telegrams.push_back(telegram); telegram->rebuildJsonString(); endInsertRows(); - return m_telegrams.size() - 1; + return m_telegrams.size() - 1; // row } - +// --------------------------------------------------------------- QSharedPointer TelegramEditModel::telegram(int row) const { if (row >= 0 && row < m_telegrams.size()) @@ -105,7 +110,7 @@ QSharedPointer TelegramEditModel::telegram(int row) const return QSharedPointer(); } - +// --------------------------------------------------------------- bool TelegramEditModel::moveUp(int row) { if (row <= 0 || row >= m_telegrams.size()) @@ -116,7 +121,7 @@ bool TelegramEditModel::moveUp(int row) return true; } - +// --------------------------------------------------------------- bool TelegramEditModel::moveDown(int row) { if (row >= (m_telegrams.size() - 1)) @@ -127,7 +132,7 @@ bool TelegramEditModel::moveDown(int row) return true; } - +// --------------------------------------------------------------- void TelegramEditModel::emitDataChanged(int row) { QModelIndex top = createIndex(row, 0); @@ -135,12 +140,12 @@ void TelegramEditModel::emitDataChanged(int row) emit dataChanged(top, bottom, {Qt::DisplayRole, Qt::ToolTipRole}); } - +// --------------------------------------------------------------- void TelegramEditModel::removeTelegrams(const QSet &rows) { QList rowList = rows.values(); std::sort(rowList.begin(), rowList.end()); - + // von oben her löschen um ein Verschieben der Indizes zu vermeiden for (int i = rowList.size() - 1 ; i >= 0; --i) { int row = rowList.at(i); @@ -150,7 +155,7 @@ void TelegramEditModel::removeTelegrams(const QSet &rows) } } - +// --------------------------------------------------------------- void TelegramEditModel::pasteRows(int row, const QSharedPointer &tele) { if (row < 0 || row > m_telegrams.size()) @@ -160,4 +165,4 @@ void TelegramEditModel::pasteRows(int row, const QSharedPointer endInsertRows(); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.hpp index ce650385c..aab522387 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramEditModel.hpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * some models for LogViewGui + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.cpp index ba750ccab..091cf682c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewTelegramSelectionDialog.hpp" #include @@ -23,7 +23,7 @@ namespace N_LogView { static int s_currentRow = 0; - +// --------------------------------------------------------------- LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent) : QDialog(a_parent) { @@ -34,7 +34,7 @@ LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent const auto telegramMap = LogViewTelegram::jsonParser()->telegramsToCreate(); for (auto it = telegramMap.cbegin(); it != telegramMap.cend(); ++it) { - if (it.key() == 0) + if (it.key() == 0) // ACK continue; auto lwi = new QListWidgetItem(it.value() + QStringLiteral(" (%1)").arg(it.key())); lwi->setData(Qt::UserRole, it.key()); @@ -51,7 +51,7 @@ LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent } - +// --------------------------------------------------------------- void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramItem) { s_currentRow = m_TelegramList->currentRow(); @@ -59,4 +59,4 @@ void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramI accept(); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.hpp index 2befcb03e..0fe2ceb67 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTelegramSelectionDialog.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -19,22 +19,29 @@ class QListWidgetItem; namespace N_LogView { - - + /** + * @author alois.wismer + * @version 1.0 + * @created 05-Mai-2010 17:24:14 + */ class LogViewTelegramSelectionDialog : public QDialog { Q_OBJECT public: - - + /** + * + * @param a_parent + */ explicit LogViewTelegramSelectionDialog(QWidget* a_parent); int getSelectedTelegramId() const { return m_SelectedTelegramId; } protected slots: - - + /** + * + * @param a_telegramItem + */ void selectTelegram(QListWidgetItem* a_telegramItem); protected: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.cpp index 62a25ce34..9ecf48e58 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.cpp @@ -1,5 +1,10 @@ - - +/** + * Parses training_area_telegrams.h + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-14 + */ #include "LogViewTetraTelegramsParser.hpp" #include @@ -67,7 +72,7 @@ static void fillBasemembers(StructInformation &si, const QHash &lines, continue; if (base.endsWith(QLatin1Char(','))) base.chop(1); - if (base.endsWith(QLatin1Char('>'))) + if (base.endsWith(QLatin1Char('>'))) // helper template - ignore { si.isVisible = true; continue; @@ -287,8 +292,8 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector &lines, in return -1; enumName = tokens.at(2); } - if (enumName.endsWith(QLatin1Char(';'))) - return iStartPos; + if (enumName.endsWith(QLatin1Char(';'))) // forward decl + return iStartPos; // move to next line EnumInformation ei; ei.type = enumName.toString(); @@ -311,7 +316,7 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector &lines, in { if (tokens.size() == 4 && tokens.at(0) == QLatin1String("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si) { - + // enum in struct with direct decl of member MemberInformation mi; if (ns.isEmpty()) mi.type = ei.type; @@ -386,7 +391,7 @@ int LogViewTetraTelegramsParser::parseConstraint(const QVector &lin } if (tokens.at(0) == QLatin1String("};")) break; - if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId")) + if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId")) // static constexpr TelegramId id() { return TelegramId::INIT; } { ++i; continue; @@ -477,7 +482,7 @@ QVector LogViewTetraTelegramsParser::tokenize(const QStringView &li const QStringView &token = ret.at(i); if (token.startsWith(QLatin1String("//"))) { - + // all comment after this - merge into one if (i == ret.size() - 1) break; const QStringView &lastToken = ret.last(); @@ -535,4 +540,4 @@ bool LogViewTetraTelegramsParser::validStructTokens(const QVector & return false; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.hpp index 972396222..cc866425f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTetraTelegramsParser.hpp @@ -1,5 +1,10 @@ - - +/** + * Parses training_area_telegrams.h + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-14 + */ #pragma once @@ -27,7 +32,7 @@ struct MemberInformation struct StructInformation { QString type; - QString baseStruct; + QString baseStruct; // we only allow one base... QVector member; bool isVisible = false; @@ -87,4 +92,4 @@ private: QHash m_visibleTelegrams; NGL::INGLLogger &m_logger; }; -} +} // namespace LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.cpp index e21dedb07..299b9fe33 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewTextEdit.hpp" #include "LogViewField.hpp" @@ -18,7 +18,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly) : QLineEdit(a_parent) , LogViewWidget(a_field, this, a_parent, a_readonly) @@ -32,12 +32,12 @@ LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft); } - + // set a validator for number of chars uint16_t maxArraySize = a_field->maxArraySize(); setMaxLength(maxArraySize); updateToolTip(value); - + // make proper width of widget QFontMetrics fm(font()); #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) setMinimumWidth(fm.width(QLatin1Char(' ') + value + QLatin1Char(' '))); @@ -45,23 +45,23 @@ LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + value + QLatin1Char(' '))); #endif - + // connect signals connect(this, &LogViewTextEdit::editingFinished, this, &LogViewTextEdit::checkAndOvertakeContent); } - +// --------------------------------------------------------------- void LogViewTextEdit::checkAndOvertakeContent() { - updateToolTip(text()); + updateToolTip(text()); // fixme nach jedem zeichen updaten m_Valid = true; } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram) { if (!isValid()) @@ -79,18 +79,18 @@ bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram) { arraySize = content.length(); a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize); - + // fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren } else { arraySize = m_Field->maxArraySize(); } - + // copy the text for (int i = 0; i < arraySize; i++) a_telegram->setUIntX(size, i < content.length() ? content[i].toLatin1() : 0); } return true; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.hpp index 725da7bd8..82cb1471d 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewTextEdit.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,18 +18,31 @@ namespace N_LogView { - - + /** + * Used for arrays of char and string. + * + * @author alois.wismer + * @version 1.0 + * @created 21-Mai-2010 10:28:05 + */ class LogViewTextEdit : public QLineEdit, public LogViewWidget { Q_OBJECT public: - - + /** + * + * @param a_field + * @param a_parent + * @param a_readonly + */ LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly); - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; protected slots: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.cpp index 117211ef7..ef1fe9f83 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewValueEdit.hpp" #include "LogViewField.hpp" @@ -18,7 +18,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly) : QLineEdit(a_parent) , LogViewWidget(a_field, this, a_parent, a_readonly) @@ -31,10 +31,10 @@ LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, con setText(valueText); - + // checkAndOvertakeContent(); updateToolTip(valueText); - + // make proper width of widget QFontMetrics fm(font()); #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) setMinimumWidth(fm.width(QLatin1Char(' ') + valueText + QLatin1Char(' '))); @@ -55,28 +55,28 @@ LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, con } - +// --------------------------------------------------------------- void LogViewValueEdit::checkAndOvertakeContent() { bool ok; int64_t intValue = 0; double floatValue = 0.0; - + // get the calculated and checked value if (m_IsFloat) floatValue = getFloat(text(), (uint64_t&)intValue, ok); else intValue = getInteger(text(), ok); - + // handle errors if (!ok) { setFocus(); selectAll(); - return; + return; // abort } - + // update if (m_IsFloat) setText(QString::number(floatValue)); else @@ -86,10 +86,10 @@ void LogViewValueEdit::checkAndOvertakeContent() } - - - - +// --------------------------------------------------------------- +// Writes the content into telegram. +// Returns true if successful. +// --------------------------------------------------------------- bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram) { if (m_Valid) @@ -97,7 +97,7 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram) bool ok; if (m_IsFloat) { - + // save the float or double-value uint64_t valueAsUint64; const double value = getFloat(text(), valueAsUint64, ok); if (ok) @@ -117,7 +117,7 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram) } else { - + // save the integer-value qint64 intValue = getInteger(text(), ok); if (ok) { @@ -132,4 +132,4 @@ bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram) return false; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.hpp index a9d4f1f9f..d293ddd4b 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewValueEdit.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,18 +18,31 @@ namespace N_LogView { - - + /** + * Used for scalar signed or unsigned values + * + * @author alois.wismer + * @version 1.0 + * @created 20-Mai-2010 14:47:50 + */ class LogViewValueEdit : public QLineEdit, public LogViewWidget { Q_OBJECT public: - - + /** + * + * @param a_field + * @param a_parent + * @param a_readonly + */ LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly); - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ bool saveContent(LogViewTelegram* a_telegram) override; protected: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.cpp index 26b7a34f7..60ce593c9 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.cpp @@ -1,17 +1,17 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewWidget.hpp" #include "LogViewField.hpp" @@ -23,7 +23,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly) : m_Readonly(a_readonly) , m_Valid(true) @@ -34,21 +34,21 @@ LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* { } - +// --------------------------------------------------------------- uint16_t LogViewWidget::getSize() const { - + // todo: check whether really a standardtype const LogViewXdrStandardType* xdrStandardType = static_cast(m_Field->xdrElement()); return xdrStandardType->getValueSize(); } - +// --------------------------------------------------------------- void LogViewWidget::showMessageBox(const QString &a_errorText) const { QMessageBox::warning(m_Parent, QObject::tr("Fehler"), a_errorText); } - +// --------------------------------------------------------------- void LogViewWidget::updateToolTip(const QString &a_text) { bool isList = m_Field->valueListSize() > 1 || m_Field->isDynamicArray(); @@ -74,7 +74,7 @@ void LogViewWidget::updateToolTip(const QString &a_text) } else { - + // fixme: bei 3-byte werten werden fälschlicherweise 4 Bytes angezeigt if (m_Field->isDateTimeField()) { m_Widget->setToolTip(QObject::tr("Unixzeit: %1 ").arg(a_text)); @@ -83,13 +83,13 @@ void LogViewWidget::updateToolTip(const QString &a_text) { m_Widget->setToolTip(QString()); } - + // actual value in hex and binary if (!isList) { int64_t value = a_text.toLong(); m_Widget->setToolTip(QStringLiteral("%1%2 %3").arg(m_Widget->toolTip(), toHex(value), toBin(value))); } - + // range if (!m_Field->isDateTimeField() && !m_Readonly) { const QString sep(isList ? QString() : QStringLiteral("
")); @@ -120,12 +120,12 @@ void LogViewWidget::updateToolTip(const QString &a_text) } - +// --------------------------------------------------------------- double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse) { +// INFO_LOG(m_logger) << "a_text=" << a_text.toStdString(); - - + //LogViewXdrStandardType::E_ByteOrder byteOrder = ((LogViewXdrStandardType*)m_Field->xdrElement())->getByteOrder(); double value; if (8 == getSize()) { @@ -136,14 +136,14 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b a_FloatAsData = LogViewTelegram::floatToXdr(value); } - - + // show error-message + // fixme zeige fehler genauer if (!a_ok) showMessageBox(QStringLiteral("Inalid real value: '%1'").arg(a_text)); m_Valid = a_ok; - + // swap for display data on table if (a_reverse) { int j = getSize() - 1; @@ -157,7 +157,7 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b } } - + // set the upper 4 bytes to 0 for float if (4 == getSize()) { ((uint8_t*)&a_FloatAsData)[4] = 0; @@ -169,17 +169,17 @@ double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, b } - - - - - - - - +// --------------------------------------------------------------- +// Converts a_text into a signed integer and returns it. The +// parameter a_ok will be true if all was successful. The +// attribute m_Valid will be set to a_ok. +// The range will be checked, if the value is out of range, an +// error will be shown as messge-box and a_ok will be false. +// The input a_text can be a calculation. +// --------------------------------------------------------------- int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok) { - + // calculate the expression into a number N_SST::IntegerCalculator calculator; N_SST::IntegerCalculator::E_Error error; int64_t value = calculator.calc(a_text.toStdString(), error); @@ -187,7 +187,7 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok) a_ok = true; if (N_SST::IntegerCalculator::e_Ok != error) { - + // todo: show exact error-message if (a_text != m_LastErrorValueText) { showMessageBox(QString::fromUtf8("Die Berechnung '%1' ist falsch").arg(a_text)); @@ -197,19 +197,19 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok) } else { - + // check the range int64_t highest = m_Field->getHighestValue(); if (value > highest) { a_ok = false; - - + // fixme: dieser Trick mit m_LastErrorValueText ist für den Benutzer etwas verwirrend, da + // plötzlich keine Reaktion mehr auf Tab, Ok oder wählen eines anderen Feldes passiert... if (a_text != m_LastErrorValueText) { showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu hoch. Maximalwert: %2").arg(a_text).arg(highest)); m_LastErrorValueText = a_text; } - return value; + return value; // abort } int64_t lowest = m_Field->getLowestValue(); if (value < lowest) @@ -220,11 +220,11 @@ int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok) showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu tief. Minimalwert: %2").arg(a_text).arg(lowest)); m_LastErrorValueText = a_text; } - return value; + return value; // abort } m_Valid = true; } return value; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.hpp index 904707785..5e7c6ff22 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewWidget.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -36,8 +36,11 @@ inline QString toBin(T num) class LogViewField; class LogViewTelegram; - - +/** + * @author alois.wismer + * @version 1.0 + * @created 20-Mai-2010 14:51:17 + */ class LogViewWidget { public: @@ -48,12 +51,17 @@ public: LogViewField* field() const { return m_Field; } bool isValid() const { return m_Valid; } - - + /** + * The content if the field is a text-field + */ QString getText() const { return m_Text; } - - + /** + * Writes the content into telegram. + * Returns true if successful. + * + * @param a_telegram + */ virtual bool saveContent(LogViewTelegram* a_telegram) = 0; protected: @@ -61,16 +69,25 @@ protected: void updateToolTip(const QString &a_text = QString()); double getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse = false); - - + /** + * Converts a_text into a signed integer and returns it. The parameter a_ok will + * be true if all was successful. The attribute m_Valid will be set to a_ok. + * The range will be checked, if the value is out of range, an error will be shown + * as messge-box and a_ok will be false. + * The input a_text can be a calculation. + * + * @param a_text + * @param a_ok + */ int64_t getInteger(const QString& a_text, bool& a_ok); protected: bool m_Readonly; bool m_Valid; - - + /** + * The content if the field is a text-field + */ QString m_Text; QString m_LastErrorValueText; QWidget *m_Widget; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.cpp index c2414c0fe..29ca61294 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.cpp @@ -1,24 +1,24 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewXdrElement.hpp" namespace N_LogView { - - - +// --------------------------------------------------------------- +// Constructor of a struct or enum +// --------------------------------------------------------------- LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName) : m_Name(a_name) , m_Kind(a_kind) @@ -28,14 +28,14 @@ LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind ERROR_LOG(m_logger) << "Element \'" << a_name.toStdString() << "\' has a problem"; } - +// --------------------------------------------------------------- void LogViewXdrElement::dump() const { INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName(); } - +// --------------------------------------------------------------- QString LogViewXdrElement::getKindName() const { switch (getKind()) @@ -58,4 +58,4 @@ QString LogViewXdrElement::getKindName() const return QStringLiteral("Unknown (%1)").arg(getKind()); } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.hpp index 26c1bc057..72765998a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrElement.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -18,14 +18,20 @@ namespace N_LogView { - - + /** + * @author alois.wismer + * @version 1.0 + * @created 05-Feb-2010 11:24:56 + */ class LogViewXdrElement { public: - - + /** + * @author alois.wismer + * @version 1.0 + * @created 10-Feb-2010 11:34:47 + */ enum E_ElementKind { e_KindStandardType, @@ -40,8 +46,12 @@ namespace N_LogView virtual ~LogViewXdrElement() = default; protected: - - + /** + * Constructor of a struct or enum + * + * @param a_name + * @param a_kind + */ LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName); public: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.cpp index 0d73a426d..a3f1c7f7c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.cpp @@ -1,21 +1,21 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewXdrParser.hpp" #include - +// from cpp_includes #include "LogViewXdrElement.hpp" #include #include "LogViewXdrStruct.hpp" @@ -46,7 +46,7 @@ LogViewXdrParser::~LogViewXdrParser() delete elem.second; } - +// --------------------------------------------------------------- void LogViewXdrParser::addStandardType(const QString& a_name, const uint16_t a_dataSize, const uint16_t a_realSize, const LogViewXdrStandardType::E_ValueKind a_kind, const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod, const LogViewXdrStandardType::E_ByteOrder a_byteOrder) { QString name = a_name.trimmed(); @@ -59,7 +59,7 @@ void LogViewXdrParser::addStandardType(const QString& a_name, const uint16_t a_d } - +// --------------------------------------------------------------- void LogViewXdrParser::parseX_File(const QString& a_fileName) { for (const auto &elem : m_ElementMap) @@ -73,7 +73,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) m_ActElement = nullptr; m_State = e_ParseMain; - + // define some (XDR-)standard-types addStandardType(QLatin1String("unsigned short"), 4, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("unsigned int"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("short"), 4, 2, LogViewXdrStandardType::e_Signed); @@ -89,7 +89,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) addStandardType(QLatin1String("opaque"), 1, 1, LogViewXdrStandardType::e_Data); addStandardType(QLatin1String("string"), 1, 1, LogViewXdrStandardType::e_Character); - + // for tetra-telegrams addStandardType(QLatin1String("alpha"), 1, 1, LogViewXdrStandardType::e_Character); addStandardType(QLatin1String("UInt8"), 1, 1, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("UInt16"), 2, 2, LogViewXdrStandardType::e_Unsigned); @@ -97,20 +97,20 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) addStandardType(QLatin1String("SInt8"), 1, 1, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("SInt16"), 2, 2, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("SInt24"), 3, 3, LogViewXdrStandardType::e_Signed); - + // little-endian values (for TETRA-header) addStandardType(QLatin1String("UInt16LE"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); addStandardType(QLatin1String("UInt32LE"), 4, 4, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); - + // index for next dyn. array (only for TETRA) addStandardType(QLatin1String("UInt8Idx"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QLatin1String("UInt16Idx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QLatin1String("UInt16LEIdx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex, LogViewXdrStandardType::e_ByteOrderLittleEndian); - + // index (div 8) for next dyn. array (only for TETRA) addStandardType(QLatin1String("UInt8IdxDiv8"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); addStandardType(QLatin1String("UInt16IdxDiv8"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); const auto DEFINE_NAME = QLatin1String("%#define"); - + // parse the file m_Filename = a_fileName; m_State = e_ParseMain; QFile xFile(a_fileName); @@ -124,25 +124,25 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) m_Line = lastLines + QLatin1Char(' ') + in.readLine(); m_Line = m_Line.simplified(); m_LineNbr++; +// INFO_LOG(m_logger) << m_LineNbr << ": " << m_Line.toStdString(); - - + // ignore lines with % if (m_Line.startsWith(QLatin1Char('%')) && !m_Line.startsWith(DEFINE_NAME)) { continue; } - + // remove comments (sourounded with /* */) const QString cleanLine = removeComments(m_Line).simplified(); - + // ignore empty lines if (cleanLine.isEmpty()) { continue; } - - +// INFO_LOG(m_logger) << "w/o comment: \'" << cleanLine.toStdString() << "\'"; + // read in whole construct if (m_DoReadUntilSemicolon && !cleanLine.endsWith(QLatin1Char(';'))) { lastLines = cleanLine; @@ -153,7 +153,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) lastLines.clear(); - + // check whether it is the begin of a construct if (e_ParseMain == m_State) { if (cleanLine.startsWith(QLatin1String("union "))) @@ -166,7 +166,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) } } - + // parse the line when we are within switch (m_State) { case e_ParseUnion: @@ -208,7 +208,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) } } xFile.close(); - + // erase all parsing-values (otherwise errormessages will have wrong informations) m_LineNbr = 0; m_Line.clear(); } @@ -219,12 +219,12 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName) } - +// --------------------------------------------------------------- QString LogViewXdrParser::removeComments(const QString& a_line) { static const QChar slash(QLatin1Char('/')); static const QChar asterik(QLatin1Char('*')); - + // remove comments (sourounded with /* */) QString cleanLine; cleanLine.reserve(a_line.size()); QString::const_iterator iter = a_line.begin(); QString::const_iterator end = a_line.end(); @@ -232,38 +232,38 @@ QString LogViewXdrParser::removeComments(const QString& a_line) { if (!m_WithinComment) { - + // does comment begin? if (slash == *iter) { if (++iter != end) { if (asterik == *iter) { - + // yes, comment begins m_WithinComment = true; } else { - + // no comment begin cleanLine.append(slash); cleanLine.append(*iter); } } else { - + // end of line cleanLine.append(slash); } } else { - + // no cleanLine.append(*iter); } } else { - + // does comment end? if (asterik == *iter) { if (++iter != end) @@ -282,26 +282,26 @@ QString LogViewXdrParser::removeComments(const QString& a_line) } - +// --------------------------------------------------------------- void LogViewXdrParser::parseTypedef(const QString &a_line) { fillWordList(a_line); - - - + // typedef: "typedef telegramm_id_int_et telegramm_id_et;" + // ------- + // keyword 'typedef' if (isNextWord("typedef")) { - + // get type bool ok; QString type = getNextType(ok); - - getElement(type); - + // fixme: make boolean for structure wrong and gray out telegrams with wrong struct + getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure + // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; if (!isNextWord(";")) return; - + // all ok uint16_t dynArrayOffset; uint16_t arraySize = parseArray(name, dynArrayOffset); LogViewXdrType* typedefElement = new LogViewXdrType(name, type, arraySize, dynArrayOffset, LogViewXdrElement::e_KindTypedef); @@ -311,7 +311,7 @@ void LogViewXdrParser::parseTypedef(const QString &a_line) } - +// --------------------------------------------------------------- void LogViewXdrParser::parseDefine(const QString &a_line) { const QString line = a_line.trimmed(); @@ -324,12 +324,12 @@ void LogViewXdrParser::parseDefine(const QString &a_line) if (sepPos >= 0) substitution = substitution.left(sepPos).trimmed(); - + // convert to number bool ok = false; const int64_t value = calcValue(substitution.toString(), ok); if (ok) { - + //INFO_LOG(m_logger) << "Define: name=" << name.toStdString() << " subst=" << substitution.toStdString() << " value=" << value; m_DefinesMap.insert(std::make_pair(name, LogViewXdrValue(name, value, LogViewXdrElement::e_KindDefine))); } } @@ -340,7 +340,7 @@ void LogViewXdrParser::parseDefine(const QString &a_line) } - +// --------------------------------------------------------------- void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSize) { if (QLatin1String("};") != a_line) @@ -348,8 +348,8 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz switch(m_State) { default: - - + // first line of enum containing the name + // i.e.: "enum telegramm_id_int_et {" if (a_line.endsWith(QLatin1String(" {"))) { m_State = e_ParseEnum; @@ -370,20 +370,20 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz case e_ParseEnum: { - - + // middle lines of struct containing the elements + // i.e.: "MANIPULATIONSMELDUNG = 2," QString name; QString valueText; if (parseEnumLine(a_line, name, valueText)) { - + // is the valueText a previous enum-element? bool error = true; uint32_t enumValue = m_ActElement->getChildValue(valueText, &error); if (!error) { valueText = QString::number(enumValue); } - + // calculate bool ok; int64_t value = calcValue(valueText, ok); if (ok) @@ -397,30 +397,30 @@ void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSiz } else { - + // end of struct m_State = e_ParseMain; - - + //INFO_LOG(m_logger) << "CheckEnum " << m_ActElement->getName().toStdString(); +// check(*m_ActElement); } } - +// --------------------------------------------------------------- void LogViewXdrParser::parseStruct(const QString &a_line) { fillWordList(a_line); if (!m_DoReadUntilSemicolon) { - - - + // first line of struct: "struct gef_wirkfeld_flaechendeckendes_feuer_meldung_rt {" + // -------------------- + // keyword 'union' if (isNextWord("struct")) { - + // union name QString structName = getNextWord("Struktur-Name"); if (structName.isEmpty()) return; if (!isNextWord("{")) return; - + // all ok => proceed parsing union m_ActElement = new LogViewXdrStruct(structName, LogViewXdrElement::e_KindStruct); if (!addToElementMap(structName, m_ActElement)) { @@ -436,15 +436,15 @@ void LogViewXdrParser::parseStruct(const QString &a_line) { if (!isNextWord("}", false)) { - - - + // next lines of struct: "gef_header_rt:3..6 header;" + // -------------------- + // get type bool ok; QString type = getNextType(ok); if (!ok) return; - - if (m_UnionType != type) getElement(type); - + // fixme: make boolean for structure wrong and gray out telegrams with wrong struct + if (m_UnionType != type) getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure + // get bitfield (if any) ":2..5" int16_t firstBit = -1; int16_t lastBit = -1; bool isLast = true; @@ -454,11 +454,11 @@ void LogViewXdrParser::parseStruct(const QString &a_line) QString bitfield = getNextWord("Bitfield"); isLast = parseBitfield(bitfield, firstBit, lastBit); } - + // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; if (!isNextWord(";")) return; - + // all ok uint16_t dynArrayOffset; uint16_t arraySize = parseArray(name, dynArrayOffset); if(firstBit >= 0) @@ -471,51 +471,51 @@ void LogViewXdrParser::parseStruct(const QString &a_line) } else { - + // end of struct "};" if (!isNextWord("}")) return; if (!isNextWord(";")) return; m_State = e_ParseMain; m_DoReadUntilSemicolon = false; - - - - - +// INFO_LOG(m_logger) << "CheckStruct \'" << m_ActElement->getName().toStdString() << "\'"; +// if (m_ActElement->getName() != "intern_tele") // fixme: remove this structure from element-map +// { +// check(*m_ActElement); +// } } } } - +// --------------------------------------------------------------- void LogViewXdrParser::parseUnion(const QString& a_line) { - - + // we can not really parse the union, we expect that only 1 union exists, and this + // union holds all the telegrams, which we insert into a telegram-list static const LogViewXdrStruct* telegramIdType = nullptr; fillWordList(a_line); if (!m_DoReadUntilSemicolon) { - - - + // first line of union "union gef_tg_nd_ switch (gef_telegramm_id_et telegramm_id) {" + // ------------------- + // keyword 'union' if (isNextWord("union")) { - + // union name m_UnionType = getNextWord("Union-Typ"); if (m_UnionType.isEmpty()) return; - + // keyword 'switch' if (!isNextWord("switch")) return; if (!isNextWord("(")) return; - + // telegram-id-type getNextEnum(telegramIdType); if (telegramIdType == nullptr) return; - + // telegram-id-name QString name = getNextWord("Parameter-Name"); if (name.isEmpty()) return; if (!isNextWord(")")) return; if (!isNextWord("{")) return; - + // all ok => proceed parsing union m_State = e_ParseUnion; m_DoReadUntilSemicolon = true; } @@ -527,29 +527,29 @@ void LogViewXdrParser::parseUnion(const QString& a_line) QString keyword = getNextWord(); if (keyword == QLatin1String("case")) { - - + // next lines of union "case GEF_INIT: gef_init_meldung_rt init_meldung;" + // ------------------- QStringList constExprList; QString type; do { - + // get constant-expression QString constExpression = getNextWord("Konstanten-Ausdruck"); if (constExpression.isEmpty()) return; constExprList << constExpression; - + // check double-point if (!isNextWord(":")) return; - + // get type or another case type = getNextWord("Typ"); if (type.isEmpty()) return; } while (type == QLatin1String("case")); - - getElement(type); - + // fixme: make boolean for structure wrong and gray out telegrams with wrong struct + getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure + // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; - + // check semicolon if (!isNextWord(";")) return; for (const QString &constExpr : std::as_const(constExprList)) @@ -558,7 +558,7 @@ void LogViewXdrParser::parseUnion(const QString& a_line) int32_t telegramId = static_cast(telegramIdType->getChildValue(constExpr, &error)); if (!error) { - m_TelegramMap.insert(std::make_pair(telegramId, LogViewXdrType(constExpr, type, 1, 0, LogViewXdrElement::e_KindEnumElement))); + m_TelegramMap.insert(std::make_pair(telegramId, LogViewXdrType(constExpr, type, 1, 0, LogViewXdrElement::e_KindEnumElement))); // fixme: e_KindCaseElement und 1 entfernen } else { @@ -568,14 +568,14 @@ void LogViewXdrParser::parseUnion(const QString& a_line) } else if (keyword == QLatin1String("default")) { - + // check double-point if (isNextWord(":")) { QString defaultDefinition = getNextWord(); if (defaultDefinition == QLatin1String("void")) { isNextWord(";"); - + // all ok } else { @@ -590,18 +590,18 @@ void LogViewXdrParser::parseUnion(const QString& a_line) } else { - + // end of union "};" if (!isNextWord("}")) return; if (!isNextWord(";")) return; m_State = e_ParseMain; m_DoReadUntilSemicolon = false; - + //check(*m_ActElement); } } } - +// --------------------------------------------------------------- bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const { QString line; @@ -626,14 +626,14 @@ bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QSt { showErrorMessage(QObject::tr("konnte Trennzeichen \'=\' zwischen Name und Wert nicht finden!")); } - return false; + return false; // failure happenend } - - - - +// --------------------------------------------------------------- +// Shows an error-message containing the line-nbr, the line +// itself and an additional error-text +// --------------------------------------------------------------- void LogViewXdrParser::showErrorMessage(const QString& a_errorText) const { const auto tlws = QApplication::topLevelWidgets(); @@ -643,10 +643,10 @@ void LogViewXdrParser::showErrorMessage(const QString& a_errorText) const } - +// --------------------------------------------------------------- int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk) { - + // ignore strings a_isOk = false; int64_t value = 0; if (!a_calcText.startsWith(QLatin1Char('\"'))) @@ -655,7 +655,7 @@ int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk) std::string errorText; value = calc(a_calcText.toStdString(), error, &errorText); - + // show error if one happend if (error != N_SST::IntegerCalculator::e_Ok) { switch (error) @@ -695,21 +695,21 @@ int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk) } - +// --------------------------------------------------------------- bool LogViewXdrParser::getVariableValue(const std::string& a_variableName, int64_t& a_value) const { return getDefine(QString::fromStdString(a_variableName), a_value); } - - - - - - - - - +// --------------------------------------------------------------- +// This function delivers the name of the telegram and the +// name of its structure. The telegram will be defined with +// a_telegramId. +// The name will be delivered as return-parameter; the +// structure-name as out parameter a_structName. +// If the telegram was not found, error-texts instead names +// will be returned. +// --------------------------------------------------------------- QString LogViewXdrParser::getTelegramName(int a_telegramId) const { const auto iter = m_TelegramMap.find(a_telegramId); @@ -719,7 +719,7 @@ QString LogViewXdrParser::getTelegramName(int a_telegramId) const return QObject::tr("").arg(a_telegramId); } - +// --------------------------------------------------------------- QString LogViewXdrParser::getStructName(int a_telegramId) const { const auto iter = m_TelegramMap.find(a_telegramId); @@ -729,7 +729,7 @@ QString LogViewXdrParser::getStructName(int a_telegramId) const return QObject::tr("").arg(a_telegramId); } - +// --------------------------------------------------------------- bool LogViewXdrParser::getDefine(const QString& a_name, int64_t& a_value) const { const auto iter = m_DefinesMap.find(a_name); @@ -742,7 +742,7 @@ bool LogViewXdrParser::getDefine(const QString& a_name, int64_t& a_value) const } - +// --------------------------------------------------------------- const LogViewXdrElement* LogViewXdrParser::getElement(const QString& a_name) const { const auto iter = m_ElementMap.find(a_name); @@ -754,27 +754,27 @@ const LogViewXdrElement* LogViewXdrParser::getElement(const QString& a_name) con } - +// --------------------------------------------------------------- uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const { a_dynArrayMsgOffset = 0; QString oldName = a_name; - - + // is it a static array []? + // ------------------------ int pos = a_name.indexOf(QLatin1Char('[')); if (pos >= 0) { int endPos = a_name.indexOf(QLatin1Char(']')); if (endPos > pos) { - + // get the array-size QString arraySizeText = a_name.mid(pos+1, endPos-pos-1); - + // set new name a_name = a_name.left(pos); - +// INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString(); int64_t arraySizeValue = 1; - + // check whether it is a define if (!getDefine(arraySizeText, arraySizeValue)) { bool ok = false; @@ -784,7 +784,7 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf showErrorMessage(QObject::tr("%1: [%2] is not a number").arg(oldName, arraySizeText)); } } - +// INFO_LOG(m_logger) << "ArraySize=" << arraySizeValue; return arraySizeValue; } else @@ -795,22 +795,22 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf else { - - - + // is it an dynamic array <>? + // -------------------------- + //INFO_LOG(m_logger) << "check for <"; pos = a_name.indexOf(QLatin1Char('<')); if (pos >= 0) { int endPos = a_name.indexOf(QLatin1Char('>')); if (endPos > pos) { - + // get the array-size QString arraySizeText = a_name.mid(pos+1, endPos-pos-1); - - + //INFO_LOG(m_logger) << "pos=" << pos << " endPos=" << endPos << " => " << arraySizeText.toStdString(); + // set new name a_name = a_name.left(pos); - - +// INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString(); + // check whether it is a define int64_t arraySizeValue = 1; if (!getDefine(arraySizeText, arraySizeValue)) { @@ -822,11 +822,11 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf } else { - +// INFO_LOG(m_logger) << "a_name=" << a_name.toStdString() << " a_dynArrayMsgOffset=" << a_dynArrayMsgOffset; } } a_dynArrayMsgOffset = arraySizeValue; - +// INFO_LOG(m_logger) << a_name.toStdString() << " is a dynamic array with size=" << arraySizeValue; return 0; } else @@ -839,14 +839,14 @@ uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOf } - +// --------------------------------------------------------------- bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement) { const QString word = QString::fromUtf8(a_word); bool ok = (m_WordListIndex < m_WordList.size() && m_WordList.at(m_WordListIndex) == word); - + // show error-message if (!ok && a_doIncrement) { if (m_WordListIndex > 0) @@ -861,7 +861,7 @@ bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement) } - +// --------------------------------------------------------------- void LogViewXdrParser::fillWordList(const QString& a_line) { QString line = a_line; @@ -873,15 +873,15 @@ void LogViewXdrParser::fillWordList(const QString& a_line) line.replace(QLatin1Char(';'), QLatin1String(" ; ")); m_WordList = line.split(QLatin1Char(' '), Qt::SkipEmptyParts); m_WordListIndex = 0; - - - - - + // ---------------------- + // for debugging only +// foreach (const QString &str, qAsConst(m_WordList)) +// INFO_LOG(m_logger) << "word=" << str.toStdString(); + // ---------------------- } - +// --------------------------------------------------------------- QString LogViewXdrParser::getNextWord(const char *a_errorText) { QString word; @@ -901,7 +901,7 @@ QString LogViewXdrParser::getNextWord(const char *a_errorText) } - +// --------------------------------------------------------------- QString LogViewXdrParser::getNextType(bool& a_ok) { a_ok = true; @@ -918,7 +918,7 @@ QString LogViewXdrParser::getNextType(bool& a_ok) } - +// --------------------------------------------------------------- QString LogViewXdrParser::getNextEnum(const LogViewXdrStruct*& a_enumStruct) { QString type; @@ -943,15 +943,15 @@ QString LogViewXdrParser::getNextEnum(const LogViewXdrStruct*& a_enumStruct) } - +// --------------------------------------------------------------- bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const { - - +// INFO_LOG(m_logger) << "a_fieldText=" << a_fieldText.toStdString(); + // bitfield-definition: "0..2" a_firstBit = -1; a_lastBit = -1; bool isLast = true; - + // first bit int doublePointPos = a_fieldText.indexOf(QLatin1String("..")); if (doublePointPos != -1) { @@ -960,9 +960,9 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs a_firstBit = bitText.toInt(&ok); if (ok) { - + // last bit bitText = a_fieldText.mid(doublePointPos+2); - + // is it the last bitfield of this data-value (indicated by !) if (bitText.endsWith(QLatin1Char('!'))) { isLast = true; @@ -975,8 +975,8 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs a_lastBit = bitText.toInt(&ok); if (ok) { - - + // remove bitfield-stuff +// a_line = a_line.remove(bitfieldPos, endPos-bitfieldPos); } else { @@ -996,12 +996,12 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs } - - - - - - +// --------------------------------------------------------------- +// adds an element to the element-map if it does not already +// exist within this map. +// If it exists, an error-message will be raised instead and +// false will be returned. +// --------------------------------------------------------------- bool LogViewXdrParser::addToElementMap(const QString& a_name, LogViewXdrElement* a_element) { if (m_ElementMap.find(a_name) == m_ElementMap.end()) @@ -1013,5 +1013,5 @@ bool LogViewXdrParser::addToElementMap(const QString& a_name, LogViewXdrElement* return false; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.hpp index 6be48a12d..4d4460651 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrParser.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -29,14 +29,22 @@ namespace N_LogView class LogViewXdrValue; class LogViewXdrType; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 05-Feb-2010 10:46:58 + */ class LogViewXdrParser : public N_SST::IntegerCalculator { public: - - + /** + * Defines in which structure the parser is parsing now + * + * @author alois.wismer + * @version 1.0 + * @created 08-Feb-2010 17:44:52 + */ enum E_ParseState { e_ParseMain, @@ -50,24 +58,43 @@ namespace N_LogView ~LogViewXdrParser(); - - + /** + * + * @param a_fileName + */ void parseX_File(const QString& a_fileName); - - + /** + * This function delivers the name of the telegram. + * The telegram will be defined with a_telegramId. + * The name will be delivered as return-parameter. + * If the telegram was not found, error-texts instead names will be returned. + * + * @param a_telegramId + */ QString getTelegramName(int a_telegramId) const; - - + /** + * This function delivers the structure name of the telegram. + * The telegram will be defined with a_telegramId. + * The structure name will be delivered as return-parameter + * If the telegram was not found, error-texts instead names will be returned. + * + * @param a_telegramId + */ QString getStructName(int a_telegramId) const; - - + /** + * + * @param a_name + * @param a_value + */ bool getDefine(const QString& a_name, int64_t& a_value) const; - - + /** + * + * @param a_name + */ const LogViewXdrElement* getElement(const QString& a_name) const; protected: @@ -80,8 +107,10 @@ namespace N_LogView bool m_DoReadUntilSemicolon; QStringList m_WordList; int m_WordListIndex; - - + /** + * This will be used to suppress an error-message when parsing the overall + * telegram structure. + */ QString m_UnionType; std::map m_ElementMap; @@ -93,8 +122,15 @@ namespace N_LogView std::map m_TelegramMap; - - + /** + * + * @param a_name + * @param a_dataSize + * @param a_realSize + * @param a_kind + * @param a_dynArraySizeMethod + * @param a_byteOrder + */ void addStandardType(const QString& a_name, const uint16_t a_dataSize, const uint16_t a_realSize, @@ -102,76 +138,130 @@ namespace N_LogView const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod = LogViewXdrStandardType::e_DynArrayMsgLength, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian); - - + /** + * + * @param a_line + */ QString removeComments(const QString& a_line); - - + /** + * + * @param a_line + */ void parseTypedef(const QString &a_line); - - + /** + * + * @param a_line + */ void parseDefine(const QString &a_line); - - + /** + * + * @param a_line + * @param a_enumSize The size in bytes of an enum-value + */ void parseEnum(const QString &a_line, const uint16_t a_enumSize = 4); - - + /** + * + * @param a_line + */ void parseStruct(const QString &a_line); - - + /** + * + * @param a_line + */ void parseUnion(const QString& a_line); - - + /** + * + * @param a_line + * @param a_name + * @param a_value + */ bool parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const; - - + /** + * Shows an error-message containing the line-nbr, the line itself and an + * additional error-text + * + * @param a_errorText + */ void showErrorMessage(const QString& a_errorText) const; - - + /** + * + * @param a_calcText + * @param a_isOk + */ int64_t calcValue(const QString& a_calcText, bool& a_isOk); - - + /** + * + * @param a_variableName + * @param a_value + */ bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const override; - - + /** + * + * @param a_name + * @param a_dynArrayMsgOffset This offset will be used for the dyn-array-method + * e_DynArrayMsgLength. Here the value in will be subtracted from the message- + * length to get the size of the dynamic array. + */ uint16_t parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const; - - + /** + * + * @param a_word + * @param a_doIncrement + */ bool isNextWord(const char *a_word, const bool a_doIncrement = true); - - + /** + * + * @param a_line + */ void fillWordList(const QString& a_line); - - + /** + * + * @param a_errorText + */ QString getNextWord(const char *a_errorText = nullptr); - - + /** + * + * @param a_ok + */ QString getNextType(bool& a_ok); - - + /** + * + * @param a_enumStruct + */ QString getNextEnum(const LogViewXdrStruct*& a_enumStruct); - - + /** + * + * @param a_fieldText + * @param a_firstBit + * @param a_lastBit + */ bool parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const; - - + /** + * adds an element to the element-map if it does not already exist within this map. + * + * If it exists, an error-message will be raised instead and false will be + * returned. + * + * @param a_name + * @param a_element + */ bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element); private: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.cpp index b5dd4bb3f..6cf6f2f26 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.cpp @@ -1,26 +1,26 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "LogViewXdrStandardType.hpp" namespace N_LogView { - - - - +// --------------------------------------------------------------- +// (a_valueKind must be Unsigned, if a_dynArraySizeMethod is +// e_DynArray...) +// --------------------------------------------------------------- LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int a_valueSize, const int a_editSize, const E_ValueKind a_valueKind, const E_DynArraySizeMethod a_dynArraySizeMethod, E_ByteOrder a_byteOrder) @@ -33,20 +33,20 @@ LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int {} - +// --------------------------------------------------------------- uint16_t LogViewXdrStandardType::getValueSize() const { return m_ValueSize; } - +// --------------------------------------------------------------- LogViewXdrStandardType::E_ValueKind LogViewXdrStandardType::getValueKind() const { return m_ValueKind; } - +// --------------------------------------------------------------- void LogViewXdrStandardType::dump() const { INFO_LOG(m_logger) << "Element[" << getName() @@ -58,27 +58,27 @@ void LogViewXdrStandardType::dump() const << " byteOrder=" << getByteOrder(); } - +// --------------------------------------------------------------- LogViewXdrStandardType::E_DynArraySizeMethod LogViewXdrStandardType::getDynArraySizeMethod() const { return m_DynArraySizeMethod; } - +// --------------------------------------------------------------- LogViewXdrStandardType::E_ByteOrder LogViewXdrStandardType::getByteOrder() const { return m_ByteOrder; } - - - - +// --------------------------------------------------------------- +// The 'real' size of the value, which will be allowd when +// editing this value +// --------------------------------------------------------------- uint16_t LogViewXdrStandardType::getEditSize() const { return m_EditSize; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.hpp index 29a75ffa5..05e8480d8 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStandardType.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,61 +17,91 @@ namespace N_LogView { - - + /** + * This class represents the standardtypes like int, char, ... + * It holds the the size of this type and its representation to user + * (signed/unsigned value or character) + * + * @author alois.wismer + * @version 1.0 + * @created 16-Feb-2010 14:22:20 + */ class LogViewXdrStandardType final : public LogViewXdrElement { public: - - + /** + * @author alois.wismer + * @version 1.0 + * @created 16-Feb-2010 14:34:38 + */ enum E_ValueKind { - - + /** + * An unsigned 32-bit integer + */ e_Unsigned, - - + /** + * An signed 32-bit integer + */ e_Signed, - - + /** + * A floating-point number + */ e_Float, - - + /** + * A character or string + */ e_Character, - - + /** + * A boolean value + */ e_Boolean, - - + /** + * Hex-Data "0000: F7 A5 07 ..." + */ e_Data }; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 31-Mrz-2010 10:27:31 + */ enum E_ByteOrder { e_ByteOrderBigEndian, e_ByteOrderLittleEndian }; - - + /** + * @author alois.wismer + * @version 1.0 + * @created 29-Mrz-2010 13:58:44 + */ enum E_DynArraySizeMethod { - - + /** + * Size of dyn array depends on message-size (size - m_DynArrayOffset) (or no dyn + * array) + * The value within <> in struct-element will be used for m_DynArrayOffset. + */ e_DynArrayMsgLength, - - + /** + * Size of dyn array is defined by a field (StandardType must be Unsigned) + */ e_DynArrayIndex, - - + /** + * Size of dyn array is defined by a field, which will be divided by 8 (used for + * bitfields) (StandardType must be Unsigned) + */ e_DynArrayIndexDiv8 }; - - + /** + * (a_valueKind must be Unsigned, if a_dynArraySizeMethod is e_DynArray...) + * + */ LogViewXdrStandardType(const QString &a_name, const int a_valueSize, const int a_editSize, @@ -94,17 +124,20 @@ namespace N_LogView LogViewXdrStandardType::E_ByteOrder getByteOrder() const; - - + /** + * The 'real' size of the value, which will be allowd when editing this value + */ uint16_t getEditSize() const; protected: - - + /** + * The size of this value as stored data. It may be bigger as the real (edit) size. + */ int m_ValueSize; - - + /** + * The 'real' size of the value, which will be allowd when editing this value + */ int m_EditSize; E_ValueKind m_ValueKind; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.cpp index b497f4222..d23a4121e 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewXdrStruct.hpp" #include "LogViewXdrValue.hpp" @@ -18,7 +18,7 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewXdrStruct::LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize) : LogViewXdrElement(a_name, a_kind, "LogViewXdrStruct") , m_EnumSize(enumSize) @@ -32,20 +32,20 @@ LogViewXdrStruct::~LogViewXdrStruct() } - +// --------------------------------------------------------------- void LogViewXdrStruct::addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast) { m_ChildList.push_back(new LogViewXdrType(a_name, a_type, a_arraySize, a_dynArrayOffset, a_kind, a_firstBit, a_lastBit, a_isLast)); } - +// --------------------------------------------------------------- void LogViewXdrStruct::addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind) { m_ChildList.push_back(new LogViewXdrValue(a_name, a_value, a_kind)); } - +// --------------------------------------------------------------- LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const { if (m_ChildList.size() > a_childIndex) @@ -55,21 +55,21 @@ LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const } - +// --------------------------------------------------------------- LogViewXdrType* LogViewXdrStruct::getChildAsType(const uint32_t a_childIndex) const { - return static_cast(getChild(a_childIndex)); + return static_cast(getChild(a_childIndex)); // fixme: check ob es wirklich ein XdrType ist } - +// --------------------------------------------------------------- LogViewXdrValue* LogViewXdrStruct::getChildAsValue(const uint32_t a_childIndex) const { - return static_cast(getChild(a_childIndex)); + return static_cast(getChild(a_childIndex)); // fixme: check ob es wirklich ein XdrValue ist } - +// --------------------------------------------------------------- void LogViewXdrStruct::dump() const { INFO_LOG(m_logger) << "Element[" << getName().toStdString() << "]: kind=" << getKindName().toStdString() << " enumSize=" << getEnumSize(); @@ -84,7 +84,7 @@ void LogViewXdrStruct::dump() const INFO_LOG(m_logger) << "-------------- childs end -----------------"; } - +// --------------------------------------------------------------- uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) const { if (a_error) @@ -101,5 +101,5 @@ uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) c return 0; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.hpp index 8faa4ed14..47cdd3355 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrStruct.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,7 +17,7 @@ #include "LogViewXdrElement.hpp" #include - +// forward declarations from stereotyped includes namespace N_LogView { class LogViewXdrValue; @@ -29,8 +29,13 @@ namespace N_LogView namespace N_LogView { - - + /** + * This class represents elements which have childs. + * This are enum and struct. + * @author alois.wismer + * @version 1.0 + * @created 31-Mrz-2010 11:59:19 + */ class LogViewXdrStruct final : public LogViewXdrElement { public: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.cpp index c4a4b05c5..4c2825482 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.cpp @@ -1,22 +1,22 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewXdrType.hpp" namespace N_LogView { - +// --------------------------------------------------------------- LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind) : LogViewXdrElement(a_name, a_kind, "LogViewXdrElement") , m_Type(a_type) @@ -29,7 +29,7 @@ LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, con } - +// --------------------------------------------------------------- LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast) : LogViewXdrElement(a_name, a_kind, "LogViewXdrType") , m_Type(a_type) @@ -42,7 +42,7 @@ LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, con } - +// --------------------------------------------------------------- void LogViewXdrType::dump() const { INFO_LOG(m_logger) << "Element[" << getName() @@ -56,27 +56,27 @@ void LogViewXdrType::dump() const } - +// --------------------------------------------------------------- const QString& LogViewXdrType::getType() const { return m_Type; } - - - - - +// --------------------------------------------------------------- +// 0 => opaque +// 1 => normal (scalar) element +// >1 => array +// --------------------------------------------------------------- uint16_t LogViewXdrType::getArraySize() const { return m_ArraySize; } - +// --------------------------------------------------------------- bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const { - +// INFO_LOG(m_logger) << "firstBit=" << m_FirstBit << " lastBit=" << m_LastBit << " isLast=" << m_IsLast; if (m_FirstBit != -1 && m_LastBit != -1) { DEBUG_LOG(m_logger) << "MaskValue for Element " << m_Name @@ -86,9 +86,9 @@ bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString << " isLast: " << m_IsLast; uint16_t bitshift = (a_size*8)-m_LastBit-1; uint32_t mask = (1<<(m_LastBit-m_FirstBit+1))-1; - +// INFO_LOG(m_logger) << "value=" << a_value << " bitshift=" << bitshift << " mask=" << mask; a_value = (a_value >> bitshift) & mask; - + // make bold the corresponding bits in the bitfield a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_FirstBit, QLatin1String("")); a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QLatin1String("")); return m_IsLast; @@ -97,10 +97,10 @@ bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString } - +// --------------------------------------------------------------- uint16_t LogViewXdrType::getMaxArraySize() const { return m_MaxArraySize; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.hpp index a189f3764..cf13cad85 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrType.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,18 +17,43 @@ namespace N_LogView { - - + /** + * This class represents XDR-elements which have a type and an arraySize. This are + * typedefs and struct-elements. + * The arraySize has following possibilities: + * 0 => opaque + * 1 => scalar + * >1 => array + * + * @author alois.wismer + * @version 1.0 + * @created 16-Feb-2010 15:48:24 + */ class LogViewXdrType final : public LogViewXdrElement { public: - - + /** + * + * @param a_name + * @param a_type + * @param a_arraySize + * @param a_dynArrayOffset + * @param a_kind + */ LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind); - - + /** + * + * @param a_name + * @param a_type + * @param a_arraySize + * @param a_dynArrayOffset + * @param a_kind + * @param a_firstBit + * @param a_lastBit + * @param a_isLast + */ LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast); @@ -37,12 +62,19 @@ namespace N_LogView const QString& getType() const; - - + /** + * 0 => opaque + * 1 => normal (scalar) element + * >1 => array + */ uint16_t getArraySize() const; - - + /** + * + * @param a_value + * @param a_size + * @param a_tooltip + */ bool maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const; @@ -51,20 +83,27 @@ namespace N_LogView protected: QString m_Type; - - + /** + * 0 => opaque + * 1 => normal (scalar) element + * >1 => array + */ uint16_t m_ArraySize; - - + /** + * The maximum size of the array. Interesting for dynamic arrays. + */ uint16_t m_MaxArraySize; - - + /** + * The first relevant bit, if we have bitfield-enum + */ int16_t m_FirstBit; - - + /** + * The last relevant bit, if we have bitfield-enum + */ int16_t m_LastBit; - - + /** + * used to step to next values when reading out content-data of bit-fields + */ bool m_IsLast; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.cpp index 70e8a2b93..cb8baa328 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "LogViewXdrValue.hpp" @@ -17,24 +17,24 @@ namespace N_LogView { - +// --------------------------------------------------------------- LogViewXdrValue::LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind) : LogViewXdrElement(a_name, a_kind, "LogViewXdrValue") , m_Value(a_value) {} - +// --------------------------------------------------------------- void LogViewXdrValue::dump() const { INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName() << " value=" << getValue(); } - +// --------------------------------------------------------------- int64_t LogViewXdrValue::getValue() const { return m_Value; } -} +} // namespace N_LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.hpp index db8eec061..d711b4995 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/LogViewXdrValue.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,8 +17,14 @@ namespace N_LogView { - - + /** + * This class represents XDR-elements which have a value. This are #defines and + * enum-elements. + * + * @author alois.wismer + * @version 1.0 + * @created 17-Feb-2010 11:17:53 + */ class LogViewXdrValue final : public LogViewXdrElement { public: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.cpp index 8790cc277..ce2a64524 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Building Config - logging facility + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "logger.h" @@ -29,4 +34,4 @@ LOGGER_T getLogger(const char *name) } } -} +} // namespace LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.h b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.h index 8baf71f9f..2bb8a786e 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/LogView/logger.h @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Logging for AudioVideoManagement + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once @@ -14,4 +19,4 @@ inline LOGGER_T getLogger(const QString &loggerName) { return getLogger(loggerName.toUtf8().constData()); } -} +} // namespace LogView diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.cpp index c81081775..9dc6e4c81 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// +// Implementation of the Class AppComponent +// ************************************************************************** #include "AppComponent.hpp" @@ -84,5 +84,5 @@ IAppComponent *AppComponent::getChild(const QString &a_name) return nullptr; } -} +} // namespace N_AppComponent diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.hpp index 5d25e871e..cafe1014c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/AppComponent.hpp @@ -1,14 +1,14 @@ - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// +// Implementation of the Class AppComponent +// ************************************************************************** #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/IAppComponent.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/IAppComponent.hpp index 44b7138c3..0b3be5bb9 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/IAppComponent.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/IAppComponent.hpp @@ -1,14 +1,14 @@ - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// +// Implementation of the Class IAppComponent +// ************************************************************************** #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/main.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/main.cpp index 4504ff73d..f9982346f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/main.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/main.cpp @@ -13,7 +13,7 @@ int main(int argc, char **argv) { QCoreApplication app(argc, argv); - + // Check alle 30 Sekunden NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false); NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.cpp index f11c41730..0afa42cf6 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.cpp @@ -1,5 +1,9 @@ - - +/** + * Tetra-Interface für Lasttest + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "tetra_if.h" #include @@ -48,7 +52,7 @@ void TetraIF::start() void TetraIF::listenMode(const QStringList &args) { - + // take input and write them to and output directory if (args.count() > 1) usage(); m_outputDir = QCoreApplication::applicationDirPath(); @@ -177,7 +181,7 @@ void TetraIF::onReadyRead() do { DEBUG_LOG(m_logger) << "Got " << m_socket->bytesAvailable() << " bytes from socket"; - + // read the 4-byte frame-header for find out the length of whole telegram N_CoPrtCnv::CoPrtCnvRadioTelegram::PrtCnvRadioGwHeader header; if (m_socket->bytesAvailable() < int(sizeof(header))) return; @@ -234,24 +238,24 @@ void TetraIF::handleReceivedTelegram(const QByteArray &data) switch (type) { - + // response to register indication case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp: - handleRegisterRsp(data.at(5)); + handleRegisterRsp(data.at(5)); // registration status break; - + // payload telegram case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: handleDataIndReq(data); break; - + // ack-telegram - not handled here case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq: - + // handleReportIndReq(data); break; - + // air-interface-load-telegram - not handled here case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq: - + // handleAirInterfaceLoadReq(data); break; default: @@ -297,7 +301,7 @@ void TetraIF::handleRegisterRsp(const uint8_t a_registrationStatus) void TetraIF::dumpData(const QByteArray &data) { - + // im Listen-Mode -> Ausgabe in Directory if (m_outputDir.isEmpty()) return; const qint64 msecs = QDateTime::currentMSecsSinceEpoch(); @@ -332,7 +336,7 @@ void TetraIF::dumpData(const QByteArray &data) << " for writing - error: " << f.errorString(); } - + // 27 Bytes Header entfernen f.write(&data.data()[27], data.size() - 27); f.close(); } @@ -341,7 +345,7 @@ void TetraIF::dumpData(const QByteArray &data) void TetraIF::onSendData() { ++m_secondFragment; - + // we're called every 10ms if (m_secondFragment == 100) { m_secondFragment = 0; @@ -358,7 +362,7 @@ void TetraIF::onSendData() { for (unsigned short dest_issi : std::as_const(m_issiList)) { - + // GEF_BESTAETIGUNG -> Dummy, gets overridden by setPayloadDataComplete() m_data[0] = s_randomChar++; N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, m_data.size(), dest_issi); tele.setPayloadDataComplete(m_data); @@ -383,7 +387,7 @@ void TetraIF::onSendData() void TetraIF::parseISSIs(const QStringList &issiList) { m_issiList.clear(); - + // broadcast if (issiList.count() == 0) { m_issiList += 0; @@ -430,7 +434,7 @@ void TetraIF::handleDataIndReq(const QByteArray &data) break; } - delete radioTelegram; + delete radioTelegram; // this deletes also a_data } } @@ -438,7 +442,7 @@ void TetraIF::handleLoginTelegram(N_CoPrtCnv::CoPrtCnvRadioTelegram *a_loginTele { uint16_t identity = a_loginTelegram->getIdentity(); uint32_t issi = a_loginTelegram->getSrcISSI(); - + // is it a login request? if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginRequest == (a_loginTelegram->getPayloadDataUInt8(2) & N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginStatusMask)) { bool sent = sendLoginResponse(issi); @@ -456,33 +460,33 @@ bool TetraIF::sendLoginResponse(const uint32_t a_ISSI) ++m_SendCounter; N_CoPrtCnv::CoPrtCnvRadioTelegram *a_telegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(GEF_BESTAETIGUNG, 20, a_ISSI); a_telegram->setZaehler(m_SendCounter); - + // set our ISSI a_telegram->setDestISSI(a_ISSI); a_telegram->setSrcISSI(2); gef_telegramm_id_et telId = a_telegram->isNormalTelegram() ? a_telegram->getTelID() : GEF_BESTAETIGUNG; - + // send telegram to radio INFO_LOG(m_logger) << "Send telegram to radio: telId=" << telId << " wcounter=" << a_telegram->zaehler() << " size= 28"; - + // Protokoll-Byte wird hier mit als Datenbyte missbraucht... a_telegram->setProtocolIdentifier(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_TDSMessageWithoutSDS_TL); a_telegram->setPayloadData(0x01); a_telegram->setPayloadData(0x04); - - a_telegram->getData()[22] = 0x0d; + // Bitanzahl anpassen + a_telegram->getData()[22] = 0x0d; // Warum 13 (bzw. 21) ?? char *data = a_telegram->getData(); - - data[02] = 0x18; - + // Header - complete Payload in Bytes + data[02] = 0x18; // 24 Bytes + // Len in Bits data[22] = 0x0d; data[23] = 0x00; - + // Len in Bytes data[24] = 0x02; data[25] = 0x00; - + // Data data[13] = 0x00; data[26] = 0x01; data[27] = 0x40; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.h b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.h index 52bbf8ac1..e080dad3a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTest/tetra_if.h @@ -1,5 +1,9 @@ - - +/** + * Tetra-Interface für Lasttest + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once #include #include diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.cpp index 80f6259ed..da80de76d 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.cpp @@ -22,10 +22,10 @@ MainWindow::MainWindow(QWidget *parent) : MainWindow::~MainWindow() { m_files.clear(); - - - - + //m_logfile.~QString(); + //delete m_logfileList; + // m_logZeiten.~QString(); + //delete ui; } void MainWindow::changeEvent(QEvent *e) @@ -43,10 +43,10 @@ void MainWindow::changeEvent(QEvent *e) void MainWindow::init() { - + //Connect Signals & Slots connect(ui->pushButtonOrdnerFinden, &QPushButton::clicked, this, &MainWindow::slot_findFolder); connect(ui->pushButtonAnalysieren, &QPushButton::clicked, this, &MainWindow::slot_analysieren); - + //m_logfileList = new QList(); ui->progressBar->setValue(0); ui->labelResult->setText(QString()); QIntValidator intVal; @@ -57,9 +57,16 @@ void MainWindow::init() void MainWindow::slot_findFolder() { - - - + //hier liegt der fehler???, der erst beim zweiten mal ausführen des Dateibrowsers in erscheinung tritt + /*QFileDialog dial(this); + dial.setFileMode(QFileDialog::Directory); + dial.setViewMode(QFileDialog::List); + QStringList files; + if (dial.exec()) + files = dial.selectedFiles(); + QString name = files.at(0); + //testblabla + */ QString name = QFileDialog::getExistingDirectory(this, tr("Choose folder"), QDir::homePath(), QFileDialog::DontResolveSymlinks); ui->lineEditOrdner->setText(name); ui->labelResult->setText(QString()); @@ -74,7 +81,7 @@ void MainWindow::slot_analysieren() ISSI = QLatin1String("1"); m_logfileList.clear(); - + //alle DAteien in dem Ordner finden QDir folder(ui->lineEditOrdner->text()); m_files = folder.entryList(); folder.~QDir(); @@ -83,7 +90,7 @@ void MainWindow::slot_analysieren() const QString issitext = ISSI + QLatin1String("-1"); for (int i = 0; i < m_files.count(); i++) { - + //Dateinamen entfernen, die keine Payload-Logs sind QString name = m_files[i]; if (name.contains(paytext)) { @@ -136,7 +143,7 @@ void MainWindow::readFiles() QFile file(filename); if (file.open(QIODevice::ReadOnly)) { - + //Datei auslesen QByteArray ar = file.read(150); file.close(); if (ar.size() > 36) @@ -144,21 +151,21 @@ void MainWindow::readFiles() QString issi = getISSI(ar); QByteArray bytes = ar; - + //Laufende Nummer bytes.remove(0, 34); bytes.remove(2, 150); uint nr = bytes[0] & 255; nr *= 256; nr += bytes[1] & 255; - - + //BytesNr 34+35 + //Sendezeit bytes = ar; bytes.remove(0, 30); bytes.remove(4, 150); const QByteArray test = bytes.toHex(); qint64 zeit = test.toLongLong(nullptr, 16); - + //Byte 30-33 const QDateTime timeStart(QDateTime::fromMSecsSinceEpoch(zeit * 1000)); writeToLogfile(issi, timeStart, getTimestamp(m_files[j]), m_files[j], nr); @@ -172,7 +179,7 @@ void MainWindow::readFiles() val *= (j + 1); val += 20; ui->progressBar->setValue(int(val)); - + // ui->progressBar->repaint(); } } @@ -273,7 +280,7 @@ QDateTime MainWindow::getTimestamp(const QString &filename) const QString MainWindow::getISSI(QByteArray ar) { - + //wird nur für die "2-timestamp"-Dateien verwendet ar.remove(0, 5); ar.remove(4, 200); QByteArray issi = ar.toHex(); @@ -310,7 +317,7 @@ QString MainWindow::getISSI(QByteArray ar) int MainWindow::auswerten() { - + //Logfile vorbereiten QFile f(m_logfile); if (!f.open(QIODevice::Append | QIODevice::Text)) return -1; @@ -319,7 +326,7 @@ int MainWindow::auswerten() issis.reserve(100); for (int i = 0; i < m_logfileList.count(); i++) { - + //Unterschiedliche Issis finden issis += m_logfileList.at(i).issi; } ui->progressBar->setValue(94); @@ -329,7 +336,7 @@ int MainWindow::auswerten() int i = 0; for (const QString &issi : std::as_const(issis)) { - + //für jede Issi die Nummern in timestampMap einlesen --> geordnet nach Zeitstempel numList.clear(); for (int j = 0; j < m_logfileList.count(); j++) { @@ -344,7 +351,7 @@ int MainWindow::auswerten() f.write(text); fehlcount += fehlendeNumsEintragen(numList, f); - + // delete numList; double val = 5; val /= issis.count(); @@ -360,7 +367,7 @@ int MainWindow::auswerten() int MainWindow::fehlendeNumsEintragen(const QVector &numList, QFile &f) { - + //schreibt die fehlenden Nummern in das Logfile und die GUI QVector fehlendeNums = getFehlendeNums(numList); QByteArray text = QByteArray::number(fehlendeNums.count()); text += " lost messages\n"; @@ -370,7 +377,7 @@ int MainWindow::fehlendeNumsEintragen(const QVector &numList, QFile &f) text += QByteArray::number(fehlendeNums.at(j)); text += ", "; } - + // delete fehlendeNums; text += ")\n"; f.write(text); @@ -380,13 +387,13 @@ int MainWindow::fehlendeNumsEintragen(const QVector &numList, QFile &f) QVector MainWindow::getFehlendeNums(const QVector &numsDurchgang) { - + //ermittelt die fehlenden Nummern pro Durchgang uint count = numsDurchgang.count(); uint maxnum = 0; uint minnum = 999999; for (uint k = 0; k < count; k++) { - + //höchste und niedrigste Num finden if (numsDurchgang.at(k) > maxnum) maxnum = numsDurchgang.at(k); if (numsDurchgang.at(k) < minnum) @@ -396,7 +403,7 @@ QVector MainWindow::getFehlendeNums(const QVector &numsDurchgang) QVector fehlendeNum; for (uint z = minnum; z <= maxnum; z++) { - + //liste nach fehlenden werten durchsuchen bool vorhanden = false; for (uint j = 0; j < count; j++) { @@ -425,5 +432,5 @@ void MainWindow::writeLogZeiten(const QDateTime &beginn, const QDateTime &end, c file.write(msg.toUtf8()); file.close(); - + //delete end; } diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.h b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.h index 8df419f23..1f65e1165 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/LastTestAuswertung/mainwindow.h @@ -51,7 +51,7 @@ private: const QDateTime ×tamp, const QString &filename, uint lfdNr); - QString getISSI(QByteArray ar); + QString getISSI(QByteArray ar);//Für alte TPUS int auswerten(); QVector getFehlendeNums(const QVector &numsDurchgang); int fehlendeNumsEintragen(const QVector &numList, QFile &file); @@ -66,4 +66,4 @@ private slots: -#endif +#endif // MAINWINDOW_H diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.cpp index b5025e0d4..057632af4 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvApplication +// ************************************************************************** #include "PrtCnvApplication.hpp" #include "PrtCnvThreadStarter.hpp" @@ -65,9 +65,9 @@ PrtCnvApplication::~PrtCnvApplication() } - - - +// --------------------------------------------------------------- +// Synchronisation of threads before create(). +// --------------------------------------------------------------- void PrtCnvApplication::waitForCreate(const E_ThreadId a_threadId) { INFO_LOG(m_logger) << "Wait for others until we can create " << threadIdToString(a_threadId); @@ -111,9 +111,9 @@ void PrtCnvApplication::waitForCreate(const E_ThreadId a_threadId) } - - - +// --------------------------------------------------------------- +// Synchronisation of threads before init(). +// --------------------------------------------------------------- void PrtCnvApplication::waitForInit(E_ThreadId a_threadId) { INFO_LOG(m_logger) << "Wait for others until we can initialize " << threadIdToString(a_threadId); @@ -152,9 +152,9 @@ void PrtCnvApplication::waitForInit(E_ThreadId a_threadId) INFO_LOG(m_logger) << "Now we can initialize " << threadIdToString(a_threadId); } - - - +// --------------------------------------------------------------- +// Synchronisation of threads before start(). +// --------------------------------------------------------------- void PrtCnvApplication::waitForStart(E_ThreadId a_threadId) { INFO_LOG(m_logger) << "Wait for others until we can start " << threadIdToString(a_threadId); @@ -209,17 +209,17 @@ void PrtCnvApplication::waitForStart(E_ThreadId a_threadId) } - - - +// --------------------------------------------------------------- +// Synchronisation of threads before execution of thread. +// --------------------------------------------------------------- void PrtCnvApplication::waitForExec(E_ThreadId a_threadId) { setStarted(a_threadId); } - - - +// --------------------------------------------------------------- +// Starts the main-application +// --------------------------------------------------------------- void PrtCnvApplication::startApp() { createApplication(); @@ -258,9 +258,9 @@ void PrtCnvApplication::setConfigFile(const QString &configFile) m_ConfigFileName = configFile; } - - - +// --------------------------------------------------------------- +// Creates the childs +// --------------------------------------------------------------- int32_t PrtCnvApplication::createApplication() { setName(QStringLiteral("Common")); @@ -283,12 +283,12 @@ int32_t PrtCnvApplication::createApplication() return 0; } - - - +// --------------------------------------------------------------- +// Starts the childs and then the main application +// --------------------------------------------------------------- int32_t PrtCnvApplication::start() { - + // start and create threads for (const auto &ti : m_threadInfo) ti.thread->start(); @@ -298,9 +298,9 @@ int32_t PrtCnvApplication::start() } - - - +// --------------------------------------------------------------- +// Returns the desired thread-starter +// --------------------------------------------------------------- PrtCnv::PrtCnvThreadStarter *PrtCnvApplication::getThreadStarter(const E_ThreadId a_threadId) { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -334,7 +334,7 @@ void PrtCnvApplication::logWlsTelegram(const TrainingAreaBase::TetraIcd::Trainin t->writeWlsTelegramLog(tele, bIsSend, 0); } - +// --------------------------------------------------------------- bool PrtCnvApplication::isConstructed(const E_ThreadId a_threadId) const { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -343,7 +343,7 @@ bool PrtCnvApplication::isConstructed(const E_ThreadId a_threadId) const return m_threadInfo[a_threadId].isConstructed; } - +// --------------------------------------------------------------- void PrtCnvApplication::setConstructed(const E_ThreadId a_threadId) { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -352,7 +352,7 @@ void PrtCnvApplication::setConstructed(const E_ThreadId a_threadId) m_threadInfo[a_threadId].isConstructed = true; } - +// --------------------------------------------------------------- bool PrtCnvApplication::isInitialized(const E_ThreadId a_threadId) const { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -361,7 +361,7 @@ bool PrtCnvApplication::isInitialized(const E_ThreadId a_threadId) const return m_threadInfo[a_threadId].isInitialized; } - +// --------------------------------------------------------------- void PrtCnvApplication::setInitialized(const E_ThreadId a_threadId) { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -370,7 +370,7 @@ void PrtCnvApplication::setInitialized(const E_ThreadId a_threadId) m_threadInfo[a_threadId].isInitialized = true; } - +// --------------------------------------------------------------- bool PrtCnvApplication::isCreated(const E_ThreadId a_threadId) const { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -379,7 +379,7 @@ bool PrtCnvApplication::isCreated(const E_ThreadId a_threadId) const return m_threadInfo[a_threadId].isCreated; } - +// --------------------------------------------------------------- void PrtCnvApplication::setCreated(const E_ThreadId a_threadId) { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -388,7 +388,7 @@ void PrtCnvApplication::setCreated(const E_ThreadId a_threadId) m_threadInfo[a_threadId].isCreated = true; } - +// --------------------------------------------------------------- bool PrtCnvApplication::isStarted(const E_ThreadId a_threadId) const { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -397,7 +397,7 @@ bool PrtCnvApplication::isStarted(const E_ThreadId a_threadId) const return m_threadInfo[a_threadId].isStarted; } - +// --------------------------------------------------------------- void PrtCnvApplication::setStarted(const E_ThreadId a_threadId) { if (a_threadId < e_Central || a_threadId >= e_ThreadIdMax) @@ -406,4 +406,4 @@ void PrtCnvApplication::setStarted(const E_ThreadId a_threadId) m_threadInfo[a_threadId].isStarted = true; } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.hpp index 9b214bbf6..bdafaa32d 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvApplication.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvApplication +// ************************************************************************** #pragma once @@ -23,20 +23,32 @@ #include "prtcnvlib_export.h" #include - - +/** + * Here are all project specific classes of protocol-converter implemented. + */ namespace PrtCnv { class PrtCnvThreadStarter; - - + /** + * The main-application of protocol-converter. It is responsible for starting and + * controlling the threads of this application. + * + * @author alois.wismer + * @version 1.0 + * @created 23-Jun-2009 17:48:47 + */ class PRTCNVLIB_EXPORT PrtCnvApplication : public QObject, public N_AppComponent::AppComponent { Q_OBJECT public: - - + /** + * This enum will be used to unique identify the threads + * + * @author alois.wismer + * @version 1.0 + * @created 19-Jan-2010 17:09:00 + */ enum E_ThreadId { e_Central, @@ -50,8 +62,9 @@ namespace PrtCnv PrtCnvApplication(); ~PrtCnvApplication(); - - + /** + * Starts the main-application + */ void startApp(); void shutdownApp(); static void setCleanDb(bool bCleanDb); @@ -59,33 +72,51 @@ namespace PrtCnv int exerciseId() const { return m_exerciseId; } void setConfigFile(const QString &configFile); - - + /** + * Starts the childs and then the main application + */ int32_t start() override; - - + /** + * Synchronisation of threads before init(). + * + * @param a_threadId id of the calling thread + */ void waitForInit(E_ThreadId a_threadId); - - + /** + * Synchronisation of threads before start(). + * + * @param a_threadId id of the calling thread + */ void waitForStart(E_ThreadId a_threadId); - - + /** + * Synchronisation of threads before create(). + * + * @param a_threadId Id of the calling thread + */ void waitForCreate(const E_ThreadId a_threadId); - - + /** + * Synchronisation of threads before execution of thread. + * + * @param a_threadId id of the calling thread + */ void waitForExec(E_ThreadId a_threadId); - - + /** + * Returns the desired thread-starter + * + * @param a_threadId Id of the desired thread-started (corresponding thread has + * the same id) + */ PrtCnvThreadStarter* getThreadStarter(const E_ThreadId a_threadId); - - + /** + * @brief Set the database connection parameter when used as library + */ void setDatabaseConnectionParams(const QString &driver, const QString &hostName, const QString &database, @@ -108,45 +139,59 @@ signals: void outgoingBroadcastTelegramsRequest(int equipmentNumber, int broadcastIndex, int resetCounter); void warehouseMessageFromPtrCnv(const QByteArray &jsonData); protected: - - + /** + * Creates the childs + */ int32_t createApplication(); - - + /** + * Returns true when the specified thread is + * already constructed + */ bool isConstructed(const E_ThreadId a_threadId) const; - - + /** + * The specifed thread is now constructed + */ void setConstructed(const E_ThreadId a_threadId); - - + /** + * Returns true when the specified thread is + * already initialized + */ bool isInitialized(const E_ThreadId a_threadId) const; - - + /** + * The specifed thread is now initialized + */ void setInitialized(const E_ThreadId a_threadId); - - + /** + * Returns true when the specified thread is + * already created + */ bool isCreated(const E_ThreadId a_threadId) const; - - + /** + * The specifed thread is now created + */ void setCreated(const E_ThreadId a_threadId); - - + /** + * Returns true when the specified thread is + * already started + */ bool isStarted(const E_ThreadId a_threadId) const; - - + /** + * The specifed thread is now started + */ void setStarted(const E_ThreadId a_threadId); protected: - - + /** + * Used to get configuration-parameter + */ NGL::Settings *m_Config; struct ThreadInfo @@ -157,11 +202,13 @@ protected: bool isInitialized = false; bool isStarted = false; } m_threadInfo[e_ThreadIdMax]; - - + /** + * The name of the config-file + */ QString m_ConfigFileName; - - + /** + * The exerciseId (or zero if not set) + */ int m_exerciseId; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.cpp index 3b897c195..5371a6c6a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.cpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #include "PrtCnvBroadcastMgr.hpp" #include @@ -40,18 +40,18 @@ PrtCnvBroadcastMgr::PrtCnvBroadcastMgr() : m_ClaimWindow(0) { } - - - +// --------------------------------------------------------------- +// Creates all subcomponents +// --------------------------------------------------------------- int32_t PrtCnvBroadcastMgr::create(NGL::Settings *settings) { m_Config = settings; return 0; } - - - +// --------------------------------------------------------------- +// Initializes the variables. +// --------------------------------------------------------------- int32_t PrtCnvBroadcastMgr::init() { const QString broadcastGroup(QStringLiteral("Broadcast")); @@ -59,10 +59,10 @@ int32_t PrtCnvBroadcastMgr::init() 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)); - + // the time [ms] to wait between sending broadcasts 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_HighLoadFactor = m_Config->getInteger(broadcastGroup, QStringLiteral("HighLoadFactor"), 3); // fixme: in spec steht 90sec normal und 3min für high m_BroadcastLimit = m_Config->getInteger(broadcastGroup, QStringLiteral("BroadcastLimit"), 10); cleanAndInit(true); @@ -73,20 +73,20 @@ int32_t PrtCnvBroadcastMgr::init() } - - - - +// --------------------------------------------------------------- +// sets the DbThread used for get the stored broadcast- +// telegrams +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::setDbThread(PrtCnvDbThread *a_dbThread) { m_DbThread = a_dbThread; } - - - - +// --------------------------------------------------------------- +// Initializes the broadcast-manager. If a_deleteTelegrams is +// true, all stored telegrams and maps will be deleted. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::cleanAndInit(const bool a_deleteTelegrams) { if (a_deleteTelegrams) @@ -102,10 +102,10 @@ void PrtCnvBroadcastMgr::cleanAndInit(const bool a_deleteTelegrams) m_BroadcastMap.clear(); - m_LastTelegramMap.clear(); - m_FunktionsraumTelegramMap.clear(); - m_WirkfeldTelegramMapByKennung.clear(); - m_WirkfeldTelegramMapByTime.clear(); + m_LastTelegramMap.clear(); // the telegrams itself were already deleted while looping through broadcastmap + m_FunktionsraumTelegramMap.clear(); // the telegrams itself were already deleted while looping through broadcastmap + m_WirkfeldTelegramMapByKennung.clear(); // the telegrams itself were already deleted while looping through broadcastmap + m_WirkfeldTelegramMapByTime.clear(); // the telegrams itself were already deleted while looping through broadcastmap m_BroadcastIndex = 0; } @@ -121,9 +121,9 @@ void PrtCnvBroadcastMgr::cleanAndInit(const bool a_deleteTelegrams) m_FirstBroadcastIndexOfBc1 = 0; } - - - +// --------------------------------------------------------------- +// returns true when the telegram should be sent to central +// --------------------------------------------------------------- bool PrtCnvBroadcastMgr::handleRadioTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram) { switch (a_radioTelegram.getTelID()) @@ -134,15 +134,15 @@ bool PrtCnvBroadcastMgr::handleRadioTelegram(const N_CoPrtCnv::CoPrtCnvRadioTele a_radioTelegram.getPayloadDataUInt8(7)); return false; default: - + // nothing break; } - return true; + return true; // => send the telegram to central } - - - +// --------------------------------------------------------------- +// Adds the TNE to the nachforderungs-list +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::handleNachforderungBroadcastTelegram(int identity, int broadcastIndex, int resetCounter) { INFO_LOG(m_loggerBcRequest) << "Got NachforderungBroadcast from TNE with id=" << identity @@ -152,7 +152,7 @@ void PrtCnvBroadcastMgr::handleNachforderungBroadcastTelegram(int identity, int if (resetCounter == m_DbThread->getResetCounter()) { m_DbThread->incClaimCount(identity); - + // already in there? for (auto &ebi : m_claimerArray) { if (ebi.equipNo == identity) @@ -170,90 +170,90 @@ void PrtCnvBroadcastMgr::handleNachforderungBroadcastTelegram(int identity, int } - - - - +// --------------------------------------------------------------- +// returns the next normal broadcast to send. +// Use the same a_currentTime in one tick-loop. +// --------------------------------------------------------------- std::shared_ptr PrtCnvBroadcastMgr::getNextBroadcastTelegramToSend(const uint16_t a_beginSearchWithBroadcastIndex, const time_t a_currentTime) { - - - + // iterate the braodcast-list and get the next broadcast to send + // but check whether it is not a sammeltelegram or has an attached + // broadcast-only-telegram 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(); - + // the following telegrams will never be sent as normal broadcast if (GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM == telId || GEF_WF_SAMMELDEAKTIVIERUNG == telId || GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN == telId) { - + // respect an attached broadcast-only-telegram, otherwise step to next telegram if (!broadcastTelegram->getBroadcastonlyTelegram()) { ++iter; continue; } } - + // use the attached broadcast-only-telegram if there is one bool isBcOnly = false; if (broadcastTelegram->getBroadcastonlyTelegram()) { broadcastTelegram = broadcastTelegram->getBroadcastonlyTelegram(); isBcOnly = true; } - + // check whether it is time to send this broadcast-telegram the 2nd or 3rd time bool wasLast = false; if (broadcastTelegram->mustBeSentAsBroadcast(a_currentTime, wasLast)) { - + // remove a 3rd-time-sent broadcast-only from all maps if (wasLast) { if (isBcOnly || broadcastTelegram->isBroadcastOnly()) { - removeFromAllMaps(broadcastTelegram); + removeFromAllMaps(broadcastTelegram); // this will destroy our iterator, but we don't need it anymore... } else { - + // time-optimizing: 3rd-time sent broadcast-telegrams must no longer be examined m_FinishedBroadcastIndex = broadcastTelegram->getBroadcastIndex(); } } - + // the identity could be dirty, because it could be sent as directed nachforderung in past broadcastTelegram->setIdentity(0); return broadcastTelegram; } else { - - - - - - - - - - - - - - - - - - - - + // this broadcast-telegram must not yet be sent + // ------------------------------------------------------------------------------------ + // optimize by time: + // Beside the fact that the m_BroadcastMap is ordered by BC-index there is also another + // implicit order: first come all 3rd time sent telegramms, then all 2nd time sent + // telegrams and finally all 1st time sent telegrams. Furthermore, the 3rd time sent + // telegrams are ordered ascending by nextsendtime. The same order exists also for 2nd + // and 1st time sent telegrams. This allows us some optimizings. + // Example: + // BC-index broadcast-counter next-send-time + // 1 3 0 + // 2 3 0 + // 3 2 1000 + // 4 2 1000 + // 5 2 1001 + // 6 2 1005 + // 7 1 1000 + // 8 1 1001 + // 9 1 1001 + // ------------------------------------------------------------------------------------- uint16_t bcCounter = broadcastTelegram->getBroadcastCounter(); if (2 == bcCounter) { - - + // step to first telegram with bc-counter == 1, because all other telegrams will have same + // or higher nextsendtime if (m_FirstBroadcastIndexOfBc1 > iter->first) { iter = m_BroadcastMap.lower_bound(m_FirstBroadcastIndexOfBc1); @@ -263,7 +263,7 @@ std::shared_ptr PrtCnvBroadcastMgr::getNextBr else if (1 == bcCounter) { m_FirstBroadcastIndexOfBc1 = broadcastTelegram->getBroadcastIndex(); - return nullptr; + return nullptr; // break, because all further telegrams will have same or higher nextsendtime } } ++iter; @@ -272,24 +272,24 @@ std::shared_ptr PrtCnvBroadcastMgr::getNextBr } - - - +// --------------------------------------------------------------- +// returns the next broadcast to send for nachforderungen +// --------------------------------------------------------------- std::shared_ptr PrtCnvBroadcastMgr::getNextNachforderungTelegramToSend() { removeExpiredTelegrams(); switch (m_State) { case e_ST_COLLECT: - + // is the claim-window elapsed (usually 30 sec)? if (m_TickCounter >= m_ActClaimWindow && !m_IsFullLoad) { - + // yes, the window has elapsed prepareForSendNachforderungen(); } else { - + // the claim-window has not elapsed getAllFinishedBroadcastsFromDb(); } break; @@ -304,17 +304,17 @@ std::shared_ptr PrtCnvBroadcastMgr::getNextNa } - - - +// --------------------------------------------------------------- +// Takes expired wirkfeld-telegrams out of maps. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::removeExpiredTelegrams() { const time_t now = time(nullptr); auto iter = m_WirkfeldTelegramMapByTime.begin(); while (iter != m_WirkfeldTelegramMapByTime.end()) { - - + // 5 Sekunden warten wir noch da sonst ggf. Wirkfelder mit Wirkzeiten < 5 Sekunden + // schon rausfallen bevor sie ins Gefechtsfeld gesendet wurden. if (iter->first + 5 > now) return; @@ -328,22 +328,22 @@ void PrtCnvBroadcastMgr::removeExpiredTelegrams() } - - - +// --------------------------------------------------------------- +// Prepares values for start sending nachforderungen +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::prepareForSendNachforderungen() { - + // are there any broadcast nachforderungen? m_TickCounter = 0; if (!m_claimerArray.empty()) { dump(); - - + // yes, there are any nachforderungen + // do we have to send them directed or broadcasted? m_State = e_ST_SEND_NACHFORDERUNG; - + // fill the receiver-map std::swap(m_claimerArray, m_claimerArray); std::sort(m_claimerArray.begin(), m_claimerArray.end(), [] (const EquipNoBcIndex &a, const EquipNoBcIndex &b) @@ -353,7 +353,7 @@ void PrtCnvBroadcastMgr::prepareForSendNachforderungen() return a.equipNo < b.equipNo; }); - + // evaluate if we begin with sending directed or broadcasted INFO_LOG(m_loggerBcRequest) << "BroadcastLimit: " << m_BroadcastLimit; if (m_claimerArray.size() > m_BroadcastLimit) { @@ -361,7 +361,7 @@ void PrtCnvBroadcastMgr::prepareForSendNachforderungen() m_claimerArray.emplace_back(0, m_claimerArray.begin()->bcIndex); } - + // now build up the telegrams for (const EquipNoBcIndex &enbi : m_claimerArray) { int curBcIndex = enbi.bcIndex; @@ -374,7 +374,7 @@ void PrtCnvBroadcastMgr::prepareForSendNachforderungen() if (tel) { auto copy(std::make_shared(*tel)); - copy->setIdentity(enbi.equipNo); + copy->setIdentity(enbi.equipNo); // issi is set during sending m_broadcastTelegamsToSend.push_back(copy); } else @@ -387,7 +387,7 @@ void PrtCnvBroadcastMgr::prepareForSendNachforderungen() 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 bcIndexA > bcIndexB; // reverse, we use back()/pop_back() return a->getIdentity() < b->getIdentity(); }); @@ -405,9 +405,9 @@ void PrtCnvBroadcastMgr::prepareForSendNachforderungen() } - - - +// --------------------------------------------------------------- +// returns the next nachforderung to send +// --------------------------------------------------------------- std::shared_ptr PrtCnvBroadcastMgr::evaluateNextNachforderungToSend() { if (m_broadcastTelegamsToSend.empty()) @@ -443,7 +443,7 @@ std::shared_ptr PrtCnvBroadcastMgr::createAcc DEBUG_LOG(m_loggerBcRequest) << " bcIndex: " << it.key() << ", id: " << it.value(); - + // the asserts are only sanity checks - should never happen auto itStart = bcIndex2Type.lowerBound(startBcIndex); if (itStart == bcIndex2Type.end()) { @@ -487,13 +487,13 @@ std::shared_ptr PrtCnvBroadcastMgr::createAcc std::advance(itStart, curIdStart); - + // hdr (3 bytes) + bc idx + sum field auto tele(std::make_shared(telId, 3 + 2 + sizeOfSumField + sizeof(uint16_t) * idsToSendNow, 0)); tele->setPayload2Byte(curBcIndex); if (sizeOfSumField == 1) - tele->setPayload1Byte(idsToSendNow); + tele->setPayload1Byte(idsToSendNow); // #Ids else if (sizeOfSumField == 2) - tele->setPayload2Byte(idsToSendNow); + tele->setPayload2Byte(idsToSendNow); // #Ids else { Q_ASSERT(false); @@ -532,7 +532,7 @@ std::shared_ptr PrtCnvBroadcastMgr::createAcc { if (m_activatedDusMines.isEmpty()) return {}; - + // we currently only can have exactly *one* telegram of this type (with max. 500 entries) const int idsToSendNow = m_activatedDusMines.size(); if (idsToSendNow > 500) { @@ -550,19 +550,19 @@ std::shared_ptr PrtCnvBroadcastMgr::createAcc } - - - - - - - - - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- std::shared_ptrPrtCnvBroadcastMgr::getNachforderungsTelegram(int curBcIndex, int startBcIndex, int &nextBcIndex) @@ -589,8 +589,8 @@ std::shared_ptrPrtCnvBroadcastMgr::getNachfor if (nextBcIndex < iter->first) { - - + // do we have gaps or is it a broadcast-only telegram => send NOP-telegram + // but iterate for summarize all broadcast-only and gaps doSendNop = true; nextBcIndex = iter->first; } @@ -621,7 +621,7 @@ std::shared_ptrPrtCnvBroadcastMgr::getNachfor break; } - + // when we got a tele but have to send a nop first, wait for the next iteration and return nop now if (retTele && doSendNop) break; ++nextBcIndex; @@ -631,8 +631,8 @@ std::shared_ptrPrtCnvBroadcastMgr::getNachfor } } - - + // due to some asyncs during startup it *may* happen that the last entry(ies) of + // the broadcast map are empty - make sure that we send a nop for them if (!doSendNop && nextBcIndex <= m_BroadcastIndex) { nextBcIndex = m_BroadcastIndex + 1; @@ -641,7 +641,7 @@ std::shared_ptrPrtCnvBroadcastMgr::getNachfor if (doSendNop) { - + // return a NOP-telegram since next tele is a 'normal' telegram to send INFO_LOG(m_loggerBcRequest) << "Returning NOP: " << curBcIndex << " to " << nextBcIndex - 1; return getNopTelegram(curBcIndex, nextBcIndex - 1); } @@ -650,18 +650,18 @@ std::shared_ptrPrtCnvBroadcastMgr::getNachfor } - - - - - +// --------------------------------------------------------------- +// Gets the braodcast-telegrams from Db, which were sent 1st +// time and adds them to the maps. Expired telegrams will be +// removed. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::getAllFinishedBroadcastsFromDb(const bool a_doRestore) { - - + // => get all broadcasts which are sent first time; replace some telegrams with + // sammeltelegrams or NOP-telegrams - - + // Attention: this must only be done, when we are not sending broadcast-nachforderungen, + // because otherwise we could change sammeltelegrams which are already sent. uint16_t broadcastIndex = 0; while (true) @@ -673,21 +673,21 @@ void PrtCnvBroadcastMgr::getAllFinishedBroadcastsFromDb(const bool a_doRestore) INFO_LOG(m_logger) << "Move Broadcast-telegram from DbThread>BroadcastMgr with telId=" << radioTelegram->getTelID() << " BC=" << broadcastIndex; dumpTelegram(m_logger, broadcastIndex, radioTelegram.get()); - - - - - - - - - - - + // abgelaufene Telegramme hier *nicht* loeschen da sonst z.B. WF_FL_FEUER_STOP/FORTSETZEN + // spaeter nicht beachtet werden und WF_FL_FEUER nicht aus der Broadcastliste + // entfernt wird. außerdem hätten wir so eine andere Ausgangsbasis als wenn der PrtCnv + // nicht neu gestartet wurde was u.U. auch woanders noch zu Problemen führt. + //if (radioTelegram->hasExpired()) + //{ + // INFO_LOG(m_logger) << "Telegram with BC " << broadcastIndex + // << " is expired - throwing away"; + // delete radioTelegram; + //} + //else { addToBroadcastMap(radioTelegram); } - + // remake overrun when restoring if (a_doRestore && MAX_BROADCAST_INDEX == broadcastIndex) handleOverrunOfBroadcastCounter(a_doRestore); } @@ -703,7 +703,7 @@ void PrtCnvBroadcastMgr::getAllFinishedBroadcastsFromDb(const bool a_doRestore) } } - + // set the actual BC-index if (a_doRestore) { m_BroadcastIndex = broadcastIndex; @@ -712,22 +712,22 @@ void PrtCnvBroadcastMgr::getAllFinishedBroadcastsFromDb(const bool a_doRestore) } - - - - +// --------------------------------------------------------------- +// adds the radio-telegram to the broadcast-map, or generates +// the sammeltelegramme +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptr &a_radioTelegram) { INFO_LOG(m_logger) << "Move from radioList to bcList: BC=" << a_radioTelegram->getBroadcastIndex() << " telID=" << a_radioTelegram->getTelID(); switch (a_radioTelegram->getTelID()) { - + // following telegrams should never be broadcasts 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; - + // the following telegrams should only be sent as normal broadcast (not as Nachforderung) case GEF_DATENVERKEHR_TDS_SRT: case GEF_DATENVERKEHR_TDS_DMF: case GEF_TREFFER_AUSLOESUNG: @@ -735,7 +735,7 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetPayloadDataUInt32(5, 2); INFO_LOG(m_logger) << "Adding to braodcast map, Telegram Id: " << a_radioTelegram->getTelID() << ", kennung: " << wirkfeldKennung; @@ -770,18 +770,18 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetTelID()) { case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP: - + // remove the corresponding FeuerFortsetzen telegram addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung, GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN); break; case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN: - + // remove the corresponding FeuerStop telegram 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: - + // remove the corresponding deactivierung_einzelmine telegrams addWirkfeldTelegram(a_radioTelegram, wirkfeldKennung, GEF_DEAKTIVIERUNG_EINZELMINE); break; default: @@ -791,12 +791,12 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetBroadcastIndex(), a_radioTelegram)); } else { - + // this should never happen, because CoPrtCnvRadioTelegram::isContentValid() filters this out ERROR_LOG(m_logger) << "Internal error: Got invalid kennung: " << wirkfeldKennung; } break; @@ -821,12 +821,12 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetBroadcastIndex(); 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::MineArea: // Minensperre + case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionArea: // Steilfeuer Fläche + case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionSingle: // Steilfeuer Einzel + case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::NContamination: // A-Waffe + case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::CContamination: // C-Waffe + case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DusSingleMineSimulator: // DUS-Einzelminensimulator case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DangerZoneExplosion: if (0 != wirkfeldKennung && wirkfeldKennung <= 32767) { @@ -838,13 +838,13 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetBroadcastIndex(), a_radioTelegram)); @@ -865,31 +865,31 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetPayloadDataUInt32(5, 2); - + // remove an old already existing funktionsraum-telegram with this kennung removeFromTechnikFunktionsAndBroadcastMaps(funktionsraumkennung); - + // insert the funktionsraum-telegram m_TechnikFunktionsraumTelegramMap.insert(std::make_pair(funktionsraumkennung, a_radioTelegram)); - + // the original telegram will be added to broadcast-list m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram)); break; } case GEF_FUNKTIONSRAUM: { - + // take funktionsraum to be (re)activated out of sammeltelegram of deactivated funktionsräume uint16_t funktionsraumkennung = a_radioTelegram->getPayloadDataUInt32(5, 2); - + // remove an old already existing funktionsraum-telegram with this kennung removeFromFunktionsAndBroadcastMaps(funktionsraumkennung); removeFromDeactivatedFuncArea(funktionsraumkennung); - + // insert the funktionsraum-telegram m_FunktionsraumTelegramMap.insert(std::make_pair(funktionsraumkennung, a_radioTelegram)); - + // the original telegram will be added to broadcast-list m_BroadcastMap.insert(std::make_pair(a_radioTelegram->getBroadcastIndex(), a_radioTelegram)); break; } @@ -909,7 +909,7 @@ void PrtCnvBroadcastMgr::addToBroadcastMap(const std::shared_ptrgetBroadcastIndex(), a_radioTelegram)); } - +// dump(); } @@ -944,7 +944,7 @@ bool PrtCnvBroadcastMgr::removeFromDeactivatedAesArea(int aesAreaId) return removeFromContainers(m_deactivatedAesArea2bcIndex, m_deactivatedBcIndex2AesArea, aesAreaId); } - +// returns true when added bool PrtCnvBroadcastMgr::addToDeactivatedAesArea(int aesAreaId, int bcIndex) { return addToContainers(m_deactivatedAesArea2bcIndex, m_deactivatedBcIndex2AesArea, aesAreaId, bcIndex); @@ -980,14 +980,14 @@ void PrtCnvBroadcastMgr::addToActivatedDusMine(int dusMineId) m_activatedDusMines.insert(dusMineId); } - - - - +// --------------------------------------------------------------- +// searches the kennung within sammeltelegram. +// returns -1 when kennung not found +// --------------------------------------------------------------- int PrtCnvBroadcastMgr::getSammeltelegramIndex(const std::shared_ptr &a_sammelTelegram, const uint16_t a_kennung) const { - + // decide the length of anzahl uint16_t nbrLength = 0; switch (a_sammelTelegram->getTelID()) { @@ -1003,7 +1003,7 @@ int PrtCnvBroadcastMgr::getSammeltelegramIndex(const std::shared_ptrgetBroadcastIndex(), a_radioTelegram)); } else { - + // normal mine => change mine in "wirkfeldStatusMinensperre" bool sentAsNormalBroadcastFinished = deactivateEinzelmineFromMinensperre(wirkfeldkennung, minenkennung, a_radioTelegram->getBroadcastIndex()); if (sentAsNormalBroadcastFinished) { - + // add the deactivierungEinzelmine-telegram as broadcast-only-telegram addWirkfeldTelegram(a_radioTelegram, wirkfeldkennung, GEF_BESTAETIGUNG, minenkennung); addBroadcastOnlyTelegramToMap(a_radioTelegram); } else { - - - - - + // the wirkfeldstatusMinensperre-telegram has changed while sending it as normal broadcast is not yet + // finished => we not add the deactiveEinzelmine-telegram as broadcast-only, so the updated wirkfeld- + // statusMinensperre-telegram will be sent as normal broadcast-telegram. The deactivateEinzelmine- + // telegram must be deleted + // delete a_radioTelegram; // no longer needed, shared_ptr } } } - - - - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- bool PrtCnvBroadcastMgr::deactivateEinzelmineFromMinensperre(const uint16_t a_wirkfeldKennung, const uint16_t a_minenKennung, const uint16_t a_broadcastIndex) { - + // search the corresponding "WirkfeldstatusMinensperre"-telegram in the broadcast-map auto iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung); while (iter != m_WirkfeldTelegramMapByKennung.end()) { @@ -1074,25 +1074,25 @@ bool PrtCnvBroadcastMgr::deactivateEinzelmineFromMinensperre(const uint16_t a_wi auto radioTelegram = iter->second; if (radioTelegram->getTelID() == GEF_WIRKFELD_STATUS_MINENSPERRE && a_wirkfeldKennung == radioTelegram->getPayloadDataUInt32(5, 2)) { - + // check whether the minekennung is valid uint16_t nbrOfMines = radioTelegram->getPayloadDataUInt32(7, 2); if (nbrOfMines >= a_minenKennung && a_minenKennung != 0) { - - + // calc the position of mine + // definition: The first mine is mine 1; MSB is bit 0 => mine 1 is bit 7; mine 2 is bit 6; ... mine 8 is bit 0; Mine 9 is bit 7 (of next byte)... uint16_t bytePos = 9 + (a_minenKennung - 1) / 8; if (bytePos < radioTelegram->getPayloadSize()) { uint8_t mask = 0x80 >> ((a_minenKennung - 1) % 8); - - +// INFO_LOG(m_logger) << "pos=" << (pos-9) << " mask=" << (int)mask; + // clear the bit for the mine radioTelegram->setPayloadDataWithIndex(bytePos, (uint8_t)(radioTelegram->getPayloadDataUInt8(bytePos) & (~mask)), 1); moveTelegramInBroadcastMap(radioTelegram, a_broadcastIndex); - - - - + // if we have a corresponding wirkstatus-minensperre which was not sent 3 times as normal broadcast, + // we have to take it out and to send the new wirkfeldstatus-minensperre-telegram instead. Also all + // the deactivate einzelmine-telegrams must not be stored within the broadcast-list as broadcast-only + // telegram, therefore we return false bool dummy; if (radioTelegram->mustBeSentAsBroadcast(std::numeric_limits::max(), dummy, false)) { @@ -1106,7 +1106,7 @@ bool PrtCnvBroadcastMgr::deactivateEinzelmineFromMinensperre(const uint16_t a_wi } else { - + // minenkennung is too big to fit into statusMinensperre => Errormessage, do not update in status, but send as normal broadcast ERROR_LOG(m_logger) << "Mine with kennung=" << a_minenKennung << " does not fit into status (nbrOfMines=" << nbrOfMines << ")"; } return true; @@ -1119,14 +1119,14 @@ bool PrtCnvBroadcastMgr::deactivateEinzelmineFromMinensperre(const uint16_t a_wi } - - - - +// --------------------------------------------------------------- +// Handles the REAKTIVIERUNG_DUS_MINE-telegram for normal- +// broadcasts and nachforderungen. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::reactivateDusMine(const std::shared_ptr &a_radioTelegram) { - - const uint32_t nbrOfMines = a_radioTelegram->getPayloadDataUInt32(5, 2); + // take all DUS-mines to be reactivated out of sammeltelegram of deactivated DUS-mines + const uint32_t nbrOfMines = a_radioTelegram->getPayloadDataUInt32(5, 2); // #mines is 2 bytes DEBUG_LOG(m_logger) << "Reactivating DUS-Mines, #mines: " << nbrOfMines; if (0 == nbrOfMines) @@ -1142,7 +1142,7 @@ void PrtCnvBroadcastMgr::reactivateDusMine(const std::shared_ptrgetPayloadDataUInt32(7 + 2 * i, 2); @@ -1162,23 +1162,23 @@ void PrtCnvBroadcastMgr::reactivateDusMine(const std::shared_ptr &a_radioTelegram, const uint16_t a_wirkfeldKennung, const gef_telegramm_id_et a_telId, const uint16_t a_minenKennung) { - + // remove an old already existing wirkfeld-telegram with this kennung auto iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung); while (iter != m_WirkfeldTelegramMapByKennung.end()) { if (iter->first != a_wirkfeldKennung) break; auto radioTelegram = iter->second; - + // same mineindex (only for "Deaktivierung_Einzelmine")? bool isSameMine = true; if (0 != a_minenKennung) { @@ -1194,18 +1194,18 @@ void PrtCnvBroadcastMgr::addWirkfeldTelegram(const std::shared_ptrgetTelID() == a_radioTelegram->getTelID() || radioTelegram->getTelID() == a_telId) && isSameMine) { - - removeFromWirkfeldAndBroadcastMaps(iter); + // remove the old telegram from wirkfeld- and broadcast-map + removeFromWirkfeldAndBroadcastMaps(iter); // iterator is corrupt after calling this function ... iter = m_WirkfeldTelegramMapByKennung.find(a_wirkfeldKennung); } else ++iter; } - + // now add the new wirkfeld-telegram INFO_LOG(m_logger) << "Add kennung: " << a_wirkfeldKennung << " telId=" << a_radioTelegram->getTelID() << " BC=" << a_radioTelegram->getBroadcastIndex(); @@ -1216,16 +1216,16 @@ void PrtCnvBroadcastMgr::addWirkfeldTelegram(const std::shared_ptrgetExpireTime(); if (0 != expireTime) { @@ -1336,19 +1336,19 @@ void PrtCnvBroadcastMgr::removeFromWirkfeldAndBroadcastMaps(const std::multimap< } - - - - - - - - - - +// --------------------------------------------------------------- +// 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. +// ATTENTION: iterators to m_BroadcastMap could be invalid +// after calling this function +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::removeFromBroadcastMap(const std::shared_ptr &a_radioTelegram) { - + // remove from broadcast-map if (!a_radioTelegram) return; @@ -1402,82 +1402,82 @@ void removeFromMap(T &cont, const std::shared_ptr &a_radioTelegram) { INFO_LOG(m_logger) << "Remove telegram with telId=" << a_radioTelegram->getTelID() << " BC=" << a_radioTelegram->getBroadcastIndex(); removeFromBroadcastMap(a_radioTelegram); - + // remove from byWirkfeldKennung-map removeFromMap(m_WirkfeldTelegramMapByKennung, a_radioTelegram); - + // remove from byWirkfeldTime-map removeFromMap(m_WirkfeldTelegramMapByTime, a_radioTelegram); - + // remove from funktionsraum-map removeFromMap(m_FunktionsraumTelegramMap, a_radioTelegram); - + // remove from last-telegram-map removeFromMap(m_LastTelegramMap, a_radioTelegram); } - - - +// --------------------------------------------------------------- +// used for telegrams that must only exists once in BC-list +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::replaceLastTelegramAndAddAtEnd(const std::shared_ptr &a_newRadioTelegram) { - + // do we have a last telegram? auto iter = m_LastTelegramMap.find(a_newRadioTelegram->getTelID()); if (iter != m_LastTelegramMap.end()) { auto lastRadioTelegram = iter->second; - + // yes => replace the last telegram with NOP INFO_LOG(m_logger) << "remove last telegram with telId=" << lastRadioTelegram->getTelID() << " and BC=" << lastRadioTelegram->getBroadcastIndex(); removeFromBroadcastMap(lastRadioTelegram); m_LastTelegramMap.erase(iter); } - + // insert the new telegram into BC-list m_BroadcastMap.insert(std::make_pair(a_newRadioTelegram->getBroadcastIndex(), a_newRadioTelegram)); - + // and insert into last-telegram-list 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(); } - - - - - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::moveTelegramInBroadcastMap(const std::shared_ptr &a_radioTelegram, const uint16_t a_newBroadcastIndex, const std::shared_ptr &a_attachTelegram) { - + // remove the old telegram from map (and detach) INFO_LOG(m_logger) << "Move telId=" << a_radioTelegram->getTelID() << " from BC=" << a_radioTelegram->getBroadcastIndex() << " to BC=" << a_newBroadcastIndex; removeFromBroadcastMap(a_radioTelegram); - + // insert telegram a end a_radioTelegram->setBroadcastIndex(a_newBroadcastIndex); m_BroadcastMap.insert(std::make_pair(a_newBroadcastIndex, a_radioTelegram)); - + // attach a_attachTelegram if (a_attachTelegram && (a_attachTelegram->getTelID() != GEF_REAKTIVIERUNG_DUS_MINE)) { INFO_LOG(m_logger) << "Attach telID=" << a_attachTelegram->getTelID() @@ -1489,52 +1489,52 @@ void PrtCnvBroadcastMgr::moveTelegramInBroadcastMap(const std::shared_ptr PrtCnvBroadcastMgr::getNopTelegram(const uint16_t a_from, const uint16_t a_to) { auto nopTelegram(std::make_shared(GEF_NOP, 7, 0)); - nopTelegram->setPayloadDataWithIndex(3, a_from, 2); - nopTelegram->setPayloadDataWithIndex(5, a_to, 2); + nopTelegram->setPayloadDataWithIndex(3, a_from, 2); // Feld Anfang + nopTelegram->setPayloadDataWithIndex(5, a_to, 2); // Feld Ende return nopTelegram; } - - - - - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::addBroadcastOnlyTelegramToMap(const std::shared_ptr &a_broadcastOnlyTelegram) { uint16_t broadcastIndex = a_broadcastOnlyTelegram->getBroadcastIndex(); auto iter = m_BroadcastMap.find(broadcastIndex); if (m_BroadcastMap.end() == iter) { - + // insert as braodcast-only marked telegram INFO_LOG(m_logger) << "Insert telId=" << a_broadcastOnlyTelegram->getTelID() << " as broadcastonly telegram with BC=" << broadcastIndex; a_broadcastOnlyTelegram->setBroadcastOnly(); @@ -1542,7 +1542,7 @@ void PrtCnvBroadcastMgr::addBroadcastOnlyTelegramToMap(const std::shared_ptr reduce broadcast-list and increment reset-counter"; - - + // first we must wait until all data are stored in DB, otherwise we will loose + // the broadcast-telegrams, which were sent the 1st time, but not yet stored permanent if (!a_doRestore) { m_DbThread->waitUntilDbWritten(); getAllFinishedBroadcastsFromDb(); } - + // reduce the broadcast-list uint16_t newBroadcastCounter = 0; std::map> newBroadcastMap; auto iter = m_BroadcastMap.begin(); @@ -1603,8 +1603,8 @@ void PrtCnvBroadcastMgr::handleOverrunOfBroadcastCounter(const bool a_doRestore) auto radioTelegram = iter->second; if (radioTelegram->isBroadcastOnly()) { - - ++iter; + // delete all broadcast-only telegrams + ++iter; // removeFromAllMaps() will destroy the iterator => we increment it before removing removeFromAllMaps(radioTelegram); } else @@ -1614,13 +1614,13 @@ void PrtCnvBroadcastMgr::handleOverrunOfBroadcastCounter(const bool a_doRestore) if (broadcastOnlyTelegram) { radioTelegram->setBroadcastonlyTelegram(nullptr); - ++iter; + ++iter; // removeFromAllMaps() will destroy the iterator => we increment it before removing removeFromAllMaps(broadcastOnlyTelegram); } else { - - + // all pending normal broadcast should no longer be sent as normal broadcasts, because all TNEs + // will anyway ask for nachforderung bool wasLast; if (radioTelegram->mustBeSentAsBroadcast(std::numeric_limits::max(), wasLast, false)) { @@ -1639,7 +1639,7 @@ void PrtCnvBroadcastMgr::handleOverrunOfBroadcastCounter(const bool a_doRestore) m_BroadcastMap.clear(); m_BroadcastMap = newBroadcastMap; - + // stop actual nachforderungen and increment reset-counter cleanAndInit(false); if (!a_doRestore) m_DbThread->setResetCounter(m_DbThread->getResetCounter() + 1); @@ -1648,21 +1648,21 @@ void PrtCnvBroadcastMgr::handleOverrunOfBroadcastCounter(const bool a_doRestore) } - - - +// --------------------------------------------------------------- +// Restores data after crash for seamless proceeding of work. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::restoreAfterCrash() { getAllFinishedBroadcastsFromDb(true); } - - - +// --------------------------------------------------------------- +// dumps important values, only for debugging +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::dump() { - + // dump the broadcast-list for (const auto &it : m_BroadcastMap) dumpTelegram(m_loggerBcRequest, it.first, it.second.get(), "m_BroadcastMap, "); @@ -1683,10 +1683,10 @@ void PrtCnvBroadcastMgr::dump() } - - - - +// --------------------------------------------------------------- +// Increments the tick-counter of broadcast-manager and +// informs the broadcast-manager about the traffic-load. +// --------------------------------------------------------------- void PrtCnvBroadcastMgr::incTickAndSetTrafficLoad(const bool a_isHighLoad, const bool a_isFullLoad) { if (e_ST_COLLECT == m_State) @@ -1698,13 +1698,13 @@ void PrtCnvBroadcastMgr::incTickAndSetTrafficLoad(const bool a_isHighLoad, const m_ActClaimWindow = m_ClaimWindow; } - - - +// --------------------------------------------------------------- +// Checks if the given id is in m_deactivatedAesArea2bcIndex +// --------------------------------------------------------------- bool PrtCnvBroadcastMgr::isEffectSimulationIdDeactivated(const uint16_t effectsimulationId) const { INFO_LOG(m_logger) << "Checking deactivation for Id " << effectsimulationId; return m_deactivatedAesArea2bcIndex.contains(effectsimulationId); } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.hpp index 6d346aab9..bf97f357b 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvBroadcastMgr.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -39,15 +39,27 @@ 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, @@ -57,74 +69,124 @@ public: 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: @@ -136,99 +198,166 @@ protected: 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); @@ -242,25 +371,25 @@ protected: 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; @@ -269,80 +398,165 @@ protected: 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: diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.cpp index c09d83d70..df356fc87 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvCentralThread +// ************************************************************************** #include "PrtCnvCentralThread.hpp" #include "PrtCnvRadioThread.hpp" @@ -35,7 +35,7 @@ namespace PrtCnv { - +// --------------------------------------------------------------- PrtCnvCentralThread::PrtCnvCentralThread(PrtCnv::PrtCnvThreadStarter* a_parent) : PrtCnvThread(a_parent, "PrtCnvCentralThread") , m_webSocket(nullptr) @@ -66,9 +66,9 @@ PrtCnvCentralThread::~PrtCnvCentralThread() destroy(); } - - - +// --------------------------------------------------------------- +// Creates all subcomponents and connects signals to slots +// --------------------------------------------------------------- int32_t PrtCnvCentralThread::create(NGL::Settings *settings) { PrtCnvThread::create(settings); @@ -115,9 +115,9 @@ int32_t PrtCnvCentralThread::create(NGL::Settings *settings) } - - - +// --------------------------------------------------------------- +// Deallocates subcomponents. +// --------------------------------------------------------------- int32_t PrtCnvCentralThread::destroy() { INFO_LOG(m_logger) << "Destroy"; @@ -129,9 +129,9 @@ int32_t PrtCnvCentralThread::destroy() return 0; } - - - +// --------------------------------------------------------------- +// Initializes the variables. +// --------------------------------------------------------------- int32_t PrtCnvCentralThread::init() { INFO_LOG(m_logger) << "Init"; @@ -143,7 +143,7 @@ int32_t PrtCnvCentralThread::init() m_sendAckTimer->setInterval(m_Config->getInteger(getName(), QStringLiteral("AckTimeout"), 900)); m_VirtualTeilnehmerId = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("VirtualIdPrtCnv"), 90); - m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000); + m_maxEqID = m_Config->getInteger(QStringLiteral("Common"), QStringLiteral("MaxEqID"), 50000); //or max unsigned short 65535 return 0; } @@ -155,9 +155,9 @@ int32_t PrtCnvCentralThread::deinit() return 0; } - - - +// --------------------------------------------------------------- +// Starts the thread and connects to TCP-server +// --------------------------------------------------------------- int32_t PrtCnvCentralThread::start() { INFO_LOG(m_logger) << "Start"; @@ -176,9 +176,9 @@ int32_t PrtCnvCentralThread::start() return 0; } - - - +// --------------------------------------------------------------- +// Stops the thread +// --------------------------------------------------------------- int32_t PrtCnvCentralThread::stop() { INFO_LOG(m_logger) << "Stop"; @@ -188,31 +188,31 @@ int32_t PrtCnvCentralThread::stop() } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvCentralThread::connected() { INFO_LOG(m_logger) << "Central-Socket connected m_Socket=" << m_webSocket; - m_SendCounter = 0; + m_SendCounter = 0; // we reset this counter after every connect to 0 => next telegram to send has counter 1 (preincrement) m_LastSendCounter = 0; - m_ReceiveCounter = 0; + m_ReceiveCounter = 0; // send 0 until we get a telegram, we reset this counter after every connect to 0 => the next telegram from central must be 1 m_ReceiveAckCounter = 0; m_aliveTimer->start(); if (m_bRadioThreadInitDone) m_sendAckTimer->start(); m_State = PrtCnvSocketThread::e_WORKING; - emit checkSendToCentral(); + emit checkSendToCentral(); // start sending telegrams for central still in list (reconnection) } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvCentralThread::disconnected() { INFO_LOG(m_logger) << "disconnected m_Socket=" << m_webSocket; - - + // for the case central is disconnecting, we have to disconnect also, otherwise + // we could send rubish (still resisting in buffers) after a reconnection if (PrtCnvSocketThread::e_WORKING == m_State && m_webSocket) m_webSocket->close(); @@ -233,10 +233,10 @@ void PrtCnvCentralThread::disconnected() } - - - - +// --------------------------------------------------------------- +// Stores that radio-thread has stopped. Cleans the Db and +// reinitializes when central-thread has also stopped. +// --------------------------------------------------------------- void PrtCnvCentralThread::radioStopped() { m_RadioStopped = true; @@ -245,25 +245,25 @@ void PrtCnvCentralThread::radioStopped() } - - - - +// --------------------------------------------------------------- +// Calls clean of radio-thread and Db-thread and initializes +// the variables for rework. +// --------------------------------------------------------------- void PrtCnvCentralThread::cleanAndReinit() { INFO_LOG(m_logger) << "cleanAndReinit"; emit cleanRadio(); - + // reinit mit sicherung und löschung der datenbestände m_ReceiveAckCounter = 0; m_DbThread->cleanAndInit(); m_DoCleanup = false; } - - - - +// --------------------------------------------------------------- +// Starts radio-thread and itself for proceeding work after +// cleaning the Db. +// --------------------------------------------------------------- void PrtCnvCentralThread::radioCleant() { if (!m_DoCleanup) @@ -280,16 +280,16 @@ void PrtCnvCentralThread::radioCleant() } } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvCentralThread::onTextMessageReceived(const QString &msg) { - + // eat all pending readyReadyRead if (m_DoCleanup) return; if (PrtCnvSocketThread::e_WORKING != m_State) - return; + return; // do nothing when we are not in working state onDirectTextMessageReceived(msg.toUtf8()); } @@ -298,7 +298,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson) try { if (baJson.isEmpty()) - throw std::exception(); + throw std::exception(); // FIXME: use own exception const QJsonObject obj = QJsonDocument::fromJson(baJson).object(); const QJsonValue typeId = obj.value(QStringLiteral("typeId")); @@ -311,16 +311,16 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson) m_aliveTimer->start(); - + // which kind of telegram is it? if (telegram.telegramId() == TrainingAreaBase::TetraIcd::BESTAETIGUNG) { - + // it is an ack-telegram handleAck(&telegram); } else { DEBUG_LOG(m_logger) << "Received telegram '" << baJson << "'"; - + // a payload-telegram handleTelegram(&telegram); } } @@ -328,7 +328,7 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson) { ERROR_LOG(m_logger) << "JSon conversion error happenend. Error:" << e.what() << ", msg: " << baJson; - + // inform central about the failure TrainingAreaBase::TetraIcd::CtaDataError tele; tele.header.equipmentNumber = m_VirtualTeilnehmerId; tele.header.timeStamp = time(nullptr) * 1000LL; @@ -339,21 +339,21 @@ void PrtCnvCentralThread::onDirectTextMessageReceived(const QByteArray &baJson) } } - +// --------------------------------------------------------------- void PrtCnvCentralThread::stateChanged(QAbstractSocket::SocketState newState) { INFO_LOG(m_logger) << "Websocket changed to state " << newState; } - - - - +// --------------------------------------------------------------- +// Stores a telegram to be sent to radio in volatile radio- +// list and permanent in DB. +// --------------------------------------------------------------- void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { - - - + // => check with receive-counter if we lost a telegram or we get a telegram twice. + // => in this cases neither store the telegram nor send an ack (just ignore and read the next telegram) + // => the receive-counter will be hold on the last correct received telegram DEBUG_LOG(m_logger) << "Receive Central-Telegram with telId=" << a_telegram->telegramId() << "; rcounter=" << a_telegram->counter(); if (checkAndUpdateReceiveCounter(a_telegram->counter())) @@ -383,7 +383,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_ case AreaEffectSimulationType::GasPipeDetonation: case AreaEffectSimulationType::SpecialArea: case AreaEffectSimulationType::Unknown: - Q_ASSERT(false); + Q_ASSERT(false); // should not happen but who knows break; case AreaEffectSimulationType::BeStillWarning: case AreaEffectSimulationType::DangerZoneExplosion: @@ -400,7 +400,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_ bool bSomethingChanged = false; for (int i = 0; i < msms.mineCount; ++i) { - if (!LtsUtils::BitArray::testBit(msms.mineState, i)) + if (!LtsUtils::BitArray::testBit(msms.mineState, i)) // 0 = triggered { INFO_LOG(m_logger) << "Testing bit " << i << " ... not set = triggered"; if (!oldTriggeredMines.contains(i)) @@ -419,7 +419,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_ return; } INFO_LOG(m_logger) << "MineState telegram contains new informations... " << msms.aesDdsId; - oldTriggeredMines = newTriggeredMines; + oldTriggeredMines = newTriggeredMines; // update in m_alreadyTriggeredMines[] } std::shared_ptr @@ -427,7 +427,7 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_ if (radioTelegram) { if (radioTelegram->getIdentity() <= m_maxEqID) { - + // save data in persistent database m_DbThread->storeRadioTelegram(radioTelegram, a_telegram->counter()); } else { WARNING_LOG(m_logger) << "Central telegram with telId=" << a_telegram->telegramId() @@ -445,20 +445,20 @@ void PrtCnvCentralThread::handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_ emit checkSendToRadio(); } - - - - - - +// --------------------------------------------------------------- +// The counter will be set to a_startCounter if a_maxCounter +// is reached +// returns true if receive-counter is ok +// returns false if a telegram is repeated or lost +// --------------------------------------------------------------- bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter) { TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter; - + // check for wrap if (std::numeric_limits::max() == ++m_ReceiveCounter) m_ReceiveCounter = 0; - + // has the counter the expected value? if (m_ReceiveCounter != a_counter) { if (m_ReceiveCounter > a_counter) @@ -473,30 +473,43 @@ bool PrtCnvCentralThread::checkAndUpdateReceiveCounter(const int32_t a_counter) } #if 0 m_ReceiveCounter--; - return false; + return false; // failure #else m_ReceiveCounter = a_counter; return true; #endif } - return true; + return true; // all ok } - - - +// --------------------------------------------------------------- +// used to send periodically an ack to central +// --------------------------------------------------------------- void PrtCnvCentralThread::timeoutTick() { - + //NOTICE_LOG(m_logger) << "timeoutTick, " << m_DoCleanup << ", " << m_State; if (m_DoCleanup) - return; + return; // eat all pending timeouts if (PrtCnvSocketThread::e_WORKING != m_State) - return; + return; // do nothing when we are not in working state +/* + // Das bringt nur noch mehr Traffic wenn zskskp die gesendeten Daten + // nicht schnell genug abarbeiten kann - deshalb ersteinmal auskommentiert + // do we have to resend unacked telegrams + if (m_DbThread->resendCentralTelegrams(m_LastSendCounter)) + { + emit checkSendToCentral(); // resend + } + else + { + // nothing has to be resent => update m_LastSendCounter + m_LastSendCounter = m_SendCounter; + } +*/ - - + // do we have to inject a central-telegram? try { N_CoPrtCnv::CoPrtCnvCentralTelegram *centralInjectTelegram; @@ -512,13 +525,13 @@ void PrtCnvCentralThread::timeoutTick() << " => could not inject radio-telegram, but we proceed..."; } - + // send the periodically ack-telegram to central sendAck(); } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvCentralThread::timeoutAliveAndConnection() { INFO_LOG(m_logger) << "timeoutAliveAndConnection socketState=" @@ -543,16 +556,16 @@ void PrtCnvCentralThread::timeoutAliveAndConnection() } } - - - +// --------------------------------------------------------------- +// Sends a ack-telegram to central. +// --------------------------------------------------------------- void PrtCnvCentralThread::sendAck() { TrainingAreaBase::TetraIcd::Acknowledge ack; ack.timeStamp = time(nullptr) * 1000; ack.ackCounter = m_ReceiveAckCounter; N_CoPrtCnv::CoPrtCnvCentralTelegram tele(ack); - + // send to socket if (m_webSocket) m_webSocket->sendTextMessage(QString::fromUtf8(tele.data())); else @@ -562,10 +575,10 @@ void PrtCnvCentralThread::sendAck() } - - - - +// --------------------------------------------------------------- +// Sends a central-telegram to socket or file, depending on +// configuration. Before sending, the send-counter will be set. +// --------------------------------------------------------------- void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { PrtCnvStoredCentralTelegram *handle = nullptr; @@ -573,11 +586,11 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te } - - - - - +// --------------------------------------------------------------- +// Sends a central-telegram to socket or file, depending on +// configuration. Before sending, the send-counter will be set. +// After sending the Db will be updated. +// --------------------------------------------------------------- void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram, PrtCnvStoredCentralTelegram *a_handle) { @@ -585,43 +598,43 @@ void PrtCnvCentralThread::sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_te if (a_telegram->telegramId() == TelegramId::DEAKTIVIERUNG_EINZELMINE) { const MineTriggered tele(MineTriggered::fromJson(a_telegram->jsonData())); - m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1); + m_alreadyTriggeredMines[tele.mineAreaId].insert(tele.mineIndex - 1); // starts at 1 ... INFO_LOG(m_logger) << "Adding triggered mine with id " << tele.mineIndex << " to area id " << tele.mineAreaId; } - + // set the counter, but keep old counter if we resend the telegram const int writeCounter = a_handle ? a_handle->writeCounter() : 0; if (writeCounter != 0) a_telegram->setCounter(writeCounter); else a_telegram->setCounter(++m_SendCounter); - + // send telegram to central DEBUG_LOG(m_logger) << "Send telegram to central: telId=" << a_telegram->telegramId() << " wcounter=" << a_telegram->counter(); - + // send to socket if (m_webSocket) m_webSocket->sendTextMessage(QString::fromUtf8(a_telegram->data())); else emit directTextMessage(a_telegram->data()); - + // mark in Db telegram as sent if (a_handle) m_DbThread->centralTelegramSent(a_telegram->counter(), a_handle); m_LogThread->writeCentralTelegramLog(a_telegram, true, 1); } - - - - - - +// --------------------------------------------------------------- +// Processes the telegram +// AnforderungStatistikBroadcastNachforderugen. The function +// fills the answer telegram StatistikBroadNachforderungen +// with the actual statistic. +// --------------------------------------------------------------- void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen() { const auto nachforderungsStat = m_DbThread->getClaimStatistics(); - + // inform central about the failure TrainingAreaBase::TetraIcd::BroadcastStatistics tele; tele.header.equipmentNumber = m_VirtualTeilnehmerId; tele.header.timeStamp = time(nullptr) * 1000LL; @@ -638,14 +651,14 @@ void PrtCnvCentralThread::handleAnforderungStatistikBroadcastNachforderungen() sendTelegram(&telegram); } - - - +// --------------------------------------------------------------- +// Checks whether a telegram must be sent and sends it. +// --------------------------------------------------------------- void PrtCnvCentralThread::checkSend() { - + // eat all pending checkSend-signals, if we have to cleanup if (m_DoCleanup) return; - if (PrtCnvSocketThread::e_WORKING != m_State) return; + if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state PrtCnvStoredCentralTelegram *handle = nullptr; auto *centralTelegram = m_DbThread->getNextCentralTelegram(handle); if (centralTelegram) @@ -656,26 +669,26 @@ void PrtCnvCentralThread::checkSend() } } - - - - +// --------------------------------------------------------------- +// Removes telegrams from ToCentral-table, if the central +// acknowledges their reception +// --------------------------------------------------------------- void PrtCnvCentralThread::handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { TrainingAreaBase::TetraIcd::Acknowledge ack(TrainingAreaBase::TetraIcd::Acknowledge::fromJson(a_telegram->jsonData())); - +// INFO_LOG(m_logger) << "Got Central-Ack with wcounter=" << a_ackTelegram.zaehler(); m_DbThread->ackCentralTelegrams(ack.ackCounter); } - - - - - +// --------------------------------------------------------------- +// Will be called from Db-thread when telegrams were stored +// permanent. This function will then send the ack to central +// (socket-based) or delete the telegramfiles (file-based) +// --------------------------------------------------------------- void PrtCnvCentralThread::permanentStored(int32_t a_centralCounter) { - if (m_DoCleanup) return; - if (PrtCnvSocketThread::e_WORKING != m_State) return; + if (m_DoCleanup) return; // eat all pending permanentStored + if (PrtCnvSocketThread::e_WORKING != m_State) return; // do nothing when we are not in working state DEBUG_LOG(m_logger) << "got permanentStored a_centralCounter=" << a_centralCounter; if (0 != a_centralCounter && a_centralCounter > m_ReceiveAckCounter) { @@ -732,10 +745,10 @@ void PrtCnvCentralThread::onRadioThreadInitDone() m_sendAckTimer->start(); } - - - - +// --------------------------------------------------------------- +// returns true if telegram should be converted, stored and +// sent to radio +// --------------------------------------------------------------- bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { using namespace TrainingAreaBase::TetraIcd; @@ -750,17 +763,17 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg case ExerciseStateData::ExerciseState::Terminated: { INFO_LOG(m_logger) << "Got Betriebszustandsmeldung Uebung_Aufraeumen => disconnect, cleanup and reconnect"; - m_DbThread->setMachineState(1); - + m_DbThread->setMachineState(1); // store permanent that we cleanup now, so we will proceed cleanup, after a crash + // send ack before disconnecting permanentStored(a_telegram->counter()); m_DoCleanup = true; m_CentralStopped = false; m_RadioStopped = false; - + // INFO_LOG(m_logger) << "stop timer"; m_sendAckTimer->stop(); m_DbThread->waitUntilDbWritten(); disconnectSocket(); - m_RadioThread->prepareCleanUp(); + m_RadioThread->prepareCleanUp(); // this makes empty the message-queue of radio-thread faster emit stopRadio(); m_reconnectTimer->start(); break; @@ -779,7 +792,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg return false; } case Constraints::id(): - + // here we must not use sendAck(), because it could be that we ack central-telegrams which are not yet stored permanent m_DbThread->centralCounterReadyForAck(a_telegram->counter()); handleAnforderungStatistikBroadcastNachforderungen(); return false; @@ -796,7 +809,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg return true; } - +// --------------------------------------------------------------- void PrtCnvCentralThread::connectSocket() { const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01")); @@ -827,7 +840,7 @@ void PrtCnvCentralThread::connectSocket() m_State = PrtCnvSocketThread::e_CONNECTING; } - +// --------------------------------------------------------------- void PrtCnvCentralThread::disconnectSocket() { m_State = PrtCnvSocketThread::e_INITIAL; @@ -841,4 +854,4 @@ void PrtCnvCentralThread::disconnectSocket() m_webSocket = nullptr; } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.hpp index 00e5727eb..4365f5bff 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvCentralThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvCentralThread +// ************************************************************************** #pragma once @@ -27,8 +27,15 @@ namespace PrtCnv { class PrtCnvRadioThread; class PrtCnvThreadStarter; - - + /** + * This class handles the protocoll to central. This includes: + * - connection with files instead sockets (configurable) + * - send and receive telegrams + * + * @author + * @version 1.0 + * @created 05-Jan-2006 13:34:28 + */ class PrtCnvCentralThread : public PrtCnv::PrtCnvThread { Q_OBJECT @@ -37,199 +44,270 @@ private: public: - - + /** + * @author wia + * @version 1.0 + * @updated 02-Jul-2009 14:32:58 + */ ~PrtCnvCentralThread(); - - + /** + * @param a_parent The pointer to the starter-thread + */ explicit PrtCnvCentralThread(PrtCnvThreadStarter* a_parent); - - + /** + * Creates all subcomponents and connects signals to slots + */ int32_t create(NGL::Settings *settings) override; int32_t deinit() 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; - - + /** + * Stops the thread + */ int32_t stop() override; - + // for direct communication void onDirectTextMessageReceived(const QByteArray &baJson); signals: - + // for direct communication void directTextMessage(const QByteArray &baJson); - - + /** + * Signal to start sending a telegram to central + */ void checkSendToCentral(); - - + /** + * Signal to start sending a telegram to radio + */ void checkSendToRadio(); - - + /** + * Signal to stop radio + */ void stopRadio(); - - + /** + * Signal to start cleaning-process of radio-thread + */ void cleanRadio(); - - + /** + * Signal to restart work of radio-thread + */ void startRadio(); protected: - - + /** + * For reading/writing json telegrams to socket + */ QWebSocket *m_webSocket; - - + /** + * The send-counter (only for sockets) + */ int32_t m_SendCounter; public slots: - - + /** + * Checks whether a telegram must be sent and sends it. + */ void checkSend(); - - + /** + * Stores that radio-thread has stopped. Cleans the Db and reinitializes when + * central-thread has also stopped. + */ void radioStopped(); - - + /** + * Starts radio-thread and itself for proceeding work after cleaning the Db. + */ void radioCleant(); - - + /** + * Will be called from Db-thread when telegrams were stored permanent. This + * function will then send the ack to central (socket-based) or delete the + * telegramfiles (file-based) + * + * @param a_centralCounter + */ void permanentStored(int32_t a_centralCounter); - + // called from Radio thread to indicate current connection state void onTetraConnectionState(bool bConnected); - + // called from Radio thread to indicate the license state of an equipment void onPlayerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind); protected slots: - + // an effect siumlation was (de)activated void onAreaEffectSimulationDeactivated(int wirkfeldKennung); void onAreaEffectSimulationActivated(int wirkfeldKennung); - + // radio thread completely initialized void onRadioThreadInitDone(); - - + /** + * called when websocket is connected + */ void connected(); - - + /** + * called when websocket is disconnected + */ void disconnected(); - - + /** + * used to send periodically an ack to central + */ void timeoutTick(); - - + /** + * see base-class + */ void timeoutAliveAndConnection(); void onTextMessageReceived(const QString &msg); void stateChanged(QAbstractSocket::SocketState newState); protected: - - + /** + * Sends a ack-telegram to central. + */ void sendAck(); - - + /** + * Stores a telegram to be sent to radio in volatile radio-list and permanent in + * DB. + * + * @param a_telegram + */ void handleTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); bool checkAndUpdateReceiveCounter(const int32_t a_counter); - - + /** + * Sends a central-telegram to socket or file, depending on configuration. Before + * sending, the send-counter will be set. After sending the Db will be updated. + * + * @param a_telegram The central-telegram to be sent. + * @param a_handle The handle assigned to telegram to be sent, we got from Db. + */ void sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram, PrtCnvStoredCentralTelegram *a_handle); - - + /** + * Processes the telegram AnforderungStatistikBroadcastNachforderugen. The + * function fills the answer telegram StatistikBroadNachforderungen with the + * actual statistic. + * + * @param a_umgMldTelegram + */ void handleAnforderungStatistikBroadcastNachforderungen(); - - + /** + * Removes telegrams from ToCentral-table, if the central acknowledges their + * reception + * + * @param a_ackTelegram + */ void handleAck(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); - - + /** + * Calls clean of radio-thread and Db-thread and initializes the variables for + * rework. + */ void cleanAndReinit(); - - + /** + * returns true if telegram should be converted, stored and sent to radio + * + * @param a_telegram + */ bool handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); - - + /** + * Sends a central-telegram to socket or file, depending on configuration. Before + * sending, the send-counter will be set. + * + * @param a_telegram The central-telegram to be sent. + */ void sendTelegram(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); - - + /** + * Connect as client to a TCP-server on ip-address configured as HostName and Port + * configured as Port + */ void connectSocket(); - - + /** + * Disconnects from TCP-server + */ void disconnectSocket(); protected: - - + /** + * used for periodically send an ack to central + */ PrtCnvRadioThread *m_RadioThread; - - + /** + * True if radio has stopped work + */ bool m_RadioStopped; - - + /** + * True if central has stopped work + */ bool m_CentralStopped; - - + /** + * Used for resending unacked telegrams + */ int32_t m_LastSendCounter; - - + /** + * The (virtual) identify of the protocol-converter + */ uint16_t m_VirtualTeilnehmerId; - - + /** + * The maximum equipment-ID for tetra - all telegrams with an higher ID will + * be silently ignored + */ uint16_t m_maxEqID; - + // timer to reconnect when no ack from central is coming anymore QTimer *m_aliveTimer; - + // timer to send ack to central QTimer *m_sendAckTimer; - + // timer to reconnect to central QTimer *m_reconnectTimer; - - + /** + * True if the database has to be cleant up (used for fast empty of signal buffers) + */ QAtomicInt m_DoCleanup; PrtCnvDbThread *m_DbThread; - + // log telegrams in file PrtCnvTelegramLogThread *m_LogThread; - + // get injected telegrams PrtCnvInjectionThread *m_InjectionThread; - - + /** + * Counter of received telegrams (only for sockets) + */ int32_t m_ReceiveCounter; - - + /** + * Acknowledged telegrams counter (only for sockets) + */ int32_t m_ReceiveAckCounter; - - + /** + * The state-event-machine state + */ PrtCnvSocketThread::E_State m_State; - + // set with all already deactivated effect simulations to not send deactivate telegram twice QSet m_deactivatedAreaEffectSimulations; - + // multimap with all mine areas and it's already triggered mines QHash> m_alreadyTriggeredMines; - + // true when we don't use socket but direct connections (through onDirectTextMessageReceived) bool m_bDirectConnection; bool m_bRadioThreadInitDone; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.cpp index fca1d57ad..f23899324 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvDbThread +// ************************************************************************** #include "PrtCnvDbThread.hpp" #include "PrtCnvThreadStarter.hpp" #include "PrtCnvCentralThread.hpp" @@ -32,9 +32,9 @@ namespace PrtCnv { - - - +// --------------------------------------------------------------- +// Constructor with thread-starter as argument +// --------------------------------------------------------------- PrtCnvDbThread::PrtCnvDbThread(const QString &dbDriver, const QString &dbHostName, const QString &dbDatabaseName, @@ -82,9 +82,9 @@ PrtCnvDbThread::~PrtCnvDbThread() } - - - +// --------------------------------------------------------------- +// reinit database +// --------------------------------------------------------------- static const int s_iCurrentDatabaseSchemeVersion = 1; void PrtCnvDbThread::reinitDatabase() { @@ -133,7 +133,7 @@ void PrtCnvDbThread::reinitDatabase() "id INTEGER PRIMARY KEY," "reset_counter INTEGER," "ctas_operating_state INTEGER," - "machine_state INTEGER" + "machine_state INTEGER" /* 0=>normal; 1=>DB-cleanup*/ ");").arg(statusTableName())); } @@ -148,9 +148,9 @@ void PrtCnvDbThread::reinitDatabase() trans.commit(); } - - - +// --------------------------------------------------------------- +// creates or restores the permanent database +// --------------------------------------------------------------- bool PrtCnvDbThread::createDatabase() { closeDb(); @@ -204,7 +204,7 @@ bool PrtCnvDbThread::createDatabase() } else { - + // check for correct version see version table in reinitDatabase()! int iVersion = q.value(0).toInt(); if (iVersion != s_iCurrentDatabaseSchemeVersion) { @@ -234,7 +234,7 @@ bool PrtCnvDbThread::createDatabase() std::cout << "Failure while checking DB-table ToRadio. Start PrtCnv with --cleandb" << std::endl; return false; } - + // check whether the broadcast-member is ok if (!q.exec(QStringLiteral("SELECT issi FROM %1 WHERE id=0;").arg(memberTableName()))) { ERROR_LOG(m_logger) << "Failure while checking DB-table Member"; @@ -262,7 +262,7 @@ bool PrtCnvDbThread::createDatabase() m_DoStorePermanent = false; INFO_LOG(m_logger) << "restoreStatus"; - + // restore important varibles if (!q.execAndFetch(QStringLiteral("SELECT reset_counter, ctas_operating_state, machine_state FROM %1;").arg(statusTableName()))) { ERROR_LOG(m_logger) << "Error reading Status from DB"; @@ -271,11 +271,11 @@ bool PrtCnvDbThread::createDatabase() } m_ResetCounter = q.value(0).toInt(); INFO_LOG(m_logger) << "Restore resetCounter=" << (int)m_ResetCounter; - + // check whether the crash happend just while cleaning up DB if (1 == q.value(2).toInt()) { INFO_LOG(m_logger) << "Crash happenend while cleaning-DB"; - + // crash while cleaning DB => clean-DB and restart m_DoStorePermanent = true; m_DoProceedCleanup = true; return true; @@ -283,7 +283,7 @@ bool PrtCnvDbThread::createDatabase() m_BattleFieldOperatingState = q.value(1).toInt(); INFO_LOG(m_logger) << "Restore battleFieldOperatingState=" << (int)m_BattleFieldOperatingState; - + // restore the members if (!q.exec(QStringLiteral("SELECT id, issi, licensed, claims, exercise_id FROM %1;").arg(memberTableName()))) { ERROR_LOG(m_logger) << "Error reading Member from DB"; @@ -310,17 +310,17 @@ bool PrtCnvDbThread::createDatabase() bool ok = licenseMember(member); if (ok) { - + //emit signal emit playerLicencedChanged(member->m_Id, N_CoPrtCnv::E_LicensingKind::Success); } } } } - - - - + // restore radio-telegrams + // Sortierung nach resetCounter + broadcastindex weil die Daten dann in + // getAllFinishedBroadcastsFromDb() der Reihenfolge nach abholt werden + // also müssen wir sie hier richtig herum in m_RadioList eintragen if (!q.exec(QStringLiteral("SELECT id, counter, broadcast_index, data " "FROM %1 ORDER BY reset_counter, broadcast_index, id;").arg(toRadioTableName()))) { @@ -339,11 +339,11 @@ bool PrtCnvDbThread::createDatabase() PrtCnvStoredRadioTelegram *storedTelegram = new PrtCnvStoredRadioTelegram(radioTelegram); storedTelegram->m_Id = id; - - + // -------------------------- + // ---------------------------- if (0 == counter) { - + // telegram not yet sent to radio m_RadioList.push_back(storedTelegram); INFO_LOG(m_logger) << "Restore unsent radiotelegram: id=" << storedTelegram->m_Id << " telId=" << storedTelegram->m_RadioTelegram->getTelID() @@ -352,17 +352,17 @@ bool PrtCnvDbThread::createDatabase() } else { - + // telegram sent to radio if (bcIndex == 0) { if (radioTelegram->getTelID() == GEF_UMGEBUNGS_MELDUNG2) m_RadioList.push_back(storedTelegram); else - delete storedTelegram; + delete storedTelegram; // normally not possible to get here, but just in case } else { - + // => broadcast-telegram radioTelegram->setBroadcastIndex(bcIndex); bool dummy; radioTelegram->mustBeSentAsBroadcast(0xFFFFFFFF, dummy); @@ -377,8 +377,8 @@ bool PrtCnvDbThread::createDatabase() } } - - q.exec(QStringLiteral("UPDATE %1 SET counter=0;").arg(toCentralTableName())); + // restore central-telegrams + q.exec(QStringLiteral("UPDATE %1 SET counter=0;").arg(toCentralTableName())); // => resend all not acked telegrams if (!q.exec(QStringLiteral("SELECT id, data FROM %1 ORDER BY id;").arg(toCentralTableName()))) { ERROR_LOG(m_logger) << "Error reading from ToCentral table"; @@ -402,7 +402,7 @@ bool PrtCnvDbThread::createDatabase() << " telId=" << storedTelegram->m_CentralTelegram->telegramId() << " counter=" << storedTelegram->m_WriteCounter << " size=" << telData.size(); - + //NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Info, telData, blobSize); } else ERROR_LOG(m_logger) << "Internal error: conversion of telegram with telId=" << radioTelegram.getTelID() << " from radio to central failed"; @@ -412,8 +412,8 @@ bool PrtCnvDbThread::createDatabase() { q.exec(QStringLiteral("VACUUM;")); q.exec(QStringLiteral("PRAGMA journal_mode=WAL;")); - - + // Sync mode to NORMAL instead FULL - small speedup at the cost + // of a little higher risk for data loss on power failure q.exec(QStringLiteral("PRAGMA synchronous=NORMAL;")); } } @@ -422,9 +422,9 @@ bool PrtCnvDbThread::createDatabase() return true; } - - - +// --------------------------------------------------------------- +// creates this thread and its childs +// --------------------------------------------------------------- int32_t PrtCnvDbThread::create(NGL::Settings *settings) { INFO_LOG(m_logger) << "create"; @@ -448,9 +448,9 @@ int32_t PrtCnvDbThread::create(NGL::Settings *settings) } - - - +// --------------------------------------------------------------- +// initializes this thread and its childs +// --------------------------------------------------------------- int32_t PrtCnvDbThread::init() { INFO_LOG(m_logger) << "init"; @@ -465,9 +465,9 @@ int32_t PrtCnvDbThread::init() } - - - +// --------------------------------------------------------------- +// starts this thread and its childs +// --------------------------------------------------------------- int32_t PrtCnvDbThread::start() { INFO_LOG(m_logger) << "start"; @@ -477,9 +477,9 @@ int32_t PrtCnvDbThread::start() } - - - +// --------------------------------------------------------------- +// stops this thread and its childs +// --------------------------------------------------------------- int32_t PrtCnvDbThread::stop() { PrtCnvThread::stop(); @@ -490,16 +490,16 @@ int32_t PrtCnvDbThread::stop() } - - - - - - - - - - +// --------------------------------------------------------------- +// stores the telegram to be sent to central in working-list +// and also in Db. Because storing data in XDR_Wrapper_it- +// format is complicated (has pointer to data), we store them +// in the radio-telegram-format). +// Attention: Be aware that centralTelegram and radioTelegram +// contain the same data. +// The DbThread takes control over centralTelegram and +// radioTelegram and deletes them when no longer needed. +// --------------------------------------------------------------- void PrtCnvDbThread::storeCentralTelegram(const std::shared_ptr &a_centralTelegram, const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram) { @@ -508,21 +508,21 @@ void PrtCnvDbThread::storeCentralTelegram(const std::shared_ptr(a_radioTelegram)); QMutexLocker l(&m_CentralListMutex); m_CentralList.push_back(storedTelegram); - +// INFO_LOG(m_logger) << "Store Central-Telegram with telId=" << a_telegram->getTelID() << " and rc=" << a_telegram->zaehler(); sendStorePermanentSignal(); } - - - - - - +// --------------------------------------------------------------- +// returns the next telegram to send to central. +// returns NULL if no telegram found. +// ATTENTION: The caller is responsible to deallocate the +// returned centralTelegram! +// --------------------------------------------------------------- N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvDbThread::getNextCentralTelegram(PrtCnvStoredCentralTelegram *&a_handle) { - + // get next telegram to send to central from DB QMutexLocker l(&m_CentralListMutex); std::vector::const_iterator iter = m_CentralList.begin(); std::vector::const_iterator end = m_CentralList.end(); @@ -538,7 +538,7 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvDbThread::getNextCentralTelegram(PrtC a_handle = storedTelegram; DEBUG_LOG(m_logger) << "Next telegram to send to central: id=" << storedTelegram->m_Id << " a_telId=" << telegram->telegramId(); - + // allocate a central-telegram return new N_CoPrtCnv::CoPrtCnvCentralTelegram(*telegram); } } @@ -546,12 +546,12 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvDbThread::getNextCentralTelegram(PrtC } - - - +// --------------------------------------------------------------- +// Marks the central-telegram as to be sent +// --------------------------------------------------------------- void PrtCnvDbThread::centralTelegramSent(const int32_t a_counter, PrtCnvStoredCentralTelegram *a_handle) { - + // update sendcounter QMutexLocker l(&m_CentralListMutex); a_handle->m_WriteCounter = a_counter; a_handle->m_WriteCounterChanged = true; @@ -560,32 +560,32 @@ void PrtCnvDbThread::centralTelegramSent(const int32_t a_counter, PrtCnvStoredCe } - - - - +// --------------------------------------------------------------- +// Indicates the Db, which telegrams were successful received +// by central. This will delete this telegrams from Db. +// --------------------------------------------------------------- void PrtCnvDbThread::ackCentralTelegrams(int32_t a_counter) { - + //DEBUG_LOG(m_logger) << "Got Ack from Central with wc=" << a_counter; m_CentralAckCounter = a_counter; sendStorePermanentSignal(); } - - - - - - - - +// --------------------------------------------------------------- +// Updates the counter for unsuccessful sending the telegram. +// If a maximal value of this counter is reached, the central- +// telegram will be deleted. +// a_handle could be deleted after calling this function! +// This function could block some milliseconds, because it +// must wait until all changes are written to DB. +// --------------------------------------------------------------- void PrtCnvDbThread::centralTelegramCouldNotBeSent(PrtCnvStoredCentralTelegram *a_handle) { if (a_handle) { - + // delete the telegram if much enough unsuccessfully sent QMutexLocker l(&m_CentralListMutex); if (++(a_handle->m_Attempts) >= 5) { @@ -593,7 +593,7 @@ void PrtCnvDbThread::centralTelegramCouldNotBeSent(PrtCnvStoredCentralTelegram * << " telId=" << a_handle->m_CentralTelegram->telegramId() << " rc=" << a_handle->m_CentralTelegram->counter() << " wc=" << a_handle->m_WriteCounter; a_handle->m_DoDelete = true; - + // mark in Db telegram as sent } l.unlock(); @@ -602,12 +602,12 @@ void PrtCnvDbThread::centralTelegramCouldNotBeSent(PrtCnvStoredCentralTelegram * } - - - - - - +// --------------------------------------------------------------- +// Stores the telegram to be sent to radio in working-list and +// also in Db. +// The DbThread takes control over a_telegram and deletes it +// when no longer needed. +// --------------------------------------------------------------- void PrtCnvDbThread::storeRadioTelegram(const std::shared_ptr &a_telegram, const int32_t a_readCounter) { @@ -627,12 +627,12 @@ void PrtCnvDbThread::storeRadioTelegram(const std::shared_ptr PrtCnvDbThread::getNextBroadcastTelegram() { QMutexLocker l(&m_BroadcastMapMutex); @@ -653,7 +653,7 @@ std::shared_ptr PrtCnvDbThread::getNextBroadc PrtCnvStoredRadioTelegram *storedRadioTelegram = m_BroadcastList.front(); std::shared_ptr radioTelegram; - + // check whether the telegram is already stored permanent in DB if (storedRadioTelegram->m_Id != 0 && !storedRadioTelegram->m_WriteCounterChanged) { radioTelegram = storedRadioTelegram->m_RadioTelegram; @@ -665,14 +665,14 @@ std::shared_ptr PrtCnvDbThread::getNextBroadc } - - - - - +// --------------------------------------------------------------- +// returns the next telegram to send to radio, respecting the +// priority. +// returns NULL if no radio-telegram found. +// --------------------------------------------------------------- std::shared_ptr PrtCnvDbThread::getNextRadioTelegram(PrtCnvStoredRadioTelegram *&a_handle) { - + // get next telegram respecting the priority to send to radio from DB std::shared_ptr telegram; uint8_t priority = 255; @@ -684,7 +684,7 @@ std::shared_ptr PrtCnvDbThread::getNextRadioT { if (!storedTelegram->m_IsSent) { - + // search the telegram with the lowest priority uint8_t newPriority = radioTelegram->getPriority(); if (newPriority < priority) { @@ -698,9 +698,9 @@ std::shared_ptr PrtCnvDbThread::getNextRadioT return telegram; } - - - +// --------------------------------------------------------------- +// Marks the radio-telegram as to be sent +// --------------------------------------------------------------- void PrtCnvDbThread::radioTelegramSent(const uint32_t a_sendCounter, PrtCnvStoredRadioTelegram *a_handle, const uint32_t a_broadcastIndex) { QMutexLocker l(&m_RadioListMutex); @@ -712,7 +712,7 @@ void PrtCnvDbThread::radioTelegramSent(const uint32_t a_sendCounter, PrtCnvStore << " BC: " << a_broadcastIndex; } - + // update sendcounter in telegram a_handle->m_WriteCounter = a_sendCounter; a_handle->m_WriteCounterChanged = true; a_handle->m_IsSent = true; @@ -721,26 +721,26 @@ void PrtCnvDbThread::radioTelegramSent(const uint32_t a_sendCounter, PrtCnvStore if (a_handle->m_BroadcastIndex != 0) { - + // set the time for the 2nd broadcast bool dummy; a_handle->m_RadioTelegram->mustBeSentAsBroadcast(0xFFFFFFFF, dummy); DEBUG_LOG(m_logger) << "Move Radio-Telegram with telId=" << a_handle->m_RadioTelegram->getTelID() << " and BC=" << a_handle->m_RadioTelegram->getBroadcastIndex() << " to BC-List of DB"; - - - - - +// if (a_handle->m_Id != 0) +// { +// M_DEBUG("Remove from radio-list") +// m_RadioList.remove(a_handle); +// } QMutexLocker l2(&m_BroadcastMapMutex); m_BroadcastList.push_back(a_handle); } else { - + // do not delete umgebungsmeldung, because we need it for restore after crash if (a_handle->m_RadioTelegram->isNormalTelegram() && (a_handle->m_RadioTelegram->getTelID() == GEF_UMGEBUNGS_MELDUNG2)) { - + // store only the last Umgebungsmeldung if (m_EnvironmentTelegram) m_EnvironmentTelegram->m_DoDelete = true; m_EnvironmentTelegram = a_handle; @@ -766,7 +766,7 @@ void PrtCnvDbThread::deleteTelegramsFromDbById(const QString &table) NSqlQuery q(m_db); q.exec(QStringLiteral("DELETE FROM %1 WHERE id IN (%2);").arg(table, sl.join(QLatin1Char(',')))); - + // cleanup m_telegramsToDelete.clear(); } @@ -789,7 +789,7 @@ void PrtCnvDbThread::updateTelegramsBroadcast(const QString &table) DEBUG_LOG(m_logger) << "Update broadcastindex for id: " << telId << " to BC: " << bcIndex; } - + // cleanup m_telegramsToUpdateBC.clear(); } @@ -812,12 +812,20 @@ void PrtCnvDbThread::updateTelegramsWriteCounter(const QString &table) DEBUG_LOG(m_logger) << "Update WriteCounter for id: " << telId << " to wc: " << writeCounter; } - + // cleanup m_telegramsToUpdateCounter.clear(); } - - +/** + * Da SQL-Kommandos im Gegensatz zum Auslesen aus dem Socket zu langsam + * ist und wir hier recht lange Lock-Zeiten haben, müssen wir uns mit einer + * zweiteiligen Verarbeitung zufrieden geben + * 1. Step - Auswerten und Aktualiseren der Liste + * 2. Step - Ausführen der SQL-Kommandos + * Da wir an Tetra keine Bestätigung verschicken bzw. Tetra im Falle + * eines Crashes sowieso nicht alles puffern kann, sollte dies ok + * sein. + */ void PrtCnvDbThread::storeCentralTelegrams() { QMutexLocker l(&m_CentralListMutex); @@ -825,9 +833,9 @@ void PrtCnvDbThread::storeCentralTelegrams() if (m_CentralList.empty()) return; - + // DEBUG_LOG(m_logger) << "centralTelegrams.size=" << m_CentralList.size(); int iEmptyCount = 0; - for (auto &storedCentralTelegram : m_CentralList) + for (auto &storedCentralTelegram : m_CentralList) // reference is important to be able to make them a nullptr in the vector { if (!storedCentralTelegram) { @@ -838,7 +846,7 @@ void PrtCnvDbThread::storeCentralTelegrams() if (0 == storedCentralTelegram->m_Id) { - + // new Telegram from Tetra, not yet in db -> insert it now m_telegramsToInsert.emplace_back(std::make_pair(storedCentralTelegram, 0)); DEBUG_LOG(m_logger) << "Permanent Central-Telegram with id=" << storedCentralTelegram->m_Id @@ -847,8 +855,8 @@ void PrtCnvDbThread::storeCentralTelegrams() } else { - - + // update counter for all sent central-telegrams + // --------------------------------------------- const int centralAckCnt = m_CentralAckCounter; if (storedCentralTelegram->m_WriteCounterChanged) { @@ -860,8 +868,8 @@ void PrtCnvDbThread::storeCentralTelegrams() << " data=" << centralTelegram->data() << " wc=" << storedCentralTelegram->m_WriteCounter; } - - + // delete all acked telegrams from central-list + // -------------------------------------------- else if ((storedCentralTelegram->m_WriteCounter > 0 && storedCentralTelegram->m_WriteCounter <= centralAckCnt) || storedCentralTelegram->m_DoDelete) @@ -870,16 +878,16 @@ void PrtCnvDbThread::storeCentralTelegrams() << " data=" << storedCentralTelegram->m_CentralTelegram->data() << " wc=" << storedCentralTelegram->m_WriteCounter; - + // no need for single delete when centralAckCnt is higher - will be deleted later with where counter <= ackCounter if (storedCentralTelegram->m_WriteCounter > centralAckCnt) m_telegramsToDelete.push_back(storedCentralTelegram->m_Id); - + // Removing from vector and DB occours some lines down delete storedCentralTelegram; storedCentralTelegram = nullptr; } } } - + // clean up m_CentralList if really needed if (iEmptyCount > 50) { const auto isNull = [](const PrtCnvStoredCentralTelegram *t) { return t == nullptr; }; @@ -888,9 +896,9 @@ void PrtCnvDbThread::storeCentralTelegrams() } l.unlock(); - + // DEBUG_LOG(m_logger) << "ready: " << m_CentralList.size(); - + // insert new telegrams into db if (!m_telegramsToInsert.empty()) { l.relock(); @@ -898,8 +906,8 @@ void PrtCnvDbThread::storeCentralTelegrams() q.prepare(QStringLiteral("INSERT INTO %1 (tel_id, counter, data)" "VALUES(:tel_id, :counter, :data);").arg(toCentralTableName())); - - + // TODO: ist das Locking mittels m_CentralListMutex überhaupt nötig? + // Wenn nein dann kann man dies hier etwas einfacher gestalten for (const auto &p : m_telegramsToInsert) { @@ -913,32 +921,32 @@ void PrtCnvDbThread::storeCentralTelegrams() storedCentralTelegram->m_Id = q.lastInsertId().toInt(); } l.unlock(); - + // DEBUG_LOG(m_logger) << "added new telegrams to db: " << m_telegramsToInsert.size(); m_telegramsToInsert.clear(); } - + // update write counter for a telegramm updateTelegramsWriteCounter(toCentralTableName()); - + // DEBUG_LOG(m_logger) << "updated write counter in db: " << m_telegramsToUpdateCounter.size(); - - - - + // Jetzt alle Telegramme löschen die von der Zentrale bestätigt worden + // da m_CentralAckCounter von anderen Threads geändert werden kann, kann es + // sein dass schon mehr Telegramme aus der DB gelöscht werden als vorher + // aus m_CentralList. Dies wird aber im nächsten Aufruf wieder korrigiert const unsigned int centralAckCnt = static_cast(m_CentralAckCounter); if (centralAckCnt > m_OldCentralAckCounter) { m_OldCentralAckCounter = centralAckCnt; - - + // wir arbeiten mit m_OldCentralAckCounter da sich m_CentralAckCounter + // währenddessen schon ändern kann DEBUG_LOG(m_logger) << "Central delete all counter <= " << m_OldCentralAckCounter; NSqlQuery q(m_db); q.exec(QStringLiteral("DELETE FROM %1 WHERE counter > 0 AND counter <= %2;").arg(toCentralTableName()).arg(m_OldCentralAckCounter)); } - + // remove all telegrams which were manually marked for deletion deleteTelegramsFromDbById(toCentralTableName()); } @@ -949,14 +957,14 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() if (m_RadioList.empty()) return 0; - + // M_DEBUG("Check for permanent actions on radio-list") int32_t centralCounter = 0; NSqlQuery q(m_db); q.prepare(QStringLiteral("INSERT INTO %1 (tel_id, counter, broadcast_index, reset_counter, data) " "VALUES (:tel_id, :counter, :broadcast_index, :reset_counter, :data);").arg(toRadioTableName())); - + // DEBUG_LOG(m_logger) << "m_RadioList.size=" << m_RadioList.size(); std::list::iterator radioIter = m_RadioList.begin(); while (radioIter != m_RadioList.end()) { @@ -972,8 +980,8 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() << " BC: " << storedRadioTelegram->m_BroadcastIndex << " wc: " << int(storedRadioTelegram->m_WriteCounter); - - + // store radio-telegrams permanent + // ------------------------------- if (0 == storedRadioTelegram->m_Id) { if (storedRadioTelegram->m_ReadCounter > centralCounter) @@ -990,11 +998,11 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() DEBUG_LOG(m_logger) << "Stored Telegramm in DB, id: " << storedRadioTelegram->m_Id; - - - - - + // for broadcast-telegrams, we have 2 cases: + // 1. case: it will be written to DB, before it is sent to radio and then moved to broadcast-list of broadcast-manager + // 2. case: it will be sent to radio before it is written to DB. In this case we cannot remove it from m_RadioList until + // it is written to DB + // here we check whether case 2 has happenend if (storedRadioTelegram->m_RadioTelegram->isMovedToBroadcastList()) { dumpTelegram(m_logger, @@ -1006,20 +1014,20 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() } else { - - - - + // delete all acked telegrams from radio-list + // ------------------------------------------ + // do we have to delete the radio-telegram in the list and DB? + // we do only delete if the telegram is stored permanent in db and therefore the ack to central is sent if (storedRadioTelegram->m_DoDelete) { DEBUG_LOG(m_logger) << "Delete Telegramm from DB, id: " << storedRadioTelegram->m_Id; m_telegramsToDelete.push_back(storedRadioTelegram->m_Id); - + // delete the telegram in the list delete storedRadioTelegram; doDeleteThisItem = true; } - - + // update write-counter for all sent radio-telegrams + // ------------------------------------------------- else if (storedRadioTelegram->m_WriteCounterChanged) { m_telegramsToUpdateCounter.emplace_back(std::make_pair(storedRadioTelegram->m_Id, @@ -1046,7 +1054,7 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() } else { - + // telegrams which will not be stored, but acked (i.e. Anforderung Nachforderungs Statistik) if (storedRadioTelegram->m_ReadCounter > centralCounter) centralCounter = storedRadioTelegram->m_ReadCounter; delete storedRadioTelegram; @@ -1060,15 +1068,15 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() } l.unlock(); - + // update write counter for a telegramm static const QString &table = toRadioTableName(); updateTelegramsWriteCounter(table); - + // DEBUG_LOG(m_logger) << "updated write counter in db: " << m_telegramsToUpdateCounter.size(); - + // update BC for a telegramm updateTelegramsBroadcast(table); - + // remove all telegrams which were manually marked for deletion deleteTelegramsFromDbById(table); return centralCounter; @@ -1076,7 +1084,7 @@ int32_t PrtCnvDbThread::storeRadioTelegrams() void PrtCnvDbThread::handleSqlCommandList() { - + // M_DEBUG("Check for permanent actions on sql-command-list") std::vector sqlCommandList; { QMutexLocker l(&m_SqlCmdListMutex); @@ -1093,10 +1101,10 @@ void PrtCnvDbThread::handleSqlCommandList() } } - - - - +// --------------------------------------------------------------- +// Stores the radio-telegrams, central-telegrams in Db and +// executes the sql-command-list. +// --------------------------------------------------------------- void PrtCnvDbThread::storePermanent() { m_StorePermanentPending = 0; @@ -1108,42 +1116,42 @@ void PrtCnvDbThread::storePermanent() return; } - - + // generate the sql-commands on permanent DB + // ----------------------------------------- DBTransaction trans(m_db); - - + // permanent DB-actions for central + // ================================ storeCentralTelegrams(); - - + // permanent DB-actions for radio + // ============================== const int32_t centralCounter = storeRadioTelegrams(); - - + // store the sql-commands (member) + // ====================== handleSqlCommandList(); - + // ready trans.commit(); - +// M_DEBUG("inform central-thread") if (0 != centralCounter && centralCounter != m_OldCentralCounter) { m_OldCentralCounter = centralCounter; emit permanentStored(centralCounter); } m_DoWaitUntilSqlWritten = false; - +// M_DEBUG("End check for permanent actions") } - - - - - +// --------------------------------------------------------------- +// Adds an sql-command in the sql-command-list. On next +// iteration of storePermanent() all command in list will be +// executed. +// --------------------------------------------------------------- void PrtCnvDbThread::addSqlCommand(const QString &sql) { QMutexLocker l(&m_SqlCmdListMutex); @@ -1154,24 +1162,24 @@ void PrtCnvDbThread::addSqlCommand(const QString &sql) - - - +// --------------------------------------------------------------- +// erases and initializes the database +// --------------------------------------------------------------- void PrtCnvDbThread::cleanAndInit() { - + // emit a signal to clean, so we can be sure that all pending signals are worked m_DoClean = true; emit doClean(); - + // simply block until clean while (m_DoClean) QThread::sleep(1); m_DoProceedCleanup = false; } - - - +// --------------------------------------------------------------- +// cleans up this thread and its childs +// --------------------------------------------------------------- void PrtCnvDbThread::clean() { NSqlQuery q(m_db); @@ -1203,8 +1211,8 @@ void PrtCnvDbThread::clean() m_BroadcastList.clear(); } - - + // clean the members + // delete the member-maps { QMutexLocker l(&m_SqlCmdListMutex); m_MemberListByISSI.clear(); @@ -1219,19 +1227,19 @@ void PrtCnvDbThread::clean() q.exec(QStringLiteral("DELETE FROM %1;").arg(memberTableName())); } - + // 'virtual' TNE for broadcasts licenseMember(addMember(0, m_Config->getInteger(QStringLiteral("Radio"), QStringLiteral("BroadcastISSI"), 5000))); m_DoClean = false; } - - - - - - +// --------------------------------------------------------------- +// Checks whether central-telegrams have to be resent. If yes, +// all actions will be done, that getNextCentralTelegram() +// delivers the telegram(s) to be resent. +// Returns true if there must telegrams be resent. +// --------------------------------------------------------------- bool PrtCnvDbThread::resendCentralTelegrams(const int32_t a_lastSendCounter) { const int centralAckCnt = m_CentralAckCounter; @@ -1269,11 +1277,11 @@ bool PrtCnvDbThread::resendCentralTelegrams(const int32_t a_lastSendCounter) - - - - - +// --------------------------------------------------------------- +// Prepares the telegrams not yet acked from central for +// reconnection. This will be done by setting the write- +// counter to 0. +// --------------------------------------------------------------- void PrtCnvDbThread::prepareCentralTelegramsForReconnection() { INFO_LOG(m_logger) << "m_CentralAckCounter=" << m_CentralAckCounter; @@ -1304,29 +1312,29 @@ void PrtCnvDbThread::prepareCentralTelegramsForReconnection() } - - - +// --------------------------------------------------------------- +// Blocks until all SQL-commands were written to DB. +// --------------------------------------------------------------- void PrtCnvDbThread::waitUntilDbWritten() { m_DoWaitUntilSqlWritten = true; emit doStorePermanent(); while (m_DoWaitUntilSqlWritten) - QThread::usleep(10000); + QThread::usleep(10000); // 10 ms - + // we have to do this twice, to be sure m_DoWaitUntilSqlWritten = true; emit doStorePermanent(); while (m_DoWaitUntilSqlWritten) - QThread::usleep(10000); + QThread::usleep(10000); // 10 ms } - - - - +// --------------------------------------------------------------- +// adds a member in the 2 maps, sorted by id and ISSI +// returns the new member +// --------------------------------------------------------------- PrtCnv::PrtCnvMember *PrtCnvDbThread::addMember(const int a_identity, const int a_ISSI) { PrtCnvMember *newMember = new PrtCnvMember(a_identity, a_ISSI); @@ -1340,7 +1348,7 @@ PrtCnv::PrtCnvMember *PrtCnvDbThread::addMember(const int a_identity, const int DEBUG_LOG(m_logger) << "Adding member with eqId " << a_identity << " and issi " << a_ISSI << ", store in db: " << m_DoStorePermanent; - + // add also permanent in DB if (m_DoStorePermanent) addSqlCommand(QStringLiteral("INSERT INTO %1 (id, issi) VALUES(%2, %3)") .arg(memberTableName()).arg(newMember->m_Id).arg(newMember->m_ISSI)); @@ -1349,9 +1357,9 @@ PrtCnv::PrtCnvMember *PrtCnvDbThread::addMember(const int a_identity, const int } - - - +// --------------------------------------------------------------- +// removes the member in the 2 maps, sorted by id and ISSI +// --------------------------------------------------------------- void PrtCnvDbThread::removeMember(PrtCnv::PrtCnvMember *a_member) { { @@ -1372,7 +1380,7 @@ void PrtCnvDbThread::removeMember(PrtCnv::PrtCnvMember *a_member) DEBUG_LOG(m_logger) << "Removing member with eqId " << a_member->m_Id << " and issi " << a_member->m_ISSI << ", store in db: " << m_DoStorePermanent; - + // remove also permanent in DB if (m_DoStorePermanent) addSqlCommand(QStringLiteral("DELETE FROM %1 WHERE id = %2 OR issi = %3") .arg(memberTableName()).arg(a_member->m_Id).arg(a_member->m_ISSI)); @@ -1381,9 +1389,9 @@ void PrtCnvDbThread::removeMember(PrtCnv::PrtCnvMember *a_member) } - - - +// --------------------------------------------------------------- +// Licenses the member +// --------------------------------------------------------------- bool PrtCnvDbThread::licenseMember(PrtCnvMember *a_member, const bool a_doLicense) { if (!a_member) @@ -1409,9 +1417,9 @@ void PrtCnvDbThread::updateExerciseIdForMember(PrtCnvMember *a_member, int newEx } - - - +// --------------------------------------------------------------- +// returns NULL if member not found +// --------------------------------------------------------------- PrtCnv::PrtCnvMember *PrtCnvDbThread::getMemberById(const uint16_t a_id) { QMutexLocker l(&m_MemberListByIdMutex); @@ -1419,13 +1427,13 @@ PrtCnv::PrtCnvMember *PrtCnvDbThread::getMemberById(const uint16_t a_id) if (iter != m_MemberListById.end()) return iter->second; - return nullptr; + return nullptr; // no member found } - - - +// --------------------------------------------------------------- +// returns NULL if no member found +// --------------------------------------------------------------- PrtCnv::PrtCnvMember *PrtCnvDbThread::getMemberByISSI(const uint32_t a_ISSI) const { auto iter = m_MemberListByISSI.find(a_ISSI); @@ -1437,18 +1445,18 @@ PrtCnv::PrtCnvMember *PrtCnvDbThread::getMemberByISSI(const uint32_t a_ISSI) con - - - +// --------------------------------------------------------------- +// Returns the actual reset-counter +// --------------------------------------------------------------- uint8_t PrtCnvDbThread::getResetCounter() const { return m_ResetCounter; } - - - +// --------------------------------------------------------------- +// Sets the actual reset-counter +// --------------------------------------------------------------- void PrtCnvDbThread::setResetCounter(uint8_t newVal) { m_ResetCounter = newVal; @@ -1462,10 +1470,10 @@ void PrtCnvDbThread::setResetCounter(uint8_t newVal) } - - - - +// --------------------------------------------------------------- +// The actual 'Betriebszustände Gefechtsfeld' which will be +// sent to TNEs periodically +// --------------------------------------------------------------- uint8_t PrtCnvDbThread::getBattleFieldOperatingState() const { QMutexLocker l(&m_BattleFieldOpStateMutex); @@ -1474,17 +1482,17 @@ uint8_t PrtCnvDbThread::getBattleFieldOperatingState() const } - - - +// --------------------------------------------------------------- +// Sets or unsets pause, depending on a_doSet. +// --------------------------------------------------------------- void PrtCnvDbThread::setPause(const bool a_doSet) { QMutexLocker l(&m_BattleFieldOpStateMutex); if (a_doSet) - m_BattleFieldOperatingState = m_BattleFieldOperatingState | 0x80; + m_BattleFieldOperatingState = m_BattleFieldOperatingState | 0x80; // pause else - m_BattleFieldOperatingState = m_BattleFieldOperatingState & 0x7F; + m_BattleFieldOperatingState = m_BattleFieldOperatingState & 0x7F; // no pause if (m_DoStorePermanent) addSqlCommand(QStringLiteral("UPDATE %1 SET ctas_operating_state = %2 WHERE id = 1") @@ -1493,9 +1501,9 @@ void PrtCnvDbThread::setPause(const bool a_doSet) INFO_LOG(m_logger) << "Update battleFieldOperatingState=" << (int)m_BattleFieldOperatingState << " doStorePermanent=" << m_DoStorePermanent; } - - - +// --------------------------------------------------------------- +// Set the inhibit time for position telegrams (1 .. 31 Seconds) +// --------------------------------------------------------------- void PrtCnvDbThread::setPositionSendTime(unsigned int sendTime) { QMutexLocker l(&m_BattleFieldOpStateMutex); @@ -1505,29 +1513,29 @@ void PrtCnvDbThread::setPositionSendTime(unsigned int sendTime) if (sendTime < 1) sendTime = 1; - + // mode zurücksetzen (Bits 2 - 6) m_BattleFieldOperatingState &= 0x83; - + // und neu setzen m_BattleFieldOperatingState |= (sendTime << 2); } - - - +// --------------------------------------------------------------- +// Set the current air load to be sent with the Umgebungsmeldung +// --------------------------------------------------------------- void PrtCnvDbThread::setAirLoad(PrtCnvRadioThread::E_TrafficLoad airLoad) { QMutexLocker l(&m_BattleFieldOpStateMutex); - + // mode zurücksetzen m_BattleFieldOperatingState &= 0xFC; - + // und neu setzen m_BattleFieldOperatingState |= (static_cast(airLoad) & 0x03); } - - - - +// --------------------------------------------------------------- +// Returns true if the resetCounter itself is different than +// the reset-counter of the environment-telegram +// --------------------------------------------------------------- bool PrtCnvDbThread::isEnvironmentResetCounterOld() const { QMutexLocker l(&m_RadioListMutex); @@ -1538,10 +1546,10 @@ bool PrtCnvDbThread::isEnvironmentResetCounterOld() const return isOld; } - - - - +// --------------------------------------------------------------- +// Sets the resetcounter of the environment-telegram to the +// actual reset-counter. +// --------------------------------------------------------------- void PrtCnvDbThread::setResetCounterOnEnvironment() { QMutexLocker l(&m_RadioListMutex); @@ -1550,9 +1558,9 @@ void PrtCnvDbThread::setResetCounterOnEnvironment() m_EnvironmentTelegram->m_RadioTelegram->setPayloadDataWithIndex(7, getResetCounter(), 1); } - - - +// --------------------------------------------------------------- +// Returns the actual Umgebungsmeldung +// --------------------------------------------------------------- std::shared_ptr PrtCnvDbThread::getEnvironmentTelegram() { QMutexLocker l(&m_RadioListMutex); @@ -1561,10 +1569,10 @@ std::shared_ptr PrtCnvDbThread::getEnvironmen return {}; } - - - - +// --------------------------------------------------------------- +// Fills the map with nachforderungsstatistic. +// Returns the number of elements in map. +// --------------------------------------------------------------- std::map PrtCnvDbThread::getClaimStatistics() const { std::map ret; @@ -1578,10 +1586,10 @@ std::map PrtCnvDbThread::getClaimStatistics() const } - - - - +// --------------------------------------------------------------- +// Increments the counter for nachforderungen of the TNE with +// id a_identity. +// --------------------------------------------------------------- void PrtCnvDbThread::incClaimCount(int a_identity) { QMutexLocker l(&m_MemberListByIdMutex); @@ -1600,10 +1608,10 @@ void PrtCnvDbThread::incClaimCount(int a_identity) - - - - +// --------------------------------------------------------------- +// Sets the actual machine-state permanent, used to proceed +// cleaning db after a crash. +// --------------------------------------------------------------- void PrtCnvDbThread::setMachineState(const int a_newMachineState) { NSqlQuery q(m_db); @@ -1613,10 +1621,10 @@ void PrtCnvDbThread::setMachineState(const int a_newMachineState) - - - - +// --------------------------------------------------------------- +// Returns true if protocol-converter was crashed while +// cleanup DB. +// --------------------------------------------------------------- bool PrtCnvDbThread::mustProceedCleanup() const { return m_DoProceedCleanup; @@ -1624,10 +1632,10 @@ bool PrtCnvDbThread::mustProceedCleanup() const - - - - +// --------------------------------------------------------------- +// Sends a signal storePermanent if not already such a signal +// is pending +// --------------------------------------------------------------- void PrtCnvDbThread::sendStorePermanentSignal() { if (m_StorePermanentPending.testAndSetOrdered(0, 1)) @@ -1644,4 +1652,4 @@ void PrtCnvDbThread::closeDb() } } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.hpp index 473432e79..4b0960a18 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvDbThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvDbThread +// ************************************************************************** #pragma once @@ -37,15 +37,28 @@ namespace PrtCnv class PrtCnvStoredCentralTelegram; class PrtCnvStoredRadioTelegram; class PrtCnvMember; - - + /** + * Handles all data which must be stored permanent: + * - central-telegrams + * - radio-telegrams + * - radio-members (TNE) + * - reset-counter + * - states + * + * @author wia + * @version 1.0 + * @created 28-Jul-2009 16:08:53 + */ class PrtCnvDbThread : public PrtCnvThread { Q_OBJECT public: - - + /** + * Constructor with thread-starter as argument + * + * @param a_parent + */ PrtCnvDbThread(const QString &dbDriver, const QString &dbHostName, const QString &dbDatabaseName, @@ -55,161 +68,287 @@ namespace PrtCnv PrtCnvThreadStarter* a_parent); ~PrtCnvDbThread(); - - + /** + * starts this thread and its childs + */ int32_t start() override; - - + /** + * stops this thread and its childs + */ int32_t stop() override; - - + /** + * creates this thread and its childs + */ int32_t create(NGL::Settings *settings) override; - - + /** + * initializes this thread and its childs + */ int32_t init() override; - - + /** + * Indicates the Db, which telegrams were successful received by central. This + * will delete this telegrams from Db. + * + * @param a_counter + */ void ackCentralTelegrams(int32_t a_counter); - - + /** + * returns the next telegram to send to central. + * returns NULL if no telegram found. + * ATTENTION: The caller is responsible to deallocate the returned + * centralTelegram! + * + * @param a_handle + */ N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextCentralTelegram(PrtCnvStoredCentralTelegram *& a_handle); - - + /** + * Marks the central-telegram as to be sent + * + * @param a_counter The counter the telegram has while sent + * @param a_handle The telegram-handle gotten from getNextCentralTelegram() + */ void centralTelegramSent(const int32_t a_counter, PrtCnvStoredCentralTelegram *a_handle); - - + /** + * Updates the counter for unsuccessful sending the telegram. If a maximal value + * of this counter is reached, the central-telegram will be deleted. + * a_handle could be deleted after calling this function! + * This function could block some milliseconds, because it must wait until all + * changes are written to DB. + * + * @param a_handle The telegram-handle gotten from getNextCentralTelegram() + */ void centralTelegramCouldNotBeSent(PrtCnvStoredCentralTelegram *a_handle); - - + /** + * Marks the radio-telegram as to be sent + * + * @param a_sendCounter + * @param a_handle + * @param a_broadcastIndex + */ void radioTelegramSent(const uint32_t a_sendCounter, PrtCnvStoredRadioTelegram *a_handle, const uint32_t a_broadcastIndex); - - + /** + * returns the next telegram to send to radio, respecting the priority. + * returns NULL if no radio-telegram found. + * + * @param a_handle + */ std::shared_ptr getNextRadioTelegram(PrtCnvStoredRadioTelegram *&a_handle); - - + /** + * returns the next broadcast-telegram from list. + * Deletes the telegram from this list. + * returns NULL if list empty. + */ std::shared_ptr getNextBroadcastTelegram(); - - + /** + * stores the telegram to be sent to central in working-list and also in Db. + * Because storing data in XDR_Wrapper_it-format is complicated (has pointer to + * data), we store them in the radio-telegram-format). + * Attention: Be aware that centralTelegram and radioTelegram contain the same + * data. + * The DbThread takes control over centralTelegram and radioTelegram and deletes + * them when no longer needed. + * + * @param a_centralTelegram + * @param a_radioTelegram Must be the same telegram like the central-telegram + * (used for storing the telegram in Db) + */ void storeCentralTelegram(const std::shared_ptr &a_centralTelegram, const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram); - - + /** + * Stores the telegram to be sent to radio in working-list and also in Db. + * The DbThread takes control over a_telegram and deletes it when no longer needed. + * + * + * @param a_telegram + * @param a_readCounter + */ void storeRadioTelegram(const std::shared_ptr &a_telegram, const int32_t a_readCounter); - - + /** + * This function causes acking a central-telegram, which must not be stored + * permanent in Db, because it will be handled immediately (i.e. + * AnforderungStatistikBroadcastNachforderungen). + * + * @param a_centralCounter The read-counter of the central-telegram + */ void centralCounterReadyForAck(const int32_t a_centralCounter); - - + /** + * Adds an sql-command in the sql-command-list. On next iteration of + * storePermanent() all command in list will be executed. + * + * @param a_sqlCommand + */ void addSqlCommand(const QString &sql); - - + /** + * erases and initializes the database + */ void cleanAndInit(); - - + /** + * Checks whether central-telegrams have to be resent. If yes, all actions will be + * done, that getNextCentralTelegram() delivers the telegram(s) to be resent. + * Returns true if there must telegrams be resent. + * + * @param a_lastSendCounter The counter of the telegram we expect a ack- + * telegram has been received + */ bool resendCentralTelegrams(const int32_t a_lastSendCounter); - - + /** + * Prepares the telegrams not yet acked from central for reconnection. This will + * be done by setting the write-counter to 0. + */ void prepareCentralTelegramsForReconnection(); - - + /** + * Blocks until all SQL-commands were written to DB. + */ void waitUntilDbWritten(); - - + /** + * returns NULL if no member found + * + * @param a_ISSI + */ PrtCnvMember* getMemberByISSI(const uint32_t a_ISSI) const; - - + /** + * returns NULL if member not found + * + * @param a_id + */ PrtCnvMember* getMemberById(const uint16_t a_id); - - + /** + * Licenses the member + * + * @param a_member + * @param a_doLicense + */ bool licenseMember(PrtCnvMember *a_member, const bool a_doLicense = true); - - + /** + * Updates the current exercise for this member + */ void updateExerciseIdForMember(PrtCnvMember *a_member, int newExerciseId); - - + /** + * adds a member in the 2 maps, sorted by id and ISSI + * returns the new member + * + * @param a_identity + * @param a_ISSI + */ PrtCnvMember* addMember(const int a_identity, const int a_ISSI); - - + /** + * removes the member in the 2 maps, sorted by id and ISSI + * + * @param a_member + */ void removeMember(PrtCnvMember* a_member); - - + /** + * Returns the actual reset-counter + */ uint8_t getResetCounter() const; - - + /** + * Sets the actual reset-counter + * + * @param newVal + */ void setResetCounter(uint8_t newVal); - - + /** + * The actual 'Betriebszustaende Gefechtsfeld' which will be sent to TNEs + * periodically + */ uint8_t getBattleFieldOperatingState() const; - - + /** + * Sets or unsets pause, depending on a_doSet. + * (Bit 0 in UMGEBUNGS_MELDUNG(2)) + * @param a_doSet + */ void setPause(const bool a_doSet = true); - - + /** + * Set the inhibit time for position telegrams (1 .. 31 Seconds) + * (Bit 1-5 in UMGEBUNGS_MELDUNG(2)) + * @param a_doSet + */ void setPositionSendTime(unsigned int sendTime); - - + /** + * Set the current air load to be sent with the Umgebungsmeldung + * (Bit 6-7 in UMGEBUNGS_MELDUNG(2)) + * @param airLoad The current air-load received from Tetra + */ void setAirLoad(PrtCnvRadioThread::E_TrafficLoad airLoad); - - + /** + * Returns true if the resetCounter itself is different than the reset-counter of + * the environment-telegram + */ bool isEnvironmentResetCounterOld() const; - - + /** + * Returns the actual Umgebungsmeldung + */ std::shared_ptr getEnvironmentTelegram(); - - + /** + * Sets the resetcounter of the environment-telegram to the actual reset-counter. + */ void setResetCounterOnEnvironment(); - - + /** + * Increments the counter for nachforderungen of the TNE with id a_identity. + * + * @param a_identity The identity of the TNE, which asked for nachforderung + */ void incClaimCount(int a_identity); - - + /** + * Fills the map with nachforderungsstatistic. + * Returns the number of elements in map. + * + * @param a_statisticMap this map will be filled with pairs of + * ausstattungsnummer and amount of nachforderungen + */ std::map getClaimStatistics() const; - - + /** + * Sets the actual machine-state permanent, used to proceed cleaning db after a + * crash. + * + * @param a_newMachineState The new machine-state. 0 => working; 1 => cleaning + * DB + */ void setMachineState(const int a_newMachineState); - - + /** + * Returns true if protocol-converter was crashed while cleanup DB. + */ bool mustProceedCleanup() const; protected: void closeDb(); - - + /** + * List of telegrams to be sent to central + */ std::vector m_CentralList; @@ -224,18 +363,23 @@ namespace PrtCnv mutable QRecursiveMutex m_CentralListMutex; - - + /** + * The permanent DB + */ QSqlDatabase m_db; - - + /** + * The last counter received from central as ack. Used for deleting no longer used + * central-telegrams and for resending of central-telegrams. + */ QAtomicInt m_CentralAckCounter; - - + /** + * Used for optimizing deletion of no longer needed central-telegrams. + */ unsigned int m_OldCentralAckCounter; - - + /** + * List of telegrams to be sent to radio + */ std::list m_RadioList; @@ -252,77 +396,104 @@ namespace PrtCnv std::list m_BroadcastList; - - + /** + * Used to wait until cleaning is finished and to suppress storing data within + * database while cleaning + */ bool m_DoClean; - - + /** + * Used for waiting data written to DB + */ bool m_DoWaitUntilSqlWritten; - - + /** + * Holds all logged in members ordered by Id. + */ std::unordered_map m_MemberListById; - - + /** + * Holds all logged in members ordered by ISSI + */ std::unordered_map m_MemberListByISSI; - - + /** + * Used to prevent data storing within DB while restoring after crash + */ bool m_DoStorePermanent; - - + /** + * the actual reset-counter + */ uint8_t m_ResetCounter; - - + /** + * The actual 'Betriebszustaende Gefechtsfeld' which will be sent to TNEs + * periodically + */ uint8_t m_BattleFieldOperatingState; - - + /** + * The actual telegram "Umgebungsmeldung" + */ PrtCnvStoredRadioTelegram* m_EnvironmentTelegram; - - + /** + * True if cleanup has to be proceed after crash. + */ bool m_DoProceedCleanup; - - + /** + * Used to optimize send the signal permanentStored + */ int32_t m_OldCentralCounter; - - + /** + * For ensure that not too much storePermanent-signals will be queued + */ QBasicAtomicInt m_StorePermanentPending; - - + /** + * nbr of unsuccessful send-attempts, before telegram will be deleted without + * sending it + */ uint32_t m_NbrOfAttempts; - - + /** + * creates or restores the permanent database + */ bool createDatabase(); - - + /** + * Sends a signal storePermanent if not already such a signal is pending + */ void sendStorePermanentSignal(); - - + /** + * Helper for storePermanent() + */ void storeCentralTelegrams(); - - + /** + * Helper for storePermanent() + */ int32_t storeRadioTelegrams(); - - + /** + * Helper for storePermanent() + */ void handleSqlCommandList(); - - + /** + * Delete all telegrams with the ids in telegramsToDelete + * from a given table + */ void deleteTelegramsFromDbById(const QString &table); - - + /** + * Update the write counter for the telegrams in + * telegramsToUpdateCounter for the given table + */ void updateTelegramsWriteCounter(const QString &table); - - + /** + * Update the broadcast counter for the telegrams in + * telegramsToUpdateCounter for the given table + */ void updateTelegramsBroadcast(const QString &table); - - + /** + * Reinitialize the database + */ void reinitDatabase(); QString toCentralTableName() const { return tableName(QStringLiteral("prtcnv_to_central")); } @@ -332,31 +503,39 @@ namespace PrtCnv QString versionTableName() const { return tableName(QStringLiteral("prtcnv_version")); } QString tableName(const QString &table) const { return m_dbSchemaName.isEmpty() ? table : m_dbSchemaName + QLatin1Char('.') + table; } protected slots: - - + /** + * Stores the radio-telegrams, central-telegrams in Db and executes the sql- + * command-list. + */ void storePermanent(); - - + /** + * cleans up this thread and its childs + */ void clean(); public: signals: - - + /** + * Signal to call storePermanent() + */ void doStorePermanent(); - - + /** + * Signal to inform central-thread about stored telegrams + * + * @param a_centralCounter + */ void permanentStored(int32_t a_centralCounter); - - + /** + * a signal to erase the permanent database + */ void doClean(); void playerLicencedChanged(int equipNo, N_CoPrtCnv::E_LicensingKind kind); private: - - - + // local caches to memory (re)allocation all the time + // note: std::vector.clear() does not release memory and therefore + // a reallocation in the next turn is not neccessary std::vector m_telegramsToDelete; std::vector > m_telegramsToUpdateCounter; std::vector > m_telegramsToUpdateBC; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.cpp index 91230606d..2e5e78ecb 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.cpp @@ -1,17 +1,17 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - +// manual class headers #include "PrtCnvInjectionSocket.hpp" #include #include @@ -33,9 +33,9 @@ PrtCnvInjectionSocket::~PrtCnvInjectionSocket() delete m_Socket; } - - - +// --------------------------------------------------------------- +// Disconnects a TCP-client +// --------------------------------------------------------------- void PrtCnvInjectionSocket::disconnectClient() { INFO_LOG(m_logger) << "A client has disconnected from the injection-server"; @@ -43,9 +43,9 @@ void PrtCnvInjectionSocket::disconnectClient() } - - - +// --------------------------------------------------------------- +// Reads in TCP-data and handles them +// --------------------------------------------------------------- void PrtCnvInjectionSocket::processInputData() { INFO_LOG(m_logger) << "Injection-server has data received"; @@ -55,7 +55,7 @@ void PrtCnvInjectionSocket::processInputData() { if (injectionHeader.isIdCorrect()) { - + // check whether all bytes are available qint64 available = m_Socket->bytesAvailable(); if (available < qint64(injectionHeader.m_Size + sizeof(injectionHeader))) { @@ -64,15 +64,15 @@ void PrtCnvInjectionSocket::processInputData() << injectionHeader.m_Id1 << " id2=" << injectionHeader.m_Id2 << " kind=" << (int)injectionHeader.m_Kind << " size=" << injectionHeader.m_Size; - return; + return; // try it later, when (maybe) enough bytes are available... } - + // enough bytes => read now all in m_Socket->read((char*)&injectionHeader, sizeof(injectionHeader)); if (injectionHeader.isIdCorrect()) { - + //INFO_LOG(m_logger) << "kind=" << (int)injectionHeader.m_Kind << " size=" << injectionHeader.m_Size; - + // read the data QByteArray data(injectionHeader.m_Size, Qt::Uninitialized); m_Socket->read(data.data(), injectionHeader.m_Size); @@ -111,7 +111,7 @@ void PrtCnvInjectionSocket::processInputData() } } - +// --------------------------------------------------------------- void PrtCnvInjectionSocket::setSocket(QTcpSocket* a_socket, PrtCnvInjectionThread* a_server) { m_Socket = a_socket; @@ -124,4 +124,4 @@ void PrtCnvInjectionSocket::setSocket(QTcpSocket* a_socket, PrtCnvInjectionThrea } } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.hpp index dc7687f15..f2a917bd0 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionSocket.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -21,8 +21,13 @@ class QTcpSocket; namespace PrtCnv { class PrtCnvInjectionThread; - - + /** + * Used for receiving the socket signals + * + * @author alois.wismer + * @version 1.0 + * @created 06-Aug-2010 16:41:44 + */ class PrtCnvInjectionSocket : public QObject { Q_OBJECT @@ -31,8 +36,11 @@ namespace PrtCnv PrtCnvInjectionSocket(); ~PrtCnvInjectionSocket(); - - + /** + * + * @param a_socket + * @param a_server + */ void setSocket(QTcpSocket* a_socket, PrtCnvInjectionThread* a_server); protected: @@ -42,19 +50,23 @@ namespace PrtCnv NGL::INGLLogger &m_logger; protected slots: - - + /** + * Disconnects a TCP-client + */ void disconnectClient(); - - + /** + * Reads in TCP-data and handles them + */ void processInputData(); public: signals: - - + /** + * + * @param a_injectSocket + */ void disconnected(PrtCnvInjectionSocket* a_injectSocket); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.cpp index 98e06717d..5fddc8db6 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.cpp @@ -1,17 +1,17 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - +// manual class headers #include "PrtCnvInjectionThread.hpp" #include "PrtCnvInjectionSocket.hpp" @@ -23,7 +23,7 @@ namespace PrtCnv { - +// --------------------------------------------------------------- PrtCnvInjectionThread::PrtCnvInjectionThread(PrtCnvThreadStarter* a_parent) : PrtCnvThread(a_parent, "PrtCnvInjectionThread") , m_Port(46666) @@ -41,7 +41,7 @@ PrtCnvInjectionThread::~PrtCnvInjectionThread() delete m_RadioListMutex; } - +// --------------------------------------------------------------- int32_t PrtCnvInjectionThread::create(NGL::Settings *settings) { INFO_LOG(m_logger) << "create"; @@ -52,7 +52,7 @@ int32_t PrtCnvInjectionThread::create(NGL::Settings *settings) m_Enabled = m_Config->getBoolean(getName(), QStringLiteral("Enable"), false); - + // prepare a tcp-server for simulating central if (m_Enabled) { m_Server = new QTcpServer(this); @@ -64,7 +64,7 @@ int32_t PrtCnvInjectionThread::create(NGL::Settings *settings) } - +// --------------------------------------------------------------- int32_t PrtCnvInjectionThread::init() { INFO_LOG(m_logger) << "init"; @@ -76,15 +76,15 @@ int32_t PrtCnvInjectionThread::init() - - - +// --------------------------------------------------------------- +// Starts the thread and listen for TCP-clients +// --------------------------------------------------------------- int32_t PrtCnvInjectionThread::start() { INFO_LOG(m_logger) << "Start"; PrtCnvThread::start(); - + // start the TCP-server if (m_Enabled) { m_Server->setMaxPendingConnections(1); @@ -97,9 +97,9 @@ int32_t PrtCnvInjectionThread::start() - - - +// --------------------------------------------------------------- +// Connects a TCP-client +// --------------------------------------------------------------- void PrtCnvInjectionThread::connectClient() { INFO_LOG(m_logger) << "A client has connected to the injection-server"; @@ -111,9 +111,9 @@ void PrtCnvInjectionThread::connectClient() - - - +// --------------------------------------------------------------- +// Disconnects a TCP-client +// --------------------------------------------------------------- void PrtCnvInjectionThread::disconnectClient(PrtCnvInjectionSocket *a_injectionSocket) { auto it = m_SocketList.find(a_injectionSocket); @@ -125,13 +125,13 @@ void PrtCnvInjectionThread::disconnectClient(PrtCnvInjectionSocket *a_injectionS - - - - - - - +// --------------------------------------------------------------- +// Returns the next central-telegram to be injected. It will +// automatically be taken out of the list. +// The caller is responsible to delete the telegram, if no +// longer used. +// Returns NULL if no central-telegram available +// --------------------------------------------------------------- N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextCentralInjectionTelegram() { QMutexLocker l(m_CentralListMutex); @@ -144,13 +144,13 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextCentralInject } - - - - - - - +// --------------------------------------------------------------- +// Returns the next radio-telegram to be injected. It will +// automatically be taken out of the list. +// The caller is responsible to delete the telegram, if no +// longer used. +// Returns NULL if no radio-telegram available +// --------------------------------------------------------------- N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextRadioInjectionTelegram() { QMutexLocker l(m_RadioListMutex); @@ -163,7 +163,7 @@ N_CoPrtCnv::CoPrtCnvCentralTelegram *PrtCnvInjectionThread::getNextRadioInjectio } - +// --------------------------------------------------------------- void PrtCnvInjectionThread::addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { QMutexLocker l(m_CentralListMutex); @@ -171,12 +171,12 @@ void PrtCnvInjectionThread::addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram } - +// --------------------------------------------------------------- void PrtCnvInjectionThread::addToRadioList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram) { QMutexLocker l(m_RadioListMutex); m_RadioTelegramList.push(a_telegram); } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.hpp index 52cf3ac1d..53b8a981f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvInjectionThread.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -28,8 +28,16 @@ class CoPrtCnvCentralTelegram; namespace PrtCnv { class PrtCnvInjectionSocket; - - + /** + * This class represents a thread, which acts as TCP-Server. The LogView- + * application can connect to it and send radio- or central-telegrams. The + * telegrams will be stored within this class and can be taken by another thread. + * This mechanism will be used for inject telegrams to protocol-converter. + * + * @author alois.wismer + * @version 1.0 + * @created 05-Aug-2010 11:17:06 + */ class PrtCnvInjectionThread : public PrtCnvThread { Q_OBJECT @@ -37,8 +45,10 @@ namespace PrtCnv ~PrtCnvInjectionThread(); - - + /** + * + * @param a_parent + */ explicit PrtCnvInjectionThread(PrtCnvThreadStarter* a_parent); @@ -47,31 +57,48 @@ namespace PrtCnv int32_t init() override; - - + /** + * Starts the thread and listen for TCP-clients + */ int32_t start() override; - - + /** + * Returns the next central-telegram to be injected. It will automatically be + * taken out of the list. + * The caller is responsible to delete the telegram, if no longer used. + * Returns NULL if no central-telegram available + */ N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextCentralInjectionTelegram(); - - + /** + * Returns the next radio-telegram to be injected. It will automatically be taken + * out of the list. + * The caller is responsible to delete the telegram, if no longer used. + * Returns NULL if no radio-telegram available + */ N_CoPrtCnv::CoPrtCnvCentralTelegram *getNextRadioInjectionTelegram(); - - + /** + * + * @param a_telegram + */ void addToCentralList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); - - + /** + * + * @param a_telegram + */ void addToRadioList(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_telegram); - protected: - + protected: /** + * The port of the injection-server (configurable with key 'Port' in group + * [Injection]) + */ uint16_t m_Port; - - + /** + * true if injection-server is enabled (configurable with key 'Enable' in group + * [Injection]) + */ bool m_Enabled; QTcpServer *m_Server; @@ -89,11 +116,15 @@ namespace PrtCnv public slots: - - + /** + * Connects a TCP-client + */ void connectClient(); - - + /** + * Disconnects a TCP-client + * + * @param a_injectionSocket + */ void disconnectClient(PrtCnvInjectionSocket* a_injectionSocket); }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMain.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMain.cpp index 32a5f65bf..823d1c8ca 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMain.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMain.cpp @@ -1,18 +1,24 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - - +/*! +* +* \page Tetra-Interface Tetra-Interface +* +* This component is needed to communicate between the Server software and the players in +* the field via Tetra. It's an extra component due to historical reasons only. +* +*/ #include "PrtCnvApplication.hpp" #include @@ -25,41 +31,41 @@ #include #endif - - - +// --------------------------------------------------------------- +// Become a daemon +// --------------------------------------------------------------- static void daemonize() { #ifndef WIN32 pid_t pid, sid; - + /* already a daemon */ if ( getppid() == 1 ) return; - + /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } - + /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } - + /* At this point we are executing as the child process */ - + /* Change the file mode mask */ umask(0); - + /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); } - - + /* Change the current working directory. This prevents the current + directory from being locked; hence not being able to remove it. */ if ((chdir("/")) < 0) { exit(EXIT_FAILURE); } diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.cpp index 8be0b0767..51d03f522 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.cpp @@ -1,26 +1,26 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - +// manual class headers #include "PrtCnvMember.hpp" #include namespace PrtCnv { - - - +// --------------------------------------------------------------- +// Constructor with id and ISSI as parameter +// --------------------------------------------------------------- PrtCnvMember::PrtCnvMember(int a_id, int a_issi) : m_ISSI(a_issi) , m_ClaimCount(0) @@ -35,9 +35,9 @@ PrtCnvMember::~PrtCnvMember() } - - - +// --------------------------------------------------------------- +// Adds a radio-telegram-fragment to this member. +// --------------------------------------------------------------- void PrtCnvMember::addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram) { m_FragmentedTelegramList.insert(std::make_pair(a_radioTelegram.getFragmentCounter(), @@ -46,28 +46,28 @@ void PrtCnvMember::addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram - - - - - +// --------------------------------------------------------------- +// Returns the telegram-Id of the fragmented telegram assiged +// to this member. +// If not evaluable: 0 will be returned. +// --------------------------------------------------------------- gef_telegramm_id_et PrtCnvMember::getFragmentedTelegramId() const { - + // the fragment with the highest counter is the first fragment for (auto rit = m_FragmentedTelegramList.rbegin(); rit != m_FragmentedTelegramList.rend(); ++rit) { N_CoPrtCnv::CoPrtCnvRadioTelegram *firstFragment = rit->second; if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment == firstFragment->getFragmentStatus()) return firstFragment->getTelID(); } - return GEF_BESTAETIGUNG; + return GEF_BESTAETIGUNG; // no telegram found => return 0 (= GEF_BESTAETIGUNG) } - - - - +// --------------------------------------------------------------- +// Erases the radio-telegram-fragments assiged to this member. +// The fragments itself will be deleted. +// --------------------------------------------------------------- void PrtCnvMember::clearFragmentedList() { for (auto it : m_FragmentedTelegramList) @@ -76,23 +76,23 @@ void PrtCnvMember::clearFragmentedList() } - - - - - +// --------------------------------------------------------------- +// Returns the radio-telegram-fragments assembled to a only +// big radio-telegram. The fragments will not be deleted. +// Returns NULL if it was impossible to assemble the telegram. +// --------------------------------------------------------------- QByteArray PrtCnvMember::getUnfragmentedTelegramData() const { return N_CoPrtCnv::CoPrtCnvRadioTelegram::getUnfragmentedData(m_FragmentedTelegramList); } - - - +// --------------------------------------------------------------- +// Returns true if the fragment-list is empty +// --------------------------------------------------------------- bool PrtCnvMember::isFragmentedListEmpty() const { return m_FragmentedTelegramList.empty(); } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.hpp index 7298efce6..1b88931d7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvMember.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -17,7 +17,7 @@ #include #include - +// manual class imports namespace N_CoPrtCnv @@ -27,14 +27,23 @@ namespace N_CoPrtCnv namespace PrtCnv { - - + /** + * Hold the data of a TNE (Client on radio-side) needed for login, licensing, + * nachforderungs-statistic and reading fragmented telegrams from TNE. + * @author wia + * @version 1.0 + * @updated 16-Mrz-2010 11:20:11 + */ class PrtCnvMember final { public: - - + /** + * The status of the member + * @author wia + * @version 1.0 + * @updated 16-Mrz-2010 11:20:11 + */ enum E_MemberStatus { e_Ok, @@ -44,40 +53,55 @@ namespace PrtCnv }; ~PrtCnvMember(); - - + /** + * Constructor with id and ISSI as parameter + * + * @param a_id + * @param a_issi + */ PrtCnvMember(int a_id, int a_issi); - - + /** + * Adds a radio-telegram-fragment to this member. + * + * @param a_radioTelegram + */ void addFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram); - - + /** + * Returns the telegram-Id of the fragmented telegram assiged to this member. + * If not evaluable: 0 will be returned. + */ gef_telegramm_id_et getFragmentedTelegramId() const; - - + /** + * Erases the radio-telegram-fragments assiged to this member. The fragments + * itself will be deleted. + */ void clearFragmentedList(); - - + /** + * Returns the radio-telegram-fragments assembled to a only big radio-telegram. + * The fragments will not be deleted. + * Returns NULL if it was impossible to assemble the telegram. + */ QByteArray getUnfragmentedTelegramData() const; - - + /** + * Returns true if the fragment-list is empty + */ bool isFragmentedListEmpty() const; public: - + // The ISSI of this TNE (0..0xFFFFFF) int m_ISSI; - + // Counts the Nachforderungen asked from this TNE int m_ClaimCount; - + // the exercise where the member is currently logged in int m_loggedInExerciseId; - + // The identification (also called Ausstattungs-Nummer) of this TNE (0..10000) int m_Id; - + // true if TNE is licensed bool m_Licensed; private: - + // Map of radio-telegram-fragments ordered by fragment-number std::multimap m_FragmentedTelegramList; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.cpp index 3f3076224..7d787fd52 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvRadioThread +// ************************************************************************** #include "PrtCnvRadioThread.hpp" #include "PrtCnvRadioTrafficThread.hpp" @@ -99,9 +99,9 @@ PrtCnvRadioThread::PrtCnvRadioThread(int exerciseId, PrtCnvThreadStarter *a_pare qRegisterMetaType("N_CoPrtCnv::E_LicensingKind"); } - - - +// --------------------------------------------------------------- +// Creates all subcomponents and connects signals to slots +// --------------------------------------------------------------- int32_t PrtCnvRadioThread::create(NGL::Settings *settings) { INFO_LOG(m_logger) << "create"; @@ -142,9 +142,9 @@ int32_t PrtCnvRadioThread::create(NGL::Settings *settings) } - - - +// --------------------------------------------------------------- +// Deallocates subcomponents. +// --------------------------------------------------------------- int32_t PrtCnvRadioThread::destroy() { INFO_LOG(m_logger) << "Destroy"; @@ -154,16 +154,16 @@ int32_t PrtCnvRadioThread::destroy() } - - - +// --------------------------------------------------------------- +// Initializes the variables. +// --------------------------------------------------------------- int32_t PrtCnvRadioThread::init() { INFO_LOG(m_logger) << "init"; PrtCnvSocketThread::init(); m_BroadcastManager.setDbThread(m_DbThread); m_TickTimeout = m_Config->getInteger(QStringLiteral("Broadcast"), QStringLiteral("SendGap"), 500); - m_TicksPerSecond = 1000 / m_TickTimeout; + m_TicksPerSecond = 1000 / m_TickTimeout; // fixme: das funktioniert nur gut, wenn m_TickTimeout ein Teiler von 1000 ist m_BroadcastManager.init(); N_CoPrtCnv::CoPrtCnvRadioTelegram::setEtsMode(m_Config->getBoolean(getName(), QStringLiteral("EtsMode"), false)); @@ -192,7 +192,7 @@ int32_t PrtCnvRadioThread::init() m_LoginPathWithPrefix = m_Config->getString(QStringLiteral("Login"), QStringLiteral("LoginFilePathWithPrefix"), QStringLiteral("login")); if (!QDir::isAbsolutePath(m_LoginPathWithPrefix)) m_LoginPathWithPrefix = QCoreApplication::applicationDirPath() + QLatin1String("/../") + m_LoginPathWithPrefix; - + // create the login-path when it not yet exists m_LoginPathWithPrefix = QDir::cleanPath(QDir::fromNativeSeparators(m_LoginPathWithPrefix)); QString path = m_LoginPathWithPrefix.left(m_LoginPathWithPrefix.lastIndexOf(QLatin1Char('/'))); QDir().mkpath(path); @@ -222,9 +222,9 @@ int32_t PrtCnvRadioThread::init() } - - - +// --------------------------------------------------------------- +// Starts the thread and connects to TCP-server +// --------------------------------------------------------------- int32_t PrtCnvRadioThread::start() { INFO_LOG(m_logger) << "Start"; @@ -235,14 +235,14 @@ int32_t PrtCnvRadioThread::start() - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvRadioThread::connected() { INFO_LOG(m_logger) << "Radio-Socket connected m_Socket=" << m_Socket; - m_ReceiveCounter = END_COUNTER - 1; - m_SendCounter = END_COUNTER; + m_ReceiveCounter = END_COUNTER - 1; // start with counter 0 (preincrement) + m_SendCounter = END_COUNTER; // start with counter 0 m_SentTelegrams = 0; m_SentBytes = 0; m_ReceivedTelegrams = 0; @@ -261,19 +261,19 @@ void PrtCnvRadioThread::connected() } - - - - +// --------------------------------------------------------------- +// Makes empty the message-queue faster, because the messages +// will be consumed without action. +// --------------------------------------------------------------- void PrtCnvRadioThread::prepareCleanUp() { m_DoCleanup = true; } - - - +// --------------------------------------------------------------- +// Stops work for cleaning DB +// --------------------------------------------------------------- void PrtCnvRadioThread::doStop() { m_DoCleanup = true; @@ -283,17 +283,17 @@ void PrtCnvRadioThread::doStop() disconnectSocket(); } - - - +// --------------------------------------------------------------- +// bc nachforderung from Wls +// --------------------------------------------------------------- void PrtCnvRadioThread::onBroadcastTelegramsRequestFromCentral(int equipmentNumber, int broadcastIndex, int resetCounter) { m_BroadcastManager.handleNachforderungBroadcastTelegram(equipmentNumber, broadcastIndex, resetCounter); } - - - +// --------------------------------------------------------------- +// Clean the DB. +// --------------------------------------------------------------- void PrtCnvRadioThread::doClean() { INFO_LOG(m_logger) << "doClean"; @@ -303,9 +303,9 @@ void PrtCnvRadioThread::doClean() } - - - +// --------------------------------------------------------------- +// Restart work after cleaning Db +// --------------------------------------------------------------- void PrtCnvRadioThread::doStart() { m_DoCleanup = false; @@ -315,14 +315,14 @@ void PrtCnvRadioThread::doStart() } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvRadioThread::disconnected() { INFO_LOG(m_logger) << "Radio-Socket disconnected m_Socket=" << m_Socket; - - + // for the case central is disconnecting, we have to disconnect also, otherwise + // we could send rubish (still resisting in buffers) after a reconnection if (e_WORKING == m_State || e_REGISTERING == m_State) { m_Socket->disconnectFromHost(); @@ -342,9 +342,9 @@ void PrtCnvRadioThread::disconnected() } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvRadioThread::readyRead() { N_CoPrtCnv::CoPrtCnvRadioTelegram::PrtCnvRadioGwHeader header; @@ -354,18 +354,18 @@ void PrtCnvRadioThread::readyRead() if (m_DoCleanup) break; - + // read the 4-byte frame-header for find out the length of whole telegram qint64 bytesRead = m_Socket->peek(reinterpret_cast(&header), sizeof(header)); - + // no more data if (0 == bytesRead) break; - + // not yet enough data if (sizeof(header) != bytesRead) break; - + // frame-header must begin with the magic number if (N_CoPrtCnv::CoPrtCnvRadioTelegram::MAGIC_NUMBER != header.m_MagicNumber) { ERROR_LOG(m_logger) << "Reconnect because radio-Telegram does not begin with magic-number 0xA5: I got 0x" @@ -374,12 +374,12 @@ void PrtCnvRadioThread::readyRead() break; } - + // is the length plausible if (!N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(header.m_Length)) WARNING_LOG(m_logger) << "Radio-Telegram length to big: " << header.m_Length << ", but I proceed with this telegram."; - + // prepare data-bucket for entire telegram uint16_t dataSize = header.m_Length + sizeof(header); if (m_Socket->bytesAvailable() < dataSize) { @@ -387,7 +387,7 @@ void PrtCnvRadioThread::readyRead() break; } QByteArray buf(dataSize, Qt::Uninitialized); - + // read the telegram with header bytesRead = 0; while (bytesRead < dataSize) { @@ -397,29 +397,29 @@ void PrtCnvRadioThread::readyRead() if (!checkAndUpdateReceiveCounter(header.m_Counter, END_COUNTER, START_COUNTER)) { - + // log the telegram m_LogThread->writeRadioTelegramLog(buf, true, 1); ERROR_LOG(m_logger) << "Reconnect because frame-counter of received radio-telegram was wrong"; disconnectSocket(); break; } - - + // all checks were successful => use the telegram + // ---------------------------------------------- handleReceivedTelegram(buf); - + // update statistics-data for traffic-control m_ReceivedTelegrams++; m_ReceivedBytes += dataSize; } } - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- void PrtCnvRadioThread::handleReceivedTelegram(const QByteArray &data) { if (m_DoDumpReceivedTelegrams) @@ -427,37 +427,37 @@ void PrtCnvRadioThread::handleReceivedTelegram(const QByteArray &data) INFO_LOG(m_logger) << "Received radio-telegram:"; NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Info, data); } - + // evaluate PDU-Type switch (data.at(4)) { - + // response to register indication case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp: - handleRegisterRsp(data.at(5)); + handleRegisterRsp(data.at(5)); // registration status m_State = e_WORKING; break; - + // payload telegram case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: handleDataIndReq(data, true); emit checkSendToCentral(); - return; + return; // no telegram log due to unscrambling - + // ack-telegram case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq: handleReportIndReq(data); break; - + // status-telegram case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_StatusIndReq: handleStatusIndReq(data); break; - + // air-interface-load-telegram case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq: handleAirInterfaceLoadReq(data); break; - case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirLoadHyterra: + case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirLoadHyterra: // ignore for now break; default: @@ -469,9 +469,9 @@ void PrtCnvRadioThread::handleReceivedTelegram(const QByteArray &data) } - - - +// --------------------------------------------------------------- +// Processes the data-indication-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeScrambled) { N_CoPrtCnv::CoPrtCnvRadioTelegram radioTelegram(data); @@ -483,10 +483,10 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc return; } - + // after unscrambling... m_LogThread->writeRadioTelegramLog(radioTelegram.data(), true, 1); - + // TrafficLoad keine Fehlermeldung wenn nicht lizensiert if (radioTelegram.isNormalTelegram() && radioTelegram.getTelID() == GEF_ESW_MELDUNG) return; @@ -496,9 +496,9 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc m_radioTrafficThread = qobject_cast(m_Parent->getOtherThread(PrtCnvApplication::e_RadioTraffic)); if (m_radioTrafficThread) m_radioTrafficThread->newTelegramArrived(radioTelegram.getPayloadSize()); - - - PrtCnvMember *member = m_DbThread->getMemberByISSI(radioTelegram.getSrcISSI()); + // check whether the TPU is logged in (login telegrams will always be accepted) + // we do not check whether the ausstattungsnummer is correct (id from map[issi] == id from telegram), we simply trust the TNE + PrtCnvMember *member = m_DbThread->getMemberByISSI(radioTelegram.getSrcISSI()); // because of fragmented telegrams we have to use the ISSI (fragmented telegrams have no ausstattungsnummer) if (radioTelegram.isLoginTelegram() || (member != nullptr)) { switch (radioTelegram.getFragmentStatus()) @@ -506,16 +506,16 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment: - + // check whether the member is licensed if (member->m_Licensed) handleFragmentedTelegram(radioTelegram); else { - + // the TNE tries to send a telegramm without beeing licensed => unlicense the TNE sendLizenzierungTneToRadio(member->m_Id, member->m_ISSI, N_CoPrtCnv::E_LicensingKind::Unlicense, N_CoPrtCnv::E_LicensingErrorCode::Unlicense); - + // and send fehlermeldungGefechtsfeld to central sendFehlermeldungGefechtsfeldToCentral(member->m_Id, TrainingAreaBase::TetraIcd::CtaDataError::Reason::ErrorNotLicensed, N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment == radioTelegram.getFragmentStatus() ? @@ -533,30 +533,30 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc if (radioTelegram.isCrcOk()) { radioTelegram.fixupTelegramIdForEts(false); - + // check whether the member is licensed or whether it is the BITE-telegram for NEUE_ANMELDUNG or WIEDER_ANMELDUNG gef_telegramm_id_et telId = radioTelegram.getTelID(); - + // BITE must be send to central - no matter if licensed or not bool bIsBite = (GEF_BITE_MELDUNG2 == telId); if (member->m_Licensed || bIsBite) { - + // check whether the content of telegram is correct if (radioTelegram.isContentValid()) { - + // handle nachforderung broadcasts if (m_BroadcastManager.handleRadioTelegram(radioTelegram)) { std::shared_ptr centralTelegram(N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(&radioTelegram)); if (centralTelegram) { - - - + // for some telegrams the protocol-converter has to send a response + // we have to generate this answer before storing, because storeCentralTelegram() overtakes + // centralTelegram and deletes it if no longer used. if (sendAnswer(radioTelegram)) { - - + // save data in persistent database + //storeCentralTelegram(centralTelegram, radioTelegram); m_DbThread->storeCentralTelegram(centralTelegram, radioTelegram); } } @@ -564,7 +564,7 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc } else { - + // and send fehlermeldungGefechtsfeld to central sendFehlermeldungGefechtsfeldToCentral(member->m_Id, TrainingAreaBase::TetraIcd::CtaDataError::Reason::InvalidByteCount, telId); @@ -573,11 +573,11 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc } else { - + // the TNE tries to send a telegramm without beeing licensed => unlicense the TNE sendLizenzierungTneToRadio(member->m_Id, member->m_ISSI, N_CoPrtCnv::E_LicensingKind::Unlicense, N_CoPrtCnv::E_LicensingErrorCode::Unlicense); - + // and send fehlermeldungGefechtsfeld to central sendFehlermeldungGefechtsfeldToCentral(member->m_Id, TrainingAreaBase::TetraIcd::CtaDataError::Reason::ErrorNotLicensed, telId); @@ -615,7 +615,7 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc ERROR_LOG(m_logger) << "The TPU with id=" << radioTelegram.getIdentity() << " and ISSI=" << radioTelegram.getSrcISSI() << " has sent a telegram without be logged in"; - + // middle or last fragments have on identity => use identity 0 instead bool hasId = !(radioTelegram.getFragmentStatus() == N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment || radioTelegram.getFragmentStatus() == N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment); sendLoginResponse(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginReject, hasId ? radioTelegram.getIdentity() : 0, radioTelegram.getSrcISSI()); } @@ -624,10 +624,15 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc { if (m_EmergencyCallISSI == dstISSI) { - - + /* + 0000: a5 33 20 00 02 a4 0f 00 + 0008: 00 28 23 00 00 0a 17 0f + 0010: 00 00 00 00 00 00 54 00 + 0018: 0a 00 00 65 38 e2 5b a2 + 0020: 49 00 00 2f + */ uint32_t arr[10]; - + // payload starts at 27, byte 26 is fragment status in normal telegram but we need it here -> -1 for (int i = 0; i < 10; ++i) arr[i] = static_cast(radioTelegram.getPayloadDataUInt8(i - 1)); for (int i = 0; i < 10; ++i) @@ -664,23 +669,23 @@ void PrtCnvRadioThread::handleDataIndReq(const QByteArray &data, bool bIsMaybeSc } - - - +// --------------------------------------------------------------- +// Processes the login-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleLoginTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_loginTelegram) { using namespace N_CoPrtCnv; uint16_t identity = a_loginTelegram.getIdentity(); uint32_t issi = a_loginTelegram.getSrcISSI(); - + // is it a login request? if (CoPrtCnvRadioTelegram::e_LoginRequest != (a_loginTelegram.getPayloadDataUInt8(2) & CoPrtCnvRadioTelegram::e_LoginStatusMask)) { ERROR_LOG(m_logger) << QStringLiteral("Unexpected login-status: 0x%1").arg(a_loginTelegram.getPayloadDataUInt8(2), 2, 16, QLatin1Char('0')); return; } - + // tries a TNE to use the identity or ISSI used for broadcast? if (0 == identity || m_BroadcastISSI == issi) { sendLoginResponse(CoPrtCnvRadioTelegram::e_LoginReject, identity, issi); @@ -706,43 +711,43 @@ void PrtCnvRadioThread::handleLoginTelegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg const int tpuExId = exerciseIdForIdentity(identity); TRACE_LOG(m_logger) << "Exercise Id for EqId " << identity << " is: " << tpuExId; - + // is a TPU with same ID or ISSI already logged in? if (member || issiMember) { - - + // TPU already logged in + // is it a relogin of the same TPU? if (member && (issi == uint32_t(member->m_ISSI))) { - - - + // relogin of a TPU + // ---------------- + // relogin happens when a TPU was powered off and on again, therefore it should no longer be licensed if (member->m_Licensed) m_DbThread->licenseMember(member, false); m_DbThread->updateExerciseIdForMember(member, m_ExerciseId); - + // send answer to TPU sendLoginAccept(identity, issi, tpuExId, bIsMasteringFlag); } else { if (bIsMasteringFlag) { - + // accept new TPU m_DbThread->addMember(identity, issi); - + // send answer to TNE sendLoginAccept(identity, issi, tpuExId, bIsMasteringFlag); sendFehlermeldungGefechtsfeldToCentral(identity, TrainingAreaBase::TetraIcd::CtaDataError::Reason::InfoLoginMasteringFlag); } else { - - + // mastering-bit is not set => reject the new TPU + // ---------------------------------------------- int rejectCause = 0; if (issiMember) rejectCause |= CoPrtCnvRadioTelegram::e_LoginOtherISSI; else if (member) rejectCause |= CoPrtCnvRadioTelegram::e_LoginOtherEqId; else - rejectCause |= CoPrtCnvRadioTelegram::e_LoginMastering; + rejectCause |= CoPrtCnvRadioTelegram::e_LoginMastering; // can not happen rejectCause |= CoPrtCnvRadioTelegram::e_LoginReject; sendLoginResponse(CoPrtCnvRadioTelegram::E_LoginStatus(rejectCause), @@ -755,19 +760,19 @@ void PrtCnvRadioThread::handleLoginTelegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg } else { - - + // TPU not yet logged in => add new TPU + // ------------------------------------ m_DbThread->addMember(identity, issi); m_DbThread->updateExerciseIdForMember(issiMember, m_ExerciseId); - + // send answer to TNE sendLoginAccept(identity, issi, tpuExId, bIsMasteringFlag); } } - - - +// --------------------------------------------------------------- +// Processes a fragment of a telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_fragmentedTelegram) { PrtCnvMember *member = m_DbThread->getMemberByISSI(a_fragmentedTelegram.getSrcISSI()); @@ -778,21 +783,21 @@ void PrtCnvRadioThread::handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadio bool doAddFragment = true; if (a_fragmentedTelegram.getFragmentStatus() == N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment) { - - + // first fragment => check whether the previous fragmented telegram was complete + // -------------- if (!member->isFragmentedListEmpty()) { ERROR_LOG(m_logger) << "Did not get the last radio-telegram-fragment"; sendFehlermeldungGefechtsfeldToCentral(member->m_Id, TrainingAreaBase::TetraIcd::CtaDataError::Reason::FragmentationError, member->getFragmentedTelegramId()); - member->clearFragmentedList(); + member->clearFragmentedList(); // deletes also the fragmented radio-telegrams itself } } else if (a_fragmentedTelegram.getFragmentStatus() == N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment) { - - + // last fragment => check whether at least one fragment was received + // ------------- if (member->isFragmentedListEmpty()) { ERROR_LOG(m_logger) << "Got a lonely last radio-telegram-fragment"; @@ -802,13 +807,13 @@ void PrtCnvRadioThread::handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadio } else { - + // it seems we got all fragments => build the not fragmented telegram member->addFragmentedTelegram(a_fragmentedTelegram); const QByteArray unfragmentedRadioTelegramData = member->getUnfragmentedTelegramData(); if (!unfragmentedRadioTelegramData.isEmpty()) { - - + // last but not least, handle the new build unfragmented telegram + // size = 0 is ok - it's a payload tleegram and size will be calculated later on handleDataIndReq(unfragmentedRadioTelegramData, false); } else @@ -816,23 +821,23 @@ void PrtCnvRadioThread::handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadio TrainingAreaBase::TetraIcd::CtaDataError::Reason::FragmentationError, member->getFragmentedTelegramId()); } - member->clearFragmentedList(); + member->clearFragmentedList(); // deletes also the fragmented radio-telegrams itself doAddFragment = false; } else { - - + // middle-fragment => check whether the first fragment was received + // --------------- if (member->isFragmentedListEmpty()) { ERROR_LOG(m_logger) << "Did not get the first radio-telegram-fragment"; - - member->clearFragmentedList(); + // wait with the error-message (FehlermeldungGefechtsfeld) to central until the last fragment is received, otherwise we get for every fragment an error + member->clearFragmentedList(); // deletes also the fragmented radio-telegrams itself doAddFragment = false; } } - + // simply add the fragment to its member if (doAddFragment) { member->addFragmentedTelegram(a_fragmentedTelegram); @@ -846,9 +851,9 @@ void PrtCnvRadioThread::handleFragmentedTelegram(const N_CoPrtCnv::CoPrtCnvRadio } - - - +// --------------------------------------------------------------- +// Processes the BITE extended-telegram +// --------------------------------------------------------------- bool PrtCnvRadioThread::handleBITEEXT_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_BITE_RadioTelegram) { auto anmeldeart = static_cast(a_BITE_RadioTelegram.getPayloadDataUInt32(7, 1)); @@ -856,7 +861,7 @@ bool PrtCnvRadioThread::handleBITEEXT_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTe uint32_t ergebnisAusstattung = a_BITE_RadioTelegram.getPayloadDataUInt8(11); uint32_t konfigurationsvergleich = a_BITE_RadioTelegram.getPayloadDataUInt8(23); uint32_t aktuelleKonfiguration = a_BITE_RadioTelegram.getPayloadDataUInt32(24, 3); - + //rad all byte errors for warehouse traffic light? QList fehlerListe; const auto nonDynamic = getBiteError(a_BITE_RadioTelegram, 12); if (nonDynamic.errorNumber != 0 || @@ -893,7 +898,7 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg { switch (anmeldeart) { - case TrainingAreaBase::TetraIcd::BiteReport::LoginType::InvalidLogin: + case TrainingAreaBase::TetraIcd::BiteReport::LoginType::InvalidLogin: // should not be sent return true; case TrainingAreaBase::TetraIcd::BiteReport::LoginType::NoLogin: case TrainingAreaBase::TetraIcd::BiteReport::LoginType::NewLogin: @@ -903,20 +908,20 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg bool doForwardBiteMeldung = true; QString logText(QStringLiteral("Licensing: The TPU with Id=%1 and ISSI=%2").arg(identity).arg(a_BITE_RadioTelegram.getSrcISSI())); - + // is this TPU logged in? PrtCnvMember *member = m_DbThread->getMemberById(identity); if (member) { - - + // TPU is logged in + // is the ISSI correct? if (a_BITE_RadioTelegram.getSrcISSI() == uint32_t(member->m_ISSI)) { - - + // the ISSI is correct + // is the identity vaild? if (isIdentityValid(identity)) { m_DbThread->updateExerciseIdForMember(member, m_ExerciseId); - + // already licensed? if (!member->m_Licensed) { m_DbThread->licenseMember(member); @@ -932,24 +937,24 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg else logText += QStringLiteral(" is now relicensed"); } - - N_CoPrtCnv::E_LicensingErrorCode errorCode = N_CoPrtCnv::E_LicensingErrorCode::Ok; - + // check the configuration and selftest + N_CoPrtCnv::E_LicensingErrorCode errorCode = N_CoPrtCnv::E_LicensingErrorCode::Ok; // ask ehrlicher (16): inform RDE about the error-codes + // Error-Code in aufsteigender Prioritaet! if (ergebnisAusstattung != 1) { - + // battery-warning errorCode = N_CoPrtCnv::E_LicensingErrorCode::Battery; logText += QStringLiteral(", has battery-Warning"); } if ((ergebnisCAN & aktuelleKonfiguration) != aktuelleKonfiguration) { - + // failure in selftest errorCode = N_CoPrtCnv::E_LicensingErrorCode::Selftest; logText += QStringLiteral(", but selftest is failed"); } if (konfigurationsvergleich != 0) { - + // configuraton-failure errorCode = N_CoPrtCnv::E_LicensingErrorCode::Configuration; logText += QStringLiteral(", but has configuration-failure: "); } @@ -959,13 +964,13 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg prepareWareHouseMessage(identity, doLicense, ergebnisCAN, ergebnisAusstattung, aktuelleKonfiguration, konfigurationsvergleich, fehlerListe); if (anmeldeart == TrainingAreaBase::TetraIcd::BiteReport::LoginType::NoLogin) return true; - - + // send the FehlermeldungGefechtsfeld message to central + // send the Lizensierung-TNE telegram to TPU sendLizenzierungTneToRadio(identity, member->m_ISSI, doLicense ? N_CoPrtCnv::E_LicensingKind::Success : N_CoPrtCnv::E_LicensingKind::Rejected, errorCode); - + // set active position response if (doLicense) m_DoNeedActPosResp.insert(identity); if (selftestOrConfigError) @@ -974,7 +979,7 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg a_BITE_RadioTelegram.getTelID()); - + // generate the login-log-entry if (selftestOrConfigError && !m_DoLicenseDespiteSelftestOrConfigFailure) { logText = QStringLiteral("Licensing: The TPU with Id=%1 and ISSI=%2").arg(identity).arg(a_BITE_RadioTelegram.getSrcISSI()); @@ -987,7 +992,7 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg } else { - + // identity is not vaild => send the Lizenzierung-TNE.Abmeldung telegram to TPU and Fehlermeldung to central sendLizenzierungTneToRadio(identity, member->m_ISSI, N_CoPrtCnv::E_LicensingKind::Rejected, N_CoPrtCnv::E_LicensingErrorCode::IdentityDenied); sendFehlermeldungGefechtsfeldToCentral(identity, TrainingAreaBase::TetraIcd::CtaDataError::Reason::ErrorSendingNamelist, @@ -997,7 +1002,7 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg } else { - + // ISSIs are different => send a login-reject-telegram to this TPU sendLoginResponse(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginReject, identity, a_BITE_RadioTelegram.getSrcISSI()); logText += QStringLiteral(" could not be licensed because ISSI is wrong"); doForwardBiteMeldung = false; @@ -1005,7 +1010,7 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg } else { - + // TPU is not logged in => send a login-reject-telegram to this TPU sendLoginResponse(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginReject, identity, a_BITE_RadioTelegram.getSrcISSI()); logText += QStringLiteral(" wants to be licensed but is not logged in"); doForwardBiteMeldung = false; @@ -1019,12 +1024,12 @@ bool PrtCnvRadioThread::handleBITE_Telegram(const N_CoPrtCnv::CoPrtCnvRadioTeleg } - - - +// --------------------------------------------------------------- +// Checks whether a normal telegram must be sent and sends it. +// --------------------------------------------------------------- void PrtCnvRadioThread::checkSend() { - + // eat all pending timeoutAck if (m_DoCleanup) return; if (PrtCnvSocketThread::e_WORKING != m_State) @@ -1037,8 +1042,8 @@ void PrtCnvRadioThread::checkSend() const auto radioTelegram = m_DbThread->getNextRadioTelegram(handle); if (radioTelegram) { - - + // for normal (not fragmented, no login-) telegrams from central we could have to do special action + // which will be done before sending if (radioTelegram->isNormalTelegram()) { switch (radioTelegram->getTelID()) @@ -1057,14 +1062,14 @@ void PrtCnvRadioThread::checkSend() m_EnvironmentTelegramTimer = new QTimer(this); connect(m_EnvironmentTelegramTimer, &QTimer::timeout, this, &PrtCnvRadioThread::timeoutEnvironmentTelegram, Qt::QueuedConnection); } - + // start the timer if (m_EnvironmentTelegramTimer) { INFO_LOG(m_logger) << "I got the Umgebungsmeldung-Telegram => I start now sending Umgebungsmeldung periodically"; m_EnvironmentTelegramTimer->setInterval(m_Config->getInteger(getName(), QStringLiteral("CyclicEnvironmentTime"), 30) * 1000); m_EnvironmentTelegramTimer->start(); } - + // if we would not set here the resetCounter, the Umgebungsmeldung would be sent twice radioTelegram->setPayloadDataWithIndex(7, m_DbThread->getResetCounter(), 1); break; } @@ -1075,13 +1080,13 @@ void PrtCnvRadioThread::checkSend() { WARNING_LOG(m_logger) << "Special Handling for GEF_WIRKFELD_STATUS_MINENSPERRE with id " << wirkfeldKennung << " -> do not send to CTA"; - m_DbThread->radioTelegramSent(m_SendCounter, handle, 0); - return; + m_DbThread->radioTelegramSent(m_SendCounter, handle, 0); // mark as sent in DB without BC + return; // GEF_WIRKFELD_STATUS_MINENSPERRE for already deactivated mine areas are not send } break; } default: - + // no special action break; } } @@ -1093,20 +1098,23 @@ void PrtCnvRadioThread::checkSend() } - - - - +// --------------------------------------------------------------- +// Processes the periodical stuff, like broadcasts and +// nachforderungen +// --------------------------------------------------------------- void PrtCnvRadioThread::timeoutTick() { - - - - - + // INFO_LOG(m_logger) << "tick"; + // todo: + /* - jede sekunde statistik-daten updaten (achtung tick is 500ms und konfigurierbar) + - nicht mehr senden, wenn anzahl telegramme erreicht (achtung while-schlaufen) + - load an broadcast-manager weitersenden + - broadcast-manager muss window abhängig von load ändern + */ + // eat all pending timeoutAck if (m_DoCleanup) return; startTickTimer(); - + // send normal broadcasts checkSend(); if (!isSendLimitReached()) { @@ -1115,7 +1123,7 @@ void PrtCnvRadioThread::timeoutTick() while (broadcastTelegram) { uint16_t broadcastIndex = broadcastTelegram->getBroadcastIndex(); - sendTelegram(broadcastTelegram, nullptr, false); + sendTelegram(broadcastTelegram, nullptr, false); // false => do not check whether expired if (isSendLimitReached()) broadcastTelegram = nullptr; @@ -1125,16 +1133,16 @@ void PrtCnvRadioThread::timeoutTick() } else INFO_LOG(m_logger) << "send limit reached"; - + // send nachforderung m_BroadcastManager.incTickAndSetTrafficLoad(E_TrafficLoad::HighLoad == m_SendLoad, E_TrafficLoad::FullLoad == m_SendLoad); if (!isSendLimitReached()) { auto radioTelegram = m_BroadcastManager.getNextNachforderungTelegramToSend(); if (radioTelegram) - sendTelegram(radioTelegram, nullptr, false); + sendTelegram(radioTelegram, nullptr, false); // false => do not check whether expired } - + // do we have to inject a radio-telegram? try { N_CoPrtCnv::CoPrtCnvCentralTelegram *radioInjectTelegram; @@ -1159,16 +1167,16 @@ void PrtCnvRadioThread::timeoutTick() ERROR_LOG(m_logger) << "Catched an unexpected exception: " << e.what() << " => could not inject radio-telegram, but we proceed..."; } - + // send imediately the umgebungsmeldung, when the reset-counter changes if (m_DbThread->isEnvironmentResetCounterOld()) timeoutEnvironmentTelegram(); computeAndLogTrafficStatistics(); } - - - +// --------------------------------------------------------------- +// see base-class +// --------------------------------------------------------------- void PrtCnvRadioThread::timeoutAliveAndConnection() { INFO_LOG(m_logger) << "timeoutAliveAndConnection socketState=" << m_Socket->state() << " m_State=" << m_State; @@ -1188,22 +1196,22 @@ void PrtCnvRadioThread::timeoutAliveAndConnection() } } - - - - - - - - - +// --------------------------------------------------------------- +// 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. +// --------------------------------------------------------------- void PrtCnvRadioThread::sendTelegram(const std::shared_ptr &a_telegram, PrtCnvStoredRadioTelegram *a_handle, const bool a_doCheckWhetherExpired) { uint16_t broadcastIndex = 0; - + // is the TNE logged in? bool isSpecialTelegram = !a_telegram->isNormalTelegram(); bool isLicensing = false; PrtCnvMember *member = nullptr; @@ -1212,22 +1220,22 @@ void PrtCnvRadioThread::sendTelegram(const std::shared_ptrgetMemberById(a_telegram->getIdentity()); isLicensing = (GEF_LIZENSIERUNG_TNE == a_telegram->getTelID()); } - + // is the TNE logged in? register and login-telegrams will always be sent if (member || isSpecialTelegram || isLicensing) { - + // is the TNE licensed? register-, login-, broadcast- and LizenzierungTNE-telegrams will anyway be sent if (!a_telegram->needsLicensing() || (member && member->m_Licensed)) { if (!a_telegram->hasExpired() || !a_doCheckWhetherExpired) { if (a_telegram->isContentValid()) { - + // must the telegram be fragmented? if (a_telegram->mustBeFragmented()) sendFragmentedTelegram(a_telegram); else broadcastIndex = sendToSocket(a_telegram); - + // log telegram into telegram log-file m_LogThread->writeRadioTelegramLog(a_telegram->data(), false, a_telegram->getPriority()); } else @@ -1261,7 +1269,7 @@ void PrtCnvRadioThread::sendTelegram(const std::shared_ptrgetTelID()); ERROR_LOG(m_logger) << "Central tries to send a telegram to TNE with id=" << a_telegram->getIdentity() << ", but the TNE is not logged in!"; - + // hexDumpHelper(m_logger, NGL::LogLevel::Info, a_telegram->data()); } if (a_handle) @@ -1276,9 +1284,9 @@ void PrtCnvRadioThread::sendTelegram(const std::shared_ptr(m_HostISSI)); @@ -1287,9 +1295,9 @@ void PrtCnvRadioThread::doRegister() } - - - +// --------------------------------------------------------------- +// Register to specific message groups (max. 5) +// --------------------------------------------------------------- void PrtCnvRadioThread::registerGroups() { if (m_ListenGroups.empty()) @@ -1298,9 +1306,9 @@ void PrtCnvRadioThread::registerGroups() sendTelegram(registerGroupIndTelegram, nullptr); } - - - +// --------------------------------------------------------------- +// Processes the register-response-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleRegisterRsp(const uint8_t a_regsitrationStatus) { INFO_LOG(m_logger) << "Got Radio-Telegram Register-Rsp with status=" << std::to_string(a_regsitrationStatus); @@ -1360,12 +1368,12 @@ std::ostream &operator<<(std::ostream &os, const PrtCnvRadioThread::E_TrafficLoa } - - - - - - +// --------------------------------------------------------------- +// 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 +// --------------------------------------------------------------- bool PrtCnvRadioThread::sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_radioTelegram) { switch (a_radioTelegram.getTelID()) @@ -1374,11 +1382,11 @@ bool PrtCnvRadioThread::sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_ra return handleBITEEXT_Telegram(a_radioTelegram); case GEF_DEAKTIVIERUNG_EINZELMINE: { - - + // if any TNE is sending DEAKTIVIERUNG_EINZELMINE, we immediately need to send this message + // as broadcast to all TNEs auto radioTelegram(std::make_shared(GEF_DEAKTIVIERUNG_EINZELMINE, 13, 0)); - radioTelegram->setPayload2Byte(0); - radioTelegram->setPayloadData(a_radioTelegram.getPayloadDataPtr(5), 8); + radioTelegram->setPayload2Byte(0); // broadcast-index will be set when sending + radioTelegram->setPayloadData(a_radioTelegram.getPayloadDataPtr(5), 8); // copy the telegram-content storeRadioTelegram(radioTelegram, 0); emit checkSendToRadio(); break; @@ -1392,10 +1400,10 @@ bool PrtCnvRadioThread::sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_ra if (it != m_DoNeedActPosResp.end()) { auto radioTelegram(std::make_shared(GEF_ALLGEMEINE_NACHRICHT, 9, a_radioTelegram.getIdentity())); - radioTelegram->setPayload2Byte(0); - radioTelegram->setPayload1Byte(3); - radioTelegram->setPayload1Byte(0); - radioTelegram->setPayload2Byte(8); + radioTelegram->setPayload2Byte(0); // broadcast-index will be set when sending the radio-telegram + radioTelegram->setPayload1Byte(3); // length 3 + radioTelegram->setPayload1Byte(0); // index 0 -> indexed text + radioTelegram->setPayload2Byte(8); // index 1 16 Bit storeRadioTelegram(radioTelegram, 0); emit checkSendToRadio(); m_DoNeedActPosResp.erase(it); @@ -1403,33 +1411,33 @@ bool PrtCnvRadioThread::sendAnswer(const N_CoPrtCnv::CoPrtCnvRadioTelegram &a_ra break; } default: - + // nothing break; } return true; } - - - +// --------------------------------------------------------------- +// Returns the ISSI of TNE with a_TNE_Id +// --------------------------------------------------------------- uint32_t PrtCnvRadioThread::getDestinationISSI(const uint16_t a_TNE_Id) const { - + // INFO_LOG(m_logger) << "Get ISSI for TNE-Id: " << a_TNE_Id; PrtCnvMember *member = m_DbThread->getMemberById(a_TNE_Id); if (member) - return member->m_ISSI; + return member->m_ISSI; // TPU found ERROR_LOG(m_logger) << "TPU with id=" << a_TNE_Id << " not logged in."; - return 0; + return 0; // TPU not found } - - - +// --------------------------------------------------------------- +// Processes the periodical sending of Umgebungsmeldung +// --------------------------------------------------------------- void PrtCnvRadioThread::timeoutEnvironmentTelegram() { - + // eat all pending timeoutAck if (m_DoCleanup) return; if (PrtCnvSocketThread::e_WORKING != m_State) return; @@ -1446,17 +1454,17 @@ void PrtCnvRadioThread::timeoutEnvironmentTelegram() } - - - +// --------------------------------------------------------------- +// Sends a telegram "FehlermeldungGefechtsfeld" to central +// --------------------------------------------------------------- void PrtCnvRadioThread::sendFehlermeldungGefechtsfeldToCentral(const uint16_t a_identity, const TrainingAreaBase::TetraIcd::CtaDataError::Reason a_errorCause, const gef_telegramm_id_et a_telegramId) { N_CoPrtCnv::CoPrtCnvRadioTelegram radioTelegram(GEF_FEHLERMELDUNG_GFD, 9, a_identity); - radioTelegram.setPayload4Byte(time(nullptr)); - radioTelegram.setPayload1Byte(static_cast(a_errorCause)); - radioTelegram.setPayload1Byte(a_telegramId); + radioTelegram.setPayload4Byte(time(nullptr)); // GPS-Zeit + radioTelegram.setPayload1Byte(static_cast(a_errorCause)); // Ursache + radioTelegram.setPayload1Byte(a_telegramId); // Telegrammkennung std::shared_ptr centralTelegram(N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(&radioTelegram)); @@ -1468,9 +1476,9 @@ void PrtCnvRadioThread::sendFehlermeldungGefechtsfeldToCentral(const uint16_t a_ } - - - +// --------------------------------------------------------------- +// Writes the login of a TNE to the login-logfile +// --------------------------------------------------------------- void PrtCnvRadioThread::writeLoginLog(uint32_t identity, uint32_t issi, const QString &a_prosaText) { const QDateTime dtCur(QDateTime::currentDateTimeUtc()); @@ -1493,7 +1501,7 @@ void PrtCnvRadioThread::writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a QByteArray logData; if (a_radioTelegram) { - + // important data of telegram int len = 3; if (a_radioTelegram->getTelID() == GEF_BITE_MELDUNG2) len = 27; @@ -1506,7 +1514,7 @@ void PrtCnvRadioThread::writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a } const QDateTime dtCur(QDateTime::currentDateTimeUtc()); - + // generate the logline: :;;; logData = QByteArray::number(dtCur.toSecsSinceEpoch()) + ";" + QByteArray::number(a_radioTelegram->getSrcISSI()) + ";" + @@ -1522,11 +1530,11 @@ void PrtCnvRadioThread::writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a INFO_LOG(m_logger) << logData; - + // generate the logfile-name QString date = QDate::currentDate().toString(QLatin1String("yyyyMMdd")); QString fileName = m_LoginPathWithPrefix + date + QLatin1Char('_') + QString::number(m_ExerciseId) + QLatin1String(".log"); - + // write into logfile QFile file(fileName); (void)file.open(QIODevice::Append); file.write(logData); @@ -1534,9 +1542,9 @@ void PrtCnvRadioThread::writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a } - - - +// --------------------------------------------------------------- +// Sends a login-telegram to radio +// --------------------------------------------------------------- void PrtCnvRadioThread::sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegram::E_LoginStatus a_loginTelegramStatus, const uint16_t a_identity, const uint32_t a_ISSI) { @@ -1565,17 +1573,17 @@ void PrtCnvRadioThread::sendLoginResponse(const N_CoPrtCnv::CoPrtCnvRadioTelegra - - - +// --------------------------------------------------------------- +// Sends a telegram "LizenzierungTNE" to radio +// --------------------------------------------------------------- void PrtCnvRadioThread::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) { auto radioTelegram(std::make_shared(GEF_LIZENSIERUNG_TNE, 7, a_identity)); - radioTelegram->setPayload1Byte(static_cast(a_licensingKind)); - radioTelegram->setPayload1Byte(static_cast(a_errorCause)); - radioTelegram->setPayload2Byte(0x0013); + radioTelegram->setPayload1Byte(static_cast(a_licensingKind)); // Lizenzierungsart + radioTelegram->setPayload1Byte(static_cast(a_errorCause)); // Fehlercode Lizenzierung: Index auf ADAG + radioTelegram->setPayload2Byte(0x0013); // Fehlercode Lizenzierung: Index auf ADAG radioTelegram->setDestISSI(a_issi); storeRadioTelegram(radioTelegram, 0); emit checkSendToRadio(); @@ -1583,23 +1591,23 @@ void PrtCnvRadioThread::sendLizenzierungTneToRadio(const uint16_t a_identity, co } - - - - +// --------------------------------------------------------------- +// Receives the file with allowed playerId, or the lowest and +// hightest allowed playerIds +// --------------------------------------------------------------- void PrtCnvRadioThread::initIdentityArray() { const QString loginGroup(QStringLiteral("login")); - + // do we check the identify? if (m_Config->getBoolean(loginGroup, QStringLiteral("DoCheckPlayerId"), true)) { - + // reset the array m_AllowedIdentities.clear(); - + // use we min/max identify or a file with allowed identites? QString identifyFileName = m_Config->getString(loginGroup, QStringLiteral("PlayerIdFilePath"), QString()); if (identifyFileName.isEmpty()) { - + // we use min/max uint32_t lowest = m_Config->getInteger(loginGroup, QStringLiteral("LowestPlayerId"), 1); uint32_t highest = m_Config->getInteger(loginGroup, QStringLiteral("HighestPlayerId"), MAX_IDENTITY); for (uint32_t i = lowest; i <= highest; i++) @@ -1608,15 +1616,15 @@ void PrtCnvRadioThread::initIdentityArray() } else { - + // we use the file INFO_LOG(m_logger) << "PlayerId-file '" << identifyFileName << "' will be used."; - + // get path relative from bin-path QString path = identifyFileName; if (!QDir::isAbsolutePath(path)) path = QCoreApplication::applicationDirPath() + QLatin1Char('/') + path; - + // read in the player-ids QFile file(path); if (file.open(QIODevice::ReadOnly)) { @@ -1633,12 +1641,12 @@ void PrtCnvRadioThread::initIdentityArray() int pos = line.indexOf('-'); if (-1 == pos) { - + // playerID setIdentityVaild(readIdentity(line, lineCount, identifyFileName)); } else { - + // playerID - playerID QByteArray playerId = line.left(pos).trimmed(); uint16_t left = readIdentity(playerId, lineCount, identifyFileName); playerId = line.right(line.length() - pos - 1).trimmed(); @@ -1660,23 +1668,23 @@ void PrtCnvRadioThread::initIdentityArray() } else { - + // no we do not check => simply set all identifies to vaild for (uint32_t i = 0; i <= MAX_IDENTITY; i++) setIdentityVaild(i); } } - - - - +// --------------------------------------------------------------- +// Reads one line of the playerId-file. +// Aborts when not successful +// --------------------------------------------------------------- uint16_t PrtCnvRadioThread::readIdentity(const QByteArray &a_idAsText, const uint32_t a_line, const QString &a_fileName) { ulong playerId = a_idAsText.toULong(); if (0 == playerId || playerId > MAX_IDENTITY) { - + // abort when we have a failure if (0 == playerId) { FATAL_LOG(m_logger) << a_fileName << ":" << a_line << ": could not read playerID - '" @@ -1693,28 +1701,28 @@ uint16_t PrtCnvRadioThread::readIdentity(const QByteArray &a_idAsText, const uin } - - - +// --------------------------------------------------------------- +// Checks whether the playerId is allowd. +// --------------------------------------------------------------- bool PrtCnvRadioThread::isIdentityValid(uint16_t a_identity) const { return m_AllowedIdentities.find(a_identity) != m_AllowedIdentities.end(); } - - - +// --------------------------------------------------------------- +// Allows this playerId. +// --------------------------------------------------------------- void PrtCnvRadioThread::setIdentityVaild(uint16_t a_identity) { m_AllowedIdentities.insert(a_identity); } - - - +// --------------------------------------------------------------- +// Fragment a telegram and sends the fragments to radio. +// --------------------------------------------------------------- void PrtCnvRadioThread::sendFragmentedTelegram(const std::shared_ptr &a_telegram) { - + // send fragmented telegrams uint8_t fragmentCounter = 0; N_CoPrtCnv::CoPrtCnvRadioTelegram::E_FragmentStatus fragmentStatus; do @@ -1724,7 +1732,7 @@ void PrtCnvRadioThread::sendFragmentedTelegram(const std::shared_ptrsetDestISSI(getDestinationISSI(a_telegram->getIdentity())); - + // now call the normal sendTelegram-function again sendTelegram(fragmentedTelegram, nullptr); fragmentStatus = fragmentedTelegram->getFragmentStatus(); } @@ -1740,23 +1748,23 @@ void PrtCnvRadioThread::sendFragmentedTelegram(const std::shared_ptr &a_telegram) { - + // increment the counter and wrap if needed if (++m_SendCounter >= END_COUNTER) m_SendCounter = START_COUNTER; a_telegram->setZaehler(m_SendCounter); - + // set our ISSI a_telegram->setSrcISSI(m_HostISSI); uint16_t broadcastIndex = 0; gef_telegramm_id_et telId = a_telegram->isNormalTelegram() ? a_telegram->getTelID() : GEF_BESTAETIGUNG; if (a_telegram->isNormalTelegram()) { - + // set ISSI of destination if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq == a_telegram->getPDU_Type()) { if (GEF_LIZENSIERUNG_TNE != a_telegram->getTelID()) @@ -1769,10 +1777,10 @@ uint16_t PrtCnvRadioThread::sendToSocket(const std::shared_ptrsetBroadcastIndex(m_BroadcastManager.getBroadcastIndex()); DEBUG_LOG(m_logger) << "MODE with bci is now: " << a_telegram->getBroadcastIndex(); } - + // set broadcastindex if (GEF_UMGEBUNGS_MELDUNG2 == telId) { - + // exception: Umgebungsmeldung does not increment the broadcastindex and must never be stored a_telegram->setBroadcastIndex(m_BroadcastManager.getBroadcastIndex()); a_telegram->setPayloadDataWithIndex(7, m_DbThread->getResetCounter(), 1); a_telegram->setPayloadDataWithIndex(8, m_DbThread->getBattleFieldOperatingState(), 1); @@ -1781,8 +1789,8 @@ uint16_t PrtCnvRadioThread::sendToSocket(const std::shared_ptrmustBroadcastBeSet()) { @@ -1793,7 +1801,7 @@ uint16_t PrtCnvRadioThread::sendToSocket(const std::shared_ptrfixupTelegramIdForEts(true); } - + // send telegram to radio DEBUG_LOG(m_logger) << "Send telegram to radio: telId=" << telId << " wcounter=" << int(a_telegram->zaehler()) << " size=" << a_telegram->getSize(); if (m_DoUseSDSTL && N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq == a_telegram->getPDU_Type()) { @@ -1815,7 +1823,7 @@ uint16_t PrtCnvRadioThread::sendToSocket(const std::shared_ptrwrite(a_telegram->data()); - + // update statistics-data for traffic-control m_SentTelegrams++; m_SentBytes += a_telegram->getSize(); @@ -1824,7 +1832,7 @@ uint16_t PrtCnvRadioThread::sendToSocket(const std::shared_ptr &a_telegram) const { const uint32_t initial = (a_telegram->getSrcISSI() % 0xFFFF) + 1; @@ -1879,23 +1887,23 @@ bool PrtCnvRadioThread::unscrambleContent(N_CoPrtCnv::CoPrtCnvRadioTelegram &a_t return false; } - - + // ERROR_LOG(m_logger) << "Unscrambling... " << a_telegram.getSrcISSI() << " " << payloadOffset << " " << scrambleLen << " " << qint64(a_telegram->getData()) << " " << qint64(dataIn); + // NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Error, a_telegram.data()); scramble(dataIn, dataOut, scrambleLen, initial, polynom); memcpy(dataIn, dataOut, scrambleLen); - - + // ERROR_LOG(m_logger) << "... done " << a_telegram.getSrcISSI(); + // NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Error, a_telegram.data()); return true; } - - - +// --------------------------------------------------------------- +// Processes the report-indication-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleReportIndReq(const QByteArray &data) { const uint8_t *a_data = reinterpret_cast(data.data()); @@ -1909,7 +1917,7 @@ void PrtCnvRadioThread::handleReportIndReq(const QByteArray &data) { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DeliveryFailed: { - uint8_t messageReference = a_data[14]; + uint8_t messageReference = a_data[14]; // messageReference contains the telegramId uint16_t identity = 0; PrtCnvMember *member = m_DbThread->getMemberByISSI(srcISSI); if (member) @@ -1938,7 +1946,7 @@ void PrtCnvRadioThread::prepareWareHouseMessage(qint32 equipNr, bool doLicence, obj.insert(QStringLiteral("configState"), aktuelleKonfiguration); obj.insert(QStringLiteral("configError"), konfigurationsvergleich); QJsonArray errorArr; - + // ERROR_LOG(m_logger) << "ERROR LIST SIZE= " << fehlerListe.size(); for (const auto &error: fehlerListe) { QJsonObject errorObj; @@ -1956,9 +1964,9 @@ void PrtCnvRadioThread::prepareWareHouseMessage(qint32 equipNr, bool doLicence, } - - - +// --------------------------------------------------------------- +// Processes the status-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleStatusIndReq(const QByteArray &data) { const uint8_t *a_data = reinterpret_cast(data.data()); @@ -1969,17 +1977,17 @@ void PrtCnvRadioThread::handleStatusIndReq(const QByteArray &data) << dstISSI << " - status: " << status; } - - - +// --------------------------------------------------------------- +// Processes the air-interface-report-telegram +// --------------------------------------------------------------- void PrtCnvRadioThread::handleAirInterfaceLoadReq(const QByteArray &data) { const uint8_t *a_data = reinterpret_cast(data.data()); - + // get the number of reports uint16_t nbrOfReports = *(uint16_t *)&a_data[5]; INFO_LOG(m_logger) << "Number of AirInterface-reports: " << nbrOfReports; - + // read in the reports and get the queue-length for SDS-network (networkIndex = 1) uint16_t sdsQueueLength = 0; uint16_t index = 7; for (int i = 0; i < nbrOfReports; i++) @@ -1994,7 +2002,7 @@ void PrtCnvRadioThread::handleAirInterfaceLoadReq(const QByteArray &data) sdsQueueLength = queueLength; } E_TrafficLoad newLoad; - + // decide the actual load-factor if (sdsQueueLength > m_SendQueueFullLoad) { newLoad = E_TrafficLoad::FullLoad; @@ -2014,9 +2022,9 @@ void PrtCnvRadioThread::handleAirInterfaceLoadReq(const QByteArray &data) m_SendLoad = newLoad; } - - - +// --------------------------------------------------------------- +// Computes and logs the sent- and receive-statistics +// --------------------------------------------------------------- void PrtCnvRadioThread::computeAndLogTrafficStatistics() { if (++m_TickCounter >= m_TicksPerSecond) @@ -2043,10 +2051,10 @@ void PrtCnvRadioThread::computeAndLogTrafficStatistics() - - - - +// --------------------------------------------------------------- +// returns true, if at the moment no more telegrams should be +// sent +// --------------------------------------------------------------- bool PrtCnvRadioThread::isSendLimitReached() const { switch (m_SendLoad) @@ -2064,13 +2072,13 @@ bool PrtCnvRadioThread::isSendLimitReached() const return false; } - - - - +// --------------------------------------------------------------- +// Immediatelly send the environment telegramm to inform the +// players about the new state +// --------------------------------------------------------------- void PrtCnvRadioThread::sendEnvironmentTelegramTimerNow() { - + // switch thread QTimer::singleShot(0, this, &PrtCnvRadioThread::onSendEnvironmentTelegramTimerNow); } @@ -2141,7 +2149,7 @@ void PrtCnvRadioThread::sendLoginAccept(int identity, int issi, int exerciseId, const auto it = m_groupIssiInformation.find(exerciseId); if (it == m_groupIssiInformation.end() || exerciseId == 0) { - + // no gissi information found or no exercise assigned QString log; if (exerciseId == 0) log = QStringLiteral("Denied Login of TPU with Id=%1 and ISSI=%2 - Id is not assigned in any exercise.") @@ -2188,7 +2196,7 @@ void PrtCnvRadioThread::sendLoginAccept(int identity, int issi, int exerciseId, bool PrtCnvRadioThread::isIdentityInCurrentExercise(int identity) const { QMutexLocker l(&m_exerciseEquipmentAssignmentMutex); - if (m_exerciseEquipmentAssignments.empty()) + if (m_exerciseEquipmentAssignments.empty()) // no assignments at all -> fallback to old behaviour return true; const auto it = m_exerciseEquipmentAssignments.find(m_ExerciseId); if (it == m_exerciseEquipmentAssignments.end()) @@ -2217,18 +2225,18 @@ void PrtCnvRadioThread::removeMasteringMember(const N_CoPrtCnv::CoPrtCnvRadioTel { using namespace N_CoPrtCnv; - + // remove old member if (member) { m_DbThread->updateExerciseIdForMember(member, 0); - + // unlicense the old TPU if (member->m_Licensed) { sendLizenzierungTneToRadio(member->m_Id, member->m_ISSI, N_CoPrtCnv::E_LicensingKind::Unlicense, N_CoPrtCnv::E_LicensingErrorCode::Unlicense); INFO_LOG(m_logger) << "Unlicense TPU with already used ID. Id=" << member->m_Id << " ISSI=" << member->m_ISSI; } - + // reject old TPU sendLoginResponse(CoPrtCnvRadioTelegram::E_LoginStatus(CoPrtCnvRadioTelegram::e_LoginReject | CoPrtCnvRadioTelegram::e_LoginOtherEqId), member->m_Id, member->m_ISSI); INFO_LOG(m_logger) << "Reject TPU with already used ID. Id=" @@ -2239,18 +2247,18 @@ void PrtCnvRadioThread::removeMasteringMember(const N_CoPrtCnv::CoPrtCnvRadioTel m_DbThread->removeMember(member); } - + // remove old issi member if (issiMember) { m_DbThread->updateExerciseIdForMember(issiMember, 0); - + // unlicense the old TPU if (issiMember->m_Licensed) { sendLizenzierungTneToRadio(issiMember->m_Id, issiMember->m_ISSI, N_CoPrtCnv::E_LicensingKind::Unlicense, N_CoPrtCnv::E_LicensingErrorCode::Unlicense); INFO_LOG(m_logger) << "Unlicense TPU with already used ISSI. Id=" << issiMember->m_Id << " ISSI=" << issiMember->m_ISSI; } - + // reject old TPU sendLoginResponse(CoPrtCnvRadioTelegram::E_LoginStatus(CoPrtCnvRadioTelegram::e_LoginReject | CoPrtCnvRadioTelegram::e_LoginOtherISSI), issiMember->m_Id, issiMember->m_ISSI); INFO_LOG(m_logger) << "Reject TPU with already used ISSI. Id=" @@ -2262,4 +2270,4 @@ void PrtCnvRadioThread::removeMasteringMember(const N_CoPrtCnv::CoPrtCnvRadioTel } } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.hpp index 207378d5c..e683021a0 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvRadioThread +// ************************************************************************** #pragma once #include "PrtCnvSocketThread.hpp" @@ -38,8 +38,17 @@ struct BiteError 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 @@ -47,25 +56,33 @@ struct BiteError 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); @@ -80,124 +97,165 @@ public: 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 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 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 &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, @@ -206,12 +264,14 @@ public: 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; @@ -219,79 +279,125 @@ public: 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 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> m_exerciseEquipmentAssignments; std::unordered_map m_groupIssiInformation; mutable QRecursiveMutex 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, @@ -302,47 +408,86 @@ public: const QList &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 &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 &a_telegram); - - + /** + * Processes the report-indication-telegram + * + * @param a_data + */ void handleReportIndReq(const QByteArray &data); void prepareWareHouseMessage(qint32 equipNr, bool doLicence, @@ -353,59 +498,78 @@ public: const QList &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; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.cpp index 989de6cac..27d8dee4d 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// @RDE_HEADER@ +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvRadioTrafficThread +// ************************************************************************** #include "PrtCnvRadioTrafficThread.hpp" #include "PrtCnvDbThread.hpp" @@ -46,7 +46,7 @@ void PrtCnvRadioTrafficThread::newTelegramArrived(unsigned int size) int32_t PrtCnvRadioTrafficThread::start() { - + // read data from m_Config const QString trafficControlGroup(QStringLiteral("TrafficControl")); int highLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueHighLoad"), 60); int fullLoad = m_Config->getInteger(trafficControlGroup, QStringLiteral("ReceiveQueueFullLoad"), 80); @@ -55,7 +55,7 @@ int32_t PrtCnvRadioTrafficThread::start() float trafficPerReceiverKB = m_Config->getFloat(trafficControlGroup, QStringLiteral("ReceiveThroughput"), 3.6f); int cntTransceiver = m_Config->getInteger(trafficControlGroup, QStringLiteral("TransceiverCount"), 6); - + // sanity checks if (highLoad < 0 || highLoad > 100) highLoad = 60; if (fullLoad < highLoad || fullLoad > 100) @@ -74,7 +74,7 @@ int32_t PrtCnvRadioTrafficThread::start() m_fullLoad = maxTrafficBytes * fullLoad / 100.f; m_highLoad = maxTrafficBytes * highLoad / 100.f; m_hystLoad = maxTrafficBytes * hystLoad / 100.f; - m_cleanupTimeout = avgTime * 1000; + m_cleanupTimeout = avgTime * 1000; // ms DEBUG_LOG(m_logger) << "Read config ReceiveQueueHighLoad: " << highLoad; DEBUG_LOG(m_logger) << "Read config ReceiveQueueFullLoad: " << fullLoad; @@ -100,12 +100,12 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad() unsigned int payload = 0; { QMutexLocker l(&m_mutex); - + // fuer aktuelle Sekunde haben wir noch nicht alle Daten for (int i = 1; i <= m_cleanupTimeout / 1000; ++i) payload += m_data.value(curTime - i); } - + // Durchschnitt ... payload /= (m_cleanupTimeout / 1000); INFO_LOG(m_logger) << "Average Payload in the last " @@ -116,34 +116,34 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad() PrtCnvRadioThread::E_TrafficLoad newReceiveLoad; if (payload >= m_fullLoad) { - + // full load newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad; - + // Hysterese nach oben if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad) { - - + // wenn cnt in Bereich m_fullLoad ... m_fullLoad + m_hystLoad + // -> noch warten if(payload < m_fullLoad + m_hystLoad) newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad; } } else if (payload >= m_highLoad) { - + // high load newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad; - + // Hysterese nach oben if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::NormalLoad) { - - + // wenn cnt in Bereich m_highLoad ... m_highLoad + m_hystLoad + // -> noch warten if (payload < m_highLoad + m_hystLoad) newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad; } - + // Hysterese nach unten if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::FullLoad) { - - + // wenn cnt in Bereich m_fullLoad ... m_fullLoad - m_hystLoad + // -> noch warten if (payload >= m_fullLoad - m_hystLoad) newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::FullLoad; } @@ -151,11 +151,11 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad() else { newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::NormalLoad; - + // Hysterese nach unten if (m_receiveLoad == PrtCnvRadioThread::E_TrafficLoad::HighLoad) { - - + // wenn cnt in Bereich m_highLoad ... m_highLoad - m_hystLoad + // -> noch warten if(payload >= m_highLoad - m_hystLoad) newReceiveLoad = PrtCnvRadioThread::E_TrafficLoad::HighLoad; } @@ -163,7 +163,7 @@ void PrtCnvRadioTrafficThread::onCalculateTrafficLoad() if (m_receiveLoad != newReceiveLoad) { m_receiveLoad = newReceiveLoad; - + // Achtung: Nicht mehr als 31 Sekunden erlaubt unsigned int wartezeit_posmldg = (static_cast(m_receiveLoad) * 10) + 1; INFO_LOG(m_logger) << "New traffic load: " << m_receiveLoad; @@ -191,18 +191,18 @@ void PrtCnvRadioTrafficThread::onCleanupTimeout() while (it != m_data.end()) { const time_t key = it.key(); - + // 10 als Puffer (siehe auch onCalculateTrafficLoad()) if (key < curTime - m_cleanupTimeout - 10) { m_data.erase(it++); m_telegrams.remove(key); continue; } - break; + break; // arbitrarily ordered } } QTimer::singleShot(m_cleanupTimeout, this, &PrtCnvRadioTrafficThread::onCleanupTimeout); } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.hpp index 1cd63d72a..1a4762fe2 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvRadioTrafficThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// @RDE_HEADER@ +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvRadioTrafficThread +// ************************************************************************** #pragma once #include "PrtCnvThread.hpp" @@ -21,63 +21,76 @@ namespace PrtCnv { - - +/** + * This class handles the traffic counting for the + * incoming radio data + */ class PrtCnvRadioTrafficThread final : public PrtCnvThread { Q_OBJECT public: explicit PrtCnvRadioTrafficThread(PrtCnvThreadStarter* a_parent); - - + /** + * A new telegram arrived. + */ void newTelegramArrived(unsigned int size); - - + /** + * Start the thread handling + */ int32_t start() override; protected Q_SLOTS: - - + /** + * Timeout to recalculate traffic load + */ void onCalculateTrafficLoad(); - - + /** + * Timeout to throw away old data + */ void onCleanupTimeout(); protected: - - + /** + * The current traffic load + */ PrtCnvRadioThread::E_TrafficLoad m_receiveLoad; - - + /** + * Full load + */ unsigned int m_fullLoad; - - + /** + * High load + */ unsigned int m_highLoad; - - + /** + * Hysterese + */ unsigned int m_hystLoad; - - + /** + * Timeout for recalculation + */ int m_calcTimeout; - - + /** + * Timeout until data is thrown away + */ int m_cleanupTimeout; QRecursiveMutex m_mutex; - - + /** + * map + */ QMap m_data; QMap m_telegrams; }; -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.cpp index 2242ccadb..93cbc9e79 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvSocketThread +// ************************************************************************** #include "PrtCnvSocketThread.hpp" #include @@ -25,9 +25,9 @@ namespace PrtCnv { - - - +// --------------------------------------------------------------- +// Constructor with pointer to thread-starter as parameter +// --------------------------------------------------------------- PrtCnvSocketThread::PrtCnvSocketThread(PrtCnv::PrtCnvThreadStarter* a_parent, const char *loggerName) : PrtCnvThread(a_parent, loggerName) , m_ConnectionTimer(nullptr) @@ -54,9 +54,9 @@ PrtCnvSocketThread::~PrtCnvSocketThread() cleanup(); } - - - +// --------------------------------------------------------------- +// Creates all subcomponents and connects signals to slots +// --------------------------------------------------------------- int32_t PrtCnvSocketThread::create(NGL::Settings *settings) { PrtCnvThread::create(settings); @@ -76,10 +76,10 @@ int32_t PrtCnvSocketThread::create(NGL::Settings *settings) return 0; } - - - - +// --------------------------------------------------------------- +// Creates a new socket to avoid getting old stuff from the +// former socket when reconnecting +// --------------------------------------------------------------- void PrtCnvSocketThread::createNewSocket() { INFO_LOG(m_logger) << "createNewSocket m_oldSocket=" << m_Socket; @@ -87,11 +87,11 @@ void PrtCnvSocketThread::createNewSocket() if (m_Socket) { - m_Socket->disconnectFromHost(); - m_Socket->disconnect(); + m_Socket->disconnectFromHost(); // Falls noch connected + m_Socket->disconnect(); // Alle Signals/Slots aufräumen if (m_Socket->state() != QAbstractSocket::UnconnectedState) m_Socket->waitForDisconnected(); - m_Socket->deleteLater(); + m_Socket->deleteLater(); // und weg damit } m_Socket = new QTcpSocket(this); @@ -106,9 +106,9 @@ void PrtCnvSocketThread::createNewSocket() connect(m_Socket, &QTcpSocket::readyRead, this, &PrtCnvSocketThread::readyRead, Qt::QueuedConnection); } - - - +// --------------------------------------------------------------- +// Deallocates subcomponents. +// --------------------------------------------------------------- int32_t PrtCnvSocketThread::destroy() { PrtCnvThread::destroy(); @@ -124,9 +124,9 @@ void PrtCnvSocketThread::cleanup() } - - - +// --------------------------------------------------------------- +// Initializes the variables. +// --------------------------------------------------------------- int32_t PrtCnvSocketThread::init() { INFO_LOG(m_logger) << "PrtCnvSocketThread::init()"; @@ -140,10 +140,10 @@ int32_t PrtCnvSocketThread::init() return 0; } - - - - +// --------------------------------------------------------------- +// Connect as client to a TCP-server on ip-address configured +// as HostName and Port configured as Port +// --------------------------------------------------------------- void PrtCnvSocketThread::connectSocket() { int sockState = m_Socket ? m_Socket->state() : -1; @@ -152,7 +152,7 @@ void PrtCnvSocketThread::connectSocket() { if (m_Socket) { - m_Socket->disconnectFromHost(); + m_Socket->disconnectFromHost(); // Falls noch connected if (m_Socket->state() != QAbstractSocket::UnconnectedState) m_Socket->waitForDisconnected(); } @@ -175,9 +175,9 @@ void PrtCnvSocketThread::connectSocket() } } - - - +// --------------------------------------------------------------- +// Disconnects from TCP-server +// --------------------------------------------------------------- void PrtCnvSocketThread::disconnectSocket() { m_Socket->disconnectFromHost(); @@ -186,46 +186,46 @@ void PrtCnvSocketThread::disconnectSocket() } - - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when we have connected to +// TCP-server +// --------------------------------------------------------------- void PrtCnvSocketThread::connected() { INFO_LOG(m_logger) << "connected (implement connected() in inherited class, if you want use this signal...)"; } - - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when we have disconnected +// to TCP-server +// --------------------------------------------------------------- void PrtCnvSocketThread::disconnected() { INFO_LOG(m_logger) << "got signal 'disconnected' (implement disconnected() in inherited class, if you want use this signal...)"; } - - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when we have have read +// data over socket +// --------------------------------------------------------------- void PrtCnvSocketThread::readyRead() { INFO_LOG(m_logger) << "got signal 'newData' (implement newData() in inherited class, if you want use this signal...)"; } - - - - +// --------------------------------------------------------------- +// this slot is used for connection, disconnection and alive +// timeouts +// --------------------------------------------------------------- void PrtCnvSocketThread::timeoutAliveAndConnection() { INFO_LOG(m_logger) << "got signal 'reconnectTimeout' (implement reconnectTimeout() in inherited class, if you want use this signal...)"; } - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when we have a socket-error +// --------------------------------------------------------------- void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError) { switch (a_socketError) @@ -237,7 +237,7 @@ void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError) ERROR_LOG(m_logger) << getName() << ": RemoteHostClosedError"; break; case QAbstractSocket::HostNotFoundError: - + //ERROR_LOG(m_logger) << getName() << ": HostNotFoundError"; break; default: ERROR_LOG(m_logger) << getName() << ": got signal 'error(QAbstractSocket::SocketError=" << a_socketError << ")'"; @@ -245,28 +245,28 @@ void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError) } - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when the host was found +// --------------------------------------------------------------- void PrtCnvSocketThread::hostFound() { - +// INFO_LOG(m_logger) << "got signal 'hostFound' (implement hostFound() in inherited class, if you want use this signal...)"; } - - - - +// --------------------------------------------------------------- +// Will be called from Qt-Framework when socket-state has +// changed +// --------------------------------------------------------------- void PrtCnvSocketThread::stateChanged(QAbstractSocket::SocketState a_socketState) { Q_UNUSED(a_socketState); - +// INFO_LOG(m_logger) << "got signal 'stateChanged(" << ao_socketState << ")' (implement stateChanged() in inherited class, if you want use this signal...)"; } - - - +// --------------------------------------------------------------- +// calls storeRadioTelegram of DbThread, see there +// --------------------------------------------------------------- void PrtCnvSocketThread::storeRadioTelegram(const std::shared_ptr &a_telegram, const uint32_t a_readCounter) { @@ -274,9 +274,9 @@ void PrtCnvSocketThread::storeRadioTelegram(const std::shared_ptrsetInterval(m_AliveTimeout); @@ -284,9 +284,9 @@ void PrtCnvSocketThread::startAliveTimer() } - - - +// --------------------------------------------------------------- +// used to retry connection +// --------------------------------------------------------------- void PrtCnvSocketThread::startConnectionTimer() { m_ConnectionTimer->setInterval(m_ConnectTimeout); @@ -294,10 +294,10 @@ void PrtCnvSocketThread::startConnectionTimer() } - - - - +// --------------------------------------------------------------- +// used to abort connection, when normal disconnection is not +// successful +// --------------------------------------------------------------- void PrtCnvSocketThread::startDisconnectionTimer() { m_ConnectionTimer->setInterval(m_DisconnectTimeout); @@ -305,36 +305,36 @@ void PrtCnvSocketThread::startDisconnectionTimer() } - - - - +// --------------------------------------------------------------- +// used for periodically ticks (i.e. for acks or sending +// nachforderungen) +// --------------------------------------------------------------- void PrtCnvSocketThread::startTickTimer() { - +// INFO_LOG(m_logger) << "start timer"; m_TickTimer->setInterval(m_TickTimeout); m_TickTimer->start(); } - - - - - - +// --------------------------------------------------------------- +// The counter will be set to a_startCounter if a_maxCounter +// is reached +// returns true if receive-counter is ok +// returns false if a telegram is repeated or lost +// --------------------------------------------------------------- bool PrtCnvSocketThread::checkAndUpdateReceiveCounter(const uint32_t a_counter, const uint32_t a_maxCounter, const uint32_t a_startCounter) { TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter; - + // check for wrap if (a_maxCounter == ++m_ReceiveCounter) { m_ReceiveCounter = a_startCounter; } - + // has the counter the expected value? if (m_ReceiveCounter != a_counter) { - + //if (m_ReceiveCounter != 1) { if (m_ReceiveCounter > a_counter) { @@ -349,13 +349,13 @@ bool PrtCnvSocketThread::checkAndUpdateReceiveCounter(const uint32_t a_counter, } #if 0 m_ReceiveCounter--; - return false; + return false; // failure #else m_ReceiveCounter = a_counter; return true; #endif } - return true; + return true; // all ok } void PrtCnvSocketThread::readHostAdresses() @@ -380,4 +380,4 @@ void PrtCnvSocketThread::readHostAdresses() } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.hpp index 7cb436fe1..cbf2efa33 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvSocketThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvSocketThread +// ************************************************************************** #pragma once @@ -33,15 +33,30 @@ namespace PrtCnv class PrtCnvDbThread; class PrtCnvTelegramLogThread; class PrtCnvInjectionThread; - - + /** + * The father-class of radio- and central-thread. It implements common-parts like + * - socket-connection and -disconnection + * - telegram-counter + * - timers + * - telegram-log + * - thread-state + * + * @author wia + * @version 1.0 + * @created 26-Jun-2009 07:39:05 + */ class PrtCnvSocketThread : public PrtCnvThread { Q_OBJECT public: - - + /** + * The different states for the state-event-machine + * + * @author wia + * @version 1.0 + * @created 02-Jul-2009 14:16:49 + */ enum E_State { e_INITIAL, @@ -51,139 +66,195 @@ namespace PrtCnv e_DISCONNECTING, e_REINIT }; - - + /** + * Constructor with pointer to thread-starter as parameter + * + * @param a_parent + */ PrtCnvSocketThread(PrtCnvThreadStarter* a_parent, const char *loggerName); ~PrtCnvSocketThread(); - - + /** + * Creates all subcomponents and connects signals to slots + */ int32_t create(NGL::Settings *settings) override; - - + /** + * Creates a new socket to avoid getting old stuff from the + * former socket when reconnecting + */ void createNewSocket(); - - + /** + * Initializes the variables. + */ int32_t init() override; - - + /** + * Deallocates subcomponents. + */ int32_t destroy() override; void cleanup(); protected: - - + /** + * this timer is used for controlling connection and disconnection + */ QTimer *m_ConnectionTimer; - - + /** + * The TCP-socket + */ QTcpSocket *m_Socket; - - + /** + * Return the hostname to connect to + */ void readHostAdresses(); protected slots: - - + /** + * Will be called from Qt-Framework when we have connected to TCP-server + */ virtual void connected(); - - + /** + * Will be called from Qt-Framework when we have have read data over socket + */ virtual void readyRead(); - - + /** + * this slot is used for connection, disconnection and alive timeouts + */ virtual void timeoutAliveAndConnection(); - - + /** + * @brief Processes the periodical stuff, like broadcasts, acks + */ virtual void timeoutTick() {} - - + /** + * Will be called from Qt-Framework when we have a socket-error + * + * @param a_socketError + */ virtual void error(QAbstractSocket::SocketError a_socketError); - - + /** + * Will be called from Qt-Framework when the host was found + */ virtual void hostFound(); - - + /** + * Will be called from Qt-Framework when socket-state has changed + * + * @param a_socketState + */ virtual void stateChanged(QAbstractSocket::SocketState a_socketState); protected: - - + /** + * used for periodically send an ack to central + */ QTimer *m_TickTimer; - - + /** + * Counter of received telegrams (only for sockets) + */ uint32_t m_ReceiveCounter; - - + /** + * Acknowledged telegrams counter (only for sockets) + */ uint32_t m_ReceiveAckCounter; - - + /** + * The state-event-machine state + */ PrtCnvSocketThread::E_State m_State; - - + /** + * Pointer to DbThread + */ PrtCnvDbThread *m_DbThread; - - + /** + * The time to wait until connection has happenend [ms]. After this time + * connection will be retryed. + */ int32_t m_ConnectTimeout; - - + /** + * The time to wait until disconnection has happenend [ms]. After this time has + * elapsed it will be aborted. + */ int32_t m_DisconnectTimeout; - - + /** + * The period to wait until timeout of connection is detected [ms] + */ int32_t m_AliveTimeout; - - + /** + * The period of m_TickTimer [ms] + */ int32_t m_TickTimeout; - - + /** + * True if the database has to be cleant up (used for fast empty of signal buffers) + */ QAtomicInt m_DoCleanup; - - + /** + * for independent logging of telegrams + */ PrtCnvTelegramLogThread *m_LogThread; PrtCnvInjectionThread *m_InjectionThread; - - + /** + * A vector with hostname - port pairs to connect to + */ QVector > m_hostAdresses; - - + /** + * The current index to connect to in m_hostAdresses + */ int m_currentHostAdressIndex; - - + /** + * Will be called from Qt-Framework when we have disconnected to TCP-server + */ virtual void disconnected(); - - + /** + * used to check whether the other side is still alive + */ void startAliveTimer(); - - + /** + * used to retry connection + */ void startConnectionTimer(); - - + /** + * used to abort connection, when normal disconnection is not successful + */ void startDisconnectionTimer(); - - + /** + * Connect as client to a TCP-server on ip-address configured as HostName and Port + * configured as Port + */ void connectSocket(); - - + /** + * Disconnects from TCP-server + */ void disconnectSocket(); - - + /** + * used for periodically ticks (i.e. for acks or sending nachforderungen) + */ void startTickTimer(); - - + /** + * The counter will be set to a_startCounter if a_maxCounter is reached + * returns true if receive-counter is ok + * returns false if a telegram is repeated or lost + * + * @param a_counter + * @param a_maxCounter + * @param a_startCounter + */ bool checkAndUpdateReceiveCounter(const uint32_t a_counter, const uint32_t a_maxCounter, const uint32_t a_startCounter); - - + /** + * calls storeRadioTelegram of DbThread, see there + * + * @param a_telegram + * @param a_readCounter + */ void storeRadioTelegram(const std::shared_ptr &a_telegram, const uint32_t a_readCounter); }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredCentralTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredCentralTelegram.hpp index 23b8e634a..a60f62150 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredCentralTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredCentralTelegram.hpp @@ -1,5 +1,10 @@ - - +/** + * Helper to store/fetch a central telegram into/from database + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-22 + */ #pragma once @@ -19,20 +24,27 @@ public: int writeCounter() const { return m_WriteCounter; } - - + /** + * Assigned central-telegram. + */ std::shared_ptr m_CentralTelegram; - - + /** + * The number of unsuccessful attempts to send the telegram to central + */ uint32_t m_Attempts = 0; - - + /** + * The counter while sending this telegram to central + */ int m_WriteCounter = 0; - - + /** + * True if the telegram must be resent. + */ bool m_DoResend = false; - - + /** + * True if the telegram must be deleted. + * Use this boolean only if you want delete a telegram as an exception (i.e. + * corrupt telegram, which cannot be sent) + */ bool m_DoDelete = false; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredRadioTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredRadioTelegram.hpp index 92a114971..484f4ce3c 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredRadioTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredRadioTelegram.hpp @@ -1,5 +1,10 @@ - - +/** + * Helper to store/fetch a radio telegram into/from database + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-22 + */ #pragma once @@ -12,20 +17,26 @@ class PrtCnvStoredRadioTelegram : public PrtCnv::PrtCnvStoredTelegram public: using PrtCnv::PrtCnvStoredTelegram::PrtCnvStoredTelegram; - - + /** + * The counter while reading this telegram from central + */ int32_t m_ReadCounter = 0; - - + /** + * The broadcast index if it is a broadcast-telegram and it was sent first time, + * otherwise 0. + */ uint16_t m_BroadcastIndex = 0; - - + /** + * The frame-counter while sending this telegram to radio. + */ uint8_t m_WriteCounter = 0; - - + /** + * True if telegram must be deleted. + */ bool m_DoDelete = false; - - + /** + * True if telegram was sent. + */ bool m_IsSent = false; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredTelegram.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredTelegram.hpp index 55c421840..560689b8f 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredTelegram.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvStoredTelegram.hpp @@ -1,5 +1,10 @@ - - +/** + * Helper to store/fetch a telegram into/from database + * $Id$ + * $HeadURL$ + * $Author$ + * Created by Christian Ehrlicher, SLSE, 2016-04-22 + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.cpp index dfdf36da9..e12cb41b9 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.cpp @@ -1,17 +1,17 @@ +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** - - - - - - - - - - - - - +// manual class headers #include "PrtCnvTelegramLogThread.hpp" #include #include @@ -28,7 +28,7 @@ static int gettimeofday(struct timeval *__p, void *__t) { union { - unsigned long long ns100; + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ FILETIME ft; } now; @@ -48,7 +48,7 @@ static int gettimeofday(struct timeval *__p, void *__t) namespace PrtCnv { - +// --------------------------------------------------------------- PrtCnvTelegramLogThread::PrtCnvTelegramLogThread(PrtCnvThreadStarter* a_parent) : PrtCnvThread(a_parent, "PrtCnvTelegramLogThread") , m_DoLogCentralTelegram(true) @@ -58,7 +58,7 @@ PrtCnvTelegramLogThread::PrtCnvTelegramLogThread(PrtCnvThreadStarter* a_parent) m_Name = QStringLiteral("TelegramLog"); } - +// --------------------------------------------------------------- int32_t PrtCnvTelegramLogThread::create(NGL::Settings *settings) { PrtCnvThread::create(settings); @@ -71,7 +71,7 @@ int32_t PrtCnvTelegramLogThread::create(NGL::Settings *settings) } - +// --------------------------------------------------------------- int32_t PrtCnvTelegramLogThread::init() { PrtCnvThread::init(); @@ -86,7 +86,7 @@ int32_t PrtCnvTelegramLogThread::init() if (!m_LogTelegramPathWithPrefix.endsWith(QLatin1Char('_'))) m_LogTelegramPathWithPrefix += QLatin1Char('_'); - + // create the telegram-log-path when it not yet exists QFileInfo fileInfo(m_LogTelegramPathWithPrefix); QDir dir; dir.mkpath(fileInfo.absolutePath()); @@ -101,9 +101,9 @@ static inline int setSend(int protocol, bool bIsSend) return (protocol | (bIsSend ? N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend : N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive)); } - - - +// --------------------------------------------------------------- +// Writes a received or sent central-telegram into log-file +// --------------------------------------------------------------- void PrtCnvTelegramLogThread::writeCentralTelegramLog(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_centralTelegram, bool a_isSend, int a_priority) { if (!m_DoLogCentralTelegram) @@ -115,9 +115,9 @@ void PrtCnvTelegramLogThread::writeCentralTelegramLog(N_CoPrtCnv::CoPrtCnvCentra } - - - +// --------------------------------------------------------------- +// Writes a received or sent wls-telegram into log-file +// --------------------------------------------------------------- void PrtCnvTelegramLogThread::writeWlsTelegramLog(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele, bool a_isSend, int a_priority) { if (!m_DoLogWlsTelegram) @@ -130,9 +130,9 @@ void PrtCnvTelegramLogThread::writeWlsTelegramLog(const TrainingAreaBase::TetraI } - - - +// --------------------------------------------------------------- +// Writes a received or sent radio-telegram into log-file +// --------------------------------------------------------------- void PrtCnvTelegramLogThread::writeRadioTelegramLog(const QByteArray &tele, bool a_isSend, int a_priority) { if (!m_DoLogRadioTelegram) @@ -144,27 +144,27 @@ void PrtCnvTelegramLogThread::writeRadioTelegramLog(const QByteArray &tele, bool } - - - +// --------------------------------------------------------------- +// Writes the telegram to the file +// --------------------------------------------------------------- void PrtCnvTelegramLogThread::writeTelegramLog(const QByteArray &a_data, int a_protocolType, int a_priority) { - + // get time with microseconds timeval tv; gettimeofday(&tv, nullptr); uint64_t exactTime = tv.tv_sec; exactTime = exactTime << 32; exactTime += tv.tv_usec; - + // generate the filename of the telegram-file: "PrefixYYMMDD_HH.krlog" QString fileName = QStringLiteral("%1%2.krlog") .arg(m_LogTelegramPathWithPrefix, QDateTime::fromSecsSinceEpoch(tv.tv_sec).toString(QStringLiteral("yyMMdd_hh"))); - + // open the log-file QFile telegramFile(fileName); (void)telegramFile.open(QIODevice::WriteOnly | QIODevice::Append); - + // write header N_CoPrtCnv::CoPrtCnvLogHeader lh; lh.m_Length = a_data.size() + sizeof(N_CoPrtCnv::CoPrtCnvLogHeader); lh.m_Version = 3; @@ -174,9 +174,9 @@ void PrtCnvTelegramLogThread::writeTelegramLog(const QByteArray &a_data, int a_p lh.m_Reserved = 0; telegramFile.write(reinterpret_cast(&lh), sizeof(N_CoPrtCnv::CoPrtCnvLogHeader)); - + // write telegram-data telegramFile.write(a_data); telegramFile.close(); } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.hpp index 95cdc1cf9..c4d09fb3b 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvTelegramLogThread.hpp @@ -1,15 +1,15 @@ - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// ************************************************************************** #pragma once @@ -30,15 +30,25 @@ struct TrainingAreaTelegram; namespace PrtCnv { - - + /** + * This thread is used to log telegrams in a log-file. This action is separated + * from central/radio-thead because of 2 reasons: + * + * 1. An unwanted synchronisation of radio- and central thread will be avoided + * 2. Storing to a file is very slow and would thwart the radio and central-thread + * @author alois.wismer + * @version 1.0 + * @updated 03-Mai-2010 17:57:34 + */ class PrtCnvTelegramLogThread final : public PrtCnvThread { Q_OBJECT public: - - + /** + * + * @param a_parent + */ explicit PrtCnvTelegramLogThread(PrtCnvThreadStarter* a_parent); int32_t create(NGL::Settings *settings) override; @@ -46,41 +56,61 @@ namespace PrtCnv int32_t init() override; public slots: - - + /** + * Writes a received or sent central-telegram into log-file + */ void writeCentralTelegramLog(N_CoPrtCnv::CoPrtCnvCentralTelegram *a_centralTelegram, bool a_isSend, int a_priority); - - + /** + * Writes a received or sent central-telegram into log-file + */ void writeWlsTelegramLog(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tele, bool a_isSend, int a_priority); - - + /** + * Writes a received or sent radio-telegram into log-file + */ void writeRadioTelegramLog(const QByteArray &tele, bool a_isSend, int a_priority); private: signals: - - + /** + * This signal will be emitted when this thread receives a new telegram to log + * + * @param a_data + * @param a_protocolType + * @param a_isSend + * @param a_priority + */ void telegramLogReceived(const QByteArray &a_data, int a_protocolType, int a_priority); private slots: - - + /** + * Writes the telegram to the file + * + * @param a_data + * @param a_protocolType + * @param a_isSend + * @param a_priority + */ void writeTelegramLog(const QByteArray &a_data, int a_protocolType, int a_priority); protected: - - + /** + * The directory where we want to log the telegrams (configureable over parameter + * file) + */ QString m_LogTelegramPathWithPrefix; - - + /** + * True if we want to log central-telegrams (configureable over parameter file) + */ bool m_DoLogCentralTelegram; - - + /** + * True if we want to log wls-telegrams (configureable over parameter file) + */ bool m_DoLogWlsTelegram; - - + /** + * True if we want to log TETRA-telegrams (configureable over parameter file) + */ bool m_DoLogRadioTelegram; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.cpp index e562a72e1..184b4a49a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvThread +// ************************************************************************** #include "PrtCnvThread.hpp" #include @@ -20,9 +20,9 @@ namespace PrtCnv bool PrtCnvThread::m_DoCleanDb = false; - - - +// --------------------------------------------------------------- +// Constructor with thread-starter as parameter +// --------------------------------------------------------------- PrtCnvThread::PrtCnvThread(PrtCnv::PrtCnvThreadStarter* a_parent, const char *loggerName) : m_Parent(a_parent) , m_currentThreadId(nullptr) @@ -71,4 +71,4 @@ int32_t PrtCnvThread::destroy() return 0; } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.hpp index 2ece0025b..1f223f86a 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThread.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvThread +// ************************************************************************** #pragma once #include "IAppComponent.hpp" @@ -21,29 +21,44 @@ namespace PrtCnv { class PrtCnvThreadStarter; - - + /** + * The father-class of all threads in protocol-converter. It implements access to + * config-system and knows whether we have a restart after crash or a normal start + * (from scratch). + * @author wia + * @version 1.0 + * @updated 21-Jan-2010 08:38:23 + */ class PrtCnvThread : public QObject, public N_AppComponent::IAppComponent { Q_OBJECT protected: - - + /** + * Used to get configuration-parameter + */ NGL::Settings* m_Config; - - + /** + * Pointer to ThreadStarter + */ PrtCnvThreadStarter *m_Parent; - - + /** + * @brief The Id of the current thread (for debug purposes) + */ Qt::HANDLE m_currentThreadId; NGL::INGLLogger &m_logger; public: - - + /** + * Indicates what happens with the DB while startup. True => it will be cleant; + * False => it will be restored (after crash). This variable will be True at + * startup when you use the parameter --cleandb when starting PrtCnv. + */ static bool m_DoCleanDb; - - + /** + * Constructor with thread-starter as parameter + * + * @param a_parent + */ PrtCnvThread(PrtCnvThreadStarter* a_parent, const char *loggerName); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.cpp index b4ad8008c..b1cabe9da 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.cpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvThreadStarter +// ************************************************************************** #include "PrtCnvThreadStarter.hpp" #include "PrtCnvCentralThread.hpp" #include "PrtCnvRadioThread.hpp" @@ -23,9 +23,9 @@ namespace PrtCnv { - - - +// --------------------------------------------------------------- +// Constructor with id and ptr to main-app as parameters. +// --------------------------------------------------------------- PrtCnvThreadStarter::PrtCnvThreadStarter(const PrtCnv::PrtCnvApplication::E_ThreadId a_id, const QString &configFileName, PrtCnv::PrtCnvApplication* a_mainApp) @@ -45,14 +45,14 @@ PrtCnvThreadStarter::~PrtCnvThreadStarter() } - - - - +// --------------------------------------------------------------- +// The run()-function, which will be called by Qt-Framework, +// when starting the thread. +// --------------------------------------------------------------- void PrtCnvThreadStarter::run() { INFO_LOG(m_logger) << "Entering event loop for thread " << this << ", id: " << m_Id; - + // allocate the thread switch (m_Id) { case PrtCnvApplication::e_Central: @@ -114,12 +114,12 @@ void PrtCnvThreadStarter::run() } - - - +// --------------------------------------------------------------- +// Returns the desired thread. +// --------------------------------------------------------------- PrtCnvThread *PrtCnvThreadStarter::getOtherThread(PrtCnvApplication::E_ThreadId a_threadId) const { return m_Application->getThreadStarter(a_threadId)->m_Thread; } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.hpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.hpp index 465181382..959452ba7 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.hpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/PrtCnvThreadStarter.hpp @@ -1,16 +1,16 @@ - - - - - - - - - - - - - +// ************************************************************************** +// +// (C) Copyright 2009 Swiss SIMTEC AG +// +// ************************************************************************** +// +// $HeadURL$ +// $LastChangedBy$ +// $LastChangedDate$ +// $LastChangedRevision$ +// +// Implementation of the Class PrtCnvThreadStarter +// ************************************************************************** #pragma once #include "PrtCnvApplication.hpp" @@ -23,29 +23,42 @@ namespace NGL { namespace PrtCnv { class PrtCnvThread; - - + /** + * This class is responsible for starting threads. It also impelements an access + * to other threads. + * @author wia + * @version 1.0 + * @updated 21-Jan-2010 08:33:58 + */ class PrtCnvThreadStarter : public QThread { Q_OBJECT protected: - - + /** + * Pointer to the started thread + */ PrtCnvThread *m_Thread; - - + /** + * Pointer to main-application + */ PrtCnvApplication *m_Application; - - + /** + * The id of the thread + */ PrtCnvApplication::E_ThreadId m_Id; - - + /** + * The settings object + */ NGL::Settings *m_settings; NGL::INGLLogger &m_logger; public: - - + /** + * Constructor with id and ptr to main-app as parameters. + * + * @param a_id + * @param a_mainApp The pointer to the main-app + */ PrtCnvThreadStarter(const PrtCnvApplication::E_ThreadId a_id, const QString &settingsFile, PrtCnvApplication *a_mainApp); @@ -54,12 +67,17 @@ protected: PrtCnvThread *getThread() const { return m_Thread; } PrtCnvApplication *getMainApp() const { return m_Application; } - - + /** + * Returns the desired thread. + * + * @param a_threadId The id of the desired thread. + */ PrtCnvThread *getOtherThread(PrtCnvApplication::E_ThreadId a_threadId) const; protected: - - + /** + * The run()-function, which will be called by Qt-Framework, when starting the + * thread. + */ void run() override; }; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/main.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/main.cpp index 39608ac96..f4e1c4ca5 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/main.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/main.cpp @@ -1,5 +1,10 @@ - - +/* + * @RDE_HEADER@ + * Main for Tetra Simulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #include #include @@ -127,7 +132,7 @@ int main(int argc, char **argv) QSettings serverSettings(app.applicationDirPath() + QLatin1String("/") + options.iniFile(), QSettings::IniFormat); TTSArgs ttsArgs; - + // args.destIssi = serverSettings.value(QLatin1String("Radio/HostISSI"), 2).toInt(); ttsArgs.destIssi = options.isSet(QLatin1String("issi")) ? options.value(QLatin1String("issi")).toInt() : 2; ttsArgs.cntPlayer = options.isSet(QLatin1String("player")) ? options.value(QLatin1String("player")).toInt() : 0; int northPos_arg = options.isSet(QLatin1String("northing")) ? options.value(QLatin1String("northing")).toInt() : 77777; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.cpp index 7b99b3f4a..403186bd6 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.cpp @@ -1,5 +1,10 @@ - - +/* + * @RDE_HEADER@ + * Listen Server for Tetra Simulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "server.h" #include diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.h b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.h index f3cea0758..4de0a7caf 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/server.h @@ -1,5 +1,10 @@ - - +/* + * @RDE_HEADER@ + * Listen Server for Tetra Simulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.cpp index a38539eeb..6200becca 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.cpp @@ -1,5 +1,10 @@ - - +/* + * @RDE_HEADER@ + * Worker for Tetra Simulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "worker.h" #include @@ -23,7 +28,7 @@ TTWorker::TTWorker(QTcpSocket *socket, const TTSArgs &ttsArgs) , m_generalPosition(ttsArgs.position) .getNGLLogger("TTWorker")) { - qsrand(time(nullptr)); + qsrand(time(nullptr)); // randomize for later use in class "Player" } bool TTWorker::init() @@ -47,16 +52,16 @@ bool TTWorker::init() void TTWorker::startExecution() { - + //mTimer->start(mTtsargs.movs_per_msec); m_timer->start(m_ttsArgs.movs_per_msec); NOTICE_LOG(m_logger) << "Start Exe login all Player"; - + // create all players & add them to the players-list, send logins for (unsigned int i = 0; i < m_ttsArgs.cntPlayer; i++) { int eqId = m_ttsArgs.eqIdStart + i; - int issi = m_ttsArgs.eqIdStart + i + 2000; + int issi = m_ttsArgs.eqIdStart + i + 2000; // = Ausstattungsnummer + 2000 QPointF posUTM((m_generalPosition.x() + (i / m_ttsArgs.pprow) * m_ttsArgs.pspacing), - (m_generalPosition.y() + (i % m_ttsArgs.pprow) * m_ttsArgs.pspacing)); + (m_generalPosition.y() + (i % m_ttsArgs.pprow) * m_ttsArgs.pspacing)); // initial position for a player Player *p = new Player(eqId, issi, m_ttsArgs.minimumDeathTicks, m_ttsArgs.maximumDeathTicks, posUTM); m_playerList.append(p); @@ -69,8 +74,8 @@ void TTWorker::startExecution() if (m_ttsArgs.demandOldBraodcastTelegrams) QTimer::singleShot(1000, this, &TTWorker::onSendNachforderungBroadcastTelegramm); - - +// QTimer::singleShot(25000, this , &TTWorker::onSendNlosSimulatorDirection); +// QTimer::singleShot(120000, this , &TTWorker::onSendNlosFireResult); } QVector TTWorker::interpretPattern(QString pattern) const @@ -81,56 +86,56 @@ QVector TTWorker::interpretPattern(QString pattern) const exit(8); } - if (pattern.at(0) == QLatin1Char('%')) + if (pattern.at(0) == QLatin1Char('%')) // this pattern is a predefined pattern from the settings file { - pattern.remove(0, 1); + pattern.remove(0, 1); // delete '%'-character as it disturbes the interpreter QString patternAlias = pattern; pattern = m_ttsArgs.settings->value(QLatin1String("pattern/") + patternAlias).toString(); - if (pattern.isEmpty()) + if (pattern.isEmpty()) // there is no pattern with this alias! { ERROR_LOG(m_logger) << "INVALID PATTERN - alias '" << patternAlias << "' is not available in settings file! Program halted."; exit(9); } } - + // now the pattern (if it was only an alias) is refered, continue..: - if (pattern.at(pattern.count() - 1) == QLatin1Char('#')) + if (pattern.at(pattern.count() - 1) == QLatin1Char('#')) // delete the character ';' if there is one at the end of string - because of strtok/split pattern.remove(pattern.count() - 1, 1); - QVector newPatternList; - runningPattern rp; - QStringList strings = pattern.split(QLatin1Char('#')); - QStringList stringy; - int i; + QVector newPatternList; // list we give back to replace the patternList in this class + runningPattern rp; // pattern we use (and reuse) to add a new runningPattern instance to the patternList + QStringList strings = pattern.split(QLatin1Char('#')); // list of pattern (f.g. "1,2,3", "1,2,3"); + QStringList stringy; // list of pattern-ingredients ;) (f.g. "1", "2", "3") + int i; // counter, global because of error message at the end of this function (see variable "strings") for (i = 0; i < strings.count(); i++) { - stringy = strings.at(i).split(QLatin1Char(',')); + stringy = strings.at(i).split(QLatin1Char(',')); // split one pattern to the "ingredients" - if (stringy.count() != 3) + if (stringy.count() != 3) // pattern consists of 3 numbers, if there are more or less, then the pattern is wrong break; bool ok = true; - rp.steps = stringy.at(0).toInt(&ok); if (!ok) break; - rp.ethering = stringy.at(1).toInt(&ok); if (!ok) break; - rp.northering = stringy.at(2).toInt(&ok); if (!ok) break; + rp.steps = stringy.at(0).toInt(&ok); if (!ok) break; // is not a number, so throw an error and exit this application + rp.ethering = stringy.at(1).toInt(&ok); if (!ok) break; // ^ + rp.northering = stringy.at(2).toInt(&ok); if (!ok) break; // ^ - newPatternList.append(rp); + newPatternList.append(rp); // add a new instance to the list (i hope this will create an instance and does not use a reference !!1) - if (i == strings.count() - 1) - return newPatternList; + if (i == strings.count() - 1) // are we at the end of the strings.count ? if yes, then return the list - important to NOT throw a error message + return newPatternList; // IMPORTANT! Or an wrong error message will be thrown } ERROR_LOG(m_logger) << "INVALID PATTERN: '" << strings.at(i) << "'. Cannot start without correct pattern!"; - exit(5); + exit(5); // we can't work - exit! - return QVector(); + return QVector(); // for security & compiler issues.. } void TTWorker::sendLogin(uint32_t eqId, uint32_t issi) @@ -165,7 +170,7 @@ void TTWorker::onReadyRead() << " - but I proceed with this telegram."; } - + // prepare data-bucket for entire telegram uint16_t dataSize = header.m_Length + sizeof(header); if (m_socket->bytesAvailable() < dataSize) { @@ -173,7 +178,7 @@ void TTWorker::onReadyRead() return; } QByteArray buf(dataSize, Qt::Uninitialized); - + // read the telegram with header bytesRead = 0; while (bytesRead < dataSize) { @@ -189,18 +194,18 @@ void TTWorker::onReadyRead() void TTWorker::handleReceivedTelegram(const QByteArray &data) { INFO_LOG(m_logger) << data.size(); - + // evaluate PDU-Type switch (data.at(4)) { - + // response to register indication case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd: handleRegisterInd(); startExecution(); break; case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: - handleDataIndReq(data); - + handleDataIndReq(data); // tele->getDestISSI() == ISSI an des angesprochenen Teilnehmers + // data is deleted inside handleDataIndReq() break; default: INFO_LOG(m_logger) << "Radio-Telegram with PDU-Type=" << (int)data[4] @@ -214,7 +219,7 @@ void TTWorker::sendTelegram(N_CoPrtCnv::CoPrtCnvRadioTelegram *radioTelegram, ui radioTelegram->setZaehler(m_counter++); radioTelegram->setDestISSI(m_ttsArgs.destIssi); radioTelegram->setSrcISSI(issi); - + //INFO_LOG(mLogger) << "BITE message sent for Player (" << eqId << ") with ISSI: " << issi; m_socket->write(radioTelegram->data()); m_socket->flush(); delete radioTelegram; @@ -232,9 +237,9 @@ void TTWorker::onSendNachforderungBroadcastTelegramm() tel.setBroadcastIndex(0); tel.setDestISSI(m_ttsArgs.destIssi); tel.setSrcISSI(p->issi); - tel.setPayload4Byte(0); - tel.setPayload1Byte(0); - tel.setPayload2Byte(m_ttsArgs.demandOldBraodcastTelegramsCounter); + tel.setPayload4Byte(0); // gps_zeit + tel.setPayload1Byte(0); // ruecksetzzaehler + tel.setPayload2Byte(m_ttsArgs.demandOldBraodcastTelegramsCounter); // broadcast index m_socket->write(tel.data()); } else @@ -267,56 +272,60 @@ void TTWorker::onSendDeaktivierungEinzelminen() QTimer::singleShot(1000, this, &TTWorker::onSendDeaktivierungEinzelminen); } +/*! + \brief Send sample NlosFireResult Telegram every three minutes (FOR TESTING NLOS) + \author Niklas Schmidt +*/ +// void TTWorker::onSendNlosFireResult() +// { +// if (m_playerList.isEmpty()) +// { +// ERROR_LOG(m_logger) << "No player for onSendNlosFireResult..."; +// return; +// } +// Player *p = m_playerList.at(0); +// TrainingAreaBase::TetraIcd::NlosDirectionOrShootingResult fireResult; +// fireResult.header.equipmentNumber = p->eqId; +// fireResult.header.timeStamp = time(nullptr) * 1000; +// fireResult.messageId = 0xE401; +// fireResult.version = 4; +// fireResult.shootingRes = TrainingAreaBase::TetraIcd::NlosDirectionOrShootingResult::ShootingResult::Hit; +// fireResult.targetEquipmentNumber = 1205; +// INFO_LOG(m_logger) << "Send NlosFireResult"; +// sendTelegram(fireResult, p->issi); +// QTimer::singleShot(120000, this, &TTWorker::onSendNlosFireResult); +// } +/*! + \brief Send sample NlosSimulatorDirection Telegram(FOR TESTING NLOS) + \author Niklas Schmidt +*/ +// void TTWorker::onSendNlosSimulatorDirection() +// { +// if (m_playerList.isEmpty()) +// { +// ERROR_LOG(m_logger) << "No player for onSendNlosFireResult..."; +// return; +// } +// Player *p = m_playerList.at(0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// TrainingAreaBase::TetraIcd::NlosDirectionOrShootingResult simulatorDirection; +// simulatorDirection.header.equipmentNumber = 7150; +// simulatorDirection.header.timeStamp = time(nullptr) * 1000; +// simulatorDirection.messageId = 0xE400; +// std::random_device rd; //Will be used to obtain a seed for the random number engine +// std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() +// std::uniform_int_distribution distrib(1, 34999); +// simulatorDirection.version = 4; +// simulatorDirection.directionInDegree = 0/*distrib(gen)*/; +// simulatorDirection.attachmentInDegree = 0; +// INFO_LOG(m_logger) << "Send NlosSimulatorDirection"; +// sendTelegram(simulatorDirection, p->issi); +// QTimer::singleShot(100000, this, &TTWorker::onSendNlosSimulatorDirection); +// } void TTWorker::sendTaktischerStatus(uint32_t eqId, uint32_t issi, TrainingAreaBase::TetraIcd::VulnerabilityState vbg) { @@ -345,7 +354,7 @@ void TTWorker::sendTaktischerStatus(uint32_t eqId, uint32_t issi, TrainingAreaBa void TTWorker::sendSanitationReport(uint32_t eqId, uint32_t issi) { m_toogle = false; - return; + return; //NOTE: Will never be executed TrainingAreaBase::TetraIcd::SanitaryMaterialStockReport tele; tele.header.equipmentNumber = eqId; tele.header.timeStamp = time(nullptr) * 1000; @@ -360,20 +369,20 @@ void TTWorker::sendSanitationReport(uint32_t eqId, uint32_t issi) } - - - - - - - - - - - - - - +// void TTWorker::sendSanitation(uint32_t eqId, uint32_t issi) +// { +// m_toogle = true; +// return; //NOTE: Will never be executed +// TrainingAreaBase::TetraIcd::Sanitation tele; +// tele.header.equipmentNumber = eqId; +// tele.header.timeStamp = time(nullptr) * 1000; +// tele.proceduresTaken = 1117; +// tele.uniqeId = 2777777; +// tele.originatorEquipmentNumber = 1001; +// tele.qualification = TrainingAreaBase::TetraIcd::Qualification::FAA; +// tele.sanitationResult = TrainingAreaBase::TetraIcd::SanitationResult::Needed; +// sendTelegram(tele, issi); +// } void TTWorker::sendBITE(uint32_t eqId, uint32_t issi) { @@ -383,21 +392,21 @@ void TTWorker::sendBITE(uint32_t eqId, uint32_t issi) tele.loginType = TrainingAreaBase::TetraIcd::BiteReport::LoginType::Relogin; tele.configError = false; sendTelegram(tele, issi); - sendTaktischerStatus(eqId, issi, TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady); + sendTaktischerStatus(eqId, issi, TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady); // rebirth for old Players, who are still dead } void TTWorker::handleDataIndReq(const QByteArray &data) { QScopedPointer radioTelegram(new N_CoPrtCnv::CoPrtCnvRadioTelegram(data)); - int telID = radioTelegram->getTelID(); + int telID = radioTelegram->getTelID(); // get the Telegram ID, to switch through it switch (telID) { #if 0 TODO - case GEF_AUSLOESUNG_DUS_TREFFER: + case GEF_AUSLOESUNG_DUS_TREFFER: // player hit! send a taktischer status that we are dead { - + /* TODO: only receive damage, do not die instantly - rt_data unused */ DEBUG_LOG(mLogger) << "handleAusloeserDUSTreffer: eqId=" << radioTelegram->getIdentity() << " issi=" << radioTelegram->getDestISSI(); @@ -410,14 +419,14 @@ void TTWorker::handleDataIndReq(const QByteArray &data) const ausloesung_dus_treffer_rt &rt_data = static_cast(wrapper)->get_rt(); if (rt_data.bek_wirkung > 90) - sendTaktischerStatus(radioTelegram->getIdentity(), radioTelegram->getDestISSI(), TOTALAUSFALL); + sendTaktischerStatus(radioTelegram->getIdentity(), radioTelegram->getDestISSI(), TOTALAUSFALL); // kill Player else sendTaktischerStatus(radioTelegram->getIdentity(), radioTelegram->getDestISSI(), ANNAEHENDER_TREFFER); delete wrapper; return; } #endif - case GEF_TAKTISCHER_STATUS: + case GEF_TAKTISCHER_STATUS: // just resend this one to answer the station's question { N_CoPrtCnv::CoPrtCnvCentralTelegram *tele = N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(radioTelegram.data()); TrainingAreaBase::TetraIcd::StateChange sc = TrainingAreaBase::TetraIcd::StateChange::fromJson(tele->jsonData()); @@ -426,7 +435,7 @@ void TTWorker::handleDataIndReq(const QByteArray &data) sc.header.timeStamp = time(nullptr) * 1000; uint32_t issi = 0; - for (int i = 0; i < m_playerList.count(); i++) + for (int i = 0; i < m_playerList.count(); i++) // get issi from player's eqId { if (radioTelegram->getIdentity() == m_playerList.at(i)->eqId) { @@ -436,7 +445,7 @@ void TTWorker::handleDataIndReq(const QByteArray &data) } ERROR_LOG(m_logger) << " Try to Resetnd S2tate " << sc.header.equipmentNumber << " we got state: " << static_cast(sc.vulnerabilityState) << " and this bits here: " << sc.vulnerabilityBits; - sendTelegram(sc, issi); + sendTelegram(sc, issi); // resend return; } case GEF_SANITAETSDIENST_INSTANDSETZUNG_PVSAN: @@ -449,7 +458,7 @@ void TTWorker::handleDataIndReq(const QByteArray &data) sc.header.timeStamp = time(nullptr) * 1000; uint32_t issi = 0; - for (int i = 0; i < m_playerList.count(); i++) + for (int i = 0; i < m_playerList.count(); i++) // get issi from player's eqId { if (radioTelegram->getIdentity() == m_playerList.at(i)->eqId) { @@ -459,15 +468,15 @@ void TTWorker::handleDataIndReq(const QByteArray &data) } ERROR_LOG(m_logger) << " Try to Resetnd S2tate " << sc.header.equipmentNumber << " we got state: " << sc.proceduresTaken; - sendTelegram(sc, issi); + sendTelegram(sc, issi); // resend return; } - case GEF_TREFFER_AUSLOESUNG: - case GEF_INIT: + case GEF_TREFFER_AUSLOESUNG: // we have got a new status (f.g. wounded lying) and send back our new status + case GEF_INIT: // ?? .. or just act like this is a treffer ausloesung ....... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ { TrainingAreaBase::TetraIcd::StateChange tele; uint32_t issi = 0; - for (int i = 0; i < m_playerList.count(); i++) + for (int i = 0; i < m_playerList.count(); i++) // get issi from player's eqId { if (radioTelegram->getIdentity() == m_playerList.at(i)->eqId) { @@ -477,17 +486,17 @@ void TTWorker::handleDataIndReq(const QByteArray &data) } TrainingAreaBase::TetraIcd::VulnerabilityState state = (telID == GEF_TREFFER_AUSLOESUNG) ? static_cast(radioTelegram->getPayloadDataUInt8(7)) - : TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady; + : TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady; //get vbg from radio - tele.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::Initialisation; - tele.header.equipmentNumber = radioTelegram->getIdentity(); + tele.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::Initialisation; //set origin + tele.header.equipmentNumber = radioTelegram->getIdentity(); //set header tele.header.timeStamp = time(nullptr) * 1000; uint32_t vulcomplete = radioTelegram->getPayloadDataUInt32(8, 2); uint32_t vitality = vulcomplete &= 0xF000; vitality >>= 12; tele.tasVulnerabilityKindId = vulcomplete &= 0x0FFF; - + //including vitality tele.tasVulnerabilityKindId <<= 16; tele.tasVulnerabilityKindId |= 0xB1; @@ -500,47 +509,47 @@ void TTWorker::handleDataIndReq(const QByteArray &data) else tele.vulnerabilityState = state; - sendTelegram(tele, issi); + sendTelegram(tele, issi); // send new status return; } - - - - - - - - - + // case GEF_NLOS_DATENVERKEHR_TDS_GEF: + // { + // ERROR_LOG(m_logger) << "NlosTargetData empfangen"; + // N_CoPrtCnv::CoPrtCnvCentralTelegram *tele = N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(radioTelegram.data()); + // TrainingAreaBase::TetraIcd::NlosTargetData sc = TrainingAreaBase::TetraIcd::NlosTargetData::fromJson(tele->jsonData()); + // delete tele; + // QJsonDocument doc(sc.toJson()); + // ERROR_LOG(m_logger) << "Receive NlosTargetData Size: " << radioTelegram.data()->getSize() << "\n Structure: " << doc.toJson(QJsonDocument::Indented); + // return; - + // } } - + // miscellaneous messages.. if (radioTelegram->isLoginTelegram()) { - + // fixme: login accepted ? DEBUG_LOG(m_logger) << "player cont: " << m_playerList.count(); - for (int i = 0; i < m_playerList.count(); i++) + for (int i = 0; i < m_playerList.count(); i++) // set player isLogin true { Player *p = m_playerList.at(i); - if (radioTelegram->getDestISSI() == p->issi) + if (radioTelegram->getDestISSI() == p->issi) // is this the player we look for? { if (p->isLogin) return; DEBUG_LOG(m_logger) << "Player #" << i << " with eqId=" << p->eqId << " and issi=" << p->issi << " is now logged in."; p->isLogin = true; - sendBITE(p->eqId, p->issi); + sendBITE(p->eqId, p->issi); // send BITE message to log us in, though return; } } - + // player not found ERROR_LOG(m_logger) << "Invalid player was logged in. issi: '" << radioTelegram->getDestISSI() << "'"; return; } - + // none of our swicthes & conditions wanted this received message! we have got a unused or invalid message.. throw it away and give, at least, a DEBUG message DEBUG_LOG(m_logger) << "Received unused or invalid telegram with Telegram-ID: " << telID; } @@ -565,38 +574,38 @@ void TTWorker::handleRegisterInd() m_socket->write(buf); - + //mTimer->start(1000); } -void TTWorker::movePlayer(Player *p) +void TTWorker::movePlayer(Player *p) // move the player like the pattern says { - + // use all variables from the Player POINTER (do not use new instances) - if (p->patternInList > m_patternList.count() - 1) - p->patternInList = 0; + if (p->patternInList > m_patternList.count() - 1) // if patternInList is HIGHER than the list-count is, then jump back to position 0 to start again + p->patternInList = 0; // set to list-start else { - if (p->stepInPattern > m_patternList.at(p->patternInList).steps) + if (p->stepInPattern > m_patternList.at(p->patternInList).steps) // if we have less steps than the stepInPattern says, then we have obsolved all wnted steps, so we can jump to the new pattern in the List { - p->stepInPattern = 1; - if (p->patternInList == m_patternList.count() - 1) + p->stepInPattern = 1; // reset steps for the new pattern + if (p->patternInList == m_patternList.count() - 1) // if there is NOT a next pattern, then reset pattern counter to 0 p->patternInList = 0; else - p->patternInList++; + p->patternInList++; // jump to next pattern IF there is a next pattern } } p->posUTM.setX(p->posUTM.x() + - m_patternList.at(p->patternInList).northering); + m_patternList.at(p->patternInList).northering); // increase northering as the pattern says p->posUTM.setY(p->posUTM.y() + - m_patternList.at(p->patternInList).ethering); + m_patternList.at(p->patternInList).ethering); // ^^^^^^^^ ethering ^^^^^^^^^^^^^^^^^^^ - p->stepInPattern++; + p->stepInPattern++; // increase the step counter before we leave, so the player can be moved the next time!! } void TTWorker::onSendPlayerPositions() { - + // return; qint64 bytesSent = 0; int playerCount = 0; TrainingAreaBase::TetraIcd::PositionReport tele; @@ -604,23 +613,23 @@ void TTWorker::onSendPlayerPositions() { Player *p = m_playerList.at(i); - if (!p->isLogin) + if (!p->isLogin) // do not send position data if one player is not logged in { INFO_LOG(m_logger) << "Player with eqId=" << p->eqId << " and issi=" << p->issi << " is not logged in."; break; } playerCount++; - - if (p->vbg != TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady && p->isEndOfTicks()) - sendTaktischerStatus(p->eqId, p->issi, TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady); + // respawn : + if (p->vbg != TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady && p->isEndOfTicks()) // only count to zero (isEndOfTicks = are the ticks running out ?) for respawn, if Player is NOT alive! + sendTaktischerStatus(p->eqId, p->issi, TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady); // only give rebirth, do not kill //(unsigned short)!p->isAlive); // kill Player if he is alive, give rebirth to Player if he is dead tele.header.equipmentNumber = p->eqId; if (m_toogle) sendSanitationReport(p->eqId, p->issi); - - - movePlayer(p); + // else + // sendSanitation(p->eqId, p->issi); + movePlayer(p); // move players tele.relPosition.offsetY = p->posUTM.y(); tele.relPosition.offsetX = p->posUTM.x(); diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.h b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.h index 6fb08e41e..9128a8809 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/TetraTestServer/worker.h @@ -1,5 +1,10 @@ - - +/* + * @RDE_HEADER@ + * Worker for Tetra Simulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once @@ -29,21 +34,21 @@ NGL::INGLLogger &m_logger; } public: - + // PU simulation vars: uint32_t eqId; uint32_t issi; QPointF posUTM; - + // PU login-state vars: bool isLogin; bool isValidBITE; TrainingAreaBase::TetraIcd::VulnerabilityState vbg; - - int patternInList; - int stepInPattern; + // pattern vars: + int patternInList; // >-| which pattern to take from the pattern list + int stepInPattern; // <-| which step we have in the current pattern (see "patternInList" above) - + // x seconds, for a Player to respawn [maximum / mininum] uint32_t deathTicks; uint32_t minimumDeathTicks; uint32_t maximumDeathTicks; @@ -64,12 +69,12 @@ public: randomizeDeathTicks(); } - bool isEndOfTicks() + bool isEndOfTicks() // gives TRUE if deathTicks is lower than 1 and randomizes deathTicks again, so this function can be reused everytime { deathTicks--; if (deathTicks < 1) { - randomizeDeathTicks(); + randomizeDeathTicks(); // randomize again return true; } return false; @@ -87,8 +92,8 @@ public: private Q_SLOTS: void onReadyRead(); - void onSendPlayerPositions(); - + void onSendPlayerPositions(); // -> nur senden, wenn isLogin & isValidBite für tln ok + // wenn LoginOk von PrtCnv -> onSendBite(eqId) void onSocketError(); void onSendNachforderungBroadcastTelegramm(); void onSendDeaktivierungEinzelminen(); @@ -112,7 +117,7 @@ protected: void sendBITE(uint32_t eqId, uint32_t issi); void sendTaktischerStatus(uint32_t eqId, uint32_t issi, TrainingAreaBase::TetraIcd::VulnerabilityState vbg); void sendSanitationReport(uint32_t eqId, uint32_t issi); - + //void sendSanitation(uint32_t eqId, uint32_t issi); private: QTcpSocket *m_socket; QTimer *m_timer; diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.cpp b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.cpp index 6bbb33031..bdc2d5757 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.cpp +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.cpp @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Building Config - logging facility + * $Id$ + * $HeadURL$ + * $Author$ + */ #include "logger.h" @@ -27,4 +32,4 @@ LOGGER_T getLogger(const char *name) } } -} +} // namespace PrtCnv diff --git a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.h b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.h index 198d77a70..e3bd12365 100644 --- a/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.h +++ b/qt6-after/qt6-migrated-legatus/TetraIF/PrtCnv/logger.h @@ -1,5 +1,10 @@ - - +/** + * @RDE_HEADER@ + * Logging for AereaEffectSimulation + * $Id$ + * $HeadURL$ + * $Author$ + */ #pragma once @@ -15,4 +20,4 @@ inline LOGGER_T getLogger(const QString &loggerName) { return getLogger(loggerName.toUtf8().constData()); } -} +} // namespace PrtCnv
%1: %20x%30b%4