class CounterController(Controller): def create_attributes(self): self.counter = Attribute(NumberMeta(description="A counter")) self.counter.meta.set_dtype('uint32') self.counter.set_put_function(self.counter.set_value) self.counter.set_value(0) yield "counter", self.counter @Controller.Resetting def do_reset(self): self.counter.set_value(0, notify=False) # Transition will do the notify for us @takes() def increment(self): self.counter.set_value(self.counter.value + 1)
class CAPart(Part): def create_attributes(self): params = self.params if params.pv is None and params.rbv is None: raise ValueError('must pass pv rbv') if params.rbv is None: if params.rbv_suff is None: params.rbv = params.pv else: params.rbv = params.pv + params.rbv_suff # Meta instance self.name = params.name self.meta = self.create_meta(params.description) # Pv strings self.pv = params.pv self.rbv = params.rbv # camonitor subscription self.monitor = None self.ca_format = catools.FORMAT_CTRL # This will be our attr self.attr = None # The attribute we will be publishing self.attr = Attribute(self.meta) self.attr.set_put_function(self.caput) yield self.name, self.attr def create_meta(self, description): raise NotImplementedError def get_datatype(self): raise NotImplementedError @Controller.Resetting def connect_pvs(self): # release old monitor self.close_monitor() # make the connection in cothread's thread, use caget for initial value pvs = [self.rbv] if self.pv: pvs.append(self.pv) ca_values = cothread.CallbackResult( catools.caget, pvs, format=self.ca_format, datatype=self.get_datatype()) # check connection is ok for i, v in enumerate(ca_values): assert v.ok, "CA connect failed with %s" % v.state_strings[v.state] self.update_value(ca_values[0]) # now setup monitor on rbv self.monitor = catools.camonitor( self.rbv, self.on_update, notify_disconnect=True, format=self.ca_format, datatype=self.get_datatype()) def close_monitor(self): if self.monitor is not None: cothread.CallbackResult(self.monitor.close) self.monitor = None def caput(self, value): cothread.CallbackResult( catools.caput, self.pv, value, wait=True, timeout=None, datatype=self.get_datatype()) # now do a caget value = cothread.CallbackResult( catools.caget, self.rbv, format=self.ca_format, datatype=self.get_datatype()) self.update_value(value) def on_update(self, value): # Called on cothread's queue, so don't block self.process.spawn(self.update_value, value) def update_value(self, value): self.log_debug("Camonitor update %r", value) # TODO: make Alarm from value.status and value.severity # TODO: make Timestamp from value.timestamp if not value.ok: # TODO: set disconnect self.attr.set_value(None) else: # update value self.attr.set_value(value)