/* 複数の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); } } } } } forked from: FeliCa Flash Contest - FeliCa Search sample