问题
I`m trying to send AT-command via COM-port, but reseived only the same command.
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");
}
}
Log:
16:19:21.910 [main] DEBUG SerialConnections.M234Serial - Create instance..
16:19:21.974 [main] DEBUG SerialConnections.M234Serial -Send request: AT^SCFG?
16:19:23.976 [EventThread COM55] DEBUG SerialConnections.M234Serial - Received message: AT^SCFG?
16:19:23.977 [main] DEBUG SerialConnections.M234Serial - End
What am I doing wrong and how can I fix it?
回答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.
回答2:
I suggest the following improvements to your code:
- Replace
waitTime(System.currentTimeMillis(), 2000);
in the event listener withif ( serialPortEvent.isRXCHAR() ) { ...
- Make sure you terminate your AT command properly; usually a linefeed and/or carriage return is required at the end of each command string. Check the documentation of your device.
- Make
isReceived
volatile, i.e.private volatile boolean isReceived;
, if it is to be shared among different threads.
To avoid busy-waiting you can use standard Java synchronization primitives, like this:
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();
}
}
来源:https://stackoverflow.com/questions/31677801/when-requesting-com-port-returns-the-same-request