# Counter like tag with cumulated value

**URL:** <https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051>\
**Category:** Ignition\
**Created:** [October 11, 2022, 6:40am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051 "2022-10-11T06:40:55Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dharani\_T](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dharani\_T](https://forum.inductiveautomation.com/u/Dharani_T)\
**Post date:** [October 11, 2022, 6:40am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/1 "2022-10-11T06:40:55Z")

</div>

Hi,

I am currently recording the live status of the machine and displaying the status of the machine as below,  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/e/de0305178c83714fae2add36e460ad64c62597c6.png)  
Whenever the machine is in Stopped state for more than 10 mins, I would like to start a counter and display as 'hh:mm:ss' in the next column ( for every shift as shift loss)  
And when the machine goes from Stopped to any other state, the duration in the loss column must be halted and whenever the machine goes back to stopped state, the cumulated time should be displayed.

Moreover whenever the shift changes, this time should reset and if the machine is already in stopped state, counter should start from one,

Currently i am following the below approach,

Tags used:

1. State tag
2. Statechange time elapsed (to display the duration )
3. Global Shift change tag

Calculation:

1. LossFlag (Expression Tag)

```auto
if ({[.]../StateChange}="Stopped",true,false)

```

2.ShiftLossCumulative Tag:

```auto
if ( ({[.]ShiftLoss} = true ) && ({[.]../StateChangeTimeElapsed}>600), {[.]ShiftLossCumulative}+1, 0)

```

Tag change event script:

```auto
vShift = system.tag.readBlocking("[~]BASE/Global/ShiftChange")[0].value
	
	if vShift == True:
		currentValue.value = 0
	
	elif currentValue.value == 0 and previousValue !=0:	
		currentValue.value =currentValue.value + previousValue.value

```

3.ShiftLossMins:

```auto
if(
            isNull({[.]ShiftLossCumulative}),
            "00:00:00",
    if ({[.]../StateChange}="Stopped" && {[.]../StateChangeTimeElapsed} > 600 && {[default]BASE/Global/ShiftChange}=FALSE,
                        
                                stringFormat(
                                            "%02d:%02d:%02d",
                                            toInt(floor(({[.]ShiftLossCumulative}+600)/3600)),
                                            toInt(floor(({[.]ShiftLossCumulative}+600)%3600/60)),
                                            toInt(floor(({[.]ShiftLossCumulative}+600)%60))),
            
                                
                    stringFormat(
                                    "%02d:%02d:%02d",
                                    toInt(floor({[.]ShiftLossCumulative}/3600)),
                                    toInt(floor({[.]ShiftLossCumulative}%3600/60)),
                                    toInt(floor({[.]ShiftLossCumulative}%60))
                    )
                    
            )
    )

```

This 'ShiftLossMins' Tag will be displayed in the screen.

Somehow, this is getting failed and occuring issues like, when the machine is in stopped state it is working fine.  
When it goes to other state, ShiftLossMins getting reset

Any suggestions to overcome this issue?

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [October 11, 2022, 7:45am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/2 "2022-10-11T07:45:40Z")

</div>

Are you attempting this from a client level tag change event script?  
Is it possible to do the downtime calculations from the machine PLCs?

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [October 11, 2022, 7:48am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/3 "2022-10-11T07:48:42Z")

</div>

Let's start with a few things that should make things simpler, and which might just point to errors in the logic:

- You don't need to do `if (boolean, true, false)`. `boolean` is enough:  
=\> LossFlag: `{[.]../StateChange} = "Stopped"`
- The same goes for `if ( ({[.]ShiftLoss} = true) ...)`. If `something = true` is true, it means that `something` is... already true.
- `if vShift == True`. Same thing, `if vShift` is enough.  
You set `currentValue.value` to 0 here, but you're not using it afterward, so the whole if statement does nothing except running a starting clause for the `else` that follows. If you want to update the tag, you need to use `system.tag.writeBlocking`.
- In the `else` condition, what is `previousValue != 0` supposed to do ? Did you want to compare it to `None` instead to make sure `previousValue` does exist, or did you mean to check its value ?  
If you want to make sure it exists, use `previousValue is not None`. If you want to check for its value, then you don't need to do it at all. The only thing `previousValue.value` is used for is an addition. If its value is 0, then adding it to something will give you the same result.
- In `ShiftLossMins` expression, you're using `{[.]..{StateChange}="Stopped"}`. You already did that comparison for `LossFlag`. Use this instead.  
I also suggest you don't format it there. Just return the time (number of seconds, minutes, whatever is the most appropriate, or even use a `datetime` tag), and format it where you display it:

```auto
if(isNull({[.]ShiftLossCumulative}),
	0,
	if ({[.]LossFlag} && {[.]../StateChangeTimeElapsed} > 600 && {[default]BASE/Global/ShiftChange} = false,
		{[.]ShiftLossCumulative}+600,
		{[.]ShiftLossCumulative}
	)
)

```

Which could be 'simplified' further but let's not go there yet.

For now, I'd take a look at the tag change script, and make sure the logic there is sound.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [October 11, 2022, 8:05am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/4 "2022-10-11T08:05:31Z")

</div>

> [@pascal.fragnoud](#):
>
> You set `currentValue.value` to 0 here, but you're not using it afterward, so the whole if statement does nothing except running a starting clause for the `else` that follows. If you want to update the tag, you need to use `system.tag.writeBlocking`.

Actually, I'm not sure about that. I don't use tag change scripts on tags, only gateway events... So maybe `currentValue` here actually updates the tag.

That being said, is that script on the tag `ShiftLossCumulative` ?  
To me, the trigger seems to be the shift change instead, so I'd put it there.

---

<div class="post-metadata">

**Author:** ![Dharani\_T](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dharani\_T](https://forum.inductiveautomation.com/u/Dharani_T)\
**Post date:** [October 11, 2022, 9:09am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/5 "2022-10-11T09:09:32Z")

</div>

Hi  
I am getting Error\_Expression\_Val in ShiftLossCumulative,ShiftlossInMins tags

---

<div class="post-metadata">

**Author:** ![Dharani\_T](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dharani\_T](https://forum.inductiveautomation.com/u/Dharani_T)\
**Post date:** [October 11, 2022, 9:11am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/6 "2022-10-11T09:11:00Z")

</div>

Attempting from tag change event script

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [October 11, 2022, 9:15am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/7 "2022-10-11T09:15:51Z")

</div>

Without seeing them, there's not much I can tell you...

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [October 11, 2022, 10:29am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/8 "2022-10-11T10:29:47Z")

</div>

So, I'm having a bit of fun trying to make this work with expression tags only, but it's a bit trickier that I thought.  
This part particularly:

> [@Dharani\_T](#):
>
> if the machine is already in stopped state, counter should start from one

Can you tell me more about the shift change tag ? Does it go to true for a few seconds then go back to false ? Does it stay on longer ? When do we start counting again, just as it becomes true, or when it goes back to false ?

For now, I have this:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/e/8eb4eed379dbcc5f15127607d16878d00c360844.png)

- `lossFlag` is just a memory boolean tag, that I toggle on and off manually.  
For you, it should be an expression tag using whatever machine state tag you want to evaluate.

- `currentStateTimer` counts the time between now and `lossFlag`'s timestamp

```auto
secondsBetween({[.]lossFlag.timestamp}, now()) * toInt({[.]lossFlag})

```

- `previousLoss` stores the time that has been lost so far, without the current timer

```auto
if (!{[.]lossFlag},
	{[.]shiftLoss},
	coalesce({[.]previousLoss}, 0)
) * toInt(!{[.]../shiftChange})

```

- `shiftLoss` is the total of `previousLoss` and `currentTimer`

```auto
coalesce({[.]previousLoss}, 0) + {[.]currentStateTimer}

```

When `lossFlag` goes to true, `currentTimer` starts counting, which also increment `shiftLoss`.  
When `lossFlag` goes back to false, `currentTimer` goes to 0, `shiftLoss` stops incrementing, and `previousLoss` takes the value of `shiftLoss`.

Now, the reset part will depend on the information you can give me about `shiftChange`

Note the `coalesce` calls in the expressions: they're here to ensure an initial value when creating the folders (I just copy/pasted the folder a few times to test it).  
The one in `previousLoss` expression is not strictly necessary, it works fine without it, but it prevents an expression eval error when initially creating the folder (the tag tries to get its own value, which doesn't work as it doesn't have one yet).

---

<div class="post-metadata">

**Author:** ![Dharani\_T](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dharani\_T](https://forum.inductiveautomation.com/u/Dharani_T)\
**Post date:** [October 11, 2022, 11:31am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/9 "2022-10-11T11:31:57Z")

</div>

I have defined a custom tag called Shift and Whenever Shift changes it goes to True  
And after few secs it goes false  
Shift change is a tag that refers this one

---

<div class="post-metadata">

**Author:** ![Dharani\_T](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dharani\_T](https://forum.inductiveautomation.com/u/Dharani_T)\
**Post date:** [October 11, 2022, 11:38am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/10 "2022-10-11T11:38:01Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/8/e8f59c4b05ee239dd1e0802d88e6f26b089d5f73.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/d/5d232928cc7018272434c9a18b0cafccf6b27f4f.png)  
For me, Previous Loss is not getting stored

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [October 11, 2022, 11:46am UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/11 "2022-10-11T11:46:22Z")

</div>

Then using this expression:  
`{[.]machineState} = "stopped" && !{[.]../shiftChange}`  
for `lossFlag` will make it false when `shiftChange` becomes true, then go back to its previous state when `shiftChange` goes back to false, with every counter reseted to 0.

Here's the json of my Test folder, you can copy and paste it in your tag browser

> **click for json**
>
> ```json
> {
> "name": "Test",
> "tagType": "Folder",
> "tags": [
> {
> "name": "Foo",
> "tagType": "Folder",
> "tags": [
> {
> "valueSource": "expr",
> "expression": "{[.]machineState} \u003d \"stopped\" \u0026\u0026 !{[.]../shiftChange}",
> "dataType": "Boolean",
> "name": "lossFlag",
> "value": false,
> "tagType": "AtomicTag"
> },
> {
> "valueSource": "expr",
> "expression": "secondsBetween({[.]lossFlag.timestamp}, now()) * toInt({[.]lossFlag})",
> "name": "currentStateTimer",
> "tagType": "AtomicTag"
> },
> {
> "valueSource": "expr",
> "expression": "if (!{[.]lossFlag},\r\n\t{[.]shiftLoss},\r\n\tcoalesce({[.]previousLoss}, 0)\r\n) * toInt(!{[.]../shiftChange})",
> "name": "previousLoss",
> "value": 0,
> "tagType": "AtomicTag"
> },
> {
> "valueSource": "memory",
> "dataType": "String",
> "name": "machineState",
> "value": "active",
> "tagType": "AtomicTag"
> },
> {
> "valueSource": "expr",
> "expression": "coalesce({[.]previousLoss}, 0) + {[.]currentStateTimer}",
> "name": "shiftLoss",
> "value": 227,
> "tagType": "AtomicTag"
> }
> ]
> },
> {
> "valueSource": "memory",
> "dataType": "Boolean",
> "name": "shiftChange",
> "value": false,
> "tagType": "AtomicTag"
> }
> ]
> }
> 
> ```

Note that it's probably not the best/simplest/easiest way of doing this. I just wanted to try and see if I could do it with expression tags only.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [October 11, 2022, 12:43pm UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/12 "2022-10-11T12:43:17Z")

</div>

The reliable way to do this is to record state changes in an event table. Then use `LEAD` or `LAG` functions in the DB to get intervals per state, clipping to the start of shift. Sum those intervals while grouping by state. With an index on t\_stamp, your DB will calculate this blisteringly fast.

```auto
Select state, sum(event_duration) as duration
From (
  Select state, nextTS - clipped as event_duration
  From (
    Select state
      , case t_stamp < :shift_start_ts then :shift_start_ts else t_stamp end as clipped
      , coalesce(lead(t_stamp) over (Order by t_stamp), current_timestamp) as nextTS
    From state_events
    Where t_stamp >= (Select max(t_stamp) Where t_stamp < :shift_start_ts)
  ) intervals
) durations

```

Display the final duration from the row that matches the current state.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [October 11, 2022, 12:57pm UTC](https://forum.inductiveautomation.com/t/counter-like-tag-with-cumulated-value/65051/13 "2022-10-11T12:57:51Z")

</div>

You also have the option to use tag history
