Timeseries Data Invalid Key Issue

Morning! I have the following data in my time-series chart. The chart works. It seems to plot without issues; however, all my keys throw an invalid key error.

image

I'm assuming this is due to the brackets, but this should be valid python

image

Keys in Perspective objects must be valid for JSON. It isn't enough to be valid python, because Perspective doesn't keep python/jython values in their original form. No brackets or slashes or other punctuation in keys. If you couldn't use it as a jython variable name, you can't use it as a key in a Perspective object. (No leading digits, either.)

Keep in mind that things that "accidentally" work with errors present may not work with future upgrades.

Thanks Phil. I'm looking at the Columns property under trends and don't see a way I can specify a different name. I'd like the xtrace to show the tag path. This obviously works with a dataset but I can't use that in this instance. Do I have any other options to configure the column names that are displayed to the user?

Make up series names (or munge the name into something valid).

Reconsider using dataset format for your series and supply the columns property in your trends.

I'm creating a 'live' trend using tag bindings, pushing their values to the series data each second, with a rolling 5-minute window. I figured this method would be more efficient than the immutable dataset.

In my experience 90% of a tag path is useless to an end user.

I would use just the tag name and replce any spaces with an _ character.

1 Like

Maybe. If Ignition isn't just resending the whole column as you add values.

Have you tried my recorder() function from my Integration Toolkit?

Unfortunately, we have many tags with the same name under different device folders/paths.

I have not! What is this Integration Toolkit you speak of? :slight_smile: Can you link me, please?

-- Update --

Found it! Thanks I will check this out.

Hint: You'll probably want to feed the recorder() with an expression involving tags()...

Just going over this module. Is the idea that the expressions are more performant than scripting?

For what it's worth, we have a similar situation, so I use something like this:

from com.inductiveautomation.ignition.common.tags.paths.parser import TagPathParser

def sanitizePenNames(pens,path):
    pathParts = TagPathParser.chopPath(path)

    def generatePenName(parts, cursor = 0):
        cursor -= 1
        #sanitize
        parts = [part.replace(' ','_') for part in parts]
        penName = '_'.join(parts[cursor:])

       if penName in pens:
            return generatePenName(parts,cursor)
        return penName
    return generatePenName(pathParts)

This converts the path into a list of its parts(excluding the provider) and then recursively walk from the tail of the list until a unique name is found. So, for example, if your pens was ['tag_name'] and you wanted to add a pen for '[provider]path/to/tag name' then the function would return 'to_tag_name'.

Less of an idea and more of a fact.

Phil's module is awesome.

2 Likes