Indoor Asset Tracking using Wi-Fi Triangulation - Hackster.io

2022-09-02 20:12:17 By : Ms. Astrid Yang

Add the following snippet to your HTML:

Build a complete indoor asset tracking IoT solution using the Blues Wireless Notecard, an ESP32 host MCU, the Notecarrier-F, and Datacake.

Read up about this project on

Build a complete indoor asset tracking IoT solution using the Blues Wireless Notecard, an ESP32 host MCU, the Notecarrier-F, and Datacake.

In the IoT, when someone says "asset tracking", you likely think of monitoring the state and location of a package, container, or vehicle. Usually this involves one or more environmental sensors to track temperature, humidity, or atmospheric pressure. It may also include an accelerometer to track motion and sudden movements.

Of course, asset tracking also involves monitoring location in a physical space. This is typically performed with GNSS/GPS, which is far and away the most consistent and reliable means of ascertaining a physical location outdoors.

However, what if the device enclosure prevents you from acquiring GPS location due to a physical barrier? What if trying to get a GPS satellite fix consumes too much power? Or (and here's the real kicker) what if your goal is to track an asset indoors?

Well have I got a solution for you today! At least a proof-of-concept solution 😅.

By using our old friend triangulation from trigonometry and geometry, we can build a fully-functional indoor asset tracking solution built upon on the Blues Wireless Notecard.

We can also tap into a commonly used sensor to measure altitude, giving us the ability to ascertain the building floor and provide "3D" asset tracking.

Ready to dive in? Let's start with the high level requirements of this indoor tracking solution.

GPS should always be the first choice when attempting to ascertain physical location. But it's good to have a backup in case getting a GPS satellite fix fails (which can often be the case inside a building).

You may already know that triangulation is the process of determining a location by forming overlapping diagrams on a common point of interest, from a series of other known points.

In this project, the Notecard is going to allow us to use both GPS and triangulation to accurately ascertain a device's position.

Tracking an asset on a 2D map is so last year 😊.

We can use data from a BME280 sensor to calculate a reasonably accurate altitude. What you may not know is, those altitude readings are commonly based on a standard sea level pressure measure of 1013.25 hPa.

Wouldn't it be cooler to actively query the sea level pressure for a known location before asking the sensor to calculate the altitude? This would provide a more accurate reading, letting us roughly calculate the floor of the building we are on.

We need a means of syncing our gathered location and altitude data to the cloud. And yeah, I already gave away our secret component: the Blues Wireless Notecard.

The Notecard is a prepaid cellular system-on-module, especially useful for low bandwidth cellular IoT communications. It comes preloaded with 500MB of data and 10 years of global cellular service, starting at $49 USD.

Even though the Notecard is a cellular device, you don't have to program the modem with archaic AT commands. The Notecard API is all JSON, all the time. For instance, say you wanted to query the last known location on the Notecard, you'd use the card.location API:

Even more importantly, security and cloud integration is turnkey. The Notecard communicates "off the public Internet" through private VPN tunnels, using the Blues Wireless cloud service Notehub.

Notehub is also our secret sauce when it comes to providing location data via triangulation. As we'll see later on, when we supply known Wi-Fi access point data to Notehub and enable the card.triangulate API, Notehub can actually look up shockingly accurate location data.

Any IoT solution that is battery-powered has to be power-conscious. Thankfully the Notecard is low power by default (to the tune of ~8uA when idle) and includes an on-board accelerometer, which allows us to calculate an asset's location only when it has detected motion!

With all of these requirements in mind, let's assemble our hardware.

The Cellular Notecard is the core of our solution, providing onboard GPS, an accelerometer for motion detection, and cellular connectivity to relay collected data to the cloud.

Since I'm not willing to give up on GPS (even for an indoor deployment) I'm going to use a small active GPS antenna alongside an LTE antenna for cellular data.

For gathering environmental data and calculating altitude, I'm including the venerable BME280 sensor from Bosch.

For a host microcontroller, I went with the ESP32-S2 Feather. I chose this MCU primarily because of its onboard Wi-Fi module and support for CircuitPython. Even though we can't use Wi-Fi for connectivity (since it's a moving system and won't be able to log in to the changing Wi-Fi APs), we will use it to gather public Wi-Fi access point data.

So how do we bring all the pieces together? That's what the new Blues Wireless Notecarrier-F is for!

Notecarriers are carrier boards that allow you to quickly prototype IoT solutions that use the Notecard. The Notecarrier-F is a great option for Feather-compatible MCUs and provides two Qwiic ports for adding peripherals (like the BME280) and JST connectors for connecting LiPo batteries.

And here is the final hardware setup, all connected and ready to be programmed:

I'm an unabashed Python fan, so CircuitPython was an easy choice for me.

Why CircuitPython? Valid question! In my humble opinion, CircuitPython has helped to open up the IoT to a new breed of developers who grew up with Python. Like its "parent" MicroPython (upon which CircuitPython is based), being able to use the uber-popular Python language to program these "things" and connect them to the world has broadened the reach and scope of IoT solutions.

So let's write some CircuitPython firmware!

The only external dependencies we have are the Notecard and BME280 sensor. Both have well-supported Python libraries that work great with CircuitPython: note-python and adafruit-circuitpython-bme280.

The final set of imports looks like this:

We need to initialize access to our peripherals. Both the Notecard and BME280 communicate over I2C, making our init steps quite simple:

In order to calculate an accurate altitude, we need to know the current sea level pressure at our given location. More on this later on, but we're going start by supplying the sensor with a standard sea level pressure measure of 1013.25 hPa.

Later on, when using a remote service to gather pressure data, we will need to use latitude/longitude coordinates. We can program in some defaults and later update them if/when GPS becomes available:

Next, we need to associate the Notecard with a cloud-based project on the Blues Wireless cloud service Notehub. This enables the Notecard to securely transmit data to a known location in the cloud:

We then want to enable the GPS module on the Notecard. Again, this is not strictly required, but it's certainly a best practice to at least try and gather GPS position if satellites are visible:

Finally, we enable motion tracking on the Notecard, which will let us ascertain the location of the device only if it has moved (as opposed to sampling at a timed interval, even if the device is stationary, unnecessarily consuming power).

We'll need a way to detect if the device has moved before attempting to ascertain its location. We can do so by using the card.motion API.

The count parameter in the response tells us how many motion events were registered since it was last checked:

There are a couple other location-based methods mentioned in here, get_gps_location and set_wifi_triangulation. Let's take a quick look at these.

What follows is a highly condensed version of the Python code used to ascertain a GPS location. The full version is available as part of the project's Github repository and, long story short, contains additional logic to override the low-power nature of the GPS module.

Again, since this is an indoor deployment, we will rarely get a valid GPS location. So let's look at using Wi-Fi triangulation instead!

Did you know that our smartphones are constantly gathering data about available Wi-Fi access points, combining that data with lat/lon coordinates, and shipping the data to Apple and Google? Welcome to yet another questionable privacy practice by big tech!

On the bright side, it also allows us to utilize a capability of Notehub to gather positioning data from nearby Wi-Fi access points.

By providing a list of Wi-Fi access points to the card.triangulate API, we can tell Notehub to calculate positioning data for us (often with shockingly accurate results).

Again, since we're using an ESP32-based MCU, we can use the built-in wifi CircuitPython library to create a list of visible Wi-Fi access points. The helper function, get_wifi_access_points, is available in the Github repository as well.

In order to calculate the most accurate altitude possible, we need to know our current location's atmospheric pressure at sea level. The only way to reliably do so is to call a remote weather service to access this data on-demand.

This is where the OpenWeather API combined with the Web APIs from the Notecard come in handy. OpenWeather provides a developer-friendly way of accessing a variety of weather-related data.

The Notecard's Web APIs allow the Notecard to send/receive data to/from remote RESTful APIs. The method below is abridged for space:

Notice the GetWeather string called in this method? This is the name of a Notehub route which is configured to query a remote service (OpenWeather) and return current weather data for the specified lat/lon coordinates. This particular route looks like this in the Notehub UI:

Once we have the updated sea level pressure, we can update the BME280 sensor with that value and finally send environmental sensing data to Notehub for syncing with a to-be-created Datacake dashboard:

Take Note (yes, pun intended) of the final request in this method, note.add. A "Note" is simply a JSON object that includes arbitrary data you want to send to the cloud.

In this case, we are sending the following data elements in the body of our Note:

With the firmware written and deployed to the microcontroller, we can check Notehub to make sure valid data is being collected and synced:

But this data is only somewhat useful being visible in Notehub. What we really need to do is route this data to a cloud dashboard to make it digestible (and pretty!).

To do so, I built a fully functional dashboard with Datacake:

Let's zoom in on the map widget though, because I made the ultimate sacrifice by testing this project indoors...at the mall:

After spending about 20 minutes walking from end to end of this indoor shopping monstrosity (admittedly some of the big department starts at the corners were closed unfortunately) I was able to gather Wi-Fi triangulation data to ascertain a shockingly accurate set location points:

Now I made a big deal about using altitude data earlier. While we can't provide a true "3D" visualization of our location on Datacake (or frankly any cloud dashboard that I'm aware of, yet), we can correlate location data on the map with altitude data provided from the BME280 sensor. Setting a "baseline altitude" of floor one (or zero for you folks outside the States) we can roughly track the floor we are on as well based on the relative altitude measured:

Let me be crystal clear: you should always at least attempt to use GPS when ascertaining device location. It's going to be the most accurate option and, when using the right combination of hardware and firmware, uses a minimal amount of power in a battery-powered device.

However, if needed, it's great to have an option like the Blues Wireless Notecard with Notehub and its triangulation capabilities.

Curious to learn more? Pick up the Blues Wireless ESP32 starter kit today!