为什么 GTFS 这么难?
Why is GTFS so difficult?
我正在尝试创建一个基于 Arduino 的显示器,显示纽约市地铁北站接下来几列火车的时间。 Metro North 由 MTA 运行(MTA 是纽约市地铁和公共汽车机构)和 I had no trouble creating a similar display for MTA busses. 但是,火车数据非常困难。它不能通过 URL 中的 GET 命令过滤。我必须自己解析数据才能获得停止级别的数据。 (由火车组织。)
我有网页可以运行简单PHP、java等。我想我需要创建一个页面来解析"json"/"XML" 文件从 MTA 给我。然后 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 的格式,应该是 "universal",但我发现很难找到适用于它的任何格式。 For example, simplexml_load_file() in PHP won't work.
Arduino 不适合解析文本。我不能强迫 Arduino 完成所有工作。
我应该学习什么方法?我对我的服务器没有太多控制权。我无法轻易更改服务器上 PHP 运行 的方式。到目前为止我发现的方法似乎需要扩展和其他我做不到的事情。
是的,"drinking from a firehose" 是使用 GTFS 数据的一个很好的比喻。 GTFS 的一方面是将运输机构系统的负载降到最低,并让应用程序开发人员的系统(您)完成尽可能多的工作。这两部分(包含当前路线信息的 "static" GTFS 文件和 GTFS 实时文件)都可以是静态数据文件,由 "dumb" 网络服务器提供(不需要网络应用程序代码),这使得提供数据非常方便可扩展。
一些交通机构(如 MTA,就其公交路线而言)很好,可以为您完成一些工作,提供 XML 或 JSON API为您提供特定路线的当前实时状态。但是,如果您学会了如何在您这边处理 GTFS 数据,您就不需要依赖他们 API,您的系统将变得 "universal",能够处理任何提供 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 流程正在尝试为目标站点创建即将到来的出发时间列表,您将:
- 将实时提要解析为对象集合(我假设您可以在 PHP 中执行此操作,正如上面提到的 Twisty 使用
json_decode()
)
- 遍历 "trip_update" 个对象的数组
- 在"stop_time_update"对象下,遍历"departure"个对象的数组
- 对于每个 "departure" 的 "stop_id" 与您希望设备显示其信息的站点相匹配,将其 "time" 值(unix 时间)添加到集合中。
- 对生成的集合进行排序,并将其从 unix 时间转换为任何 PHP 的本地日期时间对象,并将其格式化为文本
- 将接下来的两个出发时间发送到您的设备
对于这个案例,这将是您的快速解决方案。
我正在尝试创建一个基于 Arduino 的显示器,显示纽约市地铁北站接下来几列火车的时间。 Metro North 由 MTA 运行(MTA 是纽约市地铁和公共汽车机构)和 I had no trouble creating a similar display for MTA busses. 但是,火车数据非常困难。它不能通过 URL 中的 GET 命令过滤。我必须自己解析数据才能获得停止级别的数据。 (由火车组织。)
我有网页可以运行简单PHP、java等。我想我需要创建一个页面来解析"json"/"XML" 文件从 MTA 给我。然后 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 的格式,应该是 "universal",但我发现很难找到适用于它的任何格式。 For example, simplexml_load_file() in PHP won't work.
Arduino 不适合解析文本。我不能强迫 Arduino 完成所有工作。
我应该学习什么方法?我对我的服务器没有太多控制权。我无法轻易更改服务器上 PHP 运行 的方式。到目前为止我发现的方法似乎需要扩展和其他我做不到的事情。
是的,"drinking from a firehose" 是使用 GTFS 数据的一个很好的比喻。 GTFS 的一方面是将运输机构系统的负载降到最低,并让应用程序开发人员的系统(您)完成尽可能多的工作。这两部分(包含当前路线信息的 "static" GTFS 文件和 GTFS 实时文件)都可以是静态数据文件,由 "dumb" 网络服务器提供(不需要网络应用程序代码),这使得提供数据非常方便可扩展。
一些交通机构(如 MTA,就其公交路线而言)很好,可以为您完成一些工作,提供 XML 或 JSON API为您提供特定路线的当前实时状态。但是,如果您学会了如何在您这边处理 GTFS 数据,您就不需要依赖他们 API,您的系统将变得 "universal",能够处理任何提供 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 流程正在尝试为目标站点创建即将到来的出发时间列表,您将:
- 将实时提要解析为对象集合(我假设您可以在 PHP 中执行此操作,正如上面提到的 Twisty 使用
json_decode()
) - 遍历 "trip_update" 个对象的数组
- 在"stop_time_update"对象下,遍历"departure"个对象的数组
- 对于每个 "departure" 的 "stop_id" 与您希望设备显示其信息的站点相匹配,将其 "time" 值(unix 时间)添加到集合中。
- 对生成的集合进行排序,并将其从 unix 时间转换为任何 PHP 的本地日期时间对象,并将其格式化为文本
- 将接下来的两个出发时间发送到您的设备
对于这个案例,这将是您的快速解决方案。