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

时间:2015-07-28 13:30:18

标签: java serial-port at-command jssc

我试图通过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

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

2 个答案:

答案 0 :(得分:1)

Busy waiting like while (!isReceived) {} will yield horrible performance so if keeping that structure you should change the variable from a boolean to a mutex/semaphore or something similar. But you should not keep it, so I mention this just for reference.


Start by fetching a copy of the V.250 modem standard and read at least all of chapter 5. That will teach you a lot of basic AT command handling, like for instance that an AT command line should be terminated with \r.

The AT^SCFG command is obviously a proprietary manufacturer specific command so I do not have a documentation reference for that. Most mobile phone related AT commands standardized by 3GPP are given in 27.007, although some (SMS related) are given in 27.005

As mentioned at the beginning the structure needs to be changed. You should never, never, never, ever use waitTime, sleep or anything similar to wait for response from a modem. It's as useful as kicking dogs that stand in your way in order to get them to move. Yes you might be lucky and have it actually work sometimes, but at some point you will be sorry for taking that approach...

The only reliably approach is to do something similar to

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();

where the readLine function reads one and one byte from the serial port until it has received a complete line terminated with \r\n and then returns that line.

You can look at the code for atinout for an example for the is_final_result_code function (you can also compare to isFinalResponseError and isFinalResponseSuccess in ST-Ericsson's U300 RIL, although note that CONNECT is not a final result code, it is an intermediate result code, so the name isFinalResponseSuccess is strictly speaking not 100% correct).


The issue with the command send being received back is related to the modem echoing the command. This can be disabled with the ATE command but with a proper parsing structure like above this normally does not matter because you just read the echoed command as a line that will be ignored.

答案 1 :(得分:0)

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

  • 使用waitTime(System.currentTimeMillis(), 2000);
  • 替换事件监听器中的if ( serialPortEvent.isRXCHAR() ) { ...
  • 确保正确终止AT命令;通常在每个命令字符串的末尾都需要换行和/或回车。查看设备的文档。
  • 如果要在不同的主题之间共享,请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();
  }
}