/** * @author Ian Johnson * @version 1.0 * @developed for running Eiger at cSAXS */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <arpa/inet.h> #include <algorithm> // std::remove_if #include <iostream> #include <string> #include <map> #include <time.h> #include <string.h> #include "FebControl.h" #include "slsDetectorServer_defs.h" //include port number using namespace std; enum cmd_string {evNotFound, evReinitialize,evReset, evSetInputDelays, evSetDACValue,evGetDACValue,evSetDACVoltage,evGetDACVoltage,evSetHighVoltage,//evGetHighVoltage, evSetTrimBits, evSetAllTrimBits, evGetTrimBits, //evLoadTrimBitFile, evSetBitMode, evSetPhotonEnergy, // evSetPhotonEnergyCalibrationParameters,evActivateRateCorrection,evDeactivateRateCorrection,evSetRateCorrectionTau, evSetReadoutSpeed,evSetReadoutMode, //temp solution // evNotFound1,evNotFound2,evNotFound3, evSetNumberOfExposures,evSetExposureTime,evSetExposurePeriod, // evSetTriggerPolarityToPositive,evSetTriggerPolarityToNegative, evSetTriggerMode, evSetExternalGating, evStartAcquisition,evStopAcquisition,evIsDaqStillRunning, evWaitUntilDaqFinished, evExitServer }; map<string, cmd_string> enum_map; void init(){ enum_map["reinitialize"] = evReinitialize; enum_map["reset"] = evReset; enum_map["setinputdelays"] = evSetInputDelays; enum_map["setdacvalue"] = evSetDACValue; enum_map["getdacvalue"] = evGetDACValue; enum_map["setdacvoltage"] = evSetDACVoltage; enum_map["getdacvoltage"] = evGetDACVoltage; enum_map["sethighvoltage"] = evSetHighVoltage; enum_map["settrimbits"] = evSetTrimBits; enum_map["setalltrimbits"] = evSetAllTrimBits; enum_map["gettrimbits"] = evGetTrimBits; // enum_map["loadtrimbitfile"] = evLoadTrimBitFile; enum_map["setbitmode"] = evSetBitMode; enum_map["setphotonenergy"] = evSetPhotonEnergy; // enum_map["setphotonenergycalibrationparameters"] = evSetPhotonEnergyCalibrationParameters; // enum_map["activateratecorrection"] = evActivateRateCorrection; // enum_map["deactivateratecorrection"] = evDeactivateRateCorrection; // enum_map["setratecorrectiontau"] = evSetRateCorrectionTau; enum_map["setreadoutspeed"] = evSetReadoutSpeed; enum_map["setreadoutmode"] = evSetReadoutMode; enum_map["setnumberofexposures"] = evSetNumberOfExposures; enum_map["setexposuretime"] = evSetExposureTime; enum_map["setexposureperiod"] = evSetExposurePeriod; // enum_map["settriggerpolaritytopositive"] = evSetTriggerPolarityToPositive; // enum_map["settriggerpolaritytonegative"] = evSetTriggerPolarityToNegative; enum_map["settriggermode"] = evSetTriggerMode; enum_map["setexternalgating"] = evSetExternalGating; enum_map["startacquisition"] = evStartAcquisition; enum_map["stopacquisition"] = evStopAcquisition; enum_map["isdaqstillrunning"] = evIsDaqStillRunning; enum_map["waituntildaqfinished"] = evWaitUntilDaqFinished; enum_map["exitserver"] = evExitServer; } int server_list_s; int server_conn_s; int AccpetConnectionAndWaitForData(char* buffer, int maxlength); bool WriteNClose(const char* buffer, int length); bool SetupListenSocket(unsigned short int port); string LowerCase(string str); string GetNextString(string str,bool start_from_beginning=0); void AddNumber(string& str, int n, int location=-1, bool space_after=0);//-1 means append void AddNumber(string& str, float v, int location=-1, bool space_after=0);//-1 means append int main(int argc, char* argv[]){ cout<<endl<<endl; /* if(argc<2){ cout<<"Usage: feb_server port_number"<<endl<<endl; return 1; } */ init(); FebControl *feb_controler = new FebControl(); unsigned short int port_number = FEB_PORT; if(!SetupListenSocket(port_number)) return 1; int length=270000; char data[270000]; int stop = 0; time_t rawtime; struct tm *timeinfo; while(!stop){ /*cout<<"Waiting for command -> "<<flush;*/ int nread = AccpetConnectionAndWaitForData(data,length); if(nread<=0) return 0; time(&rawtime); timeinfo=localtime(&rawtime); cout<<asctime(timeinfo); /*cout<<" Command received: "<<data<<endl;*/ string tmp_str[5]; float v[4];//,v2,v3,v4,v5; int n[5]; string cmd = GetNextString(data,1); int ret_val = 1; string return_message = "";/*\n\n\tCommand recieved: "; return_message.append(data); return_message.append("\n"); */ int return_start_pos; while(cmd.length()>0){ int ret_parameter = 0; return_start_pos = return_message.length(); switch(enum_map.find(LowerCase(cmd))->second){ case evReinitialize : if(feb_controler->Init()){ return_message.append("\tExecuted: Reinitialize\n"); ret_val = 0; }else{ return_message.append("\tError executing: Reinitialize\n"); ret_val = 1; } break; case evReset : if(feb_controler->Reset()){ return_message.append("\tExecuted: Reset\n"); ret_val = 0; }else{ return_message.append("\tError executing: Reset\n"); ret_val = 1; } break; case evSetInputDelays : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetIDelays(0,n[0])){ return_message.append("\tExecuted: SetInputDelays "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetInputDelays <delay>\n"); ret_val = 1; } break; case evSetDACValue : tmp_str[0] = GetNextString(data); tmp_str[1] = GetNextString(data); n[0] = atoi(tmp_str[1].data()); if(tmp_str[0].length()>0&&tmp_str[1].length()>0&&feb_controler->SetDAC(tmp_str[0],n[0])){ return_message.append("\tExecuted: SetDACValue "); return_message.append(tmp_str[0]+" "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetDACValue <dac_name> <value>\n"); ret_val = 1; } break; case evGetDACValue : tmp_str[0] = GetNextString(data); if(tmp_str[0].length()>0&&feb_controler->GetDAC(tmp_str[0],ret_parameter)){ return_message.append("\tExecuted: GetDACValue "); return_message.append(tmp_str[0]+" -> ");AddNumber(return_message,ret_parameter); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: GetDACValue <dac_name>\n"); ret_val = 1; } break; case evSetDACVoltage : tmp_str[0] = GetNextString(data); tmp_str[1] = GetNextString(data); n[0] = atoi(tmp_str[1].data()); if(tmp_str[0].length()>0&&tmp_str[1].length()>0&&feb_controler->SetDAC(tmp_str[0],n[0],1)){ return_message.append("\tExecuted: SetDACVoltage "); return_message.append(tmp_str[0]+" "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetDACVoltage <dac_name> <voltage_mV>\n"); ret_val = 1; } break; case evGetDACVoltage : tmp_str[0] = GetNextString(data); if(tmp_str[0].length()>0&&feb_controler->GetDAC(tmp_str[0],ret_parameter,1)){ return_message.append("\tExecuted: GetDACVoltage "); return_message.append(tmp_str[0]+" -> ");AddNumber(return_message,ret_parameter); return_message.append(" mV\n"); ret_val = 0; }else{ return_message.append("\tError executing: GetDACVoltage <dac_name>\n"); ret_val = 1; } break; case evSetHighVoltage : tmp_str[0] = GetNextString(data); v[0] = atof(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetHighVoltage(v[0])){ return_message.append("\tExecuted: SetHighVoltage "); AddNumber(return_message,v[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetHighVoltage <voltage>\n"); ret_val = 1; } break; case evSetTrimBits : tmp_str[0] = GetNextString(data); if(feb_controler->LoadTrimbitFile()){ /* if(1){*/ /*tmp_str[0] = GetNextString(data); feb_controler->SetTrimbits(0,(unsigned char*)(tmp_str[0].c_str()));*/ return_message.append("\tExecuted: SetTrimBits\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetTrimBits \n"); ret_val = 1; } break; case evSetAllTrimBits : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(feb_controler->SaveAllTrimbitsTo(n[0])){ /*feb_controler->SetTrimbits(0,(unsigned char*)(tmp_str[0].c_str()));*/ /*if(1){*/ return_message.append("\tExecuted: SetAllTrimBits\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetAllTrimBits \n"); ret_val = 1; } break; case evGetTrimBits : if(feb_controler->SaveTrimbitFile()){ /*if(1){*/ /*tmp_str[0] = GetNextString(data); feb_controler->GetTrimbits();*/ return_message.append("\tExecuted: GetTrimBits\n"); ret_val = 0; }else{ return_message.append("\tError executing: GetTrimBits \n"); ret_val = 1; } break; // case evLoadTrimBitFile : case evSetBitMode : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetDynamicRange(n[0])){ return_message.append("\tExecuted: SetBitMode "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetBitMode <mode 4,8,16,32>\n"); ret_val = 1; } break; case evSetPhotonEnergy : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetPhotonEnergy(n[0])){ return_message.append("\tExecuted: SetPhotonEnergy "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetPhotonEnergy <energy eV>\n"); ret_val = 1; } break; // case evSetPhotonEnergyCalibrationParameters : // case evActivateRateCorrection : // case evDeactivateRateCorrection : // case evSetRateCorrectionTau : case evSetReadoutSpeed : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetReadoutSpeed(n[0])){ return_message.append("\tExecuted: SetReadoutSpeed "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetReadoutSpeed <speed 0-full 1-half 2-quarter 3-super_slow>\n"); ret_val = 1; } break; case evSetReadoutMode : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetReadoutMode(n[0])){ return_message.append("\tExecuted: SetReadoutMode "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetReadoutMode <mode 0->parallel,1->non-parallel,2-> safe_mode>\n"); ret_val = 1; } break; case evSetNumberOfExposures : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetNExposures(n[0])){ return_message.append("\tExecuted: SetNumberOfExposures "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetNumberOfExposures <n>\n"); ret_val = 1; } break; case evSetExposureTime : tmp_str[0] = GetNextString(data); v[0] = atof(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetExposureTime(v[0])){ return_message.append("\tExecuted: SetExposureTime "); AddNumber(return_message,v[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetExposureTime <t_seconds>\n"); ret_val = 1; } break; case evSetExposurePeriod : tmp_str[0] = GetNextString(data); v[0] = atof(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetExposurePeriod(v[0])){ return_message.append("\tExecuted: SetExposurePeriod "); AddNumber(return_message,v[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetExposurePeriod <t_seconds>\n"); ret_val = 1; } break; // case evSetTriggerPolarityToPositive : // case evSetTriggerPolarityToNegative : case evSetTriggerMode : tmp_str[0] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); if(tmp_str[0].length()>0&&feb_controler->SetTriggerMode(n[0])){ return_message.append("\tExecuted: SetTriggerMode "); AddNumber(return_message,n[0]); return_message.append("\n"); ret_val = 0; }else{ return_message.append("\tError executing: SetTriggerMode <n>\n"); ret_val = 1; } break; case evSetExternalGating : tmp_str[0] = GetNextString(data); tmp_str[1] = GetNextString(data); n[0] = atoi(tmp_str[0].data()); n[1] = atoi(tmp_str[1].data()); if(tmp_str[0].length()<1 || tmp_str[1].length()<1 || (n[0]!=0&&n[0]!=1) || (n[1]!=0&&n[1]!=1)){ return_message.append("\tError executing: setexternalgating <enable> <polarity>\n"); ret_val = 1; } feb_controler->SetExternalEnableMode(n[0],n[1]); ret_val = 0; break; case evStartAcquisition : if(feb_controler->StartAcquisition()){ return_message.append("\tExecuted: StartAcquisition\n"); ret_val = 0; }else{ return_message.append("\tError executing: StartAcquisition\n"); ret_val = 1; } break; case evStopAcquisition : if(feb_controler->StopAcquisition()){ return_message.append("\tExecuted: StopAcquisition\n"); ret_val = 0; }else{ return_message.append("\tError executing: StopAcquisition\n"); ret_val = 1; } break; case evIsDaqStillRunning : return_message.append("\tExecuted: evIsDaqStillRunning\n"); ret_parameter = feb_controler->AcquisitionInProgress(); ret_val = 0; break; case evWaitUntilDaqFinished : if(feb_controler->WaitForFinishedFlag()){ return_message.append("\tExecuted: WaitUntilDaqFinished\n"); ret_val = 0; }else{ return_message.append("\tError executing: WaitUntilDaqFinished\n"); ret_val = 1; } break; case evExitServer : return_message.append("\tExiting Server ....\n"); stop = 1; ret_val = -200; break; default : return_message.append("\tWarning command \""); return_message.append(cmd); return_message.append("\" not found.\n"); return_message.append("\t\tValid commands: "); map<string, cmd_string>::iterator it = enum_map.begin(); while(it!=enum_map.end()){ return_message.append((it++)->first); return_message.append(" "); } ret_val=-100; break; } // return_message.append("\n"); //AddNumber(return_message,ret_parameter,return_start_pos); AddNumber(return_message,ret_val,return_start_pos,1); AddNumber(return_message,ret_parameter,0,1); if(ret_val!=0) break; cmd = GetNextString(data); } /*return_message.append("\n\n\n");*/ AddNumber(return_message,ret_val,0,1); cout<<return_message.c_str()<<"\t\t"; cout<<"return: "<<ret_val<<endl; if(!WriteNClose(return_message.c_str(),return_message.length())) return 0; } delete feb_controler; return 0; } string LowerCase(string str){ string s = str; string::iterator i = s.begin(); while(i!=s.end()) *i=tolower(*(i++)); return s; } string GetNextString(string str,bool start_from_beginning){ static string::size_type start_pos = 0; if(start_from_beginning) start_pos = 0; while(start_pos != string::npos){ string::size_type found = str.find_first_of(" ",start_pos); string sub = str.substr(start_pos,found-start_pos); start_pos = found; if(start_pos != string::npos) start_pos+=1; sub.erase(remove_if(sub.begin(),sub.end(), ::isspace ),sub.end()); if(sub.length()>0) return sub; } return ""; } void AddNumber(string& str, int n, int location, bool space_after){ static char retval_st[100]; if(space_after) sprintf(retval_st,"%d ",n); else sprintf(retval_st,"%d",n); if(location<0) str.append(retval_st); else str.insert(location,retval_st); } void AddNumber(string& str, float v, int location, bool space_after){ static char retval_st[100]; if(space_after) sprintf(retval_st,"%f ",v); else sprintf(retval_st,"%f",v); if(location<0) str.append(retval_st); else str.insert(location,retval_st); } bool SetupListenSocket(unsigned short int port){ server_list_s=0; server_conn_s=0; if((server_list_s = socket(AF_INET, SOCK_STREAM, 0))<0) return 0; struct sockaddr_in servaddr; /* socket address structure */ memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); if(bind(server_list_s,(struct sockaddr *) &servaddr,sizeof(servaddr))<0) return 0; if(listen(server_list_s,32) < 0){ // 1024 /* Backlog for listen() */ return 0; } return 1; } int AccpetConnectionAndWaitForData(char* buffer, int maxlength){ if(server_list_s==0||maxlength<=0) return 0; if((server_conn_s = accept(server_list_s,NULL,NULL))< 0) return 0; int nread = read(server_conn_s,buffer,maxlength-1); if(nread<0) return 0; buffer[nread]='\0'; return nread; } bool WriteNClose(const char* buffer, int length){ if(server_conn_s==0||length<=0) return 0; int nsent = write(server_conn_s,buffer,length); if(close(server_conn_s)<0) return 0; server_conn_s=0; return (nsent==length); }