Skip to main content

A Python interface to older Garmin GPS equipment

Project description

PyGarmin

PyGarmin

The Pygarmin distribution provides a Python module and a command line application that implement the protocol used by Garmin GPS devices. It is based on the official protocol specification.

Documentation

For API documentation, usage and examples see the files in the docs directory. The documentation is also hosted on Read the Docs.

Installing

You can install Pygarmin with pip as follows:

$ pip install pygarmin

Or to upgrade to the most recent version:

$ pip install pygarmin --upgrade

To follow or contribute to pygarmin development, you can browse or clone the Git repository on Github:

$ git clone https://github.com/quentinsf/pygarmin.git

And install the requirements using the below command:

$ pip install -r requirements.txt

Pygarmin application

Description

Pygarmin is a command line application that can retrieve data from and transfer data to a Garmin GPS device connected by a serial or USB port.

The port is specified with the -p PORT option. To communicate with a Garmin GPS serially, use the name of that serial port such as /dev/ttyUSB0, /dev/cu.serial, or COM1. To communicate via USB use usb: as the port on all OSes. For this to work on GNU/Linux, you probably should remove and blacklist the garmin_gps kernel module. Some protocols won’t work at all with a serial connection, like the transfer of images and maps. So your best bet is to use the internal USB support.

The functionality is split into a number of sub-commands, like pygarmin info to return a product description, pygarmin get-waypoints to download the waypoints, and pygarmin put-map to upload a new map.

Examples

Show help message:

pygarmin --help

Show help on the get-almanac command:

pygarmin get-almanac -h

Show product description with debugging enabled:

pygarmin --debug info

Show information on the currently installed maps, use the serial port and be very verbose:

pygarmin -p /dev/ttyUSB0 -vv map

Download all waypoints in gpx format to the file waypoints.gpx:

pygarmin get-waypoints waypoints.gpx -t gpx

Upload all waypoints in the file waypoints.gpx:

pygarmin put-waypoints waypoints.gpx -t gpx

Download all activities in FIT format to the files activity001.fit to activityNNN.fit in the current directory:

pygarmin get-activities -t fit activity%03d.fit

Print real-time position, velocity, and time (PVT) to stdout:

pygarmin pvt -t tpv

List the images types:

pygarmin get-image-types

List all images:

pygarmin get-image-list

Download all images and save them according to the given filename pattern:

pygarmin get-image ~/icons/waypoint%03d.png

Download the images with index 1, 2, and 3 and save them as PNG files with the default filenames to the current directory:

pygarmin get-image -t png -i 1 2 3

Upload an image as a custom waypoint symbol with index 1, and don’t show the progress bar:

pygarmin --no-progress put-image Waypoint\ Symbol\ 000.bmp -i 1

Download the currently installed map from the device and save it as “gmapsupp.img” to the current directory:

pygarmin get-map

Upload the map “gmapsupp.img”:

pygarmin put-map gmapsupp.img

Garmin module

The garmin module is a set of Python classes which implement the protocol used by Garmin GPS receivers to talk to each other and to other machines. It is based on the official protocol specification. The project was started by Quentin Stafford-Fraser but several others have helped to make it what it is today.

PyGarmin has been used to transfer information to and from several different Garmin receivers, mostly under Linux, though there is some Windows support now and people have used it on Mac OS X as well. If you use PyGarmin, it will probably be much quicker than writing your own software from scratch.

Basics

Almost every model of Garmin receiver implements a slightly different protocol. They have many things in common, but there are minor differences. The class Garmin will create instances of the appropriate protocol classes and notes the datatype classes for each type of data used in the transmissions. It also has some friendly methods like get_waypoints(), which do what you would expect. What you get back when you call this is a list of objects, each of which is a child the Wpt class.

Example Code

Here’s a simple Python program:

#!/usr/bin/env python3
import logging
from garmin import garmin, link, logger

logger.log.addHandler(logging.StreamHandler())
logger.log.setLevel(logging.INFO)

# Create a 'physical layer' connection using serial port
phys = link.SerialLink('/dev/ttyUSB0')

# ...or using USB
phys = link.USBLink()

# Create a Garmin object using this connection
gps = garmin.Garmin(phys)

# Get the waypoints from the GPS
waypoints = gps.get_waypoints()

# Get the tracks from the GPS
tracks = gps.get_tracks()

# Print the waypoints
print("Waypoints:")
for waypoint in waypoints:
    posn = waypoint.get_posn()
    degrees = posn.as_degrees()
    lat = degrees.lat
    lon = degrees.lon
    print(waypoint.ident, lat, lon, waypoint.cmnt)

# Print the tracks
print("Tracks:")
for track in tracks:
    print(track)

# Put a new waypoint
print("Upload a new waypoint:")
waypoints = [{'ident': b'CHURCH',
              'cmnt': b'LA SAGRADA FAMILIA',
              'posn': [493961671, 25937164]}]
gps.put_waypoints(waypoints)

This should work for most models, because all waypoints will have an identity, a position (latitude and longitude), and a comment field. The latitude and longitude are transferred as ‘semicircle’ coordinates (basically degrees, but scaled to fill a signed long integer). The static method Position.to_degrees() converts a semicircle integer into a degree float and the as_degrees() method converts a Position into a DegreePosition data type.

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.

In the past, it has been released under the GNU General Public License version 2, and some contributions have been made under that license. You may use it under the terms of the GPLv2 if you prefer.

Acknowledgements

Thanks are due to, amongst others:

and probably others, to whom our apologies!

The logo was designed by Quentin Stafford-Fraser

Changelog

[1.2.0] 2024-03-17

  • Fix datetimes that were off by 12 hours

  • Localize datetimes

  • Fix name clashes of classes

  • Fix A201 route transfer protocol

  • Fix D104 waypoint datatype

  • Fix D304 track point datatype

  • Better layout of submodules

  • Support export to and import from JSON

  • Support import from GPX (export to GPX was already supported)

  • Add creator attribute to exported GPX

  • Support export to FIT

  • Use the same version for the module and the application

  • Various bugfixes

[1.1.2] 2023-12-27

  • Fix GPX export of Garmin Forerunner 305 tracks

[1.1.1] 2023-12-26

  • Use the same license (GPLv2 or later) for the package as the source

[1.1.0] 2023-12-26

  • Support Garmin Forerunner 305

  • Support images of different color depths

  • Various bugfixes

[1.0.5] 2023-11-22

  • Fix relative package import (PR #7)

[1.0.4] 2022-12-23

  • Improve documentation

  • Add usage of pygarmin application to project description

[1.0.3] 2022-12-23

  • Fix project description

[1.0.2] 2022-12-22

  • Host documentation on Read the Docs

[1.0.1] 2022-12-21

  • Made the pygarmin script a submodule

  • Improved docstrings

  • Switched from Markdown to ReStructuredText

  • Added documentation using Sphinx

[1.0]

  • Improved coding style to conform to the PEP8 style guide

  • Improved logging

  • Improved docstrings

  • Used a factory method to create objects

  • Used the new PyUSB 1.0 API

  • Used f-strings instead of %-formatting

  • Used the rawutil module instead of a customized struct

  • Implemented unit ID request

  • Added support for baudrate change

  • Added support for proximity waypoints transfer

  • Added support for waypoint category transfer

  • Added support for position initialization

  • Added support for maps

  • Added support for image transfer (screenshots and waypoint symbols)

  • Added support for screenshots

  • Removed test code (because I believe this belongs outside the main module)

  • Rewritten pygarmin to a fairly complete command-line program

[0.8]

  • Used pyserial for serial communication

  • Added debian package support

  • Added support for flightbook

  • Added support for laps

  • Added support for runs

  • Added support for USB devices

  • Migrated to python3

[0.7]

  • Fixed various bugs

  • Brought up to date with CVS (the tarball had become very dated)

  • Patches for recent pythons on Win32

  • JAHS’s mods - callback, debug etc

  • See CVS logs for more details

[0.6]

  • Fixed various bugs

  • Tidier SerialLink code

  • Runs under Python 1.5.2

  • More debugging available if wanted

[0.5]

  • Added a datum-conversion module.

  • Added Raymond Penners’ Win32SerialLink stuff and timeout stuff

  • A900 support

  • A800 support (for real-time data)

  • Waypoints now have repr, str and getDict methods

  • The ‘pygarmin’ app has some facilities to output XML, using the new xmlwriter module

[0.4]

  • Various bug fixes and minor changes. See CVS logs for details

[0.3]

  • Some changes to newstruct to fix bugs and make it work with Python 1.5.1

  • Added TrackHdr class to fix protocol D310

[0.2]

  • Incorporated James Skillen’s improvements to support protocol A001 for newer Garmin units

  • Updated the tables based on new spec

[0.1]

  • Initial release

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pygarmin-1.2.0.tar.gz (96.4 kB view hashes)

Uploaded Source

Built Distribution

pygarmin-1.2.0-py3-none-any.whl (94.0 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page