[[FrontPage]] * 本当はICタグのテストプログラム [#jb1675db] 今回ご紹介するICタグを使った書籍管理システムは、元々はSun SpotにICタグ・リーダ/ライターを接続するためのテストプログラムです。 そのため、ICタグ・リーダ/ライターの選定では、Sun Spotとの接続を考慮して以下の制限を付けました。 - 基板タイプでアンテナ一体型 - 稼働電圧が3.3V - UARTでの制御が可能 * ICタグ・リーダ/ライターを探す [#q2eb88f9] ICタグ・リーダ/ライターは、以下の条件でGoogle検索しました。 - ICタグ・リーダ/ライター - 基板 - 3.3V - RS232C (TTL) この結果、大信機器のHF-04SR( http://www.daishin-kiki.com/products.html ) (( 問い合わせ:Tel. 06-6641-7633 大信機器株式会社 営業第二部 野村秀夫さん )) にしました(サンプルのICタグが付いてきました)、価格も1万円程度です。電圧は5Vと3.3Vがありますので、接続するシステムに合わせてください。 次に、使用するICタグですが、本やシートに貼ることを考慮して - 小型 - シールタイプ - ISO15693準拠(HF-04SRのサポートしているICタグ) なものを探すことにしました。 販売量の多いメーカの方が、安く購入できると見込んで「ICタグ」でGoogleに広告を出している 「リンテック」に問い合わせてみました(サンプルのICタグを送っていただきました)。 その結果、TS-Lシリーズ( http://www.lintec.co.jp/e-dept/britem/ictag/products/tsdc_ts.html ) (( 問い合わせ:Tel. 03-3868-7737 リンテック株式会社 アドバンストマテリアルズ事業部門 佐藤誠子さん )) は100枚から注文を受け付けるとの回答を頂き、サンプルのICタグをHF-04SRで動作確認後、TS-L102JCを100枚購入しました。 * ICタグ・リーダー/ライターの動作確認 [#k46ddc39] いきなり、プログラムに接続するのは大変なので、ターミナルからシリアル接続し、 ICタグ・リーダー/ライターの動作確認をすることにします。 ** 秋月のUSB-シリアル変換モジュール [#n581ea3f] TTLレベルのRS-232C通信をテストする場合、レベルコンバータとUSB-シリアル変換モジュールが 必要ですが、秋月のAE-UM232R( http://akizukidenshi.com/catalog/items2.php?q=AE-UM232 )は、USBから電源(5V, 3.3V)を供給し、買ってすぐにブレッドボード上で 接続できるすぐれものです(これで950円は安い)。 写真1は、ブレッドボードにAE-UM232RとHF-04SRを接続したところです。 | &ref(picture.jpg); | |CENTER: 写真1 | AE-UM232RとHF-04SRの結線は、 図1(( ブレッドボードの図は、Electronic Breadboard Templates(http://code.rancidbacon.com/ElectronicBreadboardTemplates )を使用させていただきました。 )) のようにしてください。HF-04SRからでている4本のケーブルにコネクタを付けて接続しています。 | &ref(Breadboard.jpg); | |CENTER: 図1 | AE-UM232Rのジャンパーは、以下のように設定してください。 - J1: 1-2ピン間ジャンパ有り(ショート)で、VIOに3.3Vが供給されます。 - J2: 有り(ショート)で、USBバスから電源を供給します。 ** デバイスドライバーのインストール [#a9e3f233] AE-UM232Rに組み込まれているUSB・シリアル変換チップはFT232BMですので、 Future Technology Devices International Ltd.(http://www.ftdichip.com/Drivers/VCP.htm) のサイトからドライバーをダウンロードします。 - MacOSXの場合には、FTDIUSBSerialDriver_v2_2_10.dmg - WIndowsの場合には、CDM 2.04.14.zip をダウンロードしてインストールしてください。 ** ドライバーの確認 [#xb17be32] 次にドライバーが正常に動作しているか確認します。 AE-UM232RのUSBケーブルをパソコンに接続します。 *** MacOSXの場合 [#o7138132] + アプリケーション→ユーティリティのターミナルを起動し、以下のコマンドを入力します(プロンプト$を除く)。 #pre{{ $ ls /dev/cu.usb* /dev/cu.usbserial-A5002yHm }} のように/dev/cu.cusbserial-xxxxxx と表示されることを確認し、この名前をメモしておきましょう。 *** Windowsの場合 [#m9f3ca7b] + マイコンピュータを右クリックし、「プロパティ」を選択します。 + ハードウェアタグから、「デバイスマネージャ」ボタンを押します。 図2のように、ポート(COMとLPT)にUSB Serial Port(COMx)が追加されたことを確認し、COMxの名前をメモします。 |&ref(DeviceManager.jpg);| |CENTER: 図2 | ** 接続確認 [#l5047be8] *** MacOSXの場合 [#e23da818] MacOSXでは、デフォルトの通信ソフトで手頃なものがないので、 「Macにシリアル(RS-232C)ポート」のサイトから( http://www.zone0.ne.jp/2006/osxserial01.html ) から、Jerminal8095.dmgをダウンロードしました。 ターミナルからJerminal(jermコマンド)を以下のオプションで起動します。最後の/dev/cu.cusbserial-xxxxxxは、先ほどメモした名前に変更してください。 #pre{{ $ jerm -b 38400 -p none -d 8 -s 1 /dev/cu.usbserial-A5002yHm }} - ボーレート 38400 - パリティなし - データ長 8bit - ストップビット 1 接続が完了すると以下のような表示でます。 #pre{{ Jerminal v0.8095 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 candy Type "Ctrl-M ~ ." to exit. ispeed 38400 ospeed 38400 +IGNBRK -BRKINT -IGNPAR -PARMRK -INPCK -ISTRIP -INLCR -IGNCR -ICRNL -IXON -IXOFF -IXANY -IMAXBEL -OPOST -ONLCR -OXTABS -ONOEOT cs8 -CSTOPB +CREAD -PARENB -PARODD +HUPCL +CLOCAL -CCTS_OFLOW -CRTSCTS -CRTS_IFLOW -MDMBUF -ECHOKE -ECHOE -ECHO -ECHONL -ECHOPRT -ECHOCTL -ISIG -ICANON -ALTWERASE -IEXTEN -EXTPROC -TOSTOP -FLUSHO -NOKERNINFO -PENDIN -NOFLSH }} ICタグ・リーダ/ライターとの接続を確認するために、バージョン表示コマンド(V Ctrl-R) を入力します(端末のようにエコーバックはしないので、VとCtrl-Rは表示されません)。 #pre{{ 15693 V03.07 }} これで、ICタグ・リーダ/ライターが15693に対応した V03.07であることが表示されました *** Windowsの場合 [#v84ffe80] プログラム→アクセサリ→通信からハイパーターミナルを起動します。 接続ポートは、先ほどメモしたCOMxを選択してください。 ポートの設定は、図3のようにします。 |&ref(ComSetting.jpg);| |CENTER: 図3 | ハイパーターミナルの画面からV Ctrl-Rを入力すると図4のようにバージョンが表示されます。 |&ref(HyperTerminal.jpg);| |CENTER: 図4 | * JavaからICタグ・リーダー/ライターを制御する [#t53fb0a4] すべての準備が整ったところで、JavaからICタグ・リーダー/ライターを制御することにします。 ** Javaでシリアル通信をする [#ybf9c0bd] Javaからシリアルポート、パラレルポートを使用するためのAIPがSunの提供する [[Java Communications API>http://java.sun.com/products/javacomm/]] です。 残念ながらSunの提供するAPIは、SPARC Solaris/x86 Solaris/x86 Linux版のみなのでMacOSXや Windowsでは使えません。 そこで、Java Communications APIに準拠したオープンソースのライブラリRXTXを使用します。 - RXTX : serial and parallel I/O libraries supporting Sun’s CommAPI ( http://www.rxtx.org/ ) RXTXのサイトからrxtx-2.1-7-bins-r2.zipをダウンロードし、解凍します。 - MACOSX_IDE/librxtxSerial.jnlib - Windows/i368-migw32/rxtxSerial.dll - Linux/i686-unknown-linux-gnu/librxtxSerial.so を取り出します。 RXTXシリアル接続については、 - torutkの日記 ( http://d.hatena.ne.jp/torutk/20071224/p1 ) を参考にさせていただきました。 ** 使用するICTag制御コマンド [#d88a9711] javaで使用するICTagコマンドは - バージョン情報 : V - スキャンコマンド: 2XX - 連続スキャン開始コマンド: 2XS - 読出コマンド: 2R - 複数ブロック書込コマンド: 2WM としました。詳しくは、HF-04SRに付属の「コマンド編MF4_V03_07.pdf」を参照してください。 各コマンドの書式では - UID: タグのUID - tt: タグ番号 - bb: ブロック番号 - nn: 数値 - DATA: データ |コマンド|書式|戻り値成功時|戻り値失敗時|制約| |バージョン情報|V[CR]|使用できるタグの種類 バージョン|なし|| |スキャン|2XX[CR]|nn,UID{,UID,UID....}[CR]|00[CR]|複数タグ検知は最大8枚| |連続スキャン|2XS[CR]|01,UID[CR]|中断時None[CR]|1文字を送信すると中断する| |読出|2R,tt,bb,nn[CR]|tt,yy,DATA{,tt,yy,DATA...}[CR]|00[CR]|最大15ブロック| |複数ブロック書込|2WM,tt,bb,nn,DATA[CR]|tt,OK[CR]|tt,NG[CR]|最大15ブロック| ** ICタグ制御クラスHF04SL [#va7b2ded] ICタグ制御クラスHF04SLに各コマンドの処理を実装します。 *** ICタグオープンメソッド [#g9f7368e] 最初にICタグのオープンですが、バージョン情報を使って接続先がICTagかどうかをチェックします。今回はISO-15693のICTagを対象としているので、バージョン情報の15693の文字列をキーワードとしました。 #pre{{ public boolean openICTag(String pname){ if(openSerialPort(pname)){ String returnCode=""; while(returnCode.indexOf("15693") < 0){ try{ write("V\r"); returnCode = readWithTimer(3000); }catch(Exception e){ e.printStackTrace(); break; } } return true; } return false; } }} *** 連続スキャンメソッド [#v5867bca] ICTagの読み込みを逐次チェックするよりも連続スキャンを使ってICTagの検出を 待つようにした方が、処理が簡単になります。 連続スキャンの処理は以下のようになります。 #pre{{ public String contScanICTag() throws IOException { write("2XS\r"); String res = read(3); if (res.equals("01,")) { String id = read(16); read(1); // skip [CR] return (id); } else { read(2); // skip remain None[CR] return (null); } } }} *** 複数ブロック書込メソッド [#n63997e6] 書込もコマンドの仕様通りです。 #pre{{ public boolean writeICTag(int tagNo, int blokNo, byte[] data) throws IOException { int numBlock = (data.length + 3) / 4; StringBuffer buf = new StringBuffer(); buf.append("2WM,"); buf.append(String.format("%02x,", tagNo)); buf.append(String.format("%02x,", blokNo)); buf.append(String.format("%02x,", numBlock)); for (int i = 0; i < data.length; i++) buf.append(String.format("%02x", data[i])); buf.append("\r"); write(buf.toString()); read(3); // skip tt, String result = read(2); read(1); // skip [CR] return (result.equals("OK")); } }} *** 読出メソッド [#ld215b7b] 読出は、ちょっと長くなりましたが、ほとんど仕様どおりです。ICタグの読み出しに失敗した場合には、空のリストを返します。 #pre{{ public String[] readICTag(int tagNo) throws IOException { StringBuffer buf = new StringBuffer(); buf.append("2R,"); buf.append(String.format("%02d,00,0F\r", tagNo)); write(buf.toString()); String numStr = read(2); if (numStr == "00") { return (new String[0]); } else { List<String> list = new ArrayList<String>(); int numTag = Integer.parseInt(numStr); String str; int count = 1; for (int i = 0; i < numTag; i++) { if (count++ != 1) { numStr = read(2); } str = read(1); // skip ',' String lenStr = read(2); str = read(1); // skip ',' or [CR] int len = Integer.parseInt(lenStr, 16); if (len > 0) { String data = read(len*2); str = read(1); // skip ',' or [CR] list.add(data); } } return (list.toArray(new String[0])); } } }} *** テストプログラム [#nd89ca2c] 必要な部品がそろったので、テストをします。 #pre{{ public static void main(String[] args) { HF04SL ictag = new HF04SL(); try { ictag.openICTag("/dev/cu.usbserial-A5002yHm"); System.out.println(ictag.contScanICTag()); System.out.println(ictag.writeICTag(1, 1, "0123456789ABCDEF".getBytes())); String[] tagData = ictag.readICTag(1); System.out.println(tagData[0]); System.out.println(ictag.hexToString(tagData[0], 4, 16)); } catch (Exception e) { e.printStackTrace(); } finally { ictag.closeICTag(); } } }} 実行結果は、 #pre{{ Stable Library ========================================= Native lib Version = RXTX-2.1-7 Java lib Version = RXTX-2.1-7 1A8FA410000104E0 true 000000003031323334353637383941424344454630303030000000000000 000000000000740069006F006E0020002000000000000000000000000000 0123456789ABCDEF Experimental: JNI_OnLoad called. }} のように出力されます。 * サンプルプログラム [#u7eee3fc] ICタグのサンプルプログラムとして「書籍管理システム」を作りました。 書籍管理システムでは、 - 本の表紙裏にICタグを貼ります。 - 本の登録:ICタグを検出し、書籍情報と棚番号を入力する画面を表示します。 - 本の検索:文字列を入力し、一致するタイトル、著者の一覧を表示します。 - ICタグに書き込まれた棚番号を表示します。 の処理をします。 ** 書籍登録の処理の流れ [#w90edfd2] ICタグは、本の表紙裏左上(背表紙の上部に近く)にセットします(写真2)。 ((HF-04SRではスキャン距離が3cmと短いので本の背表紙からのスキャンでは、タグを認識することができませんでしたが、スキャン距離の長いICタグリーダー/ライターを導入したときのためにこのように配置します。)) |&ref(ictagSetting.jpg);| |CENTER: 写真2| ICタグをリーダー/ライターにかざし、バーコードリーダでISBNをスキャンします(写真3)。 |&ref(barcordscan.jpg);| |CENTER: 写真3| BookダイアログでISBN Searchボタンを押すと、Amazon Web Serviceから書籍情報を取得し、 ダイアログに表示します。4桁の棚番号を入力し、OKボタンを押すと棚番号がICタグに書き込まれ ます。 |&ref(BookDialog.jpg);| |CENTER: 図5| ** サンプルプログラムの構成 [#p08ae16c] サンプルプログラムは、図6のような構成となっています。 - パソコンは、Windows, MacOSX, Linuxに対応しています。 - データベースは、MySQL, PostgreSQL, HyperSQL, CSVファイルに対応しています。 - ICタグリーダー/ライター(写真1のブレッドボード) - バーコードリーダISBN番号を読み込むために使用しています。大量の書籍を登録する場合にはとても便利です。USBタイプのものを使用しています。 |&ref(Structure.jpg);| |CENTER: 図6| ** 画面説明 [#a6ad5664] 簡単に各画面の使い方を説明します。 *** 書籍画面 [#u2476737] プログラム起動時に、書籍画面が表示します(図7)。書籍画面には、メニューと書籍の登録された書籍の一覧が表示されます。書籍一覧で書籍を選択し、ダブルクリックするとBookダイアログが表示され、証跡情報の修正が可能です。 |&ref(Frame.jpg);| |CENTER: 図7| メニューには、「ファイル」メニュー1つで、 | 検索| 検索文字列入力ダイアログを表示し、文字列にマッチした書籍を一覧に表示します。文字列が入力されない場合には、すべての書籍を表示します| | 書籍登録 | ICタグを検出し、Bookダイアログを表示し、書籍をデータベースに登録します| | 棚番号表示 |ICタグから4桁の棚番号を読み取り、表示します | | 終了 |プログラムを終了します | *** Bookダイアログ [#nfe79050] Bookダイアログには、ICタグID, ISBN番号、書籍情報、棚番号が表示されます(図5)。 書籍登録の場合、 + ICタグを検出し、ICタグIDを含むBookダイアログを表示します。 + キーボード(バーコードリーダの方が便利)からISBN番号を入力し、ISBN検索ボタンを押すと書籍情報がセットされます。 + OKボタンを押すとデータベースに書籍が登録され、棚番号がICタグに書き込まれます。 + Cancelボタンで登録を終了します。 *** 棚番号表示ダイアログ [#l4ae2018] メニューから「棚番号表示」を選択し、ICタグリーダー/ライターに書籍を近づけると、ICタグから棚番号を読み取り、表示します(図8)。 |&ref(shelfID.jpg);| |CENTER: 図8| ** 開発環境 [#n620c7c7] サンプルプログラムの作成には、以下のツールが必要です。 - java JDK1.5以降 http://java.sun.com/javase/downloads/index.jsp からJava SE Development Kit (JDK)6 Update 11 の Downloadボタンを押して、プラットフォームにあった JDKをダウンロードして、インストールしてください。 - Eclipse 3.1以降 http://www.eclipse.org/ から、Download Eclipseをクリックして、 Eclipse IDE for Java DevelopersのWindowsを選択して ダウンロードして解凍すれば利用可能になります。 ** GUIの構築 [#k82cb910] GUIは、Eclipseのプラグインの一つであるVisula Editorを使って作成しました。 画面でボタンやフィールドをマウスで配置しますので、初心者でも画面の編集ができるようになります(図9)。 |&ref(VisualEditor.jpg);| |CENTER: 図9| ** ISBN検索ボタンの処理 [#q85850e1] ISBN番号から書籍の情報を取得するのは、アマゾンのAWS APIを利用しました。 namespaceの指定方法については、ひびどく( http://yhd.cocolog-nifty.com/hibidoku/2005/11/index.html ) を参考にさせていただきました。 AWS へのアクセスと書籍情報XMLの解析は、JXPathを使いました。 + DocumentContainerにAWS APIのURLをセット。 + JXPathContext#newContextメソッドで AWS APIを使って書籍XMLを取得します。 + context.getValue("//aws:Title")で書籍情報XMLからXPathで指定した書籍タイトルを取り出しています。 こんなに簡単にAWS APIを使って書籍情報を取得できることに驚かれる方も多いのはないでしょうか。 #pre{{ private void searchISBN() { String requestUrl = "http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService&SubscriptionId=" + DataBaseHelper.getAwsAccessKeyID() + "&Operation=ItemSearch&ResponseGroup=Medium&SearchIndex=Blended&Keywords=" + getIcbnField().getText(); try { DocumentContainer container = new DocumentContainer(new URL( requestUrl)); container.setNamespaceAware(true); JXPathContext context = JXPathContext.newContext(container); context.registerNamespace("aws", "http://webservices.amazon.com/AWSECommerceService/2005-10-05"); String title = context.getValue("//aws:Title").toString(); String author = context.getValue("//aws:Author").toString(); int numOfAuthor = (int)Double.parseDouble(context.getValue("count(//aws:Author)").toString()); for (int i = 1; i < numOfAuthor; i++) { String nextAuthor = "//aws:Author[" + (i+1) + "]"; author = author + "; " + context.getValue(nextAuthor).toString(); } String publisher = context.getValue("//aws:Manufacturer").toString(); String publicationDate = context.getValue("//aws:PublicationDate").toString(); String noPages = context.getValue("//aws:NumberOfPages").toString(); String listPrice = context.getValue("//aws:Amount").toString(); titleArea.setText(title); authorArea.setText(author); publisherField.setText(publisher); publicationDateField.setText(publicationDate); noPagesField.setText(noPages); listPriceField.setText(listPrice); } catch (Exception e) { e.printStackTrace(); } } }} * プログラムの実行 [#p7787631] ** AWS(Amazon Web Service)アカウントの作成 [#h64ac35c] ISBNから書籍の情報を取得するのに、AWSのAPIを使っていますので、AWSのAccess Key IDが必要となります。 - 最初にAWSのアカウントを作成します。 http://www.amazon.com/gp/aws/registration/registration-form.html にアクセスして、必要な項目を入力し、登録ボタンを押すと完了です。 - Access Key IDの取得 AWSのアカウントの登録が完了すると、Welcome to Amazon Web Services というタイトルのメールが届きます。 メールに記載されている、以下のサイトにアクセスします。 http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key Sign In画面で登録したメールアドレスとパスワードを入力すると、割り当てられたAccess Key IDが表示 されます。 ** db.propertiesの設定 [#h3259502] ** プログラムの起動 [#h8066999] ** 書籍データベース(data/book.csv) [#b80f696a] ** ICタグ・リーダー/ライターが無い場合 [#p4f8be2d] * あとがき [#l7468b27] サンプルプログラムは、コンパクトではありますが、ICタグを使った例題として - ICタグを読み書きをする方法を紹介しています - ICタグを使って書籍を管理する場合の、書籍登録作業の軽減します - java言語によってOSに依存することなくICタグ・リーダ/ライターを制御します - 特定のデータベースに依存しないで、書籍データベースを管理することができます を紹介しました。