def set_tags(self):
        typenames = {
            "BOOL":    (parser.BOOL,    0,   lambda v: bool(v)),
            "INT":     (parser.INT,     0,   lambda v: int(v)),
            "DINT":    (parser.DINT,    0,   lambda v: long(v)),
            "SINT":    (parser.SINT,    0,   lambda v: int(v)),
            "REAL":    (parser.REAL,    0.0, lambda v: float(v)),
            "SSTRING": (parser.SSTRING, '',  lambda v: str(v)),
            "STRING":  (parser.STRING,  '',  lambda v: str(v)),
        }

        for t in self.config.dtags:
            tag_name = t.name
            tag_type = t.type
            tag_size = t.size

            assert tag_type in typenames, "Invalid tag type; must be one of %r" % list(typenames)
            tag_class, tag_default, f = typenames[tag_type]
            tag_value = f(t.value)

            tag_address = t.addr
            logger.debug("tag address: %s", tag_address)

            path, attribute = None, None
            if tag_address:
                # Resolve the @cls/ins/att, and optionally [elm] or /elm
                segments, elm, cnt = device.parse_path_elements('@' + tag_address)
                assert not cnt or cnt == 1, \
                    "A Tag may be specified to indicate a single element: %s" % (tag_address)
                path = {'segment': segments}
                cls, ins, att = device.resolve(path, attribute=True)
                assert ins > 0, "Cannot specify the Class' instance for a tag's address"
                elm = device.resolve_element(path)
                # Look thru defined tags for one assigned to same cls/ins/att (maybe different elm);
                # must be same type/size.
                for tn, te in dict.items(self.tags):
                    if not te['path']:
                        continue  # Ignore tags w/o pre-defined path...
                    if device.resolve(te['path'], attribute=True) == (cls, ins, att):
                        assert te.attribute.parser.__class__ is tag_class and len(te.attribute) == tag_size, \
                            "Incompatible Attribute types for tags %r and %r" % (tn, tag_name)
                        attribute = te.attribute
                        break

            if not attribute:
                # No Attribute found
                attribute = device.Attribute(tag_name, tag_class,
                                             default = (tag_value if tag_size == 1 else [tag_value] * tag_size))


            # Ready to create the tag and its Attribute (and error code to return, if any).  If tag_size
            # is 1, it will be a scalar Attribute.  Since the tag_name may contain '.', we don't want
            # the normal dotdict.__setitem__ resolution to parse it; use plain dict.__setitem__.
            logger.debug("Creating tag: %-14s%-10s %10s[%4d]", tag_name, '@' + tag_address if tag_address else '',
                       attribute.parser.__class__.__name__, len(attribute))
            tag_entry = cpppo.dotdict()
            tag_entry.attribute = attribute  # The Attribute (may be shared by multiple tags)
            tag_entry.path = path  # Desired Attribute path (may include element), or None
            tag_entry.error = 0x00
            dict.__setitem__(self.tags, tag_name, tag_entry)
Example #2
0
    def set_tags(self):
        typenames = {
            "BOOL":    (parser.BOOL,    0,   lambda v: bool(v)),
            "INT":     (parser.INT,     0,   lambda v: int(v)),
            "DINT":    (parser.DINT,    0,   lambda v: int(v)),
            "SINT":    (parser.SINT,    0,   lambda v: int(v)),
            "REAL":    (parser.REAL,    0.0, lambda v: float(v)),
            "SSTRING": (parser.SSTRING, '',  lambda v: str(v)),
            "STRING":  (parser.STRING,  '',  lambda v: str(v)),
        }

        for t in self.config.dtags:
            tag_name = t.name
            tag_type = t.type
            tag_size = t.size

            assert tag_type in typenames, "Invalid tag type; must be one of %r" % list(typenames)
            tag_class, tag_default, f = typenames[tag_type]
            tag_value = f(t.value)

            tag_address = t.addr
            logger.debug("tag address: %s", tag_address)

            path, attribute = None, None
            if tag_address:
                # Resolve the @cls/ins/att, and optionally [elm] or /elm
                segments, elm, cnt = device.parse_path_elements('@' + tag_address)
                assert not cnt or cnt == 1, \
                    "A Tag may be specified to indicate a single element: %s" % (tag_address)
                path = {'segment': segments}
                cls, ins, att = device.resolve(path, attribute=True)
                assert ins > 0, "Cannot specify the Class' instance for a tag's address"
                elm = device.resolve_element(path)
                # Look thru defined tags for one assigned to same cls/ins/att (maybe different elm);
                # must be same type/size.
                for tn, te in dict.items(self.tags):
                    if not te['path']:
                        continue  # Ignore tags w/o pre-defined path...
                    if device.resolve(te['path'], attribute=True) == (cls, ins, att):
                        assert te.attribute.parser.__class__ is tag_class and len(te.attribute) == tag_size, \
                            "Incompatible Attribute types for tags %r and %r" % (tn, tag_name)
                        attribute = te.attribute
                        break

            if not attribute:
                # No Attribute found
                attribute = device.Attribute(tag_name, tag_class,
                                             default = (tag_value if tag_size == 1 else [tag_value] * tag_size))

            # Ready to create the tag and its Attribute (and error code to return, if any).  If tag_size
            # is 1, it will be a scalar Attribute.  Since the tag_name may contain '.', we don't want
            # the normal dotdict.__setitem__ resolution to parse it; use plain dict.__setitem__.
            logger.debug("Creating tag: %-14s%-10s %10s[%4d]", tag_name, '@' + tag_address if tag_address else '',
                       attribute.parser.__class__.__name__, len(attribute))
            tag_entry = cpppo.dotdict()
            tag_entry.attribute = attribute  # The Attribute (may be shared by multiple tags)
            tag_entry.path = path  # Desired Attribute path (may include element), or None
            tag_entry.error = 0x00
            dict.__setitem__(self.tags, tag_name, tag_entry)