From 1254c71be48148126c6a1a0441c9f958bcd63951 Mon Sep 17 00:00:00 2001 From: zilvinas Date: Fri, 20 Oct 2017 18:04:29 +0300 Subject: [PATCH 1/9] Add a couple of missing Trimble messages --- pynmea2/types/proprietary/tnl.py | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index 8f2257c..50dc6f1 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. @@ -66,6 +67,22 @@ 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) + """ + fields = ( + ('Empty', '_'), + ('Sentence Type', 'type'), + ('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 +106,25 @@ class TNLGGK(TNL, LatLonFix, DatetimeFix): ) + +class TNLVGK(TNL, DatetimeFix): + """ + Trimble VGK (vector information) message + """ + fields = ( + ('Empty', '_'), + ('Sentence Type'), + ('Timestamp', 'timestamp', timestamp), + ('Datestamp', 'datestamp', datestamp), + ('East component', 'east'), + ('North component', 'north'), + ('Up component', 'up'), + ('GPS Quality', 'gps_quality'), + ('Number of satelites', 'num_sats'), + ('DOP of fix', 'dop'), + ('Meters', 'meters'), + ) + class TNLVHD(TNL, DatetimeFix): """ Trimble VHD Message @@ -109,6 +145,25 @@ class TNLVHD(TNL, DatetimeFix): ('PDOP', 'pdop'), ) +class TNLPJK(TNL, DatetimeFix): + """ + Trimble PJK message + """ + fields = ( + ('Empty', '_'), + ('Sentence Type', 'type'), + ('Timestamp', 'timestamp', timestamp), + ('Datestamp', 'datestamp', datestamp), + ('Northing', 'northing'), + ('North', 'north'), + ('Easting', 'easting'), + ('East', 'east'), + ('GPS Quality', 'gps_quality'), + ('Number of satellites', 'num_sats'), + ('DOP of fix', 'dop'), + ('Height of antenna phase center', 'height'), + ('Meters', 'meters'), + ) class TNLPJT(TNL): """ From 43cdcb10d473eba3c319bfebda3e52e519bfa6cf Mon Sep 17 00:00:00 2001 From: zilvinas Date: Thu, 12 Apr 2018 16:50:35 +0300 Subject: [PATCH 2/9] More strict TNL typing. Add exception for TNL,DG message and tests. --- pynmea2/types/proprietary/tnl.py | 53 +++++++++------ test/test_tnl.py | 109 +++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 test/test_tnl.py diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index 50dc6f1..6f81d58 100644 --- a/pynmea2/types/proprietary/tnl.py +++ b/pynmea2/types/proprietary/tnl.py @@ -19,6 +19,10 @@ def __new__(_cls, manufacturer, data): ''' sentence_type = data[0] or data[1] name = manufacturer + sentence_type + 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, _cls) return super(TNL, cls).__new__(cls) @@ -71,9 +75,16 @@ 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 = 'TNL' + super(TNLDG, self).__init(*args, **kwargs) + fields = ( ('Empty', '_'), - ('Sentence Type', 'type'), ('Signal strength', 'strength', float), ('SNR in db', 'snr', float), ('Signal frequency in kHz', 'frequency', float), @@ -113,15 +124,15 @@ class TNLVGK(TNL, DatetimeFix): """ fields = ( ('Empty', '_'), - ('Sentence Type'), + ('Sentence Type', 'type'), ('Timestamp', 'timestamp', timestamp), ('Datestamp', 'datestamp', datestamp), - ('East component', 'east'), - ('North component', 'north'), - ('Up component', 'up'), + ('East component', 'east', float), + ('North component', 'north', float), + ('Up component', 'up', float), ('GPS Quality', 'gps_quality'), - ('Number of satelites', 'num_sats'), - ('DOP of fix', 'dop'), + ('Number of satelites', 'num_sats', Decimal), + ('DOP of fix', 'dop', float), ('Meters', 'meters'), ) @@ -133,16 +144,16 @@ 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'), - ('GPS Quality', 'gps_quality'), - ('Total number of satelites in use', 'num_sats'), - ('PDOP', 'pdop'), + ("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', Decimal), + ('Total number of satelites in use', 'num_sats', Decimal), + ('PDOP', 'pdop', float), ) class TNLPJK(TNL, DatetimeFix): @@ -154,13 +165,13 @@ class TNLPJK(TNL, DatetimeFix): ('Sentence Type', 'type'), ('Timestamp', 'timestamp', timestamp), ('Datestamp', 'datestamp', datestamp), - ('Northing', 'northing'), + ('Northing', 'northing', float), ('North', 'north'), - ('Easting', 'easting'), + ('Easting', 'easting', float), ('East', 'east'), ('GPS Quality', 'gps_quality'), - ('Number of satellites', 'num_sats'), - ('DOP of fix', 'dop'), + ('Number of satellites', 'num_sats', Decimal), + ('DOP of fix', 'dop', float), ('Height of antenna phase center', 'height'), ('Meters', 'meters'), ) diff --git a/test/test_tnl.py b/test/test_tnl.py new file mode 100644 index 0000000..eee1daa --- /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) + 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) + 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 == 5,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) + 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) + 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 From 4ee7032d1dd4fea7d578b1a60397765661b1d074 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 16:34:57 +0200 Subject: [PATCH 3/9] Fix tiemstamp assert for TNLPJK, TNLVHD, TNLVGK --- test/test_tnl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_tnl.py b/test/test_tnl.py index eee1daa..fce8f42 100644 --- a/test/test_tnl.py +++ b/test/test_tnl.py @@ -9,7 +9,7 @@ def test_tnlpjk(): assert type(msg) == pynmea2.tnl.TNLPJK assert msg.manufacturer == 'TNL' assert msg.type == 'PJK' - assert msg.timestamp == datetime.time(20, 28, 31, 500000) + 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' @@ -27,7 +27,7 @@ def test_tnlpjk2(): assert type(msg) == pynmea2.tnl.TNLPJK assert msg.manufacturer == 'TNL' assert msg.type == 'PJK' - assert msg.timestamp == datetime.time(1, 7, 17, 0) + 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' @@ -81,7 +81,7 @@ def test_tnlvgk(): assert type(msg) == pynmea2.tnl.TNLVGK assert msg.manufacturer == 'TNL' assert msg.type == 'VGK' - assert msg.timestamp == datetime.time(16, 1, 59, 0) + 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 @@ -96,7 +96,7 @@ def test_tnlvhd(): assert type(msg) == pynmea2.tnl.TNLVHD assert msg.manufacturer == 'TNL' assert msg.type == 'VHD' - assert msg.timestamp == datetime.time(3, 5, 56, 0) + 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 From e3843eecdb8e862a669c55540275f9c3a3540f8c Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 16:37:11 +0200 Subject: [PATCH 4/9] Consistend quotes in TNLVHD.Datestamp --- pynmea2/types/proprietary/tnl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index 6f81d58..b40cee8 100644 --- a/pynmea2/types/proprietary/tnl.py +++ b/pynmea2/types/proprietary/tnl.py @@ -144,7 +144,7 @@ class TNLVHD(TNL, DatetimeFix): ('Empty', '_'), ('Sentence Type', 'type'), ('Timestamp', 'timestamp', timestamp), - ("Datestamp", 'datestamp', datestamp), + ('Datestamp', 'datestamp', datestamp), ('Azimuth Angle', 'azimuth', float), ('AzimuthTime', 'azdt', float), ('Vertical Angle', 'vertical', float), From 2721f5f233bfc1eff490a377ab2b2582b263d0d9 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 17:50:40 +0200 Subject: [PATCH 5/9] Clean up the mess with TNLDG --- pynmea2/types/proprietary/tnl.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index b40cee8..19d7203 100644 --- a/pynmea2/types/proprietary/tnl.py +++ b/pynmea2/types/proprietary/tnl.py @@ -17,13 +17,13 @@ def __new__(_cls, manufacturer, data): ''' Return the correct sentence type based on the first field ''' - sentence_type = data[0] or data[1] - name = manufacturer + sentence_type - if name not in _cls.sentence_types: - # TNLDG does not have a sentence type + + name_check = manufacturer + data[1] + if name_check not in _cls.sentence_types: if TNLDG.match(data): return super(TNL, TNLDG).__new__(TNLDG) - cls = _cls.sentence_types.get(name, _cls) + + cls = _cls.sentence_types.get(name_check, _cls) return super(TNL, cls).__new__(cls) def __init__(self, manufacturer, data): @@ -81,7 +81,7 @@ def match(data): def __init__(self, *args, **kwargs): self.subtype = 'TNL' - super(TNLDG, self).__init(*args, **kwargs) + super(TNLDG, self).__init__(*args, **kwargs) fields = ( ('Empty', '_'), From 167403c6413571c8fb9a02c110f1312edba35e91 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 17:51:17 +0200 Subject: [PATCH 6/9] test/tnl: fix typo in expected frequency --- test/test_tnl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tnl.py b/test/test_tnl.py index fce8f42..4e98105 100644 --- a/test/test_tnl.py +++ b/test/test_tnl.py @@ -68,7 +68,7 @@ def test_tnldg_lband(): assert msg.manufacturer == 'TNL' assert msg.strength == 124.0 assert msg.snr == 10.5 - assert msg.frequency == 5,1557855.0 + assert msg.frequency == 1557855.0 assert msg.bitrate == 1200 assert msg.channel_no == 2 assert msg.status == '4' From a835ee7d1466f5d1722e46fdd5cf4c4d5aa41cc2 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 17:51:44 +0200 Subject: [PATCH 7/9] Update test, proprietary sentence just got updated --- test/test_proprietary.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/test_proprietary.py b/test/test_proprietary.py index ce6aea3..51eb4d4 100644 --- a/test/test_proprietary.py +++ b/test/test_proprietary.py @@ -63,20 +63,12 @@ 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' From 6c317f321b07b4ce42f91ac43b1d1c387bd4d2f6 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 18:18:06 +0200 Subject: [PATCH 8/9] tnl: consistensy in gps_quality types. Let's not make it numeric --- pynmea2/types/proprietary/tnl.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/pynmea2/types/proprietary/tnl.py b/pynmea2/types/proprietary/tnl.py index 19d7203..567c46b 100644 --- a/pynmea2/types/proprietary/tnl.py +++ b/pynmea2/types/proprietary/tnl.py @@ -17,19 +17,15 @@ def __new__(_cls, manufacturer, data): ''' Return the correct sentence type based on the first field ''' - - name_check = manufacturer + data[1] - if name_check not in _cls.sentence_types: + sentence_type = data[1] + name = manufacturer + sentence_type + 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_check, _cls) + 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): """ @@ -80,7 +76,7 @@ def match(data): return re.match(r'\d+\.\d{1}', data[1]) def __init__(self, *args, **kwargs): - self.subtype = 'TNL' + self.subtype = 'DG' super(TNLDG, self).__init__(*args, **kwargs) fields = ( @@ -117,7 +113,6 @@ class TNLGGK(TNL, LatLonFix, DatetimeFix): ) - class TNLVGK(TNL, DatetimeFix): """ Trimble VGK (vector information) message @@ -151,7 +146,7 @@ class TNLVHD(TNL, DatetimeFix): ('VerticalTime', 'vertdt', float), ('Range', 'range', float), ('RangeTime', 'rdt', float), - ('GPS Quality', 'gps_quality', Decimal), + ('GPS Quality', 'gps_quality'), ('Total number of satelites in use', 'num_sats', Decimal), ('PDOP', 'pdop', float), ) From f13bec5cf416997634f7810e25f0d776b5b2b728 Mon Sep 17 00:00:00 2001 From: kamiccolo Date: Fri, 26 Jan 2024 18:18:40 +0200 Subject: [PATCH 9/9] tests: fix tests to follow consistency --- test/test_proprietary.py | 2 +- test/test_tnl.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_proprietary.py b/test/test_proprietary.py index 51eb4d4..08ee8be 100644 --- a/test/test_proprietary.py +++ b/test/test_proprietary.py @@ -75,7 +75,7 @@ def test_proprietary_with_comma(): 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 index 4e98105..06383b8 100644 --- a/test/test_tnl.py +++ b/test/test_tnl.py @@ -104,6 +104,6 @@ def test_tnlvhd(): assert msg.vertdt == -5.015 assert msg.range == 0.033 assert msg.rdt == 0.006 - assert msg.gps_quality == 3 + assert msg.gps_quality == '3' assert msg.num_sats == 7 assert msg.pdop == 2.4