#! /usr/bin/env python
"""
gps - Opens a defined device and echoes NMEA lines to stdout.

Can optionally filter for certain NMEA sentence types.
Just add the option(s) of the type(s) you want to see.

:Copyright: Copyright 2007 Dean Hall.  All rights reserved.
:Author: Dean Hall
:Revision: 0.1
:Date: 2007/07/18

usage: gps [-EHcghlstv|p PORT]

-E          Use the EverMore GPS module
-H          Use the Holux GPS module
-p PORT     Use the module connected to the given port.
-c          Filter in $GPRMC sentence type.
-g          Filter in $GPGGA sentence type.
-h          Prints this help message
-l          Filter in $GPGLL sentence type
-s          Filter in $GPGSA sentence type.
-t          Filter in $GPVTG sentence type.
-v          Filter in $GPGSV sentence type.
--EverMore  Use the EverMore GPS module
--Holux     Use the Holux GPS module
--port=PORT Use the module connected to the given port.
--rmc       Filter in $GPRMC sentence type.
--gga       Filter in $GPGGA sentence type.
--gll       Filter in $GPGLL sentence type
--gsa       Filter in $GPGSA sentence type.
--vtg       Filter in $GPVTG sentence type.
--gsv       Filter in $GPGSV sentence type.
"""


# Device pathnames for various GPS modules
DEVICES = {
    "Holux": "/dev/cu.usbserial",
    "EverMore": "/dev/cu.SLAB_USBtoUART",
    }

DEFAULT_BAUD = 4800
#DWH: Changed default baud to 19200
#DEFAULT_BAUD = 19200


import getopt, sys
import serial


class GpsIOError(IOError):
    pass


class GpsModule(object):
    """Wraps the serial module for use with a USB/Serial GPS module."""

    def __init__(self, device=None, baudrate=DEFAULT_BAUD):

        fi = None

        # Use the GPS module if specified
        if device:
            try:
                fi = serial.Serial(device, DEFAULT_BAUD)
            except serial.serialutil.SerialException, se:
                print "Specified device is not available."
                raise se

        # Else try the first GPS module that is available
        else:
            for device in DEVICES.values():
                try:
                    fi = serial.Serial(device, DEFAULT_BAUD)
                    break
                except serial.serialutil.SerialException:
                    continue

        # Report an error if no devices are found
        if not fi:
            raise GpsIOError("Error: no devices found.")

        # Eliminate first line, it's usually trash
        fi.readline()
        self.serialobj = fi


    def readline(self, sentencefilter=[]):
        """Returns the next NMEA sentence type that matches an entry in the filter."""

        # Get a line from the module
        line = self.serialobj.readline()

        # If the sentence type is not in the filter, get a new sentence
        while sentencefilter and not line[3:6] in sentencefilter:
            line = self.serialobj.readline()

        return line


    def close(self,):
        """Closes the serial link to the GPS module."""
        self.serialobj.close()


def main():
    # Parse command line options
    try:
        opts, args = getopt.getopt(sys.argv[1:], "EHcghlp:stv",
                                   ["EverMore", "Holux", "port=", "rmc", "gga",
                                    "help", "gll", "gsa", "vtg", "gsv"])
    except getopt.GetoptError:
        print __doc__
        sys.exit(2)

    sentencefilter = []
    device = None
    for o, a in opts:
        if o in ("-h", "--help"):
            print __doc__
            sys.exit()

        elif o in ("-E", "--EverMore"):
            device = DEVICES["EverMore"]
        elif o in ("-H", "--Holux"):
            device = DEVICES["Holux"]
        elif o in ("-p", "--port"):
            device = a
        elif o in ("-c", "--rmc"):
            sentencefilter.append("RMC")
        elif o in ("-g", "--gga"):
            sentencefilter.append("GGA")
        elif o in ("-l", "--gll"):
            sentencefilter.append("GLL")
        elif o in ("-s", "--gsa"):
            sentencefilter.append("GSA")
        elif o in ("-t", "--vtg"):
            sentencefilter.append("VTG")
        elif o in ("-v", "--gsv"):
            sentencefilter.append("GSV")

    module = GpsModule(device)

    # Begin infinite loop (until users presses Ctl+C)
    try:
        while True:
            sys.stdout.write(module.readline(sentencefilter))

    # Exit cleanly when user types Ctl+C
    except KeyboardInterrupt:
        pass

    # Close files in any event
    finally:
        module.close()


if __name__ == "__main__":
    main()