#include "NetworkManager.h" #include #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() { }