Edge - Gateway Timer Script for Device Heartbeat

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:

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

I then created the following script on the Gateway:

#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

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.

.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:

2 Likes

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:

#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])
1 Like

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:

#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!

I had come up with this before your response:

#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!

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

if not value.value:

instead of:

if value.value == False:

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:


#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:

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.

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.

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. :slightly_frowning_face:

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

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

1 Like