読者です 読者をやめる 読者になる 読者になる

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

C#で東京メトロオープンデータAPIを使って列車ロケーション情報(運行状況)を取得する

おはようございます。週もあけました。

さて、今日もC#で東京メトロオープンデータAPIを使ってみましょうか。本記事では、odpt:Trainを指定して、列車ロケーション情報を取得します。

列車ロケーション情報というのは、特定の列車がどこの駅にいるのか。どこの駅からどこの駅に向かって走っている途中なのかというのがリアルタイム*1で取得できる東京メトロオープンデータの中でも大本命なAPIであることは間違いありません!!

列車ロケーション情報を取得する

東京メトロの施設情報は、JSON.NETを使って取得したJSON-LD形式のデータをパース(デシリアライズ)させます。その時、型を指定しますので事前に下記のようにTrainクラスを定義しておきましょう。

列車種別を示したodpt:trainTypeのデータを格納したTrainTypeプロパティだとよくわからないので、日本語で表した列車種別を取得するTrainTypeNameプロパティを追加しています。

using Newtonsoft.Json;
using System;

namespace WindowsFormsApplication1
{
    public class Train
    {
        [JsonProperty("@context")]
        public string Context { get; set; }

        [JsonProperty("@id")]
        public string Id { get; set; }

        [JsonProperty("@type")]
        public string Type { get; set; }

        [JsonProperty("dc:date")]
        public DateTime Date { get; set; }

        [JsonProperty("dct:valid")]
        public DateTime Valid { get; set; }

        [JsonProperty("odpt:frequency")]
        public int Frequency { get; set; }

        [JsonProperty("odpt:railway")]
        public string Railway { get; set; }

        [JsonProperty("owl:sameAs")]
        public string SameAs { get; set; }

        /// <summary>
        /// 列車番号
        /// </summary>
        [JsonProperty("odpt:trainNumber")]
        public string TrainNumber { get; set; }

        /// <summary>
        /// 列車種別
        /// </summary>
        [JsonProperty("odpt:trainType")]
        public string TrainType { get; set; }

        /// <summary>
        /// 遅延時間(秒)
        /// 5分未満は切り捨て。
        /// </summary>
        [JsonProperty("odpt:delay")]
        public int Delay { get; set; }

        /// <summary>
        /// 列車の始発駅
        /// </summary>
        [JsonProperty("odpt:startingStation")]
        public string StartingStation { get; set; }

        /// <summary>
        /// 列車の終着駅
        /// </summary>
        [JsonProperty("odpt:terminalStation")]
        public string TerminalStation { get; set; }

        /// <summary>
        /// 列車が出発した駅
        /// </summary>
        [JsonProperty("odpt:fromStation")]
        public string FromStation { get; set; }

        /// <summary>
        /// 列車が向かっている駅
        /// </summary>
        [JsonProperty("odpt:toStation")]
        public string ToStation { get; set; }

        /// <summary>
        /// 方面(渋谷方面行きを表す)
        /// </summary>
        [JsonProperty("odpt:railDirection")]
        public string RailDirection { get; set; }

        /// <summary>
        /// 車両の所属会社
        /// </summary>
        [JsonProperty("odpt:trainOwner")]
        public string TrainOwner { get; set; }

        /// <summary>
        /// 列車種別(odpt:trainType)から日本語での名称を取得する
        /// </summary>
        public string TrainTypeName
        {
            get
            {
                var name = default(string);
                switch (TrainType)
                {
                    case "odpt.TrainType:TokyoMetro.Local":
                    case "odpt.TrainType:Local":
                        name = "各停";
                        break;

                    case "odpt.TrainType:TokyoMetro.Express":
                    case "odpt.TrainType:Express":
                        name = "急行";
                        break;

                    case "odpt.TrainType:TokyoMetro.Rapid":
                    case "odpt.TrainType:Rapid":
                        name = "快速";
                        break;

                    case "odpt.TrainType:TokyoMetro.LimitedExpress":
                    case "odpt.TrainType:LimitedExpress":
                        name = "特急";
                        break;

                    default:
                        name = "列車種別不明";
                        break;
                }
                return name;
            }
        }
    }
}

第1回目の時に、東京メトロオープンデータを扱うためのTokyoMetroApiクラスを作っていたので興味のある方は読み返してくださいね。このTokyoMetroApiクラスにメソッドを追加してみましょう。

列車ロケーション情報と駅情報とを組み合わせたTipsの紹介も後述していますので、第3回目で紹介した駅情報を取得するGetStationsメソッドの実装については「C#で東京メトロオープンデータAPIを使って駅情報を取得する - 酢ろぐ!」をご覧ください。

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace TokyoMetro.Apis
{
    public class TokyoMetroApi
    {
        public string ConsumerKey { get; private set; }

        public string EndPointUrl { get; private set; }

        public TokyoMetroApi(string consumerKey)
        {
            ConsumerKey = consumerKey;
            EndPointUrl = "https://api.tokyometroapp.jp/api/v2/datapoints/";
        }

        public IEnumerable<TrainInformation> GetTrainInformation()
        {
            // 第1回の記事を参照してください
        }

        public IEnumerable<Railway> GetRailway()
        {
            // 第2回の記事を参照してください
        }

        public IEnumerable<Station> GetStations()
        {
            // 第3回の記事を参照してください
        }

        public IEnumerable<PassengerSurvey> GetPassengerSurvey()
        {
            // 第4回の記事を参照してください
        }

        public IEnumerable<StationFacility> GetStationFacility()
        {
            // 第5回の記事を参照してください
        }

        public IEnumerable<Train> GetTrains()
        {
            var parm = new Dictionary<string, string>();
            parm["rdf:type"] = "odpt:Train";
            parm["acl:consumerKey"] = ConsumerKey;

            var url = string.Format("{0}?{1}", EndPointUrl,
                string.Join("&", parm.Select(p => string.Format("{0}={1}", p.Key, p.Value))));

            // JSON-DLを取得する
            var client = new WebClient()
            {
                Encoding = System.Text.Encoding.UTF8
            };
            var json = client.DownloadString(url);

            return JsonConvert.DeserializeObject<Train[]>(json);
        }
   }
}

さて、実際に使う際には下記のようにコンシューマキーを指定して、TokyoMetroApiクラスのインスタンスを生成してGetTrainsメソッドを実行します。

var consumerKey = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
var api = new TokyoMetroApi(consumerKey);

var trains = api.GetTrains();

下図のように列車ロケーション情報が取得できます。

f:id:ch3cooh393:20140926175638p:plain

特定の路線で走行中の列車の一覧を取得する

本記事で紹介した列車ロケーション情報駅情報を使って、丸ノ内線内で走行中の取得してみましょう。

それぞれ列車ロケーション情報は名前の通りロケーション(位置)の情報であるため、「停車中であるか」「走行中であるか」といった状態を表す情報を取得することができません。

よって、列車が出発する駅を示すFromStationプロパティと列車が向かっている駅を示すToStationプロパティによって、以下のように「停車中であるか」「走行中であるか」を判定します。

  • ToStationプロパティnullの場合はどこにも向かっていない = 停車中
  • ToStationプロパティnullでない場合は駅に向かっている = 走行中

丸ノ内線の運行状況は以下のサンプルコードを実行すればわかります。

// 丸ノ内線を走っている列車の一覧を取得する
var trains = api.GetTrains()
    .Where(t => t.Railway == "odpt.Railway:TokyoMetro.Marunouchi");

// 丸ノ内線の駅の一覧を取得する
var stations = api.GetStations();

foreach (var train in trains)
{
    Console.WriteLine("・{0}({1})", train.TrainNumber, train.TrainTypeName);

    // 列車を出発した駅情報
    var fromStation = stations.Single(s => s.SameAs == train.FromStation);

    // 列車が向かっている駅情報
    var toStation = stations.SingleOrDefault(s => s.SameAs == train.ToStation);

    if (toStation != null)
    {
        // 列車が向かっている駅が存在する場合、
        // FromStationとToStationの駅間を走行している
        Console.WriteLine(" {0}駅から{1}駅へ走行中", fromStation.Title, toStation.Title);
    }
    else
    {
        // 列車が向かっている駅が存在しない場合、
        // FromStationで指定された駅で停車している
        Console.WriteLine(" {0}駅で停車中", fromStation.Title);
    }
}

Visual Studioで上記のサンプルコードを実行すると、出力欄に情報が表示されます。17:53時点で駅に停車中、駅間を走行中の列車は以下の通りです。思った以上に多くて困惑しています(汗

・A1741(各停)
 池袋駅で停車中
・A1779(各停)
 池袋駅で停車中
・A1743(各停)
 新大塚駅で停車中
・A1775(各停)
 茗荷谷駅から後楽園駅へ走行中
・A1703(各停)
 後楽園駅で停車中
・A1783(各停)
 本郷三丁目駅で停車中
・A1705(各停)
 淡路町駅で停車中
・A1765(各停)
 大手町駅で停車中
・A1709(各停)
 東京駅から銀座駅へ走行中
・A1723(各停)
 銀座駅から霞ケ関駅へ走行中
・A1721(各停)
 霞ケ関駅で停車中
・A1761(各停)
 赤坂見附駅で停車中
・A1707(各停)
 赤坂見附駅から四ツ谷駅へ走行中
・A1711(各停)
 四ツ谷駅から四谷三丁目駅へ走行中
・A1737(各停)
 四谷三丁目駅で停車中
・A1757(各停)
 新宿三丁目駅から新宿駅へ走行中
・A1747(各停)
 西新宿駅から中野坂上駅へ走行中
・A17343(各停)
 中野坂上駅で停車中
・A1753(各停)
 中野坂上駅から新中野駅へ走行中
・A1717(各停)
 新高円寺駅で停車中
・A1763(各停)
 南阿佐ケ谷駅で停車中
・A17383(各停)
 中野富士見町駅で停車中
・B17363(各停)
 方南町駅で停車中
・B17323(各停)
 中野富士見町駅で停車中
・B1787(各停)
 荻窪駅で停車中
・B1791(各停)
荻窪駅から南阿佐ケ谷駅へ走行中
・B1745(各停)
 新高円寺駅で停車中
・B1731(各停)
 新中野駅から中野坂上駅へ走行中
・B1755(各停)
 西新宿駅で停車中
・B1793(各停)
 新宿駅で停車中
・B1751(各停)
 新宿御苑前駅で停車中
・B1773(各停)
 四谷三丁目駅で停車中
・B1725(各停)
 四ツ谷駅から赤坂見附駅へ走行中
・B1733(各停)
 赤坂見附駅で停車中
・B1749(各停)
 国会議事堂前駅から霞ケ関駅へ走行中
・B1719(各停)
 霞ケ関駅から銀座駅へ走行中
・B1715(各停)
 銀座駅から東京駅へ走行中
・B1769(各停)
 大手町駅で停車中
・B1777(各停)
 淡路町駅で停車中
・B1785(各停)
 御茶ノ水駅で停車中
・B1701(各停)
 本郷三丁目駅から後楽園駅へ走行中
・B1729(各停)
 後楽園駅から茗荷谷駅へ走行中
・B1735(各停)
 茗荷谷駅から新大塚駅へ走行中
・B1771(各停)
 新大塚駅から池袋駅へ走行中

東京メトロオープンデータ本命のデータだけあって遊びがいがありそうですね。

関連記事:C#で扱う東京メトロオープンデータAPI

*1:ただしロケーション情報の更新は1分間隔である