diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index 8f2257c..567c46b 100644 --- a/pynmea2/types/proprietary/tnl.py +++ b/pynmea2/types/proprietary/tnl.py @@ -1,6 +1,7 @@ # -- TRIMBLE -- # # pylint: disable=wildcard-import,unused-wildcard-import +from decimal import Decimal from ... import nmea from ...nmea_utils import * """ Support for proprietary messages from BD9xx recievers. @@ -16,15 +17,15 @@ def __new__(_cls, manufacturer, data): ''' Return the correct sentence type based on the first field ''' - sentence_type = data[0] or data[1] + sentence_type = data[1] name = manufacturer + sentence_type - cls = _cls.sentence_types.get(name, _cls) + if name not in _cls.sentence_types: + # TNLDG does not have a sentence type + if TNLDG.match(data): + return super(TNL, TNLDG).__new__(TNLDG) + cls = _cls.sentence_types.get(name, TNL) return super(TNL, cls).__new__(cls) - def __init__(self, manufacturer, data): - self.sentence_type = data[0] or data[1] - super(TNL, self).__init__(manufacturer, data) - class TNLAVR(TNL): """ @@ -66,6 +67,29 @@ class TNLBPQ(TNL, LatLonFix, DatetimeFix): ('Total number of satelites in use', 'num_sats'), ) +class TNLDG(TNL): + """ + Trimble DG message (L-band, beacon signal strength, etc) + """ + @staticmethod + def match(data): + return re.match(r'\d+\.\d{1}', data[1]) + + def __init__(self, *args, **kwargs): + self.subtype = 'DG' + super(TNLDG, self).__init__(*args, **kwargs) + + fields = ( + ('Empty', '_'), + ('Signal strength', 'strength', float), + ('SNR in db', 'snr', float), + ('Signal frequency in kHz', 'frequency', float), + ('Bit rate', 'bitrate', Decimal), + ('Channel number', 'channel_no', Decimal), + ('Tracking status', 'status'), + ('Channel used', 'channel_used'), + ('Tracking performance indicator', 'performance', Decimal), + ) class TNLGGK(TNL, LatLonFix, DatetimeFix): """ @@ -89,6 +113,24 @@ class TNLGGK(TNL, LatLonFix, DatetimeFix): ) +class TNLVGK(TNL, DatetimeFix): + """ + Trimble VGK (vector information) message + """ + fields = ( + ('Empty', '_'), + ('Sentence Type', 'type'), + ('Timestamp', 'timestamp', timestamp), + ('Datestamp', 'datestamp', datestamp), + ('East component', 'east', float), + ('North component', 'north', float), + ('Up component', 'up', float), + ('GPS Quality', 'gps_quality'), + ('Number of satelites', 'num_sats', Decimal), + ('DOP of fix', 'dop', float), + ('Meters', 'meters'), + ) + class TNLVHD(TNL, DatetimeFix): """ Trimble VHD Message @@ -97,18 +139,37 @@ class TNLVHD(TNL, DatetimeFix): ('Empty', '_'), ('Sentence Type', 'type'), ('Timestamp', 'timestamp', timestamp), - ("Datestamp", "datestamp", datestamp), - ('Azimuth Angle', 'azimuth'), - ('AzimuthTime', 'azdt'), - ('Vertical Angle', 'vertical'), - ('VerticalTime', 'vertdt'), - ('Range', 'range'), - ('RangeTime', 'rdt'), + ('Datestamp', 'datestamp', datestamp), + ('Azimuth Angle', 'azimuth', float), + ('AzimuthTime', 'azdt', float), + ('Vertical Angle', 'vertical', float), + ('VerticalTime', 'vertdt', float), + ('Range', 'range', float), + ('RangeTime', 'rdt', float), ('GPS Quality', 'gps_quality'), - ('Total number of satelites in use', 'num_sats'), - ('PDOP', 'pdop'), + ('Total number of satelites in use', 'num_sats', Decimal), + ('PDOP', 'pdop', float), ) +class TNLPJK(TNL, DatetimeFix): + """ + Trimble PJK message + """ + fields = ( + ('Empty', '_'), + ('Sentence Type', 'type'), + ('Timestamp', 'timestamp', timestamp), + ('Datestamp', 'datestamp', datestamp), + ('Northing', 'northing', float), + ('North', 'north'), + ('Easting', 'easting', float), + ('East', 'east'), + ('GPS Quality', 'gps_quality'), + ('Number of satellites', 'num_sats', Decimal), + ('DOP of fix', 'dop', float), + ('Height of antenna phase center', 'height'), + ('Meters', 'meters'), + ) class TNLPJT(TNL): """ diff --git a/test/test_proprietary.py b/test/test_proprietary.py index ce6aea3..08ee8be 100644 --- a/test/test_proprietary.py +++ b/test/test_proprietary.py @@ -63,27 +63,19 @@ class ABC(pynmea2.ProprietarySentence): def test_proprietary_with_comma(): - # class with no extra comma - class TNLDG(pynmea2.tnl.TNL): - fields = () - - # raise Exception(TNL.sentence_types) - # raise Exception(pynmea2.ProprietarySentence.sentence_types) - data = "$PTNLDG,44.0,33.0,287.0,100,0,4,1,0,,,*3E" msg = pynmea2.parse(data) - assert isinstance(msg, TNLDG) + assert isinstance(msg, pynmea2.tnl.TNLDG) assert msg.data == ['DG', '44.0', '33.0', '287.0', '100', '0', '4', '1', '0', '', '', ''] assert str(msg) == data - # type with extra comma data = '$PTNL,PJT,NAD83(Conus),CaliforniaZone 4 0404*51' msg = pynmea2.parse(data) assert type(msg) == pynmea2.tnl.TNLPJT assert msg.manufacturer == 'TNL' - assert msg.sentence_type == 'PJT' + assert msg.type == 'PJT' assert msg.coord_name == 'NAD83(Conus)' assert msg.project_name == 'CaliforniaZone 4 0404' assert str(msg) == data diff --git a/test/test_tnl.py b/test/test_tnl.py new file mode 100644 index 0000000..06383b8 --- /dev/null +++ b/test/test_tnl.py @@ -0,0 +1,109 @@ +from decimal import Decimal +import datetime + +import pynmea2 + +def test_tnlpjk(): + data = '$PTNL,PJK,202831.50,011112,+805083.350,N,+388997.346,E,10,09,1.5,GHT+25.478,M*77' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLPJK + assert msg.manufacturer == 'TNL' + assert msg.type == 'PJK' + assert msg.timestamp == datetime.time(20, 28, 31, 500000, tzinfo=datetime.timezone.utc) + assert msg.datestamp == datetime.date(2012, 11, 1) + assert msg.northing == 805083.350 + assert msg.north == 'N' + assert msg.easting == 388997.346 + assert msg.east == 'E' + assert msg.gps_quality == '10' + assert msg.num_sats == 9 + assert msg.dop == 1.5 + assert msg.height == 'GHT+25.478' + +def test_tnlpjk2(): + # not sure if this is correct checksum, because of too long (for NMEA standard) msg + data = '$PTNL,PJK,010717.00,170896,+732646.511,N,+1731051.091,E,1,05,2.7,EHT+28.345,M*7A' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLPJK + assert msg.manufacturer == 'TNL' + assert msg.type == 'PJK' + assert msg.timestamp == datetime.time(1, 7, 17, 0, tzinfo=datetime.timezone.utc) + assert msg.datestamp == datetime.date(1996, 8, 17) + assert msg.northing == 732646.511 + assert msg.north == 'N' + assert msg.easting == 1731051.091 + assert msg.east == 'E' + assert msg.gps_quality == '1' + assert msg.num_sats == 5 + assert msg.dop == 2.7 + assert msg.height == 'EHT+28.345' + +def test_tnlpjt(): + data = '$PTNL,PJT,NAD83(Conus),California Zone 4 0404,*5D' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLPJT + assert msg.manufacturer == 'TNL' + assert msg.type == 'PJT' + assert msg.coord_name == 'NAD83(Conus)' + assert msg.project_name == 'California Zone 4 0404' + +def test_tnldg_beacon(): + data = '$PTNLDG,44.0,33.0,287.0,100,0,4,1,0,,,*3E' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLDG + assert msg.manufacturer == 'TNL' + assert msg.strength == 44.0 + assert msg.snr == 33.0 + assert msg.frequency == 287.0 + assert msg.bitrate == 100 + assert msg.channel_no == 0 + assert msg.status == '4' + assert msg.channel_used == '1' + assert msg.performance == 0 + +def test_tnldg_lband(): + data = '$PTNLDG,124.0,10.5,1557855.0,1200,2,4,0,3,,,*3C' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLDG + assert msg.manufacturer == 'TNL' + assert msg.strength == 124.0 + assert msg.snr == 10.5 + assert msg.frequency == 1557855.0 + assert msg.bitrate == 1200 + assert msg.channel_no == 2 + assert msg.status == '4' + assert msg.channel_used == '0' + assert msg.performance == 3 + +def test_tnlvgk(): + data = '$PTNL,VGK,160159.00,010997,-0000.161,00009.985,-0000.002,3,07,1.4,M*0B' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLVGK + assert msg.manufacturer == 'TNL' + assert msg.type == 'VGK' + assert msg.timestamp == datetime.time(16, 1, 59, 0, tzinfo=datetime.timezone.utc) + assert msg.datestamp == datetime.date(1997, 9, 1) + assert msg.east == -0.161 + assert msg.north == 9.985 + assert msg.up == -0.002 + assert msg.gps_quality == '3' + assert msg.num_sats == 7 + assert msg.dop == 1.4 + +def test_tnlvhd(): + data = '$PTNL,VHD,030556.00,300998,187.718,-22.138,-76.929,-5.015,0.033,0.006,3,07,2.4,M*22' + msg = pynmea2.parse(data) + assert type(msg) == pynmea2.tnl.TNLVHD + assert msg.manufacturer == 'TNL' + assert msg.type == 'VHD' + assert msg.timestamp == datetime.time(3, 5, 56, 0, tzinfo=datetime.timezone.utc) + assert msg.datestamp == datetime.date(1998, 9, 30) + assert msg.azimuth == 187.718 + assert msg.azdt == -22.138 + assert msg.vertical == -76.929 + assert msg.vertdt == -5.015 + assert msg.range == 0.033 + assert msg.rdt == 0.006 + assert msg.gps_quality == '3' + assert msg.num_sats == 7 + assert msg.pdop == 2.4