Adds q2 repos to migrate
This commit is contained in:
1 parent
ad1f62c4ee
commit
17f1c61c9e
991 files changed
+178451
No files matched your search
@@ -0,0 +1,503 @@
|
||||
|
||||
|
||||
#include "tetra_if.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QNetworkInterface>
|
||||
#include <QStringList>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
|
||||
#include <PrtCnv/PrtCnvRadioThread.hpp>
|
||||
#include <PrtCnv/PrtCnvThreadStarter.hpp>
|
||||
|
||||
TetraIF::TetraIF(const QHostAddress &addr, unsigned short port, unsigned short issi)
|
||||
: QObject()
|
||||
, m_addr(addr)
|
||||
, m_port(port)
|
||||
, m_issi(issi)
|
||||
, m_socket(new QTcpSocket(this))
|
||||
, m_count(0)
|
||||
, m_telegramsPerSecond(0)
|
||||
, m_telegramsInCurSecond(0)
|
||||
, m_secondFragment(0)
|
||||
, m_timer(nullptr)
|
||||
, m_SendCounter(0)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger())
|
||||
|
||||
{
|
||||
connect(m_socket, &QTcpSocket::connected, this, &TetraIF::onConnected);
|
||||
connect(m_socket, &QTcpSocket::disconnected, this, &TetraIF::onDisconnected);
|
||||
connect(m_socket, &QTcpSocket::readyRead, this, &TetraIF::onReadyRead);
|
||||
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &TetraIF::onError);
|
||||
|
||||
m_outputDir = QCoreApplication::applicationDirPath();
|
||||
m_outputDir += QLatin1Char('/') + QString::number(m_issi) + QLatin1Char('-');
|
||||
}
|
||||
|
||||
void TetraIF::start()
|
||||
{
|
||||
m_socket->connectToHost(m_addr, m_port);
|
||||
}
|
||||
|
||||
void TetraIF::listenMode(const QStringList &args)
|
||||
{
|
||||
|
||||
if (args.count() > 1)
|
||||
usage();
|
||||
m_outputDir = QCoreApplication::applicationDirPath();
|
||||
if (args.count() == 1)
|
||||
m_outputDir = args[0];
|
||||
if (!QDir().mkpath(m_outputDir))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error creating directory "
|
||||
<< m_outputDir;
|
||||
usage();
|
||||
}
|
||||
|
||||
m_outputDir += QLatin1Char('/') + QString::number(m_issi) + QLatin1Char('-');
|
||||
}
|
||||
|
||||
void TetraIF::randomMode(const QStringList &args)
|
||||
{
|
||||
if (args.count() < 3)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid argument count";
|
||||
usage();
|
||||
}
|
||||
bool bOk;
|
||||
int dataSize = args[0].toInt(&bOk);
|
||||
if (!bOk || dataSize > 256 || dataSize < 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid data size " << args[0];
|
||||
usage();
|
||||
}
|
||||
m_count = args[1].toInt(&bOk);
|
||||
if (!bOk || m_count == 0 || m_count < -1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid count " << args[1];
|
||||
usage();
|
||||
}
|
||||
m_telegramsPerSecond = args[2].toInt(&bOk);
|
||||
if (!bOk || m_telegramsPerSecond < 1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid telegrams/second " << args[2];
|
||||
usage();
|
||||
}
|
||||
m_data.reserve(dataSize);
|
||||
for (int i = 0; i < dataSize; ++i)
|
||||
m_data += (i % 256);
|
||||
|
||||
parseISSIs(args.mid(3));
|
||||
|
||||
INFO_LOG(m_logger) << "Sending " << m_data.size()
|
||||
<< " bytes, " << m_telegramsPerSecond
|
||||
<< " telegrams/second for " << m_count
|
||||
<< " time(s) to issi(s) " << getIssisAsString();
|
||||
|
||||
setupTimer();
|
||||
}
|
||||
|
||||
void TetraIF::fileMode(const QStringList &args)
|
||||
{
|
||||
if (args.count() < 3)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid argument count";
|
||||
usage();
|
||||
}
|
||||
QFile f(args[0]);
|
||||
if (!f.exists() || f.size() > 256)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid file: " << args[0];
|
||||
usage();
|
||||
}
|
||||
bool bOk;
|
||||
m_count = args[1].toInt(&bOk);
|
||||
if (!bOk || m_count == 0 || m_count < -1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid count " << args[1];
|
||||
usage();
|
||||
}
|
||||
m_telegramsPerSecond = args[2].toInt(&bOk);
|
||||
if (!bOk || m_telegramsPerSecond < 1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid telegrams/second " << args[2];
|
||||
usage();
|
||||
}
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error opening file "
|
||||
<< f.fileName()
|
||||
<< " for reading - error: "
|
||||
<< f.errorString();
|
||||
}
|
||||
m_data = f.readAll();
|
||||
|
||||
parseISSIs(args.mid(3));
|
||||
|
||||
INFO_LOG(m_logger) << "Sending " << m_data.size()
|
||||
<< " bytes, " << m_telegramsPerSecond
|
||||
<< " telegrams/second for " << m_count
|
||||
<< " time(s) to issi(s) " << getIssisAsString();
|
||||
|
||||
setupTimer();
|
||||
}
|
||||
|
||||
void TetraIF::usage()
|
||||
{
|
||||
NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger());
|
||||
ERROR_LOG(logger) << "Usage : " << QCoreApplication::applicationFilePath() << " <ip> <port> <src_issi> <mode> <options>";
|
||||
ERROR_LOG(logger) << " <mode> : listen|send_random|send_file";
|
||||
ERROR_LOG(logger) << " <listen> : [<output_dir>]";
|
||||
ERROR_LOG(logger) << " <send_random> : <size> <count> <telegrams_per_second_and_dest> [<dest_issi1> .. <dest_issiN>]";
|
||||
ERROR_LOG(logger) << " <send_file> : <file> <count> <telegrams_per_second_and_dest> [<dest_issi1> .. <dest_issiN>]";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void TetraIF::onConnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Connected to " << m_socket->peerName() << ":" << m_socket->peerPort();
|
||||
doInitialLogin();
|
||||
}
|
||||
|
||||
void TetraIF::onDisconnected()
|
||||
{
|
||||
INFO_LOG(m_logger) << "Disconnected - exiting application";
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
void TetraIF::onReadyRead()
|
||||
{
|
||||
do
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got " << m_socket->bytesAvailable() << " bytes from socket";
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram::PrtCnvRadioGwHeader header;
|
||||
if (m_socket->bytesAvailable() < int(sizeof(header)))
|
||||
return;
|
||||
|
||||
m_socket->peek(reinterpret_cast<char *>(&header), sizeof(header));
|
||||
if (N_CoPrtCnv::CoPrtCnvRadioTelegram::MAGIC_NUMBER != header.m_MagicNumber)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Incorrect magic number (0x"
|
||||
<< QString::number(header.m_MagicNumber, 16)
|
||||
<< " - aborting";
|
||||
exit(2);
|
||||
}
|
||||
if (!N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(header.m_Length))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Radio-Telegram length to big: "
|
||||
<< header.m_Length
|
||||
<< ", but I proceed with this telegram.";
|
||||
}
|
||||
|
||||
const quint16 dataSize = header.m_Length + sizeof(header);
|
||||
if (m_socket->bytesAvailable() < dataSize)
|
||||
{
|
||||
INFO_LOG(m_logger) << "not enough bytes available - waiting for more data";
|
||||
return;
|
||||
}
|
||||
QByteArray buf(dataSize, Qt::Uninitialized);
|
||||
m_socket->read(buf.data(), dataSize);
|
||||
handleReceivedTelegram(buf);
|
||||
|
||||
}
|
||||
while (m_socket->bytesAvailable());
|
||||
}
|
||||
|
||||
void TetraIF::onError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Socket error "
|
||||
<< err
|
||||
<< " ("
|
||||
<< m_socket->errorString()
|
||||
<< ") - aborting";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void TetraIF::doInitialLogin()
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(m_issi);
|
||||
m_socket->write(tele.data());
|
||||
m_socket->flush();
|
||||
}
|
||||
|
||||
void TetraIF::handleReceivedTelegram(const QByteArray &data)
|
||||
{
|
||||
const auto type = N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type(data.at(4));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp:
|
||||
handleRegisterRsp(data.at(5));
|
||||
break;
|
||||
|
||||
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq:
|
||||
handleDataIndReq(data);
|
||||
break;
|
||||
|
||||
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq:
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
INFO_LOG(m_logger) << "PDU Type: " << type;
|
||||
dumpData(data);
|
||||
}
|
||||
|
||||
void TetraIF::handleRegisterRsp(const uint8_t a_registrationStatus)
|
||||
{
|
||||
QByteArray logText;
|
||||
switch (a_registrationStatus)
|
||||
{
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_IssiSuccessfulRegistered:
|
||||
INFO_LOG(m_logger) << "Valid register response from Tetra ";
|
||||
if (m_timer)
|
||||
m_timer->start();
|
||||
return;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DuplicateISSI:
|
||||
logText = "TETRA: Register-Response: Status=Duplicate ISSI";
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_InvalidISSI:
|
||||
logText = "TETRA: Register-Response: Status=Invalid ISSI";
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_InvalidIpAddress:
|
||||
logText = "TETRA: Register-Response: Status=Invalid IP address => Configure TETRA for accepting our IP-address (";
|
||||
{
|
||||
const QList<QHostAddress> ipList = QNetworkInterface::allAddresses();
|
||||
for (const QHostAddress &addr : ipList)
|
||||
logText += addr.toString().toUtf8() + ", ";
|
||||
logText += ")...";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logText = "Unknown registration status: " + QByteArray::number(a_registrationStatus);
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR_LOG(m_logger) << logText;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void TetraIF::dumpData(const QByteArray &data)
|
||||
{
|
||||
|
||||
if (m_outputDir.isEmpty())
|
||||
return;
|
||||
const qint64 msecs = QDateTime::currentMSecsSinceEpoch();
|
||||
const QString timeStr = QStringLiteral("%1.%2").arg(msecs / 1000).arg(msecs % 1000);
|
||||
{
|
||||
QFile f(m_outputDir + timeStr + QLatin1String(".dat"));
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error opening file "
|
||||
<< f.fileName()
|
||||
<< " for writing - error: "
|
||||
<< f.errorString();
|
||||
}
|
||||
f.write(data);
|
||||
f.close();
|
||||
}
|
||||
if (data.size() > 27)
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(data);
|
||||
INFO_LOG(m_logger) << "Got telegram from "
|
||||
<< tele.getSrcISSI()
|
||||
<< " with size "
|
||||
<< data.size()
|
||||
<< " and payload size "
|
||||
<< tele.getPayloadSize();
|
||||
NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Info, tele.data());
|
||||
QFile f(m_outputDir + QStringLiteral("payload-%1-%2.dat").arg(QString::number(tele.getSrcISSI()), timeStr));
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error opening file "
|
||||
<< f.fileName()
|
||||
<< " for writing - error: "
|
||||
<< f.errorString();
|
||||
}
|
||||
|
||||
f.write(&data.data()[27], data.size() - 27);
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
void TetraIF::onSendData()
|
||||
{
|
||||
++m_secondFragment;
|
||||
|
||||
if (m_secondFragment == 100)
|
||||
{
|
||||
m_secondFragment = 0;
|
||||
m_telegramsInCurSecond = 0;
|
||||
}
|
||||
|
||||
int telegramsToSendNow = (m_telegramsPerSecond - m_telegramsInCurSecond) / (100 - m_secondFragment);
|
||||
NOTICE_LOG(m_logger) << "telegramsToSendNow: " << telegramsToSendNow << ", " << m_telegramsPerSecond << ", " << m_telegramsInCurSecond << ", " << m_secondFragment;
|
||||
|
||||
m_telegramsInCurSecond += telegramsToSendNow;
|
||||
static uint8_t s_counter = 1;
|
||||
static char s_randomChar = 0;
|
||||
for (int i = 0; i < telegramsToSendNow; ++i)
|
||||
{
|
||||
for (unsigned short dest_issi : qAsConst(m_issiList))
|
||||
{
|
||||
|
||||
m_data[0] = s_randomChar++;
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, m_data.size(), dest_issi);
|
||||
tele.setPayloadDataComplete(m_data);
|
||||
tele.setSrcISSI(m_issi);
|
||||
tele.setDestISSI(dest_issi);
|
||||
tele.setZaehler(s_counter++);
|
||||
DEBUG_LOG(m_logger) << "Sending " << tele.getSize() << " bytes to Tetra (ISSI: " << dest_issi << ")";
|
||||
m_socket->write(tele.data());
|
||||
}
|
||||
if (m_count > 0)
|
||||
{
|
||||
if (--m_count <= 0)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Finsihed";
|
||||
m_socket->disconnectFromHost();
|
||||
}
|
||||
}
|
||||
m_socket->flush();
|
||||
}
|
||||
}
|
||||
|
||||
void TetraIF::parseISSIs(const QStringList &issiList)
|
||||
{
|
||||
m_issiList.clear();
|
||||
|
||||
if (issiList.count() == 0)
|
||||
{
|
||||
m_issiList += 0;
|
||||
return;
|
||||
}
|
||||
for (const QString &issiStr : issiList)
|
||||
{
|
||||
bool bOk;
|
||||
unsigned short issi = issiStr.toUShort(&bOk);
|
||||
if (!bOk)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not a valid issi number: " << issiStr;
|
||||
usage();
|
||||
}
|
||||
m_issiList += issi;
|
||||
}
|
||||
}
|
||||
|
||||
QString TetraIF::getIssisAsString() const
|
||||
{
|
||||
QString ret;
|
||||
for (unsigned short issi : qAsConst(m_issiList))
|
||||
ret += QString::number(issi) + QLatin1String(", ");
|
||||
return ret.left(ret.size() - 2);
|
||||
}
|
||||
|
||||
void TetraIF::handleDataIndReq(const QByteArray &data)
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram *radioTelegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(data);
|
||||
uint32_t m_HostISSI = 2;
|
||||
if (m_HostISSI == radioTelegram->getDestISSI())
|
||||
{
|
||||
|
||||
switch (radioTelegram->getFragmentStatus())
|
||||
{
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment:
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment:
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment:
|
||||
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_NotFragmented:
|
||||
handleLoginTelegram(radioTelegram);
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Unknown payload-status!: " << radioTelegram->getFragmentStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
delete radioTelegram;
|
||||
}
|
||||
}
|
||||
|
||||
void TetraIF::handleLoginTelegram(N_CoPrtCnv::CoPrtCnvRadioTelegram *a_loginTelegram)
|
||||
{
|
||||
uint16_t identity = a_loginTelegram->getIdentity();
|
||||
uint32_t issi = a_loginTelegram->getSrcISSI();
|
||||
|
||||
if (N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginRequest == (a_loginTelegram->getPayloadDataUInt8(2) & N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginStatusMask))
|
||||
{
|
||||
bool sent = sendLoginResponse(issi);
|
||||
if (sent)
|
||||
INFO_LOG(m_logger) << "Login: New TPU with Id=" << identity << " and ISSI=" << issi << " logged in";
|
||||
else
|
||||
|
||||
INFO_LOG(m_logger) << "Login: New TPU with Id=" << identity << " and ISSI=" << issi << " is NOT logged in";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
a_telegram->setDestISSI(a_ISSI);
|
||||
a_telegram->setSrcISSI(2);
|
||||
gef_telegramm_id_et telId = a_telegram->isNormalTelegram() ? a_telegram->getTelID() : GEF_BESTAETIGUNG;
|
||||
|
||||
|
||||
INFO_LOG(m_logger) << "Send telegram to radio: telId=" << telId << " wcounter=" << a_telegram->zaehler() << " size= 28";
|
||||
|
||||
|
||||
|
||||
a_telegram->setProtocolIdentifier(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_TDSMessageWithoutSDS_TL);
|
||||
a_telegram->setPayloadData(0x01);
|
||||
a_telegram->setPayloadData(0x04);
|
||||
|
||||
a_telegram->getData()[22] = 0x0d;
|
||||
|
||||
char *data = a_telegram->getData();
|
||||
|
||||
|
||||
data[02] = 0x18;
|
||||
|
||||
data[22] = 0x0d;
|
||||
data[23] = 0x00;
|
||||
|
||||
data[24] = 0x02;
|
||||
data[25] = 0x00;
|
||||
|
||||
data[13] = 0x00;
|
||||
data[26] = 0x01;
|
||||
data[27] = 0x40;
|
||||
|
||||
m_socket->write(data, 28);
|
||||
delete a_telegram;
|
||||
return m_socket->flush();
|
||||
|
||||
}
|
||||
|
||||
void TetraIF::setupTimer()
|
||||
{
|
||||
delete m_timer;
|
||||
m_timer = new QTimer(this);
|
||||
connect(m_timer, &QTimer::timeout, this, &TetraIF::onSendData);
|
||||
m_timer->setInterval(10);
|
||||
}
|
||||
Reference in new issue
Block a user