def add_pv(self,pvname,set_motor_pairs=True): """adds a PV to the cache: actually requests the addition, which will be handled by the next process_requests in mainloop(). Here, we check for 'Motor' PV typs and make sure all motor fields are requested together, and that the motor fields are 'related' by assigning a pair_score = 10. """ pvname = normalize_pvname(pvname.strip()) fields = (pvname,) if not valid_pvname(pvname): sys.stdout.write("## MasterDB add_pv invalid pvname = '%s'" % pvname) return fields prefix = pvname isMotor = False if pvname.endswith('.VAL'): prefix = pvname[:-4] p = epics.PV(pvname) p.wait_for_connection(timeout=0.1) print 'Master Add PVname = ', pvname, p.connected if p.connected: self.request_pv_cache(pvname) if ('.' not in prefix and p.type == 'double'): rtype = epics.PV(prefix+'.RTYP') rtype.wait_for_connection(0.1) if rtype is not None: isMotor = 'motor' == rtype.get() if isMotor: fields = tuple(["%s%s" % (prefix,i) for i in motor_fields]) pvs = [] for pvname in fields: pvs.append(epics.PV(pvname)) epics.poll() for p in pvs: p.wait_for_connection(timeout=0.5) if p.connected: self.request_pv_cache(p.pvname) if isMotor and set_motor_pairs: time.sleep(0.25) self.set_allpairs(fields) return fields
def add_pv(self,name,description=None,graph={},deadtime=None,deadband=None): """add PV to the database: expected to take a while""" pvname = normalize_pvname(name) t0_start = time.time() if not valid_pvname(pvname): sys.stdout.write("## Archiver add_pv invalid pvname = '%s'" % pvname) return None if pvname in self.pvinfo: if 'yes' == self.pvinfo[pvname]['active']: self.write("PV %s is already in database.\n" % pvname) else: self.write("PV %s is in database, reactivating!\n" % pvname) self.pvinfo[pvname]['active'] = 'yes' return None # create an Epics PV, check that it's valid try: pv = epics.PV(pvname) pv.connect() pv.get_ctrlvars() typ = pv.type count = pv.count prec = pv.precision connected = pv.connected except: typ= 'int' count = 1 prec = None connected = False if not connected: self.write("cannot add PV '%s': not connected" % pvname) return None # determine type dtype = 'string' if (typ in ('int','long','short')): dtype = 'int' if (typ in ('enum',)): dtype = 'enum' if (typ in ('double','float')): dtype = 'double' # determine data table table = "pvdat%3.3i" % ((hash(pvname) % 128) + 1) # determine descrption (don't try too hard!) if description is None: if pvname.endswith('.VAL'): descpv = "%s.DESC" % pvname[:-4] else: descpv = "%s.DESC" % pvname for f in motor_fields: if pvname.endswith(f): descpv = None if descpv is not None: try: dp = epics.PV(descpv) description = dp.get(as_string=True) ## dp.disconnect() except: pass if description is None: description = '' # set graph default settings gr = {'high':'','low':'','type':'normal'} gr.update(graph) if dtype == 'enum': x = pv.get(as_string=True) gr['type'] = 'discrete' gr['low'] = 0 gr['high'] = len(pv.enum_strs) elif dtype == 'double': gr['type'] = 'normal' dx = description.lower() for i in ('cathode','pirani','pressure'): if dx.find(i) >= 0: gr['type'] = 'log' if (deadtime == None): deadtime = config.pv_deadtime_dble if dtype in ('enum','string'): deadtime = config.pv_deadtime_enum if (gr['type'] == 'log'): deadtime = 5.0 # (pressures change very frequently) if (deadband == None): deadband = 1.e-5 if (gr['type'] == 'log'): deadband = 1.e-4 if prec is not None: deadband = 10**(-(prec+1)) if dtype in ('enum','string'): deadband = 0.5 self.write('Archiver adding PV: %s, table: %s' % (pvname,table)) self.pv_table.insert(name = pvname, type = dtype, description= description, data_table = table, deadtime = deadtime, deadband = deadband, graph_lo = gr['low'], graph_hi = gr['high'], graph_type = gr['type']) dat = self.pv_table.select_where(name=pvname)[0] dat['force_time'] = get_force_update_time() dat['last_ts'] = 0 dat['last_value'] = None self.pvinfo[pvname] = dat self.update_value(pvname,time.time(),pv.value) self.write(" time=%f\n" % (time.time() - t0_start)) sys.stdout.flush() pv = None
def process_requests(self): " process requests for new PV's to be cached" req = self.sql_exec_fetch("select * from requests") if len(req) == 0: return del_cache= "delete from cache where %s" # note: if a requested PV does not connect, # wait a few minutes before dropping from # the request table. if len(req)>0: sys.stdout.write("processing %i requests at %s\n" % (len(req), time.ctime())) sys.stdout.flush() es = clean_string sys.stdout.write( 'Process Req: %i\n' % len(self.pvnames)) if len(self.pvnames)== 0: self.get_pvnames() sys.stdout.write( 'Process Req: %i\n' % len(self.pvnames)) now = time.time() self.db.set_autocommit(1) drop_ids = [] for r in req: nam, rid, action, ts = r['pvname'], r['id'], r['action'], r['ts'] where = "pvname='%s'" % nam print 'Request: ', nam, rid, action if valid_pvname(nam) and (now-ts < 3000.0): if 'suspend' == action: if self.pvs.has_key(nam): self.pvs[nam].clear_callbacks() self.cache.update(active='no',where=where) drop_ids.append(rid) elif 'drop' == action: if nam in self.pvnames: self.sql_exec(del_cache % where) drop_ids.append(rid) elif 'add' == action: if nam not in self.pvnames: pv = self.epics_connect(nam) xval = pv.get(as_string=True) conn = pv.wait_for_connection(timeout=1.0) if conn: self.add_epics_pv(pv) self.set_value(pv=pv) pv.add_callback(self.onChanges) self.pvs[nam] = pv drop_ids.append(rid) sys.stdout.write('added PV = %s\n' % nam) else: sys.stdout.write('could not connect to PV %s\n' % nam) else: print '? already in self.pvnames ', nam drop_ids.append(rid) else: drop_ids.append(rid) time.sleep(0.01) self.get_pvnames() for rid in drop_ids: self.sql_exec( "delete from requests where id=%i" % rid ) time.sleep(0.01) self.db.set_autocommit(0)