spot/ICTagリーダー・ライターを接続する
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[FrontPage]]
2008/09/25からのアクセス回数 &counter;
#contents
SunSPOTを使った用途を考えていたときに、MITの石井さんが提...
Tangibleが浮かんだ。認識範囲の短いICTagは、ある地点の道し...
書き込みができるのでおもしろいことができると思った。
Tagibleの本家の例
http://tangible.media.mit.edu/projects/sensetable/
** ICTagの選定 [#l3e06cd5]
小型で電子工作の容易なICTagリーダライターとして、大信機器...
http://www.daishin-kiki.com/products.html
価格も1万円程度で、3.3VでRS-232C/TTLレベルで通信できると...
最近はもっと小さなリーダも見つけた(http://www.neotechkno...
HF-04SRの対象とするICTagは、ISO15693とMifare規格に対応し...
タグを使うことにしました。
*** ICTagの購入が問題 [#g1b708e0]
ICTagの広告でトップにでてくるリンテック株式会社に問い合わ...
最低でも100枚単位でないと出荷できないとのことでした。
http://www.lintec.co.jp/e-dept/britem/ictag/products/tsdc...
営業の方のご厚意でサンプルタグを送ってもらい、HF-04SRでの...
** ICTagリーダライターの動作確認 [#db76db46]
いきなりSunSPOTと接続するのは大変なので、シリアル接続でタ...
*** 秋月のUSB-シリアル変換モジュール [#qb97c876]
TTLレベルのRS-232C通信をテストする場合、レベルコンバータ...
必要ですが、秋月の[[AE-UM232R>http://akizukidenshi.com/ca...
に接続できるすぐれもの(これで950円はやすい!)。
#ref(5.jpg);
*** MacOSXでシリアル接続 [#gd689039]
私の使っているMacOSXからシリアル接続できるデバイスは少な...
- PL-2303
- FT232BM
は、MacOSX用のドライバーを公開しているそうです(http://ww...
*** ドライバーのダウンロード [#k94e243b]
FT232BM用のドライバーを[[Future Technology Devices Intern...
Tiger以降でないとだめみたいですから注意してください。
*** ターミナルソフト [#h3ebe6a3]
MacOSXで使えるターミナルソフトは、Jerminalを使用すること...
先ほどの参照ページのJerminal8095.dmgをダウンロードしまし...
*** 接続確認 [#m353b7ee]
ターミナルからJerminal(jermコマンド)を以下のオプション...
#pre{{
$ jerm -b 38400 -p none -d 8 -s 1 /dev/cu.usbserial-A5002...
}}
- ボーレート 38400
- パリティなし
- データ長 8bit
- ストップビット 1
最後の/dev/cu.cusbserial-xxxxxxは、機種によって変わります。
接続が完了すると以下のような表示でます。
#pre{{
Jerminal v0.8095 Copyright (C) 2000, 2001, 2002, 2003, 2...
Type "Ctrl-M ~ ." to exit.
ispeed 38400 ospeed 38400
+IGNBRK -BRKINT -IGNPAR -PARMRK -INPCK -ISTRIP -INLCR -I...
-IXOFF -IXANY -IMAXBEL
-OPOST -ONLCR -OXTABS -ONOEOT
cs8 -CSTOPB +CREAD -PARENB -PARODD +HUPCL +CLOCAL -CCTS_...
-CRTS_IFLOW -MDMBUF -ECHOKE -ECHOE -ECHO -ECHONL -ECHOPR...
-ISIG -ICANON -ALTWERASE -IEXTEN
-EXTPROC -TOSTOP -FLUSHO -NOKERNINFO -PENDIN -NOFLSH
}}
ICTagリーダライターとの接続を確認するために、ICTagリーダ...
を入力すると、
#pre{{
15693 V03.07
}}
めでたく、ICTag 15693に対応した V03.07であることが表示さ...
** JavaからICTagを制御する [#c63e1404]
ここでのメインテーマは、ハードをjavaで制御することですか...
*** Javaでシリアル通信をする [#b6c87793]
Javaからシリアルポート、パラレルポートを使用するためのAIP...
[[Java Communications API>http://java.sun.com/products/ja...
です。
残念ながらSunの提供するAPIは、SPARC Solaris/x86 Solaris/x...
Windowsでは使えません。
そこで、Java Communications APIに準拠したオープンソースの...
- [[RXTX : serial and parallel I/O libraries supporting S...
RXTXのサイトからrxtx-2.1-7r2.zipをダウンロードし、解凍し...
-MACOSX_IDE/ForPackageMaker/install/Library/Extensionsか...
-- librxtxSerial.jnlib
-- RXTXcomm.jar
また、RXTXの例題としてprocessing/Gainerのライブラリを使い...
- http://gainer.cc/Download/Download
からProcessingをダウンロードします。
- gainer_lib_processing_v1-1-0rc4のlibraries/gainer/libra...
-- gainer.jar
-- librxtxSerial.so
-- rxtxSerial.dll
を取り出します。
RXTXシリアル接続については、
-[[ torutkの日記>http://d.hatena.ne.jp/torutk/20071224/p1]]
を参考にさせていただきました。
*** 使用するICTag制御コマンド [#oec7ed1e]
javaで使用するICTagコマンドは
- バージョン情報 : V
- スキャンコマンド: 2XX
- 連続スキャン開始コマンド: 2XS
- 読出コマンド: 2R
- 複数ブロック書込コマンド: 2WM
としました。
各コマンドの書式では
- UID: タグのUID
- tt: タグ番号
- bb: ブロック番号
- nn: 数値
- DATA: データ
|コマンド|書式|戻り値成功時|戻り値失敗時|制約|
|バージョン情報|V[CR]|使用できるタグの種類 バージョン|な...
|スキャン|2XX[CR]|nn,UID{,UID,UID....}[CR]|00[CR]|複数タ...
|連続スキャン|2XS[CR]|01,UID[CR]|中断時None[CR]|1文字を送...
|読出|2R,tt,bb,nn[CR]|tt,yy,DATA{,tt,yy,DATA...}[CR]|00[C...
|複数ブロック書込|2WM,tt,bb,nn,DATA[CR]|tt,OK[CR]|tt,NG[C...
*** ICTag制御クラスHF04SL [#zed9ad11]
ICTag制御クラスHF04SLに各コマンドの処理を実装します。
最初にICTagのオープンですが、バージョン情報を使って接続先...
#pre{{
public boolean openICTag(String pname){
if(openSerialPort(pname)){
String returnCode="";
while(returnCode.indexOf("15693") < 0){
try{
write("V\r");
returnCode = readWithTimer(1000);
}catch(TimeoutException e){
}catch(IOException e){
}
}
return true;
}
return false;
}
}}
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);
}
}
}}
連続スキャンのキャンセルはきわめて簡単です。
#pre{{
public void cancelContScanICTag() throws IOException {
write("a");
}
}}
書込もコマンドの仕様通りです。
#pre{{
public boolean writeICTag(int tagNo, int blokNo, byte[] ...
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"));
}
}}
残りの読込は、ちょっと長くなりましたが、ほとんど仕様どお...
#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 (null);
}
else {
List<String> list = new ArrayList<String>();
int numTag = Integer.parseInt(numStr);
int count = 1;
while (available() >= 2) {
if (count++ != 1) {
numStr = read(2);
}
read(1); // skip ','
String lenStr = read(2);
read(1); // skip ','
int len = Integer.parseInt(lenStr, 16);
String data = read(len*2);
read(1); // skip ',' or [CR]
list.add(data);
}
return (list.toArray(new String[0]));
}
}
}}
必要な部品がそろったので、テストをします。
#pre{{
public static void main(String[] args) {
HF04SL ictag = new HF04SL();
try {
ictag.openICTag("/dev/cu.usbserial-A5002yHm");
System.out.println(ictag.contScanICTag());
// Icode SLIは、0ブロックに書き込めない
System.out.println(ictag.writeICTag(1, 1, "0123456789A...
String[] tagData = ictag.readICTag(01);
System.out.println(tagData[0]);
System.out.println(ictag.hexToString(tagData[0], 4, 16...
}
catch (Exception e) {
e.printStackTrace();
}
finally {
ictag.closeSerialPort();
}
}
}}
実行結果は、
#pre{{
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
RXTX Warning: Removing stale lock file. /var/lock/LK.004...
1A8FA410000104E0
true
000000003031323334353637383941424344454630303030000000000...
740069006F006E0020002000000000000000000000000000
0123456789ABCDEF
closing /dev/cu.usbserial-A5002yHm
Experimental: JNI_OnLoad called.
}}
正常に動作しました。
** サンプルアプリケーション [#g36e4259]
ICTagのサンプルアプリケーションとして、本にICTagを付け、I...
- 書籍のタイトル
- 著者
- 出版社
- 総ページ数
- 出版日
- 価格
を表示する、ダイアログを作成します。
#ref(BookManager.jpg);
+ ICTagがリーダにかざされるとダイアログを表示します。
+ ISBN番号を入力しISBN Searchボタンを押すと、 アマゾンか...
+ OKボタンで次のICTagの読込まちになります。
*** Visual Editorを使ってBookDialogを作成する [#gf0ac42e]
BookDialogは、EcdlipseのプラグインVisual Editorを使って作...
#ref(VisualEditor.jpg);
*** ISBN Searchボタンの処理(AWS検索の処理) [#dba0741e]
アマゾンの検索は、AWSを使いました。
ここで、検索結果の読込に失敗して情報をうまく取得できませ...
- [[ひびどく>http://yhd.cocolog-nifty.com/hibidoku/2005/1...
にnamespaceを指定する必要があるとのコメントを見つけ、regi...
するとうまく読み取ることができました。
#pre{{
private void searchISBN() {
String requestUrl = "http://webservices.amazon.co.jp/on...
+ "Service=AWSECommerceService&SubscriptionId=" + [ここ...
+ "&Operation=ItemSearch&ResponseGroup=Medium&SearchInd...
+ getIcbnField().getText();
try {
DocumentContainer container = new DocumentContainer(ne...
requestUrl));
container.setNamespaceAware(true);
JXPathContext context = JXPathContext.newContext(conta...
context.registerNamespace("aws",
"http://webservices.amazon.com/AWSECommerceService...
String title = context.getValue("//aws:Title").toStrin...
String author = context.getValue("//aws:Author").toStr...
int numOfAuthor = (int)Double.parseDouble(context.getV...
for (int i = 1; i < numOfAuthor; i++) {
String nextAuthor = "//aws:Author[" + (i+1) + "]";
author = author + ", " + context.getValue(nextAuthor)...
}
String publisher = context.getValue("//aws:Manufacture...
String publicationDate = context.getValue("//aws:Publi...
String noPages = context.getValue("//aws:NumberOfPages...
String listPrice = context.getValue("//aws:Amount").to...
titleArea.setText(title);
authorArea.setText(author);
publisherField.setText(publisher);
publicationDateField.setText(publicationDate);
noPagesField.setText(noPages);
listPriceField.setText(listPrice);
} catch (Exception e) {
e.printStackTrace();
}
}
}}
** ソースファイル [#sc3a21cd]
今回のソースを以下から参照してください。
- &ref(BookDialog.java);
- &ref(BookManager.java);
- &ref(HF04SL.java);
** コメント [#bb543b47]
この記事は、
#vote(おもしろかった,そうでもない,わかりずらい)
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
終了行:
[[FrontPage]]
2008/09/25からのアクセス回数 &counter;
#contents
SunSPOTを使った用途を考えていたときに、MITの石井さんが提...
Tangibleが浮かんだ。認識範囲の短いICTagは、ある地点の道し...
書き込みができるのでおもしろいことができると思った。
Tagibleの本家の例
http://tangible.media.mit.edu/projects/sensetable/
** ICTagの選定 [#l3e06cd5]
小型で電子工作の容易なICTagリーダライターとして、大信機器...
http://www.daishin-kiki.com/products.html
価格も1万円程度で、3.3VでRS-232C/TTLレベルで通信できると...
最近はもっと小さなリーダも見つけた(http://www.neotechkno...
HF-04SRの対象とするICTagは、ISO15693とMifare規格に対応し...
タグを使うことにしました。
*** ICTagの購入が問題 [#g1b708e0]
ICTagの広告でトップにでてくるリンテック株式会社に問い合わ...
最低でも100枚単位でないと出荷できないとのことでした。
http://www.lintec.co.jp/e-dept/britem/ictag/products/tsdc...
営業の方のご厚意でサンプルタグを送ってもらい、HF-04SRでの...
** ICTagリーダライターの動作確認 [#db76db46]
いきなりSunSPOTと接続するのは大変なので、シリアル接続でタ...
*** 秋月のUSB-シリアル変換モジュール [#qb97c876]
TTLレベルのRS-232C通信をテストする場合、レベルコンバータ...
必要ですが、秋月の[[AE-UM232R>http://akizukidenshi.com/ca...
に接続できるすぐれもの(これで950円はやすい!)。
#ref(5.jpg);
*** MacOSXでシリアル接続 [#gd689039]
私の使っているMacOSXからシリアル接続できるデバイスは少な...
- PL-2303
- FT232BM
は、MacOSX用のドライバーを公開しているそうです(http://ww...
*** ドライバーのダウンロード [#k94e243b]
FT232BM用のドライバーを[[Future Technology Devices Intern...
Tiger以降でないとだめみたいですから注意してください。
*** ターミナルソフト [#h3ebe6a3]
MacOSXで使えるターミナルソフトは、Jerminalを使用すること...
先ほどの参照ページのJerminal8095.dmgをダウンロードしまし...
*** 接続確認 [#m353b7ee]
ターミナルからJerminal(jermコマンド)を以下のオプション...
#pre{{
$ jerm -b 38400 -p none -d 8 -s 1 /dev/cu.usbserial-A5002...
}}
- ボーレート 38400
- パリティなし
- データ長 8bit
- ストップビット 1
最後の/dev/cu.cusbserial-xxxxxxは、機種によって変わります。
接続が完了すると以下のような表示でます。
#pre{{
Jerminal v0.8095 Copyright (C) 2000, 2001, 2002, 2003, 2...
Type "Ctrl-M ~ ." to exit.
ispeed 38400 ospeed 38400
+IGNBRK -BRKINT -IGNPAR -PARMRK -INPCK -ISTRIP -INLCR -I...
-IXOFF -IXANY -IMAXBEL
-OPOST -ONLCR -OXTABS -ONOEOT
cs8 -CSTOPB +CREAD -PARENB -PARODD +HUPCL +CLOCAL -CCTS_...
-CRTS_IFLOW -MDMBUF -ECHOKE -ECHOE -ECHO -ECHONL -ECHOPR...
-ISIG -ICANON -ALTWERASE -IEXTEN
-EXTPROC -TOSTOP -FLUSHO -NOKERNINFO -PENDIN -NOFLSH
}}
ICTagリーダライターとの接続を確認するために、ICTagリーダ...
を入力すると、
#pre{{
15693 V03.07
}}
めでたく、ICTag 15693に対応した V03.07であることが表示さ...
** JavaからICTagを制御する [#c63e1404]
ここでのメインテーマは、ハードをjavaで制御することですか...
*** Javaでシリアル通信をする [#b6c87793]
Javaからシリアルポート、パラレルポートを使用するためのAIP...
[[Java Communications API>http://java.sun.com/products/ja...
です。
残念ながらSunの提供するAPIは、SPARC Solaris/x86 Solaris/x...
Windowsでは使えません。
そこで、Java Communications APIに準拠したオープンソースの...
- [[RXTX : serial and parallel I/O libraries supporting S...
RXTXのサイトからrxtx-2.1-7r2.zipをダウンロードし、解凍し...
-MACOSX_IDE/ForPackageMaker/install/Library/Extensionsか...
-- librxtxSerial.jnlib
-- RXTXcomm.jar
また、RXTXの例題としてprocessing/Gainerのライブラリを使い...
- http://gainer.cc/Download/Download
からProcessingをダウンロードします。
- gainer_lib_processing_v1-1-0rc4のlibraries/gainer/libra...
-- gainer.jar
-- librxtxSerial.so
-- rxtxSerial.dll
を取り出します。
RXTXシリアル接続については、
-[[ torutkの日記>http://d.hatena.ne.jp/torutk/20071224/p1]]
を参考にさせていただきました。
*** 使用するICTag制御コマンド [#oec7ed1e]
javaで使用するICTagコマンドは
- バージョン情報 : V
- スキャンコマンド: 2XX
- 連続スキャン開始コマンド: 2XS
- 読出コマンド: 2R
- 複数ブロック書込コマンド: 2WM
としました。
各コマンドの書式では
- UID: タグのUID
- tt: タグ番号
- bb: ブロック番号
- nn: 数値
- DATA: データ
|コマンド|書式|戻り値成功時|戻り値失敗時|制約|
|バージョン情報|V[CR]|使用できるタグの種類 バージョン|な...
|スキャン|2XX[CR]|nn,UID{,UID,UID....}[CR]|00[CR]|複数タ...
|連続スキャン|2XS[CR]|01,UID[CR]|中断時None[CR]|1文字を送...
|読出|2R,tt,bb,nn[CR]|tt,yy,DATA{,tt,yy,DATA...}[CR]|00[C...
|複数ブロック書込|2WM,tt,bb,nn,DATA[CR]|tt,OK[CR]|tt,NG[C...
*** ICTag制御クラスHF04SL [#zed9ad11]
ICTag制御クラスHF04SLに各コマンドの処理を実装します。
最初にICTagのオープンですが、バージョン情報を使って接続先...
#pre{{
public boolean openICTag(String pname){
if(openSerialPort(pname)){
String returnCode="";
while(returnCode.indexOf("15693") < 0){
try{
write("V\r");
returnCode = readWithTimer(1000);
}catch(TimeoutException e){
}catch(IOException e){
}
}
return true;
}
return false;
}
}}
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);
}
}
}}
連続スキャンのキャンセルはきわめて簡単です。
#pre{{
public void cancelContScanICTag() throws IOException {
write("a");
}
}}
書込もコマンドの仕様通りです。
#pre{{
public boolean writeICTag(int tagNo, int blokNo, byte[] ...
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"));
}
}}
残りの読込は、ちょっと長くなりましたが、ほとんど仕様どお...
#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 (null);
}
else {
List<String> list = new ArrayList<String>();
int numTag = Integer.parseInt(numStr);
int count = 1;
while (available() >= 2) {
if (count++ != 1) {
numStr = read(2);
}
read(1); // skip ','
String lenStr = read(2);
read(1); // skip ','
int len = Integer.parseInt(lenStr, 16);
String data = read(len*2);
read(1); // skip ',' or [CR]
list.add(data);
}
return (list.toArray(new String[0]));
}
}
}}
必要な部品がそろったので、テストをします。
#pre{{
public static void main(String[] args) {
HF04SL ictag = new HF04SL();
try {
ictag.openICTag("/dev/cu.usbserial-A5002yHm");
System.out.println(ictag.contScanICTag());
// Icode SLIは、0ブロックに書き込めない
System.out.println(ictag.writeICTag(1, 1, "0123456789A...
String[] tagData = ictag.readICTag(01);
System.out.println(tagData[0]);
System.out.println(ictag.hexToString(tagData[0], 4, 16...
}
catch (Exception e) {
e.printStackTrace();
}
finally {
ictag.closeSerialPort();
}
}
}}
実行結果は、
#pre{{
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
RXTX Warning: Removing stale lock file. /var/lock/LK.004...
1A8FA410000104E0
true
000000003031323334353637383941424344454630303030000000000...
740069006F006E0020002000000000000000000000000000
0123456789ABCDEF
closing /dev/cu.usbserial-A5002yHm
Experimental: JNI_OnLoad called.
}}
正常に動作しました。
** サンプルアプリケーション [#g36e4259]
ICTagのサンプルアプリケーションとして、本にICTagを付け、I...
- 書籍のタイトル
- 著者
- 出版社
- 総ページ数
- 出版日
- 価格
を表示する、ダイアログを作成します。
#ref(BookManager.jpg);
+ ICTagがリーダにかざされるとダイアログを表示します。
+ ISBN番号を入力しISBN Searchボタンを押すと、 アマゾンか...
+ OKボタンで次のICTagの読込まちになります。
*** Visual Editorを使ってBookDialogを作成する [#gf0ac42e]
BookDialogは、EcdlipseのプラグインVisual Editorを使って作...
#ref(VisualEditor.jpg);
*** ISBN Searchボタンの処理(AWS検索の処理) [#dba0741e]
アマゾンの検索は、AWSを使いました。
ここで、検索結果の読込に失敗して情報をうまく取得できませ...
- [[ひびどく>http://yhd.cocolog-nifty.com/hibidoku/2005/1...
にnamespaceを指定する必要があるとのコメントを見つけ、regi...
するとうまく読み取ることができました。
#pre{{
private void searchISBN() {
String requestUrl = "http://webservices.amazon.co.jp/on...
+ "Service=AWSECommerceService&SubscriptionId=" + [ここ...
+ "&Operation=ItemSearch&ResponseGroup=Medium&SearchInd...
+ getIcbnField().getText();
try {
DocumentContainer container = new DocumentContainer(ne...
requestUrl));
container.setNamespaceAware(true);
JXPathContext context = JXPathContext.newContext(conta...
context.registerNamespace("aws",
"http://webservices.amazon.com/AWSECommerceService...
String title = context.getValue("//aws:Title").toStrin...
String author = context.getValue("//aws:Author").toStr...
int numOfAuthor = (int)Double.parseDouble(context.getV...
for (int i = 1; i < numOfAuthor; i++) {
String nextAuthor = "//aws:Author[" + (i+1) + "]";
author = author + ", " + context.getValue(nextAuthor)...
}
String publisher = context.getValue("//aws:Manufacture...
String publicationDate = context.getValue("//aws:Publi...
String noPages = context.getValue("//aws:NumberOfPages...
String listPrice = context.getValue("//aws:Amount").to...
titleArea.setText(title);
authorArea.setText(author);
publisherField.setText(publisher);
publicationDateField.setText(publicationDate);
noPagesField.setText(noPages);
listPriceField.setText(listPrice);
} catch (Exception e) {
e.printStackTrace();
}
}
}}
** ソースファイル [#sc3a21cd]
今回のソースを以下から参照してください。
- &ref(BookDialog.java);
- &ref(BookManager.java);
- &ref(HF04SL.java);
** コメント [#bb543b47]
この記事は、
#vote(おもしろかった,そうでもない,わかりずらい)
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
ページ名:
SmartDoc