Hi All,
I've been using my best googling skills into getting this working but it evades me. I am trying to open a serial port, write a handful of bytes in hex, listen to the port, then close the port.
I cannot get past writing the bytes. My best guess is I'm having trouble satisfying the java bytearray requirements. This is the code I'm using in the interpreter.
system.serial.configureSerialPort(\
port="COM7",\
bitRate=system.serial.BIT_RATE_9600,\
dataBits=system.serial.DATA_BITS_8,\
handshake=system.serial.HANDSHAKE_NONE,\
hardwareFlowControl=False,\
parity=system.serial.PARITY_NONE,\
stopBits=system.serial.STOP_BITS_1)
system.serial.closeSerialPort("COM7")
system.serial.openSerialPort("COM7")
system.serial.writeBytes("COM7","\xCA\x00\x01\x70\x00\x8E")
system.serial.closeSerialPort("COM7")
Firing the script returns an angry traceback that the serial module trial is expired. Restarting the trial via gateway webpage and relaunching the designer have no effect. Not sure what to do here...
Java Traceback:
Traceback (most recent call last):
File "<input>", line 14, in <module>
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.checkTrialExpired(SerialScriptModule.java:154)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:616)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:599)
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)
com.inductiveautomation.ignition.modules.serial.scripting.TrialExpiredException: com.inductiveautomation.ignition.modules.serial.scripting.TrialExpiredException: Serial module trial period has expired.
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:477)
at org.python.core.PyObject.__call__(PyObject.java:481)
at org.python.pycode._pyx6.f$0(<input>:16)
at org.python.pycode._pyx6.call_function(<input>)
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 org.python.core.Py.exec(Py.java:1731)
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:277)
at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:130)
at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:611)
at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:599)
at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.desktop/javax.swing.SwingWorker.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: com.inductiveautomation.ignition.modules.serial.scripting.TrialExpiredException: Serial module trial period has expired.
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.checkTrialExpired(SerialScriptModule.java:154)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:616)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:599)
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)
... 19 more
Traceback (most recent call last):
File "<input>", line 14, in <module>
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.checkTrialExpired(SerialScriptModule.java:154)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:616)
at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.writeBytes(SerialScriptModule.java:599)
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)
com.inductiveautomation.ignition.modules.serial.scripting.TrialExpiredException: com.inductiveautomation.ignition.modules.serial.scripting.TrialExpiredException: Serial module trial period has expired.
It's because this isn't a byte array. It is a jython string whose codepoints match the bytes you want to send. You need to construct your byte array with jython's jarray module.
(Beware: java byte arrays have signed 8-bit values.)
Dang you are fast.
My apologies for my ignorance. I had a feeling I was murdering the requirements for the array.
Would you be able to walk me through constructing a simple 2-byte array that can handle unsigned values and is a valid argument for system.serial.writeBytes ?
So far I've been taking guidance from these forum posts but am lost as how to construct the array:
https://forum.inductiveautomation.com/t/serial-module-possible-error/5920/11
https://forum.inductiveautomation.com/t/solved-get-nmea-sentence-system-serial/48783
Again, my apologies for the ignorance. Any help is appreciated. Thank you!
unsignedBytes = [0xCA, 0x00, 0x01, 0x70, 0x00, 0x8E]
signedBytes = [((x + 0x80) & 0xff) - 0x80 for x in unsignedBytes]
byteArray = jarray.array(signedBytes, 'b')
Rather than rely on jython math, I usually do this:
import jarray
from java.lang import Long
unsignedBytes = [0xCA, 0x00, 0x01, 0x70, 0x00, 0x8E]
signedBytes = [Long.valueOf(x).byteValue() for x in unsignedBytes]
byteArray = jarray.array(signedBytes, 'b')
This latter implementation will simply chop the upper bits off of whatever you feed it.
Apparently, that no longer works. Jython is turning the Long
back into its own long
. ):
Thanks for the help! That snippet got me off to the races. I'll post more to this topic when my example is more complete... or if I'm completely lost
Thanks again!
Using bytearray you can get the same affect without the '0x' in the strings/values.
msg = '4142'
data = bytearray.fromhex(msg)
print data #should print 'AB'
Hey All,
For anyone watching this thread, these are the commands I ended up using to sign and unsign byte arrays, and pipe those arrays to and from the serial port. Device documentation was all in raw hex so that's the reason for working back and forth. I'm sure there's prettier code out there but this does work.
commands = [
[0xCA, 0x00, 0x01, 0x70, 0x00, 0x8E], # Current Setpoint
[0xCA, 0x00, 0x01, 0x10, 0x00, 0xEE], # Process Flowrate
for command, tag_path in zip(commands, tag_paths):
# Convert unsigned byte array to signed byte array
signedCommandBytes = [((x + 0x80) & 0xff) - 0x80 for x in command]
commandByteArray = jarray.array(signedCommandBytes, 'b')
# Send the message
system.serial.writeBytes("COM7", commandByteArray)
# Receive the reply
chillReply = system.serial.readBytes("COM7", 9)
# The reply is an unsigned array stored as a signed array
# Can't use the jarray function as before though, as it creates overflows
signedReplyBytes = [((x + 0x80) & 0xff) - 0x80 for x in chillReply]
unsignedReplyBytes = bytearray([(byte + 256) % 256 for byte in signedReplyBytes])
packet = unsignedReplyBytes
This snippet was part of a rudimentary driver for Neslab / Thermoflex chillers using "NC protocol". Please drop me a PM if you would like the entire script.