Serial module error failed to open port

Hi everyone!

I’ve been getting an error when executing a script from the gateway but not when I do it from the console.

I’m also able to call the function in the gateway from the script console and it works. So, I’m not sure why the gateway is unable to open the port. “java.io.IOException: failed to open port: COM8”

Java error

com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File “”, line 7, in File “”, line 165, in TimedMessages File “”, line 32, in sendManyMsgManyNumbers at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.openSerialPort(SerialScriptModule.java:258) at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule$PortManager.(SerialScriptModule.java:209) at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.port(SerialScriptModule.java:201) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.io.IOException: java.io.IOException: failed to open port: COM8

at org.python.core.Py.JavaError(Py.java:547)

at org.python.core.Py.JavaError(Py.java:538)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:192)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:208)

at org.python.core.PyObject.call(PyObject.java:400)

at org.python.pycode._pyx511.sendManyMsgManyNumbers$3(:42)

at org.python.pycode._pyx511.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:168)

at org.python.core.PyFunction.call(PyFunction.java:437)

at org.python.pycode._pyx508.TimedMessages$8(:166)

at org.python.pycode._pyx508.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:134)

at org.python.core.PyFunction.call(PyFunction.java:416)

at org.python.pycode._pyx510.f$0(:10)

at org.python.pycode._pyx510.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyCode.call(PyCode.java:18)

at org.python.core.Py.runCode(Py.java:1687)

at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:796)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runCode(ProjectScriptLifecycle.java:819)

at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:748)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runCode(ProjectScriptLifecycle.java:800)

at com.inductiveautomation.ignition.common.script.TimerScriptTask.run(TimerScriptTask.java:90)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)

at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)

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)

Caused by: org.python.core.PyException: java.io.IOException: java.io.IOException: failed to open port: COM8

… 31 common frames omitted

Caused by: java.io.IOException: failed to open port: COM8

at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.openSerialPort(SerialScriptModule.java:258)

at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule$PortManager.(SerialScriptModule.java:209)

at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.port(SerialScriptModule.java:201)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:190)

Does the Script Hint Scope have something to do with it?
image

When you run it in the script console, it opens the com port on the designer machine. When run in a gateway event, it opens a com port on the gateway machine.

The hInt scope doesn’t actually change the scope you are running, just what help you see.

Script console and designer are on the same machine.

Some weeks ago I did notice that there is a difference on available resources when using local/remote gateway vs local/local gateway. So, in this case my designer and my gateway are on a local machine.

Edit #1:
I’m using TeamViewer to connect to that server but I don’t think that changes anything as I’m running designer and Script Console on that machine. If I were to run Script Console on my computer using a VPN to the Gateway, that would be different scenario. It would be a “local computer to a remote gateway” case.

The same machine, but not necessarily running as the same user according to the OS. The gateway will, unless you have changed things, be authenticating (assuming Windows) as the LOCAL_SYSTEM account, which has various limitations. One of those might be COM port access; I don’t know offhand.

Maybe Windows doesn’t recognize me as a local user but I can point out that when I’m calling the function from the script console it works but when another function in the gateway calls the function it doesn’t. Functions in the gateway won’t check who is logged in as its supposed to work on its own.

I will make a dummy function in the gateway that calls the other function that uses the serial port. Maybe that helps to nail the error

Ignition isn’t checking anything. Ignition is just making the attempt from whatever OS process is executing your script. In the script console, that’s the local designer instance, which is running “as you” (per the OS). When you execute a script in Perspective, or from a tag, or anywhere else on the gateway, the COM port invocation is happening from the gateway’s process. Your OS is rejecting the attempt to open the COM port when the request is coming from the gateway process.

2 Likes

This is simply not correct. The gateway service runs as a specific user, too. LOCAL_SYSTEM by default for Windows.

I’ll supplement one other thought here as well, for your consideration. You could also experience a failure to acquire a given port if it is in use by another process (i.e. if it is locked by designer).

That is good to know. This is an old server so all the configuration over the years was done by several other people.

Ok, so Script Console runs as a local designer instance and all the rest on the gateway's process.

That is not something I think of when I'm scripting in the gateway. I guess I should consider that now since I'm using a device connected to the computer.

My engineering PC has Windows 10 and it just worked, this old server is 2012 R2. Some security/permission settings may be different.

I would drop that as a possibility since it's a new device that only Ignition is accessing. Also, I'm using with functions which will open and close the port automatically.

Edit #1:
Maybe a custom and permanent filter in Windows Event log will help me here. Has anyone created a good filter to debug every case on Ignition?

Actually, the with handler for the serial functions is/was broken. I don't recall what version fixed it, if fixed yet at all. Note that re-opening a port imposes a substantial delay (~100ms) where you can lose characters.

Meanwhile, consider not running the designer on the same computer as the gateway. If you are writing code for gateway scope, test it with a message handler that you can call from the script console (via system.util.sendRequest), don't run it directly in the script console.

Catch your exceptions in the message handler and stringify them (with backtrace) to return to the caller.

1 Like

I did some testing today.

In Gateway Message Handlers I added a “Test” function:

def handleMessage(payload):
	import traceback
	import java.lang.Exception
	print 'Error test'
	errorDict = {}
	try:
		AT.OpenComPort('COM8')
		
	except Exception, e:
		errorDict['jython'] = str(e)
	except java.lang.Exception, e:
		errorDict['java'] = str(e)
		errorDict['javaCause'] = str(e.getCause())
	return errorDict

Using the script console in another computer:

returnValue = system.util.sendRequest(project='TestProject', messageHandler='Test', payload={'hoursOn':15})
print returnValue

My results are:

{'javaCause': 'None', 'java': 'java.io.IOException: failed to open port: COM8'}

Basically the same error but at the same time I think it’s a confirmation that java is being blocked when trying to open a port.

1 Like