プロデルで交通系ICカード履歴ビューアを作る

以前、プロデルでFeliCaポートからIDmを取得する方法をご紹介しましたが、今回はFeliCaカードの内容を解析して交通系ICカードの使用履歴を取得するビューアを作ってみたいと思います。


なお、ここでは説明にSuicaを使いますが、全国各地域で使用されている交通系ICカードはSuicaと同じ仕様ですので、Suica以外の場合でもプログラムを修正する必要はありません。

Felicaカードからデータを取得する

FeliCaカードには、FeliCaポートを通じて情報を書き込んだり読み込んだりできます。カードには用途や内容に応じて、書き込み領域が区分けされています。ただセキュリティ機能によって専用の機器以外でアクセスできないように、取得できる内容や書き込みに制限があります。幸い、Suicaをはじめとする交通系ICカードの場合は、使用履歴や残額を記録された部分から内容を制限無く取得できます。(定期券情報などにはアクセスできないみたいです)

交通系ICカードの履歴を取得する

Felicaカードから情報を取得するには、まずサービスコードを指定する必要があります。サービスコードはカードの用途ごとに割り当てられた番号です。プロデルのプラグインでは、「フェリカのSuicaサービス」と書くことで交通系ICカードのサービスコードを取得できます。カードにはサービスごとにさらに0から19までのブロックで情報が区分けされて記録されています。

Felicaプラグインでは「ブロックを取得する」手順を使って、指定したブロックの情報をバイナリ形式で取得できます。取得したバイナリ配列には、各要素に履歴情報が一件ずつ格納されていますので、ビット演算で欲しい部分の情報を抜き取ります。

ビット演算の手順

プロデルでビット演算用の手順を使えます。今回は、AND演算する「論理積」手順や、ビットのシフト演算する「左シフト」「右シフト」手順を使います。

  • 【値1】と【値2】の論理積
  • 【値】を【移動ビット数】だけ左シフトしたもの
  • 【値】を【移動ビット数】だけ右シフト

Suicaの履歴データでは、残高や日付に関する情報が複数のバイトにまたがって記録されています。論理積(値1と値2で共に1のビットだけを返す)やシフト(指定したビット数だけ桁を移動する)を行うことで、バイト値から目的の値の部分だけを取り出したり、複数バイトにまたがる情報をつなぎ合わせて、記録された値を取り出していきます。

履歴を一つずつ表示する

「Produire.Felica.dll」を利用する
日マスクは、二進数から「0000000000011111」の十進数
月マスクは、二進数から「0000000111100000」の十進数
年マスクは、二進数から「1111111000000000」の十進数

フェリカポートで交通系カードを受け付けしてマイスイカとする
マイスイカのサービスコードは、フェリカのSuicaサービス

0から19までブロックを増やしながら繰り返す
  マイスイカからブロックを取得して結果とする
  結果からすべて読み取ってデータとする
  残高は、データ(12)を8だけ左シフトしたもの+データ(11)
  残高を報告する
  日付値は、データ(5)を8だけ左シフトしたもの+データ(6)
  日時は、「[年マスクと日付値の論理積を9だけ右シフト+2000]/[月マスクと日付値の論理積を5だけ右シフト]/[日マスクと日付値の論理積]」
  日時を報告

  入線区は、データ(7)
  入駅順は、データ(8)
  入線区を報告
  入駅順を報告
繰り返し終わり

一つの履歴には、残高・日時・入場駅・出場駅・履歴の種類が記録されています。最後の記録が順番に記録されていますので、最初のブロックに書かれた残高がSuicaのチャージ残高です。

このようなブロックに記録されたバイナリデータの内容は、たとえはSuicaやWAON, nanacoなどそれぞれのカードの仕様に基づいていて記録されています。これらの正式な仕様は、公開されていませんが、有志によって内容が解析されて公開されています。

felicalib プロジェクト Wiki

FeliCaカード用ライブラリを使う

このようにしてバイナリデータからカードの内容を解析することで必要な情報を抽出できます。ただSuicaの仕様書を見ながらバイナリ操作をする必要があるので、少々手間が掛かります。

そのため、プロデルのFeliCaプラグインのサンプルとして、FeliCaカードのデータを読み取るためのライブラリプログラム「FeliCaライブラリ.rdr」を用意しています。このライブラリプログラムを使えば簡単にSuicaの情報を抽出できます。

ライブラリを使って、リストビューに履歴を表示するプログラムがサンプルとして用意してあります。
次のプログラムでは、ボタンをクリックすると、Suicaから読み取った履歴から20件分の日時と残高を表示します。

「FeliCaライブラリ.rdr」を参照する
メイン画面を表示する
待機する

メイン画面とは
  ウィンドウを継承する

  はじめの手順
    初期化する
    ーー貼り付けた部品に対する操作をここに書きます
  終わり

  初期化する手順
    ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
    この内部領域大きさを{284、262}に変える
    この内容を「Suicaの読み取り」に変える
    このドラッグドロップを○に変える
    ボタン1というボタンを作る
      その位置と大きさを{13、13、75、23}に変える
      その内容を「取得」に変える
      その移動順を1に変える
    リストビュー1というリストビューを作る
      その位置と大きさを{12、42、260、208}に変える
      その表示方法を「詳細」に変える
      その全列選択を○に変える
      その見出し一覧を{「日時」、「残高」}に変える
      その見出し幅を{115、101}に変える
      その移動順を2に変える
      その位置固定方向を「右+左+下+上」に変える
  終わり

  ボタン1がクリックされた時の手順
    Suicaから読み取る
    Suicaの履歴一覧のすべての履歴についてそれぞれ繰り返す
      リストビュー1に履歴の日時を追加する
        その詳細を{履歴の残高}に変える
    繰り返し終わり
  終わり
終わり

路線名と駅名を調べる

「FeliCaライブラリ.rdr」を使って、残高や日時などの情報を調べることはできました。

履歴には、電車に乗るときに乗った駅(入場駅)・降りた駅(出場駅)も番号で記録されています。ただ、この番号を見てもどの駅であるか分かりません。番号と駅との対応表が必要ですが、全国の鉄道駅の対応表は有志によってまとめられたサイトがあります。

http://www014.upp.so-net.ne.jp/SFCardFan/

ただ残念なことに2017年8月現在は、正常にデータベースがダウンロードできなくなってしまっています。そこで今回は、筆者が以前控えていたデータを使うことにします。StationCode.csvは、こちらからダウンロードできますのでお使い下さい。このCSVファイルは、Excelワークシート(mdb用)の内容をそのままCSV形式に変換したものです。

StationCode.csv

CSVファイルの内容は、次の内容がカンマ区切りで順番に記録されています。

AreaCode,LineCode,StationCode,CompanyName,LineName,StationName,Note
0,2,1,東日本旅客鉄道,東北本,東京,

Suicaの履歴にある入場駅と出場駅には、2列目(線区:LineCode)と3列目(駅:StationCode)が記録されています。
そこで、まずStationCode.csvから、キーが路線番号+駅番号で、値が路線名+駅名の「駅コード」辞書を作り、駅の一覧を登録します。辞書には、次のようなキーと値の関係を登録していきます。

キー
2,1東北本線 東京
1,114東海道本線 名古屋
データ表を作ってデータとする
データへ「StationCode.csv」から読み込む
一覧は、データの一覧
駅コードは、空の辞書
行番号を1から一覧の個数まで増やしながら繰り返す
  レコードは、一覧(行番号)
  駅コード(「[レコード(2)],[レコード(3)]」)は、「[レコード(5)]線 [レコード(6)]」
繰り返し終わり

履歴に記録された線区と駅の組み合わせを使って、登録した「駅コード」辞書から路線名と駅名を調べるには次のような書きます。

入場駅名は、駅コード(「[履歴の入線区],[履歴の入駅順]」)
出場駅名は、駅コード(「[履歴の出線区],[履歴の出駅順]」)

なお、Suicaの実際の履歴には、物販やチャージなどの履歴も記録されていますので、「入線区」または「出線区」が0の場合もあります。

履歴ビューアの作成

最初の履歴表示プログラムを改良して、乗った駅と降りた駅の、路線名と駅名を表示できるように改良してみます。完成したプログラムは、次の通りです。

「FeliCaライブラリ.rdr」を参照する
データ表を作ってデータとする
データへ「StationCode.csv」から読み込む
一覧は、データの一覧
駅コードは、空の辞書
行番号を1から一覧の個数まで増やしながら繰り返す
  レコードは、一覧(行番号)
  駅コード(「[レコード(2)],[レコード(3)]」)は、「[レコード(5)]線 [レコード(6)]」
繰り返し終わり
メイン画面を表示する
待機する

メイン画面とは
  ウィンドウを継承する
  
  はじめの手順
    初期化する
    ーー貼り付けた部品に対する操作をここに書きます
  終わり

  初期化する手順
  ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
  この内部領域大きさを{507,262}に変える
  この内容を「Suicaの読み取り」に変える
  ボタン1というボタンを作る
    その位置と大きさを{13,13,75,23}に変える
    その内容を「取得」に変える
    その移動順を1に変える
    そのドラッグドロップを×に変える
  リストビュー1というリストビューを作る
    その位置と大きさを{12,42,483,208}に変える
    その表示方法を「詳細」に変える
    その全列選択を○に変える
    その見出し一覧を{「日時」,「残高」,「入場駅」,「出場駅」}に変える
    その見出し幅を{115,80,117,118}に変える
    その移動順を2に変える
    そのドラッグドロップを×に変える
    その位置固定方向を「右+左+下+上」に変える
終わり

  ボタン1がクリックされた時の手順
    Suicaから読み取る
    リストビュー1をクリアする
    Suicaの履歴一覧のすべての履歴についてそれぞれ繰り返す
      もし履歴の入線区が0なら
        入場駅名は、「」
      そうでなければ
        入場駅名は、駅コード(「[履歴の入線区],[履歴の入駅順]」)
      もし終わり
      もし履歴の出線区が0なら
        出場駅名は、「」
      そうでなければ
        出場駅名は、駅コード(「[履歴の出線区],[履歴の出駅順]」)
      もし終わり
      リストビュー1に履歴の日時を追加する
         その詳細を{履歴の残高,入場駅名,出場駅名}に変える
    繰り返し終わり
  終わり
終わり

まとめ

今回は、FeliCaカードからデータを取得して、そのデータからSuicaの履歴情報を抽出して、残金や利用日を表示するプログラムを作りました。
またさらに実用的に使えるように、路線名データから乗り降りした駅名を表示するようにしました。

FeliCaプラグインのサンプルには、WAONカードから残額を取得するプログラム例もあります。もしWAONを持っている方は、残金が簡単に記録家計簿ツールを作ることもできます。
FeliCaはライセンスの関係で、一般開発者が読み書きできる情報に制限がありますが、交通系ICカードや電子マネーのような利用可能な情報を最大限利用して、またプロデルの他の機能と組み合わせて、より自分にとって便利なツールを作ってみるのはいかがでしょうか?

  • いいね (10)
  • 続編を読みたい (29)

コメントを残す