# Tough Scripting Problem

**URL:** <https://forum.inductiveautomation.com/t/tough-scripting-problem/89526>\
**Category:** Ignition\
**Tags:** perspective, ignition81\
**Created:** [April 26, 2024, 2:06pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526 "2024-04-26T14:06:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ryan\_Craig](https://avatars.discourse-cdn.com/v4/letter/r/45deac/32.png) [@Ryan\_Craig](https://forum.inductiveautomation.com/u/Ryan_Craig)\
**Post date:** [April 26, 2024, 2:06pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/1 "2024-04-26T14:06:49Z")

</div>

I am writing a value change script on a tag that will show 2 results to a test we are running. (The machine works like this and I can't change the PLC code to fix it) The code has the first test results pop up, then the results go to 0, then the second test results pop up, and then it goes to 0 again. I am trying to write the 2 different results to 2 different tags. I have a working version of the script:

```python
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	#Get Variable tag paths for writing values
	TagPath1 = '[default]{ENumber}/{ENumber}/Test1OcclusionFinal'
	Var1 = system.tag.readBlocking(TagPath1)
	
	TagPath2 = '[default]{ENumber}/{ENumber}/Test2BurstFinal'
	Var2 = system.tag.readBlocking(TagPath2)
	
	programTagPath = '[default]{ENumber}/{ENumber}/ProgramNum/Current_Program_Number'
	Prgrm = system.tag.readBlocking(programTagPath)
	
	# Flip boolean
	system.tag.writeBlocking('[default]{ENumber}/{ENumber}/Results/Get_Results_Trigger', 0)
	
	#Program Numbers for Linked
	link = [3]
	
	#Program Numbers for Occlusion
	occ = [7 , 4]
	
	#Program Numbers for Burst
	burst = [2 , 5 , 6]
	
	
	#Write based off Program Number
	if Prgrm[0].value in link:
	
	# Write variable value to another tag for linked test (Test 3)
		if currentValue.value != 0 and currentValue.value < 2 and currentValue.value != Var2:
			system.tag.writeBlocking(['[default]{ENumber}/{ENumber}/Test1OcclusionFinal'], [currentValue.value])
		
		elif currentValue.value != 0 and currentValue.value != Var1:
			system.tag.writeBlocking(['[default]{ENumber}/{ENumber}/Test2BurstFinal'], [currentValue.value])
		
	elif Prgrm[0].value in occ and currentValue.value != 0:
		system.tag.writeBlocking(['[default]{ENumber}/{ENumber}/Test1OcclusionFinal'], [currentValue.value])
		
	elif Prgrm[0].value in burst and currentValue.value != 0:
		system.tag.writeBlocking(['[default]{ENumber}/{ENumber}/Test2BurstFinal'], [currentValue.value])
		
		

```

but one of the only reasons it works is because MOST of the time the first test results will be a value below 2. I am afraid that this script will not work correctly if there is an outlier for the first test and it ends up being above 2. I have also tried to work out a script that looks like this:

```python
pro = 2
tags = ['[default]E398/E398/Test1OcclusionFinal']
x = system.tag.readBlocking(tags)
results = 6

if pro == 2:
	system.tag.writeBlocking(['[default]E398/E398/Test1OcclusionFinal'], [2])
	tags2 = ['[default]E398/E398/Test1OcclusionFinal']
	y = system.tag.readBlocking(tags2)
	print y
	print x
	if x != y and results != 0:
		system.tag.writeBlocking(['[default]E398/E398/Test1OcclusionFinal'], results)

```

that would read the first results before and after I write to the first tag, to see if it should write to the second tag. Unfortunatley I don't think this will work either because this script will be executed every time the value changes..

Is there any way to work around this?

---

<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:** [April 26, 2024, 2:09pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/2 "2024-04-26T14:09:56Z")

</div>

Does the sequence have specific timing? If so, I'd use the first transition away from zero to initialize a state machine, and capture following values based on time.

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [April 26, 2024, 2:12pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/3 "2024-04-26T14:12:27Z")

</div>

@pturmel beat me to it, but what's the timing of these tag changes. I'm thinking you could determine when a new test is started based on delays. If there's like 5 seconds on each value, but a minute or more between tests, you could track how long since the last tag change, and if it's more than a certain time frame, know that a new test started.

Also, on your first script, you're doing a lot of individual readBlocking calls. I'd put those tags in an array/list and do a single call to clean it up, then split out the individual values.

---

<div class="post-metadata">

**Author:** ![Ryan\_Craig](https://avatars.discourse-cdn.com/v4/letter/r/45deac/32.png) [@Ryan\_Craig](https://forum.inductiveautomation.com/u/Ryan_Craig)\
**Post date:** [April 26, 2024, 2:15pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/4 "2024-04-26T14:15:07Z")

</div>

It does! It use a sleep(3) function (unfortunately), so I know that it will be 3 seconds before the second result. So how would I do this? I would think that I would do something like this?:

```python
if value != 0:
    system.tag.write(firstTagResults, results)
   sleep(3)
   system.tag.write(secondTagResults, results)

```

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [April 26, 2024, 2:19pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/5 "2024-04-26T14:19:47Z")

</div>

If these values are all coming in on the same tag, you'll only use data change events and you'll compare the currentValue.timestamp and the previousValue.timestamp to see how long it's been since the last value change. You'll want to give it some wiggle room, but maybe say if it's less than 10 seconds....it's the second test result, but if more, it's probably the first test result (assuming these tests are spaced out more than 1-15 seconds).

Actually, you'll have to account for 0, in this, but the results should be the same.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [April 26, 2024, 3:05pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/6 "2024-04-26T15:05:49Z")

</div>

Can the test be interrupted and never give a second value ?

If not, then you can forget the delays and just use the order in which values come in.  
I'd probably add another tag that would act like a flag indicating which value you're expecting next, and route the results to one of two tags depending on that.

something like

```python
if system.tag.readBlocking(["flag"])[0].value:
    result_tag = "value1"
else:
    result_tag = "value2"
system.tag.writeBlocking([result_tag], [currentValue])

```

---

<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:** [April 26, 2024, 3:13pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/7 "2024-04-26T15:13:27Z")

</div>

> [@Ryan\_Craig](#):
>
> do something like this

No, `.sleep()` is evil. (It can break your system if used improperly, especially in tag events.)

Make a new integer `TestState` memory tag alongside your others.  
Put this in a project library script:

```python
allTags = ['[default]E398/E398/%s' % x for x in ['Result', 'TestState', 'Test1OcclusionFinal', 'Test2BurstFinal']]
readTags = allTags[:2]
writeTags0 = allTags[1:2]
writeTags1 = allTags[1:3]
writeTags2 = allTags[1:2] + allTags[3:]

# Call this at quarter-second intervals.
def monitorE398():
	result, state = [x.value for x in system.tag.readBlocking(readTags)]
	if state == 0:
		# Check for non-zero result from PLC to start sequence.
		if result:
			state += 1
			system.tag.writeBlocking(writeTags1, [state, result])
	elif state < 8:
		# Dwelling between results. Just increment the state.
		state += 1
		system.tag.writeBlocking(writeTags0, [state])
	elif state < 16:
		# Looking for result #2
		if result:
			state = 0
			system.tag.writeBlocking(writeTags2, [state, result])
		else:
			state += 1
			system.tag.writeBlocking(writeTags0, [state])
	else:
		# Timeout or invalid state. Might want to log a message.
		state = 0
		system.tag.writeBlocking(writeTags0, [state])

```

Put this one-liner in a timer event set to 250ms:

```python
myE398script.monitorE398()

```

Adjust as you see fit. (Presumably parameterizing things.)

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [April 26, 2024, 4:46pm UTC](https://forum.inductiveautomation.com/t/tough-scripting-problem/89526/8 "2024-04-26T16:46:17Z")

</div>

I was thinking more along the lines of this in the valueChanged script (adjusting as necessary with relative paths for tags if you're using this in a UDT):

```python
if currentValue.value:
	elapSec = system.date.secondsBetween(previousValue.timestamp, currentValue.timestamp)
	if elapSec > 5:
		# This is our first result
		system.tag.writeBlocking(['[default]E398/E398/Test1OcclusionFinal'],[currentValue.value])
	else:
		# This is our second result
		system.tag.writeBlocking(['[default]E398/E398/Test2BurstFinal'],[currentValue.value])

```

Edit: Had to fix my elapSec comparison to be greater than rather than less than.
