Skip to content

Commit 8a870af

Browse files
kamiccolozilvinas
and
zilvinas
authored
Add TNLDG, TNL,VGK and TNL,PJK messages (#75)
* 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 <zilvinas.vaiciukevicius@laserpas.com>
1 parent 802bfb6 commit 8a870af

File tree

3 files changed

+187
-25
lines changed

3 files changed

+187
-25
lines changed

pynmea2/types/proprietary/tnl.py

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -- TRIMBLE -- #
22

33
# pylint: disable=wildcard-import,unused-wildcard-import
4+
from decimal import Decimal
45
from ... import nmea
56
from ...nmea_utils import *
67
""" Support for proprietary messages from BD9xx recievers.
@@ -16,15 +17,15 @@ def __new__(_cls, manufacturer, data):
1617
'''
1718
Return the correct sentence type based on the first field
1819
'''
19-
sentence_type = data[0] or data[1]
20+
sentence_type = data[1]
2021
name = manufacturer + sentence_type
21-
cls = _cls.sentence_types.get(name, _cls)
22+
if name not in _cls.sentence_types:
23+
# TNLDG does not have a sentence type
24+
if TNLDG.match(data):
25+
return super(TNL, TNLDG).__new__(TNLDG)
26+
cls = _cls.sentence_types.get(name, TNL)
2227
return super(TNL, cls).__new__(cls)
2328

24-
def __init__(self, manufacturer, data):
25-
self.sentence_type = data[0] or data[1]
26-
super(TNL, self).__init__(manufacturer, data)
27-
2829

2930
class TNLAVR(TNL):
3031
"""
@@ -66,6 +67,29 @@ class TNLBPQ(TNL, LatLonFix, DatetimeFix):
6667
('Total number of satelites in use', 'num_sats'),
6768
)
6869

70+
class TNLDG(TNL):
71+
"""
72+
Trimble DG message (L-band, beacon signal strength, etc)
73+
"""
74+
@staticmethod
75+
def match(data):
76+
return re.match(r'\d+\.\d{1}', data[1])
77+
78+
def __init__(self, *args, **kwargs):
79+
self.subtype = 'DG'
80+
super(TNLDG, self).__init__(*args, **kwargs)
81+
82+
fields = (
83+
('Empty', '_'),
84+
('Signal strength', 'strength', float),
85+
('SNR in db', 'snr', float),
86+
('Signal frequency in kHz', 'frequency', float),
87+
('Bit rate', 'bitrate', Decimal),
88+
('Channel number', 'channel_no', Decimal),
89+
('Tracking status', 'status'),
90+
('Channel used', 'channel_used'),
91+
('Tracking performance indicator', 'performance', Decimal),
92+
)
6993

7094
class TNLGGK(TNL, LatLonFix, DatetimeFix):
7195
"""
@@ -89,6 +113,24 @@ class TNLGGK(TNL, LatLonFix, DatetimeFix):
89113
)
90114

91115

116+
class TNLVGK(TNL, DatetimeFix):
117+
"""
118+
Trimble VGK (vector information) message
119+
"""
120+
fields = (
121+
('Empty', '_'),
122+
('Sentence Type', 'type'),
123+
('Timestamp', 'timestamp', timestamp),
124+
('Datestamp', 'datestamp', datestamp),
125+
('East component', 'east', float),
126+
('North component', 'north', float),
127+
('Up component', 'up', float),
128+
('GPS Quality', 'gps_quality'),
129+
('Number of satelites', 'num_sats', Decimal),
130+
('DOP of fix', 'dop', float),
131+
('Meters', 'meters'),
132+
)
133+
92134
class TNLVHD(TNL, DatetimeFix):
93135
"""
94136
Trimble VHD Message
@@ -97,18 +139,37 @@ class TNLVHD(TNL, DatetimeFix):
97139
('Empty', '_'),
98140
('Sentence Type', 'type'),
99141
('Timestamp', 'timestamp', timestamp),
100-
("Datestamp", "datestamp", datestamp),
101-
('Azimuth Angle', 'azimuth'),
102-
('AzimuthTime', 'azdt'),
103-
('Vertical Angle', 'vertical'),
104-
('VerticalTime', 'vertdt'),
105-
('Range', 'range'),
106-
('RangeTime', 'rdt'),
142+
('Datestamp', 'datestamp', datestamp),
143+
('Azimuth Angle', 'azimuth', float),
144+
('AzimuthTime', 'azdt', float),
145+
('Vertical Angle', 'vertical', float),
146+
('VerticalTime', 'vertdt', float),
147+
('Range', 'range', float),
148+
('RangeTime', 'rdt', float),
107149
('GPS Quality', 'gps_quality'),
108-
('Total number of satelites in use', 'num_sats'),
109-
('PDOP', 'pdop'),
150+
('Total number of satelites in use', 'num_sats', Decimal),
151+
('PDOP', 'pdop', float),
110152
)
111153

154+
class TNLPJK(TNL, DatetimeFix):
155+
"""
156+
Trimble PJK message
157+
"""
158+
fields = (
159+
('Empty', '_'),
160+
('Sentence Type', 'type'),
161+
('Timestamp', 'timestamp', timestamp),
162+
('Datestamp', 'datestamp', datestamp),
163+
('Northing', 'northing', float),
164+
('North', 'north'),
165+
('Easting', 'easting', float),
166+
('East', 'east'),
167+
('GPS Quality', 'gps_quality'),
168+
('Number of satellites', 'num_sats', Decimal),
169+
('DOP of fix', 'dop', float),
170+
('Height of antenna phase center', 'height'),
171+
('Meters', 'meters'),
172+
)
112173

113174
class TNLPJT(TNL):
114175
"""

test/test_proprietary.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,19 @@ class ABC(pynmea2.ProprietarySentence):
6363

6464

6565
def test_proprietary_with_comma():
66-
# class with no extra comma
67-
class TNLDG(pynmea2.tnl.TNL):
68-
fields = ()
69-
70-
# raise Exception(TNL.sentence_types)
71-
# raise Exception(pynmea2.ProprietarySentence.sentence_types)
72-
7366
data = "$PTNLDG,44.0,33.0,287.0,100,0,4,1,0,,,*3E"
7467
msg = pynmea2.parse(data)
75-
assert isinstance(msg, TNLDG)
68+
assert isinstance(msg, pynmea2.tnl.TNLDG)
7669
assert msg.data == ['DG', '44.0', '33.0', '287.0', '100', '0', '4', '1', '0', '', '', '']
7770
assert str(msg) == data
7871

79-
8072
# type with extra comma
8173

8274
data = '$PTNL,PJT,NAD83(Conus),CaliforniaZone 4 0404*51'
8375
msg = pynmea2.parse(data)
8476
assert type(msg) == pynmea2.tnl.TNLPJT
8577
assert msg.manufacturer == 'TNL'
86-
assert msg.sentence_type == 'PJT'
78+
assert msg.type == 'PJT'
8779
assert msg.coord_name == 'NAD83(Conus)'
8880
assert msg.project_name == 'CaliforniaZone 4 0404'
8981
assert str(msg) == data

test/test_tnl.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from decimal import Decimal
2+
import datetime
3+
4+
import pynmea2
5+
6+
def test_tnlpjk():
7+
data = '$PTNL,PJK,202831.50,011112,+805083.350,N,+388997.346,E,10,09,1.5,GHT+25.478,M*77'
8+
msg = pynmea2.parse(data)
9+
assert type(msg) == pynmea2.tnl.TNLPJK
10+
assert msg.manufacturer == 'TNL'
11+
assert msg.type == 'PJK'
12+
assert msg.timestamp == datetime.time(20, 28, 31, 500000, tzinfo=datetime.timezone.utc)
13+
assert msg.datestamp == datetime.date(2012, 11, 1)
14+
assert msg.northing == 805083.350
15+
assert msg.north == 'N'
16+
assert msg.easting == 388997.346
17+
assert msg.east == 'E'
18+
assert msg.gps_quality == '10'
19+
assert msg.num_sats == 9
20+
assert msg.dop == 1.5
21+
assert msg.height == 'GHT+25.478'
22+
23+
def test_tnlpjk2():
24+
# not sure if this is correct checksum, because of too long (for NMEA standard) msg
25+
data = '$PTNL,PJK,010717.00,170896,+732646.511,N,+1731051.091,E,1,05,2.7,EHT+28.345,M*7A'
26+
msg = pynmea2.parse(data)
27+
assert type(msg) == pynmea2.tnl.TNLPJK
28+
assert msg.manufacturer == 'TNL'
29+
assert msg.type == 'PJK'
30+
assert msg.timestamp == datetime.time(1, 7, 17, 0, tzinfo=datetime.timezone.utc)
31+
assert msg.datestamp == datetime.date(1996, 8, 17)
32+
assert msg.northing == 732646.511
33+
assert msg.north == 'N'
34+
assert msg.easting == 1731051.091
35+
assert msg.east == 'E'
36+
assert msg.gps_quality == '1'
37+
assert msg.num_sats == 5
38+
assert msg.dop == 2.7
39+
assert msg.height == 'EHT+28.345'
40+
41+
def test_tnlpjt():
42+
data = '$PTNL,PJT,NAD83(Conus),California Zone 4 0404,*5D'
43+
msg = pynmea2.parse(data)
44+
assert type(msg) == pynmea2.tnl.TNLPJT
45+
assert msg.manufacturer == 'TNL'
46+
assert msg.type == 'PJT'
47+
assert msg.coord_name == 'NAD83(Conus)'
48+
assert msg.project_name == 'California Zone 4 0404'
49+
50+
def test_tnldg_beacon():
51+
data = '$PTNLDG,44.0,33.0,287.0,100,0,4,1,0,,,*3E'
52+
msg = pynmea2.parse(data)
53+
assert type(msg) == pynmea2.tnl.TNLDG
54+
assert msg.manufacturer == 'TNL'
55+
assert msg.strength == 44.0
56+
assert msg.snr == 33.0
57+
assert msg.frequency == 287.0
58+
assert msg.bitrate == 100
59+
assert msg.channel_no == 0
60+
assert msg.status == '4'
61+
assert msg.channel_used == '1'
62+
assert msg.performance == 0
63+
64+
def test_tnldg_lband():
65+
data = '$PTNLDG,124.0,10.5,1557855.0,1200,2,4,0,3,,,*3C'
66+
msg = pynmea2.parse(data)
67+
assert type(msg) == pynmea2.tnl.TNLDG
68+
assert msg.manufacturer == 'TNL'
69+
assert msg.strength == 124.0
70+
assert msg.snr == 10.5
71+
assert msg.frequency == 1557855.0
72+
assert msg.bitrate == 1200
73+
assert msg.channel_no == 2
74+
assert msg.status == '4'
75+
assert msg.channel_used == '0'
76+
assert msg.performance == 3
77+
78+
def test_tnlvgk():
79+
data = '$PTNL,VGK,160159.00,010997,-0000.161,00009.985,-0000.002,3,07,1.4,M*0B'
80+
msg = pynmea2.parse(data)
81+
assert type(msg) == pynmea2.tnl.TNLVGK
82+
assert msg.manufacturer == 'TNL'
83+
assert msg.type == 'VGK'
84+
assert msg.timestamp == datetime.time(16, 1, 59, 0, tzinfo=datetime.timezone.utc)
85+
assert msg.datestamp == datetime.date(1997, 9, 1)
86+
assert msg.east == -0.161
87+
assert msg.north == 9.985
88+
assert msg.up == -0.002
89+
assert msg.gps_quality == '3'
90+
assert msg.num_sats == 7
91+
assert msg.dop == 1.4
92+
93+
def test_tnlvhd():
94+
data = '$PTNL,VHD,030556.00,300998,187.718,-22.138,-76.929,-5.015,0.033,0.006,3,07,2.4,M*22'
95+
msg = pynmea2.parse(data)
96+
assert type(msg) == pynmea2.tnl.TNLVHD
97+
assert msg.manufacturer == 'TNL'
98+
assert msg.type == 'VHD'
99+
assert msg.timestamp == datetime.time(3, 5, 56, 0, tzinfo=datetime.timezone.utc)
100+
assert msg.datestamp == datetime.date(1998, 9, 30)
101+
assert msg.azimuth == 187.718
102+
assert msg.azdt == -22.138
103+
assert msg.vertical == -76.929
104+
assert msg.vertdt == -5.015
105+
assert msg.range == 0.033
106+
assert msg.rdt == 0.006
107+
assert msg.gps_quality == '3'
108+
assert msg.num_sats == 7
109+
assert msg.pdop == 2.4

0 commit comments

Comments
 (0)