I'm trying to read bulk 500 derived tags and write bulk OPC tags as fast as I can.
First, I tested reading Derived tags and writing into Memory tags.
Using system.tag.readBlocking and system.tag.writeBlocking - It took around 4s.
Using system.tag.readBlocking and system.tag.writeAsync - it took around 100ms (which is perfect!)
To measure I used system.date.now(). For writeBlocking I printed end time after execution, while to measure writeAsync I used a callback function to print end time.
Now, when writing to OPC tags
Using system.tag.readBlocking and system.tag.writeBlocking - It took around 50 - 60s.
Using system.tag.readBlocking and system.tag.writeAsync - it took around 40 - 50s
Using system.tag.readBlocking and system.opc.writeValues - it took around 30 - 40s
How can I improve this behaviour? I'm writing to an Open ModSim Server from Ignition 8.1.48 Edge.
No it didn't. You're not "Timing" what you think you're timing.
Fundamentally, the only difference between writeBlocking() and writeAsync(), is that the system doesn't wait around for the return telling you if the writes were successful or not. Instead firing the write command and returning instantly.
You only timing the execution time of the script that you wrote, which not suprisingly took longer when you blocked it from continuing.
Also, remeber when writing to OPC tags, system.tag.write*() doesn't actually write to the device.
This seems like forever, for 500 tags. My gut reaction to this execution time is that their is an issue with the script that you're using. Please share the script, as I really do not think these times have anything to do with the driver or tag configuration.
This is the code for writeAsync and OPC tags and how I measure execution the time
def update():
# Browse UDT instances
udt_name = "point_2v1"
tag_provider = "[edge]"
filter_tags = {"tagType":"UdtInstance","typeId":udt_name,"recursive":True}
browse_results = system.tag.browse(tag_provider,filter_tags).getResults()
#Define input/output tag paths
udt_instances = [str(res["fullPath"]) for res in browse_results]
input_paths = [str(inst) + "/inputValue" for inst in udt_instances]
output_paths = [str(inst) + "/outputValue" for inst in udt_instances]
#Read input values
write_values = system.tag.readBlocking(input_paths)
values_list = [val.value for val in write_values]
#Write output values
system.tag.writeAsync(output_paths, write_values,myCallback)
def myCallback(asyncReturn):
print ("End time: {} ms".format( system.date.now()))
# Run the function
import system
print("Start time: {} ms".format( system.date.now()))
update()
The Start time is printed on the script console while the End time is printed on the output console once the operation was complete. This time took 20s to write 480 OPC tags.
Modbus Setup Description Using Ignition OPC UA server:
The Modbus setup consists of a single Modbus TCP connection to a locally installed Open ModSim server. Both the Edge Gateway and the ModSim server are hosted on the same local machine.
The Edge Gateway is configured with 500 UDT instances. Each UDT instance contains two tags: one Derived tag and one OPC tag. These OPC tags correspond to Modbus Holding Registers (Int, Float, Double), mapped sequentially from address 1.
When I run the same code as you, I have this result:
First, I check the initial values for HR1 and HR1103 in Ignition and Open ModSim Server.
Then executed the script and once it finishes check the new values HR1 and HR1103. This time took 33sec.
I try to configure each OPC tag as Integer and consecutive, but I see this error message on Gateway Logs
Ooh, or this could be a bug in the driver... I kind of remember something about the max number of registers to write actually being 123 and not 125...
Try setting the "Max Holding Registers Per Request" setting on the driver to 123 instead. The bug was that it's supposed to be 125 for reads and 123 for writes, but the driver only has one shared setting that is wrong for writes.
It's rare that you ever have writes packed so well that you fill out a request, and then I think on top of that some servers will happily accept 125 registers in a write, because it does actually fit when you're doing Modbus TCP without any regard for the size limit inherited from the original serial implmentation. I think you can fit 127 before you overflow the "Byte Count" byte in the request.
But the spec limits it to 123 so the overall PDU/ADU doesn't exceed 256 bytes, even though that doesn't matter on Modbus TCP.
Too bad this is Edge. You could use my Integration Toolkit's Republish action to do this without a script. Unless you buy my alternate Modbus driver for Edge, which gives me an opportunity to include the Toolkit....
It's my first time using Wireshark, so let me know if it's okay.
Now I'm using Modbus Slave instead of Open ModSim which improved writing to 17sec.
After running wireshark I only saw Write Single Register requests. Test 1.pcapng (841.0 KB)
During Test 2 I enabled Force Multiple Register Writes but it took 17sec as well. Test 2.pcapng (720.6 KB)