system.opc.readValue config error

I am trying to test the OPC scripting function to read a tag. I enabled “Anonymous Access” in the OPC UA server settings, all my project tags are visible in the OPC UA tag browser. I copied the tag path of one of the tags and tried to read its value with the following code copied from the scripting examples, which is called in gateway startup script.

def opctest():
	server = "Ignition OPC-UA Server"
	path = "ns=2;s=[default]/Tag 0"
	qualifiedValue = system.opc.readValue(server, path)
	print "Value: " + str(qualifiedValue.getValue())
	print "Quality: " + qualifiedValue.getQuality().toString()
	print "Timestamp: " + qualifiedValue.getTimestamp().toString()

I get error-

INFO   | jvm 1    | 2020/05/20 22:13:27 | Value: None
INFO   | jvm 1    | 2020/05/20 22:13:27 | Quality: Error_Configuration
INFO   | jvm 1    | 2020/05/20 22:13:27 | Timestamp: Sat May 16 21:53:21 IST 2020

What could be going wrong? I have the gateway server running, not in freeze.

It’s probably because you copied the tag path instead of the OPC Item Path.

I got the problem! Its is the server name “Ignition OPC-UA Server” given in the code snippet of the script function, should not have a hyphen, it should be “Ignition OPC UA Server”! That’s something in the documentation of scripting function to be changed by you guys at IA! The code snippet contains a hyphen in the server name where as the actual OPC UA server name (atleast in version 8) doesn’t have a hyphen! its working fine with that change.

INFO   | jvm 1    | 2020/05/20 23:07:08 | Value: 50.0
INFO   | jvm 1    | 2020/05/20 23:07:08 | Quality: Good
INFO   | jvm 1    | 2020/05/20 23:07:08 | Timestamp: Wed May 20 23:07:08 IST 2020

the code is:

def opctest():
	server = "Ignition OPC UA Server"
	path = "ns=2;s=[default]/Tag 0"
	qualifiedValue = system.opc.readValue(server, path)
	print "Value: " + str(qualifiedValue.getValue())
	print "Quality: " + qualifiedValue.getQuality().toString()
	print "Timestamp: " + qualifiedValue.getTimestamp().toString()

Please notice, the earlier code (copied from the code snippet), had a hyphen in the server name.

Yeah… I guess we could update that snippet, but then if your system was an upgrade it would be wrong because upgrades still have the hyphen in the name.

Removing that hyphen in the name of the default/loopback OPC UA connection on new installs of 8 was an unfortunate mistake that didn’t get caught before Ignition 8 was released.

Oh, that’s ok then.

Another strange thing I found , I just tried to increment the value by one and write back to tag and print it. I find the value is not incremented, though , it changes in Tag DB eventually ! So there is a delay . Is it due to write being async!

code is :

def opctest():
	server = "Ignition OPC UA Server"
	path = "ns=2;s=[default]/Tag 0"
	qualifiedValue = system.opc.readValue(server, path)
	print "Value: " + str(qualifiedValue.getValue())
	print "Quality: " + qualifiedValue.getQuality().toString()
	print "Timestamp: " + qualifiedValue.getTimestamp().toString()
	

	oldQualifiedValue = system.opc.readValue(server, path)
	newValue = oldQualifiedValue.getValue() + 1
	returnQuality = system.opc.writeValue(server, path, newValue)
	if returnQuality.isGood():
		print "Write was successful"
		print "Value: " + str(qualifiedValue.getValue())
		print "Quality: " + qualifiedValue.getQuality().toString()
		print "Timestamp: " + qualifiedValue.getTimestamp().toString()
	else:
		print "Write failed"

Output is-

INFO   | jvm 1    | 2020/05/20 23:21:41 | Value: 51.0
INFO   | jvm 1    | 2020/05/20 23:21:41 | Quality: Good
INFO   | jvm 1    | 2020/05/20 23:21:41 | Timestamp: Wed May 20 23:21:41 IST 2020
INFO   | jvm 1    | 2020/05/20 23:21:41 | Write was successful
INFO   | jvm 1    | 2020/05/20 23:21:41 | Value: 51.0
INFO   | jvm 1    | 2020/05/20 23:21:41 | Quality: Good
INFO   | jvm 1    | 2020/05/20 23:21:41 | Timestamp: Wed May 20 23:21:41 IST 2020

You’re not reading the value back at any point after you write it. The QualifiedValue object is never going to change or update.

Oh silly me! It works with reading new value after write

def opctest():
	server = "Ignition OPC UA Server"
	path = "ns=2;s=[default]/Tag 0"
	qualifiedValue = system.opc.readValue(server, path)
	print "Value: " + str(qualifiedValue.getValue())
	print "Quality: " + qualifiedValue.getQuality().toString()
	print "Timestamp: " + qualifiedValue.getTimestamp().toString()
	

	oldQualifiedValue = system.opc.readValue(server, path)
	newValue = oldQualifiedValue.getValue() + 1
	returnQuality = system.opc.writeValue(server, path, newValue)
	qualifiedValue = system.opc.readValue(server, path)
	if returnQuality.isGood():
		print "Write was successful"
		print "Value: " + str(qualifiedValue.getValue())
		print "Quality: " + qualifiedValue.getQuality().toString()
		print "Timestamp: " + qualifiedValue.getTimestamp().toString()
	else:
		print "Write failed"

output is-

INFO   | jvm 1    | 2020/05/20 23:33:18 | Value: 52.0
INFO   | jvm 1    | 2020/05/20 23:33:18 | Quality: Good
INFO   | jvm 1    | 2020/05/20 23:33:18 | Timestamp: Wed May 20 23:33:18 IST 2020
INFO   | jvm 1    | 2020/05/20 23:33:18 | Write was successful
INFO   | jvm 1    | 2020/05/20 23:33:18 | Value: 53.0
INFO   | jvm 1    | 2020/05/20 23:33:18 | Quality: Good
INFO   | jvm 1    | 2020/05/20 23:33:18 | Timestamp: Wed May 20 23:33:18 IST 2020

I have a few more questions -

  1. Does the Ignition OPC UA server provide the subscription function ? Why is it not supported in the scripting library?
  2. Are all the client methods defined in the spec for client classes implemented in the server?
  3. Is there any sample client code available in java or any other language like python for reference?
  1. Does the Ignition OPC UA server provide the subscription function ? Why is it not supported in the scripting library?

Yes, but there’s not really a compelling reason to make it available via scripting. Most scripts don’t have an appropriate lifecycle to create a monitored item and delete it when they are done, and if you want a continually updated value you can already just access an OPC tag from scripting.

  1. Are all the client methods defined in the spec for client classes implemented in the server?

The spec defines services. The server implements the required ones for the “Standard UA Server” profile.

  1. Is there any sample client code available in java or any other language like python for reference?

Not really sure what you’re asking for here. Sample client code to talk an OPC UA server outside of Ignition?

Makes sense! Its useful only for external applications

Got it. Thanks.

Exactly! Something in java or python , so that we can use code snippets from it!.

Use them where? You can’t use it in Ignition so I’m not sure what the purpose would be.

In our modules for ignition.

Only a driver module would have any kind of access to OPC UA APIs, and even then it’s only the server API.

No our external applications will access the Ignition opc ua server thru the services to browse its address space, subscribe to events, tags etc.

Then your external applications are presumably using some kind of OPC UA toolkit or SDK and you should find code examples that are specific to that SDK.

Ok, that’s what I was also thinking about. I did see the prosys sdk some time back for examples. However you had mentioned on the forum or LinkedIn some python based library. I think it would also be a good reference.

While trying to connect to Ignition OPC UA server with py commands “client=Client(“opc.tcp://127.0.0.1:62541”)” and “client.connect()” on localhost, I get following error:

ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it

The Ignition server is running on local mode. What could be the problem.

Does it work if you use “localhost” instead of 127.0.0.1? Is the Ignition loopback connection good?

No, the same error

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python38\lib\site-packages\opcua\client\client.py", line 272, in connect
    self.connect_socket()
  File "C:\Python38\lib\site-packages\opcua\client\client.py", line 297, in connect_socket
    self.uaclient.connect_socket(self.server_url.hostname, self.server_url.port)
  File "C:\Python38\lib\site-packages\opcua\client\ua_client.py", line 256, in connect_socket
    return self._uasocket.connect_socket(host, port)
  File "C:\Python38\lib\site-packages\opcua\client\ua_client.py", line 155, in connect_socket
    sock = socket.create_connection((host, port), timeout=self.timeout)
  File "C:\Python38\lib\socket.py", line 808, in create_connection
    raise err
  File "C:\Python38\lib\socket.py", line 796, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it