Testing location-based IoT applications typically means walking around outside carrying messy prototypes, driving test routes, or trying to get a GPS/GNSS satellite lock from out of a window. This approach of physical testing slows development and limits your ability to reliably and reproducibly test your application.
If you're building a Notecard application,
you can use Notecard's AUX serial pins to simulate a GPS/GNSS module connected to the
AUXRX
and AUXTX
pins.
Instead of relying on physical satellites, you can feed simulated GPS data directly to
your Notecard from command-line tools, giving you precise control over location,
timing, and signal quality—all from your desk.
In this post, we'll use a CLI GPS simulator
to generate realistic NMEA0183 data and connect it to a Notecard through its AUXRX
and AUXTX
pins.
You'll learn to create controlled testing scenarios for everything from stationary
tracking to complex route simulation, dramatically speeding up your development cycle.
NMEA0183 Protocol Basics
Before we get started, let's review the basics of the NMEA0183 (National Marine Electronics Association) protocol, which is the standard communication protocol for most GPS receivers.
It transmits location data as human-readable ASCII sentences at regular intervals, typically once per second. This is typically sent over a serial port at a baud rate of 9600.
Sentence Structure
Each NMEA sentence take the following format:
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
Breaking this down:
$GP
- Talker identifier (GP = GPS)GGA
- Sentence type (Global Positioning System Fix Data)- Data fields separated by commas (e.g. timestamp, latitude, longitude, etc.)
*47
- Checksum for error detection (calculated by the sender)
Important Sentence Types
For location tracking, we're primarily interested in these sentences:
$GPGGA (Global Positioning System Fix Data)
- Timestamp (UTC time in HHMMSS format)
- Latitude/longitude coordinates
- Fix quality indicator (0=invalid, 1=GPS fix, 2=differential GPS fix)
- Number of satellites in use
- Horizontal dilution of precision (HDOP)
- Altitude above sea level
$GPRMC (Recommended Minimum Course)
- Timestamp (UTC time)
- Navigation status (A=valid, V=invalid)
- Latitude/longitude coordinates
- Speed over ground (in knots)
- Course/heading (true bearing)
- Date stamp
- Magnetic variation
$GPGSA (GPS DOP and Active Satellites)
- Mode (Manual/Automatic, 2D/3D)
- Fix type (1=no fix, 2=2D, 3=3D)
- Satellite IDs being used in position fix (up to 12 satellites)
- Position dilution of precision (PDOP)
- Horizontal dilution of precision (HDOP)
- Vertical dilution of precision (VDOP)
Don't worry about needing to understand these in detail, Notecard will handle the parsing for you.
Timing and Data Flow
GPS receivers typically output a complete set of NMEA sentences every second at a typical baud rate of 9600. A typical sequence might look like:
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39
This standardized format makes NMEA data ideal for simulation. A Notecard expecting real GPS data will accept properly formatted NMEA sentences from any source, including a CLI simulator.
Connecting an External GPS Module to Notecard
In order to use an external GPS/GNSS module with Notecard, you need to connect the
module's RX
and TX
pins to Notecard's AUXTX
and AUXRX
pins.
The Notecard will then use the module's GPS data to determine the location of the device.
With an External GPS/GNSS Module
TJ wrote a great blog post on how to both set up and configure an external GPS module with Notecard. Check out his post for the details.
With the CLI GPS Simulator
Configuring the CLI GPS simulator to very similar to the real external GPS module,
except we'll use a USB to Serial adapter
to connect to a computer.
My preference is to use the Waveshare USB to Serial Adapter, as it gives you the option to switch between 3.3V and 5V operation.
You can use any Notecard with any Notecarrier that breaks out the AUXRX
and AUXTX
pins.
For development purposes, we recommend using the Blues Notecarrier F.
You'll need to connect the following pins:
Notecard | USB to Serial Adapter |
---|---|
V+ | VCC |
GND | GND |
AUXRX | TX |
AUXTX | RX |
AUXEN | Not Connected |
Unlike a real GPS module, the simulator doesn't require an EN
pin, so we'll leave it disconnected.
You should ensure that the voltage level of the USB to Serial Adapter is set to 3.3V.
Installing the Simulator
A number of libraries exist for generating NMEA data, but I didn't find many that were easy to use and allowed you to stream the data to directly to a serial port. With the help of Claude Code, I decided to write my own CLI GPS simulator in Golang, which I've called go-gps-simulator.
You can either build the binary from source (requires Go 1.23
or later):
git clone https://github.com/Bucknalla/go-gps-simulator.git
cd go-gps-simulator
go build .
Or install it conveniently via Homebrew.
brew tap Bucknalla/tools
brew install go-gps-simulator
Once installed, check the simulator is working with the following command:
gps-simulator -version
We'll then need to put Notecard into GPS mode by issuing the following request:
{
"req": "card.aux.serial",
"mode": "gps"
}
You can send requests to Notecard directly, either using the Web REPL or the notecard-cli.
Configuring the Simulator
The CLI GPS simulator has a number of options for generating NMEA data. You can check the help menu with the following command:
gps-simulator -help
To see the stream of NMEA data, you can run the command without any arguments:
gps-simulator
This will start the simulator and output the NMEA data directly to your terminal. You can also pipe the output to a file for later analysis.
Starting GPS simulator...
Initial position: 37.774900, -122.419400, 45.0m
Wandering radius: 100.0 meters
GPS jitter: 0.0 (0% jitter)
Altitude jitter: 0.0 (0% variation)
Speed: 0.0 knots
Course: 0.0 degrees
Satellites: 8
Time to lock: 2s
Output rate: 1s
NMEA output: stdout
Press Ctrl+C to stop
$GPGGA,125159,,,,,0,00,,,,,,,,,*6D
$GPRMC,125159,V,,,,,,,,120925,,,N*79
$GPGLL,,,,,125159.53,V,N*47
$GPVTG,,,,,,,,,N*30
GPS LOCKED after 2.000439958s
$GPGGA,125200,3746.4940,N,12225.1640,W,1,08,1.2,45.0,M,0.0,M,,*54
$GPRMC,125200,A,3746.4940,N,12225.1640,W,0.0,0.0,120925,,,A*61
$GPGLL,3746.4940,N,12225.1640,W,125200.53,A,A*73
$GPVTG,0.0,T,,M,0.0,N,0.0,K,A*0D
$GPGSA,A,3,01,02,03,04,05,06,07,08,,,,,2.1,1.2,1.8*33
$GPGSV,2,1,08,01,57,093,23,02,08,306,22,03,36,090,26,04,44,013,45*79
$GPGSV,2,2,08,05,79,309,42,06,36,143,41,07,14,304,40,08,53,152,27*7A
$GPZDA,125200.53,12,09,2025,00,00*6B
The simulator will display non-NMEA information about the on-going simulation, such as when a GPS lock is acquired and the duration it took to lock. Such as:
GPS LOCKED after 2.000439958s
Notecard should ignore this information and only process the NMEA data.
However, if you wish to suppress this information, you can use the -quiet
flag.
Simulator Options
The gps-simulator
tool provides comprehensive options for generating realistic
NMEA data streams. Here's a detailed breakdown of all available configuration options:
Location & Movement Configuration
Setting the starting position and movement simulation is straightforward.
Starting Position:
-lat float
: Initial latitude in decimal degrees (default:37.7749
)-lon float
: Initial longitude in decimal degrees (default:-122.4194
)-altitude float
: Starting altitude in meters (default:45m
)
From there you can configure the simulation speed and course.
Movement Simulation:
-speed float
: Static speed inknots
for consistent movement (default:0.0
)-course float
: Static course/direction in degrees (0
-359
)
Speed is given in knots
, which is a unit of speed equal to one nautical mile per hour,
typically used in aviation and marine navigation.
Jitter & Signal Quality
The simulator can also be configured to simulate real-world GPS conditions, such as
position accuracy, satellite count, and signal quality.
Real world conditions typically experience varying levels of accuracy and signal
quality, which is why we've included the -jitter
and -lock-time
options.
Position Accuracy:
-jitter float
: GPS position jitter factor (0.0
=perfectly stable,1.0
=high variation)-radius float
: Wandering radius in meters around starting position (default:100m
)-altitude-jitter float
: Separate altitude variation control for realistic elevation changes (default:0.0
)-lock-time duration
: Simulates GPS acquisition time before stable readings (default:2s
)
You may also wish to simulate the number of satellites that are available to the GPS receiver.
Satellite Configuration:
-satellites int
: Number of satellites to simulate (4
-12
, default:8
)
Satellite Configuration
won't actually affect the accuracy or jitter of the simulator,
it's just a way to simulate the number of satellites that are available to the GPS receiver.
For example, your Notecard host application might use this to determine if the GPS
quality is good enough to use for location updates, by reading the HDOP value from the NMEA sentences.
Output Configuration
We'll need configure the output of the simulator, such as the data rate and runtime duration, as well as the serial port to use.
Data Rate & Timing:
-rate duration
: NMEA sentence output frequency (default:1s
)-duration duration
: Total simulation runtime (e.g.,30s
,5m
,1h
; default: indefinite)
Serial Port:
-serial string
: Direct output to serial port (e.g.,/dev/ttyUSB0
,COM1
)-baud int
: Serial port baud rate (default:9600
)
Logging:
-gpx
: Generate timestamped GPX track file-quiet
: Suppress info messages, output only NMEA data
Advanced Features
The simulator also supports some advanced features, such as replaying existing GPX track files. This can be useful for testing your application with a consistent route, or for debugging issues with your application. For example, if you are building a delivery tracking application, you can replay a GPX track file of a delivery route to evaluate your application (e.g. leaving a geofence).
GPX Replay Mode:
-replay string
: Replay existing GPX track file instead of simulating-replay-speed float
: Control replay speed (1.0=real-time, 2.0=double speed, 0.5=half speed)
Utility Options:
-version
: Display version information
Basic Usage Examples
The following examples are a good starting point for testing your application with the simulator.
All of the following examples assume that the default serial port is /dev/ttyUSB0
.
You should change this by using the -serial
flag.
Static Location Testing
Set the simulator to a fixed location:
# Load the default settings
gps-simulator -serial /dev/ttyUSB0
# Custom location (London, UK)
gps-simulator -lat 51.509865 -lon -0.118092 -serial /dev/ttyUSB0
Movement Simulation
Create realistic movement patterns:
# Wandering within 500m radius at 5 knots
gps-simulator -lat 51.509865 -lon -0.118092 -radius 500 -speed 5 -serial /dev/ttyUSB0
# Straight line movement at specific course
gps-simulator -course 45 -speed 10 -serial /dev/ttyUSB0
Signal Quality Testing
Use the simulator to vary the GPS signal quality:
# High jitter simulation (poor GPS conditions)
gps-simulator -jitter 0.8 -satellites 4 -serial /dev/ttyUSB0
# Delayed GPS lock simulation
gps-simulator -lock-time 30s -serial /dev/ttyUSB0
Route Replay
Use recorded GPS tracks for consistent testing, using a .gpx
file:
# Replay at normal speed
gps-simulator -replay myroute.gpx -serial /dev/ttyUSB0
# Replay at double speed for faster testing
gps-simulator -replay myroute.gpx -replay-speed 2.0 -serial /dev/ttyUSB0
To understand more about the GPX format, check out the GPX Wikipedia page.
Notecard Scenarios
Once you're happy that the simulator is working as expected, you can start testing with Notecard.
Static Location
First, start the simulator with a static location:
gps-simulator -lat 37.7749 -lon -122.4194 -duration 2m -serial /dev/ttyUSB0
Then checking that the Notecard is receiving the location data:
{
"req": "card.location"
}
Movement
Next, let's try the simulator with a movement pattern:
gps-simulator -radius 200 -speed 3 -rate 1s -serial /dev/ttyUSB0
Again, checking that the Notecard is receiving data:
{
"req": "card.location"
}
Run this request multiple times to see the expected movement.
Geofence Breach
We can also test Notecard's geofencing functionality by first configuring Notecard:
{
"req": "card.location.mode",
"mode": "continuous",
"lat": 42.5776,
"lon": -70.87134,
"max": 100, // 100 meter geofence
"minutes": 1 // 1 minute outside the geofence period
}
The important values here are:
mode
:continuous
to enable continuous location updateslat
: The latitude of the center of the geofencelon
: The longitude of the center of the geofencemax
: The radius of the geofence in metersminutes
: The number of minutes outside the geofence period before the location is tracked
Then start the simulator from the center of the geofence with a speed of 10 knots heading towards the edge of the geofence:
gps-simulator -lat 42.5776 -lon -70.87134 -radius 200 -speed 10 -rate 1s -serial /dev/ttyUSB0
Once the simulator breaches the geofence, you should see the Notecard's location update in Notehub along with any Notes that were pending synchronization.
Tracking Mode
Notecard's tracking mode functionality can also be evaluated with the simulator by starting tracking mode:
{
"req": "card.location.track",
"file": "delivery_route.qo",
"start": true,
"sync": true
}
Let's use the simulator's -replay
flag to replay a GPX track file of a delivery route (delivery_route.gpx
):
gps-simulator -replay delivery_route.gpx -serial /dev/ttyUSB0
Once the simulator completes the route, you should see the Notecard's tracking data in your Notehub project. Visit _track.qo to see how Notecard will store the tracking data. This can be combined with sensor data from a BME280 or ENS210 for a simple data logging solution.
Poor GNSS Signal Quality
Finally, let's use the simulator to vary the GPS signal quality:
gps-simulator -jitter 0.6 -satellites 3 -altitude-jitter 0.3 -serial /dev/ttyUSB0
Checking that the Notecard is receiving the tracking data:
{
"req": "card.location.track"
}
You should see a value for dop
in the response body, which is the dilution of precision for the reading.
Lower numbers indicate higher confidence.
Integration with Notehub
Notecard is just one part of the equation when it comes to building a location-based IoT application. Checking and verifying that the data is being received and processed as expected on Notehub is just as important.
Simulated GPS data will appear in Notehub exactly like real GPS data. On Notehub, you can:
- View Device Locations: See your simulated tracks on Notehub's device map
- Set Up Geofences: Test location-based events
- Monitor Data Flow: Verify location updates reach your cloud applications via Notehub routes
- See Device Tracks: View
_track.qo
Notes in Notehub to see where a Notecard has been - Debug Location Issues: Use consistent, repeatable GPS data for troubleshooting
Troubleshooting
If you encounter any issues with the simulator, please check the following:
Common Issues:
- No Serial Connection: Verify the correct serial port path and ensure the USB-to-Serial adapter is properly connected
- Baud Rate Mismatch: Ensure both the simulator (
-baud
) and Notecard are using the same baud rate (typically 9600) - No Location Updates: Remember that the Notecard must be in external GPS mode using
{"req": "card.aux.serial", "mode": "gps"}
- Inconsistent Data: Use lower jitter values (
-jitter 0.1
) for more stable testing or use the-replay
flag to exactly replay a GPX track file
If you're still having trouble, please create an issue on the GitHub Repository.
Conclusion
Instead of spending hours walking test routes or waiting for GPS locks, using a simulator can rapidly iterate through dozens of scenarios from your desk.
With this approach, you have complete control over location data, timing, and signal quality. It enables you to test edge cases like GPS dropouts, poor accuracy conditions, or rapid location changes that would be difficult to reproduce with real hardware. You don't need to wait for clear skies or travel to specific test locations. You can test scenarios that might be impossible or impractical in the real world, such as crossing international borders, extreme altitude changes, or rapid long-distance movements.
However, you'll eventually need to release your product into the real world...
But you'll now have the confidence that Notecard will work as expected. You can either swap out the simulator for a real GPS module, or rely on Notecard's internal GPS module. You'll need to consider which is the best approach for your application as there are some important differences between the two.
If you've found value from this blog post and/or GitHub Project, please consider letting us know by sharing your feature requests and/or bug reports.