#pragma once #include #include namespace WirelessLocationSystem { class SfmMessage { public: enum class MsgId { TacticalState = 37, SfmRestartNotification = 76, GpsControl = 79, RequestGpsControl = 79 | 0x8000, EquipmentId = 478, RequestEquipmentId = 478 | 0x8000, 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; }; class SfmMessage_tx : public SfmMessage { public: using SfmMessage::SfmMessage; virtual QByteArray getPayload() const = 0; }; class SfmMessage_rx : public SfmMessage { public: using SfmMessage::SfmMessage; virtual bool setPayload(const QByteArray& payload) = 0; }; 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; }; 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); } }; class SfmMsgRequestEquipmentId_tx final : public SfmMessage_tx { public: SfmMsgRequestEquipmentId_tx() : SfmMessage_tx(SfmMessage::MsgId::RequestEquipmentId) {} QByteArray getPayload() const override { return QByteArray(); } }; 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; }; 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); } }; 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; }; 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; }; 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; }; 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