diff options
Diffstat (limited to 'mpm/python/usrp_mpm')
-rw-r--r-- | mpm/python/usrp_mpm/gpsd_iface.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/mpm/python/usrp_mpm/gpsd_iface.py b/mpm/python/usrp_mpm/gpsd_iface.py index 08e9fdd16..e11874d1c 100644 --- a/mpm/python/usrp_mpm/gpsd_iface.py +++ b/mpm/python/usrp_mpm/gpsd_iface.py @@ -13,6 +13,8 @@ import json import time import select import datetime +import math +import re from usrp_mpm.mpmlog import get_logger @@ -263,6 +265,105 @@ class GPSDIfaceExtension(object): 'value': gps_sky, } + def get_gps_gpgga_sensor(self): + """Get GPGGA sensor data by parsing TPV and SKY sensor data""" + def _deg_to_dm(angle): + """Convert a latitude or longitude from degrees to degrees minutes format""" + fraction_int_tuple = math.modf(angle) + return fraction_int_tuple[1] * 100 + fraction_int_tuple[0] * 60 + + def _nmea_checksum(nmea_sentence): + """Calculate the checksum for a NMEA data sentence""" + checksum = 0 + if not nmea_sentence.startswith('$'): + return checksum + + for character in nmea_sentence[1:]: + checksum ^= ord(character) + + return checksum + + self._log.trace("Polling GPS TPV and SKY results from GPSD") + # Read responses from GPSD until we get both a SKY response and TPV + # response in non-trivial mode + while True: + gps_info = self._gpsd_iface.get_gps_info(resp_class='', timeout=15) + self._log.trace("GPS info: {}".format(gps_info)) + tpv_sensor_data = gps_info.get('tpv', [{}])[0] + sky_sensor_data = gps_info.get('sky', [{}])[0] + if tpv_sensor_data and sky_sensor_data and tpv_sensor_data.get("mode", 0) > 0: + break + + gpgga = "$GPGGA," + + if 'time' in tpv_sensor_data: + time_formatted = re.subn(r'\d{4}-\d{2}-\d{2}T(\d{2}):(\d{2}):(\d{2}\.?\d*)Z', + r'\1\2\3,', tpv_sensor_data.get('time')) + if time_formatted[1] == 1: + gpgga += time_formatted[0] + else: + gpgga += "," + else: + gpgga += "," + + if 'lat' in tpv_sensor_data: + latitude = tpv_sensor_data.get('lat') + latitude_direction = 'N' if latitude > 0 else 'S' + latitude = _deg_to_dm(abs(latitude)) + gpgga += "{:09.4f},{},".format(latitude, latitude_direction) + else: + gpgga += "0.0,S," + + if 'lon' in tpv_sensor_data: + longitude = tpv_sensor_data['lon'] + longitude_direction = 'E' if longitude > 0 else 'W' + longitude = _deg_to_dm(abs(longitude)) + gpgga += "{:010.4f},{},".format(longitude, longitude_direction) + else: + gpgga += "0.0,W," + + quality = 0 + if tpv_sensor_data['mode'] > 1: + if tpv_sensor_data.get('status') == 2: + quality = 2 + else: + quality = 1 + gpgga += "{:d},".format(quality) + + if 'satellites' in sky_sensor_data: + satellites_used = 0 + for satellite in sky_sensor_data['satellites']: + if 'used' in satellite and satellite['used']: + satellites_used += 1 + gpgga += "{:02d},".format(satellites_used) + else: + gpgga += "," + + if 'hdop' in sky_sensor_data: + gpgga += "{:.2f},".format(sky_sensor_data['hdop']) + else: + gpgga += "," + + if 'alt' in tpv_sensor_data: + gpgga += "{:2f},{},".format(tpv_sensor_data['alt'], 'M') + else: + gpgga += ",," + + # separation data is not present in tpv or sky sensor data + gpgga += ",," + + # differential data is not present + gpgga += ",," + + gpgga += "*{:02X}".format(_nmea_checksum(gpgga)) + + return { + 'name': 'gpgga', + 'type': 'STRING', + 'unit': '', + 'value': gpgga, + } + def main(): """Test functionality of the GPSDIface class""" |