Hands On
100DaysOfCode

Solutions: Day 96-100 #100DaysOfCode

By Raymond Camden | 14 July 2020

Try HERE Maps

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

Get Started

Welcome to the 20th, and final, week of #100DaysOfCode with HERE. It's my honor to bring this to a wrap with a look at Data Hub. Data Hub is a cloud service focused on working with geospatial data. It allows developers to upload their data and then provides incredibly rich APIs that work with that data in a location-focused manner. The final week of #100DaysOfCode focused on working with Data Hub including how to integrate it with our Maps.

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 the previous days, you can find them in our earlier blog posts or on our YouTube channel.

Day 96

Day 96 started off rather easy. Your task was to simply get the Data Hub CLI installed. This required the use of npm, or Node Package Manager, which if you already have Node installed than you're ready to go. If not, you can install Node at Nodejs.org. To be clear, you do not have to be a Node developer to work with Data Hub. As a tool, npm is widely used to install utilities for developers. I'll use Node in later days but that's completely optional. You can use any programming language with Data Hub!

Assuming you do have Node and npm installed, you can install the Data Hub CLI like so:

npm install -g @here/cli

When done, you can confirm you've got it running by typing here -V

shot1-2

After you've got the CLI installed, you then need to login. These are the same credentials you can get by signing up for a free developer account at https://developer.here.com. This is done with here configure. You'll be prompted to enter your email address and password. This is a one time operation and the CLI will remember your credentials going forward.

You can read more about the CLI at the docs.

Day 97

On this day you were asked to download GeoJSON data and add it to a new Data Hub space. A "space" is simply a bucket for your data. In fact, you can think of it as a database. While you can use any GeoJSON data (or CSV, and more), I suggest the National Parks Service GeoJSON data found here: https://www.nps.gov/lib/npmap.js/4.0.0/examples/data/national-parks.geojson.

Download this file. Next, create a new Data Hub space with the CLI:

here xyz create -t "NPS Data"

THe -t option gives a title to the space. You can also use -d to provide a description. When you do this, an ID value will be displayed:

shot2-2

Next, we need to upload it. This is done via:

here xyz upload X -f filename

Where X is the ID of the space you created and filename is your filename. You'll get a nice summary when done:

shot3-2

The final action was to confirm your data was uploaded by looking at the contents. Technically the result of the last operation was more than enough to confirm it, but let's cross our Is and dot our Ts as I like to say. You can do this by using the show command:

here xyz show X

Again, X should be replaced by your space ID. This will output all of the contents:

shot4-2

Day 98

In the previous two days you've used the CLI to work with and manage spaces. You created a new space and uploaded data from the National Parks Service. Today's challenge was to use the REST APIs to retrieve features from the space.

Our REST APIs do everything the CLI does and more. In our case, we want to display contents from a space using the Iterate end point. It looks like so:

https://xyz.api.here.com/hub/spaces/${SPACE_ID}/iterate?access_token=${ACCESS_TOKEN}

Where ${SPACE_ID} is the ID of the space and ${ACCESS_TOKEN} is your security token. You can get your token at the Space Manangement utility. Login at that location and click the "Access Management" link on top. Then click "Generate Token". In the UI that pops up, click "readFeatures" in the first row ("ALL") to create a read only token for all your spaces.

shot5-2

Click Next in the next two screens (Features and Details) and click Submit. The new token will be displayed on top of the page:

shot6

With that token, and your space ID, you can get your data with a few lines in most any programming language. Here's a Node script that does it. It makes use of the DotEnv project to store both values in a .env file.

const fetch = require('node-fetch');

require('dotenv').config();
const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
const SPACE_ID = process.env.SPACE_ID;

fetch(`https://xyz.api.here.com/hub/spaces/${SPACE_ID}/iterate?access_token=${ACCESS_TOKEN}`)
.then(res => {
    return res.json();
})
.then(res => {
    console.log(res);
})
.catch(e => {
    console.error(e);    
});

Here's the result in my terminal:

shot7

Day 99

In yesterday's challenge, you used Data Hub's REST API to ask for data (features) from a space. I mentioned earlier that one of Data Hub's strengths is that it provides features specifically related to location. One simple but cool example of this is asking for data near a location. Your challenge for this day was to just that - ask for features near a location. Data Hub can find items within a radius, within a bounding box, in a polygon, and along a line. To search within a radius is fairly simple. Find a center location and figure out how big you want your circle. The endpoint looks like so:

https://xyz.api.here.com/hub/spaces/${SPACE_ID}/spatial?access_token=${ACCESS_TOKEN}&lat=${LAT}&lon=${LON}&radius=${RAD}

Here's a complete script written in Node.js (and again, remember that it's just a REST API, you can use any language):

const fetch = require('node-fetch');

require('dotenv').config();
const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
const SPACE_ID = process.env.SPACE_ID;

// City of New Orleans, LA
const LAT = 29.95;
const LON = -90.07;
// How big of a circle to search (meters)
const RAD = 5000;

fetch(`https://xyz.api.here.com/hub/spaces/${SPACE_ID}/spatial?access_token=${ACCESS_TOKEN}&lat=${LAT}&lon=${LON}&radius=${RAD}`)
.then(res => {
    return res.json();
})
.then(res => {
    console.log(res);
})
.catch(e => {
    console.error(e);    
});

Day 100

For the final challenge we're going to add the features from the Data Hub space to a map. For this we will use our interactive JavaScript maps. To start, we can create a map, centered on America (since our data is American parks):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Test XYZ</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>
    body {
        margin: 0;
    }

    #mapContainer {
    width: 100vw;
    height: 100vh;
    }
    </style>
  </head>
  <body>

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

    <script>
    // Get this at developer.here.com, it's a JavaScript key
    const HERE_MAPS_KEY = "change to your key";

    var platform = new H.service.Platform({
        apikey: HERE_MAPS_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: 4,
            center: { lat: 38.7984, lng: -96.3944 },
            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>

This renders a nice map:

shot8

For more on basic MapsJS usage, see the blog post for days 0-5.

Now to add in Data Hub, we only need a few lines. First, we'll create a few variables for our keys and the space.

// This is a read only key you can get in our token manager
const DATA_HUB_ACCESS_TOKEN = "AMuu6pamTieLe38Ybun60gA";
// Your space ID
const SPACE_ID = "uK3E2YoX";

Next, we create an instance of the service. You'll see XYZ a few times as this was the previous name of the product.

const service = platform.getXYZService({
    token: DATA_HUB_ACCESS_TOKEN,
});

Then we create a "provider" object:

const mySpaceProvider = new H.service.xyz.Provider(service, SPACE_ID, {});

Notice that the space ID is passed to it. Then we can tie this to a map layer:

const mySpaceLayer = new H.map.layer.TileLayer(mySpaceProvider);

And the final bit is to add it to the map:

map.addLayer(mySpaceLayer);

And that's it! Here's the result:

shot9

This map simply renders the locations but doesn't provide any functionality. It would absolutely be possible to add touch events that show data about the parks being rendered.

Conclusion

I hope you enjoyed this quick look at Data Hub. There is a heck of a lot more to Data Hub than I showed today, so be sure to check it out and see for yourself. Follow us on Twitter to see what we're up to, check out the Youtube playlist for this series, and finally, check the repository for all the solutions for #100DaysOfCode with HERE.