При запросе 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();
  }
} 
Другие вопросы по тегам