Skip to main content

Finding device location using Wi-Fi networks

This tutorial demonstrates how to find a device's location using Wi-Fi networks with nRF Connect SDK samples and nRF Cloud.

Tools

This tutorial uses Visual Studio Code with the nRF Connect extension.

Hardware requirements

The reference device for this tutorial is the nRF9160 DK. The DK has the LTE modem required for the device to communicate with nRF Cloud.

You must also supply your own external Wi-Fi module with Zephyr support.

Connect the device directly to a computer that can send commands through a terminal.

Prerequisites

See common prerequisites for Location Services, such as connecting your device to nRF Cloud.

Samples

The following samples support Wi-Fi location:

Though both samples perform the same functions, which one you choose depends on your requirements and implementation:

  • Use Modem Shell if you want to manually call the nRF Cloud API, and can keep the device connected directly to your computer.
  • Use the Location sample if you want to be able to disconnect the device from your computer after programming and test its location somewhere else. This requires an external power source.

Setup

The following steps set up the tools and hardware:

  1. Open Visual Studio Code on your computer.
  2. Install the required Visual Studio Code extensions if you do not already have them.
    • If you want to use Modem Shell and can establish physical connection to the device over USB from your computer, also install a serial terminal application such as PuTTY.
  3. Connect your device over USB and power it on.
  4. Under the Connected Devices tab, select your device.
  5. Create the sample and program your device with Modem Shell or the Location sample. Build with an overlay to enable Wi-Fi support corresponding to the Wi-Fi chip and sample you are using:
    • If you are building the Modem Shell sample and using the ESP8266 chip for Wi-Fi, see ESP8266 Wi-Fi support in the sample documentation for information on build configuration.
    • If you are building the Location sample and using the ESP8266 chip for Wi-Fi, see ESP8266 Wi-Fi support in the sample documentation for information on build configuration.
  6. Make sure your device appears as connected in nRF Terminal.

You now have three options:

Using the Location sample

Once you have finished setting up the Location sample, you do not need to keep your device connected to your computer by USB, as long as the device is connected to nRF Cloud.

Reboot your device. The sample automatically determines location, displayed as method, latitude, longitude, and accuracy in the output. nRF Cloud adds an entry to the device's location history, which you can see on a map on the device's page in the nRF Cloud portal.

Using Modem Shell

Once you have finished setting up Modem Shell, complete the following steps:

  1. Install a serial terminal application if you do not already have one, such as PuTTY.
  2. Open a serial command terminal.
  3. Establish a connection to your device. Check that the selected COM port and baud rate are correct. You can see available COM ports under the Connected Devices tab.
  4. Enter the command location get --method wifi --wifi_timeout 60 --method cellular --cellular_service nrf in the terminal. This command determines location using Wi-Fi, and falls back to cellular if Wi-Fi is unavailable.

nRF Cloud adds an entry to the device's location history. You can find this history either through the map card on the device page in the nRF Cloud portal, or using the GetLocationHistory endpoint.

If you have programmed your device with Modem Shell and want to use the nRF Cloud REST API to determine location, see Using the nRF Cloud REST API.

Using the nRF Cloud REST API

Using the nRF Cloud REST API requires a JWT or service evaluation token for authentication.

Once you have finished setting up Modem Shell, connect to your device with a serial terminal and find the MAC addresses required for the API request:

  1. Install a serial terminal application if you do not already have one, such as PuTTY.
  2. Open a serial command terminal.
  3. Establish a connection to your device. Check that the selected COM port and baud rate are correct. You can see available COM ports under the Connected Devices tab.
  4. Choose at least two MAC addresses (six hexadecimal pairs, separated by colons or dashes) associated with nearby access points (APs):
    1. In the serial terminal, enter the command wifi scan.
    2. The terminal shows a list of access points and addresses.
    3. Make note of the addresses. You need at least two of them when calling the API.

There are now two ways you can request a location using Wi-Fi data: using Wi-Fi only, or a combined Wi-Fi and cell ground fix request.

Using Wi-Fi only

Call the GetLocationFromWifiNetworks endpoint. Include required and optional parameters as an accessPoints array, formatted as JSON:

  • macAddress: Required. The addresses you found in the previous step.

  • ssid: Optional. The SSID as a string, if required by the access point.

  • signalStrength: Optional. Signal strength in dBm.

  • frequency or channel: Optional. In MHz for frequency, or numerical value for channel.

    Example request:

     curl -X POST $API_HOST/v1/location/wifi
    -H "Authorization: Bearer <generated token>"
    -H "Content-Type: application/json"
    -d {
    "accessPoints": [
    {
    "macAddress": "aa:6b:20:d9:ef:01",
    "ssid": "Example1",
    "signalStrength": -45,
    "channel": 2
    },
    {
    "macAddress": "c5:02:e3:81:b4:76",
    "ssid": "Example2",
    "signalStrength": -90,
    "channel": 1
    }
    ]
    }

The server responds with latitude, longitude, and uncertainty. Calling this endpoint also adds an entry to the device's location history.

Using ground fix

The ground fix endpoint combines Wi-Fi and cellular methods into a single call. The service attempts to find the device's location using Wi-Fi first and falls back to cellular if the Wi-Fi request cannot be resolved.

Example

The following example is for REST using Wi-Fi and cellular data:

curl --location --request POST "$API_HOST/v1/location/ground-fix" \
--header "Authorization: Bearer $JWT" \
--header "Content-Type: application/json" \
--data-raw "{\"lte\":[{\"mcc\":$MCC, \"mnc\":$MNC,\"tac\":$TAC,\"eci\":$ECI}], \"wifi\":{\"accessPoints\": [{\"macAddress\": \"FE:1E:41:2D:9E:53\", \"ssid\": \"my-wifi-network\", \"signalStrength\": -42}, {\"macAddress\": \"EF:E1:14:D2:E9:35\", \"ssid\": \"my-other-wifi-network\", \"signalStrength\": -22}]}}"

For Wi-Fi, use the -d or --data-raw field to pass a JSON-formatted accessPoints array including the following parameters:

  • macAddress: Required. The addresses you found in the previous step.
  • ssid: Optional. The SSID as a string, if required by the access point.
  • signalStrength: Optional. Signal strength in dBm.
  • frequency or channel: Optional. In MHz for frequency, or numerical value for channel.

The server responds with latitude, longitude, and uncertainty in meters. See GetLocationFromCellTowersOrWifiNetworks for an example request and response.

The server stores this cell location data in the location history. To view this, call the GetLocationHistory endpoint.