Changeset 183
- Timestamp:
- 03/12/10 15:54:15 (15 years ago)
- Location:
- hvcontrol
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
hvcontrol/hvcontrol.cpp
r161 r183 14 14 #include <pthread.h> 15 15 #include <signal.h> 16 #include <sys/socket.h>17 #include <netdb.h>18 #include <arpa/inet.h>19 16 20 17 #include "ProcessIO.h" … … 23 20 #include <readline/history.h> 24 21 25 #define DEFAULT_CONFIG "../config/HV.conf" // Default configuration file26 22 #define LOCKFILE "/tmp/CTX_HV_LOCK" 27 23 28 24 // Function prototypes 29 25 void ConsoleCommand(ProcessIO *); 30 void CCCommand(ProcessIO *);31 26 void HVMonitor(ProcessIO *); 32 27 void DummyHandler(int); … … 43 38 44 39 char str[MAX_COM_SIZE]; 45 pthread_t thread_ConsoleCommand,thread_HVMonitor ,thread_CCCommand;40 pthread_t thread_ConsoleCommand,thread_HVMonitor; 46 41 int LockDescriptor; 47 48 // Interpret command line (do before lockfile creation in case of exit())49 if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) {50 printf("Usage: %s [-c <ConfigFile>] Default file is \"%s\"\n", argv[0], DEFAULT_CONFIG);51 exit(EXIT_SUCCESS);52 }53 42 54 43 // Assure only one instance of the HV control program runs … … 69 58 70 59 system("clear"); 71 printf("\n*** HV Control built %s, %s (S.Commichau, S.Stark, O.Grimm) ***\n\n",__DATE__,__TIME__);60 printf("\n*** Bias control (%s, %s, O. Grimm, S.Commichau, S.Stark) ***\n\n",__DATE__,__TIME__); 72 61 73 62 // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls … … 84 73 85 74 // Construct main instance and create mutex for thread synchronization 86 ProcessIO pio (argc==3 ? argv[2] : DEFAULT_CONFIG);75 ProcessIO pio; 87 76 if (pthread_mutex_init(&pio.control_mutex, NULL) != 0) { 88 77 perror("pthread_mutex_init failed"); … … 105 94 throw; 106 95 } 107 if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &pio)) != 0) {108 perror("pthread_create failed with socket thread");109 throw;110 }111 96 112 97 // Threads should be accessible for sending signals 113 98 pio.HVMonitor = thread_HVMonitor; 114 pio.SocketThread = thread_CCCommand;115 99 116 100 // Wait for threads to quit 117 pthread_join(thread_CCCommand, NULL);118 101 pthread_join(thread_ConsoleCommand, NULL); 119 102 pthread_join(thread_HVMonitor, NULL); … … 169 152 if(strlen(Command)>0) add_history(Command); 170 153 171 // Log command 172 m->PrintMessage(Log, "CONSOLE> %s\n", Command); 173 174 // Process command 175 pthread_mutex_lock(&m->control_mutex); 176 m->CommandControl(Command); 177 pthread_mutex_unlock(&m->control_mutex); 178 154 // Process command (via DIM gives automatic serialisation) 155 DimClient::sendCommand("Bias/Command", Command); 179 156 free(Command); 180 157 } 181 }182 183 184 /********************************************************************\185 186 CCCommand thread187 188 Listen to commands from socket (Central Control)189 190 This thread will block execution in the accept() and read() socket function191 while waiting for a connection or data. If the exit function is invoked through192 keyboard command, these blocking functions are interrupted by raising the signal193 SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal194 handler below is needed to prevent the standard thread termination occurring195 when this signal is received.196 197 \********************************************************************/198 199 200 void CCCommand(ProcessIO *m) {201 202 int ServerSocket,ConnectionSocket,ReadResult;203 struct sockaddr_in SocketAddress, ClientAddress;204 struct hostent *ClientName;205 socklen_t SizeClientAddress=sizeof(ClientAddress);206 char Command[MAX_COM_SIZE];207 208 // Set up server socket209 if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {210 m->PrintMessage(All, "Could not open server socket, no remote connection possible (%s).\n", strerror(errno));211 return;212 }213 214 // Allows immediate reuse of socket after closing (circumvents TIME_WAIT)215 int Value=1;216 if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {217 m->PrintMessage(All, "Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno));218 }219 220 SocketAddress.sin_family = PF_INET;221 SocketAddress.sin_port = htons((unsigned short) m->fCCPort);222 SocketAddress.sin_addr.s_addr = INADDR_ANY;223 224 if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1) {225 m->PrintMessage(All, "Could not bind port to socket (%s)\n", strerror(errno));226 close(ServerSocket);227 return;228 }229 if (listen(ServerSocket, 0) == -1) {230 m->PrintMessage(All, "Could not set socket to listening (%s)\n", strerror(errno));231 close(ServerSocket);232 return;233 }234 235 while (!m->Exit) { // Looping to wait for incoming connection236 237 if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {238 if (errno!=EINTR) m->PrintMessage(All, "Failed to accept incoming connection (%s)\n", strerror(errno));239 close(ServerSocket);240 return;241 }242 243 ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);244 m->PrintMessage(All, "Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");245 m->Socket = ConnectionSocket;246 247 // Looping as long as client exists and program not terminated248 while (!m->Exit) {249 250 // Try to read command from socket251 memset(Command, 0, sizeof(Command));252 ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);253 if (ReadResult==0) break; // Client does not exist anymore254 if (ReadResult==-1) {255 if (errno!=EINTR) m->PrintMessage(All, "Error read from socket (%s)\n", strerror(errno));256 break;257 }258 if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0'; // Remove trailing newline259 260 // Log command261 //m->PrintMessage(Console, "SOCKET> %s\n", Command);262 //m->PrintMessage(Log, "SOCKET> %s\n", Command);263 264 // Process command265 pthread_mutex_lock(&m->control_mutex);266 m->CmdFromSocket = true;267 m->CommandControl(Command);268 m->CmdFromSocket = false;269 pthread_mutex_unlock(&m->control_mutex);270 }271 272 m->Socket = -1;273 m->PrintMessage(All, "Disconnected from client.\n");274 close(ConnectionSocket);275 }276 close(ServerSocket);277 158 } 278 159 -
hvcontrol/src/HV.cc
r161 r183 30 30 Name = new DimService (Buffer, BoardName); 31 31 32 for (int i=0; i<NUM_CHAINS; i++) { 33 for (int j=0; j<NUM_CHANNELS; j++) { 34 snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d/%.2d-%.3d", BoardNumber, i, j); 35 BiasVolt[i][j] = new DimService (Buffer, HVV[i][j]); 36 } 37 Overcurrent[i] = false; 38 } 32 snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d", BoardNumber); 33 BiasVolt = new DimService (Buffer, "D", HVV, NUM_CHAINS*NUM_CHANNELS*sizeof(double)); 34 35 for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i] = false; 39 36 ResetButton = false; 40 37 WrapOK = true; … … 87 84 88 85 delete Name; 89 for (int i=0; i<NUM_CHAINS; i++) { 90 for (int j=0; j<NUM_CHANNELS; j++) { 91 delete BiasVolt[i][j]; 92 } 93 } 86 delete BiasVolt; 94 87 } 95 88 … … 202 195 for (int k=0; k<NUM_CHANNELS; k++){ 203 196 HV[j][k] = 0; 204 HVV[j][k] = 0.0; 205 206 // Update DIM services 207 BiasVolt[j][k]->updateService(); 197 HVV[j][k] = 0.0; 208 198 } 209 199 } 200 // Update DIM services 201 BiasVolt->updateService(); 210 202 } 211 203 -
hvcontrol/src/HV.h
r161 r183 55 55 56 56 DimService *Name; 57 DimService *BiasVolt [NUM_CHAINS][NUM_CHANNELS];57 DimService *BiasVolt; 58 58 59 59 void ClearVoltageArrays(); -
hvcontrol/src/ProcessIO.cc
r161 r183 14 14 static char* state_str[] = {"active", "stopped", "n.a."}; 15 15 16 17 ProcessIO::ProcessIO(const char *ConfigFile): 16 ProcessIO::ProcessIO(): 18 17 DimCommand((char *) SERVER_NAME"/Command", (char *) "C"), 19 18 EvidenceServer(SERVER_NAME) { … … 24 23 // Create DIM text output service 25 24 Textout = new DimService (SERVER_NAME"/Textout", (char *) ""); 25 UpdateDelay = 0.0; 26 26 27 27 // Initialize status variables 28 28 state = active; 29 29 Exit = false; 30 CmdFromSocket = false;31 Socket = -1;32 30 33 31 NumHVBoards = 0; … … 38 36 39 37 // Get configuration data 40 char *Boards = GetConfig(SERVER_NAME " Boards"); 41 fPixMapTable = GetConfig(SERVER_NAME " PixMapTable"); 42 fTimeOut = atof(GetConfig(SERVER_NAME " TimeOut")); 43 fStatusRefreshRate = atof(GetConfig(SERVER_NAME " StatusRefreshRate")); 44 fCCPort = atoi(GetConfig(SERVER_NAME " CCPort")); 45 DACMin = atoi(GetConfig(SERVER_NAME " DACMin")); 46 DACMax = atoi(GetConfig(SERVER_NAME " DACMax")); 47 fHVCalibOffset = atof(GetConfig(SERVER_NAME " HVCalibOffset")); 48 fHVCalibSlope = atof(GetConfig(SERVER_NAME " HVCalibSlope")); 49 fHVMaxDiff = atoi(GetConfig(SERVER_NAME " HVMaxDiff")); 38 char *Boards = GetConfig("Boards"); 39 fPixMapTable = GetConfig("PixMapTable"); 40 fTimeOut = atof(GetConfig("TimeOut")); 41 fStatusRefreshRate = atof(GetConfig("StatusRefreshRate")); 42 DACMin = atoi(GetConfig("DACMin")); 43 DACMax = atoi(GetConfig("DACMax")); 44 fHVCalibOffset = atof(GetConfig("HVCalibOffset")); 45 fHVCalibSlope = atof(GetConfig("HVCalibSlope")); 46 fHVMaxDiff = atoi(GetConfig("HVMaxDiff")); 50 47 51 48 if (fStatusRefreshRate < MIN_RATE || fStatusRefreshRate > MAX_RATE) fStatusRefreshRate = 1; … … 164 161 PrintMessage( " TimeOut: %.2f s\n" 165 162 " StatusRefreshRate: %.2f Hz\n" 166 " CCPort: %d\n"167 163 " DACMin value: %d\n" 168 164 " DACMax value: %d\n" … … 170 166 " HVCalibSlope : %f\n" 171 167 " HVMaxDiff : %u\n", fTimeOut, 172 fStatusRefreshRate, fCCPort,DACMin,168 fStatusRefreshRate, DACMin, 173 169 DACMax, fHVCalibOffset, fHVCalibSlope, 174 170 fHVMaxDiff); … … 182 178 PrintMessage(" board <i>|<i> <j>|<all> Address board i, boards i-j or all boards or list boards\n" 183 179 " chain <i>|<i> <j>|<all> Address chain i, chains i-j or all chains\n" 184 " hv <PXL id>|<ch>|<all> <v> Set bias of pixel ID, ch. or all ch. of active chain(s)/board(s)\n" 185 " hvdiff <PXL id>|<ch>|<all> <diff> Change bias by <diff>\n" 180 " hv <PXL id>|<ch>|<all> <v> Set/change bias of pixel, ch. or all ch. of active chain(s)/board(s)\n" 186 181 " status [dac] Show status information (DAC values if requested)\n" 187 182 " config Print configuration\n" … … 204 199 // Set new bias voltage (if no boards available, simply returns OK) 205 200 // First reponse to socket should be 'OK' if no error occurred. 206 if (Match(Param[0], "hv") || Match(Param[0], "hvdiff")) {201 if (Match(Param[0], "hv")) { 207 202 208 203 int hvoltage, DACValue, Errors=0, Board=-1, Chain=-1, Channel=-1; … … 212 207 // Need two or parameters 213 208 if (NParam<3 || NParam>4) { 214 PrintMessage("Usage: hv /hvdiff<channel>|<all> <voltage> [dac]\n");209 PrintMessage("Usage: hv <channel>|<all> <voltage> [dac]\n"); 215 210 return; 216 211 } … … 250 245 if (k!=Channel && Channel!=-1) continue; 251 246 252 // hvdiff isignored if DAC value is zero253 if ( (strlen(Param[0])>2 || isdigit(*Param[2])==0) && (fHVBoard[i]->HV[j][k] == 0)) continue;247 // Voltage change ignored if DAC value is zero 248 if (isdigit(*Param[2])==0 && fHVBoard[i]->HV[j][k] == 0) continue; 254 249 255 250 // Determine new DAC values 256 251 if (!SetDac){ 257 if ( strlen(Param[0])>2 || isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff252 if (isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // voltage change 258 253 else fHVBoard[i]->HVV[j][k] = hvoltageV; 259 254 DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k); 260 255 } 261 256 else { 262 if (strlen(Param[0])>2 || isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff257 if (isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // voltage change 263 258 else DACValue = hvoltage; 264 259 } … … 269 264 270 265 // Update DIM services 271 fHVBoard[i]->BiasVolt[j][k]->updateService();272 266 //fHVBoard[i]->BiasVolt[j][k]->updateService(); 267 UpdateDelay = 1.0; 273 268 } // Channels 274 269 } // Chains 275 270 } // Boards 276 271 277 if (Errors > 0) PrintMessage("ERROR - Errors on %d channel(s) occurred\n", Errors); 278 else PrintMessage("OK - no errors\n"); 272 if (Errors > 0) PrintMessage("Errors on %d channel(s) occurred\n", Errors); 279 273 280 274 return; … … 318 312 319 313 // Update DIM services 320 fHVBoard[Board]->BiasVolt[Chain][Channel]->updateService();321 314 //fHVBoard[Board]->BiasVolt[Chain][Channel]->updateService(); 315 UpdateDelay = 1.0; 322 316 if(++Channel == NUM_CHANNELS) { 323 317 Chain++; … … 440 434 PrintMessage("\n Status monitor: %s\n", state_str[state]); 441 435 PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate); 442 PrintMessage(" Socket state: %s\n", Socket==-1 ? "disconnected":"connected");443 436 PrintMessage(" Total number of boards: %d\n", NumHVBoards); 444 437 PrintMessage(" Active boards: %d\n\n", LastBoard - FirstBoard + 1); … … 519 512 else if(Match(Param[0], "exit")) { 520 513 521 if (CmdFromSocket) {522 PrintMessage("Exit command not allowed over socket.\n");523 return;524 }525 526 514 Exit = true; 527 pthread_kill(HVMonitor, SIGUSR1); 528 pthread_kill(SocketThread, SIGUSR1); 529 515 pthread_kill(HVMonitor, SIGUSR1); 530 516 return; 531 517 } … … 549 535 va_list ArgumentPointer; 550 536 va_start(ArgumentPointer, Format); 551 if (CmdFromSocket) DoPrintMessage(Format, ArgumentPointer, Client); 552 else DoPrintMessage(Format, ArgumentPointer, Console); 537 DoPrintMessage(Format, ArgumentPointer, Console); 553 538 va_end(ArgumentPointer); 554 539 } … … 575 560 Textout->updateService(Textbuffer); 576 561 577 // Print to socket578 if((Target & Client) && Socket!=-1) {579 write(Socket, Textbuffer, strlen(Textbuffer));580 }581 582 562 // Send to log 583 563 if(Target & Log) { 584 564 char *Buf; 585 565 if (asprintf(&Buf, "%s %s", SERVER_NAME, Textbuffer) != -1) { 586 DimClient::sendCommand ("DColl/Log", Buf);566 DimClient::sendCommandNB("DColl/Log", Buf); 587 567 free(Buf); 588 568 } 589 else DimClient::sendCommand ("DColl/Log", SERVER_NAME" asprintf() failed");569 else DimClient::sendCommandNB("DColl/Log", SERVER_NAME" asprintf() failed"); 590 570 } 591 571 } … … 648 628 } 649 629 } 650 630 } 631 632 if (UpdateDelay >= 0) { 633 UpdateDelay -= 1.0/(NumHVBoards*fStatusRefreshRate); 634 if (UpdateDelay <= 0) for (int i=0; i<NumHVBoards; i++) { 635 fHVBoard[i]->BiasVolt->updateService(); 636 } 651 637 } 652 638 } … … 700 686 701 687 // 702 // Command handling (the only command is 'B IAS/Command')688 // Command handling (the only command is 'Bias/Command') 703 689 // 704 690 void ProcessIO::commandHandler() { 705 691 706 // Log command707 PrintMessage(Log, "DIM> %s\n", getString());708 709 // Process command710 692 pthread_mutex_lock(&control_mutex); 711 693 CommandControl(getString()); -
hvcontrol/src/ProcessIO.h
r161 r183 28 28 #define MAX_NUM_TOKEN 10 29 29 30 enum MsgTarget {Console=1, Log=2, Client=4,All=7};30 enum MsgTarget {Console=1, Log=2, All=7}; 31 31 typedef enum stateenum {active, stopped, na} state_enum; 32 32 … … 36 36 PixelMap *pm; 37 37 DimService *Textout; 38 38 float UpdateDelay; 39 39 40 void commandHandler(); 40 41 41 42 public: 42 43 //HVConfig *config; 43 44 44 HVCalib *calib; 45 45 HVBoard **fHVBoard; … … 50 50 const char *Param[MAX_NUM_TOKEN]; // For parser 51 51 int NParam; 52 bool CmdFromSocket;53 52 54 53 // Configuration data … … 56 55 float fTimeOut; 57 56 float fStatusRefreshRate; 58 int fCCPort;59 57 int DACMin; 60 58 int DACMax; … … 65 63 // Status variables 66 64 pthread_t HVMonitor; // exit function sends signal to these threads 67 pthread_t SocketThread;68 65 69 int Socket; // -1 if not connected70 71 66 int NumHVBoards; 72 67 int FirstBoard; … … 79 74 80 75 // Methods 81 ProcessIO( const char *);76 ProcessIO(); 82 77 ~ProcessIO(); 83 78
Note:
See TracChangeset
for help on using the changeset viewer.