Curiosity? Gateway Timer Event Scripts

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.

1 Like