aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToni Jones <toni.jones@ni.com>2019-01-03 16:47:27 +0000
committerBrent Stapleton <brent.stapleton@ettus.com>2019-01-03 18:54:43 -0800
commitf63c089a348090adc0023db5e6530d6d8810f5e5 (patch)
treed97229fe63a391c3ec7abcfa7657f3f808dc77e1
parent494c7338d7d3cf057a25b02ac37cfa39397dacba (diff)
downloaduhd-f63c089a348090adc0023db5e6530d6d8810f5e5.tar.gz
uhd-f63c089a348090adc0023db5e6530d6d8810f5e5.tar.bz2
uhd-f63c089a348090adc0023db5e6530d6d8810f5e5.zip
mpm: Add gpgga sensor function to GPSd iface
Add method to generate GPGGA sensor data in MPM devices. This needs to be constructed from TPV and SKY sensor data, and matches the GPGGA sensor functionality in gpsd_iface.cpp.
-rw-r--r--mpm/python/usrp_mpm/gpsd_iface.py101
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"""