Hands On
100DaysOfCode

Solutions: Day 91-95 #100DaysOfCode

By Richard Süselbeck | 08 July 2020

Try HERE Maps

Create a free API key to build location-aware apps and services.

Get Started

Welcome to week 19 of #100DaysOfCode with HERE. This week we are going to look at the Transit API. This API is similar to the Routing API, which we have used in previous weeks, except that it is focused on generating routes using public transport. It also comes with some neat additional features, such as the ability to search for public transit stations (think bus stops and subway stations). You can even get the departure boards of transit stations, including live information on delays!

If you want to know more about 100DaysOfCode with HERE, take a look at this blog post which will tell you everything about it. If you have missed the solutions for days 0-90, you can find them in the previous blogs posts or on our YouTube channel.

Let's begin!

Day 91

Our task for this day was to generate and display a public transit route between the Singapore Zoo and the Singapore Merlion. First, we should probably take a look at the API Reference for the Transit API. As we can see, the Transit API uses the same parameters for the origin and destination of the route as the Routing API. It also uses a similar return parameter to let us determine which information we want about the route. Since we want to draw it on a map, we should at least request a polyline to be returned. Our Transit API call now looks like this:


https://transit.router.hereapi.com/v8/routes
?apiKey=YOUR_API_KEY
&origin=1.40464,103.79009
&destination=1.25414,103.81883
&return=polyline

To draw the returned route on a map, we can use the HERE JavaScript API and the Fetch API, as we’ve done in previous weeks. Note that as with the Routing API we are getting a list of routes, which each contains a list of sections. When using the Routing API, the sections were the part of the route in between the individual waypoints. When using the Transit API, each section represents a different mode of transport. For example, you might start on foot and walk to a bus station (section 1), then take the bus for a while (section 2), once again walk from the bus station to a subway station (section 3), and so on. To draw the complete route on the map, we thus need to iterate through all sections in the route.


function getTransitRoute() {

    let url = "https://transit.router.hereapi.com/v8/routes" +
        "?apiKey=YOUR_API_KEY" +
        "&origin=1.40464,103.79009" +
        "&destination=1.28675,103.85441" +
        "&return=polyline";

    fetch(url)
        .then(response => response.json())
        .then(response => {

            let routeGroup = new H.map.Group();

            response.routes[0].sections.forEach(section => {

                let lineString = H.geo.LineString.fromFlexiblePolyline(section.polyline);
                var polyline = new H.map.Polyline(lineString, { style: { lineWidth: 10 } });
                routeGroup.addObject(polyline);

            });

            map.addObject(routeGroup);
            map.getViewModel().setLookAtData({
                bounds: routeGroup.getBoundingBox()
            });

        }, error => {
            console.log.error(error);
        });

}

The resulting map should look something like this.

 

day91-1

 

Day 92

On this day we were asked to create a public transit route once again (between Alexanderplatz and Checkpoint Charlie in Berlin), but to ensure that we arrive before at 9am in the morning. We also needed to request at least one alternative route. This means we need to use two additional parameters.

  • arrivalTime: This parameter lets you define an arrival time for your route. Oftentimes when we have an appointment, the most important information any type of mobility API can provide us with, is when we must leave to arrive on time.
  • alternatives: This parameter lets you request alternative routes, that is you can ask for more than one option to get from your origin to your destination. For example, if we set this to 3, we will get up to four different routes returned.

Assuming that today is July 8th, 2020, our API call now looks like this:


https://transit.router.hereapi.com/v8/routes
?apiKey=YOUR_API_KEY
&origin=52.5214,13.41555
&destination=52.50715,13.39061
&return=polyline
&arrivalTime=2020-07-09T09:00:00
&alternatives=1

Once again, we use the JavaScript API to draw our two routes on the map. Note that since we now have multiple routes we need to iterate over the routes as well as the sections.


function getTransitRoute() {

    let url = "https://transit.router.hereapi.com/v8/routes" +
        "?apiKey=YOUR_API_KEY" +
        "&origin=52.5214,13.41555" +
        "&destination=52.50715,13.39061" +
        "&return=polyline" +
        "&arrivalTime=2020-07-08T09:00:00" +
        "&alternatives=1";

    fetch(url)
        .then(response => response.json())
        .then(response => {

            let routeGroup = new H.map.Group();

            response.routes.forEach(route => {
                route.sections.forEach(section => {

                    let lineString = H.geo.LineString.fromFlexiblePolyline(section.polyline);
                    var polyline = new H.map.Polyline(lineString, { style: { lineWidth: 10 } });
                    routeGroup.addObject(polyline);

                });
            });

            map.addObject(routeGroup);
            map.getViewModel().setLookAtData({
                bounds: routeGroup.getBoundingBox()
            });

        }, error => {
            console.log.error(error);
        });
}

 

day92-1

 

Day 93

For today’s transit route (between the Empire State Building and the American Museum of Natural History in New York) we were asked to avoid the subway and display fare prices for the rides.

To avoid the subway, we need to start using the modes parameter. Whereas the similar mode parameter in the Routing API lets us define a single mode of transport to be used, the modes parameter lets us define exactly which types of transit modes we want to be considered for our route. For example, if we only wanted the use the bus, ferry, and subway we could set modes to "bus, ferry, subway”. By default, all modes are considered. We can then use a minus sign in front of a mode to exclude it from consideration. This is what we are going to do with the subway mode.

To include fare prices in the response (where supported), we can simply add the value fares to our return parameter. Our API call now looks like this:


https://transit.router.hereapi.com/v8/routes
?apiKey=YOUR_API_KEY
&origin=40.74843,-73.98567
&destination=40.78193,-73.97239
&modes=-subway
&changes=2
&return=polyline,fares

When drawn on a map, our route looks like this. (Note that depending on the time of day and any possible delays or cancellations, your routes for all the tasks in this week may of course look somewhat different.)

 

day93-1

 

If we look in the response of our API call, we can also see that fare price information is included for every relevant section of the route.


"fares": [
    {
        "id": "fare-R00215d-C0-S1-T0-F0",
        "name": "MetroCard single ride",
        "price": {
            "type": "value",
            "currency": "USD",
            "value": 2.75
        },
        "reason": "ride"
    }
]

Day 94

Switching gears (or tracks as it were), today’s task was not to find a public transit route, but a list of public transit stations (near the Tower of London). If we once again look at the Transit API Reference, we can see that there is a dedicated “Station Search “ end point we can use for this. For our task, we can provide a location to the in parameter and we will get a list of stations in return.

Note that the response provides a unique station id for each transit station. Remember this, as it will be useful for day 95. You could also use the modesInPlace parameter to search only for stations of a certain type (e.g., subway) or exclude certain types of station. It works exactly like the modes parameter from day 93!

Here’s our API call and the corresponding response:


https://transit.hereapi.com/v8/stations
?apiKey=YOUR_API_KEY
&in=51.50808,-0.07587

{
    "stations": [
        {
            "place": {
                "name": "The Tower of London (Stop TA)",
                "type": "station",
                "location": {
                    "lat": 51.509621,
                    "lng": -0.075411
                },
                "id": "420321352"
            }
        },
        {
            "place": {
                "name": "The Tower of London (Stop TB)",
                "type": "station",
                "location": {
                    "lat": 51.509689,
                    "lng": -0.075883
                },
                "id": "420321351"
            }
        },
        {
            "place": {
                "name": "Tower Hill",
                "type": "station",
                "location": {
                    "lat": 51.509715,
                    "lng": -0.077015
                },
                "id": "420326491"
            }
        },
        {
            "place": {
                "name": "Tower Pier",
                "type": "station",
                "location": {
                    "lat": 51.507339,
                    "lng": -0.078937
                },
                "id": "420325926"
            }
        },
        {
            "place": {
                "name": "Tower Gateway (Stop TC)",
                "type": "station",
                "location": {
                    "lat": 51.510281,
                    "lng": -0.075051
                },
                "id": "420308069"
            }
        }
    ]
}

We can also use this information to draw some markers on our map. Our code for this is as follows.


function getTransitRoute() {

    let url = "https://transit.router.hereapi.com/v8/stations" +
        "?apiKey=YOUR_API_KEY" +
        "&in=51.50808,-0.07587";

    fetch(url)
        .then(response => response.json())
        .then(response => {

            console.log(response);

            let markerGroup = new H.map.Group();

            response.stations.forEach(station => {
                let marker = new H.map.Marker(station.place.location);
                markerGroup.addObject(marker);
            });

            map.addObject(markerGroup);
            map.getViewModel().setLookAtData({
                bounds: markerGroup.getBoundingBox()
            });

        }, error => {
            console.log.error(error);
        });

}
day94-1

 

Day 95

We’ve almost made it! Less than a week to go in #100DaysOfCode and this is also the last task using the Transit API. Let’s get to it!

Today we want to display the departure board for a very specific tram station (the Cavill Avenue Station in Cold Coast, Australia to be precise). Once again, the Transit API has a dedicated endpoint for this, called “Next Departures”. There are two ways we can tell the Next Departures endpoint, which station we want to see departures for. First, we can simply provide a geo-coordinate. The API when then pick the closest station. However, this can be imprecise, especially when there are multiple transit stations close to each other.

This is why I told you to remember the station id provided by the Station Search endpoint! This id uniquely identifies a given station. Let’s use our Station Search endpoint again, to get the station id of Cavill Avenue station. In addition to the in parameter, we will also use the name parameter to further narrow down our search.


https://transit.hereapi.com/v8/stations
?apiKey={{apiKey}}
&in=-28.00185,153.42859
&name=cavill

From the response we can see that the station id we are looking for is 425315170. Let’s plug this id into the Next Departures endpoint, using the ids parameter. We were also asked to just provide the departures in the next 30 minutes. For this we use the timespan parameter. Our API call and response now look like this:


https://transit.hereapi.com/v8/departures
?apiKey=YOUR_API_KEY
&ids=425315170
×pan=30

{
    "boards": [
        {
            "place": {
                "name": "Cavill Avenue station",
                "type": "station",
                "location": {
                    "lat": -28.001711,
                    "lng": 153.428413
                },
                "id": "425315170",
                "platform": "2"
            },
            "departures": [
                {
                    "time": "2020-07-08T17:18:00+10:00",
                    "transport": {
                        "mode": "lightRail",
                        "name": "GLKS",
                        "category": "Tram",
                        "color": "#FFD400",
                        "textColor": "#000000",
                        "headsign": "Broadbeach South"
                    },
                    "agency": {
                        "id": "fUe61100",
                        "name": "TransLink",
                        "website": "http://translink.com.au"
                    }
                },
                {
                    "time": "2020-07-08T17:26:00+10:00",
                    "delay": 0,
                    "transport": {
                        "mode": "lightRail",
                        "name": "GLKS",
                        "category": "Tram",
                        "color": "#FFD400",
                        "textColor": "#000000",
                        "headsign": "Broadbeach South"
                    },
                    "agency": {
                        "id": "fUe61100",
                        "name": "TransLink",
                        "website": "http://translink.com.au"
                    }
                },
                {
                    "time": "2020-07-08T17:33:00+10:00",
                    "transport": {
                        "mode": "lightRail",
                        "name": "GLKS",
                        "category": "Tram",
                        "color": "#FFD400",
                        "textColor": "#000000",
                        "headsign": "Broadbeach South"
                    },
                    "agency": {
                        "id": "fUe61100",
                        "name": "TransLink",
                        "website": "http://translink.com.au"
                    }
                },
                {
                    "time": "2020-07-08T17:41:00+10:00",
                    "delay": 0,
                    "transport": {
                        "mode": "lightRail",
                        "name": "GLKS",
                        "category": "Tram",
                        "color": "#FFD400",
                        "textColor": "#000000",
                        "headsign": "Broadbeach South"
                    },
                    "agency": {
                        "id": "fUe61100",
                        "name": "TransLink",
                        "website": "http://translink.com.au"
                    }
                }
            ]
        }
    ]
}

Note that depending on the tram schedule, there may not be any departures in the next 30 minutes! Feel free to play around with the timespan and time parameters until you get a result.

That’s all for our excursion into the Transit API. Meanwhile, keep following us on Twitter for more tasks and complete all 100 days. If you want to watch the video version of these solutions, take a look at our playlist for #100DaysOfCode on YouTube. If you want the code snippets of the APIs covered with #100DaysOfCode, head over to the 100daysofcode GitHub repository.

Also, why not let HERE 🥑 Michael Palermo take you on a tour of our developer usage dashboard and see how many API calls you’ve made in the last 95 days!

Only five days to go! Happy Coding!