# Function Script not working

**URL:** <https://forum.inductiveautomation.com/t/function-script-not-working/83184>\
**Category:** Ignition\
**Tags:** ignition81, scripting, vision\
**Created:** [December 15, 2023, 10:46am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184 "2023-12-15T10:46:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 10:46am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/1 "2023-12-15T10:46:26Z")

</div>

Hi,

I have the following script:

```auto
def auto_select_operator_interaction(msg_nr, action):
    if action == 2: # Outgoing alarm
        # If action was selected, then unselect
        if msg_nr == system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition"):
            system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", 0)

        # Shift all active alarms from the selected one
        for index in range(20):
            if system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index)) == msg_nr:
                temp_index = index - 1
                while temp_index < 20:
                    temp_index += 1
                    index_van = temp_index + 1
                    system.tag.writeBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(temp_index),
                                     system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index_van)))

        # Select new one
        if system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition") == 0 and system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]") > 0:
            system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]"))

    elif action == 1: # Incoming alarm
        for index in range(20):
            if system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index)) == 0:
                system.tag.writeBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index), msg_nr)

        # Select new one
        if system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition") == 0:
            system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]"))

    else: # Loop in alarm
        system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", msg_nr)

```

and this in my script console:

```auto
operatorIndexScript.auto_select_operator_interaction(5, 1)

```

what the result should be after this is being executed is that the first number in my array of the tag 'L4\_Active\_Operator\_Msg' should be 5. But instead it stays 0.  
The function doesn't return anything so my return in the Console screen is empty.  
It is not giving an error that something is wrong with the function so I don't know why it is not working.

Is there someone who can help me with this?

---

<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:** [December 15, 2023, 10:56am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/2 "2023-12-15T10:56:58Z")

</div>

`system.tag.read*` functions return a list of qualified values. Its return will NEVER be equal to `0`.

Now, another thing to note: avoid running multiple calls to the tag read and write functions. Build the data first, then pass everything in just one call. Or as few calls as possible.  
It will also probably make the logic easier to follow.

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 10:59am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/3 "2023-12-15T10:59:17Z")

</div>

so instead of reading the tag 20 times make it in such a way that it has to read it only one time?

---

<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:** [December 15, 2023, 11:02am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/4 "2023-12-15T11:02:05Z")

</div>

Let me try to figure out what your script actually does before answering 🙂

edit:

```python
for index in xrange(20):
	if system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index)) == msg_nr:
		temp_index = index - 1
		while temp_index < 20:
			temp_index += 1
			index_van = temp_index + 1
			system.tag.writeBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(temp_index),
						system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index_van)))

```

ew... What is going on here ?

What's in the `[Test SCADA Ignition]L4_Active_Operator_Msg` array ?  
You're comparing its values to integers, but its name suggests it contains strings.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [December 15, 2023, 11:22am UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/5 "2023-12-15T11:22:14Z")

</div>

> [@Stef\_Velers](#):
>
> so instead of reading the tag 20 times

Yes, we covered that [yesterday](https://forum.inductiveautomation.com/t/gateway-scripts-or-expression/83077/18) where you were running 48 × `readBlocking` which will run one after another with each waiting until it is finished before going on to the next one. Read them all at once if at all possible. (There will be a maximum limit - but it will be large.)

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 12:41pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/6 "2023-12-15T12:41:55Z")

</div>

This code

```auto
for index in xrange(20):
	if system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index)) == msg_nr:
		temp_index = index - 1
		while temp_index < 20:
			temp_index += 1
			index_van = temp_index + 1
			system.tag.writeBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(temp_index),
						system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index_van)))

```

is changing the first array value for the second array value. basically moving the whole array one to the front.

> [@pascal.fragnoud](#):
>
> What's in the `[Test SCADA Ignition]L4_Active_Operator_Msg` array ?

This is an integer array. The values in the array will point to a text thats why it's called Msg

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 12:43pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/7 "2023-12-15T12:43:43Z")

</div>

I will change my code in the way we talked about yesterday

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [December 15, 2023, 12:51pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/8 "2023-12-15T12:51:19Z")

</div>

> [@Stef\_Velers](#):
>
> This code

But you still have 20 × `readBlocking` and up to 20 × `writeBlocking` + `readBlocking` = 20 × (20 + 20) = 800 read/write operations!

- Read everything you need in one `readBlocking`.
- Do the loop and update the list to be send out.
- Send out the list in one `writeBlocking`.

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 12:54pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/9 "2023-12-15T12:54:10Z")

</div>

I'm changing it. Give me some time. I will send the updated code when I'm done.

---

<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:** [December 15, 2023, 1:06pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/10 "2023-12-15T13:06:55Z")

</div>

> [@Stef\_Velers](#):
>
> is changing the first array value for the second array value. basically moving the whole array one to the front.

I'm not sure this does what it's supposed to do.  
Can you explain in details what you want to happen, maybe with a couple of examples ?  
Can you explain WHY you're moving things around ?

I rewrote it to read and write just once, keeping (I believe) the same logic:

```python
def auto_select_operator_interaction(msg_nr, action):
	op_index_path = "[Test SCADA Ignition]OperatorIndexIgnition"
	op_msg_path = "[Test SCADA Ignition]L4_Active_Operator_Msg"
	op_index, op_msg = [qval.value for qval in system.tag.readBlocking([op_index_path, op_msg_path])]

	if action == 2: # Outgoing alarm
		# If action was selected, then unselect
		
		if msg_nr == op_index:
			op_index = 0

		# Shift all active alarms from the selected one
		for index in xrange(20):
			if op_msg[index] == msg_nr:
				temp_index = index - 1
				while temp_index < 20:
					temp_index += 1
					op_msg[temp_index] = op_msg[temp_index + 1]

		# Select new one
		if op_index == 0 and op_msg[1] > 0:
			op_index = op_msg[1]

	elif action == 1: # Incoming alarm
		for index in range(20):
			if op_msg[index] == 0:
				op_msg[index] = msg_nr

		# Select new one
		if op_index == 0:
			op_index = op_msg[1]

	else: # Loop in alarm
		op_index = msg_nr

	system.tag.writeBlocking([op_index_path, op_msg_path], [op_index, op_msg])

```

It still needs some work to make it... let's say sane.  
But while I can see what's going on line by line, I still can't figure out the big picture (which is often a sign that it needs some rework).  
I have the feeling there's a much simpler way, but without understanding the goal I'm left with just that, a feeling.

Though, now it's a bit simpler to read and reason about, so I'm a bit more comfortable to start simplifying things

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [December 15, 2023, 1:22pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/11 "2023-12-15T13:22:55Z")

</div>

Are you trying to create a shift-register?

```auto
input = ["zero", "one", "two", "three", "four"]
print input
print input[1:]

```

`input[1:]` will give you the complete list but without `input[0]`.

```auto
['zero', 'one', 'two', 'three', 'four']
['one', 'two', 'three', 'four']
>>>

```

Can you use that syntax to simplify your code?

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 1:32pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/12 "2023-12-15T13:32:27Z")

</div>

Okay I will try to explane to you. It has to do with the thing we worked on yesterday.

The action and msg\_nr are passed to this script when my alarm of the tag values prompt goes off (same prompt tags as yesterday so there are around 20 of these prompt tags).  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/b/1ba4a074092903d4ac168281e6fc55840b57037e.png)  
All those action datatypes have this prompt tag.

if the one of the alarms of these prompt tags goes off (this happends when prompt tag value is \> 0) then action = 1 so it will run this function and then action 1 of it.

> [@pascal.fragnoud](#):
>
> ```auto
> elif action == 1: # Incoming alarm
> for index in range(20):
> if op_msg[index] == 0:
> op_msg[index] = msg_nr
> 
> ```

so this part of your updated code.  
if alarm goes away because it is being cleared. It will pass action = 2 and run:

> [@pascal.fragnoud](#):
>
> ```auto
> if action == 2: # Outgoing alarm
> # If action was selected, then unselect
> 		
> if msg_nr == op_index:
> op_index = 0
> 
> # Shift all active alarms from the selected one
> for index in xrange(20):
> if op_msg[index] == msg_nr:
> temp_index = index - 1
> while temp_index < 20:
> temp_index += 1
> op_msg[temp_index] = op_msg[temp_index + 1]
> 
> # Select new one
> if op_index == 0 and op_msg[1] > 0:
> op_index = op_msg[1]
> 
> ```

msg\_nr is the parameter that points to the right prompt tag that is \>0. This parameter is passed when the alarm goes off just like action parameter.

L4\_Active\_Operator\_Msg will be the array of msg\_nr.  
for example: if prompt tag of Action1 is \>0 then msg\_nr is 1 and the alarm goes off because this prompt is now \>0 so it will pass msg\_nr = 1 and action= 1

what must happen now is that the msg\_nr is the first number in the L4\_Active\_Operator\_Msg array.  
if not one but 2 prompt tags are \>0 then the second one that is \>0 must be stored in the array after the first one. So after this there should be 2 msg\_nr in the array.

as soon as one alarm is cleared the parameter action passes 2 so it wil run the action = 2 code. This code must delete the msg\_nr of the alarm that is just been cleared and move the whole array so that the alarm that is still on is in the first place in the array

so Action1/prompt \>0  
array: [1]  
now Action5/prompt also \>0  
array:[1,5]  
alarm of Action1/prompt \<=0  
array: [5]  
This is what must happen yes:

> [@Transistor](#):
>
> ```auto
> ['zero', 'one', 'two', 'three', 'four']
> ['one', 'two', 'three', 'four']
> 
> ```

but then with normal integers

---

<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:** [December 15, 2023, 1:42pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/13 "2023-12-15T13:42:03Z")

</div>

Is `L4_Active_Operator_Msg` supposed to be a queue then ?  
Except you're not necessarily popping the first element ?  
Are there always 20 elements in that array ?

I kind of feel like you're not using the right tools for this job.

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 1:44pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/14 "2023-12-15T13:44:37Z")

</div>

> [@pascal.fragnoud](#):
>
> I kind of feel like you're not using the right tools for this job.

I'm not sure because it code that rewrote into ignition of my company that I work for.

> [@pascal.fragnoud](#):
>
> Are there always 20 elements in that array ?

The values that will be in the array are the msg\_nrs.  
most of the time there will be 0,1 or 2 msg\_nrs in the array because there are often 0,1,2 alarms on at the same time

---

<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:** [December 15, 2023, 1:51pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/15 "2023-12-15T13:51:50Z")

</div>

Alright, let's see if I got things right:  
alarm becomes active: Put the corresponding number in the queue  
alarm cleared: Remove it from the queue

Is that it ?

What's the role of the operator index in all this ? It doesn't seem to affect the messages in any way.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [December 15, 2023, 1:54pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/16 "2023-12-15T13:54:18Z")

</div>

> [@pascal.fragnoud](#):
>
> ```auto
> if op_msg[index] == msg_nr:
> temp_index = index - 1
> while temp_index < 20:
> temp_index += 1
> op_msg[temp_index] = op_msg[temp_index + 1]
> 
> ```

can, I think, be rewriten as,

```python
if op_msg[index] == msg_nr:
	op_msg = op_msg[1:]

```

This will drop the zero element of the list and move everything else left one position.

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 1:55pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/17 "2023-12-15T13:55:23Z")

</div>

> [@pascal.fragnoud](#):
>
> Alright, let's see if I got things right:  
> alarm becomes active: Put the corresponding number in the queue  
> alarm cleared: Remove it from the queue
> 
> Is that it ?

This is right

```auto
def auto_select_operator_interaction(msg_nr, action):

	tagPaths = []
	arrayZero = []
	if action == 2: # Outgoing alarm
        # If action was selected, then unselect
        if msg_nr == system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition"):
            system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", 0)

        # Shift all active alarms from the selected one
        for index in range(20):
            if system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index)) == msg_nr:
                temp_index = index - 1
                while temp_index < 20:
                    temp_index += 1
                    index_van = temp_index + 1
                    system.tag.writeBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(temp_index), system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index_van)))

        # Select new one
        if system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition") == 0 and system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]") > 0:
            system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]"))

    elif action == 1: # Incoming alarm
        for index in range(20):
        	tagPaths.append("[Test SCADA Ignition]L4_Active_Operator_Msg[{}]".format(index))
        
        tagValues = system.tag.readBlocking(tagPaths)
        for index in range(20):
        	if tagValues[index] == 0:
           		tagValues[index] = msg_nr
        	
            # Select new one
        	if system.tag.readBlocking("[Test SCADA Ignition]OperatorIndexIgnition") == 0:
           	 	system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", system.tag.readBlocking("[Test SCADA Ignition]L4_Active_Operator_Msg[1]"))

    else: # Loop in alarm
        system.tag.writeBlocking("[Test SCADA Ignition]OperatorIndexIgnition", msg_nr)

```

If you look in this code that I had earlier operatorIndex is being written by msg\_nr or set back to 0.  
I use this tag to point to prompt values again so they will display a text in my operator screen like I said yesterday

---

<div class="post-metadata">

**Author:** ![Stef\_Velers](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@Stef\_Velers](https://forum.inductiveautomation.com/u/Stef_Velers)\
**Post date:** [December 15, 2023, 1:58pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/18 "2023-12-15T13:58:34Z")

</div>

You guys are pretty quick with all the coding so I will try to see if the current solution you guys have given to me work and let you know if I managed. I'm not that quick with all this sorry for that. It's all very new for me

---

<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:** [December 15, 2023, 1:59pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/19 "2023-12-15T13:59:15Z")

</div>

Not if elements from the middle of the list can be popped.  
What I think he wants is just

```python
del op_msg[index]

```

maybe ?  
or

```python
op_msg = [msg for msg in op_msg if msg != msg_nr]

```

But I still think the whole thing took a wrong turn at some point and there's a better way to do all this.

edit: side note  
If you're in a situation where you want to be doing `some_list[1:]`,  
consider using a queue. I'm sure Java has some types that can be used for this, or there's `collections.deque` with `.pop()` and `.popleft()`. It even has a `rotate()` method !  
It's not always worth it, but it's always nice to know it exists.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [December 15, 2023, 2:54pm UTC](https://forum.inductiveautomation.com/t/function-script-not-working/83184/20 "2023-12-15T14:54:41Z")

</div>

> [@pascal.fragnoud](#):
>
> I'm sure Java has some types that can be used for this

There are several options, depending on requirements that can be used.

[https://docs.oracle.com/javase/8/docs/api/java/util/AbstractQueue.html](https://docs.oracle.com/javase/8/docs/api/java/util/AbstractQueue.html)

I know that the `ConcurrentLinkedQueue` is thread safe.

[Next page](https://forum.inductiveautomation.com/t/function-script-not-working/83184.md?page=2)
