Files
qt5-legatus-legacy/Lts/Proxies/WirelessLocationSystem/wls_sfm_message.h
T
2026-08-13 18:33:10 +02:00

371 lines
8.2 KiB
C++
Executable File

/**
* 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 <WirelessLocationSystem/sfmconverter_export.h>
#include <QByteArray>
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