Category Archives: Geo Developers Blog

Google Geo Developers Blog

Do you like the new look of the Maps APIs tutorials?

Until recently, our docs have focused on describing features rather than telling a story. We chatted to some developers and came up with a new design for our tutorials. We’d love to know what you think of them.



Developers tell us they want quick, straightforward guides on how to integrate the Google Maps APIs into their app. The most common thing people want to do is to add a map with a marker. Just show me how to do that.





Developers are also looking for complete, step-by-step tutorials for the most common use cases. Guides that go all the way from a to z, with no deviations.



And they want code. Front and foremost. All the code.



Here are some examples of the new-look tutorials:






Each tutorial provides the entire development project, especially useful for the native mobile APIs. The doc page goes hand in hand with a new sample app on GitHub. For example, here’s the code for the current place tutorial on Android.



Each page includes a visual illustration of what you’ll achieve by following the tutorial. A working demo is ideal (such as the visualizing data tutorial for the Google Maps JavaScript API), otherwise a screenshot (as we’ve done for the native mobile APIs).



We want to make it easy for developers to find the guides. So, we’re adding tutorial showcases to the API overview pages. To date we’ve created the showcases for Android, iOS, and JavaScript. We’re also collecting together all the tutorials for the Maps JavaScript API in one place.







We’ve made a good start, but there’s plenty of change still to come. What would you like to see more of? Are we on the right track? The tech writing team would love your ideas—please add comments to this post.






author image

Posted by Sarah Maddox, Technical Writer, Google Maps APIs




Styling and custom data for polylines and polygons in the Google Maps Android API

Polygons, polylines and ground overlays are useful tools to make your maps work for your users. Today we are rolling out even more custom styling and data object association features in the Google Maps Android API to further help you customize your maps.


Style your shapes: polygons and polylines

We brought custom map styling to mobile platforms last year to help you match your map styles to your brands, apps, and more. We've seen hot pink, cool silver (shown in screenshots below), and everything in between, helping users feel at home and see what's relevant in your maps. Now we're expanding styling options for polygons and polylines, allowing you to use new stroke patterns for outlines, different caps and joints, and more, on Android devices.
Polygons.png
Your shape, your style. Now on Android

Now you have plenty of options to customize your shapes. You can change the stroke patterns in polylines and polygon outlines from solid lines to custom dashes, dots, or gaps. In polylines and polygons, you can use a bevel or round joint type rather than fixed miter joints. You can also change the cap at each end of a polyline to a square or round cap, or even specify a custom bitmap for the cap. Have a favorite fancy arrowhead you've always wanted to put in? Do it–let your imagination run wild!
Polylines.png
Get your styles in line. Now on Android.

Learn how to set and customize these new styles in our new polyline and polygon tutorial or dive straight into the documentation to get started—check out the stroke patterns, for example. Note that these new styling features are available in the full Google Maps Android API only, not in lite mode.

Store custom data with polygons, polylines, and ground overlays

Until today, you could only store data objects with markers. We're extending this functionality to polygons, polylines, circles, and ground overlays. This means you can extend your geometry objects to have any kind of data or properties you want. You no longer need to manage your data associations to your mapping visualizations–nobody enjoys writing that code anyway. For example, if you supply a set of ground overlays showing home floor plans you could store a database reference with each one. The database can contain anything! It could hold real estate listings, and you could open one of those listing URLs on click.

For further information, review our release notes.

Thank you for using the Google Maps Android API! Be sure to share your feedback or any issues in the issue tracker.

author image
Posted by Joel Kalmanowicz, Product Manager, Google Maps APIs

Styling and custom data for polylines and polygons in the Google Maps Android API

Polygons, polylines and ground overlays are useful tools to make your maps work for your users. Today we are rolling out even more custom styling and data object association features in the Google Maps Android API to further help you customize your maps.



Style your shapes: polygons and polylines

We brought custom map styling to mobile platforms last year to help you match your map styles to your brands, apps, and more. We've seen hot pink, cool silver (shown in screenshots below), and everything in between, helping users feel at home and see what's relevant in your maps. Now we're expanding styling options for polygons and polylines, allowing you to use new stroke patterns for outlines, different caps and joints, and more, on Android devices.




Polygons.png
Your shape, your style. Now on Android


Now you have plenty of options to customize your shapes. You can change the stroke patterns in polylines and polygon outlines from solid lines to custom dashes, dots, or gaps. In polylines and polygons, you can use a bevel or round joint type rather than fixed miter joints. You can also change the cap at each end of a polyline to a square or round cap, or even specify a custom bitmap for the cap. Have a favorite fancy arrowhead you've always wanted to put in? Do it–let your imagination run wild!




Polylines.png
Get your styles in line. Now on Android.


Learn how to set and customize these new styles in our new polyline and polygon tutorial or dive straight into the documentation to get started—check out the stroke patterns, for example. Note that these new styling features are available in the full Google Maps Android API only, not in lite mode.



Store custom data with polygons, polylines, and ground overlays

Until today, you could only store data objects with markers. We're extending this functionality to polygons, polylines, circles, and ground overlays. This means you can extend your geometry objects to have any kind of data or properties you want. You no longer need to manage your data associations to your mapping visualizations–nobody enjoys writing that code anyway. For example, if you supply a set of ground overlays showing home floor plans you could store a database reference with each one. The database can contain anything! It could hold real estate listings, and you could open one of those listing URLs on click.



For further information, review our release notes.



Thank you for using the Google Maps Android API! Be sure to share your feedback or any issues in the issue tracker.





author image
Posted by Joel Kalmanowicz, Product Manager, Google Maps APIs


Open-Sourcing Google Earth Enterprise



We are excited to announce that we are open-sourcing Google Earth Enterprise (GEE), the enterprise product that allows developers to build and host their own private maps and 3D globes. With this release, GEE Fusion, GEE Server, and GEE Portable Server source code (all 470,000+ lines!) will be published on GitHub under the Apache2 license in March.
Screen Shot 2017-01-26 at 2.51.24 PM.png

Originally launched in 2006, Google Earth Enterprise provides customers the ability to build and host private, on-premise versions of Google Earth and Google Maps. In March 2015, we announced the deprecation of the product and the end of all sales. To provide ample time for customers to transition, we have provided a two year maintenance period ending on March 22, 2017. During this maintenance period, product updates have been regularly shipped and technical support has been available to licensed customers.

Feedback is important to us and we’ve heard from our customers that GEE remains in-use in mission-critical applications. Many customers have not transitioned to other technologies. Open-sourcing GEE allows our customer community to continue to improve and evolve the project in perpetuity. Note that the Google Earth Enterprise Client, Google Maps JavaScript® API V3 and Google Earth API will not be open sourced. The Enterprise Client will continue to be made available and updated. However, since GEE Fusion and GEE Server are being open-sourced, the imagery and terrain quadtree implementations used in these products will allow third-party developers to build viewers that can consume GEE Server Databases.

We’re thankful for the help of our GEE partners in preparing the codebase to be migrated to GitHub. It’s a lot of work and we cannot do it without them. It is our hope that their passion for GEE and GEE customers will serve to lead the project into its next chapter.

Looking forward, GEE customers can use Google Cloud Platform (GCP) instead of legacy on-premises enterprise servers to run their GEE instances. For many customers, GCP provides a scalable and affordable infrastructure as a service where they can securely run GEE. Other GEE customers will be able to continue to operate the software in disconnected environments. However, we believe that the advantages of incorporating even some of the workloads on GCP will become apparent (such as processing large imagery or terrain assets on GCP that can be downloaded and brought to internal networks, or standing up user-facing Portable Globe Factories).

Moreover, GCP is increasingly used as a source for geospatial data. Google’s Earth Engine has made available over a petabyte of raster datasets which are readily accessible and available to the public on Google Cloud Storage. Additionally, Google uses Cloud Storage to provide data to customers who purchase Google Imagery today. Having access to massive amounts of geospatial data, on the same platform as your flexible compute and storage, makes generating high quality Google Earth Enterprise Databases and Portables easier and faster than ever.

We will be sharing a series of white papers and other technical resources to make it as frictionless as possible to get open source GEE up and running on Google Cloud Platform. We are excited about the possibilities that open-sourcing enables, and we trust this is good news for our community. We will be sharing more information when we launch the code in March on GitHub. For general product information, visit the Google Earth Enterprise Help Center. Review the essential and advanced training for how to use Google Earth Enterprise, or learn more about the benefits of Google Cloud Platform.

Open-Sourcing Google Earth Enterprise











We are excited to announce that we are open-sourcing Google Earth Enterprise (GEE), the enterprise product that allows developers to build and host their own private maps and 3D globes. With this release, GEE Fusion, GEE Server, and GEE Portable Server source code (all 470,000+ lines!) will be published on GitHub under the Apache2 license in March.


Screen Shot 2017-01-26 at 2.51.24 PM.png



Originally launched in 2006, Google Earth Enterprise provides customers the ability to build and host private, on-premise versions of Google Earth and Google Maps. In March 2015, we announced the deprecation of the product and the end of all sales. To provide ample time for customers to transition, we have provided a two year maintenance period ending on March 22, 2017. During this maintenance period, product updates have been regularly shipped and technical support has been available to licensed customers.



Feedback is important to us and we’ve heard from our customers that GEE remains in-use in mission-critical applications. Many customers have not transitioned to other technologies. Open-sourcing GEE allows our customer community to continue to improve and evolve the project in perpetuity. Note that the implementations for Google Earth Enterprise Client, Google Maps JavaScript® API V3 and Google Earth API will not be open sourced. The Enterprise Client will continue to be made available and updated. However, since GEE Fusion and GEE Server are being open-sourced, the imagery and terrain quadtree implementations used in these products will allow third-party developers to build viewers that can consume GEE Server Databases.



We’re thankful for the help of our GEE partners in preparing the codebase to be migrated to GitHub. It’s a lot of work and we cannot do it without them. It is our hope that their passion for GEE and GEE customers will serve to lead the project into its next chapter.



Looking forward, GEE customers can use Google Cloud Platform (GCP) instead of legacy on-premises enterprise servers to run their GEE instances. For many customers, GCP provides a scalable and affordable infrastructure as a service where they can securely run GEE. Other GEE customers will be able to continue to operate the software in disconnected environments. However, we believe that the advantages of incorporating even some of the workloads on GCP will become apparent (such as processing large imagery or terrain assets on GCP that can be downloaded and brought to internal networks, or standing up user-facing Portable Globe Factories).



Moreover, GCP is increasingly used as a source for geospatial data. Google’s Earth Engine has made available over a petabyte of raster datasets which are readily accessible and available to the public on Google Cloud Storage. Additionally, Google uses Cloud Storage to provide data to customers who purchase Google Imagery today. Having access to massive amounts of geospatial data, on the same platform as your flexible compute and storage, makes generating high quality Google Earth Enterprise Databases and Portables easier and faster than ever.



We will be sharing a series of white papers and other technical resources to make it as frictionless as possible to get open source GEE up and running on Google Cloud Platform. We are excited about the possibilities that open-sourcing enables, and we trust this is good news for our community. We will be sharing more information when we launch the code in March on GitHub. For general product information, visit the Google Earth Enterprise Help Center. Review the essential and advanced training for how to use Google Earth Enterprise, or learn more about the benefits of Google Cloud Platform.

Introducing insights in the Google My Business API





Today we are introducing business location insights in the Google My Business API to make it easier for third-party application developers and large multi-location brands to programmatically access location insights such as total number of searches, views and actions that let business owners track and analyze where and how people are finding them on Google.



Developers can now use the Google My Business API to request up to 18 months worth of data for each of their business locations and build applications that aggregate and visualize these insights in actionable ways. For example, a coffee shop with hundreds of locations can now easily compare and understand trends across their different locations such as number of user views, click requests for directions, phone calls, and more. They can use these insights to better allocate resources across locations and track how marketing activities affect their business.



This new API functionality brings the features from our Google My Business dashboard into your own data analysis tools. Web interface users might generate a chart of the last 90 days of Google My Business information:




Example data visible via the Google My Business web dashboard





Now the underlying data is available via the API. It's easy to get started with our new developer documentation. Here's a simple HTML request that provides a breakdown of how many searches a business listing is getting on Google Search and Google Maps:



REQUEST:

POST https://mybusiness.googleapis.com/v3/123456/locations:reportInsights
{
"locationNames": [
“accounts/110714876951578713336/locations/14372810722634034850”,
],
“basicRequest” : {
"metricRequests": [
{
"metric": QUERIES_DIRECT,
},
{
"metric": QUERIES_INDIRECT,
}
],
"timeRange": {
"startTime": 2016-10-12T01:01:23.045123456Z,
"endTime": 2017-01-10T23:59:59.045123456Z,
},
},
}



RESPONSE:

{
"locationMetrics": [
{
"locationName": "accounts/110714876951578713336/locations/
14372810722634034850",
"timeZone": "America/Los_Angeles",
"metricValues": [
{
"metric": "QUERIES_DIRECT",
"totalValue": {
"metricOption": "AGGREGATED_TOTAL",
"timeDimension": {
"timeRange": {
"startTime": "2016-10-12T04:00:00Z",
"endTime": "2017-01-10T04:00:00Z"
}
},
"value": "36738"
}
},
{
"metric": "QUERIES_INDIRECT",
"totalValue": {
"metricOption": "AGGREGATED_TOTAL",
"timeDimension": {
"timeRange": {
"startTime": "2016-10-12T04:00:00Z",
"endTime": "2017-01-10T04:00:00Z"
}
},
"value": "81770"
}
}
]
}
]
}



Here is an example that captures insights on the places from where customers request driving directions to a business:



REQUEST:

POST https://mybusiness.googleapis.com/v3/123456/locations:reportInsights
{
“locationNames": [
“accounts/110714876951578713336/locations/14372810722634034850”,
],
"drivingDirectionsRequest”: {
"numDays": NINETY,
},
}



RESPONSE (truncated to show first 3 results):

{
"locationDrivingDirectionMetrics": [
{
"locationName": "accounts/110714876951578713336/locations/
14372810722634034850",
"topDirectionSources": [
{
"dayCount": 90,
"regionCounts": [
{
"latlng": {
"latitude": 37.789,
"longitude": -121.392
},
"label": "94105",
"count": "2980",
},
{
"latlng": {
"latitude": 37.779,
"longitude": -122.421
},
"label": "94102",
"count": "887",
},
{
"latlng": {
"latitude": 37.773,
"longitude": -122.410
},
"label": "94103",
"count": "886",
}
]
}
],
"timeZone": "America/Los_Angeles"
}
]
}






Example data visible via the Google My Business web dashboard





With this new feature, Google My Business API users can optimize their listings to drive customer actions through understanding key insights about how customers are searching for their business on Google, and what actions they are taking once they find it. These insights are also available on Google My Business web and mobile, allowing users to keep track of key trends from anywhere.



To learn more about the Google My Business API and to apply for access, visit our developer page. Questions or feedback? Contact the API team on the Google My Business API Forum.

Introducing insights in the Google My Business API



Today we are introducing business location insights in the Google My Business API to make it easier for third-party application developers and large multi-location brands to programmatically access location insights such as total number of searches, views and actions that let business owners track and analyze where and how people are finding them on Google.

Developers can now use the Google My Business API to request up to 18 months worth of data for each of their business locations and build applications that aggregate and visualize these insights in actionable ways. For example, a coffee shop with hundreds of locations can now easily compare and understand trends across their different locations such as number of user views, click requests for directions, phone calls, and more. They can use these insights to better allocate resources across locations and track how marketing activities affect their business.

This new API functionality brings the features from our Google My Business dashboard into your own data analysis tools. Web interface users might generate a chart of the last 90 days of Google My Business information:
Example data visible via the Google My Business web dashboard

Now the underlying data is available via the API. It's easy to get started with our new developer documentation. Here's a simple HTML request that provides a breakdown of how many searches a business listing is getting on Google Search and Google Maps:

REQUEST:
POST https://mybusiness.googleapis.com/v3/123456/locations:reportInsights
{
  "locationNames": [
    “accounts/110714876951578713336/locations/14372810722634034850”,
  ],
  “basicRequest” : {
          "metricRequests": [
             {
               "metric": QUERIES_DIRECT,
             },
             {
               "metric": QUERIES_INDIRECT,
             }
          ],
          "timeRange": {
               "startTime": 2016-10-12T01:01:23.045123456Z,
               "endTime": 2017-01-10T23:59:59.045123456Z,
          },
    },
}

RESPONSE:
{
  "locationMetrics": [
    {
      "locationName": "accounts/110714876951578713336/locations/
                       14372810722634034850",
      "timeZone": "America/Los_Angeles",
      "metricValues": [
        {
          "metric": "QUERIES_DIRECT",
          "totalValue": {
            "metricOption": "AGGREGATED_TOTAL",
            "timeDimension": {
              "timeRange": {
                "startTime": "2016-10-12T04:00:00Z",
                "endTime": "2017-01-10T04:00:00Z"
              }
            },
            "value": "36738"
          }
        },
        {
          "metric": "QUERIES_INDIRECT",
          "totalValue": {
            "metricOption": "AGGREGATED_TOTAL",
            "timeDimension": {
              "timeRange": {
                "startTime": "2016-10-12T04:00:00Z",
                "endTime": "2017-01-10T04:00:00Z"
              }
            },
            "value": "81770"
          }
        }
      ]
    }
  ]
}

Here is an example that captures insights on the places from where customers request driving directions to a business:

REQUEST:
POST https://mybusiness.googleapis.com/v3/123456/locations:reportInsights
{
     “locationNames": [
             “accounts/110714876951578713336/locations/14372810722634034850”,
       ],
      "drivingDirectionsRequest”: {
            "numDays": NINETY,
      },
}

RESPONSE (truncated to show first 3 results):
{
  "locationDrivingDirectionMetrics": [
    {
      "locationName": "accounts/110714876951578713336/locations/
                       14372810722634034850",
      "topDirectionSources": [
        {
          "dayCount": 90,
          "regionCounts": [
            {
              "latlng": {
                "latitude": 37.789,
                "longitude": -121.392
              },
              "label": "94105",
              "count": "2980",
            },
            {
              "latlng": {
                "latitude": 37.779,
                "longitude": -122.421
              },
              "label": "94102",
              "count": "887",
            },
            {
              "latlng": {
                "latitude": 37.773,
                "longitude": -122.410
              },
              "label": "94103",
              "count": "886",
            }
          ]
        }
      ],
          "timeZone": "America/Los_Angeles"
    }
  ]
}
Example data visible via the Google My Business web dashboard

With this new feature, Google My Business API users can optimize their listings to drive customer actions through understanding key insights about how customers are searching for their business on Google, and what actions they are taking once they find it. These insights are also available on Google My Business web and mobile, allowing users to keep track of key trends from anywhere.

To learn more about the Google My Business API and to apply for access, visit our developer page. Questions or feedback? Contact the API team on the Google My Business API Forum.

Geolocation and Firebase for the Internet of Things



GPS is the workhorse of location based services, but there are use cases where you may want to avoid the cost and power consumption of GPS hardware or locate devices in places where GPS lacks accuracy, such as in urban environments or buildings.

We've seen recent growth in Internet of Things (IoT) applications using the Google Maps Geolocation API instead of GPS for asset tracking, theft prevention, usage optimization, asset servicing, and more. As part of my 20 percent project at Industry Solutions, I created a prototype IoT device that can locate itself using surrounding WiFi networks and the Google Maps Geolocation API. In this post, I’ll discuss some interesting implementation features and outline how you can create the prototype yourself.

I built a device that scans for local WiFi and writes results (WiFi hotspots and their signal strength) to a Firebase Realtime Database. A back-end service then reads this data and uses the Google Maps Geolocation API to turn this into a real-world location, which can be plotted on a map.

Set up the Device & Write Locally

For this proof of concept, I used the Intel Edison as a Linux-based computing platform and augmented it with Sparkfun’s Edison Blocks. To build the device, you will need an Intel Edison, a Base Block, a Battery Block and a Hardware pack.

Developing for the Edison is straightforward using the Intel XDK IDE. We will be creating a simple Node.js application in JavaScript. I relied on 3 libraries: Firebase for the database connection, wireless-tools/iwlist to capture WiFi networks, and macaddress to capture the device MAC. Installation instructions can be found on the linked pages.

Step 1: get the device MAC address and connect to Firebase:
function initialize() {
    macaddress.one('wlan0', function (err, mac) {
        mac_address = mac;
        if (mac === null) {
            console.log('exiting due to null mac Address');
            process.exit(1);
        }
        firebase.initializeApp({
            serviceAccount: '/node_app_slot/<service-account-key>.json',
            databaseURL: 'https://<project-id>.firebaseio.com/'
        });
        var db = firebase.database();
        ref_samples = db.ref('/samples');
        locationSample();
    });
}
The above code contains two placeholders:

  1. The service-account-key is a private key you create in the Firebase Console. Follow the gear icon in the upper left of console, select “settings”, and click Generate New Private Key. Place this key on your Edison in the directory /node_app_slot/. See this Firebase documentation for more information.
  2. The project-id in the database URL is found in the Firebase console database page after you have linked your Google project with Firebase.


Step 2: scan for WiFi networks every 10 seconds and write locally:
function locationSample() {
    var t = new Date();
    iwlist.scan('wlan0', function(err, networks) {
        if(err === null) {
            ref_samples.push({
                mac: mac_address,
                t_usec: t.getTime(),
                t_locale_string: t.toLocaleString(),
                networks: networks,
            });
        } else {
            console.log(err);
        }        
    });
    setTimeout(locationSample, 10000);
}

Write to the cloud

The locationSample() function above writes detectable WiFi networks to a Firebase database that syncs to the cloud when connected to a network.

Caveat: To configure access rights and authentication to Firebase, I set up the device as a “server”. Instructions for this configuration are on the Firebase website. For this proof of concept, I made the assumption that the device was secure enough to house our credentials. If this is not the case for your implementation you should instead follow the instructions for setting up the client JavaScript SDK.

The database uses 3 queues to manage workload: a WiFi samples queue, a geolocation results queue and a visualization data queue. The workflow will be: samples from the device go into a samples queue, which gets consumed to produce geolocations that are put into a geolocations queue. Geolocations are consumed and formatted for presentation, organized by device, and the output is stored in a visualizations bucket for use by our front end website.

Below is an example of a sample, a geolocation, and our visualization data written by the device and seen in the Firebase Database Console.

Processing the Data with Google App Engine

To execute the processing of the sample data I used a long running Google App Engine Backend Module and a custom version of the Java Client for Google Maps Services.

Caveat: To use Firebase with App Engine, you must use manual scaling. Firebase uses background threads to listen for changes and App Engine only allows long-lived background threads on manually scaled backend instances.

The Java Client for Google Maps Services takes care of a lot of the communications code required to use the Maps APIs and follows our published best practices for error handling and retry strategies that respect rate limits. The GeolocateWifiSample() function below is registered as an event listener with Firebase. It loops over each network reported by the device and incorporates it into the geolocation request.
private void GeolocateWifiSample(DataSnapshot sample,  Firebase db_geolocations, Firebase db_errors) {
    // initalize the context and request
    GeoApiContext context = new GeoApiContext(new GaeRequestHandler()).setApiKey("");
    GeolocationApiRequest request = GeolocationApi.newRequest(context)
            .ConsiderIp(false);
    // for every network that was reported in this sample...
    for (DataSnapshot wap : sample.child("networks").getChildren()) {
        // extract the network data from the database so it’s easier to work with
        String wapMac = wap.child("address").getValue(String.class);
        int wapSignalToNoise = wap.child("quality").getValue(int.class);
        int wapStrength = wap.child("signal").getValue(int.class);
        // include this network in our request
        request.AddWifiAccessPoint(new WifiAccessPoint.WifiAccessPointBuilder()
                .MacAddress(wapMac)
                .SignalStrength(wapStrength)
                .SignalToNoiseRatio(wapSignalToNoise)
                .createWifiAccessPoint());
    }
    ...
    try {
        // call the api
        GeolocationResult result = request.CreatePayload().await();
        ...
        // write results to the database and remove the original sample
    } catch (final NotFoundException e) {
        ...
    } catch (final Throwable e) {
        ...
    }
}
Register the GeolocateWifiSample() function as an event handler. The other listeners that process geolocation results and create the visualization data are built in a similar pattern.
ChildEventListener samplesListener = new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        // geolocate and write to new location
        GeolocateWifiSample(dataSnapshot, db_geolocations, db_errors);
    }
    ...
};
db_samples.addChildEventListener(samplesListener);

Visualize the Data

To visualize the device locations I used Google App Engine to serve stored data from Firebase and the Google Maps JavaScript API to create a simple web page that displays the results. The index.html page contains an empty <div> with id “map”. I initialized this <div> to contain the Google Map object. I also added “child_added” and “child_removed” event handlers to update the map as the data changes over time.
function initMap() {
    // attach listeners
    firebase.database().ref('/visualization').on('child_added', function(data) {
        ...
        data.ref.on('child_added', function(vizData) {
            circles[vizData.key]= new CircleRoyale(map,
                                vizData.val().lat,
                                vizData.val().lng,
                                vizData.val().accuracy,
                                color);
          set_latest_position(data.key, vizData.val().lat, vizData.val().lng);
        });
        data.ref.on('child_removed', function(data) {
            circles[data.key].removeFromMap();
        });
    });
    // create the map
    map = new google.maps.Map(document.getElementById('map'), {
      center: get_next_device(),
      zoom: 20,
      scaleControl: true,
    });
    ...
}
Since the API returns not only a location but also an indication of accuracy, I’ve created a custom marker that has a pulsing radius to indicate the accuracy component.
Two devices (red and blue) and their last five known positions

What’s next?

In this post I’ve outlined how you can build an IoT device that uses Google Maps Geolocation API to track any internet-connected device - from robotics to wearables. The App Engine processing module can be expanded to use other Google Maps APIs Web Services providing geographic data such as directions, elevation, place or time zone information. Happy building!

As an alternative, you can achieve a similar solution using Google Cloud Platform as a replacement for Firebase—this article shows you how.

author image
About Ken: Ken is a Lead on the Industry Solutions team. He works with customers to bring innovative solutions to market.

Geolocation and Firebase for the Internet of Things





GPS is the workhorse of location based services, but there are use cases where you may want to avoid the cost and power consumption of GPS hardware or locate devices in places where GPS lacks accuracy, such as in urban environments or buildings.



We've seen recent growth in Internet of Things (IoT) applications using the Google Maps Geolocation API instead of GPS for asset tracking, theft prevention, usage optimization, asset servicing, and more. As part of my 20 percent project at Industry Solutions, I created a prototype IoT device that can locate itself using surrounding WiFi networks and the Google Maps Geolocation API. In this post, I’ll discuss some interesting implementation features and outline how you can create the prototype yourself.



I built a device that scans for local WiFi and writes results (WiFi hotspots and their signal strength) to a Firebase Realtime Database. A back-end service then reads this data and uses the Google Maps Geolocation API to turn this into a real-world location, which can be plotted on a map.






Set up the Device & Write Locally


For this proof of concept, I used the Intel Edison as a Linux-based computing platform and augmented it with Sparkfun’s Edison Blocks. To build the device, you will need an Intel Edison, a Base Block, a Battery Block and a Hardware pack.





Developing for the Edison is straightforward using the Intel XDK IDE. We will be creating a simple Node.js application in JavaScript. I relied on 3 libraries: Firebase for the database connection, wireless-tools/iwlist to capture WiFi networks, and macaddress to capture the device MAC. Installation instructions can be found on the linked pages.



Step 1: get the device MAC address and connect to Firebase:

function initialize() {
macaddress.one('wlan0', function (err, mac) {
mac_address = mac;
if (mac === null) {
console.log('exiting due to null mac Address');
process.exit(1);
}
firebase.initializeApp({
serviceAccount: '/node_app_slot/<service-account-key>.json',
databaseURL: 'https://<project-id>.firebaseio.com/'
});
var db = firebase.database();
ref_samples = db.ref('/samples');
locationSample();
});
}

The above code contains two placeholders:




  1. The service-account-key is a private key you create in the Firebase Console. Follow the gear icon in the upper left of console, select “settings”, and click Generate New Private Key. Place this key on your Edison in the directory /node_app_slot/. See this Firebase documentation for more information.

  2. The project-id in the database URL is found in the Firebase console database page after you have linked your Google project with Firebase.






Step 2: scan for WiFi networks every 10 seconds and write locally:

function locationSample() {
var t = new Date();
iwlist.scan('wlan0', function(err, networks) {
if(err === null) {
ref_samples.push({
mac: mac_address,
t_usec: t.getTime(),
t_locale_string: t.toLocaleString(),
networks: networks,
});
} else {
console.log(err);
}
});
setTimeout(locationSample, 10000);
}


Write to the cloud


The locationSample() function above writes detectable WiFi networks to a Firebase database that syncs to the cloud when connected to a network.



Caveat: To configure access rights and authentication to Firebase, I set up the device as a “server”. Instructions for this configuration are on the Firebase website. For this proof of concept, I made the assumption that the device was secure enough to house our credentials. If this is not the case for your implementation you should instead follow the instructions for setting up the client JavaScript SDK.



The database uses 3 queues to manage workload: a WiFi samples queue, a geolocation results queue and a visualization data queue. The workflow will be: samples from the device go into a samples queue, which gets consumed to produce geolocations that are put into a geolocations queue. Geolocations are consumed and formatted for presentation, organized by device, and the output is stored in a visualizations bucket for use by our front end website.



Below is an example of a sample, a geolocation, and our visualization data written by the device and seen in the Firebase Database Console.




Processing the Data with Google App Engine


To execute the processing of the sample data I used a long running Google App Engine Backend Module and a custom version of the Java Client for Google Maps Services.



Caveat: To use Firebase with App Engine, you must use manual scaling. Firebase uses background threads to listen for changes and App Engine only allows long-lived background threads on manually scaled backend instances.



The Java Client for Google Maps Services takes care of a lot of the communications code required to use the Maps APIs and follows our published best practices for error handling and retry strategies that respect rate limits. The GeolocateWifiSample() function below is registered as an event listener with Firebase. It loops over each network reported by the device and incorporates it into the geolocation request.

private void GeolocateWifiSample(DataSnapshot sample,  Firebase db_geolocations, Firebase db_errors) {
// initalize the context and request
GeoApiContext context = new GeoApiContext(new GaeRequestHandler()).setApiKey("");
GeolocationApiRequest request = GeolocationApi.newRequest(context)
.ConsiderIp(false);
// for every network that was reported in this sample...
for (DataSnapshot wap : sample.child("networks").getChildren()) {
// extract the network data from the database so it’s easier to work with
String wapMac = wap.child("address").getValue(String.class);
int wapSignalToNoise = wap.child("quality").getValue(int.class);
int wapStrength = wap.child("signal").getValue(int.class);
// include this network in our request
request.AddWifiAccessPoint(new WifiAccessPoint.WifiAccessPointBuilder()
.MacAddress(wapMac)
.SignalStrength(wapStrength)
.SignalToNoiseRatio(wapSignalToNoise)
.createWifiAccessPoint());
}
...
try {
// call the api
GeolocationResult result = request.CreatePayload().await();
...
// write results to the database and remove the original sample
} catch (final NotFoundException e) {
...
} catch (final Throwable e) {
...
}
}

Register the GeolocateWifiSample() function as an event handler. The other listeners that process geolocation results and create the visualization data are built in a similar pattern.

ChildEventListener samplesListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
// geolocate and write to new location
GeolocateWifiSample(dataSnapshot, db_geolocations, db_errors);
}
...
};
db_samples.addChildEventListener(samplesListener);


Visualize the Data


To visualize the device locations I used Google App Engine to serve stored data from Firebase and the Google Maps JavaScript API to create a simple web page that displays the results. The index.html page contains an empty <div> with id “map”. I initialized this <div> to contain the Google Map object. I also added “child_added” and “child_removed” event handlers to update the map as the data changes over time.

function initMap() {
// attach listeners
firebase.database().ref('/visualization').on('child_added', function(data) {
...
data.ref.on('child_added', function(vizData) {
circles[vizData.key]= new CircleRoyale(map,
vizData.val().lat,
vizData.val().lng,
vizData.val().accuracy,
color);
set_latest_position(data.key, vizData.val().lat, vizData.val().lng);
});
data.ref.on('child_removed', function(data) {
circles[data.key].removeFromMap();
});
});
// create the map
map = new google.maps.Map(document.getElementById('map'), {
center: get_next_device(),
zoom: 20,
scaleControl: true,
});
...
}

Since the API returns not only a location but also an indication of accuracy, I’ve created a custom marker that has a pulsing radius to indicate the accuracy component.




Two devices (red and blue) and their last five known positions






What’s next?


In this post I’ve outlined how you can build an IoT device that uses Google Maps Geolocation API to track any internet-connected device - from robotics to wearables. The App Engine processing module can be expanded to use other Google Maps APIs Web Services providing geographic data such as directions, elevation, place or time zone information. Happy building!



As an alternative, you can achieve a similar solution using Google Cloud Platform as a replacement for Firebase—this article shows you how.






author image

About Ken: Ken is a Lead on the Industry Solutions team. He works with customers to bring innovative solutions to market.

Address Geocoding in the Google Maps APIs

Forward Geocoding is the process of converting addresses (like a street address) into geographic coordinates (latitude and longitude), which you can use to place markers on a map or position the map. The Google Maps APIs have several services that you can use to convert addresses into coordinates - the Geocoding API, the Place Autocomplete service in Places API, and the Place Search service in Places API. What are the differences between them and when should you use each one? Here’s where to start.

Note that while this blog focuses on the server-side Places and Geocoding APIs, these best practices also apply to the client-side Places and Geocoding services in the Google Maps JavaScript API.

Geocoding API

The Geocoding API is best for handling unambiguous queries: complete postal address strings (for example, “48 Pirrama Rd, Pyrmont, NSW, Australia”). Compared to other Google APIs, the Geocoding API provides the best quality matching of addresses globally for these types of complete, unambiguous queries. However, Geocoding API is not recommended if your application handles ambiguous or incomplete queries, such as “123 Main St”, or if it handles queries that may contain non-address information such as apartment numbers or business names.
Screen Shot 2016-11-15 at 6.16.15 PM.png
Geocoding API is best used for unambiguous complete addresses, such as "48 Pirrama Rd, Pyrmont, NSW, Australia" 

Places API

The Places API allows users to discover both addresses and semantic locations, such as cafes or parks, by name or type. In contrast to the Geocoding API, it handles ambiguous or incomplete requests in a more robust way. If your application handles user interaction, or addresses that are ambiguous or incomplete, consider the following services.


Place Autocomplete service

For applications that respond in real time to user input, we recommend using the Place Autocomplete service in the Places API. This service is designed to return multiple possible addresses and allow the user to choose between them. The autocomplete lookup function can also be biased to return results specific to a location, enabling high quality results to be returned for incomplete queries such as “123 Main St”. Since the Place Autocomplete service is optimized for responding to user input, it also has very low latency, usually at least 10x lower than the Geocoding API. It’s also good at handling misspelled queries, or queries containing non-address information, since as the user types, they can see suggestions and correct their spelling if needed.

Screen Shot 2016-11-14 at 5.35.53 PM.png
Typing "123 Main St" into a Place Autocomplete search box lets the user choose from multiple results. Results can also be biased to prefer those near the area shown on the map or near the current user location

Place Search service

The Place Autocomplete service relies on a user to choose the best option from multiple results. What if you have an application that handles ambiguous or incomplete queries in an automated fashion, with no user able to provide input?

For geocoding ambiguous or incomplete addresses in automated systems, when there is no user to select one of the autocomplete suggestions, we recommend the Place Search service in Places API. Place Search is better at coping with ambiguous queries than the Geocoding API, and lets you restrict your search to a specified area, or rank results by distance, allowing more precise filtering and ranking of results for ambiguous or incomplete queries. Place search is also more robust at responding to queries with additional non-address information such as business names or apartment numbers.

Future Changes to Geocoding API

We plan to roll out an update to the Geocoding API at the end of November 2016 that will increase the difference between Geocoding and Places performance for ambiguous and unambiguous queries. This change will improve the quality of Geocoding results for unambiguous queries, but will be more likely to return ZERO_RESULTS for ambiguous or incomplete queries where the Geocoding API was unable to find a high quality result.

If you are already using the above best practices, you should see an improvement in your Geocoding API results. If you are currently using the Geocoding API for incomplete or ambiguous queries, or for queries that may contain non-address information such as business names or apartment numbers, we recommend that you switch to the Places API instead, as it is likely to give better quality results for your use case.

You can try the new Geocoding service ahead of launch by adding an optional parameter, new_forward_geocoder=true, to your Geocoding API request. For example:

https://maps.googleapis.com/maps/api/geocode/json?new_forward_geocoder=true&address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY

If you want to try the new Geocoding service in the JavaScript Maps API Geocoding Service, you can set the new optional parameter newForwardGeocoder: true in the GeocoderRequest object. The new Geocoding service will launch for both the Geocoding API and the Geocoding Service in the JavaScript Maps API at the same time. All of the recommendations in this blog post apply to both the server-side and client-side APIs.

If you have any bug reports or feature requests for the new Geocoding service, please let us know using our public issue tracker.

In Summary

The following table sums up when we recommend you use the Geocoding API, Place Autocomplete service and Place Search service.


Geocoding API Place Search Place Autocomplete
Scope Addresses only Semantic locations and addresses, including businesses and points of interest
Strengths Unambiguous complete addresses Ambiguous or incomplete addresses in automated systems Responding to real-time user input

If your application does not yet follow these best practices, you may get worse results from Geocoding API in future, so we recommend you test how your application works with the new Geocoding service and update your application to use the above best practices if required. Try the upcoming Geocoding service by setting new_forward_geocoder=true in your geocoding request.

For more information on the Google Maps Geocoding API, Place Autocomplete in the Places API and Place Search in the Places API, please see the developer documentation. Also see this more detailed best practices guide in our documentation for more details on Geocoding best practices for various use cases, including minimizing latency when querying Directions API with addresses.

Finally, a big thank you to all the developers who use the Google Maps Geocoding API and provide feedback via the issue tracker. Getting feedback from developers is vital for us to be able to keep improving our products, so if you have any bug reports or feature requests, please let us know!

author image
Posted by Elena Kelareva, Product Manager, Google Maps APIs