LoginSignup
2
3

More than 3 years have passed since last update.

CoreNFCでNFC Type F(Felica)をリードしてみた。

Last updated at Posted at 2019-09-27

前回補足

前回の投稿で重要だけど、ちょっと説明不足だったかなって思うところを補足します。

NFC TypeA/B/F

NFCのカードには大きく分けてType A/B/Fがあります。他にもあるみたいなんですが、かなりマイナーなのでちょっと省略します。
Type A/Bは運転免許証とかマイナンバーなんかの公共的なカードによく使われていて、国内で流通しいるのはほぼType Bと思っていいみたいです。
一方、Type FはFelicaとも言われているもので、SuicaとかPiTaPaとかの交通系ICカードによく使われています。

AID、System Code

NFC Type A/BだとAID、NFC Type FだとSystem Codeという情報があって、これを入り口にしてカード情報にアクセスします。
CoreNFCではこの情報を事前にアプリに組み込んんでおく必要があります。というかこれが無いとCoreNFCではスキャンすら成功しないので補足でした。
この設定がプロジェクトの設定の「info」タブで項目を追加するものですね。
以下、ご参考。
Type A/BのAID
typeB.png
Type FのSystem Code
typeF.png

NFC Type F

さてさて本題のType Fカードをリードしてみるんですが、一応、以下の内容はPiTaPaで動作確認したってことをお断りしておきます。
でも、ほとんどの交通系ICカードでいけると思うんですけどね。

PiTaPa

まずはカードの仕様を確認しましょう。
以下のページを参考にしました。記録情報っていう項目が重要な情報です。
https://www.wdic.org/w/RAIL/PiTaPa

接続、サービス取得、リードの実装

実装は前回の続きってことで、カードのスキャンができたところからです。
スキャンが成功すると以下のデリゲートメソッドが呼ばれます。

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
}

この引数[NFCTag]によるとカードとかタグは同時に複数を読めるみたいですね。
とりあえず必要なものは1つ目なので、こいつに向かって接続しましょう。

let tag = tags.first!
session.connect(to: tag) { (error) in
}

こんな感じでカードに接続できます。
カードに接続できたら次にサービスを取得したいんですが、そのためにはtagNFCFeliCaTag型にする必要があります。

guard case .feliCa(let feliCaTag) = tag else {
    return
}

とりあえず、こんな感じでしょう。
そうしたらfelicaTagを使ってサービスを取得できるようになります。
どれでも良いのですが、今回はカード種別を取得してみたいので、サービスコードは0x008Bです。
そうそう、サービスコードの指定はリトルエンディアンにするみたいです。

let serivces = [Data([0x8b, 0x00])]
feliCaTag.requestService(nodeCodeList: serivces, completionHandler: {
    (nodes, error) -> Void in
}

そして1ブロックをリードします。

let serivces = [Data([0x8b, 0x00])]
let blockList = [Data([0x80, 0x00])]
feliCaTag.readWithoutEncryption(serviceCodeList: serivces,
                                blockList: blockList,
                                completionHandler: {
                                    (status1, status2, dataList, error) in

                                    for data in dataList {
                                        print("\(data[8])")
                                    }
}

長かったですが、これでカード種別をリードできました。
そして出力結果は34(0x22)となり無事に「PiTaPa」で、しかも「関西私鉄/バス」ってことがわかりました。

まとめ

とにかく初心者としてはカードの仕様がよくわからず、ちょっと厄介でしたが、段階的にでも読めるようになると楽しくなってきました。
それと実装は簡単なんですが、非同期関数の連続で、ストレートに作るとエラーとか例外の処理ですぐに複雑になるので気を付けたいですね。
まあ、通信系のAPIをよく使っている人なら問題ないでしょう。

他にもAPIの引数から新幹線の乗り継ぎみたいにカード2枚以上の同時アクセスができそうなこともわかりました。

参考文献

https://www.wdic.org/w/RAIL/サイバネ規格%20%28ICカード%29
https://www.wdic.org/w/RAIL/PiTaPa

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3