class RoboEpicsChannel: def __init__(self,pvName,verbose=0): self.MAXPUTS=10 self.pvName=pvName self.status=0 # no error self.severity=0 self.statusReady=0 # has a command been executed self.waiting=0 # is the variable overbooked self.putAttempts=0 # the number of times it has tried to put a variable self.putSuccess=0 # if the last put command was successful self.verbose=verbose # if epics should print everything out for alarms and all self.CurrentText="" if ((self.pvName.upper().find("ROBO")<0) & DebugMode): self.rPrint("Variable "+pvName+" affects beamline and will not be altered") self.reconnect() def rPrint(self,cString): self.CurrentText=self.pvName+": "+cString print self.CurrentText def binaryClick(self): #specific method for dealing with the binary variables that return T/F based on success in robot putOK=self.rPutVal(5) robotOK=self.getVal() if (robotOK==5): time.sleep(.12) robotOK=self.getVal() return (putOK & robotOK) def getVal(self): try: val=self.chan.getw() except: try: #try one time to reconnect self.rPrint("Variable "+self.pvName+" appears to be disconnected, attempting reconnect") self.reconnect() val=self.chan.getw() self.statusReady=0 except: self.connected=0 val="" self.rPrint("Variable "+self.pvName+" cannot be read after 1 reconnect attempt") return val def putVal(self,val): #direct putval without any retry features try: if (self.waiting): time.sleep(2) # give 2 seconds rest while the system is queued if ((self.pvName.upper().find("ROBO")<0) & DebugMode): self.rPrint("Debug Mode Enabled, thus not altered") else: self.chan.putw(val) self.statusReady=0 time.sleep(0.12) # sleep 120 ms to wait for alarm callback if (self.statusReady==0): self.alarmUpdate() return self.putSuccess except: self.connected=0 return 0 def rPutVal(self,val): # the safe put function that ensures the robot accepts the command, the CAChannel package makes this trickier than needed self.putSuccess=0 self.putAttempts=0 while ((self.putSuccess<>1) & (self.putAttempts<self.MAXPUTS)): self.putVal(val) if (self.putSuccess==0): self.rPrint("Ensure Robot is on and in correct Position! Attempt "+self.putAttempts.__str__()+" of "+self.MAXPUTS.__str__()) tempPA=self.putAttempts self.reconnect() time.sleep(5) self.putAttempts=tempPA if (self.putSuccess): if (self.verbose): print self.pvName+" was successfully put" return 1 else: self.rPrint("Put was not successful") return 0 def statusText(self): return self.pvName+" is currently "+ca.alarmStatusString(self.status) def alarmHandler(self,epics_args,user_args): # a function to handle the alarm feedback from epics telling the user what has happened # the primary purpose is to not allow channels to get overbooked CALC and to know if a variable has been set or nto self.status=epics_args["pv_status"] self.severity=epics_args["pv_severity"] self.alarmUpdate() def alarmUpdate(self): self.statusReady=1 if ((self.status<>ca.AlarmStatus.NO_ALARM) & (self.status<>ca.AlarmStatus.CALC_ALARM)): self.putSuccess=0 self.putAttempts+=1 if (self.verbose): print self.statusText() print "Variable "+self.pvName+" not successfully written after "+str(self.putAttempts)+" try" print "Alarm Severity : "+ca.alarmSeverityString(self.severity) else: self.putSuccess=1 self.putAttempts=0 if (self.status==ca.AlarmStatus.CALC_ALARM): self.waiting=1 if (self.verbose): print "Variable "+self.pvName+" is currently queued!" if ((self.waiting==1) & (self.status==ca.AlarmStatus.NO_ALARM)): self.waiting=0 if (self.verbose): print "Queue Cleared!" def reconnect(self): try: self.chan=CaChannel() self.chan.search(self.pvName) self.chan.pend_io() if (self.chan.element_count()<1): self.rPrint("No channels named "+self.pvName+" found, is the SoftIOC running?") self.connected=(self.chan.state()==ca.ch_state.cs_conn) self.chan.add_masked_array_event(ca.DBR_STRING,1,ca.DBE_ALARM | ca.DBE_VALUE,self.alarmHandler) except CaChannelException, status: print ca.message(status) self.connected=0
class RealRoboEpicsChannel: def __init__(self,pvName,verbose=0,asString=0,vcCallback=None): self.MAXPUTS=10 self.pvName=pvName self.asString=asString self.curValue=0 self.lastPoll=0 self.status=0 # no error self.severity=0 self.statusReady=0 # has a command been executed self.waiting=0 # is the variable overbooked self.putAttempts=0 # the number of times it has tried to put a variable self.putSuccess=0 # if the last put command was successful self.verbose=verbose # if epics should print everything out for alarms and all self.CurrentText="" self.vcCallback=vcCallback # the callback should the value change feed with (chname,newVal,oldVal) if ((self.pvName.upper().find("ROBO")<0) & DebugMode): self.rPrint("Variable "+pvName+" affects beamline and will not be altered") self.reconnect() def rPrint(self,cString): self.CurrentText=self.pvName+": "+cString print self.CurrentText def binaryClick(self): #specific method for dealing with the binary variables that return T/F based on success in robot putOK=self.rPutVal(5) robotOK=self.getVal() if (robotOK==5): time.sleep(.12) robotOK=self.getVal() if (ReadOnly): putOK=1 robotOK=1 return (putOK & robotOK) def getVal(self): try: cTime=time.time() if (cTime-self.lastPoll)>0.2: # prevent double polling val=self.chgetw() self.curValue=val self.lastPoll=cTime else: val=self.curValue except: try: #try one time to reconnect self.rPrint("Variable "+self.pvName+" appears to be disconnected, attempting reconnect") self.reconnect() val=self.chgetw() self.statusReady=0 except: self.connected=0 val="" self.rPrint("Variable "+self.pvName+" cannot be read after 1 reconnect attempt") return val def chgetw(self): if self.asString==1: return str(self.chan.getw(ca.DBF_STRING)) else: return self.chan.getw() def putVal(self,iVal): #direct putval without any retry features self.lastPoll=0 # crop string when it is too long val=iVal if type(iVal)==type(''): if len(iVal)>40: val=iVal[0:39] print 'String was cropped :'+str(val) try: if (self.waiting): time.sleep(2) # give 2 seconds rest while the system is queued if ((self.pvName.upper().find("ROBO")<0) & DebugMode): self.rPrint("Debug Mode Enabled, thus not altered") else: if not ReadOnly: self.curValue=val # default assumption is the value will be loaded self.chan.putw(val) self.statusReady=0 time.sleep(0.12) # sleep 120 ms to wait for alarm callback if (self.statusReady==0): self.alarmUpdate() return self.putSuccess except: self.connected=0 return 0 def rPutVal(self,val): # the safe put function that ensures the robot accepts the command, the CAChannel package makes this trickier than needed self.putSuccess=0 self.putAttempts=0 self.lastPoll=0 while ((self.putSuccess<>1) & (self.putAttempts<self.MAXPUTS)): self.putVal(val) if (self.putSuccess==0): self.rPrint("Ensure Robot is on and in correct Position! Attempt "+self.putAttempts.__str__()+" of "+self.MAXPUTS.__str__()) tempPA=self.putAttempts self.reconnect() time.sleep(5) self.putAttempts=tempPA if (self.putSuccess): if (self.verbose): print self.pvName+" was successfully put" return 1 else: self.rPrint("Put was not successful") return 0 def statusText(self): return self.pvName+" is currently "+ca.alarmStatusString(self.status) def vcHandler(self,epics_args,user_args): # A function to handle value change callbacks newValue=epics_args['pv_value'] self.lastPoll=time.time() if newValue!=self.curValue: # It is different from what we set it to, ick self.curValue=newValue self.vcCallback.__call__(self.pvName,newValue,self.curValue) def alarmHandler(self,epics_args,user_args): # a function to handle the alarm feedback from epics telling the user what has happened # the primary purpose is to not allow channels to get overbooked CALC and to know if a variable has been set or nto self.status=epics_args["pv_status"] self.severity=epics_args["pv_severity"] self.alarmUpdate() def alarmUpdate(self): self.statusReady=1 if ((self.status<>ca.AlarmStatus.NO_ALARM) & (self.status<>ca.AlarmStatus.CALC_ALARM)): self.putSuccess=0 self.putAttempts+=1 if (self.verbose): print self.statusText() if not (self.pvName.upper()=='ARIDI-PCT:CURRENT'): print "Variable "+self.pvName+" not successfully written after "+str(self.putAttempts)+" try" print "Alarm Severity : "+ca.alarmSeverityString(self.severity) else: self.putSuccess=1 self.putAttempts=0 if (self.status==ca.AlarmStatus.CALC_ALARM): self.waiting=1 if (self.verbose): print "Variable "+self.pvName+" is currently queued!" if ((self.waiting==1) & (self.status==ca.AlarmStatus.NO_ALARM)): self.waiting=0 if (self.verbose): print "Queue Cleared!" def reconnect(self): try: self.chan=CaChannel() self.chan.search(self.pvName) self.chan.pend_io() if (self.chan.element_count()<1): self.rPrint("No channels named "+self.pvName+" found, is the SoftIOC running?") self.connected=(self.chan.state()==ca.ch_state.cs_conn) self.chan.add_masked_array_event(ca.DBR_STRING,None,ca.DBE_ALARM,self.alarmHandler) self.rebind(self.vcCallback) except CaChannelException, status: print ca.message(status) self.connected=0