# Edge - Gateway Timer Script for Device Heartbeat

**URL:** <https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [February 20, 2024, 7:29pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043 "2024-02-20T19:29:52Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![pridesleap](https://avatars.discourse-cdn.com/v4/letter/p/f4b2a3/32.png) [@pridesleap](https://forum.inductiveautomation.com/u/pridesleap)\
**Post date:** [February 20, 2024, 7:29pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/1 "2024-02-20T19:29:53Z")

</div>

Hello,

I have a modbus gateway device that is looking for a heartbeat bit. The intention of the manufacturer of the gateway is for the SCADA to be setting a heartbeat bit to "1" and then the modbus gateway will reset the value to "0" about one second after it sees the bit go high. SCADA is supposed to monitor the value of the register and check to see if the bit goes low. If it doesn't, then SCADA is supposed to assume communication with the gateway is lost.

I attempted to implement the solution suggested here:

> [@Best way to turn boolean tag value high every 5 seconds?](https://forum.inductiveautomation.com/t/best-way-to-turn-boolean-tag-value-high-every-5-seconds/50123/4):
>
> Handshake issues asside, i’m not sure this is the most efficient way but in your place i would do the following: Create a Timer Gateway Event, configure it with a delay of 5000(ms) with fixed delay and shared threading. Use the following script: #Read the tag value myTag = system.tag.read('TagAddressHere').value if myTag == False: #Write only if the Tag is False. #If your tag is True for too long, the alarm should detect it. system.tag.write('TagAddressHere',True) Then, on your hea…

I created an OPC tag pointing to the modbus register I needed to write to:

 ![Capture](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/c/bc32901066b9d26ed4a97e0155156135a66ab282.jpeg)

I then created the following script on the Gateway:

```auto
#Tag to be read
Tag1 = '[edge]000_SCADA_HEARTBEAT'

#Read the tag value
Tag1Value = system.tag.readBlocking(Tag1)

#Write only if the Tag is False
if Tag1Value == False:
	system.tag.writeBlocking(Tag1, True)

```

I then set the following paramters for the script:

![Capture](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/c/5cf925b290c53777004674d4725875b50df33314.jpeg)

I can not get the script to write to the OPC tag as I intended. I also tried but failed to get it to write to a memory tag just as a test. The funny thing is if I manualy set the OPC bit to a "1", the modbus device sees the bit go high and resets it after one second. But then something will set the bit high again just once more and then nothing happens after that. I assume it's the script doing it but if it is then it stops after just one cycle.

Any suggestions would be appreciated.

---

<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:** [February 20, 2024, 7:33pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/2 "2024-02-20T19:33:21Z")

</div>

`.readBlocking()` doesn't return the simple value of a tag. It returns a **list** of `QualifiedValue` objects. Take a closer look at the examples in the docs:

> **[system.tag.readBlocking | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-tag/system-tag-readBlocking#keywords)**
>
> Reads the value of the tags at the given paths.

---

<div class="post-metadata">

**Author:** ![leonardo.godoi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/leonardo.godoi/32/27178_2.png) [@leonardo.godoi](https://forum.inductiveautomation.com/u/leonardo.godoi)\
**Post date:** [February 20, 2024, 8:20pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/3 "2024-02-20T20:20:03Z")

</div>

I've edited my post from 2021 since system.tag.write()/.read() aren't the correct way to read/write tags via scripting. Also added **more** comments to maybe make that clearer.  
What you''ll need is basically:

```auto
#Tag to be read
Tag1 = '[edge]000_SCADA_HEARTBEAT'

#Read the tag value
Tag1Value = system.tag.readBlocking([Tag1])[0].value

#Write only if the Tag is False
if Tag1Value == False:
	system.tag.writeBlocking([Tag1], [True])

```

---

<div class="post-metadata">

**Author:** ![pridesleap](https://avatars.discourse-cdn.com/v4/letter/p/f4b2a3/32.png) [@pridesleap](https://forum.inductiveautomation.com/u/pridesleap)\
**Post date:** [February 20, 2024, 8:46pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/4 "2024-02-20T20:46:15Z")

</div>

I was aware that there were multiple objects in a qualifiedValue and that what I wanted was the .value object. I even tried a version of script that tried to extract the .value object. After your suggestion, I went back and re-read that section again and copied/modified one of the examples in the script editor. I wound up with this:

```auto
#Tag to be read
Tag1 = '[edge]000_SCADA_HEARTBEAT'

#Read the tag value
qualifiedValues = system.tag.readBlocking(path)
value = qualifiedValues[0]

#Write only if the Tag is False
if value.value == False:
	system.tag.writeBlocking(Tag1, True)

```

This works, but is a bit messy and needs optimization. I now see that my previous attempt to extract the .value object failed because of how I formatted the script. I am still learning the basics apparently. Starting with the example in the manual squared me away.

Thank you for your help!

---

<div class="post-metadata">

**Author:** ![pridesleap](https://avatars.discourse-cdn.com/v4/letter/p/f4b2a3/32.png) [@pridesleap](https://forum.inductiveautomation.com/u/pridesleap)\
**Post date:** [February 20, 2024, 8:51pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/5 "2024-02-20T20:51:56Z")

</div>

I had come up with this before your response:

```auto
#Tag to be read
Tag1 = '[edge]000_SCADA_HEARTBEAT'

#Read the tag value
qualifiedValues = system.tag.readBlocking(path)
value = qualifiedValues[0]

#Write only if the Tag is False
if value.value == False:
     system.tag.writeBlocking(Tag1, True)

```

However, your version is more efficient.

Thank you for the assistance!

---

<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:** [February 20, 2024, 9:01pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/6 "2024-02-20T21:01:01Z")

</div>

Now that you have it working, consider optimizing by not using comparisons with booleans. Just

```auto
if not value.value:

```

instead of:

```auto
if value.value == False:

```

---

<div class="post-metadata">

**Author:** ![pridesleap](https://avatars.discourse-cdn.com/v4/letter/p/f4b2a3/32.png) [@pridesleap](https://forum.inductiveautomation.com/u/pridesleap)\
**Post date:** [February 20, 2024, 9:12pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/7 "2024-02-20T21:12:10Z")

</div>

> [@pturmel](#):
>
> Now that you have it working

It's sort of working. I tested it in the script editor and was able to see the heartbeat bit go high then low again. So I thought it was in the clear and copied it into the gateway script.

However, I'm not seing the heartbeat tag change state.

Here is the script I am currently running in the Gateway:

```auto

#Tag to be read
Tag1 = '[edge]000_SCADA_HEARTBEAT'

#Read the tag value
Tag1Value = system.tag.readBlocking([Tag1])[0].value

#Write only if the Tag is False
if Tag1Value == False:
	system.tag.writeBlocking([Tag1], [True])

```

I can also see the script is running in the gateway:

 ![Capture](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/f/0f1fb3a0fd400ff74c767b3a3be5f630988c596e.jpeg)

I'm running the current version of Edge. I beleive I'm supposed to be able to run Gateway scripts now. Is there something additional that I need to enable to do so?

I like your optimization sugestion by the way.

UPDATE:

It suddenly started working on it's own.... it's now toggling.

---

<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:** [February 20, 2024, 9:19pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/8 "2024-02-20T21:19:59Z")

</div>

It is a bad practice to write PLC tags from two directions. Consider using two separate tags, integers perhaps. Have the PLC write its current time of day seconds to one, and have Ignition regularly write its own time of day seconds to the other. Then each device can tell if the other is alive, with no race conditions.

---

<div class="post-metadata">

**Author:** ![pridesleap](https://avatars.discourse-cdn.com/v4/letter/p/f4b2a3/32.png) [@pridesleap](https://forum.inductiveautomation.com/u/pridesleap)\
**Post date:** [February 20, 2024, 9:39pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/9 "2024-02-20T21:39:51Z")

</div>

> [@pturmel](#):
>
> It is a bad practice to write PLC tags from two directions.

I agree, but I don't think I really have a choice with this thing unfortunately. The modbus device is actualy a protocal converter and I don't have any ability to modify it's addresses. 🙁

---

<div class="post-metadata">

**Author:** ![Jyoti\_Kumar](https://avatars.discourse-cdn.com/v4/letter/j/848f3c/32.png) [@Jyoti\_Kumar](https://forum.inductiveautomation.com/u/Jyoti_Kumar)\
**Post date:** [February 27, 2024, 9:59pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/10 "2024-02-27T21:59:11Z")

</div>

How we can add A time date stamp that we can display on the screen every time heartbeat is received.

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [February 27, 2024, 10:14pm UTC](https://forum.inductiveautomation.com/t/edge-gateway-timer-script-for-device-heartbeat/86043/11 "2024-02-27T22:14:28Z")

</div>

Bind a label to the timestamp member of the received heartbeat value tag
