Live readout of time between style classes

Im looking to have a live readout of the time in seconds between a props style class. Example props.style.classes is 1 then readout on a label, the live accumulated time until props.style.classes is 2 or etc.

I don't understand what you mean. Do you have a binding already on the style.classes? If so, what is it? Are you asking for help with a binding on the classes or on the props.text?

I have a binding on the style class already. It toggles between 2 classes: green and red. When the style class goes from green to red it opens a pop up and tells the operator the have problem. On that pop up I want to have a label that reads out how long that style class has been red. When the style class changes from red to green it closes the pop up.

That seems nuts. Use a proper tag and bind to that, not a binding to a style class.

1 Like

I'm with @Transistor here. Obviously, you already have something that triggers the change of style class, that seems reasonable. Why not just use that same trigger for the label?

Add 2 custom properties to the Label. Bind the first to your trigger, and add a change event to that custom prop. In the change event write the current time into the other custom prop.

For example, if you were to name your custom props, Trigger, and LastTriggerTime then you could have an expression binding on the Label that looked something like this:

if(self.custom.Trigger,secondsBetween(self.custom.LastTriggerTime,now(0)),0)

*Not tested, you may need to through some string conversions in there.

In short, the style classes aren't really intended to do what you're attempting, there are better mechanisms for accomplishing the task.

I understand, I had to ask.
SO, I am using banners on the perspective page. Should I create a script on the root of that banner? Like this on the onFocus event:

def runAction(self, event):
	if self.getChild("root").getChild("411_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '411_breakout_pop')
	if self.getChild("root").getChild("412_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '412_breakout_pop')
	if self.getChild("root").getChild("413_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '413_breakout_pop')
	if self.getChild("root").getChild("414_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '414_breakout_pop')
	if self.getChild("root").getChild("511_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '511_breakout_pop')
	if self.getChild("root").getChild("512_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '512_breakout_pop')
	if self.getChild("root").getChild("513_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '513_breakout_pop')
	if self.getChild("root").getChild("514_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '514_breakout_pop')
	if self.getChild("root").getChild("521_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '521_breakout_pop')
	if self.getChild("root").getChild("522_Label").props.style.classes == 'Stopped':
		system.perspective.openPopup('', '522_breakout_pop')

On these pop ups I will have time displaying

At the very least I would refactor that to this:

def runAction(self,event):
    for i in ('411','412','413','414','511','512','513','514','521','522'):
        if self.getChild('root').getChild('{}_Label'.format(i)).props.style.classes == 'Stopped':
            system.perspective.openPopup('','{}_breakout_pop'.format(i))
            break

I think, you're going to have to explain a little more about what exactly you're trying to accomplish. I don't really understand what the banners have to do with displaying a time (presumably from when an event occurred). That would be done with a binding. If you have multiple labels (as I see you do), then you could store the trigger time in a property on a common container, however, I assume that the triggers are independent of each other so then wouldn't the trigger be unique to the label?

What would the script on the root do?

FYI, if it can be done with an expression, use an expression (as a general rule).

2 Likes

From these labels on the banner:
image

I want a popup to happen and on that popup have a label that displays accumulated time in that error, like this:
image

what code do you use to set the style classes to "Stopped" ?

btw you should probably put those labels in a repeater or something else you'll have so much duplicate code

1 Like

I use this:

if({[default]Phase 1 Extrusion/L51/L51_Spin_Pump_Spd/Pos2}>=12,'Running','Stopped')

Consider moving that comparison to an expression tag, and use a tag change event to capture the timestamp (in a memory tag) when it becomes true. Everything else becomes simple expressions.

2 Likes

So you have a tag for each popup ?
Use that instead to compute the time.
You could use an expression:

secondsBetween({[default]Phase 1 Extrusion/L51/L51_Spin_Pump_Spd/Pos2.timestamp}, now())

I also suggest you take some time to read this:

Can you call a popup using an expression? or did I read that wrong?

You read it wrong.

You asked if you should write a script on the 'root' of the banner, similar to what you had written in the supplied script from an onFocus event. Showing a pop up can be done from an expression, using the runScript() expression function (I guess that isn't really an expression). That is, however, irrelevant to what I was actually meaning.

I assume that the script you were thinking of writing on the 'root' of the banner would be to calculate the elapsed time, when in reality that can easily be done with an expression once you have the time at which the event occurred.

We're all talking past each other here.

You have a fundamental disconnect - everyone's telling you (in different ways) that you need to separate your data from your presentation.
Calculations like "how long has a breakout been detected" should live in a single location, and be calculated on the gateway. For a variety of reasons, the easiest place to do that kind of persistent logic that's available to other parts of Ignition is tags.

Once you have a set of tags calculating and displaying this data, it's much, much easier to set up the presentation - you just bind your various components to the state of these tags (sometimes with minimal logic).

7 Likes

I would like to thank everyone here, seriously. I have seen several different way to achieve what I wanted to do. I cleaned up alot my code thank to you all and learned a new trick for what I wanted to achieve.

This:

if({this.props.style.classes} = 'Breakout',runScript("system.perspective.openPopup('','411_breakout_pop')"),'')

allowed me to have a popup execute when a style class changed, from there I had a script onStartup of that popup that wrote to a timer tag that gives me secondsBetween then and now, for fault time.

I think you're still mixing up where you're storing your data. What happens when a client only starts up after the tag changes to breakout? Then the popup will open but the seconds between will not be correct. This should all be done in tags

4 Likes

understood, thnak you

More generally, DO NOT base logic/calculations/triggers on UI elements like styles. It should be the other way around.

2 Likes