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:
- Modem Shell sample for the nRF9160 DK. Use the Modem Shell sample if you want to manually call the nRF Cloud API, and can keep the device connected directly to your computer. Modem Shell allows for interactive control of commands.
- Location sample for the nRF9160 DK. 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:
Open Visual Studio Code on your computer.
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.
Connect your device over USB and power it on.
Under the Connected Devices tab, select your device.
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:
- Modem Shell: 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.
- Location sample: 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.
Make sure your device appears as connected in nRF Terminal.
You now have three options:
Run 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.
Use a command in the Modem Shell sample
Once you have finished setting up Modem Shell, complete the following steps:
- Install a serial terminal application if you do not already have one, such as PuTTY.
- Open a serial command terminal.
- 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.
- 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.
Use Modem Shell to find MAC addresses, then call 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:
- Install a serial terminal application if you do not already have one, such as PuTTY.
- Open a serial command terminal.
- 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.
- Choose at least two MAC addresses (six hexadecimal pairs, separated by colons or dashes) associated with nearby access points (APs):
- In the serial terminal, enter the command
wifi scan
. - The terminal shows a list of access points and addresses.
- Make note of the addresses. You need at least two of them when calling the API.
- In the serial terminal, enter the command
Using the nRF Cloud portal
Both Modem Shell and the Location sample are configured by default to pass location data to nRF Cloud. You can view a device's historical location data under the Location card on the device's page.
Using the nRF Cloud REST API
There are two ways you can request a location through the APIs using Wi-Fi data:
Using ground fix
The GetLocationFromCellTowersOrWifiNetworks
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
orchannel
: 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.
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
orchannel
: 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.