// ************************************************************************** // // (C) Copyright 2009 Swiss SIMTEC AG // // ************************************************************************** // // $HeadURL$ // $LastChangedBy$ // $LastChangedDate$ // $LastChangedRevision$ // // ************************************************************************** #pragma once #include #include #include #include #include #include #include "tetra_telegram_ids.h" namespace NGL { 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, Selftest = 1, Battery = 2, Configuration = 3, Unlicense = 4, 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, e_StorageAllowed = 0x10, e_GroupServiceOrOnlyStandardReportAllowed = 0x20, e_ReceivedConfirmationRequested = 0x40, 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, // 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, e_FirstFragment = 0x40, e_MiddleFragment = 0xC0, e_LastFragment = 0x80, e_FragmentStatusMask = 0xC0, e_Checksum = 0x20, e_CounterMask = 0x0F, e_NormalTelegram = 0x00, e_LoginTelegram = 0x02, 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, e_RegisterRsp = 1, e_DataIndReq = 2, e_ReportIndReq = 3, e_StatusIndReq = 4, e_GroupMonitorReq = 6, e_AirInterfaceLoadReq = 8, e_AirLoadHyterra = 19 }; /** * @author alois.wismer * @version 1.0 * @created 17-Mrz-2010 13:06:40 */ enum E_RegistrationStatus { e_IssiSuccessfulRegistered = 0, e_DuplicateISSI = 1, e_InvalidISSI = 2, 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, e_SDS_ConsumedByDestination = 0x02, e_SourceIsNotAuthorizedForSDS = 0x43, e_DestinationIsNotAuthorizedForSDS = 0x44, e_UnknownDestinationAddress = 0x45, e_DeliveryFailed = 0x4A, e_DestinationNotRegisteredOnSystem = 0x4B, e_DestinationQueueFull = 0x4C, e_MessageTooLong = 0x4D, e_DestinationHostPC_NotConnected = 0x4F, e_ProtocolNotSupported = 0x50, e_DataCodingSchemeNotSupported = 0x51, 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, e_LoginAccept = 0x80, e_LoginReject = 0xC0, e_LoginStatusMask = 0xC0, e_LoginMastering = 0x20, // 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; /** * 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; bool isPayloadLengthOk(uint16_t a_minLength, uint16_t a_maxLength) const; 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); uint8_t getUInt8(const uint16_t a_offset) const { return static_cast(m_data.at(a_offset)); } 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: /** * The logger object */ NGL::INGLLogger &m_logger; }; }