Help with scripting an expression tag in the gateway to write to a plc tag

Hey all-

I am trying to write a script for an expression tag in the gateway, so that if it becomes true, it will write to a PLC tag. This is the script I have written so far, the first line is to prevent the script from running on changes in tag quality:

if previousValue.value != currentValue.value and initialChange == False:

if newValue.value([ProjectName]vSaaS Comm Failure) > 0:
system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[1])
else:
system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[0])

It keeps returning an error that says "no viable alternative at input 'vSaaS'".

Any help is appreciated, thank you

  1. Format your code with the </> button, we can't see your indentation.
  2. What is the tag structure?

your second if statement is incorrect

I would also recommend that you use an intermediary variable and only call writeBlocking once at the end.

if previousValue != currentValue and not initialChange: #qualified values can be compared directly, without using ".value"
    if newValue.value : #any non-zero value will return true
        scada_fail = 1
    else:
        scada_fail = 0
    system.tag.writeBlocking('[~]WWTP/Scada_Fail_Alarm_Interlock'],[scada_fail])

Ah, shoot. It looks like this:

`if previousValue.value != currentValue.value and initialChange == False:

	if newValue.value([ProjectName]vSaaS Comm Failure) > 0:
		system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[1])
	else:
		system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[0])`

How do you mean an intermediary variable?

Also, it is important that the comm failure tag being any value greater than zero is in there, that is the trigger for the script to run

newValue.value([ProjectName]vSaaS Comm Failure) Is the issue. I will assume that [ProjectName]vSaaS Comm Failure is the tag where this property change script exists? Just use newValue.value - if you need to read another tag you'll have to use system.tag.readBlocking(). The script I provided in my previous post is correct if my assumptions are correct.

if newValue.value : is the same as if newValue.value > 0 :
image

Really appreciate the quick responses, thank you.

[ProjectName]vSaaS Comm Failure is the tag I am watching for a tag value change. The tag I am writing this tag value change script for is a separate tag, called vSaaS - Autodialer Failover.

I have written this into the script:

	if previousValue != currentValue and initialChange == False:

		if system.tag.readBlocking([ProjectName]vSaaS Comm Failure) > 0:
			system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[1])
		else
			system.tag.writeBlocking(["[~]WWTP/Scada_Fail_Alarm_Interlock"],[0])

And I am now seeing this as my error:

SyntaxError: mismatched input '        ' expecting EOF (input>, line 1)
>>>
  1. Gateway Tag Change events do not have a currentValue object.
  2. You say you want to write to the tag when it is true, but your script does both, either way you don't need the else section of the script at a minimum, maybe even the entire nested if.
  3. Don't compare boolean values to 0,1 instead use them as booleans.

This should work:

if newValue.value and not initialChange:
    system.tag.writeBlocking(["[" + event.tagPath.parentPath + "]WWTP/Scada_Fail_Alarm_Interlock"],[True])

or if you want to write in both cases:

if not initialChange:
    system.tag.writeBlocking(["[" + event.tagPath.parentPath + "]WWTP/Scada_Fail_Alarm_Interlock"],[newValue])

Gateway Events do not support realtive tag paths so you have to give the fully qualified path

1 Like

Sorry, I missed that the trigger tag and the inspected tag are different.

That would look like this:

if previousValue.value != newValue.value and not initialChange and system.tag.readBlocking(["[ProjectName]vSaaS Comm Failure"])[0].value:
    system.tag.writeBlocking(["[" + event.tagPath.parentPath + "]WWTP/Scada_Fail_Alarm_Interlock"],[True])

I expect you can arrive at the script should you want to write to the tag in both cases.

Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'previousValue' is not defined

How do I define previousValue?

You don't it is provided to the event script as a built-in object.

Where are you writing this script? Is it in a tag change event on a UDT/tag or in the gateway tag change event scripts? That makes a big difference.

1 Like

I've been trying to do both to see which worked first. I didn't realize they were so different.

Initially, I was trying to create an expression tag. The "trigger" tag is a gateway tag, I followed that direction and used a gateway tag change script.

There is no such concept in ignition as a Gateway Specific Tag (as Opposed to say a Client Tag). So I assume that you mean its a normal memory tag.

You should probably just use an expression tag.

Set the Execution Mode to "Event Driven"

Use this expression as the expression:

if({"Path/To/Trigger"},{"Path/To/DrivingTag"},false})

This will only return true if both the trigger and the Driving Tag are true, otherwise it will return false.

1 Like

This, but:

{Path/To/Trigger} && {Path/To/DrivingTag}

No need for a wrapping if.

1 Like

So, to summarize what everyone has said and to make sure everyone understands (and hopefully I'm getting this correct). Your WWTP/Scada_Fail_Alarm_Interlock tag if possible should be an expression tag (unless it needs to write this value to a different PLC in which case you'll need a separate memory expression tag). The expression in that tag should be:

{vSaaS Comm Failure} && {vSaaS - Autodialer Failover}
1 Like

Also, as an aside. You really should avoid the use of spaces and reserved characters in your tag names.

e.g.

vSaaS Comm Failure should be something like vSaaS_Comm_Failure and vSaaS - Autodialer Failover should be something like vSaaS_Autodialer_Failover

4 Likes

My bad, I was just fixing syntax errors on the original script that @Evan_Curry had provided and I didn't think to check the actual variables.

I had assumed that this was on a tag property change script, not a gateway event script.

Many syntax errors and things to clean up here.

  1. Don't compare initialChange to False, just use it as a boolean.
  2. Since vSaaS Comm Failure is the tag you're watching (tag that triggers this valueChanged script), you don't need to read it again, just use currentValue.value. Even still, your system.tag.readBlocking() call is incorrect, you need to provide a list of paths as strings and then you would have to access the value of the first tag read. You're missing the brackets, quotes, and list reference (system.tag.readBlocking(["[ProjectName]vSaaS Comm Failure"])[0].value ).
  3. Again, you don't need to compare the tag value to 0, just use it as a boolean. Anything non-null and non-zero is "True".
  4. You're also missing your colon on your else
  5. @lrose is correct. If you're going to write to the tag either way, just write newValue.value to the tag instead of using the if statement.

So, in the valueChanged() script of an expression tag:

def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	if previousValue != currentValue and not initialChange:
		system.tag.writeBlocking(['[~]WWTP/Scada_Fail_Alarm_Interlock'], [currentValue.value])