При запросе com-порт возвращает тот же запрос
Я пытаюсь отправить AT-команду через COM-порт, но получаю только ту же команду.
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 -Отправить запрос: AT ^ SCFG?
16: 19: 23.976 [EventThread COM55] DEBUG SerialConnections.M234Serial - Получено сообщение: AT ^ SCFG?
16: 19: 23.977 [main] DEBUG SerialConnections.M234Serial - Конец
Что я делаю не так и как я могу это исправить?
2 ответа
Ожидание в ожидании while (!isReceived) {}
даст ужасную производительность, поэтому, если сохранить эту структуру, вы должны изменить переменную с логического на мьютекс / семафор или что-то подобное. Но вы не должны держать это, поэтому я упоминаю это только для справки.
Начните с извлечения копии стандарта модема V.250 и прочитайте, по крайней мере, всю главу 5. Это научит вас основам обработки AT-команд, например, что командная строка AT должна заканчиваться на \r
,
Команда AT^SCFG, очевидно, является проприетарной командой производителя, поэтому у меня нет ссылки на документацию по этому вопросу. Большинство связанных с мобильным телефоном AT-команд, стандартизированных 3GPP, дано в 27.007, хотя некоторые (связанные с SMS) даны в 27.005.
Как уже упоминалось в начале, структура должна быть изменена. Вы никогда не должны, никогда, никогда, никогда не используйте waitTime
, sleep
или что-нибудь подобное, чтобы ждать ответа от модема. Это так же полезно, как пинать собак, которые стоят на вашем пути, чтобы заставить их двигаться. Да, возможно, вам повезло, и иногда это действительно работает, но в какой-то момент вы пожалеете, что воспользовались этим подходом...
Единственный надежный подход - сделать что-то похожее на
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
функция (вы также можете сравнить с isFinalResponseError
а также isFinalResponseSuccess
в U300 RIL ST-Ericsson, хотя обратите внимание, что CONNECT
это не окончательный код результата, это промежуточный код результата, поэтому имя isFinalResponseSuccess, строго говоря, не на 100% правильно).
Проблема с отправкой команды, получаемой назад, связана с модемом, повторяющим команду. Это можно отключить с помощью ATE
команда, но с правильной структурой синтаксического анализа, подобной описанной выше, обычно это не имеет значения, потому что вы просто читаете echoed команду как строку, которая будет игнорироваться
Я предлагаю следующие улучшения вашего кода:
- замещать
waitTime(System.currentTimeMillis(), 2000);
в слушателе событий сif ( serialPortEvent.isRXCHAR() ) { ...
- Убедитесь, что вы правильно завершили AT-команду; обычно в конце каждой командной строки требуется перевод строки и / или возврат каретки. Проверьте документацию вашего устройства.
- Делать
isReceived
летучий, т.е.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();
}
}