1865 lines
58 KiB
C++
1865 lines
58 KiB
C++
/*******************************************************************************
|
|
* *
|
|
* Société de Transports de Montréal. *
|
|
* 2012 *
|
|
* *
|
|
* Projet Zones Tests *
|
|
* *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
/*
|
|
Description:
|
|
Machine à état principale de la ZT. Elle lit les entrées des CDV et des CI
|
|
et démarre le thread d'analyse lorsqu'un train procède sur la ZT. La classe
|
|
gère aussi la compilation des déclenchements et des logs de passage.
|
|
|
|
*/
|
|
|
|
/* ************************************************************************** */
|
|
/* Revision:
|
|
### YYYMMDD JFM
|
|
Verision d'origine.
|
|
|
|
### YYYYMMDD Description du besoin ou du bug
|
|
Description du changement.
|
|
*/
|
|
|
|
/* ************************************************************************** */
|
|
|
|
#include "ZTStateMachine.h"
|
|
#include "ZTSimulator.h"
|
|
#include <QTextStream>
|
|
#include <QTextCodec>
|
|
#include <TrainLogFileMgr.h>
|
|
#include "ZTLog.h"
|
|
#include "math.h"
|
|
#include "MaintenancePage.h"
|
|
#include "RamMonitor.h"
|
|
//#include "ModbusCCDefs.h"
|
|
|
|
CZTStateMachine::CZTStateMachine(QObject *parent) :
|
|
QObject(parent)
|
|
{
|
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
|
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
mZT2State = ZT2_WAIT_FOR_CI_STATE;
|
|
mZTState = ZT_INIT_STATE;
|
|
mZT2Present = true;
|
|
|
|
// mZTDataPtr = new CZTData;
|
|
mZTStationPtr = 0;
|
|
mZTDetectionConfig = 0;
|
|
|
|
mLastInputs = 0;
|
|
mZtSimPtr = 0;
|
|
mLogMgr = 0;
|
|
mCalibrationPassagesCount = 0;
|
|
mModbusCCMgr = 0;
|
|
//mExtIOInterface = 0;
|
|
|
|
mNbPassages = 0;
|
|
mNbTriggers = 0;
|
|
// mZT1Active = false; //JFM ztstatus
|
|
// mZT2Active = false;
|
|
mZT1ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZT2ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
|
|
mCIZT1Active = false;
|
|
|
|
mLogDelay = ZT_SM_DEFAULT_LOG_DELAY;
|
|
|
|
mAutoExportZT1CSV = false;
|
|
mAutoExportZT2CSV = false;
|
|
|
|
//mTKGenerator = new CTKGenerator();
|
|
|
|
mIsPGCalibON = false;
|
|
mIsMaintenanceModeON = false;
|
|
|
|
//Create the ZT1 train analysis thread
|
|
mZT1SMThread = new QThread;
|
|
mZT1WorkerThread = new CZT1AnalysisThread();
|
|
mZT1WorkerThread->moveToThread(mZT1SMThread);
|
|
connect(mZT1SMThread,SIGNAL(started()),mZT1WorkerThread,SLOT(AnalyzeZT1Train()));
|
|
connect(mZT1WorkerThread,SIGNAL(ZT1DataUpdate(CZT1ThreadData*,bool,int)),this,SLOT(ZT1StateChanged(CZT1ThreadData*,bool,int)));
|
|
connect(mZT1WorkerThread,SIGNAL(DetectionTriggered(CZTDetectionData*)),this,SLOT(ZT1NewDetection(CZTDetectionData*)));
|
|
connect(mZT1WorkerThread,SIGNAL(NewPGCalibrationData(CZTPGCalibrationData*)),this,SLOT(NewPGCalibrationData(CZTPGCalibrationData*)));
|
|
connect(mZT1WorkerThread,SIGNAL(NewZT1Flag(int,CZT1FlagsData*)),this,SLOT(ZT1NewFlag(int,CZT1FlagsData*)));
|
|
connect(mZT1WorkerThread,SIGNAL(AddLogString(QString)),this,SLOT(AddLogStringFromThread(QString)));
|
|
|
|
//Create the ZT2 train analysis thread (even if the station has no ZT2... it doesn't hurt anyone)
|
|
mZT2SMThread = new QThread;
|
|
mZT2WorkerThread = new CZT2AnalysisThread();
|
|
mZT2WorkerThread->moveToThread(mZT2SMThread);
|
|
connect(mZT2SMThread,SIGNAL(started()),mZT2WorkerThread,SLOT(AnalyzeZT2Train()));
|
|
connect(mZT2WorkerThread,SIGNAL(ZT2DataUpdate(CZT2ThreadData*)),this,SLOT(ZT2StateChanged(CZT2ThreadData*)));
|
|
connect(mZT2WorkerThread,SIGNAL(DetectionTriggered(CZTDetectionData*)),this,SLOT(ZT2NewDetection(CZTDetectionData*)));
|
|
connect(mZT2WorkerThread,SIGNAL(AddLogString(QString)),this,SLOT(AddLogStringFromThread(QString)));
|
|
|
|
|
|
mZT1LogDelayTimer.start();
|
|
|
|
mTimeToForceSyncFS = false;
|
|
mFSSyncTimer.start();
|
|
}
|
|
|
|
CZTStateMachine::~CZTStateMachine()
|
|
{
|
|
mZT1SMThread->quit();
|
|
mZT1SMThread->wait(1000);
|
|
delete mZT1SMThread;
|
|
delete mZT1WorkerThread;
|
|
mZT2SMThread->quit();
|
|
mZT2SMThread->wait(1000);
|
|
delete mZT2SMThread;
|
|
delete mZT2WorkerThread;
|
|
|
|
//delete mTKGenerator;
|
|
|
|
DestroyZT1Log();
|
|
DestroyZT2Log();
|
|
DestroyCalibrationData();
|
|
}
|
|
|
|
unsigned int CZTStateMachine::ZTStateMachine(unsigned int Event, unsigned int SubEvent)
|
|
{
|
|
|
|
mCurInputs = mInputModule->GetInputs();
|
|
|
|
switch(mZTState)
|
|
{
|
|
case ZT_INIT_STATE:
|
|
{
|
|
//mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1Active,mZT2Active);
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
mZTStationPtr->UpdateStationMasks(mCurInputs);
|
|
mZTStationPtr->UpdateCDVs(mCurInputs);
|
|
|
|
//Wait for ZT1 and ZT2 CDVs to be free before starting the State Machine...
|
|
if(!mZTStationPtr->IsZT1CDVOccupied() && !mZTStationPtr->IsZT2CDVOccupied())
|
|
{
|
|
mZTState = ZT_EXECUTE_STATE;
|
|
}
|
|
else
|
|
{
|
|
mZTPagePTr->UpdateCDVDisplay();
|
|
if(mZtSimPtr != 0) //ptr will be 0 if not in sim mode
|
|
{
|
|
mZtSimPtr->UpdateSimulatorDisplay();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ZT_EXECUTE_STATE:
|
|
{
|
|
|
|
if(mCurInputs != mLastInputs)
|
|
{
|
|
//Update masks
|
|
mZTStationPtr->UpdateStationMasks(mCurInputs);
|
|
|
|
//Update variables according to new inputs
|
|
mZTStationPtr->UpdateCDVs(mCurInputs);
|
|
|
|
mCIZT1Active = ((mCurInputs & mZTInputMasks->InputZT1ITIMask) != 0);
|
|
mCIZT2Active = ((mCurInputs & mZTInputMasks->InputZT2ITIMask) != 0);
|
|
bool AN1State, AN2State;
|
|
|
|
//If the ModbusCCPtr pointer is not 0, then we are using Modbus and AN states will come from there.
|
|
if(mModbusCCMgr == 0)
|
|
{
|
|
AN1State = (mCurInputs & mZTInputMasks->InputZT1ANMask) != 0;
|
|
AN2State = (mCurInputs &mZTInputMasks->InputZT2ANMask) != 0;
|
|
}
|
|
mTKGenerator->SetInputStates(AN1State,mZTStationPtr->IsZT1AlarmAutoAcquireCDVOccupied(),
|
|
AN2State,mZTStationPtr->IsZT2AlarmAutoAcquireCDVOccupied());
|
|
}
|
|
|
|
|
|
if(mIsMaintenanceModeON == false)
|
|
{
|
|
ZT1StateMachine(Event,SubEvent);
|
|
|
|
if(mZT2Present) //if there is no ZT2, don't execute the ZT2 SM
|
|
{
|
|
ZT2StateMachine(Event,SubEvent);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Do the data acquisition for the PP detection while in maintenance mode.
|
|
unsigned int Inputs = mPCIIOPtr->GetInputs();
|
|
|
|
if((Inputs & mZTInputMasks->InputZT1PIMask) == 0)
|
|
{
|
|
if(mMaintenancePPIZT1Latch == false)
|
|
{
|
|
emit MaintenancePPActivated(MAINTENANCE_PPI_ZT1_ID);
|
|
SendTKToPCC(DETECTION_PPI_DETECTION, 27);
|
|
mMaintenancePPIZT1Latch = true;
|
|
}
|
|
}
|
|
|
|
if((Inputs & mZTInputMasks->InputZT1PEMask) == 0)
|
|
{
|
|
if(mMaintenancePPEZT1Latch == false)
|
|
{
|
|
SendTKToPCC(DETECTION_PPE_DETECTION, 18);
|
|
emit MaintenancePPActivated(MAINTENANCE_PPE_ZT1_ID);
|
|
mMaintenancePPEZT1Latch = true;
|
|
}
|
|
}
|
|
|
|
if(mZT2Present) //if there is no ZT2, don't check the pedals
|
|
{
|
|
if((Inputs & mZTInputMasks->InputZT2PIMask) == 0)
|
|
{
|
|
if(mMaintenancePPIZT2Latch == false)
|
|
{
|
|
SendTKToPCC(DETECTION_ZT2_PPI_DETECTION, 27);
|
|
emit MaintenancePPActivated(MAINTENANCE_PPI_ZT2_ID);
|
|
mMaintenancePPIZT2Latch = true;
|
|
}
|
|
}
|
|
|
|
if((Inputs & mZTInputMasks->InputZT2PEMask) == 0)
|
|
{
|
|
if(mMaintenancePPEZT2Latch == false)
|
|
{
|
|
SendTKToPCC(DETECTION_ZT2_PPE_DETECTION, 18);
|
|
emit MaintenancePPActivated(MAINTENANCE_PPE_ZT2_ID);
|
|
mMaintenancePPEZT2Latch = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
mZTPagePTr->UpdateCDVDisplay();
|
|
if(mZtSimPtr != 0) //ptr will be 0 if not in sim mode
|
|
{
|
|
mZtSimPtr->UpdateSimulatorDisplay();
|
|
}
|
|
|
|
if(mTimeToForceSyncFS == true)
|
|
{
|
|
mFSSyncTimer.start();
|
|
system("sync");
|
|
mTimeToForceSyncFS = false;
|
|
qDebug() << "Sync FS took: " << mFSSyncTimer.elapsed() << "ms";
|
|
mFSSyncTimer.start();
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(mCurInputs != mLastInputs)
|
|
mLastInputs = mCurInputs;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::ZT1StateMachine(unsigned int Event, unsigned int SubEvent)
|
|
{
|
|
Q_UNUSED(Event)
|
|
Q_UNUSED(SubEvent)
|
|
|
|
switch(mZT1State)
|
|
{
|
|
case ZT1_WAIT_FOR_CI_STATE:
|
|
{
|
|
if(mCIZT1Active)
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_TRAIN_STATE;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
case ZT1_WAIT_FOR_TRAIN_STATE:
|
|
{
|
|
if(mCIZT1Active == false)
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
}
|
|
if(!mZTStationPtr->IsZT1ApproachPresent())//When there is no approach CDV (Montmorency), use the subsequent CDV to detect maintenance vehicles going backward
|
|
{
|
|
if(mZTStationPtr->IsZT1SubsequentCDVOccupied()) //If subsequent CDV is occupied when waiting for train = vehicle going backward
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_SUBSEQUENT_LIBERATION;
|
|
}
|
|
else if(mZTStationPtr->IsZT1CDVOccupied()) //since the approach is the ZT CDV, just consider the latter
|
|
{
|
|
DestroyZT1Log();
|
|
mEventsRefTimer.start();
|
|
mNbPassages++;
|
|
InsertZT1LogItem();
|
|
mZT1Log.mZT1Flags.mPGCalibrationON = (mIsPGCalibON == true);
|
|
mZT1State = ZT1_TRAIN_ON_APPROACH_CDV_STATE;
|
|
}
|
|
}
|
|
else if(mZTStationPtr->IsZT1ApproachCDVOccupied() && !mZTStationPtr->IsZT1CDVOccupied()) //Normal situation
|
|
{
|
|
DestroyZT1Log();
|
|
mEventsRefTimer.start();
|
|
mNbPassages++;
|
|
InsertZT1LogItem();
|
|
mZT1Log.mZT1Flags.mPGCalibrationON = (mIsPGCalibON == true);
|
|
mZT1State = ZT1_TRAIN_ON_APPROACH_CDV_STATE;
|
|
}
|
|
break;
|
|
}
|
|
case ZT1_WAIT_FOR_SUBSEQUENT_LIBERATION: //Subsequent CDV should never be occupied before ZT CDV.
|
|
{
|
|
if(mCIZT1Active == false)
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
}
|
|
if(!mZTStationPtr->IsZT1CDVOccupied() && !mZTStationPtr->IsZT1SubsequentCDVOccupied())
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_TRAIN_STATE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ZT1_TRAIN_ON_APPROACH_CDV_STATE:
|
|
{
|
|
if(mCIZT1Active == false)
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
}
|
|
else if(!mZTStationPtr->IsZT1ApproachCDVOccupied())
|
|
{
|
|
mZT1State = ZT1_WAIT_FOR_TRAIN_STATE;
|
|
}
|
|
else if(mZTStationPtr->IsZT1CDVOccupied())
|
|
{
|
|
bool abort = false;
|
|
if(mModbusCCMgr != 0)
|
|
{
|
|
if(mModbusCCMgr->GetZT1InhibitionFlag() == true) //Check if the CC wants us to analyze the passage
|
|
{
|
|
abort = true;
|
|
CZTLog::instance()->AddLogString("Passage de train ZT1 inhibé par le SACL",true);
|
|
mZT1State = ZT1_WAIT_FOR_SUBSEQUENT_LIBERATION; //Wait for the train to leave the ZT
|
|
if(mModbusCCMgr != 0)
|
|
{
|
|
//update train info received from the CC Modbus interface
|
|
mTrainTypeDetected = (unsigned)mModbusCCMgr->GetZT1TrainType();
|
|
mZT1TrainComposition = mModbusCCMgr->GetZT1TrainComposition();
|
|
mZTPagePTr->SetZT1TrainData(mTrainTypeDetected,mZT1TrainComposition);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(abort == false)
|
|
{
|
|
mZT1ActiveStatus = SB_ZT_ACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
mZTPagePTr->SetZT1ActivationState(true);
|
|
|
|
mZTPagePTr->ResetZT1Stats();
|
|
if(mModbusCCMgr != 0)
|
|
{
|
|
//update train info received from the CC Modbus interface
|
|
mTrainTypeDetected = (unsigned)mModbusCCMgr->GetZT1TrainType();
|
|
mZT1TrainComposition = mModbusCCMgr->GetZT1TrainComposition();
|
|
mZTPagePTr->SetZT1TrainData(mTrainTypeDetected,mZT1TrainComposition);
|
|
}
|
|
|
|
InsertZT1LogItem();
|
|
|
|
mZT1WorkerThread->UpdateDetectionConfig(mZTDetectionConfig);
|
|
mTKGenerator->UpdateDetectionConfig(mZTDetectionConfig);
|
|
mZT1SMThread->start(QThread::NormalPriority);
|
|
|
|
mZT1PassageTimeLimitTimer.start();
|
|
//CZTLog::instance()->AddLogString("ZT1 activée",true);
|
|
|
|
|
|
CZTLog::instance()->ClearBufferString();
|
|
CZTLog::instance()->AddBufferString("ZT1 activée",true);
|
|
|
|
if(mIsPGCalibON)
|
|
{
|
|
emit PGCalibrationStatus(mCalibrationPassagesCount+1,mPGNbTotalPassages);
|
|
}
|
|
mZT1State = ZT1_ANALYZE_TRAIN_STATE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case ZT1_ANALYZE_TRAIN_STATE:
|
|
{
|
|
if(mZTStationPtr->IsZT1AnalysisFinished()) //Normally, this is true when the train leaves CDV ZT1 (except in Snowdon)...
|
|
{
|
|
|
|
mZT1ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
//The train is leaving the ZT1 CDV. Stop the analysis thread.
|
|
mZT1WorkerThread->TerminateAnalysis();
|
|
mZT1SMThread->quit();
|
|
|
|
InsertZT1LogItem();
|
|
|
|
CZTLog::instance()->AddBufferString("ZT1 désactivée",true);
|
|
|
|
mZT1State = ZT1_POST_DETECTION_STATE;
|
|
}
|
|
else if(mZT1PassageTimeLimitTimer.elapsed() > ZT1_MAX_PASSAGE_DELAY) //Si le train prend plus de 5 minutes à passer = ignorer le passage.
|
|
{
|
|
mZT1ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
//Stop the analysis thread.
|
|
mZT1WorkerThread->TerminateAnalysis();
|
|
mZT1SMThread->quit();
|
|
|
|
DestroyZT1Log();
|
|
CZTLog::instance()->AddLogString("Délai de passage expiré: ZT1 désactivée",true);
|
|
|
|
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
}
|
|
break;
|
|
}
|
|
case ZT1_POST_DETECTION_STATE:
|
|
{
|
|
if(AnalyzeZT1PostDetection() == RET_POST_DETECTION_VALID)
|
|
{
|
|
SaveZT1EventsLog(&mZT1Log);
|
|
mTKGenerator->BeginTKEmission();
|
|
|
|
if(mIsPGCalibON)
|
|
{
|
|
mCalibrationPassagesCount++;
|
|
if(mCalibrationPassagesCount < mPGNbTotalPassages)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
ComputePGCalibration();
|
|
QuitPGCalibrationMode();
|
|
}
|
|
}
|
|
}
|
|
else //We detected a véhicule travaux.
|
|
{
|
|
|
|
DestroyZT1Log();
|
|
}
|
|
|
|
if(mZT2Present == false && (mFSSyncTimer.elapsed() > FILESYSTEM_FORCED_SYNC_TIMEOUT))
|
|
{
|
|
mTimeToForceSyncFS = true;
|
|
}
|
|
|
|
mZT1State = ZT1_WAIT_FOR_CI_STATE;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::AnalyzeZT1PostDetection()
|
|
{
|
|
//Get useful information from detections log...
|
|
|
|
|
|
bool MagSensorCountError = false;
|
|
bool PEQ1Error = false;
|
|
int NbPGDetections = 0;
|
|
int NbFNDetections = 0;
|
|
mZT1Log.mZT1Flags.mIsProblematicPassage = 0;
|
|
|
|
for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
{
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_PG_DETECTION)
|
|
{
|
|
NbPGDetections++;
|
|
}
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_MAGNETIC_SENSOR_COUNT)
|
|
{
|
|
MagSensorCountError = true;
|
|
CEngLog::instance()->AddLogString("[Post-Détection]--> Flag de détection d'erreur de comptage actif",3);
|
|
}
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_PEQ1_DETECTION)
|
|
{
|
|
CEngLog::instance()->AddLogString("[Post-Détection]--> Flag de détection PEQ1 actif",3);
|
|
PEQ1Error = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//2015-03-03
|
|
//Computer crash may be related to addition of this section
|
|
///START
|
|
|
|
//If the thread did not detect any count error, check if the rank count is valid...
|
|
|
|
if(MagSensorCountError == false)
|
|
{
|
|
quint32 S1Count = 0, S2Count = 0;
|
|
for(int sample = 0; sample < mZT1Log.mZT1LogData.size(); sample++)
|
|
{
|
|
if(mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData != 0)
|
|
{
|
|
if(mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData->mS1Count > S1Count)
|
|
{
|
|
S1Count = mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData->mS1Count;
|
|
}
|
|
if(mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData->mS2Count > S2Count)
|
|
{
|
|
S2Count = mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData->mS2Count;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Thread should have detected S1 S2 count discrepancy but it's easy to re-check here.
|
|
if(S1Count != S2Count)
|
|
{
|
|
MagSensorCountError = true;
|
|
}
|
|
else if(S1Count != 12 && S1Count != 24 && S1Count != 36) //Make shure we counted all the ranks
|
|
{
|
|
MagSensorCountError = true;
|
|
}
|
|
else if(S2Count != 12 && S2Count != 24 && S2Count != 36) //Make shure we counted all the ranks
|
|
{
|
|
MagSensorCountError = true;
|
|
}
|
|
|
|
}
|
|
///END
|
|
|
|
|
|
bool PostAnalyseData = MagSensorCountError; //If we have a count error, do a post-analysis of the data
|
|
|
|
if(PEQ1Error == true && mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive) //If we have a PEQ1 detection, clear all other errors and emit PEQ1 only
|
|
{
|
|
//If we have a counting error AND the PEQ1 is FN stuck (most of the time this will happen because
|
|
//of the sensor count error), then ignore the PEQ1...
|
|
if(MagSensorCountError == true && mZT1PEQType == PEQ1_FN_STUCK_LOW_TYPE)
|
|
{
|
|
PostAnalyseData = true;
|
|
}
|
|
else
|
|
{
|
|
PostAnalyseData = false;
|
|
|
|
ClearZT1DetectionsList();
|
|
NbPGDetections = 0;
|
|
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive)
|
|
{
|
|
CZTLog::instance()->AddBufferString("Panne équipement ZT1: SDF <collé> à 1",true);
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_PEQ1_DETECTION;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.prepend(NewDetection);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if(PostAnalyseData == true) //check if we need to do a post-analysis of the data.
|
|
{
|
|
int S1Count = 0, S2Count = 0, FNCount = 0, PGCount = 0, PPICount = 0, PPECount = 0;
|
|
|
|
int S1 = 0, S2 = 0, FN = 0, PPI = 0, PPE = 0;
|
|
|
|
bool PGActive = false;
|
|
bool PGCalibrationON = mZT1Log.mZT1Flags.mPGCalibrationON == 1;
|
|
qint32 PGIOffset = mZT1Log.mZT1Flags.mIntPGOffset;
|
|
qint32 PGEOffset = mZT1Log.mZT1Flags.mExtPGOffset;
|
|
qint32 PGValueTreshold = mZT1Log.mZT1Flags.mPGTresholdValue;
|
|
qint32 Quadra;
|
|
int PGNonDetectionSampleCount = 0;
|
|
|
|
CEngLog::instance()->AddLogString("[Post-Détection]--> Début de l'analyse en Post-Détection",3);
|
|
|
|
|
|
//First, clear the detections list.
|
|
ClearZT1DetectionsList();
|
|
|
|
CZT1ThreadData *Data;
|
|
//Analyze the log and add detections to the list if any.
|
|
for(int sample = 0; sample < mZT1Log.mZT1LogData.size(); sample++)
|
|
{
|
|
if(mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData != 0)
|
|
{
|
|
Data = mZT1Log.mZT1LogData.at(sample)->mZT1ThreadData;
|
|
|
|
//Count magnetic sensors.
|
|
//Detect High to Low transitions
|
|
if(S1 == 1 && Data->mS1 == 0)
|
|
{
|
|
S1Count++;
|
|
}
|
|
S1 = Data->mS1;
|
|
|
|
//Detect High to Low transitions
|
|
if(S2 == 1 && Data->mS2 == 0)
|
|
{
|
|
S2Count++;
|
|
}
|
|
S2 = Data->mS2;
|
|
|
|
//Count FN occurences
|
|
//Detect High to Low transitions
|
|
if(FN == 1 && Data->mFN == 0)
|
|
{
|
|
FNCount++;
|
|
}
|
|
FN = Data->mFN;
|
|
|
|
//If we were calibrating, ignore the PG data.
|
|
if(PGCalibrationON == false)
|
|
{
|
|
//Compute and verify if the PG is detected.
|
|
Quadra = ((Data->mPGIntValue - PGIOffset) * (Data->mPGExtValue - PGEOffset));
|
|
if(Quadra > PGValueTreshold)
|
|
{
|
|
if(PGActive == false)
|
|
{
|
|
PGCount++;
|
|
PGActive = true;
|
|
}
|
|
PGNonDetectionSampleCount = 0;
|
|
}
|
|
else
|
|
{
|
|
if(PGActive == true)
|
|
{
|
|
if(PGNonDetectionSampleCount >= 3) //To avoid false detections when glitches or rebounds appear, we need to have at least 3 consecutive samples
|
|
{ //without detection to consider the PG inactive
|
|
PGActive = false;
|
|
}
|
|
PGNonDetectionSampleCount++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//Check for PP detections if needed
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_PP].AnalysisActive == true)
|
|
{
|
|
if(PPI == 1 && Data->mPInt == 0)
|
|
{
|
|
PPICount++;
|
|
|
|
//register the detection in the list.
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_PPI_DETECTION;
|
|
NewDetection->mTimeStamp = Data->mTimeStamp;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
|
|
}
|
|
PPI = Data->mPInt;
|
|
|
|
if(PPE == 1 && Data->mPExt == 0)
|
|
{
|
|
PPECount++;
|
|
|
|
//register the detection in the list.
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_PPE_DETECTION;
|
|
NewDetection->mTimeStamp = Data->mTimeStamp;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
PPE = Data->mPExt;
|
|
}
|
|
}
|
|
}
|
|
|
|
CEngLog::instance()->AddLogString(QString().sprintf("[Post-Détection]--> Résultat des données brutes: [S1Count = %d], [S2Count = %d], [PGCount = %d], [FNCount = %d], [PPICount = %d], [PPECount = %d]",S1Count,S2Count,PGCount,FNCount,PPICount,PPECount),3);
|
|
|
|
//First, try to detect a véhicule travaux. If we have a PG count of 0, it is a véhicule travaux and we
|
|
//just totally ignore this passage
|
|
if(PGCalibrationON == false)
|
|
{
|
|
if(PGCount == 0)
|
|
{
|
|
CZTLog::instance()->AddLogString("[POST DETECTION]--> Véhicule travaux détecté. Annulation et fin de l'analyse ZT1",true);
|
|
ClearZT1DetectionsList();
|
|
return RET_POST_DETECTION_WORK_VEHICLE;
|
|
}
|
|
}
|
|
|
|
|
|
//Analyze the PG count if necessary
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_PG].AnalysisActive == true)
|
|
{
|
|
if(PGCalibrationON == false)
|
|
{
|
|
|
|
|
|
if(PGCount == 12 || PGCount == 24 || PGCount == 36)
|
|
{
|
|
//Everything is fine with the PG.
|
|
NbPGDetections = 0;
|
|
}
|
|
else
|
|
{
|
|
CEngLog::instance()->AddLogString(QString().sprintf("[Post-Détection]--> Compte PG invalide : PGCount = %d",PGCount),3);
|
|
if(PGCount > 24)
|
|
{
|
|
NbPGDetections = 36 - PGCount;
|
|
}
|
|
else if(PGCount > 12)
|
|
{
|
|
NbPGDetections = 24 - PGCount;
|
|
}
|
|
else
|
|
{
|
|
NbPGDetections = 12 - PGCount;
|
|
}
|
|
}
|
|
|
|
int alarms = NbPGDetections;
|
|
|
|
if(alarms < 0)
|
|
{
|
|
alarms = -1 * alarms;
|
|
}
|
|
|
|
for(int i = 0; i < alarms; i++)
|
|
{
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_PG_DETECTION;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//Analyze FN count if necessary
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_FN].AnalysisActive == true)
|
|
{
|
|
|
|
if(FNCount == 6 || FNCount == 12 || FNCount == 18)
|
|
{
|
|
//Everything is fine with the FN.
|
|
NbFNDetections = 0;
|
|
}
|
|
else
|
|
{
|
|
CEngLog::instance()->AddLogString(QString().sprintf("[Post-Détection]--> Compte FN invalide : FNCount = %d",FNCount),3);
|
|
if(FNCount > 12)
|
|
{
|
|
NbFNDetections = 18 - FNCount;
|
|
}
|
|
else if(FNCount > 6)
|
|
{
|
|
NbFNDetections = 12 - FNCount;
|
|
}
|
|
else
|
|
{
|
|
NbFNDetections = 6 - FNCount;
|
|
}
|
|
}
|
|
|
|
int alarms = NbFNDetections;
|
|
|
|
if(alarms < 0)
|
|
{
|
|
alarms = -1 * alarms;
|
|
}
|
|
|
|
if(alarms != 0)
|
|
{
|
|
//With Modbus interface, we send as many alarms as there are detections with rank 99 (ZT_DEFAULT_DETECTION_RANK)
|
|
for(int i = 0; i < alarms; i++)
|
|
{
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_FN_DETECTION;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
// //Send two detections only (rank 1 & 18) when detecting FN errors while in V00
|
|
// QString string;
|
|
// string.sprintf("[POST DETECTION]--> Déclenchement FN avec erreur de comptage (FNCount = %d). Envoi d'alarmes aux rangs 1 et 18.",FNCount);
|
|
// //CZTLog::instance()->AddBufferString("Déclenchement FN avec erreur de comptage. Envoi d'alarmes aux rangs 1 et 18.",true);
|
|
// CZTLog::instance()->AddBufferString(string,true);
|
|
// CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
// NewDetection->mDetectionID = DETECTION_FN_DETECTION;
|
|
// NewDetection->mTimeStamp = 0;
|
|
// NewDetection->mRank = 1;
|
|
// mZT1DetectionsLog.append(NewDetection);
|
|
|
|
// NewDetection = new CZTDetectionData();
|
|
// NewDetection->mDetectionID = DETECTION_FN_DETECTION;
|
|
// NewDetection->mTimeStamp = 0;
|
|
// NewDetection->mRank = 18;
|
|
// mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
}
|
|
|
|
if(mZT1DetectionsLog.size() != 0)
|
|
{
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive)
|
|
{
|
|
//If here, we had at least one detection. We must emit the V00 alarm.
|
|
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_MAGNETIC_SENSOR_COUNT;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//If here, we did not detect other errors than mag. sensor count.
|
|
//We can tolerate 2 miss
|
|
|
|
if(mZTDetectionConfig->mZTDetectionConfig[DETECTION_FCT_ZT1].AnalysisActive)
|
|
{
|
|
int SensorCount = S1Count;
|
|
if(SensorCount > S2Count)
|
|
SensorCount = S2Count; //Use the least of the 2 counts...
|
|
|
|
bool Error = false;
|
|
if(S1Count > 36 || S2Count > 36)
|
|
{
|
|
//Counted more than 36 ranks on at least one sensor...
|
|
Error = true;
|
|
}
|
|
if(SensorCount > 24 && SensorCount < 34)
|
|
{
|
|
//more than 2 miss for a 3 elements train
|
|
Error = true;
|
|
}
|
|
else if(SensorCount > 12 && SensorCount < 22)
|
|
{
|
|
//more than 2 miss for a 2 elements train
|
|
Error = true;
|
|
}
|
|
else if(SensorCount < 10)
|
|
{
|
|
//more than 2 miss for a 1 element train
|
|
Error = true;
|
|
}
|
|
|
|
if(Error)
|
|
{
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_MAGNETIC_SENSOR_COUNT;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
else
|
|
{
|
|
QString string;
|
|
string.sprintf("[POST DETECTION]--> Erreur de comptage ZT1 : [S1=%d] [S2=%d] essieux comptés (TK non émise au PCC car <= 2 essieux sans autre détection )",S1Count, S2Count);
|
|
CZTLog::instance()->AddBufferString(string,true,true);
|
|
mZT1Log.mZT1Flags.mIsProblematicPassage = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else//No magnetic sensors count error
|
|
{
|
|
//If we have more than 3 PG detections, check if they happened on consecutive ranks
|
|
//if so, remove them from the list and emit a PEQ1 alarm instead.
|
|
if(NbPGDetections >= 3 && mZT1DetectionsLog.size() >= 3)
|
|
{
|
|
//List the detections
|
|
int DetectionIDs[1024/*NbPGDetections*/];
|
|
int index = 0;
|
|
|
|
for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
{
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_PG_DETECTION)
|
|
{
|
|
DetectionIDs[index++] = i;
|
|
}
|
|
}
|
|
|
|
//Now check if the ranks are consecutive. If so, remove the events from the list.
|
|
if((mZT1DetectionsLog.at(DetectionIDs[0])->mRank+1 == mZT1DetectionsLog.at(DetectionIDs[1])->mRank) &&
|
|
(mZT1DetectionsLog.at(DetectionIDs[1])->mRank+1 == mZT1DetectionsLog.at(DetectionIDs[2])->mRank))
|
|
{
|
|
//remove all PG detections.
|
|
for(int i = NbPGDetections-1 ; i >= 0 ; i--)
|
|
{
|
|
delete mZT1DetectionsLog.at(DetectionIDs[i]);
|
|
mZT1DetectionsLog.remove(DetectionIDs[i]);
|
|
}
|
|
|
|
CZTLog::instance()->AddBufferString("[POST DETECTION]--> Plus de 3 PG consécutifs détectés (TK non émise au PCC)",true,true);
|
|
mZT1Log.mZT1Flags.mIsProblematicPassage = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//Check if the rank count is valid even without mag. sensor error
|
|
unsigned int S1Count = 0, S2Count = 0;
|
|
for(int i = 0; i < mZT1Log.mZT1LogData.size(); i++)
|
|
{
|
|
if(mZT1Log.mZT1LogData.at(i)->mZT1ThreadData != 0)
|
|
{
|
|
if(mZT1Log.mZT1LogData.at(i)->mZT1ThreadData->mS1Count > S1Count)
|
|
{
|
|
S1Count = mZT1Log.mZT1LogData.at(i)->mZT1ThreadData->mS1Count;
|
|
}
|
|
if(mZT1Log.mZT1LogData.at(i)->mZT1ThreadData->mS2Count > S2Count)
|
|
{
|
|
S2Count = mZT1Log.mZT1LogData.at(i)->mZT1ThreadData->mS2Count;
|
|
}
|
|
}
|
|
}
|
|
|
|
if((S1Count == 12 || S1Count == 24 || S1Count == 36) &&
|
|
(S2Count == 12 || S2Count == 24 || S2Count == 36))
|
|
{
|
|
//Everything is fine, no sensor count error...
|
|
}
|
|
else
|
|
{
|
|
if(mZT1DetectionsLog.size() != 0)
|
|
{
|
|
//If here, we had at least one detection. We must emit the V00 alarm.
|
|
CEngLog::instance()->AddLogString(QString().sprintf("[Post-Détection]--> Erreur de comptage sans flag en temps réel"),3);
|
|
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_MAGNETIC_SENSOR_COUNT;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.prepend(NewDetection); //Put the V00 alarm first (prepend)
|
|
|
|
//Clear the detections rank of all the detections since it may not be valid.
|
|
for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
{
|
|
mZT1DetectionsLog.at(i)->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
}
|
|
|
|
//JFM 20160112 V1.10
|
|
//If there was FN detection, replace it with two alarms at rank 1 and 18.
|
|
bool FNDetection = false;
|
|
int i = 0;
|
|
while(i < mZT1DetectionsLog.size())
|
|
{
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_FN_DETECTION)
|
|
{
|
|
CEngLog::instance()->AddLogString(QString().sprintf("[Post-Détection]--> Déclenchement FN détecté dans liste des alarmes"),3);
|
|
FNDetection = true;
|
|
delete mZT1DetectionsLog.at(i);
|
|
mZT1DetectionsLog.remove(i); //remove this alarm
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
};
|
|
if(FNDetection == true)
|
|
{
|
|
CZTLog::instance()->AddBufferString("[Post-Détection]--> Déclenchement FN avec erreur de comptage. Envoi d'alarmes aux rangs 1 et 18.",true);
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_FN_DETECTION;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = 1;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
|
|
NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_FN_DETECTION;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = 18;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//If here, we did not detect other errors than mag. sensor count.
|
|
//We can tolerate 2 miss
|
|
|
|
unsigned int SensorCount = S1Count;
|
|
if(SensorCount > S2Count)
|
|
SensorCount = S2Count; //Use the least of the 2 counts...
|
|
|
|
bool Error = false;
|
|
if(S1Count > 36 || S2Count > 36)
|
|
{
|
|
//Counted more than 36 ranks...
|
|
Error = true;
|
|
}
|
|
else if(SensorCount > 24 && SensorCount < 34)
|
|
{
|
|
//more than 2 miss for a 3 elements train
|
|
Error = true;
|
|
}
|
|
else if(SensorCount > 12 && SensorCount < 22)
|
|
{
|
|
//more than 2 miss for a 2 elements train
|
|
Error = true;
|
|
}
|
|
else if(SensorCount < 10)
|
|
{
|
|
//more than 2 miss for a 1 element train
|
|
Error = true;
|
|
}
|
|
|
|
if(Error)
|
|
{
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_MAGNETIC_SENSOR_COUNT;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
|
|
}
|
|
else
|
|
{
|
|
QString string;
|
|
string.sprintf("[POST DETECTION]--> Erreur de comptage ZT1 : [S1=%d] et [S2=%d] essieux comptés (TK non émise au PCC car <= 2 essieux sans autre détection )",S1Count, S2Count);
|
|
CZTLog::instance()->AddBufferString(string,true,true);
|
|
mZT1Log.mZT1Flags.mIsProblematicPassage =1;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Process detections and send TKs to PCC/PCM
|
|
for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
{
|
|
mTKGenerator->ProcessDetectionsTK(mZT1DetectionsLog.at(i));
|
|
|
|
mNbTriggers++;
|
|
|
|
QString str("");
|
|
if(mZT1DetectionsLog.at(i)->mDetectionID == DETECTION_FN_DETECTION)
|
|
str.sprintf("[POST DETECTION]--> %s au bogie %d (rang %d ou %d)",CZTData::GetErrorString(mZT1DetectionsLog.at(i)->mDetectionID),mZT1DetectionsLog.at(i)->mRank,(mZT1DetectionsLog.at(i)->mRank*2)-1,mZT1DetectionsLog.at(i)->mRank*2);
|
|
else
|
|
str.sprintf("[POST DETECTION]--> %s au rang %d",CZTData::GetErrorString(mZT1DetectionsLog.at(i)->mDetectionID),mZT1DetectionsLog.at(i)->mRank);
|
|
CZTLog::instance()->AddBufferString(str,true);
|
|
}
|
|
|
|
if(mZT1DetectionsLog.size() != 0 || CZTLog::instance()->IsWriteForced())
|
|
{
|
|
CZTLog::instance()->WriteBufferToLog();
|
|
}
|
|
else
|
|
{
|
|
CZTLog::instance()->ClearBufferString(); //2015-03-03 To avoid potention memory leak. Computer Crash problem resolution tentative...
|
|
}
|
|
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
return RET_POST_DETECTION_VALID;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::ZT2StateMachine(unsigned int Event, unsigned int SubEvent)
|
|
{
|
|
Q_UNUSED(Event)
|
|
Q_UNUSED(SubEvent)
|
|
|
|
if(IsZT1Active() == false)
|
|
{
|
|
switch(mZT2State)
|
|
{
|
|
case ZT2_WAIT_FOR_CI_STATE:
|
|
{
|
|
if(mCIZT2Active)
|
|
{
|
|
if(mZTStationPtr->IsZT2CDVOccupied() == false) //the ZT2 CDV must be free.
|
|
{
|
|
mZT2State = ZT2_WAIT_FOR_TRAIN_STATE;
|
|
}
|
|
else
|
|
{
|
|
mZT2State = ZT2_WAIT_FOR_APPROACH_LIBERATION_STATE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case ZT2_WAIT_FOR_APPROACH_LIBERATION_STATE:
|
|
{
|
|
if(mZTStationPtr->IsZT2ApproachCDVOccupied() == false)
|
|
{
|
|
mZT2State = ZT2_WAIT_FOR_CI_STATE;
|
|
}
|
|
break;
|
|
}
|
|
case ZT2_WAIT_FOR_TRAIN_STATE:
|
|
{
|
|
if(mCIZT2Active == false)
|
|
{
|
|
mZT2State = ZT2_WAIT_FOR_CI_STATE;
|
|
}
|
|
else if(mZTStationPtr->IsZT2ApproachCDVOccupied()) //À certaines stations, la ZT2 doit être activée à l'occupation du CDV d'approche.
|
|
{
|
|
bool abort = false;
|
|
|
|
if(mModbusCCMgr != 0)
|
|
{
|
|
if(mModbusCCMgr->GetZT2InhibitionFlag() == true) //Check if the CC wants us to analyze the passage
|
|
{
|
|
abort = true;
|
|
CZTLog::instance()->AddLogString("Passage de train ZT2 inhibé par le SACL",true);
|
|
mZT2State = ZT2_WAIT_FOR_CDV_LIBERATION_STATE; //Wait for the train to leave the ZT
|
|
|
|
//update train info received from the CC Modbus interface
|
|
mZT2TrainType = (unsigned)mModbusCCMgr->GetZT2TrainType();
|
|
mZT2TrainComposition = mModbusCCMgr->GetZT2TrainComposition();
|
|
mZTPagePTr->SetZT2TrainData(mZT2TrainType,mZT2TrainComposition);
|
|
}
|
|
}
|
|
|
|
|
|
if(abort == false)
|
|
{
|
|
DestroyZT2Log();
|
|
mEventsRefTimer.start();
|
|
mZTPagePTr->SetZT2ActivationSTate(true);
|
|
mZT2ActiveStatus = SB_ZT_ACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
mZTPagePTr->ResetZT2Stats();
|
|
if(mModbusCCMgr != 0)
|
|
{
|
|
//update train info received from the CC Modbus interface
|
|
mZT2TrainType = (unsigned)mModbusCCMgr->GetZT2TrainType();
|
|
mZT2TrainComposition = mModbusCCMgr->GetZT2TrainComposition();
|
|
mZTPagePTr->SetZT2TrainData(mZT2TrainType,mZT2TrainComposition);
|
|
}
|
|
InsertZT2LogItem();
|
|
mZT2WorkerThread->UpdateDetectionConfig(mZTDetectionConfig);
|
|
mTKGenerator->UpdateDetectionConfig(mZTDetectionConfig);
|
|
mZT2SMThread->start(QThread::NormalPriority);
|
|
|
|
mZT2PassageTimeLimitTimer.start();
|
|
mZT2State = ZT2_ANALYZE_TRAIN_STATE;
|
|
|
|
CZTLog::instance()->ClearBufferString();
|
|
CZTLog::instance()->AddBufferString("ZT2 activée",true);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ZT2_ANALYZE_TRAIN_STATE:
|
|
{
|
|
if(!mZTStationPtr->IsZT2CDVOccupied() && !mZTStationPtr->IsZT2ApproachCDVOccupied()) //train quit the ZT2 cdv.
|
|
{
|
|
mZT2ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
//The train is leaving the ZT2 CDV. Stop the analysis thread.
|
|
mZT2WorkerThread->TerminateAnalysis();
|
|
mZT2SMThread->quit();
|
|
|
|
InsertZT2LogItem();
|
|
|
|
CZTLog::instance()->AddBufferString("ZT2 désactivée",true);
|
|
|
|
mZT2State = ZT2_POST_DETECTION_STATE;
|
|
}
|
|
if(mZT2PassageTimeLimitTimer.elapsed() > ZT2_MAX_PASSAGE_DELAY )
|
|
{
|
|
mZT2ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
//Stop the analysis thread.
|
|
mZT2WorkerThread->TerminateAnalysis();
|
|
mZT2SMThread->quit();
|
|
|
|
DestroyZT2Log();
|
|
CZTLog::instance()->AddLogString("Délai de passage expiré: Analyse ZT2 annulée. Attente de libération du CDV",true);
|
|
|
|
mZT2State = ZT2_WAIT_FOR_CDV_LIBERATION_STATE;
|
|
}
|
|
break;
|
|
}
|
|
case ZT2_WAIT_FOR_CDV_LIBERATION_STATE:
|
|
{
|
|
if(!mZTStationPtr->IsZT2CDVOccupied() && !mZTStationPtr->IsZT2ApproachCDVOccupied())
|
|
{
|
|
CZTLog::instance()->AddLogString("CDV ZT2 Libéré. ZT2 prête",true);
|
|
mZT2State = ZT2_WAIT_FOR_CI_STATE;
|
|
}
|
|
break;
|
|
}
|
|
case ZT2_POST_DETECTION_STATE:
|
|
{
|
|
//InsertZT2LogItem(); //JFM 2014-06-11 Not sure if necessary...
|
|
AnalyzeZT2PostDetection();
|
|
SaveZT2EventsLog(&mZT2Log);
|
|
mTKGenerator->BeginTKEmission();
|
|
|
|
mZT2State = ZT2_WAIT_FOR_CI_STATE;
|
|
|
|
|
|
if(mFSSyncTimer.elapsed() > FILESYSTEM_FORCED_SYNC_TIMEOUT)
|
|
{
|
|
mTimeToForceSyncFS = true;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
|
|
unsigned int CZTStateMachine::AnalyzeZT2PostDetection()
|
|
{
|
|
bool PEQ2 = false;
|
|
qint64 PEQ2Timestamp = 0;
|
|
mZT2Log.mZT2Flags.mIsProblematicPassage = 0;
|
|
|
|
for(int i = 0; i < mZT2DetectionsLog.size(); i++)
|
|
{
|
|
if(mZT2DetectionsLog.at(i)->mDetectionID == DETECTION_PEQ2_DETECTION)
|
|
{
|
|
PEQ2 = true;
|
|
PEQ2Timestamp = mZT2DetectionsLog.at(i)->mTimeStamp;
|
|
}
|
|
}
|
|
|
|
//If we have a PEQ2, we remove all detections an leave only the PEQ2 one
|
|
if(PEQ2 == true)
|
|
{
|
|
for(int i = 0; i < mZT2DetectionsLog.size(); i++)
|
|
{
|
|
delete mZT2DetectionsLog.at(i);
|
|
}
|
|
mZT2DetectionsLog.clear();
|
|
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_PEQ2_DETECTION;
|
|
NewDetection->mTimeStamp = PEQ2Timestamp;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT2DetectionsLog.prepend(NewDetection);
|
|
}
|
|
else
|
|
{
|
|
|
|
//Check for magnetic sensor count error.
|
|
int S1Count = 0;
|
|
for(int i = 0; i < mZT2Log.mZT2LogData.size(); i++)
|
|
{
|
|
if(mZT2Log.mZT2LogData.at(i)->mZT2ThreadData != 0)
|
|
{
|
|
if((int)mZT2Log.mZT2LogData.at(i)->mZT2ThreadData->mS1Count > S1Count)
|
|
{
|
|
S1Count = mZT2Log.mZT2LogData.at(i)->mZT2ThreadData->mS1Count;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(S1Count == 12 || S1Count == 24 || S1Count == 36)
|
|
{
|
|
//Everything is fine !
|
|
|
|
}
|
|
else
|
|
{
|
|
//We had a sensor count error. Emit V02 only if we also have a PP detection.
|
|
if(mZT2DetectionsLog.size() == 0)
|
|
{
|
|
//No PP detection.
|
|
QString string("");
|
|
string.sprintf("[POST DETECTION]--> Erreur de comptage ZT2 : %d essieux comptés (TK non émise au PCC car pas de déclenchement PP)",S1Count);
|
|
CZTLog::instance()->AddBufferString(string,true,true);
|
|
mZT2Log.mZT2Flags.mIsProblematicPassage = 1;
|
|
}
|
|
else
|
|
{
|
|
//There has been a PP detection. Add V02 alarm to the list (at the beginning)
|
|
|
|
CZTDetectionData *NewDetection = new CZTDetectionData();
|
|
NewDetection->mDetectionID = DETECTION_ZT2_MAGNETIC_SENSOR_COUNT;
|
|
NewDetection->mTimeStamp = 0;
|
|
NewDetection->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
mZT2DetectionsLog.append(NewDetection);
|
|
|
|
//Clear the rank value for the other detections since it may not be valid
|
|
for(int i = 0; i < mZT2DetectionsLog.size(); i++)
|
|
{
|
|
mZT2DetectionsLog.at(i)->mRank = ZT_DEFAULT_DETECTION_RANK;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Process detections and send TKs to PCC/PCM
|
|
for(int i = 0; i < mZT2DetectionsLog.size(); i++)
|
|
{
|
|
mTKGenerator->ProcessDetectionsTK(mZT2DetectionsLog.at(i));
|
|
|
|
mNbTriggers++;
|
|
QString str("");
|
|
str.sprintf("[POST DETECTION]--> %s au rang %d",CZTData::GetErrorString(mZT2DetectionsLog.at(i)->mDetectionID),mZT2DetectionsLog.at(i)->mRank);
|
|
// CZTLog::instance()->AddLogString(str,true);
|
|
CZTLog::instance()->AddBufferString(str,true);
|
|
}
|
|
|
|
if(mZT2DetectionsLog.size() != 0 || CZTLog::instance()->IsWriteForced())
|
|
{
|
|
CZTLog::instance()->WriteBufferToLog();
|
|
}
|
|
else
|
|
{
|
|
CZTLog::instance()->ClearBufferString(); //2015-03-03 To avoid potention memory leak. Computer Crash problem resolution tentative...
|
|
}
|
|
|
|
//mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1Active,mZT2Active);
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
bool CZTStateMachine::IsZT1Active()
|
|
{
|
|
if(mZT1State == ZT1_TRAIN_ON_APPROACH_CDV_STATE || mZT1State == ZT1_ANALYZE_TRAIN_STATE)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CZTStateMachine::IsZT2Active()
|
|
{
|
|
if(mZT2State == ZT2_WAIT_FOR_CI_STATE || mZT2State == ZT2_WAIT_FOR_TRAIN_STATE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void CZTStateMachine::BindPointers(CStation *ptr,CInputModule *InputModule,COutputModule *OutputModule,CZTPage *ZTPagePTr,CPCIIOMgr *PCIIOPtr,CAbstractLazerProbe *PGIntProbePtr, CAbstractLazerProbe *PGExtProbePTr,CLogMgr *LogMgr,CTKTransportInterface *TKTransport,CZTSimulator *ZTSimPtr,CAnalogInputModule *DataQInterface)
|
|
{
|
|
Q_UNUSED(OutputModule)
|
|
|
|
mZTStationPtr = ptr;
|
|
mSDFAnalogMonitorInterface = DataQInterface;
|
|
mInputModule = InputModule;
|
|
mZTPagePTr = ZTPagePTr;
|
|
mZtSimPtr = ZTSimPtr;
|
|
mZTInputMasks = mZTStationPtr->GetInputMasks();
|
|
mPCIIOPtr = PCIIOPtr;
|
|
mPGExtProbePtr = PGExtProbePTr;
|
|
mPGIntProbePtr = PGIntProbePtr;
|
|
mLogMgr = LogMgr;
|
|
|
|
mZT1WorkerThread->Init(PCIIOPtr,mZTInputMasks,mPGExtProbePtr,mPGIntProbePtr,&mEventsRefTimer,mSDFAnalogMonitorInterface);
|
|
mZT2WorkerThread->Init(PCIIOPtr,mZTInputMasks,&mEventsRefTimer);
|
|
|
|
|
|
//mTKGenerator->BindPointers(mZTStationPtr->GetOutputMasks(),OutputModule);
|
|
//mTKGenerator->BindTransportInterface(TKTransport);
|
|
mTKGenerator = TKTransport;
|
|
}
|
|
|
|
void CZTStateMachine::BindModbusCCMgrPtr(CModbusCCMgr *ModbusCCPtr)
|
|
{
|
|
mModbusCCMgr = ModbusCCPtr;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::SetPGTreshold(qint32 PGTreshold)
|
|
{
|
|
mZT1WorkerThread->SetPGTreshold(PGTreshold);
|
|
return RET_OK;
|
|
}
|
|
|
|
void CZTStateMachine::ResetNbTriggers()
|
|
{
|
|
mNbTriggers = 0;
|
|
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
}
|
|
|
|
void CZTStateMachine::ResetNbPassages()
|
|
{
|
|
mNbPassages = 0;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
}
|
|
|
|
void CZTStateMachine::ZT1StateChanged(CZT1ThreadData *ZT1DataPtr,bool ProbesOnly,int SDF)
|
|
{
|
|
//We want to limit the sampling rate in the log file
|
|
//BUT we want to log EVERY signal transition, except lazer probes (which sample at 1Khz).
|
|
|
|
//JFM 2016-05-31
|
|
//Add this to avoid having queued signals processed after the S.M. finished,
|
|
//causing data corruption in the train file.
|
|
if(IsZT1Active() == false)
|
|
return;
|
|
|
|
if(ProbesOnly == true )
|
|
{
|
|
//JFM 20140821
|
|
if(mLogDelay != 0)
|
|
{
|
|
if(mZT1LogDelayTimer.elapsed() < mLogDelay)
|
|
{
|
|
delete ZT1DataPtr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
mZTPagePTr->SetZT1Data(ZT1DataPtr); //update display with the new data.
|
|
}
|
|
else
|
|
{
|
|
mZTPagePTr->SetZT1Data(ZT1DataPtr,true); //force update display with the new data.
|
|
}
|
|
|
|
|
|
InsertZT1LogItem(ZT1DataPtr,SDF);
|
|
|
|
mZT1LogDelayTimer.start();
|
|
//qDebug("TimeStamp: %f",(float)ZT1DataPtr->mTimeStamp/1000000000);
|
|
}
|
|
|
|
void CZTStateMachine::ZT2StateChanged(CZT2ThreadData *ZT2DataPtr)
|
|
{
|
|
mZTPagePTr->SetZT2Data(ZT2DataPtr);
|
|
InsertZT2LogItem(ZT2DataPtr);
|
|
}
|
|
|
|
void CZTStateMachine::SetZT2Presence(bool Presence)
|
|
{
|
|
mZT2Present = Presence;
|
|
}
|
|
|
|
void CZTStateMachine::ZT1NewDetection(CZTDetectionData *NewDetection)
|
|
{
|
|
|
|
mZT1DetectionsLog.append(NewDetection);
|
|
|
|
QString str("");
|
|
if(NewDetection->mDetectionID == DETECTION_FN_DETECTION)
|
|
str.sprintf("%s au bogie %d (rang %d ou %d)",CZTData::GetErrorString(NewDetection->mDetectionID),NewDetection->mRank,(NewDetection->mRank*2)-1,NewDetection->mRank*2);
|
|
else
|
|
str.sprintf("%s au rang %d",CZTData::GetErrorString(NewDetection->mDetectionID),NewDetection->mRank);
|
|
// CZTLog::instance()->AddLogString(str,true);
|
|
CZTLog::instance()->AddBufferString(str,true);
|
|
|
|
}
|
|
|
|
void CZTStateMachine::ZT2NewDetection(CZTDetectionData *NewDetection)
|
|
{
|
|
// mNbTriggers++;
|
|
mZT2DetectionsLog.append(NewDetection);
|
|
/* mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1Active,mZT2Active);
|
|
mTKGenerator->ProcessDetectionsTK(NewDetection);
|
|
QString str("");*/
|
|
QString str("");
|
|
str.sprintf("%s au rang %d",CZTData::GetErrorString(NewDetection->mDetectionID),NewDetection->mRank);
|
|
// CZTLog::instance()->AddLogString(str,true);
|
|
CZTLog::instance()->AddBufferString(str,true);
|
|
}
|
|
|
|
|
|
unsigned int CZTStateMachine::DestroyZT1Log()
|
|
{
|
|
|
|
for(int i = 0; i < mZT1Log.mZT1LogData.size(); i++)
|
|
{
|
|
delete mZT1Log.mZT1LogData.at(i);
|
|
}
|
|
//qDeleteAll(mZT1Log.mZT1LogData);
|
|
mZT1Log.mZT1LogData.clear();
|
|
// mZT1Log.mZT1LogData.squeeze();
|
|
|
|
ClearZT1DetectionsList();
|
|
// for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
// {
|
|
// delete mZT1DetectionsLog.at(i);
|
|
// }
|
|
// mZT1DetectionsLog.clear();
|
|
|
|
|
|
mZT1Log.mZT1Flags.mExtPGOffset = 0;
|
|
mZT1Log.mZT1Flags.mIntPGOffset = 0;
|
|
mZT1Log.mZT1Flags.mPGCalibrationON = false;
|
|
mZT1Log.mZT1Flags.mPGTresholdValue = 0;
|
|
mZT1Log.mZT1Flags.mAnalogTracePresent = (mSDFAnalogMonitorInterface != 0);
|
|
mZT1Log.mZT1Flags.mIsProblematicPassage = 0;
|
|
|
|
mZT1PEQType = PEQ1_UNKNOWN_TYPE;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::InsertZT1LogItem(CZT1ThreadData *ThreadData,int SDFReading)
|
|
{
|
|
CZT1LogData *NewItem = new CZT1LogData(ThreadData);
|
|
|
|
if(ThreadData == 0) //Avoid accessing mEventsRefTimer while thread is running !
|
|
NewItem->mTimestamp = mEventsRefTimer.nsecsElapsed();
|
|
else
|
|
NewItem->mTimestamp = ThreadData->mTimeStamp;
|
|
|
|
NewItem->mDateTime = QDateTime::currentDateTime();
|
|
NewItem->mCDVApproach_ZT1 = mZTStationPtr->IsZT1ApproachCDVOccupied();
|
|
NewItem->mCDVARM_ZT1 = mZTStationPtr->IsZT1CDVOccupied();
|
|
NewItem->mCIZT1 = (unsigned int)mCIZT1Active;
|
|
|
|
NewItem->mAnalogData = SDFReading;
|
|
mZT1Log.mZT1LogData.append(NewItem);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::InsertZT2LogItem(CZT2ThreadData *ThreadData)
|
|
{
|
|
CZT2LogData *NewItem = new CZT2LogData(ThreadData);
|
|
|
|
if(ThreadData == 0) //Avoid accessing mEventsRefTimer while thread is running !
|
|
NewItem->mTimestamp = mEventsRefTimer.nsecsElapsed();
|
|
else
|
|
NewItem->mTimestamp = ThreadData->mTimeStamp;
|
|
|
|
NewItem->mDateTime = QDateTime::currentDateTime();
|
|
NewItem->mCDVARM_ZT2 = mZTStationPtr->IsZT2CDVOccupied();
|
|
NewItem->mCDVApproach_ZT2 = mZTStationPtr->IsZT2ApproachCDVOccupied();
|
|
NewItem->mCIZT2 = (unsigned int)mCIZT2Active;
|
|
mZT2Log.mZT2LogData.append(NewItem);
|
|
return RET_OK;
|
|
}
|
|
unsigned int CZTStateMachine::DestroyZT2Log()
|
|
{
|
|
mZT2Log.mZT2Flags.mIsProblematicPassage = 0;
|
|
for(int i = 0; i < mZT2Log.mZT2LogData.size(); i++)
|
|
{
|
|
delete mZT2Log.mZT2LogData.at(i);
|
|
}
|
|
mZT2Log.mZT2LogData.clear();
|
|
|
|
for(int i = 0; i < mZT2DetectionsLog.size(); i++)
|
|
{
|
|
delete mZT2DetectionsLog.at(i);
|
|
}
|
|
mZT2DetectionsLog.clear();
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::DestroyCalibrationData()
|
|
{
|
|
for(unsigned int j = 0; j < ZT_SM_MAX_NB_PG_CALIB_PASSAGES; j++)
|
|
{
|
|
for(int i = 0; i < mZTPGCalibrationData[j].size(); i++)
|
|
{
|
|
delete mZTPGCalibrationData[j].at(i);
|
|
}
|
|
|
|
mZTPGCalibrationData[j].clear();
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::SaveZT1EventsLog(CZT1Log *Log)
|
|
{
|
|
|
|
QString FileName1 = "./Trains/LOGZT1_";
|
|
FileName1 += QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
|
QString FileName = FileName1 + ".bin";
|
|
qDebug("%s",FileName.toAscii().data());
|
|
|
|
CTrainLogFileMgr::instance()->SaveTrainLog(FileName,Log,&mZT1DetectionsLog,mZTStationPtr->GetStationTextualName());
|
|
mLogMgr->ParseNewLog(FileName);
|
|
|
|
|
|
if(mAutoExportZT1CSV)
|
|
{
|
|
FileName = FileName1 + ".csv";
|
|
CTrainLogFileMgr::instance()->SaveCSVFile(FileName,Log,&mZT1DetectionsLog,mZTStationPtr->GetStationTextualName());
|
|
}
|
|
|
|
DestroyZT1Log();
|
|
|
|
emit NewTrainLogSaved();
|
|
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::SaveZT2EventsLog(CZT2Log *Log)
|
|
{
|
|
QString FileName1 = "./Trains/LOGZT2_";
|
|
FileName1 += QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
|
QString FileName = FileName1 + ".bin";
|
|
qDebug("%s",FileName.toAscii().data());
|
|
|
|
CTrainLogFileMgr::instance()->SaveTrainLog(FileName,Log,&mZT2DetectionsLog,mZTStationPtr->GetStationTextualName());
|
|
mLogMgr->ParseNewLog(FileName);
|
|
|
|
if(mAutoExportZT2CSV)
|
|
{
|
|
FileName = FileName1 + ".csv";
|
|
CTrainLogFileMgr::instance()->SaveCSVFile(FileName,Log,&mZT2DetectionsLog,mZTStationPtr->GetStationTextualName());
|
|
}
|
|
|
|
DestroyZT2Log();
|
|
|
|
emit NewTrainLogSaved();
|
|
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
bool CZTStateMachine::EnterPGCalibrationMode(int NbPassages)
|
|
{
|
|
if(IsZT1Active())
|
|
return false;
|
|
|
|
if(mZT1WorkerThread->SetPGCalibration(true) == false)
|
|
return false;
|
|
|
|
mIsPGCalibON = true;
|
|
mCalibrationPassagesCount = 0;
|
|
mPGNbTotalPassages = NbPassages;
|
|
DestroyCalibrationData();
|
|
return true;
|
|
}
|
|
|
|
bool CZTStateMachine::QuitPGCalibrationMode()
|
|
{
|
|
if(IsZT1Active())
|
|
return false;
|
|
|
|
if(mZT1WorkerThread->SetPGCalibration(false) == false)
|
|
return false;
|
|
|
|
mIsPGCalibON = false;
|
|
mZT1WorkerThread->SetPGCalibration(false);
|
|
DestroyCalibrationData();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CZTStateMachine::NewPGCalibrationData(CZTPGCalibrationData *NewData)
|
|
{
|
|
// qDebug("NewData %d | %d",NewData->mPGExtValue,NewData->mPGIntValue);
|
|
mZTPGCalibrationData[mCalibrationPassagesCount].append(NewData);
|
|
}
|
|
|
|
unsigned int CZTStateMachine::ComputePGCalibration()
|
|
{
|
|
//Pour déterminer le seuil de détection du pneu de guidage nous
|
|
//appliquons la recette suivante.
|
|
//Pour chaque pneu, on multiplie les valeurs intérieur et extérieur
|
|
//Ensuite on fait moyenne de ce résultat pour tous les frotteurs d'un même train
|
|
//On multiplie cette valeur par un facteur déterminé empiriquement (0.35)
|
|
//On fait ensuite la moyenne de ce résultat pour tous les trains
|
|
//La valeur que lon recherche correspond alors à la racine carrée de cette valeur
|
|
|
|
double Treshold = 0.0;
|
|
|
|
for(unsigned int i = 0; i < mPGNbTotalPassages; i++)
|
|
{
|
|
double Temp = 0;
|
|
for(int sample = 0; sample < mZTPGCalibrationData[i].size(); sample++)
|
|
{
|
|
Temp += (mZTPGCalibrationData[i].at(sample)->mPGExtValue * mZTPGCalibrationData[i].at(sample)->mPGIntValue); //Multiply int and ext samples
|
|
}
|
|
Temp /= mZTPGCalibrationData[i].size(); //Compute the mean value for this train.
|
|
Temp *= 0.35; //multiply by the scaling factor.
|
|
|
|
Treshold += Temp;
|
|
}
|
|
|
|
Treshold /= mPGNbTotalPassages; //Compute the mean value for all the trains.
|
|
Treshold = sqrt(Treshold); //Compute the square root, and we have the treshold value.
|
|
int PGTreshold = (int)Treshold;
|
|
qDebug("Calibration result: %d",PGTreshold);
|
|
|
|
DestroyCalibrationData();
|
|
|
|
emit PGCalibrationFinished(PGTreshold);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
|
|
void CZTStateMachine::SetLogResolution(bool HighResON)
|
|
{
|
|
if(HighResON == true)
|
|
{
|
|
mLogDelay = 0; //Log each data sample.
|
|
}
|
|
else
|
|
{
|
|
mLogDelay = ZT_SM_DEFAULT_LOG_DELAY;
|
|
}
|
|
}
|
|
|
|
void CZTStateMachine::ZT1NewFlag(int FlagID, CZT1FlagsData *FlagData)
|
|
{
|
|
switch(FlagID)
|
|
{
|
|
case ZT1_INT_PG_OFFSET_FLAG_ID:
|
|
{
|
|
mZT1Log.mZT1Flags.mIntPGOffset = FlagData->mIntPGOffset;
|
|
break;
|
|
}
|
|
case ZT1_EXT_PG_OFFSET_FLAG_ID:
|
|
{
|
|
mZT1Log.mZT1Flags.mExtPGOffset = FlagData->mExtPGOffset;
|
|
break;
|
|
}
|
|
case ZT1_PG_TRESHOLD_VALUE_FLAG_ID:
|
|
{
|
|
mZT1Log.mZT1Flags.mPGTresholdValue = FlagData->mPGTresholdValue;
|
|
break;
|
|
}
|
|
case ZT1_PG_CALIB_ON_FLAG_ID:
|
|
{
|
|
mZT1Log.mZT1Flags.mPGCalibrationON = FlagData->mPGCalibrationON;
|
|
break;
|
|
}
|
|
case ZT1_PEQ_TYPE_FLAG_ID:
|
|
{
|
|
mZT1PEQType = FlagData->mPEQ1Type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete FlagData; //We MUST delete this pointer, because the thread will not.
|
|
}
|
|
|
|
|
|
unsigned int CZTStateMachine::SendTKToPCC(int DetectionID, int Rank)
|
|
{
|
|
CZTDetectionData *Detection = new CZTDetectionData();
|
|
Detection->mDetectionID = DetectionID;
|
|
Detection->mRank = Rank;
|
|
|
|
mTKGenerator->UpdateDetectionConfig(mZTDetectionConfig);
|
|
|
|
mTKGenerator->ProcessDetectionsTK(Detection);
|
|
delete Detection;
|
|
|
|
mTKGenerator->BeginTKEmission();
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::EnterMaintenanceMode()
|
|
{
|
|
if(IsZT1Active() || IsZT2Active())
|
|
{
|
|
return RET_ERROR;
|
|
}
|
|
|
|
if(mIsPGCalibON == true)
|
|
{
|
|
return RET_ERROR;
|
|
}
|
|
|
|
if(mTKGenerator->EnterMaintenance() == RET_ERROR)
|
|
{
|
|
return RET_ERROR;
|
|
}
|
|
|
|
mIsMaintenanceModeON = true;
|
|
mZT1ActiveStatus = SB_ZT_DISABLED_STATUS;
|
|
mZT2ActiveStatus = SB_ZT_DISABLED_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
mMaintenancePPIZT1Latch = false;
|
|
mMaintenancePPEZT1Latch = false;
|
|
mMaintenancePPIZT2Latch = false;
|
|
mMaintenancePPEZT2Latch = false;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::QuitMaintenanceMode()
|
|
{
|
|
mIsMaintenanceModeON = false;
|
|
mTKGenerator->ExitMaintenance();
|
|
|
|
mZT1ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZT2ActiveStatus = SB_ZT_INACTIVE_STATUS;
|
|
mZTPagePTr->SetZTStatus(mNbPassages,mNbTriggers,mZT1ActiveStatus,mZT2ActiveStatus);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
unsigned int CZTStateMachine::ClearMaintenanceCurrentTK()
|
|
{
|
|
return mTKGenerator->CancelMaintenanceCurrentTK();
|
|
}
|
|
|
|
|
|
void CZTStateMachine::ClearZT1DetectionsList()
|
|
{
|
|
for(int i = 0; i < mZT1DetectionsLog.size(); i++)
|
|
{
|
|
delete mZT1DetectionsLog.at(i);
|
|
}
|
|
mZT1DetectionsLog.clear();
|
|
}
|
|
|
|
void CZTStateMachine::AddLogStringFromThread(QString logstring)
|
|
{
|
|
CZTLog::instance()->AddLogString(logstring,true);
|
|
}
|
|
|
|
void CZTStateMachine::ModbusCCANUpdate()
|
|
{
|
|
// bool AN1State = false, AN2State = false;
|
|
// AN1State = (mCCModbusRepo->GetSingleReg(MODBUS_CC_AN_BASE_REG_ADD) & MODBUS_CC_AN1_FLAG_MASK) != 0;
|
|
// AN2State = (mCCModbusRepo->GetSingleReg(MODBUS_CC_AN_BASE_REG_ADD) & MODBUS_CC_AN2_FLAG_MASK) != 0;
|
|
// mTKGenerator->SetInputStates(AN1State,mZTStationPtr->IsZT1AlarmAutoAcquireCDVOccupied(),
|
|
// AN2State,mZTStationPtr->IsZT2AlarmAutoAcquireCDVOccupied());
|
|
|
|
// qDebug("Modbus changes: AN1 = %d, AN2 = %d",AN1State,AN2State);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|