我正在尝试通过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或类似的东西,但我认为这对桌面应用程序来说太过分了。没有Actors,有没有办法做到这一点?也许我正在读串口错误的响应?
TL; DR:我想通过RxTx对串行设备进行多次查询而不锁定整个应用程序(当前解决方案通过Thread.sleep
实现,这会阻止整个应用程序)。我怎么能这样做?