writeBlocking not working like expected

Fairly new to Ignition and Python in particular. I'm making a simple button to increase all the setpoints in a group by 1. I know there are many ways to do this, but, in trying to learn Python, I'm curious why this method doesn't work. Here's my script in the console with full read/write gateway enabled.


For readability, script is:

valuewrite = [0,0,0]
paths = ["[default]MM01_Dryer/MM01_Z1/MM01_Zone1_Temperature_SP",
			"[default]MM01_Dryer/MM01_Z2/MM01_Zone2_Temperature_SP",
			"[default]MM01_Dryer/MM01_Z3/MM01_Zone3_Temperature_SP"]

values = system.tag.readBlocking(paths)
print values
for index in range(3):
	valuew[index] = values[index].value + 1;
	
print valuew

system.tag.writeBlocking(paths, valuew)

values = system.tag.readBlocking(paths)

print values

When the script runs, it correctly prints out the values array with the value, status and timestamp for each of the three elements. It takes the value for each element, adds one and dumps it into a new list that prints correctly. The script tries to write and shows a good status. It reads the tags back and shows they haven't changed. If I wait a bit and read the tags back it shows they have changed - but only the third tag. I can understand why the read-back doesn't show a change - maybe it's too "soon" after the write, but why only the third setpoint?

Any guidance is appreciated.

Have you actually inspected the result from the writeBlocking or do you mean that the entire script completed without throwing an error?

system.tag.writeBlocking will return the status of the writes to the tags as a list. Inspect that to see if the writes succeeded.

I would also confirm that those tags are not read only tags.

writeBlocking blocks until the write result is available, which for OPC tags means when the StatusCodes for the write service call are received.

It doesn't block until the value of the tag has changed. OPC tags are updated only by Subscription updates (in OPC subscribe mode, with optimistic writes disabled - the default tag group configuration).

If you waited long enough to read you should see all 3 with your final readBlocking. Only seeing one is probably just a timing quirk. Other possibility is the write doesn't "stick", e.g. the PLC logic overwrites it or something.

If you used system.opc.read/write calls instead you'd probably see the behavior you expect because each of these are going directly to the OPC server and subsequently to the PLC.

2 Likes

The console printed out [Good,Good,Good] after issuing the write. I assumed that was confirmation of no errors. I have value input controls for these three values and can freely change them. The idea behind this was I didn't want the operator to change the zones independently, so this was a simple up and down button to add or subtract one degree from the all setpoints simultaneously. It does that, but only to the third setpoint in the list.

Is your code snippet actual? Or is it modified to not have sensitive info? I'm not seeing where valuew is defined. That might be contributing.

If this is being used for a roller button on a temperature entry, the following list comprehension might be better:

values = [qv.value + 1.0 for qv in system.tag.readBlocking(paths)]
system.tag.writeBlocking(paths, values)

That just means the write code path thinks the values were successfully handed to the OPC Server for write. (For native Ignition drivers, it generally means wrote through to the device.) It does not mean that the tag value in Ignition matches, as that doesn't happen until the OPC subscription (or re-poll, if polling) confirms it.

(Note that "optimistic writes" changes this, but can have other negative consequences.)

Fundamentally, reading/writing values that live in two places (PLC & Ignition) will always be subject to synchronization/timing issues. It isn't a python/jython thing.

I rewrote things using system.opc:

server = "Ignition OPC UA Server"
path = ["[MM01_Dryer]Zone_1A.PID_Zone_Temp_Control.SP",
"[MM01_Dryer]Zone_2.PID_Zone_Temp_Control.SP",
"[MM01_Dryer]Zone_3.PID_Zone_Temp_Control.SP"]
valueCurrent = system.opc.readValues(server, path)
for index in range(3):
	valueNew[index] = valueCurrent[index].value + 1;
system.opc.writeValues(server,path,valueNew)
print valueCurrent
print valueNew

My output is:
array(com.inductiveautomation.ignition.common.model.values.QualityCode, [Good, Good, Good])
array(com.inductiveautomation.ignition.common.model.values.QualifiedValue, [[440.0, Good, Mon Jul 07 16:59:03 EDT 2025 (1751921943661)], [430.0, Good, Mon Jul 07 16:59:03 EDT 2025 (1751921943661)], [405.0, Good, Mon Jul 07 16:59:03 EDT 2025 (1751921943661)]])
[441.0, 431.0, 406.0]

When I execute the code, the same thing happens, only the third setpoint changes, the "Zone_3" tag.

I did find a clue, however. When I change the order of the tags, and swapped Zone_2 and Zone_3, only Zone_3 changed. It's acting like a permission issue, but I'm not even sure where to look - they're all coming from the same PLC, same device. This isn't a tag security issue, correct? I'm writing directly through the OPC server.

What am I missing?

Any permissions issues would have produced a non-Good write status. Look for logic in the PLC that is writing to the setpoints (bumpless auto-manual handoff, perhaps).