Now when we look the the Logs in Ignition, we can see the following output as expected showing Data1 and Data2 have the same value. 
The problem arises when MQTT Engine is calling 'update tag' on both Data1 and Data2 very quickly (many times a second). This can lead to synchronization problems in our tag change script because by the time the script is reading Data2, MQTT Engine has already written a new value to it and we end up with an erroneous output.
To simulate this scenario, let's edit the Gateway Timer Script and set the delay to only 5ms

Now when we look the the Logs in Ignition, we can see the following output showing that the values are out of synchronization. 
Configuring Tag Latching
When this happens, we can use tag latching to synchronize MQTT Engine with the tag change script.
The configuration for Tag Latching is available under MQTT Engine General tab > Advanced Settings with the following properties:
- Enable Tag Latching
- Whether or not to enable Tag latching to synchronize MQTT Tag updates with events in Ignition.
Latch Timeout
- The amount of time in milliseconds MQTT Engine will to wait for a tag latch to be released before does it on its own.
Latch Tags
- A semicolon separated list comma separated list of Trigger Tag and Latch Tag pairs.
- A 'Trigger Tag' is a 'real tag' that you would normally use in a standard Transaction Group or Tag Change Script as a trigger.
- The 'Latch Tag' is a tag that will be created in the [MQTT Engine]Engine Info/Latches folder. Each latch tag will be set to true when MQTT Engine calls updateTag for that given trigger tag. Then MQTT Engine waits until the timeout or until the latch tag gets set back to false by a script, transaction group, etc - which ever comes first. The latch tag is what should be used by scripts or transaction groups and must be set back to false at the end of the operation to allow MQTT Engine to continue processing incoming Sparkplug messages.
- The 'Latch Tags' must be of the form:
- Group ID/Edge Node ID/Device ID/Trigger Tag,Group ID/Edge Node ID/Device ID/Latch Tag for example:
- G1/E1/D1/Trigger Tag 1,G1/E1/D1/Latch Tag 1
- You can also have longer folder paths on any trigger tag or latch tag. For example:
- G1/E1/D1/my/longer/tag/path/Trigger Tag 1,G1/E1/D1/my/longer/path/Latch Tag 1
- If you want to specify two or more latches, separate them with a semicolon:
- G1/E1/D1/Trigger Tag 1,G1/E1/D1/Latch Tag 1;G1/E1/D1/Trigger Tag 2,G1/E1/D1/Latch Tag 2
- You can also specify multiple trigger tags for any given latch. Just create two or more entries that each point to the same latch tag:
- G1/E1/D1/Trigger Tag 1,G1/E1/D1/Latch Tag 1;G1/E1/D1/Trigger Tag 2,G1/E1/D1/Latch Tag 1
- You can specify as many as trigger and latch tags as you want.

Edit the configuration as shown below to set the Latch Tags field as 'G1/E1/D1/Data1,G1/E1/D1/Latch'.

With this set, MQTT Engine will now set a new tag '[MQTT Engine]Engine Info/Latches/G1/E1/D1/Latch' to true every time the trigger tag changes.

So for this example, the tag change script is modified as follows to release the latch at the end of the script. (Scripts to use/copy can be found here)

Now with this setup, we can see the output is correct as shown below. Note all of this output came from within the same second.
Gateway Event Scripts
value = system.tag.read("[default]Edge Nodes/G1/E1/D1/Data1").value
value += 1
if value > 500:
value = 0
system.tag.writeSynchronous("[default]Edge Nodes/G1/E1/D1/Data2", value, 30)
system.tag.writeSynchronous("[default]Edge Nodes/G1/E1/D1/Data1", value, 30)
#add logger
logger = system.util.logger("com.cirruslink.test.MQTTEngine.latching")
dataOneValue = newValue.getValue()
dataTwoValue = system.tag.read("[MQTT Engine]Edge Nodes/G1/E1/D1/Data2").value
logger.info("Values: " + str(dataOneValue) + " => " + str(dataTwoValue))
#add logger
logger = system.util.logger("com.cirruslink.test.MQTTEngine.latching")
dataOneValue = newValue.getValue()
dataTwoValue = system.tag.read("[MQTT Engine]Edge Nodes/G1/E1/D1/Data2").value
logger.info("Values: " + str(dataOneValue) + " => " + str(dataTwoValue))
# Free the latch
system.tag.writeSynchronous("[MQTT Engine]Engine Info/Latches/G1/E1/D1/Latch", False, 45)
Additional Resources
- Inductive Automation's Ignition download with free trial
- Azure Injector download with free trial
- Questions about this tutorial?
- Sales questions
- About Cirrus Link