今回は、プロデルFeliCaプラグインを使ったFeliCa Lite-Sカードのデータを読み書きプログラムを紹介します。以前の記事では、カード固有のIDmを読み取ったり、Suicaなどの交通系ICカードの履歴を読み取ったりする例を紹介しました。好評だったので続きとしてスタンプラリーアプリを作る例を紹介します。
最新版のプロデルFeliCaプラグインでは、認証を必要としないブロックへの書き込み操作するための手順を追加しました。プロデルプラグインが利用するfelicalibというライブラリでは、以前から書き込みに対応していました。ただ普段手にするFeliCaカードは、認証が必要な自由に書き込みができないタイプですので、プロデルプラグインでは対応していませんでした。
今回は、認証不要で自由に読み書きができるFeliCa Lite-Sカードと最新版のプラグインを使って、FeliCaカードのデータを読み書きするプログラムを作ってみます。
準備
今回は次の物を使います。
- PaSoRi (RC-S320もしくはRC-S380、ノートPC組み込みのFeliCaポートでもOKです)
- FeliCa Lite-Sカード
- PC/SCプラグインもしくはプロデルFeliCaプラグイン
FeliCa Lite-Sカードについて
データを書き込むには、FeliCa Lite-Sカードが必要です。FeliCa Lite-Sカードは、SuicaなどのFeliCaカードに比べてセキュリティを簡素化し記録できる容量も最低限にすることで、値段を安くしたFeliCaカードです。FeliCa Lite-Sカードは、Amazonなどで1セット5枚程度から買えます。
このカードは「FeliCa Lite-S」で検索するとページがたくさん出てきますので、詳しい説明は割愛しますが、FeliCa Lite-Sではデータを書き込むこともできるので、読み取りしかできなかったSuicaなどよりも利用用途が広がります。もちろんIDmも取得できます。
FeliCa Lite-Sには、1ブロック16バイトで0番から13番までの合計14ブロック分の自由に書き込める領域があります。
一度の命令で1ブロック分を記録できます。16バイトは半角英数字16文字分で、日本語(Shift-JIS)だと8文字分です。UTF-8の場合はさらに少ない6文字程度です。
書き込み可能領域の部分だけをイメージ図を示しました。実際には改ざん検出の機能のための制御領域もあり、もう少し複雑です。Sony公式の仕様書が公開されていますので気になる方はそちらをお調べ下さい。今回は誰でも変更可能な単純なデータの読み書きのみに使ってみます。
データを書き込んで読み込んでみる
では実際にFeliCa Lite-Sカードにデータを書き込んでみます。次のプログラムでは、ブロック番号0番に今の日時を記録します。その後に、0番目のブロックの内容を取得して、書き込めたかどうか確認します。
FeliCa Lite-Sカードでは、システムコードが0x88B4、読み書きに使うサービスコードは、0x0009で固定です。確認のためにIDmも取得しておきます。
「Produire.Felica.dll」を利用する
フェリカポートで0x88B4を受け付けして白カードとする
白カードからIDmをテキストで取得して報告する
白カードのサービスコードは、0x0009
ブロック番号は、0
白カードでブロック番号に「[今を「yy/MM/ddHH:mm:ss」に整えたもの]」を書き込む
白カードからブロック番号をテキストで取得して結果とする
結果を報告する
『書き込む』手順で、カードにデータを書き込みます。データには、文字列またはバイナリデータを指定できます。逆に「テキストで取得する」手順で、カードに記録されたデータを文字列で読み取ります。バイナリデータで取得するには、「取得する」手順を使います。
1ブロックに記録できるのは、日時や名前、学籍番号などのIDぐらいです。カード1枚には、14ブロックだけ記録できますので、工夫すればもう少し記録できます。それでも簡単な文章程度で、画像や音声データを記録できるだけの容量はありません。
「Produire.Felica.dll」を利用する
フェリカポートで0x88B4を受け付けして白カードとする
白カードのサービスコードは、0x0009
0から13までブロックを増やしながら繰り返す
白カードでブロックに[1000000000から10000000000までの乱数]を書き込む
繰り返し終わり
0から13までブロックを増やしながら繰り返す
白カードからブロックをテキストで取得して結果とする
結果を報告する
繰り返し終わり
スタンプラリーアプリを作る
カードへ書き込む機能を使って、スタンプラリーアプリを作ってみようと思います。PaSoRiをスタンプ場所に見立てて、台紙にスタンプを押す代わりにカードをタッチするとカードへ呪文が記録されて、すべての呪文を集めるとメッセージを表示するプログラムを作ってみます。
スタンプラリーでは、それぞれのスタンプ場所にPCとPaSoRiを用意しておきます。それぞれのPC上のプロデルで、記録先のブロック番号と、書き込む呪文を変えたプログラムを実行しておきます。
利用者は、カードを1枚持ち、順番にスタンプ場所のPaSoRiにタッチしていきます。呪文がそろった時点で「おめでとう!」と表示させることにします。
残念ながら筆者の手元にはPaSoRiが1台しかないので、今回は呪文が異なるだけのプログラムを3つ用意して、順番に起動して記録することにします。
ロジックを考える
スタンプラリーアプリの動作を考えてみましょう。ここでは、スタンプ場所が3つあるとします。そこで呪文を3種類配列として用意します。
カードには、指定した「スタンプ番号」に応じてブロック番号を決めて、そのブロックに呪文を記録するようにします。ブロック番号は、0から始まりますので、スタンプ番号から-1します。カードが置かれているときに、実際に呪文を書き込みます。
そして、0から2までのブロックをすべて確認して、それぞれのブロックに呪文が記録されているかどうかを確認します。呪文が一致するブロックの個数をカウントしておき、それが3つになったら、「おめでとう」と表示されます。
それでは、スタンプラリーのロジックを確認するために、テストプログラムを作ってみます。
「Produire.Felica.dll」を利用する
フェリカポートで0x88B4を受け付けして白カードとする
白カードのサービスコードは、0x0009
スタンプ番号は、1 //スタンプ場所ごとに番号を変えておく
呪文は、{「きりん」,「アライグマ」,「うさぎ」}
白カードでスタンプ番号-1に呪文(スタンプ番号)を書き込む
// 集まったかどうか判定する
集めた個数は、0
0から(呪文の個数-1)までブロックを増やしながら繰り返す
白カードからブロックをテキストで取得して中身とする
もし中身が呪文(ブロック+1)なら集めた個数を増やす
繰り返し終わり
もし集めた個数が呪文の個数なら
「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行]スタンプがぜんぶ集まりました。おめでとう!」を表示する
そうでなければ
「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行][集めた個数]個集まりました。」を表示する
もし終わり
「スタンプ番号」変数の番号を1から3まで変えておき、カードには
その番号に応じた呪文を書き込みます。
カードをクリアする
カードに3つの呪文が集まると、「おめでとう!」メッセージが表示されます。何度もテストできるように、カードの呪文をクリアするプログラムも作っておきましょう。
「Produire.Felica.dll」を利用する
フェリカポートで0x88B4を受け付けして白カードとする
白カードのサービスコードは、0x0009
空データというバイナリデータを作る
16回繰り返す
空データに0を書き込む
繰り返し終わり
0から13までブロックを増やしながら繰り返す
白カードでブロックに空データを書き込む
繰り返し終わり
「スタンプをリセットしました。」を報告する
16バイト分値を0で埋めたデータを、0から13までのブロックに書き込んでいきます。
画面を作る
メッセージボックスだけでは寂しいので、ウィンドウの設計で画面を作ります。文字を大きめにして視覚的にわかりやすいデザインにしてみます。
カードの検出
先ほどのテストプログラムは、PaSoRiにカードが置かれていることが前提でしたが、実際にはカードが置かれていない状態もあります。
そこでアプリでは、「タイマー」種類を使って3秒ごとポーリングすることにします。カードが置かれているかどうかは、「フェリカポートで受け付けする」手順の戻り値が「無」かどうかで判定できます。
タイマーが時間になったときの手順の部分のプログラムは、次の通りです。
-カードIDm=「」
時間になった手順
フェリカポートで0x88B4を受け付けして白カードとする
もし白カードが無でなければ
// カードが置かれた時
白カードからIDmをテキストで取得して読み取り結果とする
もしカードIDmが読み取り結果なら繰り返しを続ける
カードIDmは、読み取り結果
白カードのサービスコードは、0x0009
白カードで(スタンプ番号-1)に呪文(スタンプ番号)を書き込む
// 集まったかどうか判定する
集めた個数は、0
1から呪文の個数まで番号を増やしながら繰り返す
白カードから(番号-1)をテキストで取得して中身とする
もし中身が呪文(番号)なら集めた個数を増やす
繰り返し終わり
もし集めた個数が呪文の個数なら
メッセージラベルの文字色は、赤
メッセージラベルの内容は、「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行]スタンプがぜんぶ集まりました。[改行]おめでとう!」
そうでなければ
メッセージラベルの文字色は、青
メッセージラベルの内容は、「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行][集めた個数]個集まりました。」
もし終わり
そうでなければ
メッセージラベルの文字色は、黒
メッセージラベルの内容は、「カードを置いてね」
もし終わり
終わり
カードが置かれているかどうかや、スタンプの集まり状況に応じてメッセージの色を変えています。ポーリング処理やメッセージを表示するプログラムが増えていますが、それ以外は最初に作ったテストプログラムをほぼそのままです。
完成!
スタンプラリーアプリが完成しました。もし3台分のPCとPaSoRiを用意できる場合は、実際に試してみるとスタンプラリーの気分で遊ぶことができるかと思います。
参考にプログラム全体も載せておきます。
「Produire.Felica.dll」を利用する
呪文は、{「きりん」,「アライグマ」,「うさぎ」}
スタンプ番号は、3
メイン画面を表示する
待機する
メイン画面とは
ウィンドウを継承する
はじめの手順
初期化する
ーー貼り付けた部品に対する操作をここに書きます
タイマー1というタイマーを作る
タイマー1の時間になった時の手順は、時間になった
タイマー1の間隔を3000に変える
タイマー1を開始する
終わり
初期化する手順
ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
この設計スケール比率を{144,144}に変える
この実質大きさを{686,417}に変える
この内容を「スタンプラリー」に変える
初期化開始する
メッセージラベルというラベルを作る
その位置と大きさを{77,150,554,187}に変える
その内容を「こんにちは」に変える
そのフォントを「MS UI Gothic,18」に変える
その文字配置を「上中央」に変える
その移動順を1に変える
ラベル1というラベルを作る
その位置と大きさを{176,48,417,102}に変える
その内容を「スタンプラリー」に変える
そのフォントを「Segoe UI Symbol,28」に変える
その移動順を2に変える
その文字色を「RoyalBlue」に変える
初期化終了する
終わり
-カードIDm=「」
時間になった手順
フェリカポートで0x88B4を受け付けして白カードとする
もし白カードが無でなければ
// カードが置かれた時
白カードからIDmをテキストで取得して読み取り結果とする
もしカードIDmが読み取り結果なら繰り返しを続ける
白カードのサービスコードは、0x0009
白カードで(スタンプ番号-1)に呪文(スタンプ番号)を書き込む
// 集まったかどうか判定する
集めた個数は、0
1から呪文の個数まで番号を増やしながら繰り返す
白カードから(番号-1)をテキストで取得して中身とする
もし中身が呪文(番号)なら集めた個数を増やす
繰り返し終わり
もし集めた個数が呪文の個数なら
メッセージラベルの文字色は、赤
メッセージラベルの内容は、「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行]スタンプがぜんぶ集まりました。[改行]おめでとう!」
そうでなければ
メッセージラベルの文字色は、青
メッセージラベルの内容は、「"[呪文(スタンプ番号)]"のスタンプをゲットしました。[改行][集めた個数]個集まりました。」
もし終わり
そうでなければ
メッセージラベルの文字色は、黒
メッセージラベルの内容は、「カードを置いてね」
もし終わり
終わり
終わり
実行可能ファイルにする時の注意
FeliCaプラグインは、32ビット向けに用意されています。64ビット版のWindowsでもプロデルデザイナ上では動作しますが、実行可能ファイルとして作成するときには、常に32ビットで起動する(WoW64を有効にする)必要があります。
有効にするには、プロデルデザイナの「オプション」→「プログラム」の「常に32ビット(WoW64)で起動する」にチェックしてください。
まとめ
今回は、自由にデータを書き込めるFeliCa Lite-Sカードを使って、カードに記録するスタンプラリー風のアプリを作りました。記録容量は多くありませんが、IDや呪文ならカードに記録できるので、例えば受付や作業進捗をカードに記録して、状況を把握したりするといった用途に使うことができるかと思います。
プロデルではこのようなデスクトップアプリを作るのが得意な日本語プログラミング言語です。ぜひ身近な物でFeliCaを利用したアプリをプロデルで作ってみましょう。