Datagram via serial in jython HEX bytes problem

Hi!

I want to send following datagram via the serial binding in jython:

oh.sendCommand("PhotovoltaicSerial",  "QPIWS" + "\x96\xA7\x0D")

The problem is that tha wrong charset is used. In the log file it looks like:

QPIWS??

So instead of the hex values I converts to “?” because its higher than 128.

I changed the charset at init to utf8:

def __init__(self):
        reload(sys)
        sys.setdefaultencoding('utf8')

Thats not a good way, but I have no idea what I can do instead.
The main problem is also, that it doesnt work after a reboot.
I must restart openhab after every reboot to work correctly because the charset is not changed.

Any ideas ?

kind regards
Martin

Is this just a logging issue or are the wrong bytes being sent to the serial port?

The wrong string is also send out the serial port.
There are also thrown some exceptions when a string is receveived with some higher hex values in it.

I think this is a Java issue and not specific to Jython. It’s generally not possible to use a java.util.String to store arbitrary binary data. There are too many Unicode encoding/decoding issues. Commands are sent through the openHAB event bus as java.util.Strings and converted to bytes in the binding using the platform encoding. For your purposes, it would be good if openHAB supported a byte array or stream command for communicating non-textual data. However, as far as I know, it does not.

Is there a possibility to use something like PySerial to communicate directly?
I do that allready with UDP, but I have absolutely no idea how I can integrate serial communication directly into Jython…

You could directly use a Java library that provides the Java Communication API extensions. OpenHAB uses nrjavaserial-3.9.3.jar. Pyserial supports Jython but you need the Java extension anyway.

You can experiment with…

import sys
# This is the JAR location in my installation.
sys.path.append("server/configuration/org.eclipse.osgi/bundles/202/1/.cp/lib/nrjavaserial-3.9.3.jar")
from gnu.io import SerialPort, CommPortIdentifier

Look at the openHAB code for SerialDevice.java to see how to use the Java Communiations API classes. The javadocs are at:

http://docs.oracle.com/cd/E17802_01/products/products/javacomm/reference/api/javax/comm/package-summary.html).

I’d be interested in hearing if you get this working. Sending binary data to a serial port seems like a useful capability.

Thx for the tipp.
It works!
I can send strings with with hex bytes included and I can receive data.
BUT! I have absolutely no idea how the events ar working.
Here is my testcode.

import sys
import time

sys.path.append("/usr/share/openhab/serialtest/nrjavaserial-3.10.0.jar")
from gnu.io import SerialPort, CommPortIdentifier


class PvSerial(Rule):
    def __init__(self):
        port = "/dev/ttyUSB11"
        Baudrate = 2400
        tryCounter = 0

        try:
            while True:
                PortId = None
                portList = CommPortIdentifier.getPortIdentifiers()
                while portList.hasMoreElements():
                    ActPortId = portList.nextElement()

                    if str(ActPortId.getPortType()) == str(CommPortIdentifier.PORT_SERIAL):
                        if ActPortId.getName() == port:
                            oh.logError("PvSerial", "Port found: " + str(ActPortId.getName()))
                            PortId = ActPortId
                            break

                if PortId is not None:
                    break

                time.sleep(2)
                tryCounter += 1
                if tryCounter > 7:
                    break

            if PortId is not None:
                self.PvSerialPort = PortId.open("openhab", 1000)
                inputStream = self.PvSerialPort.getInputStream()
                self.PvSerialPort.notifyOnDataAvailable(True)
                self.PvSerialPort.setSerialPortParams(Baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE)
                self.PvSerialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE)
                self.PvSerialPort.enableReceiveTimeout(500)

                self.PvSerialPort.addEventListener(self.serialEvent)

                outputStream = self.PvSerialPort.getOutputStream()

                oh.logError("PvSerial", "up and running")
                sendstring = "QPIGS\xB7\xA9\x0D"
                outputStream.write(sendstring)
                outputStream.flush()

                oh.logError("PvSerial", "data send " + sendstring)

                tryCounter = 0

                while inputStream.available() == 0:
                    time.sleep(1)
                    tryCounter += 1
                    if tryCounter > 5:
                        break

                oh.logError("PvSerial", "inputStream while fin")

                readBuffer = ""
                byteCnt = 0
                while inputStream.available() > 0:
                    readBuffer += chr(inputStream.read())
                    byteCnt += 1

                if byteCnt > 0:
                    oh.logError("PvSerial", " Avail " + str(byteCnt) + " " + readBuffer)
  
        except Exception, e:
            oh.logError("PvSerial", "exception: " + str(e))

    def serialEvent(SerialPortEvent):
        oh.logError("PvSerial", "serialEvent")

    def __del__(self):
        oh.logError("PvSerial", "del")
        try:
            self.PvSerialPort.close()
        except Exception, e:
            pass

Some ideas?