Forked from: felicacontest2010's FeliCa Flash Contest - FeliCa Search sample diff:311 FeliCa Flash Contest - 歩数計 sample (http://bit.ly/55pCjn) felicacontes.. forked:0favorite:0lines:215license : see code comments modified : 2010-01-15 23:41:22 Embed Tweet <?xml version="1.0" encoding="utf-8"?> <!-- Copyright 2009 Sony Corporation --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="377" creationComplete="init()" height="458"> <mx:Button x="10" y="10" label="初期化中・・・お待ち下さい" width="357" height="46" click="onClick();" enabled="false" id="startButton" fontSize="16" fontWeight="bold"/> <mx:DataGrid y="64" width="357" height="384" dataProvider="{tableData}" resizableColumns="false" sortableColumns="false" x="10"> <mx:columns> <mx:DataGridColumn headerText="日付" dataField="date" textAlign="left"/> <mx:DataGridColumn headerText="歩数" dataField="steps" textAlign="right"/> <mx:DataGridColumn headerText="AW" dataField="aw" textAlign="right"/> <mx:DataGridColumn headerText="kcal" dataField="cal" textAlign="right"/> <mx:DataGridColumn headerText="Ex" dataField="ex" textAlign="right"/> </mx:columns> </mx:DataGrid> <mx:Script> <![CDATA[ // イベント概要,エントリー規約をご確認ください // http://wonderfl.net/event/felica // see http://wonderfl.net/event/felica for contest regulation, only in Japanese for now, sorry // copyright sony corp. all rights reserved. // copied from http://www.felicalauncher.com/sdk4air/#menu_02 with permission :-) import mx.collections.ArrayCollection; import com.sony.jp.felica.event.OpenStatusEvent import com.sony.jp.felica.event.FeliCaStatusEvent import com.sony.jp.felica.FeliCaControl import com.sony.jp.felica.FeliCaPollingAndGetCardInformationRequest import com.sony.jp.felica.FeliCaPollingAndGetCardInformationResponse import com.sony.jp.felica.FeliCaOpenReaderWriterAutoRequest import com.sony.jp.felica.FeliCaOpenReaderWriterAutoResponse import com.sony.jp.felica.FeliCaWriteBlockWithoutEncryptionRequest import com.sony.jp.felica.FeliCaWriteBlockWithoutEncryptionResponse import com.sony.jp.felica.FeliCaReadBlockWithoutEncryptionRequest import com.sony.jp.felica.FeliCaReadBlockWithoutEncryptionResponse import com.sony.jp.felica.FeliCaCloseReaderWriterRequest import com.sony.jp.felica.FeliCaCloseReaderWriterResponse [Bindable] private var tableData:ArrayCollection = new ArrayCollection(); private var fc:FeliCaControl = new FeliCaControl(); private var idm:String = ""; private var intervalId:int; private var retry:int = 0; /** * アプリケーション初期化時に呼ばれます。 * openを実行し、FeliCa Proxy Serviceとの接続を試みます。 */ private function init():void { fc.addEventListener(OpenStatusEvent.OPEN_COMPLETE, onOpenComplete); fc.addEventListener(OpenStatusEvent.OPEN_FAILURE, onOpenFailure); fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, onAccessComplete); fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_FAILURE, onAccessFailure); fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_PARAMETER_ERROR, onParameterError); fc.open(10250, "ff2a9b72-8878-40a4-9202-57834cdd898c", ""); } /** * init()で呼ばれたopenの結果が成功だった場合に呼ばれます。 * ボタンを有効化します。 */ private function onOpenComplete(evt:OpenStatusEvent):void { fc.removeEventListener(OpenStatusEvent.OPEN_COMPLETE, onOpenComplete); fc.removeEventListener(OpenStatusEvent.OPEN_FAILURE, onOpenFailure); this.startButton.label = "歩数計読み取り開始"; this.startButton.enabled = true; } /** * init()で呼ばれたopenの結果が失敗だった場合に呼ばれます。 */ private function onOpenFailure(evt:OpenStatusEvent):void { mx.controls.Alert.show("オープンに失敗しました。"); } /** * ボタンが押されたときの挙動を定義します。 * Open Reader Writer Auto を実行します。その後の処理はonAccessCompleteで為されます。 */ private function onClick():void { startButton.enabled = false; retry = 1; start(); } private function start():void { tableData.removeAll(); var openReq:FeliCaOpenReaderWriterAutoRequest = new FeliCaOpenReaderWriterAutoRequest(); fc.access(openReq); } /** * FeliCaカード、リーダ/ライタへのアクセスが成功した場合に呼ばれます。 * Open Reader Writer Auto に成功した後、Polling を試みます。 * Polling に成功した後、Write Block Without Encryption を試みます。 * Write Block Without Encryption が成功した後、Read Block Without Encryptionを試みます。 * この際、setTimeoutによって実行を遅延させます。(歩数計の仕様。) * Read Block Without Encryption が成功した後、Close Reader Writer を試みます。 * * @param evt FeliCa Status Event、実行したコマンドの結果が格納されている */ private function onAccessComplete(evt:FeliCaStatusEvent):void { if (evt.object is FeliCaOpenReaderWriterAutoResponse) { var pollingReq:FeliCaPollingAndGetCardInformationRequest = new FeliCaPollingAndGetCardInformationRequest(); pollingReq.systemCode = "FEE1" fc.access(pollingReq); } else if (evt.object is FeliCaPollingAndGetCardInformationResponse) { var pollingRes:FeliCaPollingAndGetCardInformationResponse = evt.object as FeliCaPollingAndGetCardInformationResponse; this.idm = pollingRes.idm; var writeReq:FeliCaWriteBlockWithoutEncryptionRequest = new FeliCaWriteBlockWithoutEncryptionRequest(); writeReq.idm = this.idm; writeReq.numberOfBlocks = 1; writeReq.numberOfServices = 1; writeReq.blockList.push("8001"); writeReq.serviceCodeList.push("0009"); var head:String = "0A" + "0000000000" + "0001" + "5000" + todayInBCDString(); var sum:uint = getSum(head); if (sum < 0x10) { head += "0"; } head += sum.toString(16); writeReq.blockData = head; fc.access(writeReq); } else if (evt.object is FeliCaWriteBlockWithoutEncryptionResponse) { this.intervalId = setTimeout(read, 400); } else if (evt.object is FeliCaReadBlockWithoutEncryptionResponse) { var readRes:FeliCaReadBlockWithoutEncryptionResponse = evt.object as FeliCaReadBlockWithoutEncryptionResponse; updateTable(readRes.blockData); var closeReq:FeliCaCloseReaderWriterRequest = new FeliCaCloseReaderWriterRequest(); fc.access(closeReq); } else if (evt.object is FeliCaCloseReaderWriterResponse) { setTimeout(enableButton, 1000); } } /** * FeliCaカード、リーダ/ライタへのアクセスが失敗した場合に呼ばれます。 * * @param evt FeliCa Status Event、実行したコマンドの結果が格納されている */ private function onAccessFailure(evt:FeliCaStatusEvent):void { if (retry != 0) { retry--; setTimeout(start, 1000); } else { mx.controls.Alert.show("歩数計へのアクセスに失敗しました。"); setTimeout(enableButton, 1000); } } /** * FeliCaカード、リーダ/ライタへのアクセスがパラメータエラーだった場合に呼ばれます。 * * @param evt FeliCa Status Event、実行したコマンドの結果が格納されている */ private function onParameterError(evt:FeliCaStatusEvent):void { if (retry != 0) { retry--; setTimeout(start, 1000); } else { mx.controls.Alert.show("パラメータエラーです。"); setTimeout(enableButton, 1000); } } /** * Read Block Without Encryptionを実行します。 */ private function read():void { var readReq:FeliCaReadBlockWithoutEncryptionRequest = new FeliCaReadBlockWithoutEncryptionRequest(); readReq.idm = idm; readReq.numberOfServices = 1; readReq.serviceCodeList.push("0009"); readReq.numberOfBlocks = 0x0C; readReq.blockList = ["8001", "8002", "8003", "8004", "8005", "8006", "8007", "8008", "8009", "800A", "800B", "800C"]; fc.access(readReq); } /** * 今日の日付をBCD文字列の形式で返します。 * * @return 今日の日付のBCD文字列 */ private function todayInBCDString(): String { var now:Date = new Date(); var str:String = "" + extendDigit(now.getMinutes()) + extendDigit(now.getHours()) + extendDigit(now.getDate()) + extendDigit(now.getMonth() + 1) + now.getFullYear().toString().slice(2, 4); return str; } /** * 0を付加して桁数を10に拡張します。 */ private function extendDigit(num:Number): String { var str:String = num.toString(); if (num < 10) { str = "0" + num; } return str; } /** * sumを計算します。 * * \param str 入力データ * \returns sum計算結果 */ private function getSum(str:String): int { var sum:Number = 0; var count:int = 0; while (count < str.length / 2) { var sub:String = str.slice(count * 2, count * 2 + 2); var temp:Number = parseInt(sub, 16); sum += temp; count++; } sum %= 0x100; return sum; } /** * BCD Little Endian を出力可能な文字列に変換します。 * * @param bcdLE BCD Little Endian 表記の入力データ * @return 出力可能な文字列 */ private function readable(bcdLE:String, decimal:int=0): String { var readable:String = ""; var count:int = bcdLE.length / 2; while (count >= 0) { count--; readable += bcdLE.charAt(count * 2) + bcdLE.charAt(count * 2 + 1); } while (readable.charAt(0) == "0") { readable = readable.slice(1); } if (readable == "") { readable = "0"; } else { if (decimal != 0) { readable = readable.slice(0, readable.length - decimal) + "." + readable.slice(readable.length - decimal); } } return readable; } /** * tableData の内容を更新します。 * * @param Read Block Without Encryption で読み込まれたブロックデータ */ private function updateTable(input:Array): void { var data:String = ""; for each (var block:String in input) { data += block; } var today:Date = new Date(); var day:int = 0; while (day <= 14) { var offset:int = 0x10 * 2 + day * 0x0b * 2; var thisDay:Date = new Date(today.getTime() - day * 1000 * 60 * 60 * 24); this.tableData.addItem({ date:((thisDay.getMonth() + 1).toString() + "/" + thisDay.getDate().toString()), steps:readable(data.substr(offset, 6)), aw:readable(data.substr(0x03 * 2+ offset, 6)), cal:readable(data.substr(0x06 * 2+ offset, 6), 1), ex:readable(data.substr(0x09 * 2+ offset, 4), 1) }); day++; } } /** * ボタンを有効に戻します。 */ private function enableButton():void { this.startButton.enabled = true; } ]]> </mx:Script> </mx:Application> Code Fullscreen Preview Fullscreen felica 万歩計 歩数計 substr getDate day toString