Skip to content

Commit

Permalink
Add TNLDG, TNL,VGK and TNL,PJK messages (#75)
Browse files Browse the repository at this point in the history
* Add a couple of missing Trimble messages

* More strict TNL typing. Add exception for TNL,DG message and tests.

* Fix tiemstamp assert for TNLPJK, TNLVHD, TNLVGK

* Consistend quotes in TNLVHD.Datestamp

* Clean up the mess with TNLDG

* test/tnl: fix typo in expected frequency

* Update test, proprietary sentence just got updated

* tnl: consistensy in gps_quality types. Let's not make it numeric

* tests: fix tests to follow consistency

---------

Co-authored-by: zilvinas <[email protected]>
  • Loading branch information
kamiccolo and zilvinas authored Mar 5, 2024
1 parent 802bfb6 commit 8a870af
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 25 deletions.
91 changes: 76 additions & 15 deletions pynmea2/types/proprietary/tnl.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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
Expand All @@ -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):
"""
Expand Down
12 changes: 2 additions & 10 deletions test/test_proprietary.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
109 changes: 109 additions & 0 deletions test/test_tnl.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8a870af

Please sign in to comment.