Hi. I got the following error when I try to call OPC UA method from Gateway script.
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 1, in java.lang.ClassCastException: class org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode cannot be cast to class org.eclipse.milo.opcua.sdk.client.model.nodes.variables.PropertyTypeNode (org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode and org.eclipse.milo.opcua.sdk.client.model.nodes.variables.PropertyTypeNode are in unnamed module of loader com.inductiveautomation.ignition.gateway.modules.ModuleClassLoader @fa6080) at org.eclipse.milo.opcua.sdk.client.nodes.UaNode.lambda$null$15(UaNode.java:1064) at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.thenApply(Unknown Source) at org.eclipse.milo.opcua.sdk.client.nodes.UaNode.lambda$null$16(UaNode.java:1064) at java.base/java.util.Optional.map(Unknown Source) at org.eclipse.milo.opcua.sdk.client.nodes.UaNode.lambda$null$17(UaNode.java:1061) at java.base/java.util.stream.ReferencePipeline$7$1.accept(Unknown Source) at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source) at java.base/java.util.Spliterators$ArraySpliterator.tryAdvance(Unknown Source) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(Unknown Source) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(Unknown Source) at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(Unknown Source) at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source) at java.base/java.util.stream.ReferencePipeline.findFirst(Unknown Source) at org.eclipse.milo.opcua.sdk.client.nodes.UaNode.lambda$getPropertyNodeAsync$18(UaNode.java:1069) at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.postComplete(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.complete(Unknown Source) at org.eclipse.milo.opcua.stack.client.UaStackClient.lambda$deliverResponse$5(UaStackClient.java:318) at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$Task.run(ExecutionQueue.java:119) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) java.lang.ClassCastException: java.lang.ClassCastException: class org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode cannot be cast to class org.eclipse.milo.opcua.sdk.client.model.nodes.variables.PropertyTypeNode (org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode and org.eclipse.milo.opcua.sdk.client.model.nodes.variables.PropertyTypeNode are in unnamed module of loader com.inductiveautomation.ignition.gateway.modules.ModuleClassLoader @fa6080)
I tried to call the same method from UaExpert client and it worked successfully.
I used the following code to create the server and the methods.
import sys
sys.path.insert(0, "..")
import logging
try:
from IPython import embed
except ImportError:
import code
def embed():
vars = globals()
vars.update(locals())
shell = code.InteractiveConsole(vars)
shell.interact()
from opcua import ua, uamethod, Server
# method to be exposed through server
def func(parent, variant):
ret = False
if variant.Value % 2 == 0:
ret = True
return [ua.Variant(ret, ua.VariantType.Boolean)]
# method to be exposed through server
# uses a decorator to automatically convert to and from variants
@uamethod
def multiply(parent, x, y):
print("multiply method call with parameters: ", x, y)
return x * y
if __name__ == "__main__":
# optional: setup logging
logging.basicConfig(level=logging.WARN)
#logger = logging.getLogger("opcua.address_space")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.internal_server")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.binary_server_asyncio")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.uaprocessor")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.subscription_service")
# logger.setLevel(logging.DEBUG)
# now setup our server
server = Server()
#server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
server.set_server_name("FreeOpcUa Example Server")
# setup our own namespace
uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri)
# get Objects node, this is where we should put our custom stuff
objects = server.get_objects_node()
# populating our address space
myfolder = objects.add_folder(idx, "myEmptyFolder")
myobj = objects.add_object(idx, "MyObject")
myvar = myobj.add_variable(idx, "MyVariable", 6.7)
myvar.set_writable() # Set MyVariable to be writable by clients
myarrayvar = myobj.add_variable(idx, "myarrayvar", [6.7, 7.9])
myarrayvar = myobj.add_variable(idx, "myStronglytTypedVariable", ua.Variant([], ua.VariantType.UInt32))
myprop = myobj.add_property(idx, "myproperty", "I am a property")
mymethod = myobj.add_method(idx, "mymethod", func, [ua.VariantType.Int64], [ua.VariantType.Boolean])
inargx = ua.Argument()
inargx.Name = "x"
inargx.DataType = ua.NodeId(ua.ObjectIds.Int64)
inargx.ValueRank = -1
inargx.ArrayDimensions = []
inargx.Description = ua.LocalizedText("First number x")
inargy = ua.Argument()
inargy.Name = "y"
inargy.DataType = ua.NodeId(ua.ObjectIds.Int64)
inargy.ValueRank = -1
inargy.ArrayDimensions = []
inargy.Description = ua.LocalizedText("Second number y")
outarg = ua.Argument()
outarg.Name = "Result"
outarg.DataType = ua.NodeId(ua.ObjectIds.Int64)
outarg.ValueRank = -1
outarg.ArrayDimensions = []
outarg.Description = ua.LocalizedText("Multiplication result")
multiply_node = myobj.add_method(idx, "multiply", multiply, [inargx, inargy], [outarg])
# starting!
server.start()
print("Available loggers are: ", logging.Logger.manager.loggerDict.keys())
try:
embed()
finally:
server.stop()
and the script I used to call the method from Ignition Gateway tag change script is:
system.opcua.callMethod("PyServerMethods", "ns=2;i=2", "ns=2;i=10", [5, 3])