#include "radarActions.h" RadarActions::RadarActions( QWidget* parent, int r, int c ) { // Copy pointer locations for other modules and parent widget. parentCP = parent; // Set default values. proc = NULL; procFinished = false; digitalChassisOn = true; runRadarOnce = true; splashQLook = NULL; quickLook = NULL; tcpClient = NULL; // Create the Channel Masks window. chanMaskWindow = new ChannelMasks( c, parentCP, this ); chanMaskWindow->setGeometry( 300, 300, 400, 300 ); chanMaskWindow->hide(); // Create the HDD Status window. hddWin = new HDDWindow( c, parentCP, this ); hddWin->setGeometry( 200, 200, 900, 500 ); hddWin->hide(); // Create the Run Commands window. runCmd = new RunCmd( c, r, chanMaskWindow, parentCP, this ); runCmd->setGeometry( 300, 300, 500, 200 ); runCmd->hide(); // Create the Radar Parameters window. radarParamWindow = new RadarParams( parentCP, this ); radarParamWindow->hide(); // Create the QLook Splash Screen picture. splashQLookPic.load( "misc/qlookpic.png" ); // Copy the other parameters to member variables. rNumber = r; // Radar number. cNumber = c; // Number of channels. hddStatusTimes = new QTime[ cNumber ]; procMount = new QProcess*[ cNumber ]; procMountFinished = new bool[ cNumber ]; procCmd = new QProcess*[ cNumber ]; procCmdFinished = new bool[ cNumber ]; for( int i = 0; i < cNumber; ++i ) { procMount[i] = NULL; procMountFinished[i] = false; procCmd[i] = NULL; procCmdFinished[i] = false; } // Connect the signal to the parent widget for writing a message to the log or changing an LED color. connect( this, SIGNAL( writeMsg( QString, int ) ), parent, SLOT( writeToLog( QString, int ) ) ); connect( this, SIGNAL( changeFeedbackLED( QColor, int ) ), parent, SLOT( changeFeedbackLEDColor( QColor, int ) ) ); connect( this, SIGNAL( changeStatusLED( QColor, int ) ), parent, SLOT( changeStatusLEDColor( QColor, int ) ) ); connect( this, SIGNAL( recSpeed( QString ) ), parent, SLOT( dispDataRate( QString ) ) ); // Create the main layout for the module. layout = new QVBoxLayout; // Create each button and connect it to a function for when it is clicked. buttons[ CONFIG ] = new QPushButton( tr( "Radar Configuration" ) ); connect( buttons[ CONFIG ], SIGNAL( clicked() ), this, SLOT( radarParams() ) ); buttons[ DAQ ] = new QPushButton( tr( "Load DAQ Slices" ) ); connect( buttons[ DAQ ], SIGNAL( clicked() ), this, SLOT( loadDAQSlices() ) ); buttons[ SERVER ] = new QPushButton( tr( "Start Slice Servers" ) ); connect( buttons[ SERVER ], SIGNAL( clicked() ), this, SLOT( startServers() ) ); buttons[ RADARON ] = new QPushButton( tr( "Start Radar" ) ); connect( buttons[ RADARON ], SIGNAL( clicked() ), this, SLOT( startRadar() ) ); buttons[ QLOOK ] = new QPushButton( tr( "Quick-Look Program" ) ); connect( buttons[ QLOOK ], SIGNAL( clicked() ), this, SLOT( startQLook() ) ); buttons[ MOUNT ] = new QPushButton( tr( "Mount HDDs" ) ); connect( buttons[ MOUNT ], SIGNAL( clicked() ), this, SLOT( mountHDD() ) ); buttons[ REC0 ] = new QPushButton( tr( "HDD Record /d0" ) ); connect( buttons[ REC0 ], SIGNAL( clicked() ), this, SLOT( startHDDRec0() ) ); buttons[ REC1 ] = new QPushButton( tr( "HDD Record /d1" ) ); connect( buttons[ REC1 ], SIGNAL( clicked() ), this, SLOT( startHDDRec1() ) ); buttons[ RECOFF ] = new QPushButton( tr( "HDD Recording Off" ) ); connect( buttons[ RECOFF ], SIGNAL( clicked() ), this, SLOT( stopHDDRec() ) ); buttons[ RADAROFF ] = new QPushButton( tr( "Stop Radar" ) ); connect( buttons[ RADAROFF ], SIGNAL( clicked() ), this, SLOT( stopRadar() ) ); buttons[ REBOOT ] = new QPushButton( tr( "Reboot Radar" ) ); connect( buttons[ REBOOT ], SIGNAL( clicked() ), this, SLOT( rebootRadar() ) ); buttons[ SHUTDOWN ] = new QPushButton( tr( "Shutdown Radar" ) ); connect( buttons[ SHUTDOWN ], SIGNAL( clicked() ), this, SLOT( shutdownDialog() ) ); buttons[ MASKS ] = new QPushButton( tr( "Disable Channels" ) ); connect( buttons[ MASKS ], SIGNAL( clicked() ), this, SLOT( showChannelMasks() ) ); buttons[ UNMOUNT ] = new QPushButton( tr( "Unmount Drives" ) ); connect( buttons[ UNMOUNT ], SIGNAL( clicked() ), this, SLOT( unmountHDD() ) ); buttons[ HDDSTATS ] = new QPushButton( tr( "HDD Status" ) ); connect( buttons[ HDDSTATS ], SIGNAL( clicked() ), this, SLOT( showHDDStats() ) ); buttons[ RUNCMD ] = new QPushButton( tr( "Run Commands" ) ); connect( buttons[ RUNCMD ], SIGNAL( clicked() ), this, SLOT( showRunCmd() ) ); buttons[ DONE ] = new QPushButton( tr( "Exit GUI" ) ); connect( buttons[ DONE ], SIGNAL( clicked() ), this, SLOT( exitGUI() ) ); // Add the buttons to the layout. layout->addWidget( buttons[ CONFIG ] ); // Run Radar Configuration Program. layout->addWidget( buttons[ MASKS ] ); // Set Channel Masks. layout->addWidget( buttons[ DAQ ] ); // Load DAQ Slices. layout->addWidget( buttons[ SERVER ] ); // Start Servers. layout->addWidget( buttons[ RADARON] ); // Start Radar. layout->addWidget( buttons[ QLOOK ] ); // Quick Look. layout->addWidget( buttons[ MOUNT ] ); // Mount Drives. layout->addWidget( buttons[ REC0 ] ); // HDD Rec On /d0. layout->addWidget( buttons[ REC1 ] ); // HDD Rec On /d1. layout->addWidget( buttons[ HDDSTATS ] ); // HDD Status. layout->addWidget( buttons[ RECOFF ] ); // HDD Rec Off. layout->addWidget( buttons[ RADAROFF ] ); // Stop Radar. layout->addWidget( buttons[ UNMOUNT ] ); // Unmount Drives. layout->addWidget( buttons[ RUNCMD ] ); // Run Commands. layout->addWidget( buttons[ REBOOT ] ); // Reboot Radar. layout->addWidget( buttons[ SHUTDOWN ] ); // Shutdown Radar. layout->addWidget( buttons[ DONE ] ); // Exit GUI // Set the initial states for each button. buttonState[ CONFIG ] = true; buttonState[ MASKS ] = true; buttonState[ DAQ ] = true; buttonState[ SERVER ] = true; buttonState[ RADARON ] = true; buttonState[ MOUNT ] = true; buttonState[ RECOFF ] = true; buttonState[ REBOOT ] = true; buttonState[ SHUTDOWN ] = true; buttonState[ RADAROFF ] = true; buttonState[ QLOOK ] = true; buttonState[ REC0 ] = true; buttonState[ REC1 ] = true; buttonState[ UNMOUNT ] = true; buttonState[ HDDSTATS ] = true; buttonState[ RUNCMD ] = true; buttonState[ DONE ] = true; // Assume that neither drive bay is mounted. d0Mounted = false; d1Mounted = false; // Recording is disabled. recQLook = false; recHDD = false; // The radar has not been run. radarStarted = false; // Enable/Disable buttons based on state. enableButtons(); } RadarActions::~RadarActions() { chanMaskWindow->hide(); chanMaskWindow->close(); if( chanMaskWindow ) { delete chanMaskWindow; chanMaskWindow = NULL; } hddWin->hide(); hddWin->close(); if( hddWin ) { delete hddWin; hddWin = NULL; } runCmd->hide(); runCmd->close(); if( runCmd ) { delete runCmd; runCmd = NULL; } } QGroupBox* RadarActions::getGroupBox( QString title ) { // Create the group box, title it, and set the layout. raBox = new QGroupBox( tr( title.toStdString().c_str() ) ); raBox->setLayout( layout ); // Return the group box. return raBox; } void RadarActions::enableButtons() { for( int i = 0; i < numButtons; ++i ) { if( i == REC0 ) { if( d0Mounted && buttonState[ REC0 ] && radarStarted ) { buttons[ REC0 ]->setEnabled( true ); } else { buttons[ REC0 ]->setEnabled( false ); } } else if( i == REC1 ) { if( d1Mounted && buttonState[ REC1 ] && radarStarted ) { buttons[ REC1 ]->setEnabled( true ); } else { buttons[ REC1 ]->setEnabled( false ); } } /*else if( i == 12 ) { if( buttonState[12] && buttonState[4] ) { buttons[i]->setEnabled( true ); } else { buttons[i]->setEnabled( false ); } }*/ else { if( buttonState[i] ) { buttons[i]->setEnabled( true ); } else { buttons[i]->setEnabled( false ); } } } } void RadarActions::startQLook() { if( !digitalChassisOn ) { emit writeMsg( "ERROR: Radar is turned off", NORMAL ); } else if( !quickLook ) { emit writeMsg( ">Starting Quick Look", NORMAL ); buttonState[ QLOOK ] = false; // Create the splash screen. if( splashQLook ) { delete splashQLook; splashQLook = NULL; } //splashQLook = new QSplashScreen( splashQLookPic ); //splashQLook->show(); enableButtons(); radarParamWindow->offsetChange(); radarParamWindow->hiChanChange(); quickLook = new QuickLook( rNumber, cNumber, chanMaskWindow, parentCP, this ); quickLook->loadClasses( recQLook, radarParamWindow->getProcessingValues() ); quickLook->resize( 400, 300 ); quickLook->setMaximumHeight( 760 ); radarParamWindow->offsetChange(); radarParamWindow->hiChanChange(); //splashQLook->hide(); //splashQLook->close(); quickLook->show(); } } void RadarActions::closeQLook() { if( quickLook ) { emit writeMsg( ">Closed Quick Look", NORMAL ); quickLook->close(); delete quickLook; quickLook = NULL; buttonState[ QLOOK ] = true; enableButtons(); emit changeFeedbackLED( Qt::red, numLEDs ); } } void RadarActions::mountHDD() { if( digitalChassisOn ) { emit writeMsg( ">Mounting HDDs", NORMAL ); disableButtons(); d0Mounted = false; d1Mounted = false; // Setup the commands and processes. QString cmd[ cNumber ]; QStringList args[ cNumber ]; QString chanNum; QString radarNum; radarNum.setNum( rNumber ); for( int j = 0; j < cNumber; ++j ) { cmd[j] = "ssh"; chanNum.setNum( j+1 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "cd "; script.append( PATH_MCORDS ); script.append( "; ./mount_and_check.sh /d0 /d1" ); args[j] << server << script; if( procMount[j] ) { delete procMount[j]; procMount[j] = NULL; } procMount[j] = new QProcess( this ); connect( procMount[j], SIGNAL( finished( int ) ), this, SLOT( mountHDDFin() ) ); // None of the processes have finished. procMountFinished[j] = false; } // Run the proccesses. for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->hddMasked( k ) ) { chanNum.setNum( k+1 ); procMount[k]->start( cmd[k], args[k] ); emit writeMsg( "Mounting drives on slice " + chanNum, NORMAL ); } } // Check to see if all of the hdds were masked. if( chanMaskWindow->hddMaskedNum() == cNumber ) { enableButtons(); } } else { emit writeMsg( "ERROR: Radar is turned off.", NORMAL ); } } void RadarActions::mountHDDFin() { // Check to see if every process has finished. If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procMount[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->hddMasked( i ) ) { allFinished = false; if( !procMountFinished[i] ) { procMountFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "Mount command finished for slice " + chanNum, NORMAL ); } } } for( int k = 0; k < cNumber; ++k ) { if( !procMountFinished[k] && !chanMaskWindow->hddMasked( k ) ) { procMountFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "Mount command finished for slice " + chanNum, NORMAL ); } } // DEBUG if( allFinished ) { emit writeMsg( "All processes finished for mounting.", DEBUG ); } else { emit writeMsg( "Processes not finished for mounting.", DEBUG ); } // Initialize two variables to keep track of how many slices mounted properly. int d0 = 0, d1 = 0; // Channel number in a QString. QString chanNum; // Check the exit codes to see if drives mounted on each slice properly. if( allFinished ) { // Run through every channel. for( int j = 0; j < cNumber; ++j ) { // Check if the current channel has been masked. if( !chanMaskWindow->hddMasked( j ) ) { chanNum.setNum( j+1 ); // Look at the error code for each process and write a message based on the code. int eCode = procMount[j]->exitCode(); if( eCode == 0 ) { QString errorMsg = "ERROR: NO DRIVE MOUNTED FOR SLICE "; errorMsg.append( chanNum ); emit writeMsg( errorMsg, NORMAL ); } else if( eCode == 1 ) { QString newText = "Hard drive was mounted on d0."; emit writeMsg( newText, NORMAL ); d0++; } else if( eCode == 2 ) { QString newText = "Hard drive was mounted on d1."; emit writeMsg( newText, NORMAL ); d1++; } else if( eCode == 3 ) { QString newText = "Hard drive was mounted on d0 and d1."; emit writeMsg( newText, NORMAL ); d0++; d1++; } else { QString errorMsg = "ERROR: BAD RETURN CODE FOR SLICE "; errorMsg.append( chanNum ); emit writeMsg( errorMsg, NORMAL ); } } } // Find the number of masked hdds and subtract it from the total number of channels. int count = cNumber - chanMaskWindow->hddMaskedNum(); if( !( ( d0 == count ) || ( d1 == count ) ) ) { emit writeMsg( ">ERROR: DRIVES NOT MOUNTED ON EVERY SLICE", NORMAL ); } if( d0 == count ) { // Set HDD Rec D0 to enabled. d0Mounted = true; emit writeMsg( ">Drive pack d0 mounted on all slices.", NORMAL ); } if( d1 == count ) { // Set HDD Rec D1 to enabled. d1Mounted = true; emit writeMsg( ">Drive pack d1 mounted on all slices.", NORMAL ); } buttonState[ REC0 ] = true; buttonState[ REC1 ] = true; buttonState[ RECOFF ] = true; enableButtons(); } } void RadarActions::unmountHDD() { emit writeMsg( ">Unmounting HDDs", NORMAL ); disableButtons(); // Disable buttons while processes are running. // If current recording to HDDs, turn off recording. if( recHDD ) { stopHDDRec(); } // /d0 and /d1 will not be mounted by the end of the processes. d0Mounted = false; d1Mounted = false; // Setup the commands and processes. QString cmd[ cNumber ]; QStringList args[ cNumber ]; QString chanNum; QString radarNum; radarNum.setNum( rNumber ); for( int j = 0; j < cNumber; ++j ) { cmd[j] = "ssh"; chanNum.setNum( j+1 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "umount /d0; umount /d1"; args[j] << server << script; if( procMount[j] ) { delete procMount[j]; procMount[j] = NULL; } procMount[j] = new QProcess( this ); connect( procMount[j], SIGNAL( finished( int ) ), this, SLOT( unmountHDDFin() ) ); // None of the processes have finished. procMountFinished[j] = false; } // Run the proccesses. for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->hddMasked( k ) ) { chanNum.setNum( k+1 ); procMount[k]->start( cmd[k], args[k] ); emit writeMsg( "Unmounting drives on slice " + chanNum, NORMAL ); } } // Check to see if all of the hdds were masked. if( chanMaskWindow->hddMaskedNum() == cNumber ) { enableButtons(); } } void RadarActions::unmountHDDFin() { // Check to see if every process has finished. If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procMount[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->hddMasked( i ) ) { allFinished = false; if( !procMountFinished[i] ) { procMountFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "Unmount command finished for slice " + chanNum, NORMAL ); } } } // All of the processes have finished. if( allFinished ) { // Write out a message for the last process to finish. for( int k = 0; k < cNumber; ++k ) { if( !procMountFinished[k] && !chanMaskWindow->hddMasked( k ) ) { procMountFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "Unmount command finished for slice " + chanNum, NORMAL ); } } // Disable the recording buttons as the HDDs are not mounted anymore. buttonState[ REC0 ] = false; buttonState[ REC1 ] = false; buttonState[ RECOFF ] = false; // Enable the buttons. enableButtons(); // Write a message that the processes are all finished. emit writeMsg( ">All HDDs are now unmounted.", NORMAL ); } } void RadarActions::radarParams() { emit writeMsg( ">Starting Radar Parameter Configuration", NORMAL ); //radarParamWindow->show(); radarParamWindow->showMaximized(); } void RadarActions::startHDDRec0() { if( radarStarted ) { for( int i = 0; i < numButtons; ++i ) { buttons[i]->setEnabled( false ); } const char* c = "0"; sendCharServer( c ); recHDD = true; buttonState[ REC0 ] = false; enableButtons(); emit writeMsg( ">Turned On HDD Recording /d0", NORMAL ); emit changeStatusLED( Qt::green, REC ); //hddRecLabel = 0; } else { emit writeMsg( "ERROR: Radar is turned off.", NORMAL ); } } void RadarActions::startHDDRec1() { if( radarStarted ) { for( int i = 0; i < numButtons; ++i ) { buttons[i]->setEnabled( false ); } const char* c = "1"; sendCharServer( c ); recHDD = true; buttonState[ REC1 ] = false; enableButtons(); emit writeMsg( ">Turned On HDD Recording /d1", NORMAL ); emit changeStatusLED( Qt::green, REC ); //hddRecLabel = 1; } else { emit writeMsg( "ERROR: Radar is turned off.", NORMAL ); } } void RadarActions::stopHDDRec() { //if( radarOn ) //{ for( int i = 0; i < numButtons; ++i ) { buttons[i]->setEnabled( false ); } const char* c = "X"; sendCharServer( c ); recHDD = false; buttonState[ REC0 ] = true; buttonState[ REC1 ] = true; enableButtons(); emit writeMsg( ">Turned Off HDD Recording", NORMAL ); // Change the Status LED lights. emit changeStatusLED( Qt::red, REC ); // Delete the tcpClients for each slice; for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->hddMasked( k ) && tcpClient[k] ) { tcpClient[k]->close(); delete tcpClient[k]; tcpClient[k] = NULL; } } if( tcpClient ) { delete [] tcpClient; tcpClient = NULL; } //} //else //{ //emit writeMsg( "ERROR: Radar is turned off.", NORMAL ); //} } void RadarActions::sendCharServer( const char* letter ) { // Create the TCP Socket objects. if( !tcpClient ) { emit writeMsg( "Create new socket connections to servers.", NORMAL ); tcpClient = new QTcpSocket*[ cNumber ]; // Create the server strings and setup the sockets. for( int i = 0; i < cNumber; ++i ) { QString host = "10.14."; QString tempRad; QString tempChan; tempRad.setNum( rNumber ); tempChan.setNum( i+1 ); host.append( tempRad ); host.append( "." ); host.append( tempChan ); if( !chanMaskWindow->hddMasked( i ) ) { tcpClient[i] = new QTcpSocket(); tcpClient[i]->connectToHost( host, HDDPORT, QIODevice::ReadWrite ); connect( tcpClient[i], SIGNAL( readyRead() ), this, SLOT( readLinesSockets() ) ); } } // Wait for every client to be connected. for( int j = 0; j < cNumber; ++j ) { if( !chanMaskWindow->hddMasked( j ) ) { QString chanNum; chanNum.setNum( j+1 ); emit writeMsg( "Waiting to connect to slice " + chanNum, NORMAL ); tcpClient[j]->waitForConnected(); } } // All clients are now connected, write characters to servers. emit writeMsg( "All slices connected, writing character to servers.", NORMAL ); } for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->hddMasked( k ) ) { hddStatusTimes[k].start(); if( tcpClient[k]->write( letter, qstrlen( letter ) ) == -1 ) { //QErrorMessage* msgD = new QErrorMessage( this ); //msgD->showMessage( "Error writing character to server." ); QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( ">ERROR: Error writing character to server on channel " + chanNum, NORMAL ); } tcpClient[k]->flush(); } } emit writeMsg( "All characters written to server.", NORMAL ); } void RadarActions::readLinesSockets() { for( int i = 0; i < cNumber; ++i ) { if( !chanMaskWindow->hddMasked( i ) ) { while( tcpClient[i]->canReadLine() ) { // First, see if we're getting a stall warning or HDD information. QString outputChar = tcpClient[i]->read( 1 ); if( outputChar.toStdString() == "Z" ) // HDD information { double secs = 0.0; if( hddStatusTimes[i].elapsed() != 0 ) { secs = hddStatusTimes[i].elapsed() / 1000.0; hddStatusTimes[i].start(); } QString totalSpace = tcpClient[i]->readLine(); QString usedSpace = tcpClient[i]->readLine(); QString tmp = tcpClient[i]->readAll(); hddWin->hddStatusData( i, totalSpace, usedSpace, secs ); } if( outputChar.toStdString() == "S" ) // Stall warning. { QString outputTxt = tcpClient[i]->readLine(); QString timeStamp = tcpClient[i]->readLine(); //QString tmp = tcpClient[i]->readAll(); QString chNum; chNum.setNum( i + 1 ); outputTxt.prepend( chNum + " - " ); outputTxt.prepend( ") Channel " ); outputTxt.prepend( timeStamp ); outputTxt.prepend( "(" ); emit writeMsg( outputTxt, NORMAL ); } } } } } void RadarActions::showChannelMasks() { chanMaskWindow->show(); } void RadarActions::startRadar() { disableButtons(); // Disable all of the buttons while the radar is started. // Turn off HDD recording if it is currently enabled. if( recHDD ) { stopHDDRec(); } // First, scp config_radar.txt to the control slice. QString cmdSCP = "scp"; QStringList argsSCP; QString file, newFile, radFile; file = QDir::currentPath(); file.append( "/radar_configs/config_radar.txt" ); radFile.setNum( rNumber ); newFile.append( "root@10.14." ); newFile.append( radFile ); newFile.append( ".100:" ); newFile.append( PATH_WFG ); newFile.append( "/config_radar.txt" ); argsSCP << file << newFile; // Run the process and wait for completion. QProcess* scp = new QProcess( this ); if( runRadarOnce ) { emit writeMsg( ">Copying configuration file to control slice.", NORMAL ); } scp->start( cmdSCP, argsSCP ); scp->waitForFinished(); if( scp->exitCode() != 0 ) { emit writeMsg( "ERROR: Problem using scp to move configuration file to control slice.", NORMAL ); } delete scp; scp = NULL; // Second, copy the config_radar.txt file to a new file with a timestamp on it. QString cmdCP = "cp"; QStringList argsCP; QString oldF, newF; oldF = QDir::currentPath(); oldF.append( "/radar_configs/config_radar.txt" ); newF = QDir::currentPath(); newF.append( "/radar_configs/config_radar.txt." ); newF.append( timeStamp() ); argsCP << oldF << newF; // Run the process and wait for completion. QProcess* cp = new QProcess( this ); if( runRadarOnce ) { emit writeMsg( ">Copying configuration file locally with a timestamp.", NORMAL ); } cp->start( cmdCP, argsCP ); cp->waitForFinished(); if( cp->exitCode() != 0 ) { emit writeMsg( "ERROR: Problem using cp to copy configuration file.", NORMAL ); } delete cp; cp = NULL; // Third, copy the config_radar.bin file to each slice. QString* cmdSCPs = new QString[ cNumber ]; QStringList* argsSCPs = new QStringList[ cNumber ]; for( int z = 0; z < cNumber; ++z ) { cmdSCPs[z] = "scp"; QString file, newFile, radFile, cFile; file = QDir::currentPath(); file.append( "/radar_configs/config_radar.bin" ); radFile.setNum( rNumber ); cFile.setNum( z + 1 ); newFile.append( "root@10.14." ); newFile.append( radFile ); newFile.append( "." ); newFile.append( cFile ); newFile.append( ":" ); newFile.append( PATH_WFG ); newFile.append( "/config_radar.bin" ); argsSCPs[z] << file << newFile; } // Run the processes and wait for completion. QProcess** scps = new QProcess*[ cNumber ]; if( runRadarOnce ) { emit writeMsg( ">Copying binary configuration file to each channel.", NORMAL ); } for( int y = 0; y < cNumber; ++y ) { scps[y] = new QProcess( this ); scps[y]->start( cmdSCPs[y], argsSCPs[y] ); } for( int x = 0; x < cNumber; ++x ) { scps[x]->waitForFinished(); if( scps[x]->exitCode() != 0 ) { QString chan; chan.setNum( x + 1 ); emit writeMsg( "ERROR: SCP to channel " + chan + " did not work correctly.", NORMAL ); } } if( runRadarOnce ) { emit writeMsg( ">Starting Radar", NORMAL ); // Message to log. } // Generate the command to run. QString cmd = "ssh"; QStringList args; QString rad, chan, server, script, option, timeout; option = "-o"; timeout = "ConnectTimeout=5"; rad.setNum( rNumber ); chan.setNum( 100 ); server.append( "root@10.14." ); server.append( rad ); server.append( "." ); server.append( chan ); script = "cd "; script.append( PATH_WFG ); script.append( "/; ./radar" ); args << option << timeout << server << script; // Delete the old proc object if it exists. if( proc ) { delete proc; proc = NULL; } // Create a new QProcess object, connect it to functions, and start it. proc = new QProcess( this ); connect( proc, SIGNAL(finished( int ) ), this, SLOT( startRadarFin() ) ); connect( proc, SIGNAL( readyRead() ), this, SLOT( readLinesProc() ) ); proc->start( cmd, args ); //emit writeMsg( server, DEBUG ); //emit writeMsg( script, DEBUG ); } void RadarActions::startRadarFin() { readLinesProc(); // Read in any extra lines after the process is finished. if( !runRadarOnce ) { emit writeMsg( ">Radar is now running.", NORMAL ); // Write message to log. } buttonState[ SHUTDOWN ] = true; buttonState[ MOUNT ] = true; emit changeStatusLED( Qt::green, RADAR ); radarStarted = true; enableButtons(); // Enable the correct buttons. if( runRadarOnce ) { runRadarOnce = false; startRadar(); } else { runRadarOnce = true; } } void RadarActions::stopRadar() { disableButtons(); // Disable all of the buttons while the radar is started. emit writeMsg( ">Stopping Radar", NORMAL ); // Message to log. // Generate the command to run. QString cmd = "ssh"; QStringList args; QString rad, chan, server, script, option, timeout; option = "-o"; timeout = "ConnectTimeout=5"; rad.setNum( rNumber ); chan.setNum( 100 ); server.append( "root@10.14." ); server.append( rad ); server.append( "." ); server.append( chan ); script = "cd "; script.append( PATH_WFG ); script.append( "; ./radaroff" ); args << option << timeout << server << script; // Delete the old proc object if it exists. if( proc ) { delete proc; proc = NULL; } // Create a new QProcess object, connect it to functions, and start it. proc = new QProcess( this ); connect( proc, SIGNAL(finished( int ) ), this, SLOT( stopRadarFin() ) ); connect( proc, SIGNAL( readyRead() ), this, SLOT( readLinesProc() ) ); proc->start( cmd, args ); //emit writeMsg( server, DEBUG ); //emit writeMsg( script, DEBUG ); } void RadarActions::stopRadarFin() { stopHDDRec(); // Stop recording on the HDD (if recording is on). readLinesProc(); // Read in any extra lines after the process is finished. emit writeMsg( ">Radar is now off.", NORMAL ); // Write message to log. buttonState[ REC1 ] = false; buttonState[ REC0 ] = false; emit changeStatusLED( Qt::red, RADAR ); radarStarted = false; enableButtons(); // Enable the correct buttons. } void RadarActions::rebootRadar() { emit writeMsg( ">Rebooting the radar", NORMAL ); disableButtons(); d0Mounted = false; d1Mounted = false; // Setup the commands and processes for the normal slices. QString cmd[ cNumber ]; QStringList args[ cNumber ]; QString chanNum; QString radarNum; radarNum.setNum( rNumber ); for( int j = 0; j < cNumber; ++j ) { cmd[j] = "ssh"; chanNum.setNum( j+1 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "pkill server; umount /d0; umount /d1; reboot"; args[j] << server << script; if( procCmd[j] ) { delete procCmd[j]; procCmd[j] = NULL; } procCmd[j] = new QProcess( this ); connect( procCmd[j], SIGNAL( finished( int ) ), this, SLOT( rebootRadarFin() ) ); // None of the processes have finished. procCmdFinished[j] = false; } // Second, create the control slice process. QString cmdC = "ssh"; QStringList argsC; chanNum.setNum( 100 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); //QString script = "reboot"; QString script = "cd "; script.append( PATH_WFG ); script.append( "; ./radaroff; cd ~; pkill server; umount /d0; umount /d1; reboot" ); argsC << server << script; //emit writeMsg( server, DEBUG ); if( proc ) { delete proc; proc = NULL; } proc = new QProcess( this ); connect( proc, SIGNAL( finished( int ) ), this, SLOT( rebootRadarFin() ) ); // The control process has not finished yet. procFinished = false; // Run the proccesses. for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->chanMasked( k ) ) { chanNum.setNum( k+1 ); procCmd[k]->start( cmd[k], args[k] ); emit writeMsg( "Rebooting slice " + chanNum, NORMAL ); } } proc->start( cmdC, argsC ); emit writeMsg( "Rebooting slice C", NORMAL ); //emit writeMsg( script, DEBUG ); } void RadarActions::rebootRadarFin() { // Check if every process has finished. // If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procCmd[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->hddMasked( i ) ) { allFinished = false; if( !procCmdFinished[i] ) { procCmdFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "Slice " + chanNum + " reboot started", NORMAL ); } } } if( proc->state() != QProcess::NotRunning ) { allFinished = false; if( !procFinished ) { procFinished = true; emit writeMsg( "Slice C reboot started", NORMAL ); } } // All of the processes have finished. if( allFinished ) { // Write out a message for the last process to finish. for( int k = 0; k < cNumber; ++k ) { if( !procCmdFinished[k] && !chanMaskWindow->hddMasked( k ) ) { procCmdFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "Slice " + chanNum + " reboot started", NORMAL ); } if( !procFinished ) { procFinished = true; emit writeMsg( "Slice C reboot started", NORMAL ); } } // Write a message that the processes are all finished. emit writeMsg( ">All channels have started the reboot process.", NORMAL ); QTimer* timer = new QTimer( this ); connect( timer, SIGNAL( timeout() ), this, SLOT( pingChannels() ) ); timer->setSingleShot( true ); timer->start( 15000 ); } } void RadarActions::pingChannels() { //Write message to say we are pining the channels. emit writeMsg( "Pinging channels to determine when reboot sequence has finished.", NORMAL ); // Ping every channel. Know a channel is rebooting when the ping command is successful. QString radarNum; radarNum.setNum( rNumber ); for( int m = 0; m < cNumber; ++m ) { // Setup the ping command. QString cmd = "ping"; QStringList args; // Ping command arguments. QString opt1 = "-c"; QString opt2 = "1"; QString opt3 = "-w"; QString opt4 = "5"; // Setup the server. QString chNum; chNum.setNum( m + 1 ); QString server = "10.14."; server.append( radarNum ); server.append( "." ); server.append( chNum ); args << server << opt1 << opt2 << opt3 << opt4; // Create the process. QProcess* pingProc = new QProcess( this ); // Keep running the command until successful. int res = 1; while( res == 1 ) { pingProc->start( cmd, args ); pingProc->waitForFinished(); res = pingProc->exitCode(); } delete pingProc; emit writeMsg( "Finished rebooting channel " + chNum, NORMAL ); } // Enable the correct buttons. enableButtons(); // Write message that the process is now complete. emit writeMsg( ">Rebooting process is complete.", NORMAL ); } void RadarActions::shutdownDialog() { // Disable the buttons. disableButtons(); // Create a message box to make sure the user wants to shutdown the radar. // Shutting down the radar requires a power cycle to turn back on. QMessageBox* shutdownMsg = new QMessageBox( parentCP ); shutdownMsg->setText( "Shutdown." ); shutdownMsg->setInformativeText( "Are you sure you want to shutdown the slices? Turning them on again will require cycling the power." ); shutdownMsg->setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel ); shutdownMsg->setDefaultButton( QMessageBox::Cancel ); int ret = shutdownMsg->exec(); // Wait for the window to close and grab the return value. // If the return value was OK, then proceed with shutting down the radar. if( ret == QMessageBox::Ok ) { shutdownRadar(); digitalChassisOn = false; } // The user did not want to proceed, so enable the buttons. else { enableButtons(); } } void RadarActions::shutdownRadar() { emit writeMsg( ">Shutting down the radar", NORMAL ); disableButtons(); d0Mounted = false; d1Mounted = false; // Setup the commands and processes for the normal slices. QString cmd[ cNumber ]; QStringList args[ cNumber ]; QString chanNum; QString radarNum; radarNum.setNum( rNumber ); for( int j = 0; j < cNumber; ++j ) { cmd[j] = "ssh"; chanNum.setNum( j+1 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "pkill server; umount /d0; umount /d1; halt"; args[j] << server << script; if( procCmd[j] ) { delete procCmd[j]; procCmd[j] = NULL; } procCmd[j] = new QProcess( this ); connect( procCmd[j], SIGNAL( finished( int ) ), this, SLOT( shutdownRadarFin() ) ); // None of the processes have finished. procCmdFinished[j] = false; } // Second, create the control slice process. QString cmdC = "ssh"; QStringList argsC; chanNum.setNum( 100 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "cd "; script.append( PATH_WFG ); script.append( "; ./radaroff; halt" ); argsC << server << script; writeMsg( server, DEBUG ); writeMsg( script, DEBUG ); if( proc ) { delete proc; proc = NULL; } proc = new QProcess( this ); connect( proc, SIGNAL( finished( int ) ), this, SLOT( shutdownRadarFin() ) ); // The control process has not finished yet. procFinished = false; // Run the proccesses. for( int k = 0; k < cNumber; ++k ) { if( !chanMaskWindow->hddMasked( k ) ) { chanNum.setNum( k+1 ); procCmd[k]->start( cmd[k], args[k] ); emit writeMsg( "Shutting down slice " + chanNum, NORMAL ); } } proc->start( cmdC, argsC ); emit writeMsg( "Shutting down slice C", NORMAL ); //emit writeMsg( script, DEBUG ); } void RadarActions::shutdownRadarFin() { // Check if every process has finished. // If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procCmd[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->hddMasked( i ) ) { allFinished = false; if( !procCmdFinished[i] ) { procCmdFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "Slice " + chanNum + " shutdown", NORMAL ); } } } if( proc->state() != QProcess::NotRunning ) { allFinished = false; if( !procFinished ) { procFinished = true; emit writeMsg( "Slice C shutdown", NORMAL ); } } // All of the processes have finished. if( allFinished ) { // Write out a message for the last process to finish. for( int k = 0; k < cNumber; ++k ) { if( !procCmdFinished[k] && !chanMaskWindow->hddMasked( k ) ) { procCmdFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "Slice " + chanNum + " shutdown", NORMAL ); } if( !procFinished ) { procFinished = true; emit writeMsg( "Slice C shutdown", NORMAL ); } } // Enable the correct buttons. enableButtons(); // Write a message that the processes are all finished. emit writeMsg( ">All channels have been shutdown.", NORMAL ); } } void RadarActions::loadDAQSlices() { // Write a message about what is happening. emit writeMsg( ">Loading DAQ Slices", NORMAL ); // Disable buttons and turn the Radar LED off, as the radar program on the control // slice will need to be run again. disableButtons(); emit changeStatusLED( Qt::red, RADAR ); //radarOn = false; //radarStarted = false; // Setup the commands and processes to run. QString cmd[ cNumber ]; QStringList args[ cNumber ]; QString chanNum; QString radarNum; radarNum.setNum( rNumber ); for( int i = 0; i < cNumber; ++i ) { cmd[i] = "ssh"; chanNum.setNum( i+1 ); QString server = "root@10.14."; server.append( radarNum ); server.append( "." ); server.append( chanNum ); QString script = "cd "; script.append( PATH_DAQ ); script.append( "; ./radar" ); args[i] << server << script; if( procCmd[i] ) { delete procCmd[i]; procCmd[i] = NULL; } procCmd[i] = new QProcess( this ); connect( procCmd[i], SIGNAL( finished( int ) ), this, SLOT( loadDAQSlicesFin() ) ); // None of the processes have finished. procCmdFinished[i] = false; } // Run the processes. for( int j = 0; j < cNumber; ++j ) { if( !chanMaskWindow->chanMasked( j ) ) { chanNum.setNum( j+1 ); procCmd[j]->start( cmd[j], args[j] ); emit writeMsg( "Loading FPGA on DAQ slice " + chanNum, NORMAL ); } } // Check if all channels have been masked. if( chanMaskWindow->chanMaskedNum() == cNumber ) { // Enable buttons because no processes will be run. enableButtons(); } } void RadarActions::loadDAQSlicesFin() { // Check if every process has finished. // If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procCmd[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->chanMasked( i ) ) { allFinished = false; if( !procCmdFinished[i] ) { procCmdFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "FPGA loaded on slice " + chanNum, NORMAL ); } } } // All of the processes have finished. if( allFinished ) { // Write out a message for the last process to finish. for( int k = 0; k < cNumber; ++k ) { if( !procCmdFinished[k] && !chanMaskWindow->chanMasked( k ) ) { procCmdFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "FPGA loaded on slice " + chanNum, NORMAL ); } } // Enable the correct buttons. enableButtons(); // Write a message that the processes are all finished. emit writeMsg( ">All DAQs are now loaded.", NORMAL ); emit writeMsg( ">Make sure to start the radar again.", NORMAL ); } } void RadarActions::startServers() { // Write a message about what is happening. emit writeMsg( ">Starting servers on slices.", NORMAL ); // Disable buttons. disableButtons(); // Create the process to run on each slice. // Create some variables to use. QString radNum; radNum.setNum( rNumber ); QString chanNum; QString cmd[ cNumber ]; QStringList args[ cNumber ]; // First, create the n Rx slice processes. for( int i = 0; i < cNumber; ++i ) { cmd[i] = "ssh"; chanNum.setNum( i+1 ); QString server = "root@10.14."; server.append( radNum ); server.append( "." ); server.append( chanNum ); QString script = "pkill server_hi; pkill server_rec; cd "; script.append( PATH_SER ); script.append( "; mv server_hi.err server_hi.err.old; mv server_hi.out server_hi.out.old; nohup ./server_hi > server_hi.out 2> server_hi.err < /dev/null & nohup ./server_rec > /dev/null 2> /dev/null < /dev/null &" ); args[i] << server << script; if( procCmd[i] ) { delete procCmd[i]; procCmd[i] = NULL; } procCmd[i] = new QProcess( this ); connect( procCmd[i], SIGNAL( finished( int ) ), this, SLOT( startServersFin() ) ); // None of the processes have finished. procCmdFinished[i] = false; } // Second, create the control slice process. QString cmdC = "ssh"; QStringList argsC; chanNum.setNum( 100 ); QString server = "root@10.14."; server.append( rNumber ); server.append( "." ); server.append( chanNum ); QString script = "pkill server_hi; pkill server_rec; cd "; script.append( PATH_SER ); script.append( "; mv server_hi.err server_hi.err.old; mv server_hi.out server_hi.out.old; nohup ./server_hi > server_hi.out 2> server_hi.err < /dev/null & nohup ./server_rec > /dev/null 2> /dev/null < /dev/null &" ); argsC << server << script; if( proc ) { delete proc; proc = NULL; } proc = new QProcess( this ); connect( proc, SIGNAL( finished( int ) ), this, SLOT( startServersFin() ) ); // The control process has not finished yet. procFinished = false; // Run the processes. for( int j = 0; j < cNumber; ++j ) { if( !chanMaskWindow->chanMasked( j ) ) { chanNum.setNum( j+1 ); procCmd[j]->start( cmd[j], args[j] ); emit writeMsg( "Starting servers on slice " + chanNum, NORMAL ); } } proc->start( cmdC, argsC ); emit writeMsg( "Starting servers on slice C", NORMAL ); //emit writeMsg( script, DEBUG ); } void RadarActions::startServersFin() { // Check if every process has finished. // If a process is not running, it has finished. bool allFinished = true; for( int i = 0; i < cNumber; ++i ) { if( ( procCmd[i]->state() != QProcess::NotRunning ) && !chanMaskWindow->chanMasked( i ) ) { allFinished = false; if( !procCmdFinished[i] ) { procCmdFinished[i] = true; QString chanNum; chanNum.setNum( i+1 ); emit writeMsg( "Servers started on slice " + chanNum, NORMAL ); } } } if( proc->state() != QProcess::NotRunning ) { allFinished = false; if( !procFinished ) { procFinished = true; emit writeMsg( "Servers started on slice C", NORMAL ); } } // All of the processes have finished. if( allFinished ) { // Write out a message for the last process to finish. for( int k = 0; k < cNumber; ++k ) { if( !procCmdFinished[k] && !chanMaskWindow->chanMasked( k ) ) { procCmdFinished[k] = true; QString chanNum; chanNum.setNum( k+1 ); emit writeMsg( "Servers started on slice " + chanNum, NORMAL ); } if( !procFinished ) { procFinished = true; emit writeMsg( "Servers started on slice C", NORMAL ); } } // Enable the correct buttons. enableButtons(); // Write a message that the processes are all finished. emit writeMsg( ">All servers have been started.", NORMAL ); } } void RadarActions::readLinesProc() { while( proc->canReadLine() ) { QString outputTxt = proc->readLine(); if( runRadarOnce ) { emit writeMsg( outputTxt, NORMAL ); } } } void RadarActions::disableButtons() { for( int i = 0; i < numButtons; ++i ) { buttons[i]->setEnabled( false ); } } void RadarActions::showHDDStats() { hddWin->show(); } void RadarActions::showRunCmd() { //runCmd->show(); runCmd->displayWindow(); } void RadarActions::writeLog( QString t, int type ) { emit writeMsg( t, type ); } void RadarActions::dispDataRate( QString msg ) { emit recSpeed( msg ); hddWin->setEstRecTime( msg ); } void RadarActions::offsetChanged( double offset ) { if( quickLook ) { quickLook->setOffset( offset ); } } void RadarActions::setTau( double tau ) { if( quickLook ) { quickLook->setNewTau( tau ); } } QString RadarActions::timeStamp() { time_t rawtime; struct tm* timeInfo; char buffer[80]; time( &rawtime ); timeInfo = localtime( &rawtime ); strftime( buffer, 80, "%Y%m%d_%H%M%S", timeInfo ); QString output = buffer; return output; } void RadarActions::exitGUI() { parentCP->close(); } void RadarActions::themeSound( bool toggle ) { hddWin->themeGood( toggle ); }