Premier commit suite au crash du repo le 10 juillet 2017
This commit is contained in:
@@ -0,0 +1,687 @@
|
||||
#include "ModbusBackend.h"
|
||||
#include "QBuffer"
|
||||
#include "EngLog.h"
|
||||
#include "ZTLog.h"
|
||||
|
||||
CModbusBackend::CModbusBackend(CModbusRepository *Repo)
|
||||
{
|
||||
mModbusTCPSocketHandle = 0;
|
||||
mDataLinkValid = false;
|
||||
mModbusRepo = Repo;
|
||||
mModbusMode = MODBUS_INVALID_MODE;
|
||||
mTransactionIDCounter = 0;
|
||||
mDeviceID = 9;//0xFF;
|
||||
|
||||
mModbusMaxRetry = MODBUS_RETRY_MAX_COUNT;
|
||||
mModbusRequestTimeout = MODBUS_RETRY_DELAY;
|
||||
}
|
||||
|
||||
CModbusBackend::~CModbusBackend()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CModbusBackend::ModbusDataReady()
|
||||
{
|
||||
|
||||
CModbusTransaction Transaction;
|
||||
QByteArray InData = mModbusTCPSocketHandle->readAll();
|
||||
|
||||
QBuffer FileBuffer(&InData);
|
||||
FileBuffer.open(QIODevice::ReadOnly);
|
||||
FileBuffer.seek(0);
|
||||
QDataStream *TransactionDataStrm = new QDataStream(&FileBuffer);
|
||||
*TransactionDataStrm >> Transaction.mHeader;
|
||||
*TransactionDataStrm >> Transaction.mPDU.mFunctionCode;
|
||||
Transaction.mPDU.mData = InData.right(Transaction.mHeader.mMessageLength - 2); //-2 to remove Device ID and Function Code.
|
||||
|
||||
qDebug("modbus data received %s",InData.toHex().data());
|
||||
qDebug("Transaction ID 0x%X",Transaction.mHeader.mTransactionID);
|
||||
qDebug("Message Length %d",Transaction.mHeader.mMessageLength);
|
||||
qDebug("Protocol ID 0x%X",Transaction.mHeader.mProtocolID);
|
||||
qDebug("Unit ID 0x%X",Transaction.mHeader.mUnitID);
|
||||
|
||||
qDebug("Function Code 0x%X",Transaction.mPDU.mFunctionCode);
|
||||
qDebug("Data %s",Transaction.mPDU.mData.toHex().data());
|
||||
|
||||
if(mModbusMode == MODBUS_MASTER_MODE)
|
||||
{
|
||||
AnalyzeModbusResponse(Transaction);
|
||||
}
|
||||
else if( mModbusMode == MODBUS_SLAVE_MODE)
|
||||
{
|
||||
AnalyzeModbusRequest(Transaction);
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur Modbus: <Illegal modbus backend mode...>");
|
||||
}
|
||||
}
|
||||
|
||||
void CModbusBackend::ModbusLinkDisconnected()
|
||||
{
|
||||
// qDebug("Modbus link disconnected");
|
||||
mDataLinkValid = false;
|
||||
}
|
||||
|
||||
|
||||
//In client mode. This is the request from the master.
|
||||
int CModbusBackend::AnalyzeModbusRequest(CModbusTransaction Transaction)
|
||||
{
|
||||
if(Transaction.mHeader.mProtocolID != 0)
|
||||
{
|
||||
//Invalid protocol... what can we do?
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(Transaction.mPDU.mFunctionCode)
|
||||
{
|
||||
case MODBUS_FCT_READ_HOLDING_REGISTERS:
|
||||
{
|
||||
bool ok = true;
|
||||
unsigned short StartAdress = 0;
|
||||
StartAdress = Transaction.mPDU.mData[0]&0xFF;
|
||||
StartAdress <<= 8;
|
||||
StartAdress += Transaction.mPDU.mData[1]&0xFF;
|
||||
unsigned short NbRegisters = 0;
|
||||
NbRegisters = Transaction.mPDU.mData[2]&0xFF;
|
||||
NbRegisters <<= 8;
|
||||
NbRegisters += Transaction.mPDU.mData[3]&0xFF;
|
||||
|
||||
//Validate nb of registers
|
||||
if(NbRegisters < 1 || NbRegisters > MODBUS_MAX_NB_REGISTERS)
|
||||
{
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_FCT_READ_HOLDING_REGISTERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Validate data range
|
||||
if(!mModbusRepo->IsHRValid(StartAdress,NbRegisters))
|
||||
{
|
||||
qDebug("Reg invalid");
|
||||
//Send negative response
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,MODBUS_FCT_READ_HOLDING_REGISTERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QByteArray data = mModbusRepo->GetHRData(StartAdress,NbRegisters,&ok);
|
||||
|
||||
qDebug("Slave Rx Read Holding Registers. Address: %d, Nb Reg: %d",StartAdress, NbRegisters);
|
||||
qDebug("Data: %s",data.toHex().data());
|
||||
|
||||
//The response to a HR reading needs the byte count before the data.
|
||||
quint8 ByteCount = data.size();
|
||||
data.prepend(ByteCount);
|
||||
SendModbusResponse(Transaction, data);
|
||||
|
||||
//All OK
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_WRITE_SINGLE_REGISTER:
|
||||
{
|
||||
unsigned short StartAdress = 0;
|
||||
|
||||
StartAdress = Transaction.mPDU.mData[0]&0xFF;
|
||||
StartAdress <<= 8;
|
||||
StartAdress += Transaction.mPDU.mData[1]&0xFF;
|
||||
|
||||
//Validate data range
|
||||
if(!mModbusRepo->IsHRValid(StartAdress,1))
|
||||
{
|
||||
qDebug("Reg invalid");
|
||||
//Send negative response
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,MODBUS_WRITE_SINGLE_REGISTER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Extract data.
|
||||
QByteArray data = Transaction.mPDU.mData.right(2);
|
||||
|
||||
//Write register data
|
||||
mModbusRepo->WriteHRData(StartAdress,1,data);
|
||||
|
||||
qDebug("Slave Rx Write Single Register. Address: %d, Value: 0x%s",StartAdress, data.toHex().data());
|
||||
qDebug("Data: %s",data.toHex().data());
|
||||
|
||||
data = Transaction.mPDU.mData.left(4); //The response corresponds to the Reg. Address & the value. Which is the first 4 bytes of the initial request.
|
||||
SendModbusResponse(Transaction, data);
|
||||
RegistersDatabaseUpdated(StartAdress,1);
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_FCT_WRITE_MULTIPLE_REGISTERS:
|
||||
{
|
||||
unsigned short StartAdress = 0;
|
||||
StartAdress = Transaction.mPDU.mData[0]&0xFF;
|
||||
StartAdress <<= 8;
|
||||
StartAdress += Transaction.mPDU.mData[1]&0xFF;
|
||||
|
||||
unsigned short NbRegisters = 0;
|
||||
NbRegisters = Transaction.mPDU.mData[2]&0xFF;
|
||||
NbRegisters <<= 8;
|
||||
NbRegisters += Transaction.mPDU.mData[3]&0xFF;
|
||||
|
||||
quint8 ByteCount = Transaction.mPDU.mData[4];
|
||||
|
||||
//Validate nb of registers
|
||||
if(NbRegisters < 1 || NbRegisters > 0x7D || ByteCount != (NbRegisters*2))
|
||||
{
|
||||
qDebug("Invalid register number or byte count ");
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_FCT_WRITE_MULTIPLE_REGISTERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Validate data range
|
||||
if(!mModbusRepo->IsHRValid(StartAdress,NbRegisters))
|
||||
{
|
||||
qDebug("Reg invalid");
|
||||
//Send negative response
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,MODBUS_FCT_WRITE_MULTIPLE_REGISTERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Extract data.
|
||||
QByteArray data = Transaction.mPDU.mData.right(ByteCount);
|
||||
|
||||
//Write register data
|
||||
mModbusRepo->WriteHRData(StartAdress,NbRegisters,data);
|
||||
|
||||
qDebug("Slave Rx Write Multiple Registers. Address: %d, Nb Reg: %d",StartAdress, NbRegisters);
|
||||
qDebug("Data: %s",data.toHex().data());
|
||||
|
||||
data = Transaction.mPDU.mData.left(4); //The response corresponds to the Start Adress and Nb of Regs. Which is the first 4 bytes of the initial request.
|
||||
SendModbusResponse(Transaction, data);
|
||||
|
||||
RegistersDatabaseUpdated(StartAdress,NbRegisters);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Received "Illegal function code". Send the exception code to master
|
||||
//TODO: Log this.
|
||||
qDebug("Slave received illegal function code from master: 0x%x",Transaction.mPDU.mFunctionCode);
|
||||
SendErrorResponse(Transaction,MODBUS_EXCEPTION_ILLEGAL_FCT);
|
||||
ModbusRequestException(MODBUS_EXCEPTION_ILLEGAL_FCT,Transaction.mPDU.mFunctionCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CModbusBackend::SendModbusResponse(CModbusTransaction RequestTransaction, QByteArray Data)
|
||||
{
|
||||
QByteArray ModbusPacket;
|
||||
|
||||
QBuffer Buffer(&ModbusPacket);
|
||||
Buffer.open(QIODevice::WriteOnly|QIODevice::Unbuffered);
|
||||
Buffer.seek(0);
|
||||
QDataStream *PacketDataStrm = new QDataStream(&Buffer);
|
||||
|
||||
//For a response, the header will be the same as the original request, except for the msg. length.
|
||||
//Set the appropriate msg length.
|
||||
RequestTransaction.mHeader.mMessageLength = Data.size() + 2; //+2 to add function code & Unit ID.
|
||||
RequestTransaction.mPDU.mData = Data;
|
||||
|
||||
*PacketDataStrm << RequestTransaction.mHeader;
|
||||
*PacketDataStrm << RequestTransaction.mPDU.mFunctionCode;
|
||||
Buffer.close();
|
||||
ModbusPacket.append(Data);
|
||||
|
||||
|
||||
qDebug("Response packet: %s",ModbusPacket.toHex().data());
|
||||
|
||||
mModbusTCPSocketHandle->write(ModbusPacket);
|
||||
|
||||
delete PacketDataStrm;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
//In Master mode. This is the response from slave to a previously sent request.
|
||||
int CModbusBackend::AnalyzeModbusResponse(CModbusTransaction Transaction)
|
||||
{
|
||||
if(Transaction.mHeader.mProtocolID != 0)
|
||||
{
|
||||
//Invalid protocol... what can we do?
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Find matching request and remove it from the queue...
|
||||
CModbusRequest *Request;
|
||||
bool Found = false;
|
||||
for(int i = 0; i < mRequestsList.size(); i++)
|
||||
{
|
||||
if(mRequestsList.at(i)->mHeader.mTransactionID == Transaction.mHeader.mTransactionID)
|
||||
{
|
||||
Request = mRequestsList.takeAt(i); //Remove from queue and keep a copy
|
||||
Request->mRequestTimer->stop(); //Stop the resend timer
|
||||
Found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(Found == false)
|
||||
{
|
||||
//Invalid request number. This should happen only if a very long delay exists in the comm.
|
||||
//TODO: Log this...
|
||||
qDebug("Master received response to a non existent request!!!");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//check if we have an exception response
|
||||
if((Transaction.mPDU.mFunctionCode & MODBUS_EXCEPTION_FCT_MASK) != 0)
|
||||
{
|
||||
//we have an exception response... something went wrong.
|
||||
quint8 ExceptionCode = Transaction.mPDU.mData[0];
|
||||
|
||||
//TODO: Manage this!
|
||||
qDebug("Master Rx exception code %d to request %d",ExceptionCode,Request->mPDU.mFunctionCode);
|
||||
emit ModbusResponseException(ExceptionCode,Request->mPDU.mFunctionCode);
|
||||
delete Request;
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
switch(Transaction.mPDU.mFunctionCode)
|
||||
{
|
||||
case MODBUS_FCT_READ_HOLDING_REGISTERS:
|
||||
{
|
||||
quint8 ByteCount = 0;
|
||||
ByteCount = Transaction.mPDU.mData.at(0);
|
||||
|
||||
if((Request->mNbRegisters*2) != ByteCount)
|
||||
{
|
||||
//Inconsistency between the data range and the data count.
|
||||
//TODO: Log the error.
|
||||
qDebug("Master eceived a wrong data size in response for a MODBUS_FCT_READ_HOLDING_REGISTERS request");
|
||||
emit ModbusResponseException(MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_FCT_READ_HOLDING_REGISTERS);
|
||||
delete Request;
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
QByteArray RegisterValues = Transaction.mPDU.mData.right(ByteCount);
|
||||
|
||||
|
||||
qDebug("Master Rx Read Holding Registers Response.");
|
||||
qDebug("Data: %s",RegisterValues.toHex().data());
|
||||
|
||||
mModbusRepo->WriteHRData(Request->mStartAddress,Request->mNbRegisters,RegisterValues);
|
||||
RegistersDatabaseUpdated(Request->mStartAddress, Request->mNbRegisters);
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_WRITE_SINGLE_REGISTER:
|
||||
{
|
||||
quint16 RegAddress = 0;
|
||||
RegAddress = Transaction.mPDU.mData[0]&0xFF;
|
||||
RegAddress <<= 8;
|
||||
RegAddress += Transaction.mPDU.mData[1]&0xFF;
|
||||
|
||||
if(Request->mStartAddress != RegAddress)
|
||||
{
|
||||
//Inconsistency between the request Adress and response Adress.
|
||||
//TODO: Log the error.
|
||||
qDebug("Master received a wrong Register Adress in response for a MODBUS_WRITE_SINGLE_REGISTER request");
|
||||
emit ModbusResponseException(MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_WRITE_SINGLE_REGISTER);
|
||||
delete Request;
|
||||
return RET_ERROR;
|
||||
}
|
||||
qDebug("Master Rx Write Single Register response. Address: %d,",RegAddress);
|
||||
qDebug("Data: %s",Transaction.mPDU.mData.toHex().data());
|
||||
|
||||
//Everything seems good.
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_FCT_WRITE_MULTIPLE_REGISTERS:
|
||||
{
|
||||
unsigned short StartAdress = 0;
|
||||
StartAdress = Transaction.mPDU.mData[0]&0xFF;
|
||||
StartAdress <<= 8;
|
||||
StartAdress += Transaction.mPDU.mData[1]&0xFF;
|
||||
|
||||
unsigned short NbRegisters = 0;
|
||||
NbRegisters = Transaction.mPDU.mData[2]&0xFF;
|
||||
NbRegisters <<= 8;
|
||||
NbRegisters += Transaction.mPDU.mData[3]&0xFF;
|
||||
|
||||
if(StartAdress != Request->mStartAddress || NbRegisters != Request->mNbRegisters)
|
||||
{
|
||||
//Inconsistency between the request Adress or NbRegisters and response.
|
||||
//TODO: Log the error.
|
||||
qDebug("Master Received a wrong Register Adress or NbRegisters in response for a MODBUS_FCT_WRITE_MULTIPLE_REGISTERS request");
|
||||
emit ModbusResponseException(MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_FCT_WRITE_MULTIPLE_REGISTERS);
|
||||
delete Request;
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
qDebug("Master Rx Write Multiple Registers response. Address: %d, Nb Reg: %d",StartAdress, NbRegisters);
|
||||
qDebug("Data: %s",Transaction.mPDU.mData.toHex().data());
|
||||
|
||||
//All is good.
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Received "Illegal function code" response
|
||||
//TODO: Log this.
|
||||
qDebug("Master received illegal function code 0x%x",Transaction.mPDU.mFunctionCode);
|
||||
emit ModbusResponseException(MODBUS_EXCEPTION_ILLEGAL_FCT,MODBUS_FCT_WRITE_MULTIPLE_REGISTERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete Request;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CModbusBackend::SendModbusRequest(CModbusRequest *Request)
|
||||
{
|
||||
QByteArray ModbusPacket;
|
||||
|
||||
QBuffer Buffer(&ModbusPacket);
|
||||
Buffer.open(QIODevice::WriteOnly|QIODevice::Unbuffered);
|
||||
Buffer.seek(0);
|
||||
QDataStream *PacketDataStrm = new QDataStream(&Buffer);
|
||||
|
||||
*PacketDataStrm << Request->mHeader;
|
||||
*PacketDataStrm << Request->mPDU.mFunctionCode;
|
||||
Buffer.close();
|
||||
ModbusPacket.append(Request->mPDU.mData);
|
||||
|
||||
qDebug("Request packet: %s",ModbusPacket.toHex().data());
|
||||
|
||||
mModbusTCPSocketHandle->write(ModbusPacket);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusBackend::SendErrorResponse(CModbusTransaction RequestTransaction, quint8 ErrorCode)
|
||||
{
|
||||
QByteArray ModbusPacket;
|
||||
|
||||
QBuffer Buffer(&ModbusPacket);
|
||||
Buffer.open(QIODevice::WriteOnly|QIODevice::Unbuffered);
|
||||
Buffer.seek(0);
|
||||
QDataStream *PacketDataStrm = new QDataStream(&Buffer);
|
||||
|
||||
//For a response, the header will be the same as the original request, except for the msg. length.
|
||||
//Set the appropriate msg length.
|
||||
RequestTransaction.mHeader.mMessageLength = 3; //Unit ID, function code & Exception code.
|
||||
|
||||
*PacketDataStrm << RequestTransaction.mHeader;
|
||||
Buffer.close();
|
||||
ModbusPacket.append(RequestTransaction.mPDU.mFunctionCode + 0x80);
|
||||
ModbusPacket.append(ErrorCode);
|
||||
|
||||
|
||||
CEngLog::instance()->AddLogString(QString("Modbus: Envoi d'un code d'un code d'erreur. Error Code %1, Error Packet: %2").arg(ErrorCode).arg(ModbusPacket.toHex().data()));
|
||||
// qDebug("Sending error code %d. Error packet: %s",ErrorCode,ModbusPacket.toHex().data());
|
||||
|
||||
mModbusTCPSocketHandle->write(ModbusPacket);
|
||||
|
||||
delete PacketDataStrm;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
int CModbusBackend::SendReadHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount)
|
||||
{
|
||||
//First, validate that the reading range is within our repo
|
||||
if(mModbusRepo->IsHRValid(StartAddress,RegisterCount) == false)
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Trying to send a read HR in an invalid range");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Create a request.
|
||||
CModbusRequest *NewRequest = new CModbusRequest;
|
||||
NewRequest->mStartAddress = StartAddress;
|
||||
NewRequest->mNbRegisters = RegisterCount;
|
||||
connect(NewRequest->mRequestTimer,SIGNAL(timeout()),this,SLOT(RequestTimerExpired()));
|
||||
|
||||
NewRequest->mPDU.mData.clear();
|
||||
NewRequest->mPDU.mFunctionCode = MODBUS_FCT_READ_HOLDING_REGISTERS;
|
||||
|
||||
quint8 HighByte, LowByte;
|
||||
LowByte = StartAddress & 0x00FF;
|
||||
HighByte = (StartAddress >> 8) & 0x00FF;
|
||||
NewRequest->mPDU.mData.append(HighByte);
|
||||
NewRequest->mPDU.mData.append(LowByte);
|
||||
|
||||
LowByte = RegisterCount & 0x00FF;
|
||||
HighByte = (RegisterCount >> 8) & 0x00FF;
|
||||
NewRequest->mPDU.mData.append(HighByte);
|
||||
NewRequest->mPDU.mData.append(LowByte);
|
||||
|
||||
NewRequest->mHeader.mMessageLength = NewRequest->mPDU.mData.size() + 2;
|
||||
NewRequest->mHeader.mProtocolID = 0;
|
||||
NewRequest->mHeader.mTransactionID = (qint16)GetNewTransactionID();
|
||||
NewRequest->mHeader.mUnitID = mDeviceID;
|
||||
|
||||
mRequestsList.append(NewRequest);
|
||||
|
||||
SendModbusRequest(NewRequest);
|
||||
|
||||
NewRequest->mRequestTimer->start(mModbusRequestTimeout);
|
||||
|
||||
|
||||
return RET_OK;
|
||||
|
||||
}
|
||||
|
||||
int CModbusBackend::SendWriteHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount)
|
||||
{
|
||||
//First, validate that the reading range is within our repo
|
||||
if(mModbusRepo->IsHRValid(StartAddress,RegisterCount) == false)
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Trying to send a Write HR in an invalid range SendWriteHoldingRegistersRequest()");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
if(RegisterCount > MODBUS_MAX_NB_REGISTERS)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Get data.
|
||||
bool OK;
|
||||
QByteArray RegData = mModbusRepo->GetHRData(StartAddress,RegisterCount,&OK);
|
||||
if(OK == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Create a request.
|
||||
CModbusRequest *NewRequest = new CModbusRequest;
|
||||
NewRequest->mStartAddress = StartAddress;
|
||||
NewRequest->mNbRegisters = RegisterCount;
|
||||
connect(NewRequest->mRequestTimer,SIGNAL(timeout()),this,SLOT(RequestTimerExpired()));
|
||||
|
||||
NewRequest->mPDU.mData.clear();
|
||||
NewRequest->mPDU.mFunctionCode = MODBUS_FCT_WRITE_MULTIPLE_REGISTERS;
|
||||
|
||||
quint8 HighByte, LowByte;
|
||||
LowByte = StartAddress & 0x00FF;
|
||||
HighByte = (StartAddress >> 8) & 0x00FF;
|
||||
NewRequest->mPDU.mData.append(HighByte);
|
||||
NewRequest->mPDU.mData.append(LowByte);
|
||||
|
||||
LowByte = RegisterCount & 0x00FF;
|
||||
HighByte = (RegisterCount >> 8) & 0x00FF;
|
||||
NewRequest->mPDU.mData.append(HighByte);
|
||||
NewRequest->mPDU.mData.append(LowByte);
|
||||
|
||||
NewRequest->mPDU.mData.append(RegData);
|
||||
|
||||
NewRequest->mHeader.mMessageLength = NewRequest->mPDU.mData.size() + 2;
|
||||
NewRequest->mHeader.mProtocolID = 0;
|
||||
NewRequest->mHeader.mTransactionID = (qint16)GetNewTransactionID();
|
||||
NewRequest->mHeader.mUnitID = mDeviceID;
|
||||
|
||||
mRequestsList.append(NewRequest);
|
||||
|
||||
SendModbusRequest(NewRequest);
|
||||
|
||||
NewRequest->mRequestTimer->start(mModbusRequestTimeout);
|
||||
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusBackend::SendWriteSingleRegisterRequest(quint16 Address)
|
||||
{
|
||||
//First, validate that the reading range is within our repo
|
||||
if(mModbusRepo->IsHRValid(Address,1) == false)
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Trying to send a Write HR in an invalid range SendWriteSingleRegisterRequest()");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Get data.
|
||||
bool OK;
|
||||
QByteArray RegData = mModbusRepo->GetHRData(Address,1,&OK);
|
||||
if(OK == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
//Create a request.
|
||||
CModbusRequest *NewRequest = new CModbusRequest;
|
||||
NewRequest->mStartAddress = Address;
|
||||
NewRequest->mNbRegisters = 1;
|
||||
connect(NewRequest->mRequestTimer,SIGNAL(timeout()),this,SLOT(RequestTimerExpired()));
|
||||
|
||||
NewRequest->mPDU.mData.clear();
|
||||
NewRequest->mPDU.mFunctionCode = MODBUS_WRITE_SINGLE_REGISTER;
|
||||
|
||||
quint8 HighByte, LowByte;
|
||||
LowByte = Address & 0x00FF;
|
||||
HighByte = (Address >> 8) & 0x00FF;
|
||||
NewRequest->mPDU.mData.append(HighByte);
|
||||
NewRequest->mPDU.mData.append(LowByte);
|
||||
|
||||
NewRequest->mPDU.mData.append(RegData);
|
||||
|
||||
NewRequest->mHeader.mMessageLength = NewRequest->mPDU.mData.size() + 2;
|
||||
NewRequest->mHeader.mProtocolID = 0;
|
||||
NewRequest->mHeader.mTransactionID = (qint16)GetNewTransactionID();
|
||||
NewRequest->mHeader.mUnitID = mDeviceID;
|
||||
|
||||
mRequestsList.append(NewRequest);
|
||||
|
||||
SendModbusRequest(NewRequest);
|
||||
|
||||
NewRequest->mRequestTimer->start(mModbusRequestTimeout);
|
||||
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CModbusBackend::RequestTimerExpired()
|
||||
{
|
||||
//find the expired request
|
||||
for(int i = 0; i < mRequestsList.size(); i++)
|
||||
{
|
||||
if(mRequestsList.at(i)->mRequestTimer->isActive() == false)
|
||||
{
|
||||
if(mRequestsList.at(i)->mRetries >= mModbusMaxRetry)
|
||||
{
|
||||
//The max number of retry has been reached. The device is probably offline.
|
||||
|
||||
CZTLog::instance()->AddLogString("Modbus Maître: Nombre maximal de tentatives sans réponse atteint avec le partenaire",true);
|
||||
|
||||
|
||||
delete mRequestsList[i];
|
||||
mRequestsList.removeAt(i);
|
||||
|
||||
|
||||
//TODO: Manage this situation (log?)
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendModbusRequest(mRequestsList[i]);
|
||||
mRequestsList.at(i)->mRequestTimer->start(mModbusRequestTimeout);
|
||||
mRequestsList[i]->mRetries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quint16 CModbusBackend::GetNewTransactionID()
|
||||
{
|
||||
quint16 ID = mTransactionIDCounter++;
|
||||
|
||||
if(mTransactionIDCounter == 0xFFFF - 10)
|
||||
{
|
||||
mTransactionIDCounter = 0;
|
||||
}
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CModbusRequest::CModbusRequest():
|
||||
mRetries(0)
|
||||
{
|
||||
mRequestTimer = new QTimer;
|
||||
mRequestTimer->setSingleShot(true);
|
||||
}
|
||||
CModbusRequest::~CModbusRequest()
|
||||
{
|
||||
delete mRequestTimer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const CModbusHeader &source)
|
||||
{
|
||||
out << source.mTransactionID
|
||||
<< source.mProtocolID
|
||||
<< source.mMessageLength
|
||||
<< source.mUnitID
|
||||
;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, CModbusHeader &dest)
|
||||
{
|
||||
in >> dest.mTransactionID
|
||||
>> dest.mProtocolID
|
||||
>> dest.mMessageLength
|
||||
>> dest.mUnitID
|
||||
;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//Virtual function that should not even get called...
|
||||
void CModbusBackend::ModbusResponseException(quint8 ExceptionCode, quint8 FctCode)
|
||||
{
|
||||
Q_UNUSED(ExceptionCode)
|
||||
Q_UNUSED(FctCode)
|
||||
CEngLog::instance()->AddLogString("ModbusResponseException called from within slave object... weird stuff!");
|
||||
}
|
||||
|
||||
//Virtual function that should not even get called...
|
||||
void CModbusBackend::ModbusRequestException(quint8 ExceptionCode, quint8 FctCode)
|
||||
{
|
||||
Q_UNUSED(ExceptionCode)
|
||||
Q_UNUSED(FctCode)
|
||||
CEngLog::instance()->AddLogString("ModbusResponseException called from within master object... weird stuff!");
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
#ifndef CMODBUSBACKEND_H
|
||||
#define CMODBUSBACKEND_H
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
#include "ModbusRepository.h"
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
#define MODBUS_EXCEPTION_FCT_MASK 0x80
|
||||
#define MODBUS_RETRY_DELAY 2000 //millisecs
|
||||
#define MODBUS_RETRY_MAX_COUNT 2 //resend an unanswered request this many times
|
||||
#define MODBUS_MAX_NB_REGISTERS 0x7D
|
||||
|
||||
enum eModbusFunctions
|
||||
{
|
||||
MODBUS_FCT_READ_HOLDING_REGISTERS = 3,
|
||||
MODBUS_WRITE_SINGLE_REGISTER = 6,
|
||||
MODBUS_FCT_WRITE_MULTIPLE_REGISTERS = 16
|
||||
};
|
||||
|
||||
enum eModbusExceptionCodes
|
||||
{
|
||||
MODBUS_EXCEPTION_ILLEGAL_FCT = 1,
|
||||
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2,
|
||||
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3,
|
||||
MODBUS_EXCEPTION_SERVER_DEVICE_FAILURE = 4,
|
||||
MODBUS_EXCEPTION_ACKNOWLEDGE = 5,
|
||||
MODBUS_EXCEPTION_SERVER_DEVICE_BUSY = 6,
|
||||
MODBUS_EXCEPTION_MEMORY_PARITY_ERROR = 8,
|
||||
MODBUS_EXCEPTION_GATEWAY_PATH_UNAVAILABLE = 10,
|
||||
MODBUS_EXCEPTION_GATEWAY_TARGET_DEV_NOT_RESPONDING = 11
|
||||
};
|
||||
|
||||
enum eModbusModes
|
||||
{
|
||||
MODBUS_MASTER_MODE,
|
||||
MODBUS_SLAVE_MODE,
|
||||
MODBUS_INVALID_MODE
|
||||
};
|
||||
|
||||
class CModbusException
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
class CModbusPDU
|
||||
{
|
||||
public:
|
||||
qint8 mFunctionCode;
|
||||
QByteArray mData;
|
||||
};
|
||||
|
||||
class CModbusHeader
|
||||
{
|
||||
public:
|
||||
qint16 mTransactionID;
|
||||
qint16 mProtocolID;
|
||||
qint16 mMessageLength;
|
||||
qint8 mUnitID;
|
||||
};
|
||||
|
||||
class CModbusTransaction
|
||||
{
|
||||
public:
|
||||
CModbusHeader mHeader;
|
||||
CModbusPDU mPDU;
|
||||
};
|
||||
|
||||
class CModbusRequest : public CModbusTransaction
|
||||
{
|
||||
public:
|
||||
CModbusRequest();
|
||||
~CModbusRequest();
|
||||
int mRetries;
|
||||
QTimer *mRequestTimer;
|
||||
quint16 mStartAddress, mNbRegisters; //For convinience...
|
||||
};
|
||||
|
||||
class CModbusBackend : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
|
||||
private:
|
||||
enum eModbusMasterSMStates
|
||||
{
|
||||
MODBUS_SM_WAIT_FOR__STATE
|
||||
};
|
||||
|
||||
enum eModbusSlaveSMStates
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
CModbusBackend(CModbusRepository *Repo);
|
||||
virtual ~CModbusBackend();
|
||||
QTcpSocket *mModbusTCPSocketHandle;
|
||||
CModbusRepository *mModbusRepo;
|
||||
|
||||
bool mDataLinkValid;
|
||||
int mModbusMode;
|
||||
qint8 mDeviceID;
|
||||
void ModbusLinkDisconnected();
|
||||
void SetDeviceID(qint8 ID){mDeviceID = ID;}
|
||||
|
||||
//Master (client)
|
||||
int SendReadHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount);
|
||||
int SendWriteHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount);
|
||||
int SendWriteSingleRegisterRequest(quint16 Address);
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length) = 0;
|
||||
|
||||
//Master Exception
|
||||
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
//Slave Exception
|
||||
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
//Slave (server)
|
||||
int AnalyzeModbusRequest(CModbusTransaction Transaction);
|
||||
int ModbusStateMachine(int Event, QByteArray Data);
|
||||
int SendModbusResponse(CModbusTransaction RequestTransaction, QByteArray Data);
|
||||
int SendErrorResponse(CModbusTransaction RequestTransaction, quint8 ErrorCode);
|
||||
|
||||
//Master (client)
|
||||
QList<CModbusRequest*> mRequestsList;
|
||||
int SendModbusRequest(CModbusRequest *Request);
|
||||
quint16 GetNewTransactionID();
|
||||
int AnalyzeModbusResponse(CModbusTransaction Transaction);
|
||||
|
||||
quint16 mTransactionIDCounter;
|
||||
int mModbusRequestTimeout;
|
||||
int mModbusMaxRetry;
|
||||
|
||||
signals:
|
||||
|
||||
// void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length);
|
||||
|
||||
// //Master signals
|
||||
// void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
//// //Slave signals
|
||||
// void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
void ModbusDataReady();
|
||||
|
||||
void RequestTimerExpired();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const CModbusHeader &source);
|
||||
QDataStream &operator>>(QDataStream &in, CModbusHeader &dest);
|
||||
|
||||
#endif // CMODBUSBACKEND_H
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef PROTOCOLDEFS_H
|
||||
#define PROTOCOLDEFS_H
|
||||
|
||||
|
||||
|
||||
//ZT - CC modbus table masks
|
||||
|
||||
|
||||
//Flags definitions for HR2000
|
||||
#define ZT1_PP_INT_FLAG_MASK_1 0x0001
|
||||
#define ZT1_PP_INT_FLAG_MASK_2 0x0002
|
||||
#define ZT1_PP_INT_FLAG_MASK_3 0x0004
|
||||
#define ZT1_PP_INT_FLAG_MASK_4 0x0008
|
||||
#define ZT1_PP_EXT_FLAG_MASK_1 0x0010
|
||||
#define ZT1_PP_EXT_FLAG_MASK_2 0x0020
|
||||
#define ZT1_PP_EXT_FLAG_MASK_3 0x0040
|
||||
#define ZT1_PP_EXT_FLAG_MASK_4 0x0080
|
||||
#define ZT1_PG_FLAG_MASK_1 0x0100
|
||||
#define ZT1_PG_FLAG_MASK_2 0x0200
|
||||
#define ZT1_PG_FLAG_MASK_3 0x0400
|
||||
#define ZT1_PG_FLAG_MASK_4 0x0800
|
||||
#define ZT1_FN_FLAG_MASK_1 0x1000
|
||||
#define ZT1_FN_FLAG_MASK_2 0x2000
|
||||
#define ZT1_FN_FLAG_MASK_3 0x4000
|
||||
#define ZT1_FN_FLAG_MASK_4 0x8000
|
||||
|
||||
//Flags definitions for HR2017
|
||||
#define ZT2_PP_INT_FLAG_MASK_1 0x0001
|
||||
#define ZT2_PP_INT_FLAG_MASK_2 0x0002
|
||||
#define ZT2_PP_INT_FLAG_MASK_3 0x0004
|
||||
#define ZT2_PP_INT_FLAG_MASK_4 0x0008
|
||||
#define ZT2_PP_EXT_FLAG_MASK_1 0x0010
|
||||
#define ZT2_PP_EXT_FLAG_MASK_2 0x0020
|
||||
#define ZT2_PP_EXT_FLAG_MASK_3 0x0040
|
||||
#define ZT2_PP_EXT_FLAG_MASK_4 0x0080
|
||||
|
||||
//Flags definitions for HR2026
|
||||
#define ZT1_V00_ALARM_FLAG_MASK 0x0001
|
||||
#define ZT1_PEQ1_ALARM_FLAG_MASK 0x0002
|
||||
#define ZT1_ALARM_ITI_FLAG_MASK 0x8000
|
||||
#define ZT2_V02_ALARM_FLAG_MASK 0x0004
|
||||
#define ZT2_PEQ2_ALARM_FLAG_MASK 0x0008
|
||||
|
||||
|
||||
|
||||
//Register addressing
|
||||
//Outgoing
|
||||
#define MODBUS_ZT_DATA_BASE_REG 2000
|
||||
#define MODBUS_ZT_TABLE_DATA_SIZE 28 //Taille de la table = 28 registres
|
||||
|
||||
#define MODBUS_ZT1_ALARM_DATA_BASE_REG_ADD 2000
|
||||
#define MODBUS_ZT2_ALARM_DATA_BASE_REG_ADD 2017
|
||||
#define MODBUS_MISC_DATA_BASE_REG_ADD 2026
|
||||
#define MODBUS_ZT_WATCHDOG_REG_ADD 2027
|
||||
|
||||
#define MODBUS_ZT1_ALARM_RANKS_BASE_ADD 2001
|
||||
#define MODBUS_ZT1_RANK_PP_INT_1_REG_ADD 2001
|
||||
#define MODBUS_ZT1_RANK_PP_INT_2_REG_ADD 2002
|
||||
#define MODBUS_ZT1_RANK_PP_INT_3_REG_ADD 2003
|
||||
#define MODBUS_ZT1_RANK_PP_INT_4_REG_ADD 2004
|
||||
#define MODBUS_ZT1_RANK_PP_EXT_1_REG_ADD 2005
|
||||
#define MODBUS_ZT1_RANK_PP_EXT_2_REG_ADD 2006
|
||||
#define MODBUS_ZT1_RANK_PP_EXT_3_REG_ADD 2007
|
||||
#define MODBUS_ZT1_RANK_PP_EXT_4_REG_ADD 2008
|
||||
#define MODBUS_ZT1_RANK_PG_1_REG_ADD 2009
|
||||
#define MODBUS_ZT1_RANK_PG_2_REG_ADD 2010
|
||||
#define MODBUS_ZT1_RANK_PG_3_REG_ADD 2011
|
||||
#define MODBUS_ZT1_RANK_PG_4_REG_ADD 2012
|
||||
#define MODBUS_ZT1_RANK_FN_1_REG_ADD 2013
|
||||
#define MODBUS_ZT1_RANK_FN_2_REG_ADD 2014
|
||||
#define MODBUS_ZT1_RANK_FN_3_REG_ADD 2015
|
||||
#define MODBUS_ZT1_RANK_FN_4_REG_ADD 2016
|
||||
|
||||
#define MODBUS_ZT2_ALARM_RANKS_BASE_ADD 2018
|
||||
#define MODBUS_ZT2_RANK_PP_INT_1_REG_ADD 2018
|
||||
#define MODBUS_ZT2_RANK_PP_INT_2_REG_ADD 2019
|
||||
#define MODBUS_ZT2_RANK_PP_INT_3_REG_ADD 2020
|
||||
#define MODBUS_ZT2_RANK_PP_INT_4_REG_ADD 2021
|
||||
#define MODBUS_ZT2_RANK_PP_EXT_1_REG_ADD 2022
|
||||
#define MODBUS_ZT2_RANK_PP_EXT_2_REG_ADD 2023
|
||||
#define MODBUS_ZT2_RANK_PP_EXT_3_REG_ADD 2024
|
||||
#define MODBUS_ZT2_RANK_PP_EXT_4_REG_ADD 2025
|
||||
|
||||
|
||||
|
||||
//Incoming
|
||||
#define MODBUS_CC_ZTC_ZT1_FLAG_MASK 0x0001
|
||||
#define MODBUS_CC_ZTC_ZT2_FLAG_MASK 0x0002
|
||||
#define MODBUS_CC_FCYCLE_ZT1_FLAG_MASK 0x0004
|
||||
#define MODBUS_CC_FCYCLE_ZT2_FLAG_MASK 0x0008
|
||||
|
||||
#define MODBUS_CC_DATA_BASE_REG_ADD 2028
|
||||
#define MODBUS_CC_TABLE_DATA_SIZE 13 //Taille de la table = 28 registres
|
||||
|
||||
|
||||
#define MODBUS_CC_WATCHDOG_BASE_REG_ADD 2028
|
||||
#define MODBUS_CC_AN_BASE_REG_ADD 2029
|
||||
#define MODBUS_CC_CLK_UPDATE_BASE_REG_ADD 2036
|
||||
#define MODUBS_CC_CLK_SEC_BASE_REG_ADD 2037
|
||||
#define MODUBS_CC_CLK_HR_MIN_BASE_REG_ADD 2038
|
||||
#define MODUBS_CC_CLK_MNT_DAY_BASE_REG_ADD 2039
|
||||
#define MODUBS_CC_CLK_YEAR_BASE_REG_ADD 2040
|
||||
|
||||
|
||||
#endif // PROTOCOLDEFS_H
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "ModbusCCMgr.h"
|
||||
#include "ZTLog.h"
|
||||
#include "EngLog.h"
|
||||
|
||||
|
||||
CModbusCCMgr::CModbusCCMgr(CModbusRepository *Repo, int ModbusPort, int DevID) :
|
||||
CModbusBackend(Repo)
|
||||
{
|
||||
mModbusServer = new QTcpServer();
|
||||
mDeviceID = DevID;
|
||||
mModbusPort = ModbusPort;
|
||||
|
||||
connect(mModbusServer,SIGNAL(newConnection()),this,SLOT(NewModbusConnection()));
|
||||
mModbusMode = MODBUS_SLAVE_MODE;
|
||||
}
|
||||
|
||||
CModbusCCMgr::~CModbusCCMgr()
|
||||
{
|
||||
delete mModbusServer;
|
||||
}
|
||||
|
||||
int CModbusCCMgr::StartModbusCCServer()
|
||||
{
|
||||
mModbusServer->listen(QHostAddress::Any,mModbusPort);
|
||||
CZTLog::instance()->AddLogString(QString("Serveur Modbus Commande Centralisée démarré sur le port %1").arg(mModbusPort),true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CModbusCCMgr::NewModbusConnection()
|
||||
{
|
||||
mModbusTCPSocketHandle = mModbusServer->nextPendingConnection();
|
||||
if(mModbusTCPSocketHandle != 0)
|
||||
{
|
||||
mDataLinkValid = true;
|
||||
connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady()));
|
||||
connect(mModbusTCPSocketHandle,SIGNAL(disconnected()),this,SLOT(ConnectionLost()));
|
||||
//qDebug("ModbusCC: Connection with CC established");
|
||||
CZTLog::instance()->AddLogString(QString("Connection Modbus avec la CC établie. IP[%1]").arg(mModbusTCPSocketHandle->peerAddress().toString()),true);
|
||||
|
||||
emit ModbusCCConnected();
|
||||
}
|
||||
}
|
||||
|
||||
void CModbusCCMgr::ConnectionLost()
|
||||
{
|
||||
ModbusLinkDisconnected();
|
||||
emit ModbusCCDisconnected();
|
||||
CZTLog::instance()->AddLogString(QString("Connection Modbus avec la CC rompue."),true);
|
||||
}
|
||||
|
||||
bool CModbusCCMgr::IsModbusConnected()
|
||||
{
|
||||
return mDataLinkValid;
|
||||
}
|
||||
|
||||
void CModbusCCMgr::RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length)
|
||||
{
|
||||
Q_UNUSED(StartAddress)
|
||||
Q_UNUSED(Length)
|
||||
emit RepoHasChanged();
|
||||
}
|
||||
|
||||
void CModbusCCMgr::ModbusRequestException(quint8 ExceptionCode, quint8 FctCode)
|
||||
{
|
||||
//qDebug("Modbus CC: Request exception occured. ExceptCode: [%d], FctCode: [%d]",ExceptionCode,FctCode);
|
||||
CEngLog::instance()->AddLogString(QString("Modbus CC: Exception de requête. ExceptionCode[%1], FctCode[%2]").arg(ExceptionCode).arg(FctCode));
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef CMODBUSSLAVE_H
|
||||
#define CMODBUSSLAVE_H
|
||||
|
||||
#include <QObject>
|
||||
#include "ModbusBackend.h"
|
||||
#include <QTcpServer>
|
||||
#include "ModbusRepository.h"
|
||||
|
||||
class CModbusCCMgr : public CModbusBackend
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CModbusCCMgr(CModbusRepository *Repo, int ModbusPort, int DevID);
|
||||
virtual ~CModbusCCMgr();
|
||||
|
||||
int StartModbusCCServer();
|
||||
bool IsModbusConnected();
|
||||
|
||||
|
||||
|
||||
virtual void RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length);
|
||||
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
private:
|
||||
QTcpServer *mModbusServer;
|
||||
int mModbusPort;
|
||||
|
||||
signals:
|
||||
void RepoHasChanged();
|
||||
void ModbusCCConnected();
|
||||
void ModbusCCDisconnected();
|
||||
|
||||
public slots:
|
||||
void NewModbusConnection();
|
||||
void ConnectionLost();
|
||||
};
|
||||
|
||||
#endif // CMODBUSSLAVE_H
|
||||
@@ -0,0 +1,94 @@
|
||||
#include "ModbusMaster.h"
|
||||
#include <QTcpSocket>
|
||||
#include "ModbusCCDefs.h"
|
||||
|
||||
CModbusMaster::CModbusMaster(CModbusRepository *Repo, int ModbusPort, int DevID):
|
||||
CModbusBackend(Repo)
|
||||
{
|
||||
// connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady()));
|
||||
mModbusMode = MODBUS_MASTER_MODE;
|
||||
mModbusPort = ModbusPort;
|
||||
mDeviceID = DevID;
|
||||
|
||||
mModbusTCPSocketHandle = new QTcpSocket();
|
||||
connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady()));
|
||||
connect(mModbusTCPSocketHandle,SIGNAL(disconnected()),this,SLOT(SocketDisconnected()));
|
||||
connect(mModbusTCPSocketHandle,SIGNAL(connected()),this,SLOT(SocketConnected()));
|
||||
}
|
||||
|
||||
CModbusMaster::~CModbusMaster()
|
||||
{
|
||||
if(mModbusTCPSocketHandle->state() != QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
mModbusTCPSocketHandle->disconnectFromHost();
|
||||
mModbusTCPSocketHandle->waitForDisconnected(1000);
|
||||
}
|
||||
delete mModbusTCPSocketHandle;
|
||||
}
|
||||
|
||||
int CModbusMaster::ConnectToSlave(QString SlaveIP, int SlavePort)
|
||||
{
|
||||
if(mModbusTCPSocketHandle->state() != QAbstractSocket::UnconnectedState)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
mModbusTCPSocketHandle->connectToHost(SlaveIP,SlavePort);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusMaster::DisconnectFromSlave()
|
||||
{
|
||||
if(mModbusTCPSocketHandle->state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
qDebug("Trying to disconnect a non connected socket");
|
||||
mModbusTCPSocketHandle->disconnectFromHost();
|
||||
return 0;
|
||||
}
|
||||
|
||||
qDebug("Requesting Disconnection...");
|
||||
mModbusTCPSocketHandle->disconnectFromHost();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CModbusMaster::SocketConnected()
|
||||
{
|
||||
emit ModbusMasterConnected(this);
|
||||
qDebug("Master: Connection established with slave");
|
||||
}
|
||||
|
||||
void CModbusMaster::SocketDisconnected()
|
||||
{
|
||||
ModbusLinkDisconnected();
|
||||
emit ModbusMasterDisconnected(this);
|
||||
}
|
||||
|
||||
int CModbusMaster::ReadModbusRegisters()
|
||||
{
|
||||
//return SendReadHoldingRegistersRequest(ZT_DATA_BASE_REGISTER_ADDRESS,4); //Read all 3 registers from ZT (2000 - 2003)
|
||||
}
|
||||
|
||||
|
||||
void CModbusMaster::RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length)
|
||||
{
|
||||
emit ModbusMasterRepositoryUpdated();
|
||||
qDebug("Database updated with ZT data...");
|
||||
}
|
||||
|
||||
void CModbusMaster::ModbusResponseException(quint8 ExceptionCode, quint8 FctCode)
|
||||
{
|
||||
qDebug("Modbus MASTER exception: code:%d Fct:%d",ExceptionCode,FctCode);
|
||||
}
|
||||
|
||||
int CModbusMaster::SendAN1ToZT()
|
||||
{
|
||||
//return SendWriteHoldingRegistersRequest(CC_AN1_REGISTER_ADDRESS,1);
|
||||
//return SendWriteSingleRegisterRequest(CC_AN1_REGISTER_ADDRESS);
|
||||
}
|
||||
|
||||
int CModbusMaster::SendAN2ToZT()
|
||||
{
|
||||
//return SendWriteHoldingRegistersRequest(CC_AN2_REGISTER_ADDRESS,1);
|
||||
//return SendWriteSingleRegisterRequest(CC_AN2_REGISTER_ADDRESS);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef CMODBUSMASTER_H
|
||||
#define CMODBUSMASTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "ModbusBackend.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class CModbusMaster : public CModbusBackend
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CModbusMaster(CModbusRepository *Repo, int ModbusPort, int DevID);
|
||||
~CModbusMaster();
|
||||
|
||||
int ConnectToSlave(QString SlaveIP, int SlavePort);
|
||||
int DisconnectFromSlave();
|
||||
int ReadModbusRegisters();
|
||||
int SendAN1ToZT();
|
||||
int SendAN2ToZT();
|
||||
|
||||
virtual void RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length);
|
||||
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
|
||||
|
||||
private:
|
||||
int mModbusPort;
|
||||
|
||||
signals:
|
||||
void ModbusMasterConnected(CModbusMaster *);
|
||||
void ModbusMasterDisconnected(CModbusMaster *);
|
||||
void ModbusMasterRepositoryUpdated();
|
||||
|
||||
public slots:
|
||||
void SocketConnected();
|
||||
void SocketDisconnected();
|
||||
};
|
||||
|
||||
#endif // CMODBUSMASTER_H
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "ModbusRepository.h"
|
||||
#include <QByteArray>
|
||||
#include <QBuffer>
|
||||
#include <QDataStream>
|
||||
#include "EngLog.h"
|
||||
|
||||
CModbusRepository::CModbusRepository()
|
||||
{
|
||||
}
|
||||
|
||||
int CModbusRepository::AddHRDataMap(quint16 StartAddress, quint16 Length)
|
||||
{
|
||||
mMutex.lockForWrite();
|
||||
for(int i= 0; i < mHoldingRegisters.size(); i++)
|
||||
{
|
||||
if((StartAddress >= mHoldingRegisters.at(i).mStartAddress && StartAddress <= mHoldingRegisters.at(i).mEndAddress) ||
|
||||
(StartAddress + Length - 1 >= mHoldingRegisters.at(i).mStartAddress && StartAddress + Length - 1 <= mHoldingRegisters.at(i).mEndAddress))
|
||||
{
|
||||
mMutex.unlock();
|
||||
return RET_ERROR; //The data map overlaps an existing map.
|
||||
}
|
||||
}
|
||||
|
||||
CHRDataMap NewHRMap(StartAddress,Length);
|
||||
|
||||
mHoldingRegisters.append(NewHRMap);
|
||||
mMutex.unlock();
|
||||
|
||||
CEngLog::instance()->AddLogString(QString("Création d'une zone registre modbus à l'adresse: %1 de taille %2").arg(StartAddress).arg(Length));
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
bool CModbusRepository::IsHRValid(quint16 StartAddress, quint16 Length, int *index)
|
||||
{
|
||||
mMutex.lockForRead();
|
||||
for(int i= 0; i < mHoldingRegisters.size(); i++)
|
||||
{
|
||||
if((StartAddress >= mHoldingRegisters.at(i).mStartAddress && StartAddress + Length - 1 <= mHoldingRegisters.at(i).mEndAddress))
|
||||
{
|
||||
if(index != 0)
|
||||
{
|
||||
*index = i;
|
||||
}
|
||||
mMutex.unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mMutex.unlock();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray CModbusRepository::GetHRData(quint16 StartAddress, quint16 Length, bool *OK)
|
||||
{
|
||||
QByteArray Data;
|
||||
int RegisterIndex = 0;
|
||||
|
||||
if(IsHRValid(StartAddress,Length, &RegisterIndex) == false)
|
||||
{
|
||||
if(OK != 0)
|
||||
{
|
||||
*OK = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutex.lockForRead();
|
||||
int DataIndex = StartAddress - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
for(int i = 0; i < Length; i++)
|
||||
{
|
||||
quint16 CurReg = mHoldingRegisters.at(RegisterIndex).mRegistersData.at(DataIndex++);
|
||||
quint8 HighByte, LowByte;
|
||||
|
||||
LowByte = CurReg & 0x00FF;
|
||||
HighByte = (CurReg >> 8) & 0x00FF;
|
||||
Data.append(HighByte);
|
||||
Data.append(LowByte);
|
||||
}
|
||||
mMutex.unlock();
|
||||
|
||||
if(OK != 0)
|
||||
*OK = true;
|
||||
}
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
int CModbusRepository::WriteHRData(quint16 StartAddress, quint16 Length, QByteArray Data)
|
||||
{
|
||||
int RegisterIndex;
|
||||
|
||||
if(IsHRValid(StartAddress,Length, &RegisterIndex) == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
if(Length*2 != Data.size())
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
mMutex.lockForWrite();
|
||||
int DataIndex = StartAddress - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
|
||||
for(int i = 0; i < Length; i++)
|
||||
{
|
||||
quint8 HighByte = Data.at(i*2);
|
||||
quint8 LowByte = Data.at(i*2 + 1);
|
||||
qint16 Word = HighByte;
|
||||
Word <<= 8;
|
||||
Word += LowByte;
|
||||
Word = Word &0xFFFF;
|
||||
|
||||
mHoldingRegisters[RegisterIndex].mRegistersData[DataIndex++] = Word;
|
||||
}
|
||||
mMutex.unlock();
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusRepository::WriteSingleReg(quint16 Address, quint16 Value)
|
||||
{
|
||||
int RegisterIndex;
|
||||
|
||||
if(IsHRValid(Address,1, &RegisterIndex) == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
mMutex.lockForWrite();
|
||||
int DataIndex = Address - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
mHoldingRegisters[RegisterIndex].mRegistersData[DataIndex] = Value;
|
||||
mMutex.unlock();
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusRepository::WriteMultipleRegs(quint16 StartAddress, QList<qint16> Data)
|
||||
{
|
||||
int RegisterIndex;
|
||||
|
||||
if(IsHRValid(StartAddress,Data.size(), &RegisterIndex) == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
mMutex.lockForWrite();
|
||||
int DataIndex = StartAddress - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
for(int i = 0; i < Data.size(); i++)
|
||||
{
|
||||
mHoldingRegisters[RegisterIndex].mRegistersData[DataIndex++] = Data.at(i);
|
||||
}
|
||||
mMutex.unlock();
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
QList<qint16> CModbusRepository::GetRegs(quint16 StartAddress, quint16 Length, bool *OK)
|
||||
{
|
||||
int RegisterIndex;
|
||||
|
||||
if(IsHRValid(StartAddress,Length, &RegisterIndex) == false)
|
||||
{
|
||||
if(OK != 0)
|
||||
{
|
||||
*OK = false;
|
||||
}
|
||||
return QList<qint16>();
|
||||
}
|
||||
|
||||
if(OK != 0)
|
||||
{
|
||||
*OK = true;
|
||||
}
|
||||
|
||||
int DataIndex = StartAddress - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
return mHoldingRegisters[RegisterIndex].mRegistersData.mid(DataIndex,Length);
|
||||
}
|
||||
quint16 CModbusRepository::GetSingleReg(quint16 Address, bool *OK)
|
||||
{
|
||||
int RegisterIndex;
|
||||
|
||||
if(IsHRValid(Address,1, &RegisterIndex) == false)
|
||||
{
|
||||
if(OK != 0)
|
||||
*OK = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(OK != 0)
|
||||
*OK = true;
|
||||
|
||||
mMutex.lockForRead();
|
||||
int DataIndex = Address - mHoldingRegisters.at(RegisterIndex).mStartAddress;
|
||||
quint16 Data = mHoldingRegisters[RegisterIndex].mRegistersData[DataIndex];
|
||||
mMutex.unlock();
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
CHRDataMap::CHRDataMap(quint16 StartAddress, quint16 Length)
|
||||
{
|
||||
mStartAddress = StartAddress;
|
||||
mLength = Length;
|
||||
for(int i = 0; i < Length; i++)
|
||||
{
|
||||
mRegistersData.append(0);
|
||||
}
|
||||
mEndAddress = StartAddress + Length - 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef MODBUSREPOSITORY_H
|
||||
#define MODBUSREPOSITORY_H
|
||||
#include "GlobalDefine.h"
|
||||
#include <QList>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
class CHRDataMap ///Holding Register data map.
|
||||
{
|
||||
public:
|
||||
CHRDataMap(quint16 StartAddress, quint16 Length);
|
||||
quint16 mStartAddress,mEndAddress;
|
||||
quint16 mLength;
|
||||
QList<qint16> mRegistersData;
|
||||
|
||||
};
|
||||
|
||||
class CModbusRepository
|
||||
{
|
||||
public:
|
||||
CModbusRepository();
|
||||
|
||||
//Holding Registers
|
||||
int AddHRDataMap(quint16 StartAddress, quint16 Length);
|
||||
bool IsHRValid(quint16 StartAddress, quint16 Length, int *index = 0);
|
||||
QByteArray GetHRData(quint16 StartAddress, quint16 Length, bool *OK = 0);
|
||||
quint16 GetSingleReg(quint16 Address, bool *OK = 0);
|
||||
QList<qint16> GetRegs(quint16 StartAddress, quint16 Length, bool *OK = 0);
|
||||
int WriteHRData(quint16 StartAddress, quint16 Length, QByteArray Data);
|
||||
int WriteSingleReg(quint16 Address, quint16 Value);
|
||||
int WriteMultipleRegs(quint16 StartAddress, QList<qint16> Data);
|
||||
|
||||
private:
|
||||
QList<CHRDataMap> mHoldingRegisters;
|
||||
QReadWriteLock mMutex;
|
||||
|
||||
};
|
||||
|
||||
#endif // MODBUSREPOSITORY_H
|
||||
@@ -0,0 +1,655 @@
|
||||
#include "ModbusTKTransport.h"
|
||||
#include "ZTData.h"
|
||||
#include "ZTLog.h"
|
||||
#include "EngLog.h"
|
||||
|
||||
|
||||
CModbusTKTransport::CModbusTKTransport(CModbusRepository *Repo)
|
||||
{
|
||||
mModbusRepo = Repo;
|
||||
mZT1CDVState = mZT2CDVState = false;
|
||||
mMaintenanceMode = mForceZT1Clear = mForceZT2Clear = false;
|
||||
mZT1TKDataList.clear();
|
||||
mZT2TKDataList.clear();
|
||||
|
||||
mModbusTKZT1SMState = MODBUS_ZT1_TK_STANDBY_STATE;
|
||||
mModbusTKZT2SMState = MODBUS_ZT2_TK_STANDBY_STATE;
|
||||
|
||||
mZT1TKStateMachineTimer = new QTimer();
|
||||
mZT1TKStateMachineTimer->setSingleShot(false);
|
||||
mZT1TKStateMachineTimer->setInterval(0);
|
||||
connect(mZT1TKStateMachineTimer,SIGNAL(timeout()),this,SLOT(ExecZT1SM()));
|
||||
|
||||
mZT2TKStateMachineTimer = new QTimer();
|
||||
mZT2TKStateMachineTimer->setSingleShot(false);
|
||||
mZT2TKStateMachineTimer->setInterval(0);
|
||||
connect(mZT2TKStateMachineTimer,SIGNAL(timeout()),this,SLOT(ExecZT2SM()));
|
||||
}
|
||||
|
||||
CModbusTKTransport::~CModbusTKTransport()
|
||||
{
|
||||
delete mZT1TKStateMachineTimer;
|
||||
delete mZT2TKStateMachineTimer;
|
||||
}
|
||||
|
||||
int CModbusTKTransport::ClearTK(int ZT)
|
||||
{
|
||||
|
||||
if(ZT == ZT1_TYPE_ID)
|
||||
{
|
||||
//Fill ZT1 alarm regs with 0.
|
||||
QList<qint16> Data;
|
||||
for(int i = 0; i <= 16; i++) //17 registers (1 flags reg + 16 ranks regs)
|
||||
{
|
||||
Data.append(0);
|
||||
}
|
||||
|
||||
//Clear pannes & itineraire flags
|
||||
bool OK = false;
|
||||
quint16 PannesReg = mModbusRepo->GetSingleReg(MODBUS_MISC_DATA_BASE_REG_ADD,&OK);
|
||||
|
||||
if(OK == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
PannesReg ^= ZT1_V00_ALARM_FLAG_MASK;
|
||||
PannesReg ^= ZT1_PEQ1_ALARM_FLAG_MASK;
|
||||
PannesReg ^= ZT1_ALARM_ITI_FLAG_MASK;
|
||||
|
||||
//Clear repo now...
|
||||
mModbusRepo->WriteMultipleRegs(MODBUS_ZT1_ALARM_DATA_BASE_REG_ADD,Data);
|
||||
mModbusRepo->WriteSingleReg(MODBUS_MISC_DATA_BASE_REG_ADD,PannesReg);
|
||||
|
||||
|
||||
}
|
||||
else if(ZT == ZT2_TYPE_ID)
|
||||
{
|
||||
//Fill ZT2 alarm regs with 0.
|
||||
QList<qint16> Data;
|
||||
for(int i = 0; i <= 8; i++) //9 registers (1 flags reg + 8 ranks regs)
|
||||
{
|
||||
Data.append(0);
|
||||
}
|
||||
|
||||
//Clear pannes
|
||||
bool OK = false;
|
||||
quint16 PannesReg = mModbusRepo->GetSingleReg(MODBUS_MISC_DATA_BASE_REG_ADD,&OK);
|
||||
|
||||
if(OK == false)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
PannesReg ^= ZT2_V02_ALARM_FLAG_MASK;
|
||||
PannesReg ^= ZT2_PEQ2_ALARM_FLAG_MASK;
|
||||
|
||||
//Clear repo now...
|
||||
mModbusRepo->WriteMultipleRegs(MODBUS_ZT2_ALARM_DATA_BASE_REG_ADD,Data);
|
||||
mModbusRepo->WriteSingleReg(MODBUS_MISC_DATA_BASE_REG_ADD,PannesReg);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CModbusTKTransport::SendTKToCC(int ZT)
|
||||
{
|
||||
if(ZT == ZT1_TYPE_ID)
|
||||
{
|
||||
int PPIntIndex = 0, PPExtIndex = 0, FNIndex = 0, PGIndex = 0;
|
||||
qint16 FlagsReg = 0;
|
||||
qint16 PannesReg;
|
||||
|
||||
QList<qint16> DataBuf;
|
||||
|
||||
//Get a local buffer of the repo...
|
||||
bool OK;
|
||||
DataBuf = mModbusRepo->GetRegs(MODBUS_ZT_DATA_BASE_REG,MODBUS_ZT_TABLE_DATA_SIZE,&OK);
|
||||
if(OK == false)
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() ZT1 -> Lecture repository invalide.");
|
||||
}
|
||||
|
||||
PannesReg = DataBuf.at(RegOffset(MODBUS_MISC_DATA_BASE_REG_ADD));
|
||||
|
||||
for(int i = 0; i < mZT1TKDataList.size(); i++)
|
||||
{
|
||||
CZTDetectionData TKData = mZT1TKDataList.at(i);
|
||||
|
||||
switch(TKData.mDetectionID)
|
||||
{
|
||||
case DETECTION_MAGNETIC_SENSOR_COUNT:
|
||||
{
|
||||
PannesReg |= ZT1_V00_ALARM_FLAG_MASK;
|
||||
break;
|
||||
}
|
||||
case DETECTION_FN_DETECTION:
|
||||
{
|
||||
if(FNIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT1_FN_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_FN_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(FNIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT1_FN_FLAG_MASK_2;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_FN_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(FNIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT1_FN_FLAG_MASK_3;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_FN_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(FNIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT1_FN_FLAG_MASK_4;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_FN_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> FNIndex > 3");
|
||||
}
|
||||
FNIndex++;
|
||||
break;
|
||||
}
|
||||
case DETECTION_PG_DETECTION:
|
||||
{
|
||||
if(PGIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT1_PG_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PG_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PGIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT1_PG_FLAG_MASK_2;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PG_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PGIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT1_PG_FLAG_MASK_3;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PG_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PGIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT1_PG_FLAG_MASK_4;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PG_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> PGIndex > 3");
|
||||
}
|
||||
PGIndex++;
|
||||
break;
|
||||
}
|
||||
case DETECTION_PPI_DETECTION:
|
||||
{
|
||||
if(PPIntIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_INT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_INT_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_INT_FLAG_MASK_2;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_INT_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_INT_FLAG_MASK_3;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_INT_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_INT_FLAG_MASK_4;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_INT_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> PPIntIndex ZT1 > 3");
|
||||
}
|
||||
PPIntIndex++;
|
||||
break;
|
||||
}
|
||||
case DETECTION_PPE_DETECTION:
|
||||
{
|
||||
if(PPExtIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT1_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> PPExtIndex ZT1 > 3");
|
||||
}
|
||||
PPExtIndex++;
|
||||
break;
|
||||
}
|
||||
case DETECTION_PEQ1_DETECTION:
|
||||
{
|
||||
PannesReg |= ZT1_PEQ1_ALARM_FLAG_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update the modbus repo to send the alarms...
|
||||
DataBuf[RegOffset(MODBUS_ZT1_ALARM_DATA_BASE_REG_ADD)] = FlagsReg;
|
||||
DataBuf[RegOffset(MODBUS_MISC_DATA_BASE_REG_ADD)] = PannesReg;
|
||||
mModbusRepo->WriteMultipleRegs(MODBUS_ZT_DATA_BASE_REG,DataBuf);
|
||||
|
||||
}
|
||||
else if(ZT == ZT2_TYPE_ID)
|
||||
{
|
||||
int PPIntIndex = 0, PPExtIndex = 0;
|
||||
qint16 FlagsReg = 0;
|
||||
qint16 PannesReg;
|
||||
|
||||
QList<qint16> DataBuf;
|
||||
|
||||
//Get a local buffer of the repo...
|
||||
bool OK;
|
||||
DataBuf = mModbusRepo->GetRegs(MODBUS_ZT_DATA_BASE_REG,MODBUS_ZT_TABLE_DATA_SIZE,&OK);
|
||||
if(OK == false)
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() ZT2 -> Lecture repository invalide.");
|
||||
}
|
||||
|
||||
PannesReg = DataBuf.at(RegOffset(MODBUS_MISC_DATA_BASE_REG_ADD));
|
||||
|
||||
for(int i = 0; i < mZT1TKDataList.size(); i++)
|
||||
{
|
||||
CZTDetectionData TKData = mZT1TKDataList.at(i);
|
||||
|
||||
switch(TKData.mDetectionID)
|
||||
{
|
||||
|
||||
case DETECTION_PEQ2_DETECTION:
|
||||
{
|
||||
PannesReg |= ZT2_PEQ2_ALARM_FLAG_MASK;
|
||||
break;
|
||||
}
|
||||
case DETECTION_ZT2_MAGNETIC_SENSOR_COUNT:
|
||||
{
|
||||
PannesReg |= ZT2_V02_ALARM_FLAG_MASK;
|
||||
break;
|
||||
}
|
||||
case DETECTION_ZT2_PPI_DETECTION:
|
||||
{
|
||||
if(PPIntIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_INT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_INT_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_INT_FLAG_MASK_2;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_INT_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_INT_FLAG_MASK_3;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_INT_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPIntIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_INT_FLAG_MASK_4;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_INT_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> PPIntIndex ZT2 > 3");
|
||||
}
|
||||
PPIntIndex++;
|
||||
break;
|
||||
}
|
||||
case DETECTION_ZT2_PPE_DETECTION:
|
||||
{
|
||||
if(PPExtIndex == 0)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_1_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 1)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_2_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 2)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_3_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else if(PPExtIndex == 3)
|
||||
{
|
||||
FlagsReg |= ZT2_PP_EXT_FLAG_MASK_1;
|
||||
DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_4_REG_ADD)] = (qint16)TKData.mRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> PPExtIndex ZT2 > 3");
|
||||
}
|
||||
PPExtIndex++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update the modbus repo to send the alarms...
|
||||
DataBuf[RegOffset(MODBUS_ZT2_ALARM_RANKS_BASE_ADD)] = FlagsReg;
|
||||
DataBuf[RegOffset(MODBUS_MISC_DATA_BASE_REG_ADD)] = PannesReg;
|
||||
mModbusRepo->WriteMultipleRegs(MODBUS_ZT_DATA_BASE_REG,DataBuf);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CEngLog::instance()->AddLogString("Erreur de logique. ModbusTkTransport::SendTKToCC() -> Index de ZT invalide!!!");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool CModbusTKTransport::IsZT2TKProcessing()
|
||||
{
|
||||
if(mModbusTKZT2SMState != MODBUS_ZT2_TK_STANDBY_STATE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CModbusTKTransport::IsZT1TKProcessing()
|
||||
{
|
||||
if(mModbusTKZT1SMState != MODBUS_ZT1_TK_STANDBY_STATE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CModbusTKTransport::IsTKProcessing()
|
||||
{
|
||||
if(IsZT1TKProcessing() || IsZT2TKProcessing())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CModbusTKTransport::AddNewZT1Detection(CZTDetectionData Detection)
|
||||
{
|
||||
mZT1TKDataList.append(Detection);
|
||||
return RET_OK;
|
||||
}
|
||||
int CModbusTKTransport::AddNewZT2Detection(CZTDetectionData Detection)
|
||||
{
|
||||
mZT2TKDataList.append(Detection);
|
||||
return RET_OK;
|
||||
}
|
||||
unsigned int CModbusTKTransport::BeginTKEmission()
|
||||
{
|
||||
|
||||
if(mZT1TKDataList.size() > 0)
|
||||
{
|
||||
if(GetDetectionConfig()->mZTDetectionConfig[DETECTION_FCT_ZT1].TKActive == false)
|
||||
{
|
||||
mZT1TKDataList.clear();
|
||||
}
|
||||
else if(mModbusTKZT1SMState == MODBUS_ZT1_TK_STANDBY_STATE)
|
||||
{
|
||||
mModbusTKZT1SMState = MODBUS_ZT1_TK_SHOW_STATE;
|
||||
mZT1TKStateMachineTimer->start(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(mZT2TKDataList.size() > 0)
|
||||
{
|
||||
if(GetDetectionConfig()->mZTDetectionConfig[DETECTION_FCT_ZT2].TKActive == false)
|
||||
{
|
||||
mZT2TKDataList.clear();
|
||||
}
|
||||
else if(mModbusTKZT2SMState == MODBUS_ZT2_TK_STANDBY_STATE)
|
||||
{
|
||||
mModbusTKZT2SMState = MODBUS_ZT2_TK_SHOW_STATE;
|
||||
mZT2TKStateMachineTimer->start(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
unsigned int CModbusTKTransport::SetInputStates(bool AN1State, bool ZT1CDVState, bool AN2State, bool ZT2CDVState)
|
||||
{
|
||||
Q_UNUSED(AN2State)
|
||||
Q_UNUSED(AN1State)
|
||||
|
||||
mZT1CDVState = ZT1CDVState;
|
||||
mZT2CDVState = ZT2CDVState;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
unsigned int CModbusTKTransport::CancelAllTK()
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
unsigned int CModbusTKTransport::CancelMaintenanceCurrentTK()
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
unsigned int CModbusTKTransport::ExitMaintenance()
|
||||
{
|
||||
mMaintenanceMode = false;
|
||||
mForceZT1Clear = false;
|
||||
mForceZT2Clear = false;
|
||||
CancelAllTK();
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
unsigned int CModbusTKTransport::EnterMaintenance()
|
||||
{
|
||||
if(IsTKProcessing())
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
CancelAllTK();
|
||||
mMaintenanceMode = true;
|
||||
mForceZT1Clear = false;
|
||||
mForceZT2Clear = false;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CModbusTKTransport::ExecZT1SM()
|
||||
{
|
||||
switch(mModbusTKZT1SMState)
|
||||
{
|
||||
case MODBUS_ZT1_TK_SHOW_STATE:
|
||||
{
|
||||
|
||||
SendTKToCC(ZT1_TYPE_ID); //Mise à jour de la table Modbus avec les données des alarmes actives.
|
||||
|
||||
mModbusTKZT1SMState = MODBUS_ZT1_TK_WAIT_FOR_CLEAR_STATE;
|
||||
|
||||
CZTLog::instance()->AddLogString("Émission des alarmes PCC",true);
|
||||
for(int i = 0; i < mZT1TKDataList.size(); i++)
|
||||
{
|
||||
LogTK(mZT1TKDataList.at(i));
|
||||
}
|
||||
|
||||
if(mMaintenanceMode)
|
||||
{
|
||||
emit TKOutputStatesChanged(true,false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_ZT1_TK_WAIT_FOR_CLEAR_STATE:
|
||||
{
|
||||
if(mZT1Clear == true || (mMaintenanceMode == true && mForceZT1Clear == true))
|
||||
{
|
||||
ClearTK(ZT1_TYPE_ID); //Remise à zéro des données d'alarmes dans la table modbus.
|
||||
|
||||
mModbusTKZT1SMState = MODBUS_ZT1_TK_STANDBY_STATE;
|
||||
|
||||
if(mMaintenanceMode == true)
|
||||
{
|
||||
if(mForceZT1Clear == true)
|
||||
{
|
||||
mForceZT1Clear = false;
|
||||
CZTLog::instance()->AddLogString("Acquitement manuel de la TK ZT1",true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CZTLog::instance()->AddLogString("Acquitement ZTC ou FCYCLE détectée",true);
|
||||
}
|
||||
|
||||
emit TKOutputStatesChanged(false,false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CZTLog::instance()->AddLogString("Acquitement ZTC ou FCYCLE détectée",true);
|
||||
}
|
||||
}
|
||||
else if(mZT1CDVState == false && mMaintenanceMode == false)
|
||||
{
|
||||
//The train has left... clear the alarms...
|
||||
CZTLog::instance()->AddLogString("Libération du CDV de quai ZT1. Acquitement automatique des alarmes ZT1 au PCC",true);
|
||||
ClearTK(ZT1_TYPE_ID);
|
||||
mModbusTKZT1SMState = MODBUS_ZT1_TK_STANDBY_STATE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_ZT1_TK_STANDBY_STATE:
|
||||
{
|
||||
mZT1TKDataList.clear();
|
||||
mZT1TKStateMachineTimer->stop();
|
||||
|
||||
//In maintenance mode, it is possible to have ZT2 events at the same time
|
||||
//than ZT1. So if any ZT2 events are waiting in the qeue, send them...
|
||||
if(mMaintenanceMode)
|
||||
{
|
||||
if(mZT2TKDataList.size() > 0)
|
||||
{
|
||||
BeginTKEmission();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CModbusTKTransport::ExecZT2SM()
|
||||
{
|
||||
switch(mModbusTKZT2SMState)
|
||||
{
|
||||
case MODBUS_ZT2_TK_SHOW_STATE:
|
||||
{
|
||||
|
||||
SendTKToCC(ZT2_TYPE_ID); //Mise à jour de la table Modbus avec les données des alarmes actives.
|
||||
|
||||
mModbusTKZT1SMState = MODBUS_ZT2_TK_WAIT_FOR_CLEAR_STATE;
|
||||
|
||||
CZTLog::instance()->AddLogString("Émission des alarmes PCC",true);
|
||||
for(int i = 0; i < mZT2TKDataList.size(); i++)
|
||||
{
|
||||
LogTK(mZT2TKDataList.at(i));
|
||||
}
|
||||
|
||||
if(mMaintenanceMode)
|
||||
{
|
||||
emit TKOutputStatesChanged(false,true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MODBUS_ZT2_TK_WAIT_FOR_CLEAR_STATE:
|
||||
{
|
||||
if(mZT2Clear == true || (mMaintenanceMode == true && mForceZT2Clear == true))
|
||||
{
|
||||
ClearTK(ZT2_TYPE_ID); //Remise à zéro des données d'alarmes dans la table modbus.
|
||||
|
||||
mModbusTKZT2SMState = MODBUS_ZT2_TK_STANDBY_STATE;
|
||||
|
||||
if(mMaintenanceMode == true)
|
||||
{
|
||||
if(mForceZT2Clear == true)
|
||||
{
|
||||
mForceZT2Clear = false;
|
||||
CZTLog::instance()->AddLogString("Acquitement manuel de la TK ZT2",true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CZTLog::instance()->AddLogString("Acquitement ZTC ou FCYCLE détectée",true);
|
||||
}
|
||||
|
||||
emit TKOutputStatesChanged(false,false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CZTLog::instance()->AddLogString("Acquitement ZTC ou FCYCLE détectée",true);
|
||||
}
|
||||
}
|
||||
else if(mZT2CDVState == false && mMaintenanceMode == false)
|
||||
{
|
||||
//The train has left... clear the alarms...
|
||||
CZTLog::instance()->AddLogString("Libération du CDV de quai ZT2. Acquitement automatique des alarmes ZT2 au PCC",true);
|
||||
ClearTK(ZT2_TYPE_ID);
|
||||
mModbusTKZT1SMState = MODBUS_ZT2_TK_STANDBY_STATE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_ZT2_TK_STANDBY_STATE:
|
||||
{
|
||||
mZT2TKDataList.clear();
|
||||
mZT2TKStateMachineTimer->stop();
|
||||
|
||||
//In maintenance mode, it is possible to have ZT1 events at the same time
|
||||
//than ZT2. So if any ZT1 events are waiting in the qeue, send them...
|
||||
if(mMaintenanceMode)
|
||||
{
|
||||
if(mZT1TKDataList.size() > 0)
|
||||
{
|
||||
BeginTKEmission();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CModbusTKTransport::ModbusCCUpdated()
|
||||
{
|
||||
qint16 ClearReg = mModbusRepo->GetSingleReg(MODBUS_CC_AN_BASE_REG_ADD);
|
||||
mZT1Clear = (ClearReg & (MODBUS_CC_FCYCLE_ZT1_FLAG_MASK | MODBUS_CC_ZTC_ZT1_FLAG_MASK)) != 0;
|
||||
mZT2Clear = (ClearReg & (MODBUS_CC_FCYCLE_ZT2_FLAG_MASK | MODBUS_CC_ZTC_ZT2_FLAG_MASK)) != 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef MODBUSTKTRANSPORT_H
|
||||
#define MODBUSTKTRANSPORT_H
|
||||
|
||||
#include "TKTransportInterface.h"
|
||||
#include "ModbusRepository.h"
|
||||
#include <QTimer>
|
||||
#include "ModbusCCDefs.h"
|
||||
|
||||
|
||||
class CModbusTKTransport : public CTKTransportInterface
|
||||
{
|
||||
public:
|
||||
enum eModbusTKSMStates
|
||||
{
|
||||
MODBUS_ZT1_TK_STANDBY_STATE,
|
||||
MODBUS_ZT1_TK_SHOW_STATE,
|
||||
MODBUS_ZT1_TK_WAIT_FOR_CLEAR_STATE,
|
||||
|
||||
MODBUS_ZT2_TK_STANDBY_STATE,
|
||||
MODBUS_ZT2_TK_SHOW_STATE,
|
||||
MODBUS_ZT2_TK_WAIT_FOR_CLEAR_STATE
|
||||
};
|
||||
|
||||
|
||||
|
||||
CModbusTKTransport(CModbusRepository *Repo);
|
||||
~CModbusTKTransport();
|
||||
|
||||
|
||||
int SendTKToCC(int ZT);
|
||||
int ClearTK(int ZT);
|
||||
|
||||
virtual bool IsZT2TKProcessing();
|
||||
virtual bool IsZT1TKProcessing();
|
||||
virtual bool IsTKProcessing();
|
||||
virtual int AddNewZT1Detection(CZTDetectionData Detection);
|
||||
virtual int AddNewZT2Detection(CZTDetectionData Detection);
|
||||
virtual unsigned int BeginTKEmission();
|
||||
virtual unsigned int SetInputStates(bool AN1State, bool ZT1CDVState, bool AN2State, bool ZT2CDVState);
|
||||
|
||||
virtual unsigned int CancelAllTK();
|
||||
virtual unsigned int CancelMaintenanceCurrentTK();
|
||||
virtual unsigned int ExitMaintenance();
|
||||
virtual unsigned int EnterMaintenance();
|
||||
|
||||
private:
|
||||
CModbusRepository *mModbusRepo;
|
||||
QList<CZTDetectionData> mZT1TKDataList,mZT2TKDataList;
|
||||
bool mZT1CDVState, mZT2CDVState;
|
||||
bool mMaintenanceMode, mForceZT1Clear, mForceZT2Clear;
|
||||
int mModbusTKZT1SMState,mModbusTKZT2SMState;
|
||||
QTimer *mZT1TKStateMachineTimer, *mZT2TKStateMachineTimer;
|
||||
bool mZT1Clear, mZT2Clear;
|
||||
|
||||
int RegOffset(qint16 Reg){return (int)Reg-MODBUS_ZT_DATA_BASE_REG;}
|
||||
|
||||
public slots:
|
||||
void ExecZT1SM();
|
||||
void ExecZT2SM();
|
||||
void ModbusCCUpdated();
|
||||
};
|
||||
|
||||
#endif // MODBUSTKTRANSPORT_H
|
||||
Reference in New Issue
Block a user