Reputation: 51
I have an NMEA test data file that contains a few gps points:
$GPGGA,170358.132,5230.704,N,01324.262,E,1,12,1.0,0.0,M,0.0,M,,*63
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,170358.132,A,5230.704,N,01324.262,E,4152.6,050.1,150822,000.0,W*4B
$GPGGA,170359.132,5231.634,N,01325.380,E,1,12,1.0,0.0,M,0.0,M,,*6D
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,170359.132,A,5231.634,N,01325.380,E,2369.6,047.3,150822,000.0,W*4D
$GPGGA,170400.132,5232.183,N,01325.977,E,1,12,1.0,0.0,M,0.0,M,,*6C
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,170400.132,A,5232.183,N,01325.977,E,1313.3,288.5,150822,000.0,W*40
I am trying to feed these to gpsfake to test it with a gpsd demo script I have. I have tried running gpsfake alone, piping it with gpsd, and gpsd alone, but no luck. Mind you, this is the first time I use gpsd.
I have tried running gpsd using my script and a physical GPS dongle, it runs perfectly fine and I get the following output per my code:
~$ /usr/sbin/gpsd -n -G -b /dev/ttyUSB0 &
[1] 4514
~$ ./demo
WARNING: Opening interface localhost:gpsd
WARNING: Entering GPS poll loop (2000000us)
Speed: 0.017
Speed: 0.018
Speed: 0.018
Speed: 0.021
speed: 0.046976
{
"timestamp": 1660331437857,
"latitude": 33.6973963,
"longitude": -117.7707148,
"eph": 4.563,
"speed": 0.047,
"eps": 0.460,
"track": 0.000,
"satellites_used": 8,
"hdop": 0.000000,
"vdop": 0.000000
}
Speed: 0.021
[1]+ Done /usr/sbin/gpsd -n -G -b /dev/ttyUSB0
Can someone please tell me how I can feed the fake data to gpsfake instead of using the GPS dongle? Thanks!
Upvotes: 3
Views: 1711
Reputation: 2607
Today was the first time I've used gpsfake
to spoof GPS data. It's rather straightforward. I'm running Kali Linux so this response should be valid for Debian distros, though it will likely work elsewhere.
Here is the command syntax I used:
sudo systemctl stop gpsd
sudo systemctl stop gpsd.socket
sudo gpsfake -l --cycle 0.142857 --slow /home/user/gps/gps_sample.nmea
A couple notes:
gpsfake
uses port 2947 by default; this is the same default port as gpsd
gpsd
before running gpsfake
gpsd.socket
binds to port 2947 and does not shut down concurrently with gpsd
so it also must be stopped for the port to be free.gpsfake
is essentially a full replacement for gpsd
gpsd
, the switch to gpsfake
was transparent
gpsd
and gpsfake
gpsfake
is working with cgps
or gpspipe -r
That should be it!
I packaged it all in to a handy little python script that can be used to automatically switch between gpsd
and gpsfake
. The script restores gpsd
functionality while it stops. Be sure to run the script as sudo
since it starts and stops services:
import subprocess
import time
def log_journal(message):
#Logs to journalctl for better debugging
subprocess.run(['logger', message])
print(message)
def check_and_stop_service(service_name):
#Checks the status of a service before stopping it
status = subprocess.run(['sudo', 'systemctl', 'is-active', '--quiet', service_name])
if status.returncode == 0: # Service is running
log_journal(f'Stopping {service_name}...')
subprocess.run(['sudo', 'systemctl', 'stop', service_name])
return True
return False
def start_service(service_name):
#Starts the specified service name
log_journal(f'Starting {service_name}...')
subprocess.run(['sudo', 'systemctl', 'start', service_name])
def run_gpsfake():
log_journal('Starting gpsfake...')
return subprocess.Popen(
['sudo', 'gpsfake', '-l', '--cycle', '0.142857', '--slow', '/home/user/gps/gps_sample.nmea'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
def prompt_exit():
input("Press Enter to stop gpsfake and restart gpsd...")
def terminate_process(proc):
if proc:
log_journal('Terminating gpsfake process...')
proc.terminate()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.kill()
def main():
gpsfake_proc = None
try:
# Step 1: Check and stop gpsd services
gpsd_running = check_and_stop_service('gpsd')
gpsd_socket_running = check_and_stop_service('gpsd.socket')
# Step 2: Execute gpsfake
gpsfake_proc = run_gpsfake()
time.sleep(5) # Allow some time for gpsfake to start
# Wait for user input to terminate gpsfake and restart gpsd services
prompt_exit()
finally:
# Step 3: Cleanup
terminate_process(gpsfake_proc)
start_service('gpsd')
if __name__ == "__main__":
main()
Also, I used nmeagen to create a simple nmea file, however you can just capture gpspipe
output while using a gps receiver for more realistic simulations.
Upvotes: 2