OutilZT/sources/NetworkManager.cpp
jfmartel ce57a2e501 Compilation sur Qt 5.14.2
Compatibilité avec les fichiers logs contenant les états des fonctions de détection.
2024-08-15 14:05:30 -04:00

500 lines
14 KiB
C++

#include "NetworkManager.h"
#include <QDebug>
#include "OutilZT.h"
//CNetworkManager CNetworkManager::mSingleton;
CNetworkManager::CNetworkManager(QObject *parent)
{
mConfig = 0;
mCurZTID = 0;
mProgramHandle = 0;
mZTUDPSocket = 0;
mUDPServerAdress = QHostAddress::Null;
mNetworkSMState = NETWORK_SM_STANDBY_STATE;
mOnlineCheckNetworkSMState = NETWORK_ONLINE_CHK_SM_STANDBY_STATE;
// mZTTcpSocket.setSocketOption(QAbstractSocket::LowDelayOption,1);
connect(&mZTTcpSocket,SIGNAL(connected()),this,SLOT(SocketConnected()));
connect(&mZTTcpSocket,SIGNAL(disconnected()),this,SLOT(SocketDisconnected()));
connect(&mZTTcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(SocketError(QAbstractSocket::SocketError)));
connect(&mZTTcpSocket,SIGNAL(readyRead()),this,SLOT(SocketDataReady()));
mZTOnlineCheckingSocket.setSocketOption(QAbstractSocket::LowDelayOption,1);
connect(&mZTOnlineCheckingSocket,SIGNAL(connected()),this,SLOT(OnlineCheckSocketConnected()));
connect(&mZTOnlineCheckingSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(OnlineCheckSocketError(QAbstractSocket::SocketError)));
}
CNetworkManager::~CNetworkManager()
{
mZTTcpSocket.disconnectFromHost();
mZTOnlineCheckingSocket.disconnectFromHost();
}
void CNetworkManager::BindPointers(COutilZT *ProgramHandle)
{
mProgramHandle = ProgramHandle;
}
void CNetworkManager::OnlineCheckStateMachine(eNetworkSMEvent event)
{
switch(mOnlineCheckNetworkSMState)
{
case NETWORK_ONLINE_CHK_SM_INIT_STATE:
{
break;
}
case NETWORK_ONLINE_CHK_SM_STANDBY_STATE:
{
break;
}
case NETWORK_ONLINE_CHK_SM_CHECK_CONNECTIONS_STATE:
{
switch(event)
{
case NETWORK_SM_SOCKET_CONNECTED_EVENT:
{
// qDebug("%s Connected",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
emit NetworkZTConnectionStatus(mOnlineCheckZTID,ZT_NETWORK_ONLINE_STATUS);
break;
}
case NETWORK_SM_SOCKET_ERROR_EVENT:
{
// qDebug("%s Not connected",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
emit NetworkZTConnectionStatus(mOnlineCheckZTID,ZT_NETWORK_OFFLINE_STATUS);
break;
}
case NETWORK_SM_SOCKET_DISCONNECTED_EVENT:
{
//Nothing to do here but we need to manage it because it will be received each time we disconnect.
return;
break;
}
default:
{
// qDebug("Unmanaged event in NETWORK_ONLINE_CHK_SM_CHECK_CONNECTIONS_STATE : %d",event);
return;
break;
}
}
mOnlineCheckZTID++;
if(mNetworkSMState != NETWORK_SM_STANDBY_STATE)
{
//Skip the connected ZT if there is one.
if(mOnlineCheckZTID == mCurZTID)
{
mOnlineCheckZTID++;
}
}
if(mOnlineCheckZTID >= NB_ZT_ID)
{
mOnlineCheckNetworkSMState = NETWORK_ONLINE_CHK_SM_STANDBY_STATE;
mZTOnlineCheckingSocket.disconnectFromHost();
}
else
{
mZTOnlineCheckingSocket.disconnectFromHost();
// qDebug("Attempting to connect to %s",mConfig->mNetworkCfgList.at(mOnlineCheckZTID).mIPAdress.toAscii().data());
emit NetworkZTConnectionStatus(mOnlineCheckZTID,ZT_NETWORK_SEARCHING_STATUS);
mZTOnlineCheckingSocket.connectToHost(mConfig->mNetworkCfgList.at(mOnlineCheckZTID).mIPAdress,ZT_TCP_PORT);
}
break;
}
}
}
void CNetworkManager::NetworkStateMachine(eNetworkSMEvent event)
{
switch(mNetworkSMState)
{
case NETWORK_SM_INIT_STATE:
{
break;
}
case NETWORK_SM_STANDBY_STATE:
{
break;
}
case NETWORK_SM_INITIATE_CLIENT_CONNECTION_STATE:
{
switch(event)
{
case NETWORK_SM_SOCKET_CONNECTED_EVENT:
{
//qDebug("%s Connected",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
emit NetworkZTConnected(mCurZTID);
emit NetworkZTConnectionStatus(mCurZTID,ZT_NETWORK_CONNECTED_STATUS);
//RequestHeartbeat();
//mZTTcpSocket.write(GetStationNameReqPacket());
TCPTxRequest(GetStationNameReqPacket());
mNetworkSMState = NETWORK_SM_CLIENT_CONNECTED_STATE;
break;
}
case NETWORK_SM_SOCKET_ERROR_EVENT:
{
// qDebug("%s Socket error",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
emit NetworkZTConnectionError(mCurZTID);
mNetworkSMState = NETWORK_SM_STANDBY_STATE;
break;
}
case NETWORK_SM_SOCKET_DISCONNECTED_EVENT:
{
mNetworkSMState = NETWORK_SM_STANDBY_STATE;
emit NetworkZTConnectionStatus(mOnlineCheckZTID,ZT_NETWORK_UNKNOWN_STATUS);
emit NetworkZTConnectionError(mCurZTID);
break;
}
default:
{
mNetworkSMState = NETWORK_SM_STANDBY_STATE;
qDebug("Invalid event in NETWORK_SM_INITIATE_CLIENT_CONNECTION_STATE : %d",event);
break;
}
}
break;
}
case NETWORK_SM_CLIENT_CONNECTED_STATE:
{
switch(event)
{
case NETWORK_SM_SOCKET_ERROR_EVENT:
{
// qDebug("%s Socket error",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
break;
}
case NETWORK_SM_SOCKET_DISCONNECTED_EVENT:
{
emit NetworkZTDisconnected(mCurZTID);
emit NetworkZTConnectionStatus(mCurZTID,ZT_NETWORK_UNKNOWN_STATUS);
mNetworkSMState = NETWORK_SM_STANDBY_STATE;
//qDebug("%s Disconnected",mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
qDebug("TCP Socket disconnected");
break;
}
default:
{
qDebug("Unmanaged event in NETWORK_SM_CLIENT_CONNECTED_STATE : %d",event);
break;
}
}
break;
}
default:
{
break;
}
}
}
unsigned int CNetworkManager::InitUDPConnection(int ZTID)
{
mZTUDPSocket = new QUdpSocket(this);
if(mZTUDPSocket->bind(QHostAddress::Any,ZT_UDP_PORT) == false)
return RET_ERROR;
mUDPServerAdress = QHostAddress(mConfig->mNetworkCfgList.at(ZTID).mIPAdress);
connect(mZTUDPSocket,SIGNAL(readyRead()),this,SLOT(UDPSocketDataReady()));
QByteArray packet = GetInitUDPConnectionPacket();
mZTUDPSocket->writeDatagram(packet,mUDPServerAdress,ZT_UDP_PORT);
return RET_OK;
}
unsigned int CNetworkManager::StopUDPStream()
{
if(mZTUDPSocket == 0)
return RET_ERROR;
QByteArray packet = GetCloseUDPConnectionPacket();
mZTUDPSocket->writeDatagram(packet,mUDPServerAdress,ZT_UDP_PORT);
mZTUDPSocket->waitForBytesWritten();
return RET_OK;
}
unsigned int CNetworkManager::CloseUDPConnection()
{
if(mZTUDPSocket == 0)
return RET_ERROR;
// QByteArray packet = GetCloseUDPConnectionPacket();
// mZTUDPSocket->writeDatagram(packet,mUDPServerAdress,ZT_UDP_PORT);
// mZTUDPSocket->flush();
delete mZTUDPSocket;
mZTUDPSocket = 0;
mUDPServerAdress = QHostAddress::Null;
return RET_OK;
}
int CNetworkManager::CheckZTConnectionsStatus()
{
if(mOnlineCheckNetworkSMState != NETWORK_ONLINE_CHK_SM_STANDBY_STATE)
return RET_ERROR;
mOnlineCheckZTID = 0;
mOnlineCheckNetworkSMState = NETWORK_ONLINE_CHK_SM_CHECK_CONNECTIONS_STATE;
emit NetworkZTConnectionStatus(mOnlineCheckZTID,ZT_NETWORK_SEARCHING_STATUS);
// qDebug("Attempting to connect to %s",mConfig->mNetworkCfgList.at(mOnlineCheckZTID).mIPAdress.toAscii().data());
mZTOnlineCheckingSocket.connectToHost(mConfig->mNetworkCfgList.at(mOnlineCheckZTID).mIPAdress,ZT_TCP_PORT);
return RET_OK;
}
unsigned int CNetworkManager::SetConfig(CSettingsData *Config)
{
mConfig = Config;
return RET_OK;
}
unsigned int CNetworkManager::ConnectToZT(int ZTID)
{
if(ZTID >= NB_ZT_ID)
{
qDebug("Cannot connect: Invalid ZT ID");
return RET_ERROR;
}
if(mNetworkSMState != NETWORK_SM_STANDBY_STATE)
{
qDebug("Cannot connect: Invalid State machine state : %d",mNetworkSMState);
return RET_ERROR;
}
mCurZTID = ZTID;
mNetworkSMState = NETWORK_SM_INITIATE_CLIENT_CONNECTION_STATE;
mZTTcpSocket.connectToHost(mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress,ZT_TCP_PORT);
// qDebug("Connecting to %s", mConfig->mNetworkCfgList.at(mCurZTID).mIPAdress.toAscii().data());
return RET_OK;
}
unsigned int CNetworkManager::DisconnectZT()
{
// if(mNetworkSMState == NETWORK_SM_STANDBY_STATE)
// return RET_ERROR;
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
{
qDebug("Aborting connection from ZT. Socket state : %d",mZTTcpSocket.state());
mZTTcpSocket.abort();
NetworkStateMachine(NETWORK_SM_SOCKET_DISCONNECTED_EVENT);
}
else
{
qDebug("Disconnecting from ZT. Socket state : %d",mZTTcpSocket.state());
mZTTcpSocket.disconnectFromHost();
}
return RET_OK;
}
void CNetworkManager::TCPTxRequest(const QByteArray &request)
{
qDebug() << "Tx request in Network Manager : " << request.size() << " bytes : " << request.toHex();
emit NetworkTCPTx();
mZTTcpSocket.write(request);
}
unsigned int CNetworkManager::RefreshRemoteZTStatus()
{
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
return RET_ERROR;
TCPTxRequest(GetZTStatusReqPacket());
return RET_OK;
}
unsigned int CNetworkManager::DownloadZTLog()
{
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
return RET_ERROR;
TCPTxRequest(GetZTLogDownloadReqPacket());
return RET_OK;
}
unsigned int CNetworkManager::DownloadTrainLogs()
{
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
return RET_ERROR;
TCPTxRequest(GetTrainLogsDownloadReqPacket());
return RET_OK;
}
unsigned int CNetworkManager::DeleteRemoteZTLog()
{
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
return RET_ERROR;
TCPTxRequest(GetDeleteZTLogReqPacket());
return RET_OK;
}
unsigned int CNetworkManager::SetZTFunctions(const CTCPZTFunctionsStatus &ZTFunctions)
{
if(mNetworkSMState != NETWORK_SM_CLIENT_CONNECTED_STATE)
return RET_ERROR;
QByteArray data;
QDataStream strm(&data,QIODevice::WriteOnly);
strm.device()->seek(0);
strm << ZTFunctions;
TCPTxRequest(GetSetZTFunctionsPacket(data));
return RET_OK;
}
//slots
void CNetworkManager::SocketConnected()
{
qDebug("Socket connected slot");
NetworkStateMachine(NETWORK_SM_SOCKET_CONNECTED_EVENT);
}
void CNetworkManager::SocketDisconnected()
{
qDebug("Socket disconnected slot");
NetworkStateMachine(NETWORK_SM_SOCKET_DISCONNECTED_EVENT);
}
void CNetworkManager::SocketError(QAbstractSocket::SocketError socketError)
{
qDebug("Socket error slot. Error:[%d]",socketError);
NetworkStateMachine(NETWORK_SM_SOCKET_ERROR_EVENT);
}
void CNetworkManager::SocketDataReady()
{
// qDebug() << "Socket data ready:" << mZTTcpSocket.bytesAvailable();
emit NetworkTCPRx();
AnalyzeNewData(mZTTcpSocket.readAll());
}
void CNetworkManager::OnlineCheckSocketConnected()
{
OnlineCheckStateMachine(NETWORK_SM_SOCKET_CONNECTED_EVENT);
}
void CNetworkManager::OnlineCheckSocketError(QAbstractSocket::SocketError socketError)
{
OnlineCheckStateMachine(NETWORK_SM_SOCKET_ERROR_EVENT);
}
void CNetworkManager::TCPRxHeartbeat()
{
qDebug() << "TCP: Received Heartbeat";
}
void CNetworkManager::TCPRxStationName(QString Name)
{
qDebug() << "TCP: Received station name:" << Name;
mProgramHandle->RxStationName(Name);
mZTTcpSocket.write(GetZTStatusReqPacket());
}
void CNetworkManager::TCPRxZTStatus(const QByteArray &data)
{
CTCPZTStatus status;
QDataStream stream(data);
stream.device()->seek(0);
stream >> status;
qDebug() << "TCP: Received ZT Status";
mProgramHandle->RxZTStatus(status);
}
void CNetworkManager::TCPRxZTLog(QString ZTLog)
{
mProgramHandle->RxZTLog(ZTLog);
}
void CNetworkManager::TCPRxTrainLogsDownladAck(qint32 NbFiles)
{
qDebug("TCP: Received downoad train files ack : %d",NbFiles);
mProgramHandle->DownloadTrainLogsBegin(NbFiles);
mZTTcpSocket.write(GetTrainLogsFileDataAckPacket((qint32)TCP_PROTOCOL_ACK));
}
void CNetworkManager::TCPRxTrainLogFileData(const QByteArray &TrainFileData)
{
QDataStream strm(TrainFileData);
strm.device()->seek(0);
QString LogFilePathName;
strm >> LogFilePathName;
LogFilePathName.prepend(mProgramHandle->GetTrainLogsTempPath());
QFile* BinaryLogFile = new QFile(LogFilePathName);
if(BinaryLogFile)
{
if(BinaryLogFile->open(QIODevice::WriteOnly) == false)
{
qDebug("Could not create log file : %s",LogFilePathName.toLatin1().data());
delete BinaryLogFile;
return;
}
}
BinaryLogFile->write(strm.device()->readAll());
BinaryLogFile->close();
delete BinaryLogFile;
mProgramHandle->RxTrainLogData(LogFilePathName);
mZTTcpSocket.write(GetTrainLogsFileDataAckPacket((qint32)TCP_PROTOCOL_ACK));
}
void CNetworkManager::TCPRxTrainLogsDownloadFinished()
{
mProgramHandle->RxTrainLogsDownloadFinished();
}
void CNetworkManager::TCPRxDeleteZTLogAck(bool success)
{
mProgramHandle->RemoteZTLogDeleted(success);
}
void CNetworkManager::TCPRxSetZTFunctionsAck(bool ack)
{
mProgramHandle->SetZTFunctionsSatusDone(ack);
}
void CNetworkManager::UDPSocketDataReady()
{
}