143 lines
3.8 KiB
C++
Executable File
143 lines
3.8 KiB
C++
Executable File
/**
|
|
* Send / Receive telegrams to/from PrtCnv
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Christian Ehrlicher, SLSE, 2016-09-26
|
|
*/
|
|
|
|
#include "socket_dispatcher_json.h"
|
|
#include <QCoreApplication>
|
|
#include <QDir>
|
|
#include <QTcpServer>
|
|
|
|
namespace TetraRadio
|
|
{
|
|
|
|
//
|
|
// SocketDispatcher
|
|
//
|
|
SocketDispatcher::SocketDispatcher(TrainingAreaBase::Plugin::DataProvider *pdp,
|
|
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &recvFromTabCb)
|
|
: QObject()
|
|
, ConvertFromJson(recvFromTabCb, "TAB.Plugin.SocketDispatcher")
|
|
, m_txHandler(std::make_shared<ConvertToJson>("TxSocketHandler"))
|
|
, m_dataProvider(pdp)
|
|
, m_prtCnvApp(nullptr)
|
|
, m_ackTimer(new QTimer(this))
|
|
, m_bInitialAck(false)
|
|
, m_receiveCounter(0)
|
|
{
|
|
m_ackTimer->setInterval(1000);
|
|
m_ackTimer->setSingleShot(false);
|
|
connect(m_ackTimer, &QTimer::timeout,
|
|
this, &SocketDispatcher::onAckTimeout);
|
|
}
|
|
|
|
SocketDispatcher::~SocketDispatcher()
|
|
{
|
|
delete m_ackTimer;
|
|
}
|
|
|
|
bool SocketDispatcher::init(PrtCnv::PrtCnvApplication *prtCnvApp)
|
|
{
|
|
if (m_prtCnvApp == prtCnvApp)
|
|
return true;
|
|
if (m_prtCnvApp)
|
|
m_prtCnvApp->disconnect(this);
|
|
m_prtCnvApp = prtCnvApp;
|
|
if (m_prtCnvApp)
|
|
{
|
|
connect(m_txHandler.get(), &ConvertToJson::outgoingMessage,
|
|
m_prtCnvApp, &PrtCnv::PrtCnvApplication::textMessageFromCentralToPrtCnv);
|
|
connect(m_prtCnvApp, &PrtCnv::PrtCnvApplication::textMessageFromPrtCnvToCentral,
|
|
this, &SocketDispatcher::onTextMessageReceived);
|
|
connect(m_prtCnvApp, &PrtCnv::PrtCnvApplication::warehouseMessageFromPtrCnv,
|
|
this, &SocketDispatcher::warehouseMessage);
|
|
|
|
m_ackTimer->start();
|
|
m_bInitialAck = true;
|
|
}
|
|
else
|
|
{
|
|
m_bInitialAck = false;
|
|
m_ackTimer->stop();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
quint16 SocketDispatcher::randomListenPort() const
|
|
{
|
|
QTcpServer *s = new QTcpServer;
|
|
s->listen(QHostAddress::Any, 0);
|
|
while (!s->isListening())
|
|
QCoreApplication::processEvents();
|
|
quint16 port = s->serverPort();
|
|
delete s;
|
|
return port;
|
|
}
|
|
|
|
std::shared_ptr<TrainingAreaBase::SendToTab> SocketDispatcher::sendToTab()
|
|
{
|
|
return std::static_pointer_cast<TrainingAreaBase::SendToTab>(m_txHandler);
|
|
}
|
|
|
|
void SocketDispatcher::onTextMessageReceived(const QByteArray &message)
|
|
{
|
|
DEBUG_LOG(m_logger) << "TetraJson onTextMessageReceived: '" << message << "'";
|
|
int newRecvCounter = 0;
|
|
if (!handleTelegram(message, newRecvCounter))
|
|
return;
|
|
m_receiveCounter = newRecvCounter;
|
|
}
|
|
|
|
void SocketDispatcher::handleTetraConnectionChanged(bool bConnected)
|
|
{
|
|
emit tetraConnectionChanged(bConnected);
|
|
}
|
|
|
|
void SocketDispatcher::handleAcknowledge(qint64 timeStamp, int counter)
|
|
{
|
|
TRACE_LOG(m_logger) << "Ack from Socket for time " << timeStamp
|
|
<< " with counter " << counter
|
|
<< ", initial: " << m_bInitialAck;
|
|
if (m_bInitialAck)
|
|
{
|
|
m_txHandler->setConnected(true);
|
|
m_bInitialAck = false;
|
|
onSendInitialData();
|
|
}
|
|
// TODO: remove all now outdated telegrams !?
|
|
}
|
|
|
|
void SocketDispatcher::onAckTimeout()
|
|
{
|
|
TrainingAreaBase::TetraIcd::Acknowledge ack;
|
|
ack.timeStamp = time(nullptr) * 1000;
|
|
ack.ackCounter = m_receiveCounter;
|
|
m_txHandler->txData(ack);
|
|
}
|
|
|
|
void SocketDispatcher::onSendInitialData()
|
|
{
|
|
if (m_dataProvider)
|
|
{
|
|
NOTICE_LOG(m_logger) << "sending initial data exerciseId=" << m_dataProvider->exerciseId();
|
|
// on connect we must send:
|
|
if (m_dataProvider->exerciseId() > 0)
|
|
{
|
|
// - Umgebungsmeldung
|
|
m_txHandler->txData(m_dataProvider->exerciseEnvironmentData());
|
|
}
|
|
// - Betriebszustandsmeldung
|
|
m_txHandler->txData(m_dataProvider->exerciseStateData());
|
|
m_txHandler->txData(m_dataProvider->exerciseEquipmentAssignment());
|
|
const auto &aesTeles = m_dataProvider->aesTelegrams();
|
|
for (TrainingAreaBase::TetraIcd::TrainingAreaTelegram *aesTele : aesTeles)
|
|
m_txHandler->sendToTx(aesTele);
|
|
|
|
}
|
|
}
|
|
|
|
} // namespace TetraRadio
|