为什么GTFS如此困难?

时间:2015-09-22 03:11:29

标签: php json xml parsing

我正在尝试创建一个基于Arduino的显示屏,显示纽约市地铁北站的下几列火车的时间。 Metro North由MTA运营(MTA是纽约地铁和公共汽车代理商)和I had no trouble creating a similar display for MTA busses.但是,列车数据非常困难。它无法通过URL中的GET命令进行过滤。我必须自己解析数据以获取停止级数据。 (它是按火车组织的。)

我有网页,我可以运行简单的PHP,java等。我想我需要创建一个页面来解析MTA中的“json”/“XML”文件。然后Arduino可以使用简化数据。我可以使用URL和我的api密钥获取实时数据。这就是它的样子:

{"header":{"gtfs_realtime_version":"1","timestamp":1442890458},"entity":[{"id":"1392","trip_update":{"trip":{"start_time":"2251","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1392"},"stop_time_update":[{"departure":{"delay":180,"time":1442890260},"stop_id":"112"},{"departure":{"delay":180,"time":1442890500},"stop_id":"114"},{"departure":{"delay":180,"time":1442890680},"stop_id":"115"},{"departure":{"delay":180,"time":1442890920},"stop_id":"116"},{"departure":{"delay":180,"time":1442891100},"stop_id":"118"},{"departure":{"delay":180,"time":1442891280},"stop_id":"120"},{"departure":{"delay":180,"time":1442891400},"stop_id":"121"},{"departure":{"delay":180,"time":1442891880},"stop_id":"124"}]}},{"id":"1394","trip_update":{"trip":{"start_time":"2254","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1394"},"stop_time_update":[{"departure":{"delay":0,"time":1442890440},"stop_id":"4"},{"departure":{"delay":0,"time":1442890920},"stop_id":"56"},{"departure":{"delay":0,"time":1442891400},"stop_id":"105"},{"departure":{"delay":0,"time":1442891580},"stop_id":"106"},{"departure":{"delay":0,"time":1442891760},"stop_id":"108"},{"departure":{"delay":0,"time":1442892000},"stop_id":"110"},{"departure":{"delay":0,"time":1442892180},"stop_id":"111"},{"departure":{"delay":0,"time":1442892360},"stop_id":"112"},{"departure":{"delay":0,"time":1442892600},"stop_id":"114"},{"departure":{"delay":0,"time":1442892780},"stop_id":"115"},{"departure":{"delay":0,"time":1442893020},"stop_id":"116"},{"departure":{"delay":0,"time":1442893200},"stop_id":"118"},{"departure":{"delay":0,"time":1442893380},"stop_id":"120"},{"departure":{"delay":0,"time":1442893500},"stop_id":"121"},{"departure":{"delay":0,"time":1442893980},"stop_id":"124"}]}},{"id":"1395","trip_update":{"trip":{"start_time":"2303","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1395"},"stop_time_update":[{"departure":{"delay":0,"time":1442890980},"stop_id":"4"},{"departure":{"delay":0,"time":1442891640},"stop_id":"1"}]}},{"id":"1586","trip_update":{"trip":{"start_time":"2247","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1586"},"stop_time_update":[{"departure":{"delay":60,"time":1442890020},"stop_id":"144"},{"departure":{"delay":60,"time":1442890200},"stop_id":"145"},{"departure":{"delay":60,"time":1442890620},"stop_id":"190"},{"departure":{"delay":60,"time":1442891220},"stop_id":"149"}]}},{"id":"1588","trip_update":{"trip":{"start_time":"2254","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1588"},"stop_time_update":[{"departure":{"delay":0,"time":1442890440},"stop_id":"136"},{"departure":{"delay":0,"time":1442890620},"stop_id":"137"},{"departure":{"delay":0,"time":1442890860},"stop_id":"138"},{"departure":{"delay":0,"time":1442891040},"stop_id":"188"},{"departure":{"delay":0,"time":1442891520},"stop_id":"140"},{"departure":{"delay":0,"time":1442891880},"stop_id":"143"},{"departure":{"delay":0,"time":1442892120},"stop_id":"144"},{"departure":{"delay":0,"time":1442892300},"stop_id":"145"},{"departure":{"delay":0,"time":1442892720},"stop_id":"190"},{"departure":{"delay":0,"time":1442893380},"stop_id":"149"}]}},{"id":"1597","trip_update":{"trip":{"start_time":"2203","start_date":"09212015","schedule_relationship":0,"route_id":"3"},"vehicle":{"label":"1597"},"stop_time_update":[{"departure":{"delay":0,"time":1442887380},"stop_id":"144"},{"departure":{"delay":0,"time":1442890560},"stop_id":"124"},{"departure":{"delay":0,"time":1442892900},"stop_id":"4"},{"departure":{"delay":0,"time":1442893560},"stop_id":"1"}]}},{"id":"1699","trip_update":{"trip":{"start_time":"2220","start_date":"09212015","schedule_relationship":0,"route_id":"20"},"vehicle":{"label":"1699"},"stop_time_update":[{"departure":{"delay":60,"time":1442888400},"stop_id":"40714"},{"departure":{"delay":60,"time":1442889600},"stop_id":"40712"},{"departure":{"delay":60,"time":1442889960},"stop_id":"40710"},{"departure":{"delay":60,"time":1442890740},"stop_id":"40704"},{"departure":{"delay":60,"time":1442892000},"stop_id":"149"}]}},{"id":"1795","trip_update":{"trip":{"start_time":"2145","start_date":"09212015","schedule_relationship":0,"route_id":"4"},"vehicle":{"label":"1795"},"stop_time_update":[{"departure":{"delay":4200,"time":1442886300},"stop_id":"124"}]}},{"id":"588","trip_update":{"trip":{"start_time":"2248","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"588"},"stop_time_update":[{"departure":{"delay":300,"time":1442890080},"stop_id":"4"},{"departure":{"delay":300,"time":1442890740},"stop_id":"1"}]}},{"id":"591","trip_update":{"trip":{"start_time":"2250","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"591"},"stop_time_update":[{"departure":{"delay":0,"time":1442890200},"stop_id":"56"},{"departure":{"delay":0,"time":1442890320},"stop_id":"57"},{"departure":{"delay":0,"time":1442890500},"stop_id":"58"},{"departure":{"delay":0,"time":1442890680},"stop_id":"59"},{"departure":{"delay":0,"time":1442890800},"stop_id":"61"},{"departure":{"delay":0,"time":1442890980},"stop_id":"62"},{"departure":{"delay":0,"time":1442891100},"stop_id":"64"},{"departure":{"delay":0,"time":1442891220},"stop_id":"65"},{"departure":{"delay":0,"time":1442891340},"stop_id":"66"},{"departure":{"delay":0,"time":1442891520},"stop_id":"68"},{"departure":{"delay":0,"time":1442891700},"stop_id":"71"},{"departure":{"delay":0,"time":1442891880},"stop_id":"72"},{"departure":{"delay":0,"time":1442892060},"stop_id":"74"},{"departure":{"delay":0,"time":1442892480},"stop_id":"76"}]}},{"id":"67","trip_update":{"trip":{"start_time":"0035","start_date":"09222015","schedule_relationship":0,"route_id":"17"},"vehicle":{"label":"67"},"stop_time_update":[{"departure":{"delay":80880,"time":1442896500},"stop_id":"149"},{"departure":{"delay":80880,"time":1442899260},"stop_id":"124"},{"departure":{"delay":80880,"time":1442905200},"stop_id":"15001"},{"departure":{"delay":80880,"time":1442906400},"stop_id":"17016"},{"departure":{"delay":80880,"time":1442907360},"stop_id":"17015"},{"departure":{"delay":80880,"time":1442908980},"stop_id":"17012"},{"departure":{"delay":80880,"time":1442911200},"stop_id":"17010"},{"departure":{"delay":80880,"time":1442912760},"stop_id":"17009"},{"departure":{"delay":80880,"time":1442916600},"stop_id":"17006"},{"departure":{"delay":80880,"time":1442917380},"stop_id":"17005"},{"departure":{"delay":80880,"time":1442918520},"stop_id":"17004"},{"departure":{"delay":80880,"time":1442921400},"stop_id":"17003"},{"departure":{"delay":80880,"time":1442929500},"stop_id":"17002"},{"departure":{"delay":80880,"time":1442937000},"stop_id":"17001"}]}},{"id":"687","trip_update":{"trip":{"start_time":"2254","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"687"},"stop_time_update":[{"departure":{"delay":0,"time":1442890440},"stop_id":"85"},{"departure":{"delay":0,"time":1442890620},"stop_id":"86"},{"departure":{"delay":0,"time":1442890860},"stop_id":"88"},{"departure":{"delay":0,"time":1442891100},"stop_id":"89"},{"departure":{"delay":0,"time":1442891280},"stop_id":"90"},{"departure":{"delay":0,"time":1442891640},"stop_id":"91"},{"departure":{"delay":0,"time":1442892000},"stop_id":"94"}]}},{"id":"689","trip_update":{"trip":{"start_time":"2256","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"689"},"stop_time_update":[{"departure":{"delay":120,"time":1442890560},"stop_id":"74"},{"departure":{"delay":120,"time":1442890740},"stop_id":"76"},{"departure":{"delay":120,"time":1442890980},"stop_id":"78"},{"departure":{"delay":120,"time":1442891220},"stop_id":"80"},{"departure":{"delay":120,"time":1442891460},"stop_id":"81"},{"departure":{"delay":120,"time":1442891640},"stop_id":"83"},{"departure":{"delay":120,"time":1442892000},"stop_id":"84"},{"departure":{"delay":120,"time":1442892240},"stop_id":"85"},{"departure":{"delay":120,"time":1442892420},"stop_id":"86"},{"departure":{"delay":120,"time":1442892660},"stop_id":"88"},{"departure":{"delay":120,"time":1442892900},"stop_id":"89"},{"departure":{"delay":120,"time":1442893080},"stop_id":"90"},{"departure":{"delay":120,"time":1442893440},"stop_id":"91"},{"departure":{"delay":120,"time":1442893800},"stop_id":"94"}]}},{"id":"692","trip_update":{"trip":{"start_time":"2253","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"692"},"stop_time_update":[{"departure":{"delay":0,"time":1442890380},"stop_id":"80"},{"departure":{"delay":0,"time":1442890620},"stop_id":"78"},{"departure":{"delay":0,"time":1442890860},"stop_id":"76"},{"departure":{"delay":0,"time":1442891100},"stop_id":"74"},{"departure":{"delay":0,"time":1442892780},"stop_id":"4"},{"departure":{"delay":0,"time":1442893440},"stop_id":"1"}]}},{"id":"791","trip_update":{"trip":{"start_time":"2252","start_date":"09212015","schedule_relationship":0,"route_id":"1"},"vehicle":{"label":"791"},"stop_time_update":[{"departure":{"delay":0,"time":1442890320},"stop_id":"18"},{"departure":{"delay":0,"time":1442890440},"stop_id":"19"},{"departure":{"delay":0,"time":1442890620},"stop_id":"20"},{"departure":{"delay":0,"time":1442890800},"stop_id":"22"},{"departure":{"delay":0,"time":1442890980},"stop_id":"23"},{"departure":{"delay":0,"time":1442891100},"stop_id":"24"},{"departure":{"delay":0,"time":1442891220},"stop_id":"25"},{"departure":{"delay":0,"time":1442891460},"stop_id":"27"},{"departure":{"delay":0,"time":1442891580},"stop_id":"29"},{"departure":{"delay":0,"time":1442891820},"stop_id":"30"},{"departure":{"delay":0,"time":1442892000},"stop_id":"31"},{"departure":{"delay":0,"time":1442892480},"stop_id":"33"}]}},{"id":"792","trip_update":{"trip":{"start_time":"2249","start_date":"09212015","schedule_relationship":0,"route_id":"1"},"vehicle":{"label":"792"},"stop_time_update":[{"departure":{"delay":180,"time":1442890140},"stop_id":"622"},{"departure":{"delay":180,"time":1442890560},"stop_id":"4"},{"departure":{"delay":180,"time":1442891220},"stop_id":"1"}]}},{"id":"887","trip_update":{"trip":{"start_time":"2245","start_date":"09212015","schedule_relationship":0,"route_id":"1"},"vehicle":{"label":"887"},"stop_time_update":[{"departure":{"delay":180,"time":1442889900},"stop_id":"39"},{"departure":{"delay":180,"time":1442890560},"stop_id":"42"},{"departure":{"delay":180,"time":1442890800},"stop_id":"43"},{"departure":{"delay":180,"time":1442891280},"stop_id":"46"},{"departure":{"delay":180,"time":1442891760},"stop_id":"49"},{"departure":{"delay":180,"time":1442892780},"stop_id":"51"}]}},{"id":"983","trip_update":{"trip":{"start_time":"2253","start_date":"09212015","schedule_relationship":0,"route_id":"2"},"vehicle":{"label":"983"},"stop_time_update":[{"departure":{"delay":60,"time":1442890380},"stop_id":"101"},{"departure":{"delay":60,"time":1442890560},"stop_id":"176"},{"departure":{"delay":60,"time":1442891160},"stop_id":"177"}]}}]}

喜欢从消防水中喝酒。

这是一种名为GTFS的格式,它应该是“通用的”,但我发现很难找到任何适合它的东西。 For example, simplexml_load_file() in PHP won't work.

Arduinos不适合解析文本。我无法强迫Arduino完成所有工作。

我应该学习什么方法?我对我的服务器没有多少控制权。我无法轻易改变PHP在我的服务器上的运行方式。到目前为止我发现的方法似乎需要扩展和其他我不能做的事情。

1 个答案:

答案 0 :(得分:2)

是的,“从消防中喝水”是使用GTFS数据的一个很好的比喻。 GTFS的一个方面是将最少的负载放在运输代理商的系统上,并让应用程序开发人员的系统(您)尽可能多地完成工作。两个部分(具有当前路由信息的“静态”GTFS文件和GTFS实时文件)可以是从“哑”Web服务器(不需要Web应用程序代码)提供的静态数据文件,这使得提供的数据非常可扩展。

某些公交机构(如MTA,如果是公交路线)很不错,可以为您做一些工作,提供XML或JSON API,以便为您提供特定路线的当前实时状态。但是,如果您了解如何处理GTFS数据,则无需依赖其API,您的系统将变得“通用”,能够处理任何提供GTFS实时信息的代理商。

我的猜测是你已经查看了文档,但为了以防万一,这里是参考:https://developers.google.com/transit/

通常,您将使用GTFS文件(包含日历,路线,行程,停靠点和stop_times)和GTFS实时文件(特别是tripUpdate文件)的组合来确定车辆的当前状态是什么与当前旅行的站点有关。它们可能只是为您提供当前行程中车辆的延迟时间,然后您需要查找目标停靠点的每次行程的停止时间并根据相应的延迟进行调整。

然而,MTA再次变得更好,他们只是在实时饲料中给你足够的信息,以显示车辆(例如火车1586)何时将一次到达停靠点(例如停止144)(例如unix)时间1442890020 =星期二,2015年9月22日02:47:00 GMT)和延迟(例如60秒)。

因此,如果您的PHP流程正在尝试为目标站点创建即将到来的出发时间列表,您可以:

  1. 将实时Feed解析为对象集合(我假设您可以在PHP中执行此操作,如上面提到的Twisty使用json_decode()
  2. 遍历“trip_update”对象数组
  3. 在“stop_time_update”对象下,遍历“离开”对象数组
  4. 对于每个“出发”,其“stop_id”与您希望设备显示信息的停止匹配,将其“时间”值(unix时间)添加到集合中。
  5. 对生成的集合进行排序,并将unix时间转换为PHP的本地日期时间对象,并将其格式化为文本
  6. 将接下来的两个出发时间发送到您的设备
  7. 对于这个案例,这将是一个快速解决方案。