使用USB数据线端对端传输数据
maven引入:
<dependency>
<groupId>org.usb4java</groupId>
<artifactId>usb4java</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.usb4java</groupId>
<artifactId>usb4java-javax</artifactId>
<version>1.3.0</version>
</dependency>
代码示例:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.usb.*;
@Slf4j
public class Tests {
public static void main(String[] args) {
try {
Tests tests = new Tests();
tests.useUsb(0x0bda, 0x5411);
} catch (Exception e) {
System.out.println(ExceptionUtils.getStackTrace(e));
}
}
public Map<String,Object> useUsb(int vendorId, int productId) throws Exception{
Map<String,Object> mainMap = new HashMap<>();
mainMap.put("code", "USB_CONNECT_TRUE");
// UsbDevice device = findDevice(UsbHostManager.getUsbServices().getRootUsbHub(), 0x30c9, 0x00a8);
UsbDevice device = findDevice(UsbHostManager.getUsbServices().getRootUsbHub(), 0x0bda, 0x5411);
if (device == null) {
log.error("设备未找到!");
mainMap.put("code", "USB_CONNECT_NOT_EXIST");
return mainMap;
}
UsbInterface usbInterface = initUsbDevice(device);
if (null == usbInterface) {
log.error("设备初始化失败");
mainMap.put("code", "USB_CONNECT_NOT_KNOW");
return mainMap;
}
mainMap.put("usbInterface", usbInterface);
UsbEndpoint receivedUsbEndpoint;
UsbEndpoint sendUsbEndpoint = (UsbEndpoint)usbInterface.getUsbEndpoints().get(0);
if (!sendUsbEndpoint.getUsbEndpointDescriptor().toString().contains("OUT")) {
receivedUsbEndpoint = sendUsbEndpoint;
sendUsbEndpoint = (UsbEndpoint)usbInterface.getUsbEndpoints().get(1);
} else {
receivedUsbEndpoint = (UsbEndpoint)usbInterface.getUsbEndpoints().get(1);
}
// 发送。打开发送通道
UsbPipe sendUsbPipe = sendUsbEndpoint.getUsbPipe();
if (sendUsbPipe.isOpen()){
sendUsbPipe.close();
sendUsbPipe.open();
} else {
sendUsbPipe.open();
}
sendMessage("123", sendUsbPipe);
// 接收。打开接收通道
final UsbPipe receivedUsbPipe = receivedUsbEndpoint.getUsbPipe();
if (!receivedUsbPipe.isOpen()) {
receivedUsbPipe.open();
}
// 接收操作放到子线程实现异步回调
Thread th = new Thread(() -> {
receivedMessage(receivedUsbPipe);
/*
try {
receivedMessage(receivedUsbPipe);
} catch (Exception e) {
System.out.println(ExceptionUtils.getStackTrace(e));
} finally {
receivedUsbPipe.abortAllSubmissions();
try {
receivedUsbPipe.close();
} catch (Exception e){
}
}
*/
});
th.start();
return mainMap;
}
/**
* 搜索特定USB设备
* @param hub UsbHub
* @param vendorId VID
* @param productId PID
* @return USB设备
*/
public UsbDevice findDevice(UsbHub hub, int vendorId, int productId) {
List<UsbDevice> list = (List<UsbDevice>)hub.getAttachedUsbDevices();
for (UsbDevice device : list) {
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
log.info("vendorId:" + desc.idVendor() + ",productId:" + desc.idProduct());
if (desc.idVendor() == vendorId && desc.idProduct() == productId) {
return device;
}
if (device.isUsbHub()) {
device = findDevice((UsbHub)device, vendorId, productId);
if(device != null){
return device;
}
}
}
return null;
}
/**
* 初始化设备
* @param device UsbDevice
* @return UsbInterface
*/
private UsbInterface initUsbDevice(UsbDevice device) {
UsbInterface usbInterface = null;
try {
// 当你想要与一个接口或者这个接口的端点进行通信时,那么你在使用它之前必须要claim它,并且当你结束时你必须释放它。
UsbConfiguration configuration = device.getActiveUsbConfiguration();
if (!configuration.getUsbInterfaces().isEmpty()) {
// iface = (UsbInterface)configuration.getUsbInterfaces().get(0);
usbInterface = configuration.getUsbInterface((byte) 0);
// claim连接必须打开。如果设备是连接状态我们把他关闭
if (usbInterface.isClaimed()){
usbInterface.release();
}
// 可能出现的一种情况是你想要通信的接口已经被内核驱动使用,在这种情况下你可能需要通过传递一个接口策略到claim方法以此尝试强制claim:
usbInterface.claim(iface -> true);
}
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
return null;
}
return usbInterface;
}
/**
* 发送数据
* @param data 待发送的数据
* @param usbPipe UsbPipe
*/
public static void sendMessage(String data, UsbPipe usbPipe) {
try {
log.info("进入sendMassge发送数据");
// 阻塞
usbPipe.syncSubmit(data.getBytes(StandardCharsets.UTF_8));
// 非阻塞
// usbPipe.asyncSubmit(data.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
}
/**
* 接收数据
* @param usbPipe UsbPipe
*/
public void receivedMessage(UsbPipe usbPipe) {
byte[] buffer = new byte[64];
while (true) {
try {
int length = asyncSubmit(buffer, usbPipe);
for (int i = 0; i < length; i++) {
System.out.print(Byte.toUnsignedInt(buffer[i])+" ");
}
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
}
}
public int asyncSubmit(final byte[] data, UsbPipe usbPipe) throws UsbException {
// 异步
final UsbIrp irp = usbPipe.asyncSubmit(data);
//这里一定要注意,若果你设置的接收时间太短了,你硬件还没反应过来通讯就结束了。建议设置为15秒。
irp.waitUntilComplete(30000);
if (irp.isUsbException()) {
throw irp.getUsbException();
}
return irp.getActualLength();
}
public int syncSubmit(final byte[] data, UsbPipe usbPipe) throws UsbException {
// 同步
return usbPipe.syncSubmit(data);
}
}