java - Al solicitar el puerto com, se devuelve la misma solicitud
serial-port at-command (2)
Ocupado esperando como
while (!isReceived) {}
producirá un rendimiento horrible, por lo que si mantiene esa estructura, debe cambiar la variable de booleano a mutex / semáforo o algo similar.
Pero no debe guardarlo, así que lo menciono solo como referencia.
Comience buscando una copia del estándar de módem
V.250
y lea al menos todo el capítulo 5. Eso le enseñará una gran cantidad de manejo básico de comandos AT, como por ejemplo que una línea de comandos AT debe terminar con
/r
.
El comando AT ^ SCFG es obviamente un comando específico del fabricante, por lo que no tengo una referencia de documentación para eso. La mayoría de los comandos AT relacionados con teléfonos móviles estandarizados por 3GPP se dan en 27.007 , aunque algunos (relacionados con SMS) se dan en 27.005
Como se mencionó al principio, la estructura necesita ser cambiada.
Nunca, nunca, nunca, nunca
use
waitTime
,
sleep
o algo similar para esperar la respuesta de un módem.
Es tan útil como patear perros que se interponen en tu camino para que se muevan.
Sí, puede ser afortunado y hacer que realmente funcione a veces, pero en algún momento lamentará adoptar ese enfoque ...
El único enfoque confiable es hacer algo similar a
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();
donde la función
readLine
lee uno y un byte del puerto serie hasta que recibe una línea completa terminada con
/r/n
y luego devuelve esa línea.
Puede consultar el código de
atinout
para ver un ejemplo de la función
is_final_result_code
(también puede comparar
isFinalResponseError
e
isFinalResponseSuccess
en
U300 RIL de ST-Ericsson
, aunque tenga en cuenta que
CONNECT
no es un código de resultado final, es un código de resultado intermedio, por lo que el nombre es FinalResponseSuccess es estrictamente hablando no 100% correcto).
El problema con el envío del comando que se devuelve está relacionado con el módem que hace eco del comando.
Esto puede deshabilitarse con el comando
ATE
pero con una estructura de análisis adecuada como la anterior, esto normalmente no importa porque solo lee el comando echo como una línea que se ignorará.
Estoy tratando de enviar el comando AT a través del puerto COM, pero solo recibí el mismo comando.
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");
}
}
Iniciar sesión:
16: 19: 21.910 [main] DEBUG SerialConnections.M234Serial - Crear instancia ..
16: 19: 21.974 [main] DEBUG SerialConnections.M234Serial -Enviar solicitud: AT ^ SCFG?
16: 19: 23.976 [EventThread COM55] DEBUG SerialConnections.M234Serial - Mensaje recibido: AT ^ SCFG?
16: 19: 23.977 [main] DEBUG SerialConnections.M234Serial - End
¿Qué estoy haciendo mal y cómo puedo solucionarlo?
Sugiero las siguientes mejoras a su código:
-
Reemplazar
waitTime(System.currentTimeMillis(), 2000);
en el escucha del evento conif ( serialPortEvent.isRXCHAR() ) { ...
- Asegúrese de terminar su comando AT correctamente; generalmente se requiere un salto de línea y / o retorno de carro al final de cada cadena de comando. Consulte la documentación de su dispositivo.
-
Make
isReceived
volátil , es decir,private volatile boolean isReceived;
, si se va a compartir entre diferentes subprocesos.
Para evitar la espera ocupada, puede utilizar primitivas de sincronización estándar de Java, como esta:
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();
}
}