我正在尝试通过 RxTx一次向设备(汽车的 ECU,特别是ELM327 )发送多个查询。这是使用 RxTx 的类:
import collection.JavaConversions._
import gnu.io._
import java.io._
import java.util.TooManyListenersException
class Serial private (portName: String,
baudRate: Int,
dataBits: Int,
stopBits: Int,
parity: Int,
flowControl: Int) {
private val portId = CommPortIdentifier.getPortIdentifier(portName)
private val serial = portId.open("Serial Connection from OBDScan",
5000).asInstanceOf[SerialPort]
setPortParameters(baudRate, dataBits, stopBits, parity, flowControl)
private val istream = serial.getInputStream
private val ostream = serial.getOutputStream
def this(portName: String, baudRate: Int = 115200) = this(portName, baudRate,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE,
SerialPort.FLOWCONTROL_NONE)
def close = {
try {
istream.close
ostream.close
} catch {
case ioe: IOException => // don't care, it's ended already
}
serial.close
}
def query(command: String) = {
ostream.write(command.getBytes)
ostream.write("\r\n".getBytes) // neccessary for Serial port.
}
def queryResult: String = {
try {
val availableBytes = istream.available
val buffer = new Array[Byte](availableBytes)
if (availableBytes > 0) {
istream.read(buffer, 0, availableBytes)
}
new String(buffer, 0, availableBytes)
} catch {
case ioe: IOException => "Something wrong! Please try again."
}
}
def addListener(listener: SerialPortEventListener) = {
try {
serial.addEventListener(listener)
serial.notifyOnDataAvailable(true)
} catch {
case tm: TooManyListenersException => println("Too many listener")
}
}
def removeListener = {
serial.removeEventListener
}
private def setPortParameters(br: Int,
db: Int,
sb: Int,
p: Int,
fc: Int) = {
serial.setSerialPortParams(baudRate, dataBits, stopBits, parity)
serial.setFlowControlMode(flowControl)
}
}
object Serial {
def connect(portName: String, baudRate: Int = 115200): Serial = {
try {
val ret = new Serial(portName, baudRate)
ret
} catch {
// exception handling omitted.
}
}
}
现在查询工作正常并给我正确的结果。当我一次发送多个查询时,问题就来了:
val serial = Serial.connect("COM34")
serial.query("AT Z")
serial.query("10 00")
设备收到了两个查询,但只返回一个结果。如果我想获得下一个结果,我必须发送另一个查询,这将导致程序延迟一个查询。如果我Thread.sleep
在每次查询后调用:
val serial = Serial.connect("COM34")
serial.query("AT Z")
Thread.sleep(500)
serial.query("10 00")
问题解决了,当然整个应用程序在Thread.sleep
被调用时都会停止。我不希望这样,因为应用程序会一直执行此查询(这意味着如果我这样做,它将一直挂起)。
由于我在 Scala 上,我正在考虑使用 Actors 或类似的东西,但我认为这对于桌面应用程序来说太过分了。没有演员有没有办法做到这一点?也许我读错了串口的响应?
TL;DR:我想通过 RxTx 对串行设备进行几次查询,而不锁定整个应用程序(当前的解决方案是通过 实现Thread.sleep
的,这会阻止整个应用程序)。我怎样才能做到这一点?