forked from: FeliCa Flash Contest - FeliCa Search sample
複数のFeliCaを使って図形を描画します。
(一回りを勤務時間にして、休憩や作業時間のビジュアル化を試みたのですが、実用的なレベルまでになってないです。)
/*
複数のFeliCaを使って図形を描画します。
(一回りを勤務時間にして、休憩や作業時間のビジュアル化を試みたのですが、実用的なレベルまでになってないです。)
*/
package {
import com.sony.jp.felica.FeliCaCloseReaderWriterRequest;
import com.sony.jp.felica.FeliCaCloseReaderWriterResponse;
import com.sony.jp.felica.FeliCaControl;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoRequest;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoResponse;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationRequest;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationResponse;
import com.sony.jp.felica.FeliCaSessionRequest;
import com.sony.jp.felica.FeliCaSessionResponse;
import com.sony.jp.felica.error.FeliCaAccessError;
import com.sony.jp.felica.event.FeliCaStatusEvent;
import com.sony.jp.felica.event.OpenStatusEvent;
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.clearInterval;
import flash.utils.setInterval;
[SWF(width="465", height="465", backgroundColor="#111111", frameRate="60")]
public class FeliCaContest extends MovieClip {
private const TIMESCALE:int = 30;
private var txtLog:TextField = new TextField();
private var logFormat:TextFormat = new TextFormat();
public function FeliCaContest() {
trace("###################");
format.color = 0xDDDDDD;
txtIDm.text = "txtIDm:";
txtIDm.autoSize = TextFieldAutoSize.LEFT;
txtIDm.defaultTextFormat = format;
txtIDm.x = 10;
txtIDm.y = 10;
this.addChild(txtIDm);
this.logFormat.color = 0x333333;
this.logFormat.size = 9;
txtLog.text = "";
txtLog.autoSize = TextFieldAutoSize.LEFT;
txtLog.defaultTextFormat = logFormat;
txtLog.x = this.stage.stageWidth / 2;
txtLog.y = 10;
this.addChild(txtLog);
graphInit();
init();
pollingStart();
}
private var counter:int = 1;
// エラー情報
private var error:Object = {felica: "0", rw: "0", proxy: "0"};
// 連続 Polling 終了フラグ
private var exitPollingFlag:Boolean = false;
// FeliCaProxy との通信を行うコントロールクラス
private var fc:FeliCaControl = new FeliCaControl();
private var format:TextFormat = new TextFormat();
private var g:Graphics;
private var g2:Graphics;
private var idm:String; //Felica製造ID
private const r:int = 200; //半径
// private var runFlag:Boolean = false;
private var s:Sprite;
private var s2:Sprite;
// private var textArea1:TextField = new TextField();
private var txtIDm:TextField = new TextField();
private var txtPMm:TextField = new TextField();
// 連続 Polling を行なう間隔に対する一意の数値識別子(呼び出しID)
private var waitIntervalId:uint = 0;
// FeliCaProxy の切断
private function FeliCaProxyClose():void {
if(fc.close() == true) {
displayMessage("FeliCaProxy との接続を切断しました。");
} else {
displayMessage("FeliCaProxy との接続を切断に失敗しました。");
}
idm = null;
}
/**
* FeliCa を検出するために、Polling の実行
*/
private function Polling():void {
// [polling_and_get_card_information] コマンドを実行する為の情報の設定
var request:FeliCaPollingAndGetCardInformationRequest = new FeliCaPollingAndGetCardInformationRequest();
request.systemCode = "FFFF"; // ポーリングするシステムコード
// [polling_and_get_card_information] コマンドを実行
fc.access(request);
}
// リーダ/ライタのクローズを実行
private function RwClose():void {
// [close_reader_writer] コマンドを実行
fc.access(new FeliCaCloseReaderWriterRequest());
}
// リーダ/ライタの専有を実行
private function RwLock():void {
// リーダ/ライタを専有する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.HOLD; // リーダ・ライタ専有要求
request.lockTimeout = 10; // 専有(Lock)するまでのタイムアウト時間(秒)
request.unlockTimeout = 60; // 専有(Lock)してから開放(Unlock)するまでの見込み時間(秒)
// FeliCaProxyは、このunlockTimeout時間経過した場合自動でR/W開放を行う。
// リーダ/ライタ専有を実行
fc.access(request);
}
// リーダ/ライタのオープンを実行
private function RwOpen():void {
// [open_reader_writer_auto] コマンドを実行
fc.access(new FeliCaOpenReaderWriterAutoRequest());
}
// リーダ/ライタ専有の開放を実行
private function RwUnlock():void {
// リーダ/ライタ専有を開放する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.RELEASE; // リーダ・ライタ開放要求
// リーダ/ライタ専有開放を実行
fc.access(request);
}
private function clickHandler(e:MouseEvent = null):void {
trace("clickHandler");
if(exitPollingFlag == false) {
// 連続 Polling 終了フラグのセット
this.exitPollingFlag = true;
} else {
this.txtLog.text = "";
counter = 0;
reStart();
resetGraph();
}
}
// [FeliCa を検出を開始する] ボタンクリック時
private function reStart():void {
// 連続 Polling 終了フラグの初期化
this.exitPollingFlag = false;
// 連続 Polling を行なう間隔に対する一意の数値識別子の初期化
this.waitIntervalId = 0;
fcOpen();
}
// メッセージの表示
private function displayMessage(msg:String):void {
trace(msg);
}
private function drawTriangle(x1:int, y1:int, x2:int, y2:int, x3:int, y3:int, c:uint):void {
g.beginFill(c);
g.moveTo(x1, y1);
g.lineTo(x2, y2);
g.lineTo(x3, y3);
g.lineTo(x1, y1);
}
private function enterFrameHandler(e:Event):void {
// trace("enterFrameHandler");
//trace(i % 180)
if(counter % (360 * TIMESCALE) == 0) {
// 連続 Polling 終了フラグのセット
this.exitPollingFlag = true;
// runFlag = false;
}
if(exitPollingFlag == false) {
if(counter % 360 == 0) {
resetGraph();
}
g2.lineTo(Math.cos(counter * Math.PI / 180) * r, Math.sin(counter * Math.PI / 180) * r);
//g.moveTo(0,0);
//g.lineTo(Math.sin(i* Math.PI / 180)*r,Math.cos(i* Math.PI / 180)*r);
//radian = from 0 to Math.PI *2
if(counter % TIMESCALE == 0) {
var c:int = counter / TIMESCALE;
var x1:int = Math.cos((c - 1) * Math.PI / 180) * r;
var y1:int = Math.sin((c - 1) * Math.PI / 180) * r;
var x2:int = Math.cos(c * Math.PI / 180) * r;
var y2:int = Math.sin(c * Math.PI / 180) * r;
if(idm != null) {
var n:Number = Number("0x" + idm) >> 12 & 0xffffff;
drawTriangle(0, 0, x1, y1, x2, y2, n);
}
}
}
counter++;
}
/**
* 連続 Polling 実行待ち合わせ完了時
*/
private function execPolling():void {
// 指定した setInterval() 呼び出しをキャンセル
clearInterval(this.waitIntervalId);
// FeliCa を検出するために、Polling の実行
Polling();
}
private function graphInit():void {
// runFlag = true;
s = new Sprite();
g = s.graphics;
s2 = new Sprite();
g2 = s2.graphics;
s2.x = this.stage.stageWidth / 2;
s2.y = this.stage.stageHeight / 2;
this.addChild(s2);
s.x = this.stage.stageWidth / 2;
s.y = this.stage.stageHeight / 2;
this.addChild(s);
resetGraph();
}
private function init():void {
fc.addEventListener(OpenStatusEvent.OPEN_COMPLETE, onOpenComplete);
fc.addEventListener(OpenStatusEvent.OPEN_FAILURE, onOpenFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, onFeliCaAccessComplete);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_FAILURE, onFeliCaAccessFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_PARAMETER_ERROR, onFeliCaAccessParameterError);
}
/**
* 次の実行処理を行なう
* 連続 Polling をそのまま行なうか
* 連続 Polling を終了してリーダ/ライタのクローズを行なう
*/
private function nextProcess():void {
if(this.exitPollingFlag == true) {
// リーダ/ライタのクローズを実行
RwClose();
} else {
// 次の Polling まで 500 ミリ秒待ち合わせる
this.waitIntervalId = setInterval(execPolling, 500);
}
}
/**
* FeliCa アクセス成功時
* @param evt
*/
private function onFeliCaAccessComplete(evt:FeliCaStatusEvent):void {
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
this.stage.addEventListener(MouseEvent.CLICK, clickHandler);
if(evt.object is FeliCaSessionResponse) {
var session:FeliCaSessionResponse = evt.object as FeliCaSessionResponse;
// リーダ/ライタの専有
if(session.type == FeliCaSessionResponse.HOLD) {
displayMessage("リーダ/ライタの専有しました。");
// リーダ/ライタのオープンを実行
RwOpen();
} else {
// リーダ/ライタの開放
displayMessage("リーダ/ライタの専有を開放しました。");
// FeliCaProxy の切断
FeliCaProxyClose();
}
} else if(evt.object is FeliCaOpenReaderWriterAutoResponse) {
displayMessage("リーダ/ライタのオープンに成功しました。");
// 連続 Polling を終了させる関数をミリ秒単位で指定した間隔ごとに実行
// ※ 今回は 30 秒とする
// this.pollingIntervalId = setInterval(exitPolling, 60*1000);
// FeliCa を検出するために、Polling の実行
Polling();
} else if(evt.object is FeliCaPollingAndGetCardInformationResponse) {
var response:FeliCaPollingAndGetCardInformationResponse = evt.object as FeliCaPollingAndGetCardInformationResponse;
if(idm != response.idm) {
// FeliCa を検出した時の画像に変更する
// this.imgAutoPolling.source = "./image/find.gif";
// 検出した FeliCa の情報を表示
idm = response.idm;
this.txtIDm.text = response.idm;
this.txtPMm.text = response.pmm;
displayMessage("FeliCa を検出しました。\n" + " idm = " + response.idm + "\n" + " pmm = " + response.pmm);
var d:Date = new Date();
this.txtLog.appendText("LOGIN:" + response.idm + "(" + d.toLocaleTimeString() + ")\n");
}
// エラー情報のクリア
this.error["felica"] = response.felicaError;
this.error["rw"] = response.rwError;
this.error["proxy"] = response.felicaProxyError;
// 次の実行処理を行なう
this.nextProcess();
} else if(evt.object is FeliCaCloseReaderWriterResponse) {
displayMessage("リーダ/ライタのクローズに成功しました。");
// リーダ/ライタ専有の開放
RwUnlock();
}
}
/**
* FeliCa アクセス失敗時
* @param evt
*/
private function onFeliCaAccessFailure(evt:FeliCaStatusEvent):void {
var errorMsg:String;
if(evt.object is FeliCaAccessError) {
var error1:FeliCaAccessError = evt.object as FeliCaAccessError;
if(error1.rwError == 157) {
if(error1.rwError != this.error["rw"]) {
if(idm != null) {
var d:Date = new Date();
this.txtLog.appendText("LOGOUT:" + idm + "(" + d.toLocaleTimeString() + ")\n");
}
// 検出した FeliCa の情報を表示するテキストエリアをクリア
idm = null;
this.txtIDm.text = "";
this.txtPMm.text = "";
// メッセージの表示
displayMessage("FeliCa を検出できませんでした。");
}
// 次の実行処理を行なう
this.nextProcess();
} else {
if((this.error["felica"] != error1.felicaError) || (this.error["rw"] != error1.rwError) || (this.error["proxy"] != error1.felicaProxyError)) {
// エラー情報の表示
errorMsg = " ERROR: (" + error1.errorID + ")" + error1.message + "\n" + " FeliCa Error Code (" + error1.felicaError + ")\n" + " RW Error Code (" + error1.rwError + ")\n" + " FeliCaProxy Error Code (" + error1.felicaProxyError + ")";
displayMessage("FeliCa アクセスに失敗しました\n" + errorMsg);
}
}
// エラー情報のセット
this.error["felica"] = error1.felicaError;
this.error["rw"] = error1.rwError;
this.error["proxy"] = error1.felicaProxyError;
} else if(evt.object is Error) {
var error2:Error = evt.object as Error;
// エラー情報の表示
errorMsg = " ERROR : (" + error2.errorID + ") " + error2.message;
displayMessage("FeliCa アクセスに失敗しました\n" + errorMsg);
// FeliCaProxy の切断
FeliCaProxyClose();
}
}
/**
* FeliCa アクセスパラメータ設定エラー発生時
* @param evt
*/
private function onFeliCaAccessParameterError(evt:FeliCaStatusEvent):void {
var error:Error = evt.object as Error;
displayMessage("FeliCa アクセスでパラメータエラーが発生しました。\n" + " ERROR: (" + error.errorID + ")" + error.message);
// FeliCaProxy の切断
FeliCaProxyClose();
}
/**
* FeliCaProxy との認証完了時
* @param evt
*/
private function onOpenComplete(evt:OpenStatusEvent):void {
displayMessage("FeliCaProxy との認証に成功しました。");
// リーダ/ライタの専有
RwLock();
}
/**
* FeliCaProxy との認証処理でエラー発生時
* @param evt
*/
private function onOpenFailure(evt:OpenStatusEvent):void {
var error:Error = evt.object as Error;
displayMessage("FeliCaProxy との相互認証に失敗しました。\n" + " ERROR : (" + error.errorID + ") " + error.message);
}
// [FeliCa を検出を開始する] ボタンクリック時
private function pollingStart():void {
// 連続 Polling 終了フラグの初期化
this.exitPollingFlag = false;
// 連続 Polling を行なう間隔に対する一意の数値識別子の初期化
this.waitIntervalId = 0;
fcOpen();
}
private function fcOpen():void{
// FeliCaProxy の認証
//fc.open(10250);
fc.open(10250, "__FELICA_STANDARD_KEY__", "");
}
private function resetGraph():void {
// trace(counter);
if(exitPollingFlag == false) {
g2.clear();
g2.lineStyle(1, 0xffffff);
g2.moveTo(r, 0);
if(counter % (TIMESCALE * 360) == 0) {
counter = 1;
g.clear();
g.moveTo(r, 0);
}
}
}
}
}