UDT Instance value changed not working

I have some tag change scripts in normal memory tags. They work perfectly.
I had a UDT instance with a tag change in one of the tags within the UDT that doesn't work quite right.

I take a large string from my mqtt and separate the position I need and put it in my UDT tag. I force the write from scratch and finally get the value I want. And it WORKS, but when I shut down the computer and open everything again, it doesn't work. I have to go directly to the tag (here outside the UDT definition tab), write anything, and it updates and the script works as it should.

Translated with DeepL.com (free version)

But I can't understand why it only doesn't work in the UDT instance.

Does anyone have any idea what I can do? I apologize if it's too obvious, I'm new to Ignition and Python.

I want to do it through UDT, because I will have several pumps and other instruments in the project and it would take too long to develop scripts with each tag path to change via gateway event script pump by pump.

Are there any errors or warnings in the gateway logs?

On line 8 , tag_Value [0] should be tag_value[0] the extra space is likely causing issues.

Assuming you are using the same UDT for each pump (or similar UDTs for groups of pumps),
Gateway tag event scripts allow wildcards at the folder level when defining the tags to monitor.

Inside of the event script, you also have access to the full tag path of the tag that triggered the event, so you should be able to indirectly build the path to related tags without hard defining a list or a massive if...else chain. Worst case is that you make 1 gateway event per UDT type.

Gateway Tag Change Event object

Finally, screenshots are great for showing context, but code should also be posted as preformatted text, to help speed up troubleshooting by allowing a simple copy/paste instead of having to read it from a screenshot. See Wiki - how to post code on this forum.

1 Like

Sorry, here's the script
This one is in the UDT instance.

def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
		refTagPath = "[.]../_Topico/TOP_SET_SEUP"
		Update_Tag = "[.]../_Updt_Dados_Cmb/Update_Tags"	
		tag_value = system.tag.readBlocking([refTagPath])[0].value.split("; ")
		
		if Update_Tag != 0:
			targetPath = "[.]TMPPL1"
	    	values = tag_value[0]
	    	system.tag.writeAsync(targetPath, 0)
	    	system.tag.writeBlocking(targetPath, values)

My refTagPath It's the big string, it leaves the PLC, goes to a broker, and arrives via MQTT in Ignition. At the moment, it only has random numbers, as you can see.
When I change the refTagPath, TMPPL1 (the UDT tag I'm testing in isolation) changes the value.

Update_Tag It's that memory tag.

As I change refTagPath, TMPPL1 changes too. The sad part happens after I shut down the entire computer and perform the same test.
image
image

Ryan, I removed the space from tag_value[0], but I didn't understand what you meant by event script, Could you explain it to me?

This:

if Update_Tag != 0:

Is always true, and I don't think that is your intended purpose. I'm not sure as you clearly know that you need to read the tag to get its value as demonstrated in the assignment of tag_value.

Also, using system.tag.writeAsync() imediately prior to a system.tag.writeBlocking() call to the same path, makes no sense. There isn't even really a gaurentee that the writes happen in that order. Just use the blocking write.

Instead you should do something like:

tagPaths = ['[.]../_Topico/TOP_SET_SETUP','[.]../_Udpt_Dados_Cmb/Update_Tags']
refTag,updateTag = [qv.value for qv in system.tag.readBlocking(tagPaths)]

if not updateTag:
    system.tag.writeBlocking(['[.]TMPPL1'],[refTag.split('; ')[0]])
2 Likes

To make sure I'm understanding correctly, each UDT instance is passed a chunk of the main MQTT message, and that chunk contains the data for all members of that UDT? And you are trying to make it so that, when that data chunk updates or is passed a new value, all members of the UDT are updated with their new values based on the data in the chunk?

Is that correct?

Yes!
Every piece of the main MQTT message goes to the UDT members.
We send a lot of pump information to SCADA. I know it would be much easier via Modbus, but the customer wants MQTT.

Louis, I replaced my script with yours, but unfortunately it didn't work as expected, and my system.tag.writeBlocking() really doesn't make sense. Thanks a lot for the tip!

If there is no expectation for writing back to the device, you can get away with probably just using expression tags. split is available in in expressions, so if you add an additional expression tag with an expression of split([TOP_SET_SEUP], ';'), it should yield a single column dataset.

From there, each of your UDT members would be expression tags with the expression of {path/to/ref/dataset}[positionIndex, 0], where positionIndex is the 0-based position of the members' data in the reference dataset made by splitting the MQTT message on the ; character.

This assumes that all members of a device exist in the same relative position of every chunk. For example, across all pumps of type A, the pump RPM value is always in position 1, temperature is position 2, etc.

2 Likes

I'm not sure how, as other than correcting the value actualy being read into updateTag, The code does exactly the same thing that your code does. Which I suppose my not be working as expected?

In fact, I'm not really sure exactly what your expectation is, or what the script is doing that is unexpected.

Not every hero wears a cape, Ryan, thank you very much!!
It worked! Brabo demais campeão!