/******************************************************************************* * * * Société de Transports de Montréal. * * 2015 * * * * Projet Zones Tests * * * * * * * *******************************************************************************/ /* Description: Classe qui contient toute la logique du protocole de communication par réseau entre la Zone Test et le logiciel d'analyse. */ /* ************************************************************************** */ /* Revision: ### 20121210 JFM Verision d'origine. ### YYYYMMDD Description du besoin ou du bug Description du changement. */ /* ************************************************************************** */ #include "TCPProtocol.h" #include #include #include CTCPProtocol::CTCPProtocol() { } // unsigned int CTCPProtocol::AnalyzeNewData(QByteArray data) { QDataStream stream(data); stream.device()->seek(0); switch(mProtocolRxState) { case TCP_PROTOCOL_GET_HEADER_STATE: { quint32 header = 0; qint32 msg = 0; stream >> header; if(header != TCP_PROTOCOL_HEADER) { return RET_ERROR; } stream >> msg; stream >> mCurTransactionDataSize; mCurTransactionMsg = (eTCPMessage)msg; if(mCurTransactionDataSize != 0) { mCurTransactionData = stream.device()->readAll(); if(mCurTransactionData.size() < mCurTransactionDataSize) { mProtocolRxState = TCP_PROTOCOL_GET_DATA_STATE; } else if(mCurTransactionData.size() > mCurTransactionDataSize) { //error qDebug("Rx data > Transaction data. Aborting transaction"); ResetRxStateMachine(); } else { DecodeTCPMessage(); ResetRxStateMachine(); } } else { DecodeTCPMessage(); ResetRxStateMachine(); } break; } case TCP_PROTOCOL_GET_MSG_STATE: { break; } case TCP_PROTOCOL_GET_DATASIZE_STATE: { break; } case TCP_PROTOCOL_GET_DATA_STATE: { mCurTransactionData.append(data); if(mCurTransactionData.size() == mCurTransactionDataSize) { //All data received DecodeTCPMessage(); ResetRxStateMachine(); } else if(mCurTransactionData.size() > mCurTransactionDataSize) { //error qDebug("Rx data > Transaction data. Aborting transaction"); ResetRxStateMachine(); } else { qDebug() << "Chunk received. New data size = " << mCurTransactionData.size(); } break; } } return RET_OK; } QByteArray CTCPProtocol::GetHeartbeatPacket() { QByteArray request; QDataStream stream(&request,QIODevice::WriteOnly); stream.device()->seek(0); request.clear(); stream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_HEARTBEAT_RESPONSE << (qint64)0; ; //no data... // TCPTxRequest(request); return request; } QByteArray CTCPProtocol::GetStationNamePacket(QString StationName) { QByteArray request; QDataStream stream(&request,QIODevice::WriteOnly); stream.device()->seek(0); request.clear(); stream << TCP_PROTOCOL_HEADER; stream << (qint32)TCP_MSG_STATION_NAME_RESPONSE; stream << (qint64)StationName.size(); request.append(StationName); //no data... // TCPTxRequest(request); return request; } QByteArray CTCPProtocol::GetZTStatusPacket(CTCPZTStatus *Status) { QByteArray request; request.clear(); QByteArray data; data.clear(); QDataStream datastream(&data,QIODevice::WriteOnly); datastream.device()->seek(0); datastream << *Status; QDataStream requeststream(&request,QIODevice::WriteOnly); requeststream.device()->seek(0); requeststream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_ZT_STATUS_RESPONSE << (qint64)data.size(); request.append(data); // TCPTxRequest(request); return request; } QByteArray CTCPProtocol::GetZTLogPacket(QString *ZTLog) { QByteArray request; request.clear(); QByteArray data; data.clear(); data = ZTLog->toUtf8(); QDataStream requeststream(&request,QIODevice::WriteOnly); requeststream.device()->seek(0); requeststream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_ZTLOG_DOWNLOAD_RESPONSE << (qint64)data.size(); request.append(data); return request; } QByteArray CTCPProtocol::GetTrainLogsDownloadAckPacket(qint32 FileCount) { QByteArray request; request.clear(); QDataStream requeststream(&request,QIODevice::WriteOnly); requeststream.device()->seek(0); requeststream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_TRAINSLOGS_DOWNLOAD_ACK << (qint64)sizeof(FileCount) << FileCount; return request; } QByteArray *CTCPProtocol::GetTrainLogDataPacket(const QByteArray &FileData) { QByteArray *request = new QByteArray; request->clear(); QDataStream requeststream(request,QIODevice::WriteOnly); requeststream.device()->seek(0); requeststream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_TRAINLOG_FILE_DATA << (qint64)FileData.size(); request->append(FileData); return request; //MUST BE DELETED BY CALLER !!!! } QByteArray CTCPProtocol::GetTrainLogsDownloadFinishedPacket() { QByteArray request; QDataStream stream(&request,QIODevice::WriteOnly); stream.device()->seek(0); request.clear(); stream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_TRAINLOGS_DOWNLOAD_FINISHED << (qint64)0; ; return request; } QByteArray CTCPProtocol::GetDeleteZTLogsAckPacket(qint32 Acknowledge) { QByteArray request; QDataStream stream(&request,QIODevice::WriteOnly); stream.device()->seek(0); request.clear(); stream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_DELETE_ZTLOG_ACK << (qint64)4 << Acknowledge; return request; } QByteArray CTCPProtocol::GetSetZTFunctionsConfigAckPacket(qint32 Ack) { QByteArray request; QDataStream stream(&request,QIODevice::WriteOnly); stream.device()->seek(0); request.clear(); stream << TCP_PROTOCOL_HEADER << (qint32)TCP_MSG_SET_ZT_FUNCTIONS_ACK << (qint64)4 << Ack; return request; } void CTCPProtocol::TCPTxRequest(QByteArray request) { Q_UNUSED(request) qDebug("No reimplementation of TXRequest in TCPProtocol.c. Request not sent..."); } void CTCPProtocol::ResetRxStateMachine() { mCurTransactionData.clear(); mCurTransactionDataSize = 0; mCurTransactionMsg = TCP_MSG_UNKNOWN; mProtocolRxState = TCP_PROTOCOL_GET_HEADER_STATE; } int CTCPProtocol::DecodeTCPMessage() { switch(mCurTransactionMsg) { case TCP_MSG_HEARTBEAT_REQUEST: { TCPHeartbeatRequest(); break; } case TCP_MSG_STATION_NAME_REQUEST: { TCPStationNameRequest(); break; } case TCP_MSG_ZT_STATUS_REQUEST: { TCPStatusRequest(); break; } case TCP_MSG_ZTLOG_DOWNLOAD_REQUEST: { TCPZTLogDownloadRequest(); break; } case TCP_MSG_TRAINLOGS_DOWNLOAD_REQUEST: { TCPTrainLogsDownloadRequest(); break; } case TCP_MSG_TRAINLOG_FILE_DATA_ACK: { qint32 ack = TCP_PROTOCOL_INVALID_ACK; QDataStream strm(mCurTransactionData); strm.device()->seek(0); strm >> ack; TCPTrainLogFileDataAck((eTCPProtocolAcknowledge)ack); break; } case TCP_MSG_DELETE_ZTLOG_REQUEST: { TCPDeleteZTLogRequest(); break; } case TCP_MSG_SET_ZT_FUNCTIONS: { TCPSetZTFunctionsConfigRequest(mCurTransactionData); break; } case TCP_MSG_SET_ZT_FUNCTIONS_ACK: case TCP_MSG_DELETE_ZTLOG_ACK: case TCP_MSG_ZT_STATUS_RESPONSE: case TCP_MSG_HEARTBEAT_RESPONSE: case TCP_MSG_STATION_NAME_RESPONSE: case TCP_MSG_ZTLOG_DOWNLOAD_RESPONSE: case TCP_MSG_TRAINSLOGS_DOWNLOAD_ACK: case TCP_MSG_TRAINLOG_FILE_DATA: case TCP_MSG_TRAINLOGS_DOWNLOAD_FINISHED: case TCP_MSG_UNKNOWN: { qDebug() << "Received invalid msg:" << mCurTransactionMsg; break; } } return RET_OK; } QDataStream &operator<<(QDataStream &out, const CTCPZTStatus &source) { out << source.mZT1Status << source.mZT2Status << source.mNbPass << source.mNbTrigs << source.mZTStartDateTime << source.mActualDateTime << source.mPGTreshold << source.mModeMaintenanceON << source.mCalibModeON << source.mFNTKActive << source.mFNAnalysisActive << source.mPGTKActive << source.mPGAnalysisActive << source.mPP1TKActive << source.mPP1AnalysisActive << source.mPP2TKActive << source.mPP2AnalysisActive << source.mZT1TKActive << source.mZT1AnalysisActive << source.mZT2TKActive << source.mZT2AnalysisActive << source.mUSBKeyConnected; return out; } QDataStream &operator>>(QDataStream &in, CTCPZTFunctionsStatus &dest) { in >> dest.mFNTKActive >> dest.mFNAnalysisActive >> dest.mPGTKActive >> dest.mPGAnalysisActive >> dest.mPP1TKActive >> dest.mPP1AnalysisActive >> dest.mPP2TKActive >> dest.mPP2AnalysisActive >> dest.mZT1TKActive >> dest.mZT1AnalysisActive >> dest.mZT2TKActive >> dest.mZT2AnalysisActive; return in; } QDataStream &operator<<(QDataStream &out, const CTCPZTFunctionsStatus &source) { out << source.mFNTKActive << source.mFNAnalysisActive << source.mPGTKActive << source.mPGAnalysisActive << source.mPP1TKActive << source.mPP1AnalysisActive << source.mPP2TKActive << source.mPP2AnalysisActive << source.mZT1TKActive << source.mZT1AnalysisActive << source.mZT2TKActive << source.mZT2AnalysisActive; return out; }