/** * Messages from/to a SFM (passed through Wls message PayloadMobileToHost / PayloadHostToMobile * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2017-01-10 */ #pragma once #include #include namespace WirelessLocationSystem { /** * \class SfmMessage * * \brief Oberklasse fuer Nachrichten von/an das SFM * * \author B. Ziegler */ class SfmMessage { public: enum class MsgId { TacticalState = 37, SfmRestartNotification = 76, GpsControl = 79, RequestGpsControl = 79 | 0x8000, // RTR bit set EquipmentId = 478, RequestEquipmentId = 478 | 0x8000, // RTR bit set Acknowledge = 1098, LicenseState = 1099, TetraMessage = 1100 }; protected: explicit SfmMessage(MsgId id) : m_id(id) {} public: virtual ~SfmMessage() = default; MsgId getId() const { return m_id; } private: MsgId m_id; }; /// --------------SfmMessage_tx-------------- /** * \class SfmMessage_tx * * \brief Oberklasse fuer sendbare Nachrichten * * \author B. Ziegler */ class SfmMessage_tx : public SfmMessage { public: using SfmMessage::SfmMessage; /** * \brief Interface zur Abfrage der Payload * * \author B. Ziegler * * Diese Methode gibt der reine Payload der Nachricht wieder. * Default: Leeres ByteArray (keine Parameter) * * \return Ein ByteArray welches die vollstaendige Payload enthaelt */ virtual QByteArray getPayload() const = 0; }; /// --------------SfmMessage_rx-------------- /** * \class SfmMessage_rx * * \brief Oberklasse fuer empfangbare Nachrichten * * \author B. Ziegler */ class SfmMessage_rx : public SfmMessage { public: using SfmMessage::SfmMessage; /** * \brief Interface zur Püfung und Aufschlüsselung der Payload * * \author B. Ziegler * * Standard Implementierung geht von einer leeren Payload aus * * \param payload Die zu verarbeitende Payload * * \return true: Payload konnte korrekt verarbeitet werden */ virtual bool setPayload(const QByteArray &payload) = 0; }; /// ########## Specific Messages ########## /// ---------- SfmMsgGpsControl_tx ---------- /** * \class SfmMsgGpsControl_tx * * \brief Setzen der GPS-Control * * \author B. Ziegler */ class SfmMsgGpsControl_tx final : public SfmMessage_tx { public: explicit SfmMsgGpsControl_tx(bool gpsOn = false) : SfmMessage_tx(SfmMessage::MsgId::GpsControl) , m_gpsOn(gpsOn) {} QByteArray getPayload() const override; void setGpsOn(bool bOn) { m_gpsOn = bOn; } bool isGpsOn() const { return m_gpsOn; } private: bool m_gpsOn; }; /// ---------- SfmMsgRequestGpsControl_rx ---------- /** * \class SfmMsgRequestGpsControl_rx * * \brief Request from SFM to get current GPS mode * * description * * \author Ch. Ehrlicher */ class SfmMsgRequestGpsControl_rx final : public SfmMessage_rx { public: SfmMsgRequestGpsControl_rx() : SfmMessage_rx(SfmMessage::MsgId::RequestGpsControl) {} bool setPayload(const QByteArray &payload) override { return (payload.size() == 0); } }; /// ---------- SfmMsgRequestEquipmentId_tx ---------- /** * \class SfmMsgRequestEquipmentId_tx * * \brief Anfrage der AusstattungsNr * * description * * \author B. Ziegler */ class SfmMsgRequestEquipmentId_tx final : public SfmMessage_tx { public: SfmMsgRequestEquipmentId_tx() : SfmMessage_tx(SfmMessage::MsgId::RequestEquipmentId) {} QByteArray getPayload() const override { return QByteArray(); } }; /// ---------- SfmMsgEquipmentId_rx ---------- /** * \class SfmMsgEquipmentId_rx * * \brief Rueckgabe der AusstattungsNr * * \author B. Ziegler */ class SFMCONVERTER_EXPORT SfmMsgEquipmentId final : public SfmMessage_rx, public SfmMessage_tx { public: SfmMsgEquipmentId() : SfmMessage_rx(SfmMessage::MsgId::EquipmentId) , SfmMessage_tx(SfmMessage::MsgId::EquipmentId) {} bool setPayload(const QByteArray &) override; QByteArray getPayload() const override; static constexpr int s_payloadSize = 3; unsigned short getEquipmentNumber() const { return m_equipmentNumber; } void setEquipmentNumber(quint16 equipmentNumber) { m_equipmentNumber = equipmentNumber; } private: unsigned short m_equipmentNumber = 0; }; /// ---------- SfmMsgSfmRestart_rx ---------- /** * \class SfmMsgSfmRestart_rx * * \brief Anzeigen eines SFM-Restarts * * \author B. Ziegler */ class SfmMsgSfmRestart_rx final : public SfmMessage_rx { public: SfmMsgSfmRestart_rx() : SfmMessage_rx(SfmMessage::MsgId::SfmRestartNotification) {} bool setPayload(const QByteArray &payload) override { return (payload.size() == 0); } }; /// ---------- SfmMsgTacticalState_rx ---------- /** * \class SfmMsgTacticalState_rx * * \brief Setzen des VBGs eines Teilnehmers * * \author B. Ziegler */ class SfmMsgTacticalState_rx final : public SfmMessage_rx { public: SfmMsgTacticalState_rx() : SfmMessage_rx(SfmMessage::MsgId::TacticalState) {} static constexpr int s_payloadSize = 1; bool setPayload(const QByteArray &) override; unsigned char getTacticalState() const { return m_tacticalState; } private: unsigned char m_tacticalState = 0; }; /// ---------- SfmMsgTetra ---------- /** * \class SfmMsgTetra * * \brief Eine Tetra-Nachricht die zur Zentrale weitergereicht werden muss * * \author B. Ziegler */ class SfmMsgTetra_rx final : public SfmMessage_rx { public: SfmMsgTetra_rx() : SfmMessage_rx(SfmMessage::MsgId::TetraMessage) {} bool setPayload(const QByteArray &p_data) override; uint8_t sendCounter() const { return m_sendCounter; } bool isFragmented() const { return fragmentCount() > 1; } uint8_t fragmentNumber() const { return m_fragmentByte & 0x0f; } uint8_t fragmentCount() const { return (m_fragmentByte & 0xf0) >> 4;} const QByteArray &payload() const { return m_payload; } private: QByteArray m_payload; uint8_t m_sendCounter = 0; uint8_t m_fragmentByte = 0; }; class SfmMsgTetra_tx final : public SfmMessage_tx { public: explicit SfmMsgTetra_tx(uint8_t sendCounter, int fragmentCount, int fragmentNumber, const QByteArray &data) : SfmMessage_tx(SfmMessage::MsgId::TetraMessage) { m_data.reserve(data.size() + 2); m_data += sendCounter; m_data += fragmentByte(fragmentCount, fragmentNumber); m_data += data; } static char fragmentByte(int fragmentCount, int fragmentNumber) { Q_ASSERT(fragmentCount >= 0 && fragmentCount < 16); Q_ASSERT(fragmentNumber >= 0 && fragmentNumber <= fragmentCount); return ((fragmentCount & 0x0f) << 4 ) | (fragmentNumber & 0x0f); } QByteArray getPayload() const override { return m_data; } private: QByteArray m_data; }; /// ---------- Ack/NAck ---------- class Acknowledge_rx final : public SfmMessage_rx { public: Acknowledge_rx() : SfmMessage_rx(SfmMessage::MsgId::Acknowledge) {} static constexpr int s_payloadSize = 2; bool setPayload(const QByteArray &p_data) override; uint8_t recvCounter() const { return m_recvCounter; } bool isOk() const { return m_ackState == 0; } bool isCrcError() const { return (m_ackState & 0x20) == 0x20; } bool isFragmentError() const { return (m_ackState & 0x10) == 0x10; } uint8_t missingFragment() const { return (m_ackState & 0x0f)!= 0; } private: uint8_t m_recvCounter = 0; uint8_t m_ackState = 0; }; class Acknowledge_tx final : public SfmMessage_tx { public: explicit Acknowledge_tx() : SfmMessage_tx(SfmMessage::MsgId::Acknowledge) {} QByteArray getPayload() const override; void setRecvCounter(uint8_t recvCounter) { m_recvCounter = recvCounter; } void setCrcError() { m_ackState |= 0x20; } void setFragmentError(uint8_t missingFrag) { m_ackState |= (0x10 | (0x0f & missingFrag)); } private: uint8_t m_recvCounter = 0; uint8_t m_ackState = 0; }; /// ---------- MsgLizensStatus ---------- /** * \class SfmMsgLizensStatus * * \brief Eine Lizenzstatus-Nachricht die zur Zentrale weitergereicht werden muss * * \author B. Ziegler */ class SfmMsgLicenseState_rx final : public SfmMessage_rx { public: SfmMsgLicenseState_rx() : SfmMessage_rx(SfmMessage::MsgId::LicenseState) {} static constexpr int s_payloadSize = 1; bool setPayload(const QByteArray &p_data) override; bool isLicensed() const { return m_isLicensed; } private: bool m_isLicensed = false; }; }//namespace WirelessLocationSystem