Modbus dev...

This commit is contained in:
jfmartel 2019-10-02 14:13:14 -04:00
parent 9ef96c5db5
commit 8f046e4223
7 changed files with 138 additions and 18 deletions

View File

@ -70,7 +70,7 @@
#define USE_NETWORKING
#define TCP_SERVER_PORT 1234
#define CUSTOM_KERNEL_INSTALLED //Custom kernel with modified serial.c to disable hardware FIFO.
#define COMPILE_MODBUS_TEST_MODE //Utilisé seulement pour les tests d'intégration Modbus.
//#define COMPILE_MODBUS_TEST_MODE //Utilisé seulement pour les tests d'intégration Modbus.
//Debug defs

View File

@ -350,8 +350,8 @@ int CModbusBackend::AnalyzeModbusResponse(CModbusTransaction Transaction)
QByteArray RegisterValues = Transaction.mPDU.mData.right(ByteCount);
qDebug("Master Rx Read Holding Registers Response.");
qDebug("Data: %s",RegisterValues.toHex().data());
// 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);
@ -374,8 +374,10 @@ int CModbusBackend::AnalyzeModbusResponse(CModbusTransaction Transaction)
delete Request;
return RET_ERROR;
}
qDebug("Master Rx Write Single Register response. Address: %d,",RegAddress);
qDebug("Data: %s",Transaction.mPDU.mData.toHex().data());
// qDebug("Master Rx Write Single Register response. Address: %d,",RegAddress);
// qDebug("Data: %s",Transaction.mPDU.mData.toHex().data());
ModbusWriteSingleRegsSuccess();
//Everything seems good.
@ -405,6 +407,7 @@ int CModbusBackend::AnalyzeModbusResponse(CModbusTransaction Transaction)
// qDebug("Master Rx Write Multiple Registers response. Address: %d, Nb Reg: %d",StartAdress, NbRegisters);
// qDebug("Data: %s",Transaction.mPDU.mData.toHex().data());
ModbusWriteMultipleRegsSuccess();
//All is good.
@ -414,7 +417,8 @@ int CModbusBackend::AnalyzeModbusResponse(CModbusTransaction Transaction)
{
//Received "Illegal function code" response
//TODO: Log this.
qDebug("Master received illegal function code 0x%x",Transaction.mPDU.mFunctionCode);
CEngLog::instance()->AddLogString(QString().sprintf("Modbus Maître, réception d'un code de fonction illégal: 0x%x",Transaction.mPDU.mFunctionCode));
// qDebug("Master received illegal function code 0x%x",Transaction.mPDU.mFunctionCode);
emit ModbusResponseException(MODBUS_EXCEPTION_ILLEGAL_FCT,MODBUS_FCT_WRITE_MULTIPLE_REGISTERS);
break;
}
@ -483,7 +487,7 @@ int CModbusBackend::SendReadHoldingRegistersRequest(quint16 StartAddress, quint1
//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");
CEngLog::instance()->AddLogString("ModbusBackend: Tentative de lecture d'un registre hors de portée.");
return RET_ERROR;
}
@ -647,12 +651,12 @@ void CModbusBackend::RequestTimerExpired()
{
//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);
// CZTLog::instance()->AddLogString("Modbus Maître: Nombre maximal de tentatives sans réponse atteint avec le partenaire",true);
delete mRequestsList[i];
mRequestsList.removeAt(i);
ModbusRequestMaxRetryReached();
//TODO: Manage this situation (log?)
@ -734,3 +738,18 @@ void CModbusBackend::ModbusRequestException(quint8 ExceptionCode, quint8 FctCode
Q_UNUSED(FctCode)
CEngLog::instance()->AddLogString("ModbusResponseException called from within master object... weird stuff!");
}
void CModbusBackend::ModbusWriteMultipleRegsSuccess()
{
qDebug("Weird! Default implementation of ModbusWriteMultipleRegsSuccess() called in CModbusBackend. This function should be reimplemented in the ModbusMaster child class");
}
void CModbusBackend::ModbusWriteSingleRegsSuccess()
{
qDebug("Weird! Default implementation of ModbusWriteSingleRegsSuccess() called in CModbusBackend. This function should be reimplemented in the ModbusMaster child class");
}
void CModbusBackend::ModbusRequestMaxRetryReached()
{
qDebug("Weird! Default implementation of ModbusRequestMaxRetryReached() called in CModbusBackend. This function should be reimplemented in the ModbusMaster child class");
}

View File

@ -137,16 +137,21 @@ public:
virtual void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length) = 0; //Fonction virtuelle à être implémentée par le parent
virtual void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length) = 0; //Fonction virtuelle à être implémentée par la classe dérivée
//Appelée lorsque de nouvelles données ont été reçues du réseau Modbus et écrites dans le registre
virtual void ModbusWriteMultipleRegsSuccess(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée suite à la réception d'une réponse à une requête d'écriture multiple.
virtual void ModbusWriteSingleRegsSuccess(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée suite à la réception d'une réponse à une requête d'écriture simple.
virtual void ModbusRequestMaxRetryReached(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée lors de l'atteinte du nombre maximal d'essai de transmission d'une requête.
//Master Exception
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par le parent
//Sert à informer le parent lorsqu'une exception se produit dans la communication Modbus (réponse)
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode) = 0; //Fonction virtuelle à être implémentée par la classe dérivée
//Sert à informer la classe dérivée lorsqu'une exception se produit dans la communication Modbus (réponse)
//Slave Exception
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par le parent
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode) = 0; //Fonction virtuelle à être implémentée par la classe dérivée
//Sert à informer le parent lorsqu'une exception se produit dans la communication Modbus (requête)

View File

@ -10,7 +10,9 @@
#define SEI_MODBUS_ZT_WATCHDOG_REG 2027
#define SEI_MODBUS_SEI_WATCHDOG_REG 2038
#define SEI_MODBUS_SEI_WATCHDOG_MASK 0x0001
#define SEI_MODBUS_SEI_ALARMS_RESET_REG 2037
#define SEI_MODBUS_SEI_ZT1_ALARM_RESET_MASK 0X0001
#define SEI_MODBUS_SEI_ZT2_ALARM_RESET_MASK 0X0002

View File

@ -25,9 +25,18 @@ CModbusSEIMgr::CModbusSEIMgr(CModbusRepository *SEIRepo, CModbusRepository *CCRe
mSEIModbusUpdateTimer = new QTimer();
mSEIModbusUpdateTimer->setInterval(1000);
mSEIModbusUpdateTimer->setSingleShot(false);
mSEIModbusUpdateTimer->setSingleShot(true);
mSEIModbusUpdateTimer->stop();
mSEIWatchdogTimer = new QTimer();
mSEIWatchdogTimer->setInterval(SEI_MODBUS_WATCHDOG_TIMEOUT);
mSEIWatchdogTimer->setSingleShot(true);
mSEIWatchdogTimer->stop();
mSEILinkState = false;
mSEIWatchdogState = 0;
mModbusTCPSocketHandle = new QTcpSocket();
connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady()));
@ -35,6 +44,7 @@ CModbusSEIMgr::CModbusSEIMgr(CModbusRepository *SEIRepo, CModbusRepository *CCRe
connect(mModbusTCPSocketHandle,SIGNAL(connected()),this,SLOT(SocketConnected()));
connect(mConnectionTimer,SIGNAL(timeout()),this,SLOT(ConnectionTimerExpired()));
connect(mSEIModbusUpdateTimer,SIGNAL(timeout()),this,SLOT(SEIModbusUpdateTimerExpired()));
connect(mSEIWatchdogTimer,SIGNAL(timeout()),this,SLOT(SEIModbusWatchdogtimerExpired()));
}
CModbusSEIMgr::~CModbusSEIMgr()
@ -50,6 +60,8 @@ CModbusSEIMgr::~CModbusSEIMgr()
delete mConnectionTimer;
if(mSEIModbusUpdateTimer)
delete mSEIModbusUpdateTimer;
if(mSEIWatchdogTimer)
delete mSEIWatchdogTimer;
}
int CModbusSEIMgr::StartSEICommunication()
@ -85,16 +97,18 @@ void CModbusSEIMgr::SocketConnected()
CZTLog::instance()->AddLogString("Connection Modbus (Ethernet) avec NetTrac établi",true);
mConnectionTimer->stop();
mSEIModbusUpdateTimer->start();
mSEIWatchdogTimer->start(SEI_MODBUS_WATCHDOG_TIMEOUT*2); //allow twice the time for the first watchdog to come in
}
void CModbusSEIMgr::SocketDisconnected()
{
ModbusLinkDisconnected();
emit ModbusMasterDisconnected();
emit SEIModbusLinkLost();
mConnectionTimer->start();
mSEIModbusUpdateTimer->stop();
// qDebug("Disconnected from NetTrac");
// CZTLog::instance()->AddLogString("Connexion avec NetTrac établi",true);
mSEILinkState = false;
mSEIWatchdogState = 0xBEEF;
CZTLog::instance()->AddLogString("Connection Modbus (Ethernet) avec NetTrac rompue",true);
}
@ -133,6 +147,13 @@ int CModbusSEIMgr::SEISettingsChanged(QHostAddress ServerIP, int ModbusPort, int
}
void CModbusSEIMgr::SEIModbusUpdateTimerExpired()
{
//Read the SEI data...
SendReadHoldingRegistersRequest(SEI_MODBUS_SEI_DATA_BASE_REG,SEI_MODBUS_SEI_TABLE_DATA_SIZE);
}
int CModbusSEIMgr::SendZTRegistersToSEI()
{
//The SEI Modbus table is updated on event, triggered by the TKTransport object (see ZTTKUpdated()).
//Just update the watchdog and send the current table.
@ -149,6 +170,7 @@ void CModbusSEIMgr::SEIModbusUpdateTimerExpired()
SendWriteHoldingRegistersRequest(SEI_MODBUS_ZT_DATA_BASE_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE);
return RET_OK;
}
@ -175,11 +197,42 @@ void CModbusSEIMgr::ZTTKUpdated()
}
void CModbusSEIMgr::SEIModbusWatchdogtimerExpired()
{
CZTLog::instance()->AddLogString("Perte du lien de communication avec la NetTrac: Watchdog NetTrac Expiré",true);
emit SEIModbusLinkLost();
mSEILinkState = false;
// mSEIWatchdogState = 0;
}
void CModbusSEIMgr::RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length)
{
Q_UNUSED(StartAddress)
Q_UNUSED(Length)
qint16 WD = mModbusRepo->GetSingleReg(SEI_MODBUS_SEI_WATCHDOG_REG);
WD = (WD & SEI_MODBUS_SEI_WATCHDOG_MASK);
// qDebug("WD = %d",WD);
if(WD != mSEIWatchdogState)
{
mSEIWatchdogTimer->start(SEI_MODBUS_WATCHDOG_TIMEOUT); //The watchdog has toggled. Kick the timer.
mSEIWatchdogState = WD;
if(mSEILinkState == false)
{
mSEILinkState = true;
emit SEIModbusLinkRecovered();
CZTLog::instance()->AddLogString("Lien de communication (Watchdog) avec NetTrac rétabli",true);
}
}
if(mSEILinkState == true) //only consider data when link is healthy
{
}
SendZTRegistersToSEI();
emit ModbusMasterRepositoryUpdated();
}
@ -187,3 +240,28 @@ void CModbusSEIMgr::ModbusResponseException(quint8 ExceptionCode, quint8 FctCode
{
qDebug("Modbus MASTER exception: code:%d Fct:%d",ExceptionCode,FctCode);
}
void CModbusSEIMgr::ModbusWriteMultipleRegsSuccess()
{
if(mModbusTCPSocketHandle->state() == QAbstractSocket::ConnectedState)
{
mSEIModbusUpdateTimer->start();
}
}
void CModbusSEIMgr::ModbusWriteSingleRegsSuccess()
{
if(mModbusTCPSocketHandle->state() == QAbstractSocket::ConnectedState)
{
mSEIModbusUpdateTimer->start();
}
}
void CModbusSEIMgr::ModbusRequestMaxRetryReached()
{
//The server did not respond to last request... Retry...
if(mModbusTCPSocketHandle->state() == QAbstractSocket::ConnectedState)
{
mSEIModbusUpdateTimer->start();
}
}

View File

@ -8,7 +8,7 @@
#include <QElapsedTimer>
#include <QHostAddress>
#define SEI_MODBUS_WATCHDOG_TIMEOUT 7000 //ms
class CModbusSEIMgr : public CModbusBackend
@ -23,13 +23,17 @@ public:
int ReadModbusRegisters();
int StartSEICommunication();
int SEISettingsChanged(QHostAddress ServerIP, int ModbusPort, int DevID);
int SendZTRegistersToSEI();
virtual void RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length);
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
virtual void ModbusWriteMultipleRegsSuccess();
virtual void ModbusWriteSingleRegsSuccess();
virtual void ModbusRequestMaxRetryReached();
QTimer *mConnectionTimer;
// QTimer *mSEIWatchdogTimer;
QTimer *mSEIWatchdogTimer;
QTimer *mSEIModbusUpdateTimer;
private:
@ -37,11 +41,19 @@ private:
QHostAddress mSEIIPAddress;
CModbusRepository *mCCRepoHandle;
bool mZTWatchdog;
bool mSEILinkState;
int mSEIWatchdogState;
signals:
void ModbusMasterConnected(qint32 LocalIP, qint32 RemoteIP);
void ModbusMasterDisconnected();
void ModbusMasterRepositoryUpdated();
void SEIModbusLinkLost();
void SEIModbusLinkRecovered();
public slots:
void SocketConnected();
@ -49,6 +61,8 @@ public slots:
void ConnectionTimerExpired();
void SEIModbusUpdateTimerExpired();
void ZTTKUpdated();
void SEIModbusWatchdogtimerExpired();
};
#endif // CMODBUSSEIMGR_H

View File

@ -606,6 +606,8 @@ unsigned int CZoneTest::InitZT()
connect(mModbusSEIMgr,SIGNAL(ModbusMasterConnected(qint32,qint32)),panel.mSEISettingsPage,SLOT(ModbusSEIConnected(qint32,qint32)));
connect(mModbusSEIMgr,SIGNAL(ModbusMasterDisconnected()),panel.mSEISettingsPage,SLOT(ModbusSEIDisconnected()));
connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkLost()),panel.mSEISettingsPage,SLOT(ModbusSEILinkDown()));
connect(mModbusSEIMgr,SIGNAL(SEIModbusLinkRecovered()),panel.mSEISettingsPage,SLOT(ModbusSEILinkUP()));
panel.mZTMainPage->ModbusSEIDisconnected();