---
# System prepended metadata

title: JAVA hid4java for MacOs
tags: [hid4java, Java, Usb]

---

# 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();
	      }
	    }
	  }

	}
```

