Comunicación de host USB Android
io serial-communication (1)
Odio responder a mi propia pregunta, pero ... ya lo entendí. Estaba mezclando mis lecturas y escrituras. Además, al dispositivo no le gustó el ''/ n'' que estaba usando al final de mis comandos. Parece que se lleva bien con ''/ r'' mucho mejor.
Terminé usando bulkTransfer de Android para lecturas y escrituras. Mis escritos se veían así.
try {
device.getWriter().write(command + "/r");
device.getWriter().flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
Y mi método de escritura anulado para mi BufferedWriter:
@Anular
public void write(char[] buf, int offset, int count) throws IOException {
byte[] buffer = new String(buf, offset, count).getBytes(Charset.forName("US-ASCII"));
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
}
Las lecturas fueron similares:
char[] buffer = new char[BUF_SIZE];
try {
BufferedReader reader = device.getReader();
int readBytes = reader.read(buffer);
Log.d(TAG, "BYTES READ: " + readBytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
String strBuf = new String(buffer).trim();
if (DEBUG) {
Log.d(TAG, "Read: " + strBuf);
}
Y:
@Override
public int read(char[] buf, int offset, int count) throws IOException {
byte[] buffer = new byte[count];
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
if (byteCount < 0) {
throw new IOException();
}
char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
System.arraycopy(charBuffer, 0, buf, offset, byteCount);
return byteCount;
}
Todo esto se inició en un hilo como el siguiente:
new Thread() {
@Override
public void run() {
String command = "go";
write(command);
while (true) {
String coords = read();
}
}
}.start();
Obviamente, esto es solo un asunto de comunicación y ahora tendré que hacer algo con él (ponlo en un Servicio que pueda informar a una actividad de IU de nivel superior usando un controlador). Pero esta parte de ella está resuelta.
Muchísimas gracias a las personas que están trabajando en rosjava ( http://code.google.com/p/rosjava/ ) ... Han organizado muchos grandes proyectos y su código fue muy útil.
Agregando mi clase de dispositivo para ayudar a aclarar las cosas.
import com.google.common.base.Preconditions;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
/* This class represents a USB device that supports the adb protocol. */
public class BKDevice {
// private static final int TIMEOUT = 3000;
private final UsbDeviceConnection usbDeviceConnection;
private final BufferedReader reader;
private final BufferedWriter writer;
public static final String TAG = "AcmDevice";
public BKDevice(UsbDeviceConnection usbDeviceConnection,
UsbInterface usbInterface) {
Preconditions.checkState(usbDeviceConnection.claimInterface(
usbInterface, true));
this.usbDeviceConnection = usbDeviceConnection;
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
UsbEndpoint ep = usbInterface.getEndpoint(i);
Log.d(TAG, "EP " + i + ": " + ep.getType());
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
epIn = ep;
}
}
}
if (epOut == null || epIn == null) {
throw new IllegalArgumentException("Not all endpoints found.");
}
BKReader acmReader = new BKReader(usbDeviceConnection, epIn);
BKWriter acmWriter = new BKWriter(usbDeviceConnection, epOut);
reader = new BufferedReader(acmReader);
writer = new BufferedWriter(acmWriter);
}
public BufferedReader getReader() {
return reader;
}
public BufferedWriter getWriter() {
return writer;
}
}
Añadiendo código BKReader:
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.util.Log;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
public class BKReader extends Reader {
private static final int TIMEOUT = 1000;
private final UsbDeviceConnection connection;
private final UsbEndpoint endpoint;
public BKReader(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.connection = connection;
this.endpoint = endpoint;
}
@Override
public int read(char[] buf, int offset, int count) throws IOException {
byte[] buffer = new byte[count];
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
if (byteCount < 0) {
throw new IOException();
}
char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
System.arraycopy(charBuffer, 0, buf, offset, byteCount);
return byteCount;
}
@Override
public void close() throws IOException {
}
}
Estoy trabajando en un proyecto que utiliza las capacidades del host USB en Android 3.2. Estoy sufriendo de una deplorable falta de conocimiento y talento con respecto a la comunicación USB / serie en general. Tampoco puedo encontrar ningún buen código de ejemplo para lo que necesito hacer.
Necesito leer desde un dispositivo de comunicación USB.
Ej: Cuando me conecto a través de Putty (en mi PC), ingreso:
>GO
Y el dispositivo empieza a arrojarme datos por mí. Pitch / Roll / Temp / Checksum.
Ex:
$R1.217P-0.986T26.3*60
$R1.217P-0.986T26.3*60
$R1.217P-0.987T26.3*61
$R1.217P-0.986T26.3*60
$R1.217P-0.985T26.3*63
Puedo enviar el comando inicial ''GO'' desde el dispositivo Android, momento en el que recibo un eco de ''GO''.
Entonces nada más en las lecturas posteriores.
¿Cómo puedo: 1) Enviar el comando ''ir''. 2) Leer en el flujo de datos que resulta.
El dispositivo USB con el que estoy trabajando tiene las siguientes interfaces (puntos finales).
Clase de dispositivo: Dispositivo de comunicación (0x2)
Interfaces:
Interfaz # 0 Clase: Dispositivo de comunicación (0x2) Punto final # 0 Dirección: Entrante (0x80) Tipo: Interrupción (0x3) Intervalo de sondeo: 255 Tamaño máximo del paquete: 32 Atributos: 000000011
Clase de interfaz # 1: Clase de dispositivo de comunicación (CDC) (0xa) Punto final # 0 Dirección: 129 Número: 1 Dirección: Entrante (0x80) Tipo: Granel (0x2) Intervalo de sondeo (0) Tamaño máximo del paquete: 32 Atributos: 000000010
Dirección del punto final n. ° 1: 2 Número: 2 Dirección: Saliente (0x0) Tipo: Granel (0x2) Intervalo de sondeo (0) Tamaño máximo del paquete: 32 Atributos: 000000010
Soy capaz de lidiar con el permiso, conectarme al dispositivo, encontrar la interfaz correcta y asignar los puntos finales. Solo estoy teniendo problemas para determinar qué técnica usar para enviar el comando inicial, leer los datos posteriores. He probado diferentes combinaciones de bulkTransfer y controlTransfer sin suerte.
Gracias.
Estoy usando la interfaz # 1 como se ve a continuación:
public AcmDevice(UsbDeviceConnection usbDeviceConnection, UsbInterface usbInterface) {
Preconditions.checkState(usbDeviceConnection.claimInterface(usbInterface, true));
this.usbDeviceConnection = usbDeviceConnection;
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
UsbEndpoint ep = usbInterface.getEndpoint(i);
Log.d(TAG, "EP " + i + ": " + ep.getType());
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
epIn = ep;
}
}
}
if (epOut == null || epIn == null) {
throw new IllegalArgumentException("Not all endpoints found.");
}
AcmReader acmReader = new AcmReader(usbDeviceConnection, epIn);
AcmWriter acmWriter = new AcmWriter(usbDeviceConnection, epOut);
reader = new BufferedReader(acmReader);
writer = new BufferedWriter(acmWriter);
}