As Ryan suggests, don't count in a timer event. The timing is not very precise.
To get retention of prior time, you need at least two timestamps to hold state, updated when the signal changes. A stop timestamp, and an adjusted start timestamp. The start timestamp needs to be adjusted backwards from now()
by the amount accumulated before.
Drop these tags into a test folder to see how to set this up:
{
"tags": [
{
"valueSource": "expr",
"expression": "if(\n\t{[.]RTO_Reset},\n\t0.0,\n\t0.001 * dateDiff(\n\t\t{[.]RTO_StartTS},\n\t\tif(\n\t\t\t{[.]RTO_Signal},\n\t\t\tnow(250),\n\t\t\t{[.]RTO_StopTS}\n\t\t),\n\t\t\u0027ms\u0027\n\t)\n)",
"dataType": "Float8",
"name": "RTO_Accum",
"formatString": "#,##0.000",
"tagType": "AtomicTag"
},
{
"valueSource": "memory",
"eventScripts": [
{
"eventid": "valueChanged",
"script": "\tnowTS \u003d system.date.now()\n\tif currentValue.value:\n\t\t# Signal is true. Write the current timestamp to both state tags.\n\t\tsystem.tag.writeBlocking([\u0027[.]RTO_StartTS\u0027, \u0027[.]RTO_StopTS\u0027], [nowTS, nowTS])\n"
}
],
"dataType": "Boolean",
"name": "RTO_Reset",
"value": false,
"tagType": "AtomicTag"
},
{
"valueSource": "memory",
"eventScripts": [
{
"eventid": "valueChanged",
"script": "\tresetting, startTS, stopTS \u003d [qv.value for qv in system.tag.readBlocking([\u0027[.]RTO_Reset\u0027, \u0027[.]RTO_StartTS\u0027, \u0027[.]RTO_StopTS\u0027])]\n\tif not resetting:\n\t\tnowTS \u003d system.date.now()\n\t\tif currentValue.value:\n\t\t\t# Signal is true. If stopTS is after startTS, the new startTS must\n\t\t\t# be moved back before nowTS by their delta.\n\t\t\tif stopTS.after(startTS):\n\t\t\t\tpriorMS \u003d stopTS.time - startTS.time\n\t\t\t\tsystem.tag.writeBlocking([\u0027[.]RTO_StartTS\u0027], [system.date.addMillis(nowTS, -priorMS)])\n\t\t\telse:\n\t\t\t\tsystem.tag.writeBlocking([\u0027[.]RTO_StartTS\u0027], [nowTS])\n\t\telse:\n\t\t\t# Signal is false. Just write the current timestamp to stopTS\n\t\t\tsystem.tag.writeBlocking([\u0027[.]RTO_StopTS\u0027], [nowTS])\n"
}
],
"dataType": "Boolean",
"name": "RTO_Signal",
"value": false,
"tagType": "AtomicTag"
},
{
"valueSource": "memory",
"dataType": "DateTime",
"name": "RTO_StartTS",
"formatString": "yyyy-MM-dd h:mm:ss aa",
"value": 1740157975856,
"tagType": "AtomicTag"
},
{
"valueSource": "memory",
"dataType": "DateTime",
"name": "RTO_StopTS",
"formatString": "yyyy-MM-dd h:mm:ss aa",
"value": 1740157975856,
"tagType": "AtomicTag"
}
]
}
In the accumulator expression tag, adjust the now(250)
to the update pace you want.
Edit: If you do many of these, move the two scripts to functions in the Gateway Scripting Project's library, so the tag events can be one-liners.