Say you're building a residential air quality monitor (hey, like Blues Airnote). Your customers are likely to mount it on a porch railing or a fence post, it'll report AQI readings every hour, and your cloud app will plot every device on a public map so neighbors can watch wildfire smoke roll through town.
That public map needs each device's location. However, it does not need that location to be accurate to someone's front door.
As an aside, this is what my Airnote dashboard looked like this summer as that aforementioned wildfire smoke hit us:

The trouble is that a GPS/GNSS receiver under open sky routinely resolves a position to within a few meters. That's easily enough to pick out a single house. The same problem shows up across many different types of connected products: a vehicle's GPS coordinates can identify its driver, a wearable's coordinates can reveal where someone sleeps, and an unattended sensor's exact location can tell a vandal where to find it.
A common fix is to strip a few decimal places in the cloud before displaying anything. That certainly helps privacy on any public map, but the precise coordinates have still crossed the network, landed in your event store, and flowed into every log, backup, and downstream integration that touches the data.
All is not lost though, as
Blues Notecard can perform this
"fuzzing" of location coordinates on the device instead, with a single
environment variable:
_gps_fuzz_degrees.
What "Location" Means to Notecard and Notehub
Before configuring anything, it's worth knowing where a Notecard-based device's location actually comes from, because there are three possible sources:
- GPS/GNSS. Notecard models with a GNSS receiver (i.e. any Notecard with a
cellular modem) compute a fix on the device, as does a Notecard with an
external GPS module
connected to its AUX pins. The fix shows up in
card.locationresponses, in_track.qoNotes, and in thewhere_*fields Notehub appends to every event. - Cell tower location. Notecard reports the ID of the tower it's connected
to, and Notehub looks up that tower's position (the
tower_*fields). - Triangulation. If you enable it with
card.triangulate, Notecard uploads nearby WiFi access point and cell tower scan data, and Notehub resolves an estimated location (thetri_*fields).
Notehub then picks the best available option and exposes it as the best_*
fields (the full list is in
Data Notehub Appends to Events).
Notice the difference in those three options. The first source is computed on
the device, while the other two are computed in Notehub from data the device
sends. A useful privacy control has to cover both places, and
_gps_fuzz_degrees does just that. Notecard applies it to GPS/GNSS coordinates
before they leave the device, and Notehub applies the same fuzzing calculation
to the tower and triangulated locations it computes.
There are two potential gaps to keep in mind for your product design:
-
Fuzzing only covers the location Notecard itself determines. It's unlikely, but if your host MCU supplies its own coordinates (say, from a separate GPS module), Notecard stores them exactly as given, whether they're in a Note body or attached to the Note as location metadata.
-
Notecard still sends Notehub the network data it uses for location. The ID of the cell tower it's connected to goes up with each session (and routed events carry it as
tower_id), and with triangulation enabled, Notecard firmware through v11.3.2 also uploads raw WiFi access point and cell tower scans. For the strictest designs, set the_suppress_towerand_suppress_trienvironment variables.
How Grid Snapping Works
The value you specify for _gps_fuzz_degrees is a grid size in decimal degrees.
Every coordinate Notecard reports is "snapped" to a multiple of that value by
dropping the extra precision. For example, with a value of 0.001, device
coordinates would appear like so:
| Real coordinate | Reported coordinate |
|---|---|
42.5779 | 42.577 |
-70.8729 | -70.872 |
To be clear, that's truncation, not rounding, so values always move toward
zero. 42.5779 becomes 42.577 rather than 42.578, and -70.8729 becomes
-70.872 rather than -70.873. Notecard and Notehub use the same math, so a
device's GPS, tower, and triangulated locations all land on the same grid.
The grid is measured in degrees, and a degree of longitude shrinks as you move away from the equator, so the cells are rectangles rather than squares. Here's what that looks like at 45° latitude (e.g. Minneapolis, Bordeaux, or Turin):
_gps_fuzz_degrees | Cell size at 45° (N–S × E–W) | Roughly the scale of |
|---|---|---|
0.0001 | 11 m × 8 m | A single building |
0.001 | 111 m × 79 m | A city block |
0.01 | 1.1 km × 0.79 km | A neighborhood |
0.1 | 11 km × 7.9 km | A small town |
Now why would you want to use a fixed grid like this instead of random noise? The obvious alternative is adding a random offset to every fix. The problem is that a device that doesn't move keeps reporting, and averaging a few hundred noisy reports can lead you right back to the true position! A grid is deterministic, so there's nothing to average: every fix that lands in the same cell reports the same corner. The catch is a device sitting near a cell edge, where ordinary GPS jitter can flip it back and forth between two neighboring cells. That doesn't reveal the exact spot, but it does tell an observer the device is close to that line.
Enabling Location Fuzzing
Step 1: Pick a Grid Size
Ask yourself this question: "what's the smallest area my product actually needs to know about?"
For instance, a regional air quality map should work fine at 0.01. Something
like sales territory or regulatory reporting might only need 0.1. If you can't
say why you need a precise location, you probably don't need one!
Also consider where your devices will live. A 0.001 cell in a city might
contain dozens of homes, but the same cell in farm country might contain exactly
one, and a snapped coordinate that maps to one house is still a home address. If
your devices ship to rural customers, size the grid for them, not for your
downtown beta testers.
Step 2: Set It in Firmware
Set the value from your host firmware with the env.default API. This way fuzzing is in effect from the device's first boot, before it has ever synced with Notehub:
{
"req": "env.default",
"name": "_gps_fuzz_degrees",
"text": "0.01"
}Like every environment variable, the value is passed as a string in text.
Send the command during setup, before you configure card.location.mode or
add any Notes.
The ordering of these commands in firmware matters because fuzzing isn't retroactive. Notecard applies the grid at the moment it reads its location, and a Note captures its location when it's added. Anything queued before the setting took effect keeps whatever precision it had.
Step 3: Mirror Preferences in Notehub
You can also set _gps_fuzz_degrees as a
project or fleet environment variable
in Notehub, which is the easiest way to apply it to thousands of devices at
once. Fleets also let you vary the policy, for example fuzzing every customer
unit while leaving your own test devices at full precision.
If you rely on tower or triangulated locations, I'd set the same value in both places (on device and in Notehub). That way Notehub's side of the policy doesn't depend on when a device first reports its defaults.
In the
environment variable hierarchy,
device, fleet, and project variables in Notehub all take precedence over an
env.default value. Anyone who can edit those variables can loosen (or remove)
the fuzzing your firmware set. That's handy for fleet management, but it means
your privacy guarantee is ultimately enforced by Notehub access control, not by
the hardware.
Step 4: Check the Output
After a GPS fix is made, a
card.location
request will return lat/lon coordinates snapped to the 0.01 grid from Step 2:
{
"status": "GPS updated (58 sec, 41dB SNR, 9 sats) {gps-active} {gps}",
"mode": "periodic",
"lat": 42.57,
"lon": -70.87,
"time": 1598554399
}In Notehub, the where_* fields on every event are derived from that reported
point.
Some Location Data Stays Precise
It's important to note that Notecard's internal motion detection and geofence logic keep working from the real GPS fix. If those features ran on the fuzzed location, a device parked near a boundary could appear to "move" a full grid step every time its fix jittered across the line, and a 100-meter fence would be meaningless inside a 1-kilometer cell. Because Notecard evaluates its geofence against the precise fix, you can still send an alert from a device whose reported location is only accurate to the neighborhood.
Where to Fuzz Location: Device, Cloud, or App
Fuzzing on Notecard isn't the only way to reduce location precision, so it's worth comparing it to the alternatives:
| Approach | Precise location leaves the device? | Precision recoverable later? | Good fit for |
|---|---|---|---|
Suppress location (_suppress_*) | No | No | Products that don't need location |
Fuzz on Notecard (_gps_fuzz_degrees) | No (GPS/GNSS) | No | Coarse location, minimized at the source |
| Fuzz in a Notehub route or your app | Yes | Yes | Precise internally, coarse for customers or partners |
| Full precision | Yes | N/A | Asset tracking, where precision is the product |
Note that sometimes the right answer is no location at all! The
_suppress_where, _suppress_tower, and _suppress_tri environment variables
stop each category of location data from leaving Notecard entirely
(details here).
Cloud-side fuzzing, using a JSONata transform in a Notehub route or logic in your own app, is the right call when you genuinely need both views: precise for your own operations, coarse for a public map or a partner feed. Just be honest that the precise data then exists in Notehub and everywhere you route it, and your privacy story depends on securing all of it.
On-device fuzzing is the strongest option that still gives you a location. Precision you never collect can't leak, and "the device never sends it" is a lot easier to explain to a customer than a chain of access controls.
Summary
If your product needs to know roughly where it is, but your customers would be
uncomfortable with it knowing exactly where they are, _gps_fuzz_degrees is
the simplest privacy control you can add. It's one environment variable, it
covers GPS/GNSS on the device and tower and triangulated locations in Notehub,
and it leaves geofencing and motion detection intact.
For the full reference, read Location Privacy with GPS Fuzzing in the Notecard walkthrough, and browse the reserved environment variables for the other location controls mentioned here.
Happy hacking! 💙
Frequently Asked Questions
What is GPS fuzzing on Blues Notecard?
GPS fuzzing is a privacy feature controlled by the _gps_fuzz_degrees reserved
environment variable. Notecard snaps the GPS/GNSS location it determines to a
grid of the size you specify, in decimal degrees, before that location leaves
the device. Notehub applies the same grid to the cell tower and triangulated
locations it computes, so all of a device's reported locations share the same
reduced precision.
How do I enable location fuzzing on a Notecard?
Send an env.default request from your host firmware with name set to
_gps_fuzz_degrees and text set to the grid size as a string, such as
"0.01" for a cell roughly one kilometer across. You can also set the variable
at the project, fleet, or device level in Notehub. Setting it in firmware
ensures fuzzing is active from the device's first boot, before it has ever
synced with Notehub.
Does GPS fuzzing break geofencing or motion tracking?
No. Fuzzing is applied when location data leaves Notecard. Notecard's internal geofence and motion detection logic continue to use the precise GPS fix, so a geofence stays accurate even when the reported coordinates are fuzzed.
Where is the real location relative to a fuzzed coordinate?
Notecard and Notehub truncate toward zero rather than rounding, so the reported coordinate is a corner of the grid cell, not its center. The real location lies between the reported value and one grid step farther from zero on each axis. For a device in North America (positive latitude, negative longitude), that means it is somewhere north and west of the reported point.
Can I recover a device's precise location after enabling fuzzing?
Not for data that was already reported. For the location Notecard determines
itself, the extra precision is discarded on the device and never transmitted.
You can turn fuzzing off for a single device going
forward by setting a device-level _gps_fuzz_degrees variable to 0 in
Notehub, which takes precedence over fleet, project, and env.default values.

