/************/ /* Includes */ /************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for lexical_cast() #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dbObject.hh" // The following ifdef is here because something above defines "slots" macro as empty string // and include file for shared memory doe snot compile when it gets included and preprocessed. #ifdef slots #undef slots #endif #include "jlabSSPDIRCBoard.hh" using namespace std; string Get_IPAddress( void ); int Get_ROCID( void ); void Format_Name( string& locString ); bool gDebugFlag = false; extern "C" { #include "asynDrvChassis.h" #include "asynDrvBoard.h" // Actual function for temporarily hooking Paul's software from the IOC script char* hook4Paul( const char *ttFileName = 0, int intPar = 0 ) { // We need to register database entries with EPICS // Interface to the database David uses to build the translation table // Create entries based on that: one for each crate/board/channel, and then alias it to the real detector component cout << "Hookup function is called" << endl; // Get ROC ID from IP Address int locROCID = Get_ROCID(); cout << "This roc id = " << locROCID << endl; // Open the translation table cout << "open database" << endl; string locSQLitePath = "sqlite:///gluex/etc/tt.db"; if ( ttFileName != 0 ) { locSQLitePath = string( ttFileName ); } QSqlDatabase locSQLDatabase = dbObject::openDB( locSQLitePath ); cout << "db opened" << endl; // Get the crate id and type QSqlQuery locCrateSQLQuery( locSQLDatabase ); QString locCrateQueryString = QString( "SELECT crateid, name, Function FROM Crate WHERE rocid='%1'" ).arg( locROCID ); if ( gDebugFlag ) cout << locCrateQueryString.toStdString() << endl; locCrateSQLQuery.prepare( locCrateQueryString ); locCrateSQLQuery.exec(); //get the first (and better-be-only) crate entry if ( !locCrateSQLQuery.next() ) { cout << "ERROR, BAD ROC ID. ABORTING" << endl; abort(); } // process the crate entry int locGlobalCrateID = locCrateSQLQuery.value( 0 ).toInt(); string locCrateName = locCrateSQLQuery.value( 1 ).toString().toStdString(); Format_Name( locCrateName ); //replace all "-" with ":" string locCrateFunction = locCrateSQLQuery.value( 2 ).toString().toStdString(); if ( (locCrateFunction != "fADC250") && (locCrateFunction != "DISC") && (locCrateFunction != "SSPDIRC") ) { cout << "WARNING, NO/UN-SUPPORTED SCALAR READOUT FOR THIS CRATE " << locCrateFunction << " . ABORTING" << endl; abort(); } cout << "Crate function is <" << locCrateFunction << ">" << endl; //Make asyn driver config call for crate ostringstream locCratePortStream; locCratePortStream << "ROC" << locROCID; if ( locCrateFunction == "DISC" ) asynDrvDiscChassisConfig( locCratePortStream.str().c_str() ); else if ( locCrateFunction == "fADC250" ) asynDrvFADCChassisConfig( locCratePortStream.str().c_str() ); else if ( locCrateFunction == "SSPDIRC" ) asynDrvSSPDIRCChassisConfig( locCratePortStream.str().c_str() ); //Load db record for crate ostringstream locMacroSubstitutions_Crate; locMacroSubstitutions_Crate << "P=Scalars,PORT=" << locCratePortStream.str() << ",CRATE_NAME=" << locCrateName; string locDBRecordPath_Crate = "db/vmeCrate.db"; if ( gDebugFlag ) cout << "Crate macro sub string: " << locMacroSubstitutions_Crate.str() << endl; dbLoadRecords( locDBRecordPath_Crate.c_str(), locMacroSubstitutions_Crate.str().c_str() ); // Get all of the modules in this crate QSqlQuery locModuleSQLQuery( locSQLDatabase ); QString locModuleQueryString = QString( "SELECT moduleid, slot FROM Module WHERE crateid='%1'" ).arg( locGlobalCrateID ); if ( gDebugFlag ) cout << locModuleQueryString.toStdString() << endl; locModuleSQLQuery.prepare( locModuleQueryString ); locModuleSQLQuery.exec(); map loadedChannelName; // loop through the modules while ( locModuleSQLQuery.next() ) { int locGlobalModuleID = locModuleSQLQuery.value( 0 ).toInt(); int locSlotID = locModuleSQLQuery.value( 1 ).toInt(); // build and execute channel query requesting only the maximum runrangeid for each chanid. QSqlQuery locChannelSQLQuery( locSQLDatabase ); QString locChannelQueryString = QString( "SELECT chanid, name, channel, system, col_name, MAX(runrangeid) from Channel WHERE moduleid='%1' GROUP by chanid" ).arg(locGlobalModuleID ); if ( gDebugFlag ) cout << locChannelQueryString.toStdString() << endl; locChannelSQLQuery.prepare( locChannelQueryString ); locChannelSQLQuery.exec(); // loop through the channels bool locAsynDriverConfigCalledFlag = false; char* driverPointer = 0; while ( locChannelSQLQuery.next() ) { // int locGlobalChannelID = locChannelSQLQuery.value(0).toInt(); string locChannelName = locChannelSQLQuery.value( 1 ).toString().toStdString(); if ( locChannelName == "SPARE" ) continue; if ( locChannelName.find( "unused" ) != string::npos ) continue; Format_Name( locChannelName ); //replace all "-" with ":" int locLocalChannelID = locChannelSQLQuery.value( 2 ).toInt(); if ( locCrateFunction == "DISC" ) --locLocalChannelID; //tt.db starts from 1 for DISC, 0 for ADC, and code assumes all start from 0 string locSystemName = locChannelSQLQuery.value( 3 ).toString().toStdString(); string localSlotName; string localSlotID; if ( gDebugFlag ) { cout << "crate, slot, channel, type, system, channel name = " << locGlobalCrateID << ", " << locSlotID << ", " << locLocalChannelID; cout << ", " << locCrateFunction << ", " << locSystemName << ", " << locChannelName << endl; } string locColumnName = locChannelSQLQuery.value( 4 ).toString().toStdString(); // int localRunRangeID = locChannelSQLQuery.value(5).toInt(); // Skip this channelid if the system with the highest runrangeid is null. if( locChannelSQLQuery.record().isNull(3) ) continue; //Make asyn driver config call for module (board) ostringstream locModulePortStream; locModulePortStream << "ROC" << locROCID << ":Slot" << locSlotID; if ( !locAsynDriverConfigCalledFlag ) { locAsynDriverConfigCalledFlag = true; if ( locCrateFunction == "DISC" ) driverPointer = asynDrvDiscBoardConfig( locCratePortStream.str().c_str(), locModulePortStream.str().c_str(), locSlotID ); else if ( locCrateFunction == "fADC250" ) driverPointer = asynDrvFADCBoardConfig( locCratePortStream.str().c_str(), locModulePortStream.str().c_str(), locSlotID ); else if ( locCrateFunction == "SSPDIRC" ) driverPointer = asynDrvSSPDIRCBoardConfig( locCratePortStream.str().c_str(), locModulePortStream.str().c_str(), locSlotID ); } if ( driverPointer != 0 ) { if ( gDebugFlag ) cout << "Will load records for " << locCratePortStream.str() << ":" << locSlotID << endl; //Load db record for channel ostringstream locMacroSubstitutions_Channel; locMacroSubstitutions_Channel << "P=Scalars,PORT=" << locModulePortStream.str(); locMacroSubstitutions_Channel << ",CHAN=" << locLocalChannelID; locMacroSubstitutions_Channel << ",CHANNEL_NAME=" << locChannelName; ostringstream locMacroSubstitutions_Slot; if ( gDebugFlag ) cout << "Channel macro sub string: " << locMacroSubstitutions_Channel.str() << endl; string dbRecordPath_Channel = "."; string dbRecordPath_Slot = "."; if ( locCrateFunction == "DISC" ) { dbRecordPath_Channel = "db/jlabDiscChannel.db"; dbRecordPath_Slot = ""; } else if ( locCrateFunction == "fADC250" ) { dbRecordPath_Channel = "db/jlabFADC250Channel.db"; dbRecordPath_Slot = ""; } else if ( locCrateFunction == "SSPDIRC" ) { // for DIRC the temperatures are measure per fiber, so we drop the last // two labels in the name that correspond to the channel within the PMT and the PMT number. // The reset stays the same in the channel name other than the suffix. dbRecordPath_Channel = "db/jlabSSPDIRCChannel.db"; dbRecordPath_Slot = "db/jlabSSPDIRCFiber.db"; localSlotID = boost::lexical_cast( jlabSSPDIRCBoard::GetFiberNumber( locLocalChannelID ) ); localSlotName = locChannelName.substr( 0, locChannelName.rfind( ":" ) ).substr( 0, locChannelName.substr( 0, locChannelName.rfind( ":" ) ).rfind( ":" ) ); locMacroSubstitutions_Slot << "P=Scalars,PORT=" << locModulePortStream.str(); locMacroSubstitutions_Slot << ",CHAN=" << localSlotID; locMacroSubstitutions_Slot << ",CHANNEL_NAME=" << localSlotName; } if ( loadedChannelName.count( locChannelName ) < 1 ) { // cout << "Loading " << dbRecordPath_Channel << " with " // << locMacroSubstitutions_Channel.str() << endl; dbLoadRecords( dbRecordPath_Channel.c_str(), locMacroSubstitutions_Channel.str().c_str() ); loadedChannelName[locChannelName] = true; } if ( dbRecordPath_Slot != "" && loadedChannelName.count( localSlotName ) < 1 ) { // cout << "Loading " << dbRecordPath_Slot << " with " << locMacroSubstitutions_Slot.str() << endl; dbLoadRecords( dbRecordPath_Slot.c_str(), locMacroSubstitutions_Slot.str().c_str() ); loadedChannelName[localSlotName] = true; } } else { if ( gDebugFlag ) cout << "Will skip generating records for " << locCratePortStream.str() << ":" << locSlotID << endl; } } } return 0; } /* iocsh config function */ static const iocshArg hook4PaulArg0 = { "Some string paramer", iocshArgString }; static const iocshArg hook4PaulArg1 = { "Some integer parameter", iocshArgInt }; static const iocshArg * const hook4PaulArgs[] = { &hook4PaulArg0, &hook4PaulArg1 }; static const iocshFuncDef hook4PaulFuncDef = { "hook4Paul", 2, hook4PaulArgs }; static void hook4PaulCallFunc( const iocshArgBuf *args ) { hook4Paul( args[0].sval, args[1].ival ); } void hook4PaulRegister( void ) { iocshRegister( &hook4PaulFuncDef, hook4PaulCallFunc ); } epicsExportRegistrar( hook4PaulRegister ); } // extern "C" string Get_IPAddress( void ) { //GET MY IP ADDRESS: // http://stackoverflow.com/questions/212528/get-the-ip-address-of-the-machine FILE* locIFConfigFile = popen( "/sbin/ifconfig", "r" ); if ( !locIFConfigFile ) return ""; //Get all IP addresses char *p = NULL, *e; size_t n = 0; string locLANIPAddress = ""; while ( getline( &p, &n, locIFConfigFile ) > 0 ) { if ( p == NULL ) break; p = strstr( p, "inet " ); if ( p == NULL ) continue; p += 5; p = strchr( p, ':' ); if ( p == NULL ) continue; ++p; e = strchr( p, ' ' ); if ( e == NULL ) continue; *e = '\0'; string locIPAddress = p; if ( locIPAddress.compare( 0, 4, "127." ) == 0 ) continue; locLANIPAddress = locIPAddress; cout << locLANIPAddress << endl; } pclose( locIFConfigFile ); //select the one that is not 127.0.0.1 return locLANIPAddress; } int Get_ROCID( void ) { string locIPAddress = Get_IPAddress(); size_t locLastDotIndex = locIPAddress.rfind( "." ); if ( locLastDotIndex == string::npos ) { cout << "ERROR, CANNOT READ IP ADDRESS, SO CANNOT GET ROC ID. ABORTING." << endl; abort(); } string locROCString = locIPAddress.substr( locLastDotIndex + 1 ); int locROCID = atoi( locROCString.c_str() ); //Check subnet size_t loc2ndToLastDotIndex = locIPAddress.rfind( ".", locLastDotIndex - 1 ); if ( loc2ndToLastDotIndex == string::npos ) { cout << "ERROR, CANNOT READ IP ADDRESS, SO CANNOT GET ROC ID. ABORTING." << endl; abort(); } size_t locSubnetLength = locLastDotIndex - loc2ndToLastDotIndex - 1; string locSubnetString = locIPAddress.substr( loc2ndToLastDotIndex + 1, locSubnetLength ); if ( locSubnetString == "26" ) locROCID += 256; return locROCID; } void Format_Name( string& locString ) { //for non-FCAL, CCAL, ECAL: replace all "-" with ":" if ( locString.substr( 0, 4 ) == "FCAL" || locString.substr( 0, 4 ) == "CCAL" || locString.substr( 0, 4 ) == "ECAL") return; size_t locStringIndex = locString.find( "-", 0 ); while ( locStringIndex != string::npos ) { locString.replace( locStringIndex, 1, ":" ); ++locStringIndex; locStringIndex = locString.find( "-", locStringIndex ); } }