#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(); mZT1Clear = mZT2Clear = false; 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())); ResetAlarmCount(ZTGLOBAL_TYPE_ID); } CModbusTKTransport::~CModbusTKTransport() { delete mZT1TKStateMachineTimer; delete mZT2TKStateMachineTimer; } int CModbusTKTransport::ClearTK(int ZT) { if(ZT == ZT1_TYPE_ID) { //Fill ZT1 alarm regs with 0. QList 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 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 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_2; DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_2_REG_ADD)] = (qint16)TKData.mRank; } else if(PPExtIndex == 2) { FlagsReg |= ZT1_PP_EXT_FLAG_MASK_3; DataBuf[RegOffset(MODBUS_ZT1_RANK_PP_EXT_3_REG_ADD)] = (qint16)TKData.mRank; } else if(PPExtIndex == 3) { FlagsReg |= ZT1_PP_EXT_FLAG_MASK_4; 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 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 < mZT2TKDataList.size(); i++) { CZTDetectionData TKData = mZT2TKDataList.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_2; DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_2_REG_ADD)] = (qint16)TKData.mRank; } else if(PPExtIndex == 2) { FlagsReg |= ZT2_PP_EXT_FLAG_MASK_3; DataBuf[RegOffset(MODBUS_ZT2_RANK_PP_EXT_3_REG_ADD)] = (qint16)TKData.mRank; } else if(PPExtIndex == 3) { FlagsReg |= ZT2_PP_EXT_FLAG_MASK_4; 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_DATA_BASE_REG_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); } else if(mMaintenanceMode == true && mModbusTKZT1SMState == MODBUS_ZT1_TK_WAIT_FOR_CLEAR_STATE) { //When we are in maintenance mode and we are already sending the alarms, just add the new alarm to the modbus buffer. SendTKToCC(ZT1_TYPE_ID); } } 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); } else if(mMaintenanceMode == true && mModbusTKZT2SMState == MODBUS_ZT2_TK_WAIT_FOR_CLEAR_STATE) { //In maintenance mode, just add the new alarm to the modbus buffer. SendTKToCC(ZT2_TYPE_ID); } } 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() { ClearTK(ZT1_TYPE_ID); ClearTK(ZT2_TYPE_ID); mModbusTKZT1SMState = MODBUS_ZT1_TK_STANDBY_STATE; mModbusTKZT2SMState = MODBUS_ZT2_TK_STANDBY_STATE; mZT1TKDataList.clear(); mZT2TKDataList.clear(); //exec the SM once mZT1TKStateMachineTimer->start(); mZT2TKStateMachineTimer->start(); ResetAlarmCount(ZTGLOBAL_TYPE_ID); return RET_OK; } unsigned int CModbusTKTransport::CancelMaintenanceCurrentTK() { int ret = RET_ERROR; if(mMaintenanceMode == false) { return ret; } if(mModbusTKZT1SMState == MODBUS_ZT1_TK_WAIT_FOR_CLEAR_STATE) { mForceZT1Clear = true; ret = RET_OK; } if(mModbusTKZT2SMState == MODBUS_ZT2_TK_WAIT_FOR_CLEAR_STATE) { mForceZT2Clear = true; ret = RET_OK; } return ret; } 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(); ResetAlarmCount(ZT1_TYPE_ID); // //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. mModbusTKZT2SMState = 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 N+1 ZT2. Acquitement automatique des alarmes ZT2 au PCC",true); ClearTK(ZT2_TYPE_ID); mModbusTKZT2SMState = MODBUS_ZT2_TK_STANDBY_STATE; } break; } case MODBUS_ZT2_TK_STANDBY_STATE: { mZT2TKDataList.clear(); mZT2TKStateMachineTimer->stop(); ResetAlarmCount(ZT2_TYPE_ID); // //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)) != 0; mZT2Clear = (ClearReg & (MODBUS_CC_FCYCLE_ZT2_FLAG_MASK)) != 0; }