Getting started with IBM Call for Code Community Collaboration

By Raymond Camden | 06 May 2020

Try HERE Maps

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

Get Started

Last week we introduced our collaboration with IBM on Call for Code 2020. We are working with IBM on the Call for Code challenges to encourage developers to find ways to help fight both COVID-19 and climate change. To help with this, we've released two starter kits that give you, well, a start in building your project. In this post, I'm going to help you with the first starter kit on Community Collaboration.

This starter kit imagines a scenario where a community needs to find a way to connect people who have items (food, masks, and so forth) with people who need items. The starter kits contains a Node.js server-side application to handle communication with IBM Watson and a React Native mobile application as the client. The React Native application makes use of HERE Maps support as well as Routing and Geolocation.

In this post, I'm going to give a quick introduction to HERE Location Services used in the starter kit and give some tips and examples for how you could use them, and other services, if you decide to join this initiative. Remember that the "Starter Kit" is just that - a way to get started. You're completely welcome to use it in any way you wish, or not at all!

First, let me start off with something not HERE or IBM related at all. In the React Native application, geolocation code is used to determine the user's position. For folks who are building a pure web based solution, you will want to use the browser's Geolocation API instead. All modern browsers support the ability to request a user's location (see the CanIUse data for a comprehensive look at browser support), but it is something that the user will have to give permission for.

The Mozilla Developer Network has great documentation for the API, but here's an incredibly simple demo that gets the user's location and prints it to the screen:

<html>
<head>
<title>Geolocation Test</title>
</head>

<body>
<div id="result"></div>
<script>
document.addEventListener('DOMContentLoaded', init, false);
function init() {
    if(!navigator.geolocation) {
        alert("Your browser doesn't support geolocation.");
        return;
    }

    navigator.geolocation.getCurrentPosition(result => {
        console.log(result);
        let html = `
<p>
Your position is ${result.coords.latitude}, ${result.coords.longitude}.
</p>
        `;

        document.querySelector('#result').innerHTML = html;
    }, error => {
        alert(error);
    });
}
</script>
</body>
</html>

The API I used here was navigategor.geolocation.getCurrentPosition. This API supports additional parameters related to how the location is determined but the defaults should be fine for most use cases. There's also an API to watch the user's location which will give you updated values as the user moves. (Which is probably something you only want to do on a mobile device!)

Now, let's talk about our maps. You should begin by looking at the documentation, which covers our maps library for JavaScript, Android, and iOS. I'm primarily a web developer so I'll focus my attention on this. Using our maps require loading a few JavaScript libraries, a CSS resource, and then adding some code to your site. You'll also need a key which you can get with a free developer account. The keys used in client-side applications can be locked down to specific hosts so it's safe to use in JavaScript. Here's a template that loads up a map, enables basic interaction controls (pinch to zoom, touch or click to move, and so forth), and adds UI for zooming.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Test</title>
        <meta name="description" content="">
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
        <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js" type="text/javascript" charset="utf-8"></script>
        <link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
        <style>
            #mapContainer {
                width: 500px;
                height: 500px;
            }
        </style>
    </head>
    <body>

        <div id="mapContainer"></div>

        <script>
        const KEY = 'c1LJuR0Bl2y02PefaQ2d8PvPnBKEN8KdhAOFYR_Bgmw';
        var platform = new H.service.Platform({
            'apikey': KEY
        });

        // Obtain the default map types from the platform object:
        var defaultLayers = platform.createDefaultLayers();

        var map = new H.Map(
            document.getElementById('mapContainer'),
            defaultLayers.vector.normal.map,
            {
                zoom: 5,
                center: { lat: 30.22, lng: -92.02 },
                pixelRatio: window.devicePixelRatio || 1
            }
        );


        var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));

        // Create the default UI:
        var ui = H.ui.UI.createDefault(map, defaultLayers);

        </script>
    </body>
</html>

The map above is centered on my home town, but obviously you could center it anywhere, or even better, combine it with geolocation code to center the map on the user's location.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Test</title>
        <meta name="description" content="">
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
        <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js" type="text/javascript" charset="utf-8"></script>
        <link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
        <style>
            #mapContainer {
                width: 500px;
                height: 500px;
            }
        </style>
    </head>
    <body>

        <div id="mapContainer"></div>

        <script>
        const KEY = 'c1LJuR0Bl2y02PefaQ2d8PvPnBKEN8KdhAOFYR_Bgmw';
        var loc;

        document.addEventListener('DOMContentLoaded', init, false);

        function init() {
            if(!navigator.geolocation) {
                alert("You're browser doesn't support geolocation.");
                return;
            }

            navigator.geolocation.getCurrentPosition(result => {
                loc = result.coords;
                renderMap();
            }, error => {
                alert(error);
            });

        }

        function renderMap() {
            var platform = new H.service.Platform({
                'apikey': KEY
            });

            var defaultLayers = platform.createDefaultLayers();

            var map = new H.Map(
                document.getElementById('mapContainer'),
                defaultLayers.vector.normal.map,
                {
                    zoom: 12,
                    center: { lat: loc.latitude, lng: loc.longitude },
                    pixelRatio: window.devicePixelRatio || 1
                }
            );

            var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));

            var ui = H.ui.UI.createDefault(map, defaultLayers);
        }
        </script>
    </body>
</html>

Finally, the starter applications makes use of both Routing and Geocoding. Both of these services can be used outside of our maps as well. You can use the Geocoding and Search REST APIs both in your client-side and server-side code. Search in particular could be useful as it would let you find medical-related points of interest near your user.

Consider this API call as an example:

https://browse.search.hereapi.com/v1/browse?apikey={{apiKey}}&at=30.22,-92.02&categories=800-8000-0000

This returns hospitals and health care facilities near the location specified in the at parameter. Here's an example result:

{
    "title": "Home Care Associates",
    "id": "here:pds:place:8403fv6k-1b0587e41e2a05c09781481bd6b94f8d",
    "resultType": "place",
    "address": {
        "label": "Home Care Associates, 600 Jefferson St, Lafayette, LA 70501, United States",
        "countryCode": "USA",
        "countryName": "United States",
        "state": "Louisiana",
        "county": "Lafayette",
        "city": "Lafayette",
        "street": "Jefferson St",
        "postalCode": "70501",
        "houseNumber": "600"
    },
    "position": {
        "lat": 30.22339,
        "lng": -92.01931
    },
    "access": [
        {
            "lat": 30.22338,
            "lng": -92.01878
        }
    ],
    "distance": 383,
    "categories": [
        {
            "id": "700-7200-0272"
        },
        {
            "id": "700-7200-0277"
        },
        {
            "id": "700-7400-0138"
        },
        {
            "id": "800-8000-0000"
        }
    ],
    "contacts": [
        {
            "phone": [
                {
                    "value": "+13375047710"
                }
            ],
            "www": [
                {
                    "value": "http://www.homecareassoc.com"
                },
                {
                    "value": "http://www.homecareassoc.com/"
                }
            ],
            "email": [
                {
                    "value": "info@homecareassoc.com"
                }
            ]
        }
    ],
    "openingHours": [
        {
            "text": [
                "Mon-Sun: 00:00 - 24:00"
            ],
            "isOpen": true,
            "structured": [
                {
                    "start": "T000000",
                    "duration": "PT24H00M",
                    "recurrence": "FREQ:DAILY;BYDAY:MO,TU,WE,TH,FR,SA,SU"
                }
            ]
        }
    ]
},

As you can see, quite a bit of information is returned. Everything from it's location to contact information about open hours.

Routing also has a REST API with extensive options covering things like waypoints (stopping at certain points along the way), avoidance (avoiding locations as well as types of locations) and routes that make use of public transit. Here's a simple example of a route calculation call:

https://router.hereapi.com/v8/routes?transportMode=car&origin=30.22,-92.02&destination=32.8047,-96.6782&return=summaryapikey={{apiKey}}

This just returns a summary of the trip which would useful for letting the user know how long it's going to take to get to their destination. You can absolutely return much more information including complete turn by turn navigation.

Lastly, the starter code project makes use of IBM Cloudant for storing resources and their location. While Cloudant is excellent, you may also want to consider using HERE's Data Hub. Data Hub lets you store data with specific APIs tailored for location related tasks. For example, returning all items within a certain radius. Data Hub is part of our freemium tier and consists of APIs, a CLI, as well as Studio, a full web-based tool for rendering maps of location-aware data.

I hope this has been useful for folks accepting the Call for Code challne. If you need more help with HERE's tools, be sure to visit us on Slack or Stack Overflow. We'll also be creating more helpful content for Call for Code and will be answering real-time questions on future IBM Twitch streams.