# OPC questions - differences between opc.readValue and tag.read

**URL:** <https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277>\
**Category:** General Discussion\
**Tags:** scripting\
**Created:** [December 10, 2017, 12:45pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277 "2017-12-10T12:45:26Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![tkelch](https://avatars.discourse-cdn.com/v4/letter/t/ccd318/32.png) [@tkelch](https://forum.inductiveautomation.com/u/tkelch)\
**Post date:** [December 10, 2017, 12:45pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/1 "2017-12-10T12:45:26Z")

</div>

I have some specific questions regarding how the OPC server is working behind the scenes and the recommend methods for scripting when reading/writing OPC tags.

- Is the sample handshake analysis below correct?
- `tag.read/write` will read/write values from the OPC server, whereas `system.opc.readValue/writeValue` will **force** interaction with the data source (opc server connection) - is this accurate?
- How can you _100% guarantee_ data in `system.tag.read` is accurate - or is the only guarantee `system.opc.readValue`? Is it normal to see people exclusively using `system.opc.*` in scripts?
- Is there a list of OPC best practices that IA has compiled over the years?

## Sample Handshake

The OPC server scans for updated information and based on the scans, updates its internal OPC server memory map.

Ignition and the `system.tag.read/write` commands interface with the block of memory stored on the OPC server - increasing the systems speed - but since actions are async so there is no guarantee that the event actually occurs. So if the handshake shown below was implemented, it would fail some times (or every time). Because at step 6, `ACK_Complete` is low, getting set to high, IA will write the bit and immediately look for it to be low (step 9). It will start looking for a low bit prior to the PLC doing any action. Sometimes the handshake will work, other times it won't (probably won't?).

 ![](https://us1.discourse-cdn.com/inductiveautomation/original/2X/f/f6a11459a0f8e22fd493fccfb528243a346f6ede.png)

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 10, 2017, 6:55pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/2 "2017-12-10T18:55:02Z")

</div>

The tag in Ignition and the node in the OPC server are completely decoupled.

`system.tag.read` will just give you the current value in memory for the Ignition tag.  
`system.tag.write` will write to the Ignition tag, which in turn causes a write to the OPC server to happen if it’s an OPC tag.

`system.opc.read` bypasses Ignition’s tags altogether and just sends a read request to the OPC server.  
`system.opc.write` bypasses Ignition’s tags algotether and just sends a write request to the OPC server. If successful and there’s an Ignition OPC tag pointing at any of the nodes in the write, those tags will eventually receive the updated value through the normal OPC subscription mechanism.

---

<div class="post-metadata">

**Author:** ![tkelch](https://avatars.discourse-cdn.com/v4/letter/t/ccd318/32.png) [@tkelch](https://forum.inductiveautomation.com/u/tkelch)\
**Post date:** [December 11, 2017, 3:39pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/3 "2017-12-11T15:39:29Z")

</div>

Is there a process or procedure to guarantee every read/write has happened on the PLC hardware before moving onto the next step?

This psudo code procedure doesn’t seem reasonable for every write.  
`write Tag1 = 1`  
`while (read Tag1) != 1:`  
`.... sleep`

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 11, 2017, 3:47pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/4 "2017-12-11T15:47:45Z")

</div>

Using `system.opc` functions is the best you can do. There’s no such thing as a guarantee. Any PLC can report that the write was successful, and while that’s usually good enough, the only way you can verify the value is to read it. Even if the write didn’t fail, another write or some logic in the PLC could change the value after the value you wrote.

---

<div class="post-metadata">

**Author:** ![tkelch](https://avatars.discourse-cdn.com/v4/letter/t/ccd318/32.png) [@tkelch](https://forum.inductiveautomation.com/u/tkelch)\
**Post date:** [December 11, 2017, 4:01pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/5 "2017-12-11T16:01:50Z")

</div>

Is there any documentation that IA has compiled over the years that provide best practices for setting up OPC-UA handshakes?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 11, 2017, 4:03pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/6 "2017-12-11T16:03:52Z")

</div>

No, but I’m sure some of our forum users can jump in and share what’s worked for them.

(That’s your queue, guys… 😉 @pturmel maybe?)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 11, 2017, 5:12pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/7 "2017-12-11T17:12:17Z")

</div>

The only way to know for sure that a specific write to the PLC has occured is to use [system.opc.writeValue](https://docs.inductiveautomation.com/display/DOC79/system.opc.writeValue) and examine the status it returns. Even better is to use different addresses in the PLC for reads and writes. I generally prefer to use odometer-style integers as triggers for critical handshakes, in both directions. When a block of data needs to go to the PLC, I have Ignition write all but the trigger via system.opc.writeValues(), and if all succeeded, increment and write a trigger with system.opc.writeValue(). The PLC does the same with another set of variables and a trigger integer. An Ignition tag monitor’s the PLC-\>Ignition trigger for scripted operations, or a transaction group’s trigger points at it. The remaining PLC-\>Ignition data is read after the trigger is detected, either with system.opc.readValues(), or by the transaction group (in OPC Read mode).

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [December 11, 2017, 8:58pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/8 "2017-12-11T20:58:04Z")

</div>

Depending on how much data is being moved, I have:

- **Concatenated the data into a single string** with delimiter of choice (I work a lot with strings, part numbers, serial numbers, etc). Handshake the string back to the PLC then increment the trigger (an integer, like Phil mentioned). The transaction group splits it back out into the individual data points.  
**Advantage** : only one tag to monitor for matches. Generally adaptable across data types. Relatively short time to implement.  
**Disadvantage** : Strings are limited to 255 characters (At least on the AB driver. painful discovery, that one.😒)

- **CRC all your values.** Start with a seed value, shift to the left one bit, XOR in value, shift, XOR, shift, XOR, rinse, repeat. Handshake on the CRC  
**Advantage** : only one tag to monitor for handshake. Adaptable for different data types.  
**Disadvantage** : Long time and more difficult to implement. Especially on the PLC side of things

Been thinking on a simple hash system, but alas, unlike the song by the Stones, time is not on my side.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 11, 2017, 9:01pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/9 "2017-12-11T21:01:34Z")

</div>

> [@JordanCClark](#):
>
> I work a lot with strings

Masochist, eh? But who am I to talk -- my primary laptop runs [gentoo](https://www.gentoo.org/). (-:

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [December 11, 2017, 9:02pm UTC](https://forum.inductiveautomation.com/t/opc-questions-differences-between-opc-readvalue-and-tag-read/16277/10 "2017-12-11T21:02:42Z")

</div>

> [@pturmel](#):
>
> Masochist, eh? But who am I to talk -- my primary laptop runs gentoo. (-:

Traceability is a harsh mistress...
