1

我正在尝试通过 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的,这会阻止整个应用程序)。我怎样才能做到这一点?

4

0 回答 0