# JAVA hid4java for MacOs ###### tags: `Java` `hid4java` `Usb` ## 安裝使用 因為 hid4java 是透過 JNA 打包 所以需要安裝這兩個依賴 hid4java 0.5.0 JNA 4.2.2 可以直接用maven安裝就可 ``` <!-- hid4java for cross-platform HID USB --> <dependency> <groupId>org.hid4java</groupId> <artifactId>hid4java</artifactId> <version>0.5.0</version> </dependency> ``` Mac必須先把 https://github.com/libusb/hidapi 安裝到系統環境變數路徑下,才可以編譯,否則會報錯 我是直接安裝到 /Library/Java/Extensions 下 ## 測試 LED mini badge 範例: ``` package com.leo.test; import java.util.concurrent.TimeUnit; import org.hid4java.HidDevice; import org.hid4java.HidException; import org.hid4java.HidManager; import org.hid4java.HidServices; import org.hid4java.HidServicesListener; import org.hid4java.HidServicesSpecification; import org.hid4java.ScanMode; import org.hid4java.event.HidServicesEvent; import static java.util.concurrent.TimeUnit.NANOSECONDS; public class UsbHidDeviceExample implements HidServicesListener { private static final Integer VENDOR_ID = 0x416; private static final Integer PRODUCT_ID = 0x5020; // private static final Integer VENDOR_ID = 0x204c; // private static final Integer PRODUCT_ID = 0x4359; private static final int PACKET_LENGTH = 64; public static final String SERIAL_NUMBER = null; public static void main(String[] args) throws HidException { UsbHidDeviceExample example = new UsbHidDeviceExample(); example.executeExample(); } public void executeExample() throws HidException { // Configure to use custom specification HidServicesSpecification hidServicesSpecification = new HidServicesSpecification(); hidServicesSpecification.setAutoShutdown(true); hidServicesSpecification.setScanInterval(500); hidServicesSpecification.setPauseInterval(5000); hidServicesSpecification.setScanMode(ScanMode.SCAN_AT_FIXED_INTERVAL_WITH_PAUSE_AFTER_WRITE); // Get HID services using custom specification HidServices hidServices = HidManager.getHidServices(hidServicesSpecification); hidServices.addHidServicesListener(this); // Start the services System.out.println("Starting HID services."); hidServices.start(); System.out.println("Enumerating attached devices..."); // Provide a list of attached devices for (HidDevice hidDevice : hidServices.getAttachedHidDevices()) { System.out.println(hidDevice); } // Open the device device by Vendor ID and Product ID with wildcard serial number HidDevice hidDevice = hidServices.getHidDevice(VENDOR_ID, PRODUCT_ID, SERIAL_NUMBER); if (hidDevice != null) { System.out.println("find devices....."); System.out.println(hidDevice.getUsage()); System.out.println(hidDevice.getId()); System.out.println(hidDevice.getUsagePage()); // Consider overriding dropReportIdZero on Windows // if you see "The parameter is incorrect" // HidApi.dropReportIdZero = true; // Device is already attached and successfully opened so send message sendMessage(hidDevice); } System.out.printf("Waiting 30s to demonstrate attach/detach handling. Watch for slow response after write if configured.%n"); // Stop the main thread to demonstrate attach and detach events sleepUninterruptibly(10, TimeUnit.SECONDS); // Shut down and rely on auto-shutdown hook to clear HidApi resources hidServices.shutdown(); } @Override public void hidDeviceAttached(HidServicesEvent event) { System.out.println("Device attached: " + event); // Add serial number when more than one device with the same // vendor ID and product ID will be present at the same time if (event.getHidDevice().isVidPidSerial(VENDOR_ID, PRODUCT_ID, null)) { sendMessage(event.getHidDevice()); } } @Override public void hidDeviceDetached(HidServicesEvent event) { System.err.println("Device detached: " + event); } @Override public void hidFailure(HidServicesEvent event) { System.err.println("HID failure: " + event); } private void sendMessage(HidDevice hidDevice) { // Ensure device is open after an attach/detach event if (!hidDevice.isOpen()) { System.out.println("open hidDevice"); hidDevice.open(); } // Send the Initialise message byte[] message = new byte[PACKET_LENGTH]; message[0] = 0x3f; // USB: Payload 63 bytes message[1] = 0x23; // Device: '#' message[2] = 0x23; // Device: '#' message[3] = 0x00; // INITIALISE // String string = "1b00e006f46208d2ffff0000000009000001000d0001014000000077616e67000000003021324354667788000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // String string2 = "1b00e096bc6208d2ffff0000000009000001000d00010140000000e1a2a7e8aeaaeea4a4a6a90080c020e0a0e04040c020021f09091f000f09090f093ca42828b0282424242c2000030001000300030001028aef084cabefaacf92"; // String string3 = "1b005030346208d2ffff0000000009000001000d000101400000001222008000800080008000000072077d057700770577557740d05040f05050202050902828b0282424242c2000030001000300030001028aef084cabefaacf92"; // A 文字 String string = "1b00d047be0007e7ffff0000000009000001002e0001014000000077616e67000000004046474840444647000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; String string2 = "1b00d097010107e7ffff0000000009000001002e0001014000000000386cc6c6fec6c6c6c6004840444647000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // String string = "1b0010d0a46208d2ffff00000000090000010015000101400000004c4359f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // String string2 = "1b0020a87e6208d2ffff00000000090000010015000101400000004c4359dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // String string3 = "1b00b092fb5f08d2ffff000000000900000100150001014000000000000000000000020201030001000000000000c8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // String string4 = "1b00d087ad6208d2ffff0000000009000001001500010140000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // String string5 = "1b00e0f11e6208d2ffff0000000009000001001500010140000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // String string6 = "1b00a007436208d2ffff0000000009000001001500010140000000ffffffffffffffff009245d4555504c33320aaaa282aaa0caaaaa8ccccecccccdc0410100c3ae0eeaa902800a800000000000000000000000000000000000000"; // String string7 = "1b0090d7ac6208d2ffff000000000900000100150001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // String string8 = "1b005030516108d2ffff00000000090000010015000101400000004c435999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; String packetString = string.substring(54); String packetString2 = string2.substring(54); // String packetString3 = string3.substring(54); // String packetString4 = string.substring(54); // String packetString5 = string2.substring(54); // String packetString6 = string3.substring(54); // String packetString7 = string.substring(54); // String packetString8 = string2.substring(54); byte[] packet1 = new byte[packetString.length() / 2]; for (int i = 0; i < packet1.length; i++) { int index = i * 2; int j = Integer.parseInt(packetString.substring(index, index + 2), 16); packet1[i] = (byte) j; } byte[] packet2 = new byte[packetString2.length() / 2]; for (int i = 0; i < packet2.length; i++) { int index = i * 2; int j = Integer.parseInt(packetString2.substring(index, index + 2), 16); packet2[i] = (byte) j; } // byte[] packet3 = new byte[packetString3.length() / 2]; // for (int i = 0; i < packet3.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString3.substring(index, index + 2), 16); // packet3[i] = (byte) j; // } // byte[] packet4 = new byte[packetString4.length() / 2]; // for (int i = 0; i < packet4.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString4.substring(index, index + 2), 16); // packet4[i] = (byte) j; // } // byte[] packet5 = new byte[packetString5.length() / 2]; // for (int i = 0; i < packet5.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString5.substring(index, index + 2), 16); // packet5[i] = (byte) j; // } // byte[] packet6 = new byte[packetString6.length() / 2]; // for (int i = 0; i < packet6.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString6.substring(index, index + 2), 16); // packet6[i] = (byte) j; // } // byte[] packet7 = new byte[packetString7.length() / 2]; // for (int i = 0; i < packet7.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString7.substring(index, index + 2), 16); // packet7[i] = (byte) j; // } // byte[] packet8 = new byte[packetString8.length() / 2]; // for (int i = 0; i < packet8.length; i++) { // int index = i * 2; // int j = Integer.parseInt(packetString8.substring(index, index + 2), 16); // packet8[i] = (byte) j; // } // ByteArrayOutputStream outputStream = new ByteArrayOutputStream( ); // byte c[]; // try { // outputStream.write( packet1 ); // outputStream.write( packet2 ); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // c = outputStream.toByteArray( ); // byte[] bytes = {-1, 0, 1, 2, 3 }; // StringBuilder sb = new StringBuilder(); // for (byte b : c) { // sb.append(String.format("%02X ", b)); // } int val = hidDevice.write(packet1, 64, (byte) 0x00); int val2 = hidDevice.write(packet2, 64, (byte) 0x00); // int val3 = hidDevice.write(packet3, 64, (byte) 0x00); // int val4 = hidDevice.write(packet4, 64, (byte) 0x00); // int val5 = hidDevice.write(packet5, 64, (byte) 0x00); // int val6 = hidDevice.write(packet6, 64, (byte) 0x00); // int val7 = hidDevice.write(packet7, 64, (byte) 0x00); // int val8 = hidDevice.write(packet8, 64, (byte) 0x00); if (val >= 0) { System.out.println("> [" + val + "]"); } else { System.err.println(hidDevice.getLastErrorMessage()); } // Prepare to read a single data packet boolean moreData = true; while (moreData) { byte data[] = new byte[PACKET_LENGTH]; // This method will now block for 500ms or until data is read val = hidDevice.read(data, 500); switch (val) { case -1: System.err.println(hidDevice.getLastErrorMessage()); break; case 0: moreData = false; break; default: System.out.print("< ["); for (byte b : data) { System.out.printf(" %02x", b); } System.out.println("]"); break; } } } /** * Invokes {@code unit.}{@link java.util.concurrent.TimeUnit#sleep(long) sleep(sleepFor)} * uninterruptibly. */ public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) { boolean interrupted = false; try { long remainingNanos = unit.toNanos(sleepFor); long end = System.nanoTime() + remainingNanos; while (true) { try { // TimeUnit.sleep() treats negative timeouts just like zero. NANOSECONDS.sleep(remainingNanos); return; } catch (InterruptedException e) { interrupted = true; remainingNanos = end - System.nanoTime(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } } ```