Exemplo n.º 1
0
    def dyn_attr(self):
        self.dyn_attrs = getattr(self, 'dyn_attrs', [])
        self.info('dyn_attr(%s)' % self.dyn_attrs)
        for l, n in product('VPI', '1234'):

            if l + n not in self.dyn_attrs:
                self.info('Adding attribute: %s' % (l + n))
                unit, frmt = {
                    'V': ('V', '%d'),
                    'P': ('mbar', '%g'),
                    'I': ('mA', '%g')
                }[l]
                attrib = PyTango.Attr(l + n, PyTango.DevDouble,
                                      PyTango.AttrWriteType.READ)
                props = PyTango.UserDefaultAttrProp()
                props.set_format(frmt), props.set_unit(unit)
                attrib.set_default_properties(props)
                self.add_attribute(attrib, self.read_dyn_attr, None,
                                   self.is_Attr_allowed)

            self.thread.append(l + n, period=self.Refresh)

        for a in ('Model', 'ErrorCode', 'ModeLocal'):
            self.info('Adding attribute (%d s): %s' % (self.Refresh * 5, a))
            attrib = PyTango.Attr(a, PyTango.DevString,
                                  PyTango.AttrWriteType.READ)
            self.add_attribute(attrib, self.read_dyn_attr, None,
                               self.is_Attr_allowed)
            self.thread.append(a, period=self.Refresh * 5)
Exemplo n.º 2
0
    def initialize_dynamic_attributes(self):
        """ Initialize dynamic attributes
        """
        if self.chiller_type == self.POLYSCIENCE:
            # Add temperature attribute
            attr = PT.Attr("Temperature", PT.DevDouble, PT.AttrWriteType.READ)
            attr_prop = PT.UserDefaultAttrProp()
            attr_prop.label = "Temperature"
            attr_prop.format = "%.1f"
            attr_prop.unit = "°C"
            attr.set_default_properties(attr_prop)
            attr.set_change_event(True, False)
            self.add_attribute(attr, self.read_Temperature)

            # Subscribe events
            self.dev.subscribe_event("Temperature", PT.EventType.CHANGE_EVENT,
                                     self.event_callback)
            self.dev.subscribe_event("State", PT.EventType.CHANGE_EVENT,
                                     self.event_callback)

        else:
            # Subscribe events
            self.dev.subscribe_event("State", PT.EventType.CHANGE_EVENT,
                                     self.event_callback)

        # Subscribe events from water valve
        self.water.subscribe_event("State", PT.EventType.CHANGE_EVENT,
                                   self.event_callback)
        self.water.subscribe_event("WaterFlow", PT.EventType.CHANGE_EVENT,
                                   self.event_callback)
Exemplo n.º 3
0
    def add_RegulationTuneable(self):
        @PS.AttrExc
        def read_RegulationTuneable(inst, attr):
            attr.set_value(self.writeable)

        @PS.AttrExc
        def write_RegulationTuneable(inst, attr):
            self.writeable = attr.get_write_value()
            inst.push_change_event('RegulationTuneable', self.writeable)

        attr = Tg.Attr('RegulationTuneable', Tg.DevBoolean, Tg.READ_WRITE)
        self.impl.add_attribute(attr,
                                r_meth=read_RegulationTuneable,
                                w_meth=write_RegulationTuneable)
        while True:
            try:
                self.impl.set_change_event('RegulationTuneable', True)
                break
            except ValueError:
                self.impl.warn('add_RegulationTuneable', exc_info=1)
                sleep(0.1)
            except Tg.DevFailed, df:
                if df[-1].reason == 'API_AttrNotFound':
                    self.impl.warn('add_RegulationTuneable', exc_info=1)
                    sleep(0.1)
                else:
                    raise
Exemplo n.º 4
0
 def __configureRamping(self, attrName, definition, readmethod,
                        writemethod):
     if self.__device is not None:
         db = PyTango.Database()
         step = PyTango.Attr(attrName + "Step", definition['type'],
                             PyTango.READ_WRITE)
         step.set_memorized()
         step.set_memorized_init(True)
         self.__device.add_attribute(step,
                                     r_meth=readmethod,
                                     w_meth=writemethod)
         try:
             devName = self.__device.get_name()
             stepAttrName = attrName + "Step"
             attrProp = db.get_device_attribute_property(
                 devName, stepAttrName)
             propertyValueStr = attrProp[stepAttrName]['__value'][0]
             value = float(propertyValueStr)
             rampObj = self._parent.attributes[attrName].getRampObj()
             rampObj.rampStep = value
         except:
             rampObj = self._parent.attributes[attrName].getRampObj()
             rampObj.rampStep = None
         stepspeed = PyTango.Attr(attrName + "StepSpeed",
                                  PyTango.CmdArgType.DevDouble,
                                  PyTango.READ_WRITE)
         stepspeed.set_memorized()
         stepspeed.set_memorized_init(True)
         self.__device.add_attribute(stepspeed,
                                     r_meth=readmethod,
                                     w_meth=writemethod)
         try:
             devName = self.__device.get_name()
             stepSpeedAttrName = attrName + "StepSpeed"
             attrProp = db.get_device_attribute_property(
                 devName, stepSpeedAttrName)
             propertyValueStr = attrProp[attrName +
                                         "StepSpeed"]['__value'][0]
             value = float(propertyValueStr)
             rampObj = self._parent.attributes[attrName].getRampObj()
             rampObj.rampStepSpeed = value
         except:
             rampObj = self._parent.attributes[attrName].getRampObj()
             rampObj.rampStepSpeed = None
     self._attributeList.append(attrName + "Step")
     self._attributeList.append(attrName + "StepSpeed")
Exemplo n.º 5
0
 def createReconnectTriggerAttribute(self):
     attr = PyTango.Attr("Reconnect_Trigger", PyTango.DevDouble,
                         PyTango.AttrWriteType.WRITE)
     prop = PyTango.UserDefaultAttrProp()
     prop.set_description(
         "Triggers a reconnection attempt to the hardware.")
     attr.set_default_properties(prop)
     self.add_attribute(attr, self.read_Reconnect_Trigger,
                        self.write_Reconnect_Trigger)
    def dyn_attr(self):
        for process in self.ProcessList:
            #self.debug_stream('dyn_attr(): Adding attributes for %s process'%process)
            aname = re.sub('[^0-9a-zA-Z]+', '_', process)
            for suffix,data_type,data_format,unit in\
                (('nprocesses',PyTango.DevLong,PyTango.SCALAR,None),
                 ('nthreads',PyTango.DevLong,PyTango.SCALAR,None),
                 ('pids',PyTango.DevLong,PyTango.SPECTRUM,None),
                 ('cpu',PyTango.DevDouble,PyTango.SCALAR,'%'),
                 ('mem',PyTango.DevDouble,PyTango.SCALAR,'MB'),
                 ('vmem',PyTango.DevDouble,PyTango.SCALAR,'MB'),
                 ('memRatio',PyTango.DevDouble,PyTango.SCALAR,'%'),
                 ('kbpm',PyTango.DevDouble,PyTango.SCALAR,'%'),
                ):
                #TODO: set the units
                if data_format == PyTango.SCALAR:
                    self.add_attribute(
                        PyTango.Attr(aname + '_' + suffix, data_type,
                                     PyTango.AttrWriteType.READ),
                        self.read_dyn_attr, None,
                        (lambda s, req_type, attr_name=aname + '_' + suffix:
                         True))
                    if self.UseEvents:
                        self.set_change_event(aname + '_' + suffix, True,
                                              False)

                elif data_format == PyTango.SPECTRUM:
                    self.add_attribute(
                        PyTango.SpectrumAttr(aname + '_' + suffix, data_type,
                                             PyTango.READ, 1000),
                        self.read_dyn_attr, None,
                        (lambda s, req_type, attr_name=aname + '_' + suffix:
                         True))
                    if self.UseEvents:
                        self.set_change_event(aname + '_' + suffix, True,
                                              False)
        #self._dyn_attr_build = True
        self.change_state(PyTango.DevState.ON)
        return
Exemplo n.º 7
0
    def add_attr(self, aname, rp, slave_index, **extra):
        impl = self.impl
        extra['format'] = '%7.4f'
        index = rp.index + slave_index

        @PS.AttrExc
        def read_f(inst, attr):
            inst.obj_vdq(rp.cobj, index).set_attr(attr)

        @PS.AttrExc
        def write_f(inst, wattr):
            if not self.writeable:
                raise PS.PS_Exception('tuning regulation parameters disabled')
            write_value = wattr.get_write_value()
            inst.obj_set(rp.cobj, index, repr(write_value))

        attr = Tg.Attr(aname, Tg.DevDouble, rp.rw)
        aprop = Tg.UserDefaultAttrProp()

        if 'desc' in extra:
            extra['description'] = extra['desc']
            del extra['desc']

        attr.set_disp_level(Tg.DispLevel.EXPERT)

        for key, val in extra.iteritems():
            getattr(aprop, 'set_' + key)(val)

        # retries for 10 seconds...
        for x in range(0, 40):
            try:
                self.impl.add_attribute(attr, r_meth=read_f, w_meth=write_f)
                break
            except Exception, exc:
                self.impl.log.debug(str(exc), exc_info=1)
                sleep(0.25)
Exemplo n.º 8
0
    def initialize_dynamic_attributes(self):
        self.debug_stream('In initialize_dynamic_attributes()')
        if self.pv is not None:  # already initialized
            return
        # variables initialization
        READ_METHOD = self.read_attr
        WRITE_METHOD = self.write_attr
        if self.Host == []:
            self.Host = ''
        self.pv = {}
        pvs = {}

        try:
            # initialize libca library
            epics.ca.initialize_libca()

            # get pv names and build libca channels
            for pv_entry in self.ProcessVariables:
                pv_attr = pv_entry.split('\t')
                attr_name = None
                if len(pv_attr) == 1:
                    pv_name = pv_attr[0]
                elif len(pv_attr) == 2:
                    pv_name, attr_name = pv_attr
                else:
                    msg = 'Invalid entry in ProcessVariables device property:'\
                        ' %s' % pv_entry
                    self.error_stream(msg)
                    self._set_state(PyTango.DevState.FAULT, msg)
                    return
                # get host name if necessary
                if self.Host != '':
                    pv_full_name = '%s:%s' % (self.Host, pv_name)
                else:
                    pv_full_name = pv_name
                # create epics channel to PV (to increase performance do not
                # wait for a connection)
                ch_id = epics.ca.create_channel(
                    pv_full_name,
                    connect=False,
                    auto_cb=False)
                # build default attribute name (if not provided)
                if attr_name is None:
                    attr_name = self.epics2tango_name(pv_name)
                self.pv[attr_name] = [ch_id, pv_full_name]
                pvs[attr_name] = [ch_id]

            # connect PVs and get necessary info
            for name, data in pvs.items():
                connected = epics.ca.connect_channel(data[0])
                if not connected:
                    msg = 'At least one channel unreachable. Is hardware up?'
                    self.error_stream(msg)
                    self._set_state(PyTango.DevState.FAULT,
                                    msg, force_init=True)
                    return
            epics.ca.poll()  # wait for connections completion
            for name, data in pvs.items():
                data.append(epics.ca.field_type(data[0]))
                data.append(epics.ca.read_access(data[0]))
                data.append(epics.ca.write_access(data[0]))
                data.append(epics.ca.element_count(data[0]))

            # add dynamic attributes
            for attr_name, data in pvs.items():
                # find out tango type
                tango_type = self.epics2tango_type(data[1])
                if tango_type is None:
                    msg = 'Unknown type %s for PV %s' %\
                          (str(data[1]), self.pv[attr_name][1])
                    self.error_stream(msg)
                    self._set_state(PyTango.DevState.ALARM, msg)
                    del self.pv[attr_name]
                    continue
                # find out read/write access
                read_access = bool(data[2])
                write_access = bool(data[3])
                read_method = None
                write_method = None
                if read_access and write_access:
                    read_method = READ_METHOD
                    write_method = WRITE_METHOD
                    access_type = PyTango.AttrWriteType.READ_WRITE
                elif read_access and not write_access:
                    read_method = READ_METHOD
                    access_type = PyTango.AttrWriteType.READ
                elif not read_access and write_access:
                    write_method = WRITE_METHOD
                    access_type = PyTango.AttrWriteType.WRITE
                else:
                    msg = 'PV %s has neither read nor write permissions'\
                          % pv_full_name
                    self.error_stream(msg)
                    self._set_state(PyTango.DevState.FAULT, msg)
                    continue
                # find out dimension and build attribute
                dimension = data[4]
                if dimension > 1:
                    attr = PyTango.SpectrumAttr(
                        attr_name,
                        tango_type,
                        access_type,
                        dimension)
                else:
                    attr = PyTango.Attr(
                        attr_name,
                        tango_type,
                        access_type)
                properties = PyTango.UserDefaultAttrProp()
                # set description field with PV name
                properties.set_description(self.pv[attr_name][1])
                attr.set_default_properties(properties)
                # add attribute
                self.add_attribute(attr, read_method, write_method)
        except Exception as e:
            msg = 'Unable to create dynamic attributes'
            self.error_stream('%s: %s' % (msg, str(e)))
            self._set_state(PyTango.DevState.FAULT, msg)
        del pvs  # no longer used
Exemplo n.º 9
0
 def __getAttrObj(self,
                  attrName,
                  definition,
                  channel=None,
                  function=None,
                  multiple=None):
     # TODO: image dimensions
     if self.__device is not None:
         if definition['dim'] == [0]:
             if 'writeCmd' in definition:
                 attr = PyTango.Attr(attrName, definition['type'],
                                     PyTango.READ_WRITE)
                 readmethod = AttrExc(getattr(self.__device, 'read_attr'))
                 writemethod = AttrExc(getattr(self.__device, 'write_attr'))
             else:
                 attr = PyTango.Attr(attrName, definition['type'],
                                     PyTango.READ)
                 readmethod = AttrExc(getattr(self.__device, 'read_attr'))
                 writemethod = None
         elif definition['dim'][0] == 1:
             if 'writeCmd' in definition:
                 attr = PyTango.SpectrumAttr(attrName, definition['type'],
                                             PyTango.READ_WRITE,
                                             definition['dim'][1])
                 readmethod = AttrExc(getattr(self.__device, 'read_attr'))
                 writemethod = AttrExc(getattr(self.__device, 'write_attr'))
             else:
                 attr = PyTango.SpectrumAttr(attrName, definition['type'],
                                             PyTango.READ,
                                             definition['dim'][1])
                 readmethod = AttrExc(getattr(self.__device, 'read_attr'))
                 writemethod = None
         else:
             raise AttributeError("Not supported multiple dimensions")
         # attribute properties
         aprop = PyTango.UserDefaultAttrProp()
         if 'unit' in definition:
             aprop.set_unit(latin1(definition['unit']))
         if 'min' in definition:
             aprop.set_min_value(str(definition['min']))
         if 'max' in definition:
             aprop.set_max_value(str(definition['max']))
         if 'format' in definition:
             format = latin1(definition['format'])
             if format.count("%") == 2:
                 format = format.replace('%', '', 1)
             aprop.set_format(format)
         if 'description' in definition:
             aprop.set_description(latin1(definition['description']))
         if 'label' in definition:
             aprop.set_label(latin1(definition['label']))
         if 'memorized' in definition:
             attr.set_memorized()
             attr.set_memorized_init(True)
         attr.set_default_properties(aprop)
         self.__device.add_attribute(attr,
                                     r_meth=readmethod,
                                     w_meth=writemethod)
         multiattr = self.__device.get_device_attr()
         attrId = multiattr.get_attr_ind_by_name(attrName)
         self._attributeIds[attrId] = attrName
     else:
         attrId = self._generateAttrId(attrName)
         attr = None
         aprop = None
     # self.debug_stream("Attribute %s has the id %s" % (attrName, attrId))
     self._attributeList.append(attrName)
     # prepare internal structure ---
     if channel is not None or function is not None or multiple is not None:
         if channel is not None:
             like = "channel"
             number = channel
         elif function is not None:
             like = "function"
             number = function
         elif multiple is not None and \
                 'scpiPrefix' in definition['multiple'] and\
                 'attrSuffix' in definition['multiple']:
             like = definition['multiple']['scpiPrefix']
             number = multiple
         else:
             raise AttributeError("Wrong definition of multiple attribute")
         self.__prepareChannelLikeAttr(like, number, definition, attrName)
     else:
         readCmd = definition['readCmd']
         if 'writeCmd' not in definition:
             # writeCmd = definition['writeCmd']
             definition['writeCmd'] = None
     if 'readFormula' not in definition:
         # readFormula = definition['readFormula']
         definition['readFormula'] = None
     # if 'writeFormula' not in definition:
     #     # writeFormula = definition['writeFormula']
     #     writeFormula = None
     # build internal structure ---
     if 'rampeable' in definition and definition['rampeable'] is True:
         self.__buildRWObj(attrName, attrId, definition, readmethod,
                           writemethod)
     if 'delayAfterWrite' not in definition:
         definition['delayAfterWrite'] = 0.0
     if definition['writeCmd'] is None:
         self.__buildROObj(attrName, attrId, definition)
     else:
         self.__buildRWObj(attrName, attrId, definition)
         if 'writeValues' in definition:
             self.__prepareWriteValues(attrName, definition, aprop, attr)
     return attr
Exemplo n.º 10
0
    def reader_hook(self, attribute, values):
        """This method will be executed by the ReaderProcess to process the queried data."""
        try:
            print('>' * 80)
            print(time.ctime() + ' In reader_hook(%s,[%d])' %
                  (attribute, len(values)))
            self.counter -= 1
            print(self.counter)

            MAXDIM = 1024 * 1024 * 1024
            #First create the attributes
            epoch, data, aname = [], [], attribute.replace('/', '__')
            values = decimate_values(values)
            [(epoch.append(v[0]), data.append(v[1])) for v in values]
            writable = PyTango.AttrWriteType.READ

            #Adding time attribute
            m, atformat, dims = None, PyTango.SpectrumAttr, [MAXDIM]
            for d in data:
                if d is not None:
                    if fn.isSequence(d):
                        atformat, dims = PyTango.ImageAttr, [MAXDIM, MAXDIM]
                        m = d[0]
                    else:
                        m = d
                    break

            attype = PyTango.DevDouble if (
                fn.isNumber(m) or fn.isBool(m)) else PyTango.DevString
            self.add_attribute(
                PyTango.ImageAttr(aname, attype, writable, MAXDIM, MAXDIM),
                self.read_dyn_attr, None, self.is_dyn_attr_allowed)

            self.add_attribute(
                PyTango.SpectrumAttr(aname + '_t', PyTango.DevDouble, writable,
                                     MAXDIM), self.read_dyn_attr, None,
                self.is_dyn_attr_allowed)

            self.add_attribute(
                PyTango.SpectrumAttr(aname + '_d', PyTango.DevString, writable,
                                     MAXDIM), self.read_dyn_attr, None,
                self.is_dyn_attr_allowed)

            self.add_attribute(atformat(aname + '_r', attype, writable,
                                        *dims), self.read_dyn_attr, None,
                               self.is_dyn_attr_allowed)

            self.add_attribute(
                PyTango.Attr(aname + '_l', attype, PyTango.AttrWriteType.READ),
                self.read_dyn_attr, None, self.is_dyn_attr_allowed)

            self.add_attribute(
                PyTango.Attr(aname + '_ld', PyTango.DevString,
                             PyTango.AttrWriteType.READ), self.read_dyn_attr,
                None, self.is_dyn_attr_allowed)

            #Then add the data to Cache values, so IsDataReady will return True
            t = fn.now()
            self.RemoveCachedAttribute(attribute)
            self.AttrData[attribute] = (t, atformat, attype, values)
            print('Done: %s,%s,%s,%s,%d' %
                  (attribute, t, atformat, attype, len(values)))
        except:
            print(traceback.format_exc())
Exemplo n.º 11
0
 def CreateAttribute(self, name):
     #    Add your own code here
     attr = PyTango.Attr(name, PyTango.DevString, PyTango.READ_WRITE)
     self.add_attribute(attr, self.read_General, self.write_General)
Exemplo n.º 12
0
 def __getAttrObj(self,
                  attrName,
                  definition,
                  channel=None,
                  function=None,
                  multiple=None):
     # TODO: image dimensions
     if definition['dim'] == [0]:
         if 'writeCmd' in definition:
             attr = PyTango.Attr(attrName, definition['type'],
                                 PyTango.READ_WRITE)
             readmethod = AttrExc(getattr(self.__device, 'read_attr'))
             writemethod = AttrExc(getattr(self.__device, 'write_attr'))
         else:
             attr = PyTango.Attr(attrName, definition['type'], PyTango.READ)
             readmethod = AttrExc(getattr(self.__device, 'read_attr'))
             writemethod = None
     elif definition['dim'][0] == 1:
         if 'writeCmd' in definition:
             attr = PyTango.SpectrumAttr(attrName, definition['type'],
                                         PyTango.READ_WRITE,
                                         definition['dim'][1])
             readmethod = AttrExc(getattr(self.__device, 'read_attr'))
             writemethod = AttrExc(getattr(self.__device, 'write_attr'))
         else:
             attr = PyTango.SpectrumAttr(attrName, definition['type'],
                                         PyTango.READ, definition['dim'][1])
             readmethod = AttrExc(getattr(self.__device, 'read_attr'))
             writemethod = None
     else:
         raise AttributeError("Not supported multiple dimensions")
     # attribute properties
     aprop = PyTango.UserDefaultAttrProp()
     if 'unit' in definition:
         aprop.set_unit(latin1(definition['unit']))
     if 'min' in definition:
         aprop.set_min_value(str(definition['min']))
     if 'max' in definition:
         aprop.set_max_value(str(definition['max']))
     if 'format' in definition:
         aprop.set_format(latin1(definition['format']))
     if 'description' in definition:
         aprop.set_description(latin1(definition['description']))
     if 'label' in definition:
         aprop.set_label(latin1(definition['label']))
     if 'memorized' in definition:
         attr.set_memorized()
         attr.set_memorized_init(True)
     attr.set_default_properties(aprop)
     self.__device.add_attribute(attr,
                                 r_meth=readmethod,
                                 w_meth=writemethod)
     self._attributeList.append(attrName)
     # prepare internal structure ---
     if channel or function or multiple:
         if channel:
             like = "channel"
         elif function:
             like = "function"
         elif multiple and 'scpiPrefix' in definition['multiple'] and\
                 'attrSuffix' in definition['multiple']:
             like = definition['multiple']['scpiPrefix']
         else:
             raise AttributeError("Wrong definition of multiple attribute")
         number = channel or function or multiple
         self.__prepareChannelLikeAttr(like, number, definition)
     else:
         readCmd = definition['readCmd']
         if 'writeCmd' not in definition:
             # writeCmd = definition['writeCmd']
             definition['writeCmd'] = None
     if 'readFormula' not in definition:
         # readFormula = definition['readFormula']
         definition['readFormula'] = None
     # if 'writeFormula' not in definition:
     #     # writeFormula = definition['writeFormula']
     #     writeFormula = None
     # build internal structure ---
     if definition['writeCmd'] is None:
         self.__buildROObj(attrName, definition)
     else:
         self.__buildRWObj(attrName, definition, readmethod, writemethod)
         if 'writeValues' in definition:
             self.__prepareWriteValues(attrName, definition, aprop, attr)
     return attr
Exemplo n.º 13
0
    def initialize_dynamic_attributes(self):
        """ Initialize dynamic attributes
        """
        if self.IsCameraOnline():

            # Get attributes
            multi_attr = self.get_device_attr()

            # Set minimum and maximum integration time
            attribute = multi_attr.get_attr_by_name("ExposureTime")
            multi_prop = attribute.get_properties()
            multi_prop.unit = self.camera.ExposureTimeAbs.Unit
            multi_prop.min_value = "{0:.1f}".format(
                self.camera.ExposureTimeAbs.GetMin())
            multi_prop.max_value = "{0:.1f}".format(
                self.camera.ExposureTimeAbs.GetMax())
            attribute.set_properties(multi_prop)
            attribute.set_change_event(True, False)

            # Set minimum and maximum gain
            attribute = multi_attr.get_attr_by_name("Gain")
            multi_prop = attribute.get_properties()
            if "Gain" in dir(self.camera):
                multi_prop.min_value = "{0:.1f}".format(
                    self.camera.Gain.GetMin())
                multi_prop.max_value = "{0:.1f}".format(
                    self.camera.Gain.GetMax())
            else:
                multi_prop.min_value = "{0:.1f}".format(
                    self.gc.raw2db(self.camera.GainRaw.GetMin(),
                                   self.camera.DeviceModelName()))
                multi_prop.max_value = "{0:.1f}".format(
                    self.gc.raw2db(self.camera.GainRaw.GetMax(),
                                   self.camera.DeviceModelName()))
            attribute.set_properties(multi_prop)
            attribute.set_change_event(True, False)

            # Enable change event on enable trigger
            attribute = multi_attr.get_attr_by_name("EnableTrigger")
            attribute.set_change_event(True, False)

            # Create TriggerSource attribute
            attr = PT.Attr("TriggerSource", PT.DevEnum,
                           PT.AttrWriteType.READ_WRITE)
            attr_prop = PT.UserDefaultAttrProp()
            attr_prop.label = "Trigger Source"
            attr_prop.set_enum_labels(
                list(self.camera.TriggerSource.GetSymbolics()))
            attr.set_default_properties(attr_prop)
            attr.set_memorized()
            attr.set_memorized_init(True)
            attr.set_change_event(True, False)
            self.add_attribute(attr, self.read_TriggerSource,
                               self.write_TriggerSource, self.IsCameraOnline)

            # Create PixelFormat attribute
            attr = PT.Attr("PixelFormat", PT.DevEnum,
                           PT.AttrWriteType.READ_WRITE)
            attr_prop = PT.UserDefaultAttrProp()
            attr_prop.label = "Pixel Format"
            attr_prop.set_enum_labels(
                list(self.camera.PixelFormat.GetSymbolics()))
            attr.set_default_properties(attr_prop)
            attr.set_memorized()
            attr.set_memorized_init(True)
            attr.set_change_event(True, False)
            self.add_attribute(attr, self.read_PixelFormat,
                               self.write_PixelFormat, self.IsCameraOnline)

            # Create auto-exposure attribute
            if "ExposureAuto" in dir(self.camera):
                attr = PT.Attr("AutoExposure", PT.DevEnum,
                               PT.AttrWriteType.READ_WRITE)
                attr_prop = PT.UserDefaultAttrProp()
                attr_prop.label = "Auto exposure"
                attr_prop.set_enum_labels(
                    list(self.camera.ExposureAuto.GetSymbolics()))
                attr.set_default_properties(attr_prop)
                attr.set_change_event(True, False)
                self.add_attribute(attr, self.read_AutoExposure,
                                   self.write_AutoExposure,
                                   self.IsCameraOnline)

                # Brightness target
                attr = PT.Attr("AutoBrightnessTarget", PT.DevUShort,
                               PT.AttrWriteType.READ_WRITE)
                attr_prop = PT.UserDefaultAttrProp()
                attr_prop.label = "Auto brightness target"
                attr_prop.min_value = "{0:d}".format(
                    self.camera.AutoTargetValue.GetMin())
                attr_prop.max_value = "{0:d}".format(
                    self.camera.AutoTargetValue.GetMax())
                attr_prop.format = "%d"
                attr.set_default_properties(attr_prop)
                attr.set_memorized()
                attr.set_memorized_init(True)
                attr.set_change_event(True, False)
                self.add_attribute(attr, self.read_AutoBrightnessTarget,
                                   self.write_AutoBrightnessTarget,
                                   self.IsCameraOnline)

                # Exposure time lower limit
                attr = PT.Attr("AutoExposureLowerLimit", PT.DevDouble,
                               PT.AttrWriteType.READ_WRITE)
                attr_prop = PT.UserDefaultAttrProp()
                attr_prop.label = "Auto exposure time lower limit"
                attr_prop.min_value = "{0:.1f}".format(
                    self.camera.AutoExposureTimeAbsLowerLimit.GetMin())
                attr_prop.max_value = "{0:.1f}".format(
                    self.camera.AutoExposureTimeAbsLowerLimit.GetMax())
                attr_prop.format = "%.1f"
                attr_prop.unit = "us"
                attr.set_default_properties(attr_prop)
                attr.set_memorized()
                attr.set_memorized_init(True)
                attr.set_change_event(True, False)
                self.add_attribute(attr, self.read_AutoExposureLowerLimit,
                                   self.write_AutoExposureLowerLimit,
                                   self.IsCameraOnline)

                # Exposure time upper limit
                attr = PT.Attr("AutoExposureUpperLimit", PT.DevDouble,
                               PT.AttrWriteType.READ_WRITE)
                attr_prop = PT.UserDefaultAttrProp()
                attr_prop.label = "Auto exposure time lower limit"
                attr_prop.min_value = "{0:.1f}".format(
                    self.camera.AutoExposureTimeAbsUpperLimit.GetMin())
                attr_prop.max_value = "{0:.1f}".format(
                    self.camera.AutoExposureTimeAbsUpperLimit.GetMax())
                attr_prop.format = "%.1f"
                attr_prop.unit = "us"
                attr.set_default_properties(attr_prop)
                attr.set_memorized()
                attr.set_memorized_init(True)
                attr.set_change_event(True, False)
                self.add_attribute(attr, self.read_AutoExposureUpperLimit,
                                   self.write_AutoExposureUpperLimit,
                                   self.IsCameraOnline)

            # Create image attributes
            # NOTE: also the full image is created as a dynamic attribute because creating it as a static attribute hang the
            # image callback on push_change_event call
            attr = PT.ImageAttr("Image", PT.DevUShort, PT.AttrWriteType.READ,
                                2048, 2048)
            attr.set_change_event(True, False)
            self.add_attribute(attr, self.read_image)

            # Create one image for each defined ROIs
            for r in self.rois:
                m = re.match("(\d+):(\d+):(\d+):(\d+)", r)
                if m is not None:
                    try:
                        x = int(m.groups()[0])
                        y = int(m.groups()[1])
                        w = int(m.groups()[2])
                        h = int(m.groups()[3])

                        attr_name = "Image_{0:02d}".format(len(self.rois_img))
                        self.debug_stream(
                            "Adding attribute for roi [X: {0:d}, Y: {1:d}, W: {2:d}, H: {3:d}], named '{4}'"
                            .format(x, y, w, h, attr_name))

                        attr = PT.ImageAttr(attr_name, PT.DevUShort,
                                            PT.AttrWriteType.READ, 2048, 2048)
                        attr.set_change_event(True, False)
                        self.add_attribute(attr, self.read_roi_image)
                        self.rois_img.append({
                            'x': x,
                            'y': y,
                            'w': w,
                            'h': h,
                            'name': attr_name,
                            'image': None
                        })
                    except PT.DevFailed as e:
                        self.error_stream(
                            "Failed to create attribute. Error: {0!s}".format(
                                e.args[0]))
                    except Exception as e:
                        self.error_stream(
                            "Failed to create attribute. Error: {0!s}".format(
                                e))

            # Initialization done, we can start grabbing
            self.start_grabbing()