You Might Not Need GNSS

You Might Not Need GNSS

Building hardware involves thinking far into the future to ensure that a device will continue to serve its intended purpose in any environment in which it may be deployed. However, simply adding more and more components to the bill of materials (BOM) can lead to hitting constraints around price, power, cost, and availability. One common requirement for connected device products is the ability to identify the current location. Generally this functionality is provided via a global navigation satellite system (GNSS), which requires dedicated hardware, has a negative impact on battery life, and can be unreliable in some locations.

There are a number of GNSS’s. You may be more familiar with a specific implementation, such as the Global Positioning System (GPS), which is operated by the United States government.

For some use cases, these attributes are not worth the precision offered by GNSS. For example, if it is only necessary to obtain the rough position of a device, it may not make sense to increase the BOM cost and decrease the battery life. Furthermore, in brownfield scenarios, it may be desirable to add location capabilities to a product when the existing hardware does not support it.

How to Know Where You Are

GNSS works by communicating with satellites that are orbiting the Earth. These satellites broadcast their position information, and after acquiring signals from four satellites, a device can use a process called trilateration to identify its own location. In short, devices can find their own location by talking to systems that know their own location.

Device obtaining location by communicating with 4 GNSS satellites.

Issues with GNSS occur when communication with these satellites is interrupted by physical obstacles or some other interference. After all, these satellites are very far away and communicate at a low data rate. To combat these limitations, some devices will employ an A-GNSS (Assisted GNSS) service, which supplies information about the satellites that aid the device in reaching its time to first fix (TTFF). This is referred to as Mobile Station Based (MSB) A-GNSS. Alternatively, the device can send the partial position data it has been able to obtain to the A-GNSS service, which the service will then use to calculate the position and return it to the device. This mode is referred to as Mobile Station Assisted (MSA).

Device obtaining location information by communicating with GNSS satellites and an A-GNSS service.

A-GNSS is a helpful solution when the behavior of the device is impacted by its location. However, in the event that the location of the device is only relevant to an external system, such as a human tracking a device, A-GNSS may not be necessary.

An alternative option to talking to a system that knows its own location is to talk to a system that knows the location of other devices that are near to you. For example, a device with a WiFi radio can identify the networks that are advertising in its area, and if a third-party is aware of the location of that network, then it can determine the rough location of the device. The same is true for a cellular device connecting to a tower, or even Bluetooth devices surrounded by other devices that may have a known location. A major advantage of this option is that the device already needs to establish this communication for connectivity, so leveraging it for location removes the need to include additional hardware, credentials, or firmware networking stacks.

Who Do You Ask

These third-parties that know where everything is sound extremely useful, but who are they? A few weeks ago, Chris Gammell wrote a blog post about using one such service, HERE, to build a geofence device with a WiFi capable ESP32-C3. Other services include those from popular smartphones makers, such as Google and Apple, each of which leverage their vast network of multi-radio devices to build out a robust database of wireless access point location information. If my phone has obtained a GNSS signal, it can survey the nearby WiFi access points and Bluetooth devices, and report their MAC addresses along with its current location back to the service. That data can then be used to help the next device identify its location just by sending one or more of those MAC addresses. If that sounds to you like it could be used for nefarious purposes, you’re right.

Many other location services you may encounter are actually just thin wrappers on the services listed above. In fact, Chris’ aforementioned post effectively built a wrapper service on HERE using the open source n8n project. However, when determining how to more seamlessly expose location services to Golioth users, we wanted to ensure that we preserved flexibility for moving between services. We also wanted to allow for devices that may already be sending network information to Golioth to be enhanced with location information without needing changes to be made to their firmware.

Device obtaining location information by sending nearby wireless network data to a positioning service.

Fortunately, our recently released webhook transformer enables leveraging external services to augment data sent from devices to Golioth. This feature is a perfect candidate for transforming network information into location data, then forwarding it along to its final destination. As with all Golioth Pipelines functionality, this can be introduced alongside existing streaming data routing without interruption.

HERE

In the following example, CBOR data streamed on the /netinfo path is transformed into JSON before being delivered to HERE’s positioning service.

filter:
  path: "/netinfo"
  content_type: application/cbor
steps:
  - name: convert
    transformer:
      type: cbor-to-json
  - name: get-location
    transformer:
      type: webhook
      parameters:
        url: $HERE_URL
  - name: send-lightdb
    destination:
      type: lightdb-stream
      version: v1

The $HERE_URL secret is in the format https://positioning.hereapi.com/v2/locate?api-key={YOUR_API_KEY}.

For example, the following device payload (shown as JSON for readability), which includes information about nearby WiFi access points, could be used for identifying the device’s location.

{
  "wlan": [
    {
      "mac": "00:18:39:59:8C:53",
      "rss": -87
    },
    {
      "mac": "00:21:55:61:F3:0A",
      "rss": -86
    },
    {
      "mac": "00:11:5C:6B:9A:00",
      "rss": -71
    }
  ]
}

The location data in this case is delivered to LightDB Stream, creating a timeseries history of the device’s location.

Location data in LightDB Stream.

HERE supports supplying information about multiple types of networks, such as WiFi and cellular, to enable more precise positioning.

Google Geolocation API

The true power of Pipelines is on display with the ability to switch out the service that resolves device location, without needing to update the firmware or systems that consume the location data. In the following pipeline, we switch from using HERE to Google’s Geolocation API, which expects a different request body.

filter:
  path: "/netinfo"
  content_type: application/cbor
steps:
  - name: convert
    transformer:
      type: cbor-to-json
  - name: transform-google-geo
    transformer:
      type: json-patch
      parameters:
        patch: |
          [
            {"op": "add", "path": "/wifiAccessPoints", "value": [{"macAddress": "", "signalStrength": 0}, {"macAddress": "", "signalStrength": 0}, {"macAddress": "", "signalStrength": 0}]},
            {"op": "move", "from": "/wlan/0/mac", "path": "/wifiAccessPoints/0/macAddress"},
            {"op": "move", "from": "/wlan/0/rss", "path": "/wifiAccessPoints/0/signalStrength"},
            {"op": "move", "from": "/wlan/1/mac", "path": "/wifiAccessPoints/1/macAddress"},
            {"op": "move", "from": "/wlan/1/rss", "path": "/wifiAccessPoints/1/signalStrength"},
            {"op": "move", "from": "/wlan/2/mac", "path": "/wifiAccessPoints/2/macAddress"},
            {"op": "move", "from": "/wlan/2/rss", "path": "/wifiAccessPoints/2/signalStrength"},
            {"op": "remove", "path": "/wlan"}
          ]
  - name: get-location
    transformer:
      type: webhook
      parameters:
        url: $GOOGLE_GEO_API_URL
  - name: transform-standard-loc
    transformer:
      type: json-patch
      parameters:
        patch: |
          [
            {"op": "add", "path": "/location/accuracy", "value": 0},
            {"op": "move", "from": "/accuracy", "path": "/location/accuracy"}
          ]
  - name: send-lightdb
    destination:
      type: lightdb-stream
      version: v1

The $GOOGLE_GEO_API_URL secret is in the format https://www.googleapis.com/geolocation/v1/geolocate?key={YOUR_API_KEY}.

We can utilize the json-patch transformer to update the structure of the device payload after converting it to JSON. After patching, the same structure for device payload sent to the HERE pipeline now looks as follows.

{
  "wifiAccessPoints": [
    {
      "macAddress": "3c:37:86:5d:75:d4",
      "signalStrength": -35
    },
    {
      "macAddress": "30:86:2d:c4:29:d0",
      "signalStrength": -35
    },
    {
      "macAddress": "30:22:96:6B:9A:11",
      "signalStrength": -22
    }
  ]
}

The Google Geolocation API returns the following response.

{
  "accuracy": 20,
  "location": {
    "lat": 37.4241224,
    "lng": -122.0915874
  }
}

This looks almost the same as the response from HERE, but the accuracy measure is outside of the location object. We can apply a second json-patch transformer to make it match exactly. The result is location data appearing in LightDB Stream with no discernible difference when moving between services. Location data in LightDB Strema.

Visualizing Device Location

With data flowing to a destination, we can then query that data source to expose location information in a helpful context. For example, we can setup a Grafana dashboard that live plots location updates for the device, allowing us to observe its movement over time without it needing to be equipped with GNSS capabilities.

Device shown in Grafana map view.

Going Further

In all of the use cases shown above, device location data was sent to a destination for consumption, but it was not returned back to the device. You can watch the demo from Chris’ post to see how Golioth’s LightDB State service can be used to return location information to a device when necessary. However, we’ll soon be introducing functionality that makes this process even easier. In the mean time, reach out on the forum to let us know how you are using Golioth Pipelines and what features you would like to see added!

Talk with an Expert

Implementing an IoT project takes a team of people, and we want to help out as part of your team. If you want to troubleshoot a current problem or talk through a new project idea, we're here for you.

Start the discussion at forum.golioth.io