I'm trying to figure out if anyone of you has experienced this behavior of Ignition OPC server when used to serve items to 3rd party applications.
Let me first describe the environment I am currently testing: I have a Siemens PLC connected to Ignition through Kepserver. The entire communication is based on OPC UA so PLC -> Kepware is OPC UA and (of course) Kepware -> Ignition is OPC UA.
Ignition is subscribed to several items offered by PLC which some of them are strings that contains null values. Both Kepserver and Ignition recognize the datatype and Ignition shows "null" in the data value.
Now, for certain data manipulation purposes, I need to expose a Tag Provider from Ignition to another application (another Kepserver in this case). The tag provider contains a Reference tag to a PLC tag configured in another Ignition Tag Provider and the string contains a null value.
With my surprise, when I tried to read that exposed tag via UAExpert from the connected Kepserver I got a Bad status when the data value was "none". Then I tried to connect to Ignition OPC Server with UAExpert and that I got a Good quality but data type and value "null".
I tried to dig a bit more in order to understand why "null" value exposed by PLC was properly interpreted by the first Kepserver and was not properly read by the Kepserver connected to Ignition, so I fired up my Wireshark and analyzed both traffic streams and I discovered this:
PLC always report in the PublishResponse message the Value field under MonitoredItemNotification that contains an empty string and proper data type (String) so, even if the string is null, a proper notification is sent by PLC to Kepware.
Ignition does not report Value field when Tag is "null" and that is causing issues with Kepserver that (probabily by design) report Bad quality since the reported MonitoredItemNotification does not contains Value and Data Type.
Now the question is: that behavior of Ignition OPC Server is valid and simply Kepserver is doing wrong or Ignition should behave like PLC so reporting Value filed in the MonitoredItemNotification even if the content of a Tag is "null"?
Does anybody has encountered the same issue?
Here's a snippet of PLC response and Ignition response for the same tag:
Ignition (Value Field is missing)
And the same variable read with UAExpert from Ignition
Is that second Wireshark picture traffic between Ignition Client and Kepware Server or Kepware Client and Ignition Server?
Also if you can share the captures that would be useful because I can’t tell from the screenshot if the PLC is returning a null string or empty string from just that screenshot. The difference would be in whether it indicates the length is -1 or 0.
the second wireshark is the traffic between Kepserver (or UAExpert) and Ignition and the first is the traffic between PLC (S7-1500) and Kepserver. In Ignition the PLC tag states "null" as value as well as in UAExpert if connected to the Kepserver facing towards PLC but reports the correct Datatype (String). If UAExpert is then connected to Ignition UA Server then it displays null value and null datatype.
The full data pipeline is this:
S7-1500 -> Kepserver UA Client/Server --> Ignition UA Client/Server -> Kepserver UA Client/Server
I'll share Wireshark captures ASAP.
I still need to look into this more closely, but I think it's just some nuance in how null values be encoded.
At some point the type information is lost, but there's no reason that Kepware should be applying bad quality to the value it receives from Ignition. What you're seeing there is the encoding of a DataValue with a null Variant and a Good quality.
It's not exactly like this, but conceptually in code it might be something like the difference between:
Variant v = new Variant((String) null);
Variant v = new Variant(null);
They're both null values. One still carries type information, the other doesn't. When you go system to system at some point the type information encoded in the Variant itself is lost, but it shouldn't matter for a null Value.
here's the captures. I guess it's how Kepserver handles missing Variant information as UaExpert, for example, doesn't report Data Type if missing but properly report Quality thus it allows me to write to the tag.
In contrast if I put Kepware in the middle, between UaExpert and Ignition, Kepserver itself do its own interpretation and translating the Quality attribute to Bad when Variant is null.
Anyhow seems that Ignition doesn't report Variant when Tag value is null (tested also with a String Memory tag).
In the data capture I did this sequence of actions:
- Subscribed and Ingition Reference tag in UaExpert (the tag refers to another OPC Tag)
- Write value "1" to the tag from UaExpert
- Write "" (empty) to the tag from UaExpert
Actions are fond at these wireshark frames:
In file Kepserver to PLC (communication between PLC and Kepserver OPC Client)
- Frame 47: WriteRequest to PLC - Writing value "1"
- Frame 56: PublishResponse from PLC - Data change notification containing the new value ("1")
- Frame 67: WriteRequest to PLC - Writing vale "" (empty)
- Frame 73: PublishResponse from PLC - Data change notification containing the new value ("OpcUa Empty String")
In file UaExpert to Ignition (communication between UaExpert and Ignition UA Server)
- Frame 231: WriteRequest to Ignition - Writing value "1"
- Frame 241: PublishResponse from Ignition - Data change notification containing the new value ("1")
- Frame 253: WriteRequest to Ignition - Writing vale "" (empty)
- Frame 257: PublishResponse from Ignition - Data change notification without Variant
UaExpert to Ignition.pcapng (133.1 KB)
Kepserver to PLC.pcapng (15.5 KB)
Yeah, I was able to reproduce/verify this as well.
There is nothing wrong with what Ignition is doing, and nothing I can change. Kepware shouldn't be applying a bad quality to this value.
The Variant is only "missing" in Wireshark because the OPC UA encoding of DataValue omits null Variant as an optimization. It is implied to be null when not explicitly encoded. The same thing with StatusCode - implied to be Good when not explicitly encoded, which you can see UaExpert is correctly reporting.
Thanks Kevin for the clear answer! I got the point and I was suspecting the same.
I'll address the issue to PTC support.
It might be best to try and avoid using null values as part of whatever you're designing, if possible.
It seems to be working as expected here, but Ignition's handling of null values can be a little wonky. I think you might find that trying to write a null value to a Node in the Ignition OPC UA server isn't possible. Ignition's tag system was originally built around the idea a tag value would never be null, and that expectation changed over time, but there's still a lot of corner cases that don't work right.
Agree with that, but seems that null value is related to how S7 OPC UA reports empty strings (Variant Type: String and String: [OpcUa Null String])
I did further tests and I just want a confirmation from your side: looking at how Siemens send a "" (blank string) value the packed contain Value String: [OpcUa Empty String] that doesn't represent a Null value but an empty string instead (am I wrong?). So why Ignition translate it into null value rather than an empty string?
Also UaExpert read it as empty string
When I connect directly to the Siemens OPC UA server, create a tag for the empty string, and then connect another OPC UA client to Ignition's server to read the Exposed Tag, it remains an empty string; it does not become null.
Siemens S7-1500 <--> Ignition OPC UA Client <--> Ignition Tag <--> Ignition OPC UA Server <--> Other UA Client
Is it possible Kepware is turning it into a null string in your case?
Oh my goodness....that's Kepserver
Here's how PLC answer:
And here's Kepserver:
Thanks again Kevin.