Skip to content

Commit

Permalink
Merge pull request #26 from sakapon/v1.2
Browse files Browse the repository at this point in the history
v1.2.67 request
  • Loading branch information
sakapon committed Mar 27, 2014
2 parents 2ca89cf + 7ff3e4a commit a087a45
Show file tree
Hide file tree
Showing 21 changed files with 1,083 additions and 320 deletions.
11 changes: 7 additions & 4 deletions FelicaLib_Remodeled/ConsoleAppTest45/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ static void Test1()

using (var felica = new Felica(FelicaSystemCode.Edy))
{
Console.WriteLine("FeliCa ポート: {0}", felica.TryConnectionToPort());
Console.WriteLine("IC カード: {0}", felica.TryConnectionToCard());

try
{
Console.WriteLine(felica.GetIDm().ToHexString());
Expand All @@ -52,8 +55,8 @@ static void Test1()
}
try
{
var data = felica.ReadWithoutEncryption(0x1317, 0);
Console.WriteLine(data.ToEdyBalance());
var data = felica.ReadWithoutEncryption(FelicaServiceCode.EdyBalance, 0);
Console.WriteLine(new EdyBalanceItem(data).Balance);
}
catch (Exception ex)
{
Expand All @@ -71,8 +74,8 @@ static void Test2()
{
try
{
var data = felica.ReadWithoutEncryption(0x1317, 0);
Console.WriteLine(data.ToEdyBalance());
var data = felica.ReadWithoutEncryption(FelicaServiceCode.EdyBalance, 0);
Console.WriteLine(new EdyBalanceItem(data).Balance);
}
catch (Exception ex)
{
Expand Down
280 changes: 238 additions & 42 deletions FelicaLib_Remodeled/FelicaLib_DotNet/FelicaHelper.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,215 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace FelicaLib
{
/// <summary>
/// FeliCa のシステム コードを表します。
/// </summary>
public enum FelicaSystemCode
public static class FelicaSystemCode
{
/// <summary>すべて。</summary>
Any = 0xFFFF,
public const int Any = 0xFFFF;
/// <summary>共通領域。</summary>
Common = 0xFE00,
public const int Common = 0xFE00;
/// <summary>サイバネ領域。</summary>
Cybernetics = 0x0003,
public const int Cybernetics = 0x0003;

/// <summary>Edy。共通領域を使用します。</summary>
Edy = Common,
public const int Edy = Common;
/// <summary>WAON。共通領域を使用します。</summary>
Waon = Common,
public const int Waon = Common;
/// <summary>Suica。サイバネ領域を使用します。</summary>
Suica = Cybernetics,
public const int Suica = Cybernetics;
/// <summary>QUICPay。</summary>
QuicPay = 0x04C1,
public const int QuicPay = 0x04C1;
}

/// <summary>
/// FeliCa のサービス コードを表します。
/// </summary>
public static class FelicaServiceCode
{
/// <summary>Edy の残高情報。</summary>
public const int EdyBalance = 0x1317;
/// <summary>Edy の履歴情報。</summary>
public const int EdyHistory = 0x170F;
/// <summary>WAON の残高情報。</summary>
public const int WaonBalance = 0x6817;
/// <summary>WAON の履歴情報。</summary>
public const int WaonHistory = 0x680B;
/// <summary>Suica の属性情報。</summary>
public const int SuicaAttributes = 0x008B;
/// <summary>Suica の履歴情報。</summary>
public const int SuicaHistory = 0x090F;
}

/// <summary>
/// FeliCa のブロックを表すための基本クラスです。
/// </summary>
public abstract class FelicaBlockItem
{
/// <summary>元のバイナリ データを取得します。</summary>
/// <value>元のバイナリ データ。</value>
public byte[] RawData { get; private set; }

/// <summary>
/// <see cref="FelicaBlockItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
protected FelicaBlockItem(byte[] data)
{
RawData = data;
}
}

/// <summary>
/// Edy の残高情報を表します。
/// </summary>
[DebuggerDisplay(@"\{Balance: {Balance}\}")]
public class EdyBalanceItem : FelicaBlockItem
{
/// <summary>
/// <see cref="EdyBalanceItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
public EdyBalanceItem(byte[] data) : base(data) { }

/// <summary>残高を取得します。</summary>
/// <value>残高。</value>
public int Balance { get { return RawData.ToInt32(0, 4, true); } }
}

/// <summary>
/// Edy の履歴情報を表します。
/// </summary>
[DebuggerDisplay(@"\{ID: {TransactionId}, {DateTime}\}")]
public class EdyHistoryItem : FelicaBlockItem
{
/// <summary>
/// <see cref="EdyHistoryItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
public EdyHistoryItem(byte[] data) : base(data) { }

static readonly DateTime BaseDateTime = new DateTime(2000, 1, 1);

/// <summary>利用日時を取得します。</summary>
/// <value>利用日時。</value>
public DateTime DateTime
{
get
{
var days = RawData.ToInt32(4, 2) >> 1;
var seconds = RawData.ToInt32(5, 3) & 0x01FFFF;
return BaseDateTime.AddDays(days).AddSeconds(seconds);
}
}

/// <summary>利用種別を取得します。</summary>
/// <value>利用種別。</value>
public int UsageCode { get { return RawData.ToInt32(0, 1); } }
/// <summary>取引通番を取得します。</summary>
/// <value>取引通番。</value>
public int TransactionId { get { return RawData.ToInt32(2, 2); } }
/// <summary>利用額を取得します。</summary>
/// <value>利用額。</value>
public int Amount { get { return RawData.ToInt32(8, 4); } }
/// <summary>残高を取得します。</summary>
/// <value>残高。</value>
public int Balance { get { return RawData.ToInt32(12, 4); } }
}

/// <summary>
/// WAON の残高情報を表します。
/// </summary>
[DebuggerDisplay(@"\{Balance: {Balance}\}")]
public class WaonBalanceItem : FelicaBlockItem
{
/// <summary>
/// <see cref="WaonBalanceItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
public WaonBalanceItem(byte[] data) : base(data) { }

/// <summary>残高を取得します。</summary>
/// <value>残高。</value>
public int Balance { get { return RawData.ToInt32(0, 2, true); } }
}

/// <summary>
/// Suica の属性情報を表します。
/// PASMO などの交通系 IC カードと互換性があります。
/// </summary>
[DebuggerDisplay(@"\{Balance: {Balance}\}")]
public class SuicaAttributesItem : FelicaBlockItem
{
/// <summary>
/// <see cref="SuicaAttributesItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
public SuicaAttributesItem(byte[] data) : base(data) { }

/// <summary>カード種別を取得します。</summary>
/// <value>カード種別。</value>
public int CardCode { get { return RawData.ToInt32(8, 1) >> 4; } }
/// <summary>地域を取得します。</summary>
/// <value>地域。</value>
public int AreaCode { get { return RawData.ToInt32(8, 1) & 0x0F; } }
/// <summary>残高を取得します。</summary>
/// <value>残高。</value>
public int Balance { get { return RawData.ToInt32(11, 2, true); } }
/// <summary>取引通番を取得します。</summary>
/// <value>取引通番。</value>
public int TransactionId { get { return RawData.ToInt32(14, 2); } }
}

/// <summary>
/// Suica の履歴情報を表します。
/// PASMO などの交通系 IC カードと互換性があります。
/// </summary>
[DebuggerDisplay(@"\{ID: {TransactionId}, {DateTime}\}")]
public class SuicaHistoryItem : FelicaBlockItem
{
/// <summary>
/// <see cref="SuicaHistoryItem"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="data">バイナリ データ。</param>
public SuicaHistoryItem(byte[] data) : base(data) { }

/// <summary>利用日付を取得します。</summary>
/// <value>利用日付。</value>
public DateTime DateTime
{
get
{
var year = 2000 + (RawData.ToInt32(4, 1) >> 1);
var month = RawData.ToInt32(4, 2) >> 5 & 0x000F;
var day = RawData.ToInt32(5, 1) & 0x1F;
return new DateTime(year, month, day);
}
}

/// <summary>機器種別を取得します。</summary>
/// <value>機器種別。</value>
public int DeviceCode { get { return RawData.ToInt32(0, 1); } }
/// <summary>利用種別を取得します。</summary>
/// <value>利用種別。</value>
public int UsageCode { get { return RawData.ToInt32(1, 1); } }
/// <summary>支払種別を取得します。</summary>
/// <value>支払種別。</value>
public int PaymentCode { get { return RawData.ToInt32(2, 1); } }
/// <summary>入出場種別を取得します。</summary>
/// <value>入出場種別。</value>
public int EntryCode { get { return RawData.ToInt32(3, 1); } }
/// <summary>残高を取得します。</summary>
/// <value>残高。</value>
public int Balance { get { return RawData.ToInt32(10, 2, true); } }
/// <summary>取引通番を取得します。</summary>
/// <value>取引通番。</value>
public int TransactionId { get { return RawData.ToInt32(13, 2); } }
}

/// <summary>
Expand All @@ -37,8 +223,19 @@ public static class FelicaHelper
/// <returns>Edy の残高。</returns>
public static int GetEdyBalance()
{
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Edy, 0x1317, 0);
return data.ToEdyBalance();
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Edy, FelicaServiceCode.EdyBalance, 0);
var item = new EdyBalanceItem(data);
return item.Balance;
}

/// <summary>
/// Edy の利用履歴を取得します。
/// </summary>
/// <returns>Edy の利用履歴。</returns>
public static IEnumerable<EdyHistoryItem> GetEdyHistory()
{
var data = FelicaUtility.ReadBlocksWithoutEncryption(FelicaSystemCode.Edy, FelicaServiceCode.EdyHistory, 0, 6);
return data.Select(x => new EdyHistoryItem(x));
}

/// <summary>
Expand All @@ -47,63 +244,62 @@ public static int GetEdyBalance()
/// <returns>WAON の残高。</returns>
public static int GetWaonBalance()
{
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Waon, 0x6817, 0);
return data.ToWaonBalance();
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Waon, FelicaServiceCode.WaonBalance, 0);
var item = new WaonBalanceItem(data);
return item.Balance;
}

/// <summary>
/// Suica の残高を取得します。PASMO などの交通系 IC カードと互換性があります。
/// Suica の残高を取得します。
/// </summary>
/// <returns>Suica の残高。</returns>
public static int GetSuicaBalance()
{
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Suica, 0x008B, 0);
return data.ToSuicaBalance();
var data = FelicaUtility.ReadWithoutEncryption(FelicaSystemCode.Suica, FelicaServiceCode.SuicaAttributes, 0);
var item = new SuicaAttributesItem(data);
return item.Balance;
}

/// <summary>
/// Edy の残高情報のバイナリ データを残高に変換します
/// Suica の利用履歴を取得します
/// </summary>
/// <param name="data">バイナリ データ。</param>
/// <returns>Edy の残高。</returns>
public static int ToEdyBalance(this byte[] data)
/// <returns>Suica の利用履歴。</returns>
public static IEnumerable<SuicaHistoryItem> GetSuicaHistory()
{
if (data == null) throw new ArgumentNullException("data");

return data
.Take(4)
.Select((b, i) => b * (int)Math.Pow(256, i))
.Sum();
var data = FelicaUtility.ReadBlocksWithoutEncryption(FelicaSystemCode.Suica, FelicaServiceCode.SuicaHistory, 0, 20);
return data.Select(x => new SuicaHistoryItem(x));
}

/// <summary>
/// WAON の残高情報のバイナリ データを残高に変換します
/// バイト配列から指定した部分の要素を数値に変換します
/// </summary>
/// <param name="data">バイナリ データ。</param>
/// <returns>WAON の残高。</returns>
public static int ToWaonBalance(this byte[] data)
/// <param name="data">バイト配列。</param>
/// <param name="start">開始インデックス。</param>
/// <param name="count">要素の数。</param>
/// <returns>数値。</returns>
public static int ToInt32(this byte[] data, int start, int count)
{
if (data == null) throw new ArgumentNullException("data");

return data
.Take(2)
.Select((b, i) => b * (int)Math.Pow(256, i))
.Sum();
return ToInt32(data, start, count, false);
}

/// <summary>
/// Suica の属性情報のバイナリ データを残高に変換します。PASMO などの交通系 IC カードと互換性があります
/// バイト配列から指定した部分の要素を数値に変換します
/// </summary>
/// <param name="data">バイナリ データ。</param>
/// <returns>Suica の残高。</returns>
public static int ToSuicaBalance(this byte[] data)
/// <param name="data">バイト配列。</param>
/// <param name="start">開始インデックス。</param>
/// <param name="count">要素の数。</param>
/// <param name="littleEndian">リトル エンディアンの場合は <see langword="true"/>。</param>
/// <returns>数値。</returns>
public static int ToInt32(this byte[] data, int start, int count, bool littleEndian)
{
if (data == null) throw new ArgumentNullException("data");
if (count < 0 || 4 < count) throw new ArgumentOutOfRangeException("count", "最大で 4 バイトです。");
if (start < 0 || data.Length < start + count) throw new IndexOutOfRangeException("指定されたインデックスが範囲外です。");

return data
.Skip(11)
.Take(2)
.Select((b, i) => b * (int)Math.Pow(256, i))
.Skip(start)
.Take(count)
.Select((b, i) => b * (int)Math.Pow(256, littleEndian ? i : count - 1 - i))
.Sum();
}

Expand Down
Loading

0 comments on commit a087a45

Please sign in to comment.