ZT/sources/Modbus/ModbusCCMgr.cpp
zonetest 0efe9b3e8d Développement Modbus CC (suite)
- Implémentation des stats de ZT1 et ZT2 (compo et type de train)
provenant de Modbus CC.
- Implémentation de l'inhibition ZT1 et ZT2 par la CC via Modbus.
- Dégradation des données Modbus lors de la perte du Watchdog SACL.
2017-08-30 11:03:53 -04:00

344 lines
10 KiB
C++

#include "ModbusCCMgr.h"
#include "ZTLog.h"
#include "EngLog.h"
#include "ModbusCCDefs.h"
#include <QDateTime>
#include "ZTData.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;
mZTWatchdogTimer = new QTimer;
mZTWatchdogTimer->setSingleShot(false);
mZTWatchdogTimer->setInterval(MODBUS_ZT_WATCHDOG_TIMEOUT);
connect(mZTWatchdogTimer,SIGNAL(timeout()),this,SLOT(ModbusZTWatchdogTimeout()));
mCCWatchdogTimer = new QTimer;
mCCWatchdogTimer->setSingleShot(true);
mCCWatchdogTimer->setInterval(MODBUS_CC_WATCHDOG_TIMEOUT);
connect(mCCWatchdogTimer,SIGNAL(timeout()),this,SLOT(ModbusCCWatchdogTimeout()));
mZTWatchdog = 0;
mCCWatchdogState = 0;
mCCLinkState = false;
mLastDateTime = 0;
}
CModbusCCMgr::~CModbusCCMgr()
{
delete mModbusServer;
delete mZTWatchdogTimer;
delete mCCWatchdogTimer;
}
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);
mZTWatchdogTimer->start();
mCCWatchdogTimer->start(MODBUS_CC_WATCHDOG_TIMEOUT*2); //Allow twice the time for the first watchdog reset.
mCCLinkState = true;
emit ModbusCCConnected();
}
}
void CModbusCCMgr::ConnectionLost()
{
ModbusLinkDisconnected();
mZTWatchdogTimer->stop();
mCCWatchdogTimer->stop();
emit ModbusCCDisconnected();
ResetCCRepository();
CZTLog::instance()->AddLogString(QString("Connection Modbus (Ethernet) avec la CC rompue."),true);
}
bool CModbusCCMgr::IsModbusConnected()
{
return mDataLinkValid;
}
void CModbusCCMgr::RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length)
{
Q_UNUSED(StartAddress)
Q_UNUSED(Length)
qint16 WD = mModbusRepo->GetSingleReg(MODBUS_CC_WATCHDOG_BASE_REG_ADD);
// qDebug("WD = %d",WD);
if(WD != mCCWatchdogState)
{
mCCWatchdogTimer->start(MODBUS_CC_WATCHDOG_TIMEOUT); //The watchdog has toggled. Kick the timer.
mCCWatchdogState = WD;
if(mCCLinkState == false)
{
mCCLinkState = true;
CZTLog::instance()->AddLogString("Lien de communication (Watchdog) avec la CC rétabli",true);
}
}
if(mCCLinkState == true) //Ignore incoming data if the link is not healty (Watchdog).
{
qint16 NTPWrite = mModbusRepo->GetSingleReg(MODBUS_CC_CLK_UPDATE_BASE_REG_ADD);
if(NTPWrite == 1)
{
//Update date & time...
bool OK;
QList<qint16> DateTime = mModbusRepo->GetRegs(MODUBS_CC_CLK_SEC_BASE_REG_ADD,4,&OK);
if(OK)
{
qint8 Secs, Minutes, Hours, Month, Day;
Secs = (qint8)(DateTime.at(0) >> 8);
Minutes = (qint8)(DateTime.at(1) & 0x00FF);
Hours = (qint8)(DateTime.at(1) >> 8);
Day = (qint8)(DateTime.at(2) & 0x00FF);
Month = (qint8)(DateTime.at(2) >> 8);
qint16 Year = DateTime.at(3);
QDateTime NetworkTime;
NetworkTime.setTimeSpec(Qt::UTC);
NetworkTime.setDate(QDate(Year,Month,Day));
NetworkTime.setTime(QTime(Hours,Minutes,Secs));
// QDateTime MyTime = NetworkTime.toLocalTime();
if(mLastDateTime != 0)
{
delete mLastDateTime;
}
mLastDateTime = new QDateTime(NetworkTime.toLocalTime());
emit ModbusDateTimeReceived(mLastDateTime);
qDebug("Date & Heure reçue du SACL: %s",mLastDateTime->toString("yyyy-MM-dd hh:mm:ss").toAscii().data());
mModbusRepo->WriteSingleReg(MODBUS_CC_CLK_UPDATE_BASE_REG_ADD,0);
}
}
}
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));
}
void CModbusCCMgr::ModbusCCWatchdogTimeout()
{
CZTLog::instance()->AddLogString("Perte du lien de communication avec la CC: Watchdog CC Expiré",true);
ResetCCRepository();
mCCLinkState = false;
}
void CModbusCCMgr::ModbusZTWatchdogTimeout()
{
qint16 WD = mZTWatchdog;
mModbusRepo->WriteSingleReg(MODBUS_ZT_WATCHDOG_REG_ADD,WD);
if(mZTWatchdog == 1)
{
mZTWatchdog = 0;
}
else
{
mZTWatchdog = 1;
}
}
int CModbusCCMgr::ResetCCRepository()
{
//Clear read registers
mModbusRepo->WriteSingleReg(MODBUS_CC_WATCHDOG_BASE_REG_ADD,0);
mModbusRepo->WriteSingleReg(MODBUS_CC_AN_BASE_REG_ADD,0);
mModbusRepo->WriteSingleReg(MODBUS_CC_ZT1_TRAIN_TYPE_REG_ADD, MODBUS_CC_TRAIN_TYPE_INVALID_SACL_OFFLINE);
mModbusRepo->WriteSingleReg(MODBUS_CC_ZT2_TRAIN_TYPE_REG_ADD, MODBUS_CC_TRAIN_TYPE_INVALID_SACL_OFFLINE);
QList<qint16> ResetValues;
ResetValues << 0 << 0 << 0 //Train compo ZT1
<< 0 << 0 << 0 //Train compo ZT2
<< 0 << 0 << 0 << 0 << 0; //Date & Time update registers
mModbusRepo->WriteMultipleRegs(MODBUS_CC_ZT1_TRAIN_ID_1_REG_ADD,ResetValues);
//Do not clear the TK (write) regisers, they will clear themselves when needed.
return RET_OK;
}
bool CModbusCCMgr::GetZT1InhibitionFlag()
{
bool OK = false;
if(mCCLinkState == false)//Ignore registers data if link is with SACL is not healthy
{
return false;
}
qint16 Reg = mModbusRepo->GetSingleReg(MODBUS_CC_AN_BASE_REG_ADD,&OK);
if(OK)
{
if((Reg & MODBUS_CC_INHIBIT_ZT1_FLAG_MASK) != 0)
{
return true;
}
}
return false;
}
bool CModbusCCMgr::GetZT2InhibitionFlag()
{
bool OK = false;
if(mCCLinkState == false)//Ignore registers data if link is with SACL is not healthy
{
return false;
}
qint16 Reg = mModbusRepo->GetSingleReg(MODBUS_CC_AN_BASE_REG_ADD,&OK);
if(OK)
{
if((Reg & MODBUS_CC_INHIBIT_ZT2_FLAG_MASK) != 0)
{
return true;
}
}
return false;
}
QList<qint16> CModbusCCMgr::GetZT1TrainComposition()
{
bool OK = false;
QList<qint16> Compo;
Compo = mModbusRepo->GetRegs(MODBUS_CC_ZT1_TRAIN_ID_1_REG_ADD,3,&OK);
if(OK == false || mCCLinkState == false) //Ignore registers data if link is with SACL is not healthy
{
Compo << 0 << 0 << 0;
}
return Compo;
}
QList<qint16> CModbusCCMgr::GetZT2TrainComposition()
{
bool OK = false;
QList<qint16> Compo;
Compo = mModbusRepo->GetRegs(MODBUS_CC_ZT2_TRAIN_ID_1_REG_ADD,3,&OK);
if(OK == false || mCCLinkState == false)//Ignore registers data if link is with SACL is not healthy
{
Compo << 0 << 0 << 0;
}
return Compo;
}
qint16 CModbusCCMgr::GetZT1TrainType()
{
bool OK = false;
qint16 Reg = mModbusRepo->GetSingleReg(MODBUS_CC_ZT1_TRAIN_TYPE_REG_ADD,&OK);
int Type = TRAIN_TYPE_UNKNOWN;
if(OK)
{
if(Reg == MODBUS_CC_TRAIN_TYPE_MR63)
{
Type = TRAIN_TYPE_MR63;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MR73)
{
Type = TRAIN_TYPE_MR73;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MPM10)
{
Type = TRAIN_TYPE_MPM10;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MAINTENANCE)
{
Type = TRAIN_TYPE_MAINTENANCE_VEHICLE;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_INVALID_SACL_OFFLINE)
{
Type = TRAIN_TYPE_UNKNOWN;
}
else
{
CEngLog::instance()->AddLogString(QString("MODBUS: Réception d'un type de train ZT1 invalide du SACL [%1]").arg(Reg));
Type = TRAIN_TYPE_UNKNOWN;
}
}
if(mCCLinkState == false)//Ignore registers data if link is with SACL is not healthy
{
Type = TRAIN_TYPE_UNKNOWN;
}
return Type;
}
qint16 CModbusCCMgr::GetZT2TrainType()
{
bool OK = false;
qint16 Reg = mModbusRepo->GetSingleReg(MODBUS_CC_ZT2_TRAIN_TYPE_REG_ADD,&OK);
int Type = TRAIN_TYPE_UNKNOWN;
if(OK)
{
if(Reg == MODBUS_CC_TRAIN_TYPE_MR63)
{
Type = TRAIN_TYPE_MR63;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MR73)
{
Type = TRAIN_TYPE_MR73;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MPM10)
{
Type = TRAIN_TYPE_MPM10;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_MAINTENANCE)
{
Type = TRAIN_TYPE_MAINTENANCE_VEHICLE;
}
else if(Reg == MODBUS_CC_TRAIN_TYPE_INVALID_SACL_OFFLINE)
{
Type = TRAIN_TYPE_UNKNOWN;
}
else
{
CEngLog::instance()->AddLogString(QString("MODBUS: Réception d'un type de train ZT2 invalide du SACL [%1]").arg(Reg));
Type = TRAIN_TYPE_UNKNOWN;
}
}
if(mCCLinkState == false) //Ignore registers data if link is with SACL is not healthy
{
Type = TRAIN_TYPE_UNKNOWN;
}
return Type;
}