Example #1
0
    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
Example #2
0
    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        
Example #3
0
    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)