Skip to content
bdferris edited this page Feb 28, 2012 · 7 revisions

The goal of the GTFS-realtime specification is to provide both transit agencies and developers with a consistent way to exchange real-time public transit data. One specific feature of GTFS-realtime is support for structured service alerts, which allow an agency to specify targeted alerts data about service changes and other disruptions.

I want to make it easy to provide service alert information using the GTFS-realtime format, so I've put together a quick demo project that shows how to produce a GTFS-realtime alerts feed.

In our demo project, we'll walk you through a simple Java-based program that converts a custom alerts data-source from SEPTA into a GTFS-realtime format.

If you want to follow along at home, you can download a ZIP of the source-code for the demo project or import the code from the Git repository directly. The project is designed to be built with Apache Maven, so download that if you are interested in building the project.

Running the Demo Project

Before we dig into how the demo application the works, let's see it in action! After you've downloaded the code for the project, open up a terminal and change to the root directory of the project. From there, run Maven to compile and package the application:

mvn package

Now that the project has been built, you should be able to run the resulting application bundle:

java -jar target/onebusaway-gtfs-realtime-alerts-producer-demo-0.0.1-SNAPSHOT.jar --alertsUrl=http://localhost:8080/alerts

Once the application has started, you should see output like:

2012-02-23 21:42:04,172 INFO  [GtfsRealtimeProviderImpl.java:105] : starting GTFS-realtime service
2012-02-23 21:42:04,173 INFO  [GtfsRealtimeProviderImpl.java:273] : refreshing alerts
2012-02-23 21:42:05,586 INFO  [GtfsRealtimeProviderImpl.java:233] : alerts extracted: 36

Alerts will be refreshed every 30 seconds. You can access the resulting GTFS-realtime alert stream at http://localhost:8080/alerts but it will be binary-encoded, which won't mean much unless you are a computer. You can see a more human-friendly debug version of the stream at http://localhost:8080/alerts?debug. The output should look something like:

header {
  gtfs_realtime_version: "1.0"
  incrementality: FULL_DATASET
  timestamp: 1330030345776
}
entity {
  id: "154323dc759418a69a9e80da7adbc96f"
  alert {
    informed_entity {
      route_id: "rr_route_gc"
    }
    header_text {
      translation {
        text: "Weekday and Sunday Bus Substitution"
      }
    }
    description_text {
      translation {
        text: "Due to overhead wire replacement work, the following trains will no longer serve ..."
      }
    }
  }
}
[... more entries follow ...]

Hey, that's a GTFS-realtime service alert feed!

Digging into the Code

So how does this all work? Let's look at the code! Most of the work is done in the following class:

org.onebusaway.gtfs_realtime.alerts_producer_demo.GtfsRealtimeProviderImpl

The class does the following:

  • Periodically downloads alert data from the SEPTA alert data-stream.
  • Extracts alert information from the SEPTA data.
  • Constructs a GTFS-realtime alert for each alert in the original feed.
  • Save the resulting GTFS-realtime feed.

Let's step through the code for each of these steps.

We setup a recurring task that downloads data from the SEPTA alert data-stream. The data comes in the form of an array of JSON objects:

JSONArray alertArray = downloadAlerts();

Next we create a FeedMessage.Builder that we will use to build the FeedMessage that represents the GTFS-realtime feed. We use a convenience method from the OneBusAway GTFS-realtime library to setup a FeedMessage with a FeedHeader already added.

FeedMessage.Builder feedMessage = GtfsRealtimeSupport.createFeedMessageBuilder();

Next, we iterate over the SEPTA alert objects.

for (int i = 0; i < alertArray.length(); ++i) {

  JSONObject obj = alertArray.getJSONObject(i);

We then extract the alert text, including a title and description, from the SEPTA alert.

AlertText text = _alertTextExtractor.getAlertText(obj);

It's time to build our GTFS-realtime alert. We create an Alert.Builder which we will use to build our Alert.

Alert.Builder alert = Alert.newBuilder();

First we set the the alert header and description text. Note that GTFS-realtime supports providing text in multiple languages, but in this example, we just specify a single message in the default language. Again, we use the OneBusAway GTFS-realtime library to construct the GTFS-realtime TranslatedString object for the alert.

alert.setHeaderText(GtfsRealtimeSupport.getTextAsTranslatedString(text.getTitle()));
alert.setDescriptionText(GtfsRealtimeSupport.getTextAsTranslatedString(text.getDescription()));

Every alert needs an id. Since one isn't included in the SEPTA JSON alerts API, we generate one by taking the MD5-sum of the alert body. The way the id will be the same if we see the same alert twice.

String id = getHashOfValue(obj.toString());

Every alert also needs to be attached to something: a route, a stop, a trip, or maybe even some combination. The SEPTA feed provides route information. We create an EntitySelector.Builder which we'll use to build the GTFS-realtime EntitySelector.

EntitySelector.Builder entitySelector = EntitySelector.newBuilder();
entitySelector.setRouteId(obj.getString("route_id"));
alert.addInformedEntity(entitySelector);

We create a new FeedEntity to wrap the alert and add it to the GTFS-realtime feed message.

FeedEntity.Builder entity = FeedEntity.newBuilder();
entity.setId(id);
entity.setAlert(alert);
feedMessage.addEntity(entity);

We build out the final GTFS-realtime feed message and save it to the alerts field.

_alerts = feedMessage.build();

We've now got a GTFS-realtime alert feed!

Of course, we've left out a few details. We take advantage of a couple of OneBusAway libraries to simplify our application:

Next Steps

We provided this demo application as an example that you can build on when generating your own GTFS-realtime alerts feed. The format of your alert data source may differ, but hopefully we've given you a simple model that you can adapt to produce your own feed.

Also be sure to check out all our GTFS-realtime resources.

Clone this wiki locally