test_sdk/hw/ADCCluster/stpclient.cpp

225 lines
6.8 KiB
C++
Raw Normal View History

#include "stpclient.h"
stpClient::stpClient(QHostAddress address, int port, QObject *parent)
: QObject{parent},
_state(stpClient_ns::stpState::DISCONNECTED),
_pingState(stpClient_ns::pingState::IDLE),
_socket(new QUdpSocket()),
_address(address),
_port(port),
_pingTimer(new QTimer()),
_pingTimeoutCount(0),
_reconnectionTimer(new QTimer())
{
_reconnectionTimer->setInterval(STP_RECONNECTION_PERIOD);
QObject::connect(_reconnectionTimer, &QTimer::timeout, [=]{
connectToHost();
});
QObject::connect(_socket, &QUdpSocket::readyRead,
this, [=](){
#ifdef STP_MANY_PACKETS_DEBUG
int __count = 0;
#endif
while (_socket->hasPendingDatagrams()) {
#ifdef STP_MANY_PACKETS_DEBUG
__count++;
#endif
_processData(_socket->receiveDatagram());
}
#ifdef STP_MANY_PACKETS_DEBUG
if (__count > 44) qDebug() << "Received packets at once(!): " << __count;
#endif
});
_pingTimer->setTimerType(Qt::PreciseTimer);
_pingTimer->setInterval(STP_PING_INTERVAL_MS);
QObject::connect(_pingTimer, &QTimer::timeout, [=]{
if (_state == stpClient_ns::stpState::CONNECTED) {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::PING), _address, _port);
_pingState = stpClient_ns::pingState::PENDING;
QTimer::singleShot(STP_TIMEOUT_MS, [=]{
if (_pingState == stpClient_ns::pingState::PENDING) {
#ifdef STP_DEBUG
qDebug() << QTime::currentTime().toString() << "ping timeout";
#endif
_pingTimeoutCount++;
if (_pingTimeoutCount >= STP_TIMEOUT_COUNT) {
disconnectFromHost();
emit STP_disconnected();
}
}
});
}
});
}
stpClient::~stpClient()
{
delete _pingTimer;
delete _reconnectionTimer;
delete _socket;
#ifdef STP_DEBUG
qDebug() << "stpClient desctructor";
#endif
}
void stpClient::connectToHost()
{
if ((_state == stpClient_ns::stpState::DISCONNECTED) ||
(_state == stpClient_ns::stpState::CONNECTING)) {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::SYNCReq), _address, _port);
_state = stpClient_ns::stpState::CONNECTING;
_reconnectionTimer->start();
}
}
void stpClient::disconnectFromHost()
{
if (_state != stpClient_ns::stpState::DISCONNECTED) {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::RESET), _address, _port);
_state = stpClient_ns::stpState::DISCONNECTED;
_pingState = stpClient_ns::pingState::IDLE;
_pingTimer->stop();
}
}
void stpClient::sendData(QByteArray *buff)
{
if (_state == stpClient_ns::stpState::CONNECTED) {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::DATA, buff), _address, _port);
}
}
QByteArray stpClient::_pack(stpProtocol_ns::packetType packetType, QByteArray *data)
{
QByteArray __result;
if ( (packetType == stpProtocol_ns::packetType::DATA)
&& (data != nullptr) ) {
// data packet
trans_ns::bytes2word __size;
__size.word = data->size();
__result.resize(CONST_HEADER_SIZE);
__result[0] = packetType;
__result[1] = __size.bytes.L;
__result[2] = __size.bytes.H;
__result.append(*data);
} else {
// system packets
__result.resize(CONST_HEADER_SIZE);
__result[0] = packetType;
__result[1] = 0;
__result[2] = 0;
}
return __result;
}
QByteArray stpClient::packIdRequest()
{
QByteArray __result;
__result.resize(CONST_HEADER_SIZE + 1);
__result[0] = stpProtocol_ns::packetType::DATA;
__result[1] = 0x01;
__result[2] = 0x00;
__result[3] = (uint8_t)stpProtocol_ns::stpCommand::REQ_ID;
return __result;
}
QByteArray stpClient::packIdSnRequest(uint16_t sn)
{
trans_ns::bytes2word __sn;
__sn.word = sn;
QByteArray __result;
__result.resize(CONST_HEADER_SIZE + 3);
__result[0] = stpProtocol_ns::packetType::DATA;
__result[1] = 0x03;
__result[2] = 0x00;
__result[3] = (uint8_t)stpProtocol_ns::stpCommand::REQ_ID_SN;
__result[4] = __sn.bytes.L;
__result[5] = __sn.bytes.H;
return __result;
}
void stpClient::_processData(QNetworkDatagram dg)
{
int __size = dg.data().size();
if (__size < CONST_HEADER_SIZE) return;
QByteArray __header = dg.data().first(CONST_HEADER_SIZE);
QByteArray __data = dg.data().last(__size - CONST_HEADER_SIZE);
trans_ns::bytes2word __declaredSize;
__declaredSize.bytes.L = __header[1];
__declaredSize.bytes.H = __header[2];
if (__data.size() != __declaredSize.word) {
#ifdef STP_DEBUG
qDebug() << dg.senderAddress().toString() << "badPacketSize (packetSize: " << __data.size() << "; declaredSize: " << __declaredSize.word << ")";
#endif
return;
}
switch (__header[0]) {
case stpProtocol_ns::packetType::PING:
if (_state == stpClient_ns::stpState::CONNECTED) {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::PONG), _address, _port);
} else {
_socket->writeDatagram(_pack(stpProtocol_ns::packetType::RESET), _address, _port);
}
break;
case stpProtocol_ns::packetType::PONG:
if (_pingState == stpClient_ns::pingState::PENDING) {
_pingState = stpClient_ns::pingState::IDLE;
_pingTimeoutCount = 0;
}
break;
case stpProtocol_ns::packetType::DATA:
emit STP_newDataPacketReceived(__data);
break;
case stpProtocol_ns::packetType::RESET:
#ifdef STP_DEBUG
qDebug() << "stp conection reset from: " << dg.senderAddress().toString();
#endif
_state = stpClient_ns::stpState::DISCONNECTED;
_pingState = stpClient_ns::pingState::IDLE;
_pingTimer->stop();
emit STP_disconnected();
break;
case stpProtocol_ns::packetType::SYNCAck:
if (_state == stpClient_ns::stpState::CONNECTED) {
#ifdef STP_DEBUG
qDebug() << _address.toString() << "(!!!) <SYNCAck> came when client is already connected";
#endif
} else {
_state = stpClient_ns::stpState::CONNECTED;
_pingTimer->start();
emit STP_connected();
}
break;
case stpProtocol_ns::packetType::SYNCReq:
// клиент не реагирует
break;
}
}