请求com端口时返回相同的请求

我试图通过COM端口发送AT命令,但只重新发送相同的命令。

package SerialConnections; import jssc.SerialPort; import jssc.SerialPortEvent; import jssc.SerialPortEventListener; import jssc.SerialPortException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static ru.telemetria.qa.utils.Utilities.waitTime; public class M234Serial { private static Logger log = LoggerFactory.getLogger(M234Serial.class); private SerialPort serialPort; private byte[] receivedData; private boolean isReceived; public M234Serial() throws Exception { serialPort = new SerialPort("COM55"); } public void sendCommand() throws Exception { open(); String command = "AT^SCFG?"; serialPort.writeBytes(command.getBytes()); log.debug("Send request: " + command); while (!isReceived) {} close(); } private void open() throws Exception { serialPort.openPort(); serialPort.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.addEventListener(new SerialPortEventListener() { @Override public void serialEvent(SerialPortEvent serialPortEvent) { try { waitTime(System.currentTimeMillis(), 2000); receivedData = serialPort.readBytes(); log.debug("Received message: " + StringUtils.asciiToString(receivedData)); isReceived = true; serialPort.removeEventListener(); } catch (SerialPortException spe) { spe.printStackTrace(); } } }); } private void close() throws Exception { serialPort.closePort(); } public static void main(String[] args) throws Exception { log.debug("Create instance.."); M234Serial serial = new M234Serial(); serial.sendCommand(); log.debug("End"); } } 

日志:

16:19:21.910 [main] DEBUG SerialConnections.M234Serial – 创建实例..

16:19:21.974 [main] DEBUG SerialConnections.M234Serial -Send request:AT ^ SCFG?

16:19:23.976 [EventThread COM55] DEBUG SerialConnections.M234Serial – 收到的消息:AT ^ SCFG?

16:19:23.977 [main] DEBUG SerialConnections.M234Serial – End

我做错了什么,我该如何解决?

while (!isReceived) {}那样繁忙的等待将产生可怕的性能,因此如果保持该结构,您应该将变量从布尔值更改为互斥量/信号量或类似的东西。 但你不应该保留它,所以我提到这只是为了参考。


首先获取V.250调制解调器标准的副本并至少读取第5章的所有内容。这将教你很多基本的AT命令处理,例如AT命令行应该用\r终止。

AT ^ SCFG命令显然是专有的制造商特定命令,因此我没有相关的文档参考。 由3GPP标准化的大多数与移动电话相关的AT命令在27.007中给出,尽管在27.005中给出了一些(SMS相关)

如开头所述,结构需要改变。 你永远不应该,永远不会,永远不会使用waitTimesleep或类似的东西来等待调制解调器的响应。 它就像踢狗一样有用,可以阻挡它们移动。 是的,你可能很幸运,有时它确实有效,但在某些时候你会抱歉采取这种方法……

唯一可靠的方法是做类似的事情

 serialPort.openPort(); ... // start sending AT^SCFG? serialPort.writeBytes("AT^SCFG?\r"); do { line = readLine(serialPort); } while (! is_final_result_code(line)) // Sending of AT^SCFG? command finished (successfully or not) ... serialPort.closePort(); 

其中readLine函数从串行端口读取一个和一个字节,直到它收到以\r\n结尾的完整行,然后返回该行。

您可以查看atinout的代码以获取 is_final_result_code函数的示例(您也可以比较ST-Ericsson的U300 RIL中的 isFinalResponseErrorisFinalResponseSuccess ,但请注意CONNECT不是最终结果代码,它是一个中间结果代码,所以名称isFinalResponseSuccess严格来说不是100%正确)。


发送回命令的问题与回显命令的调制解调器有关。 这可以通过ATE命令禁用,但是如上所述具有正确的解析结构通常无关紧要,因为您只是将echoed命令读作将被忽略的行。

我建议您对代码进行以下改进:

  • 替换waitTime(System.currentTimeMillis(), 2000); 在事件监听器中使用if ( serialPortEvent.isRXCHAR() ) { ...
  • 确保正确终止AT命令; 通常在每个命令字符串的末尾都需要换行和/或回车。 查看设备的文档。
  • make isReceived volatile ,即private volatile boolean isReceived; ,如果要在不同的线程之间共享。

为避免繁忙等待,您可以使用标准Java同步原语,如下所示:

 private volatile boolean isReceived; private final Object syncObject = new Object(); // ... private void waitForReceived() { synchronized(syncObject) { while( !isReceived ) { syncObject.wait(); } } } private void signalReceived() { synchronized(syncObject) { isReceived = true; syncObject.notifyAll(); } }