def __init__(self, channel, prefix): """Initialize the Low Level object. callback is the callable to be called each time a low level PV changes its value. """ super().__init__() self.channel = _PVName(channel) self.prefix = prefix self._dict_functs_for_write = self._define_dict_for_write() self._dict_functs_for_update = self._define_dict_for_update() self._dict_functs_for_read = self._define_dict_for_read() self._dict_convert_prop2pv = self._define_convertion_prop2pv() self._dict_convert_pv2prop = { val: key for key, val in self._dict_convert_prop2pv.items() } self._config_ok_values = dict() self._base_freq = _RFFREQ / _RFDIV self._writepvs = dict() self._readpvs = dict() self._locked = False evg_name = _LLTimeSearch.get_evg_name() self._base_freq_pv = _PV(LL_PREFIX + evg_name + ':FPGAClk-Cte') self._update_base_freq() self._base_freq_pv.add_callback(self._update_base_freq) _log.info(self.channel + ': Creating PVs.') for prop, pvname in self._dict_convert_prop2pv.items(): pvnamerb = pvnamesp = None if not _PVName.is_write_pv(pvname): pvnamerb = pvname pvnamesp = _PVName.from_rb2sp(pvname) elif _PVName.is_cmd_pv(pvname): # -Cmd is different!! self._writepvs[prop] = _PV(pvname) if pvnamerb is not None: self._readpvs[prop] = _PV(pvnamerb) if pvnamesp != pvnamerb and not prop.endswith('DevEnbl'): self._writepvs[prop] = _PV(pvnamesp) self._writepvs[prop]._initialized = False for prop, pv in self._writepvs.items(): if not pv.wait_for_connection(): _log.info(pv.pvname + ' not connected.') for prop, pv in self._readpvs.items(): if not pv.wait_for_connection(): _log.info(pv.pvname + ' not connected.') for prop, pv in self._writepvs.items(): if _PVName.is_cmd_pv(pv.pvname): continue pv.add_callback(self._on_change_writepv) pv.connection_callbacks.append(self._on_connection_writepv) for prop, pv in self._readpvs.items(): pv.add_callback(self._on_change_readpv) pv.connection_callbacks.append(self._on_connection)
def readall(self, is_sp=False): """Read all.""" values = dict() for prop, suf in self._all_props_suffix.items(): if _PVName.is_cmd_pv(suf) or (is_sp and not _PVName.is_rb_pv(suf)): continue value = self.read(prop, is_sp=is_sp) if value is None or not value: continue values[prop] = value return values
def get_map2readpvs(self): """Get the database.""" dbase = self.get_database() map2readpvs = dict() for pvname in dbase: if _PVName.is_cte_pv(pvname) or _PVName.is_cmd_pv(pvname): continue prop = self._get_prop_name(pvname) map2readpvs[pvname] = _partial( self.read, prop, is_sp=_PVName.is_sp_pv(pvname)) return map2readpvs
def _update_pvs_thread(self): _time.sleep(1/10) # limit update in 10Hz for prop, suf in self._all_props_suffix.items(): if _PVName.is_cmd_pv(suf): continue value = self.read(prop) if value is None: return self.run_callbacks(self._get_pv_name(prop), **value) # Uncomment this if you want to update setpoint PVs as well # This is not recommended though, because it can create very # strange unusual behavior with widgets such as spinbox in PyDM # and CS-Studio. if not _PVName.is_rb_pv(suf): continue value = self.read(prop, is_sp=True) if value is None: return self.run_callbacks(self._get_pv_name(prop, is_sp=True), **value)
def _on_connection_writepv(self, pvname, conn, **kwargs): if not _PVName.is_cmd_pv(pvname): # -Cmd must not change prop = self._dict_convert_pv2prop[_PVName.from_sp2rb(pvname)] self._writepvs[prop]._initialized = False # not self._locked self._on_connection(pvname, conn)
def _on_change_writepv(self, pvname, value, **kwargs): # -Cmd PVs do not have a state associated to them if value is None or _PVName.is_cmd_pv(pvname): return _Thread(target=self._on_change_pv_thread, args=(pvname, value)).start()