JavaからUSBランプを光らせてみる
続編あります。
2013/2/14追記: WindowsサービスでWebmail Notifierを制御するユーティリティを作ったけど半年以上忘れてたので紹介 - ka-ka_xyzの日記
Webmail windowというUSB接続のLEDランプを制御するプログラムを作りました - ashelの日記
↑を読んでて、便利そうだったので早速WebMail Notifierを購入してみました。
WebMail Notifierを購入する
こういうUSB接続のちょっと微妙なガジェットといえばこちら。
All about USB | USB 3.0, USB Gaming, USB Lifestyle | Brando Workshop
"Webmail"で商品検索するとあっけなくヒットします。
とりあえず、ランプ単体版とUSBハブ機能付き版があったので、下記のハブ機能付き版を購入。
All about USB | USB 3.0, USB Gaming, USB Lifestyle | Brando Workshop : USB Webmail Notifier + 4-Port Hub Cable
まあ、最悪使えなくてもUSBハブにできればいくらか投資を回収できるかな。(実はこの時点で罠が潜んでいたのですが、詳細については後述)
libusb-win32の導入
さて、JavaからUSBデバイスを制御するといえば、JSRであるにも関わらず誰からも注目されていないJSR-80実装は無視して、libusb-win32と、libusb / libusb-win32 wrapperの組み合わせで行ってみます。環境はwin7 64bit。
Linux環境はとりあえず置きで。
手順1 libusb-win32関連dllのインストール
↑から、libusb-win32 v1.2.0.6(現時点での最新版リリース)をダウンロードします。
binフォルダの下にあるreadme.txtに従い、libusb0.dllおよびlibusb0.sysをコピーします。32bitと64bit(amd64)アーキテクチャでのコピー方法を引用します。
ALL ARCHITECTURES:
x86\libusb0_x86.dll: x86 32-bit library. Must be renamed to libusb0.dll
On 64 bit, Installs to Windows\syswow64\libusb0.dll.
On 32 bit, Installs to Windows\system32\libusb0.dll.x86\inf-wizard.exe: inf-wizard application with embedded libusb-win32
v1.2.6.0 binaries.X86 ONLY ARCHITECTURES:
x86\libusb0.sys: x86 32-bit driver.
Installs to Windows\system32\drivers\libusb0.sysAMD64-INTEL64 ONLY ARCHITECTURES:
amd64\libusb0.sys: x64 64-bit driver.
Installs to Windows\system32\drivers\libusb0.sysamd64\libusb0.dll: x64 64-bit library.
Installs to Windows\system32\libusb0.dll
32bit版と64bit版でコピー元のディレクトリが違う(32bit版はbin/x86、64bit版はbin/amd64)ので注意。
infファイルの作成
Webmail Notifierを刺した状態でbin/inf-wizard.exeを起動します。
OSが認識しているUSBデバイス一覧が出てくるので、下記の条件に当てはまるものを選択。
VenderID 0x1294
ProductID 0x1320
libusb用のINF ファイルを生成してくれるので、適当な場所に保存します。
次に、WindowsのデバイスマネージャーからWebmail Notifierを探してきて、「プロパティ」->「ドライバーの更新」から、「コンピュータを参照してドライバソフトウェアの検索」->「コンピュータ上のデバイスドライバの一覧から選択します」->「ディスク使用」という流れで、上で作成したinfファイルを指定し、ドライバをインストールします。
inf-wizard.exeのダイアログにある「install now」ボタンをクリックすると自動でインストールしてくれます。
正常にインストールが終了すると、Windowsデバイスマネージャーの該当デバイスプロパティから「ドライバーの詳細」ボタンをクリックすると下記のように表示されるはず。
C:\windows\system32\drivers\libusb0.sys
C:\windows\system32\libusb0.dll
C:\windows\syswow64\libusb0.dll
最後に、libusb-win32のbin/x86/testlibusb-win.exeを実行して以下のようなダイアログが表示されればインストールは成功です。
DLL version: 1.2.6.0
Driver version: 1.2.6.0bus/device idVendor/idProduct
bus-0/\\.\libusb0-0001--0x1294-0x1320 1294/1320
- Unable to fetch manufacturer string
- Unable to fetch product string
bLength: 18
bDescriptorType: 01h
bcdUSB: 0110h
bDeviceClass: 00h
bDeviceSubClass: 00h
bDeviceProtocol: 00h
bMaxPacketSize0: 08h
idVendor: 1294h
idProduct: 1320h
bcdDevice: 0100h
iManufacturer: 1
iProduct: 2
iSerialNumber: 0
bNumConfigurations: 1
wTotalLength: 41
bNumInterfaces: 1
bConfigurationValue: 1
iConfiguration: 4
bmAttributes: 80h
MaxPower: 100
bInterfaceNumber: 0
bAlternateSetting: 0
bNumEndpoints: 2
bInterfaceClass: 3
bInterfaceSubClass: 0
bInterfaceProtocol: 0
iInterface: 0
bEndpointAddress: 83h
bmAttributes: 03h
wMaxPacketSize: 8
bInterval: 10
bRefresh: 0
bSynchAddress: 0
bEndpointAddress: 04h
bmAttributes: 03h
wMaxPacketSize: 5
bInterval: 10
bRefresh: 0
bSynchAddress: 0
(赤字部分は後で使用)
wrapperのインストール
ダウンロードサイトからdllファイルおよびjarファイルを入手します。
LibusbJava.dllをwindows/system32へコピー。
32bit版LibusbJava.dllをwindows/syswow64へコピー。
javaプログラムの実行
ch.ntb.usb-0.5.9.jarをクラスパスに入れて、以下のコードを実行します。
問題がなければ、一秒間だけ赤色LEDが点灯し、その後消灯するはずです。
package jp.gr.java_conf.ka_ka_xyz.usb; import ch.ntb.usb.Device; import ch.ntb.usb.USB; import ch.ntb.usb.USBException; public class UsbMain { public static void main(String[] args){ UsbMain usbMain = new UsbMain(); usbMain.firstLight(); } public UsbMain(){} public void firstLight(){ /* * testlibusb-win.exe実行結果にあるベンダIDとプロダクトIDでUSBデバイスを指定 * ベンダID: 0x1294 * プロダクトID: 0x1320 * */ Device dev = USB.getDevice((short) 0x1294, (short) 0x1320); if(dev == null){ System.out.println("failed to open USB device!"); System.exit(1); } try { dev.open(1, 0, -1); //RED light final byte[] red = {1, 0, 0, 0, 0,}; System.out.println("result: " + dev.writeInterrupt(0x04, red, red.length, 100, true)); try { //一秒待ち Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //ライトを消す final byte[] lightOff = {0, 0, 0, 0, 0}; //0x04: testlibusb-win.exe実行結果中のEndpoint値 dev.writeInterrupt(0x04, lightOff, lightOff.length, 100, true); dev.close(); } catch (USBException e) { e.printStackTrace(); } } }
赤色LEDしか点かないんだが・・・・
以下の配列で、先頭部分の値を1〜7に変えることで色が変わるはずだと思っていましたが・・・値を変えても何故か赤色のまま。
final byte[] red = {1, 0, 0, 0, 0,};
で、Webmail Notifierを分解してみたわけです。
中には3つのLEDが入っており、値を1〜7に変えて実行してやると確かに点灯するLEDのパターンが変わりますが・・・3つとも全部赤色LEDじゃねーか。
何なの!? HOI3で真っ先にソ連プレイした祟りなの? それとも生産工場に文化大革命並みに「赤以外の使用はまかりならん」とか政治的指導が入ったの?シベリアに飛ばされちゃうの?
とか思ってましたが、バカなのは自分でした。
USBハブ機能の無いWebmail Notifierの製品紹介ページには
Soft Illuminated Blue, Red, Green indicator
と書いていますが、USBハブ機能付きWebmail Notifierの製品紹介ページには
Soft Illuminated Red indicator
としか書かれていません。
ぐぬぅ。これが孔明の罠ってやつか。
とりあえず、ハブ無し版Webmail Notifierをオーダーして、多色発光がうまくいくか試してみます。
まあ、最終的にはHTMLパーサーと組み合わせてテスト自動化サーバーや職場のWebアプリと連携していろいろする予定。