knio / pynmea2 Goto Github PK
View Code? Open in Web Editor NEWPython library for parsing the NMEA 0183 protocol (GPS)
License: MIT License
Python library for parsing the NMEA 0183 protocol (GPS)
License: MIT License
Just a thought but you might want to consider allowing the stream reader to defer parsing exceptions rather than raising them immediately to the caller. The problem with raising the exceptions immediately is that you then drop out and lose the remainder of the stream buffer even though it might contain legitimate data after an item that caused the parser to fail.
Currently the pynmea2.parse
method raises a ValueError
on each kind of parser failure. It would be more convenient if there is a distinction in the type of exception so the user-code can decide how to handle each failure type;
Invalid checksum
Unknown sentence type
Sentence not parseable
Hi, I use pyserial to open serial port from a GPS dongle, when I set wrong baudrate, NMEAStreamReader will read lots of non-ascii char and failed to decode to unicode, so Exception will be raised at line 30 from stream.py:
lines = (self.buffer + data).split('\n')
Does pynmea2 support pythong 3.5.3? I'm having no luck getting it to run. It doesnt throw me any errors it just doesnt give me an output. Any ideas?
It does successfully run in python 2.7.
I realize the library is listed as 2.7 and 3, but so far the only change I needed to make to allow it to work (in my application) using Python 2.6 was to change nmea.py line 29 to:
cls.name_to_idx = dict((f[1], i) for i, f in enumerate(cls.fields))
If this is indeed the only change required to add additional backwards compatibility, then perhaps its trivial enough to include in the baseline?
When using Python 3 it gives following error:
File "C:\Python33\lib\site-packages\pynmea2\stream.py", line 48, in next
lines = (self.buffer + data).split('\n')
TypeError: Can't convert 'bytes' object to str implicitly
To fix it just replace in stream.py
line 48:
lines = (self.buffer + data).split('\n')
with
lines = (self.buffer + data.decode('ascii')).split('\n')
Hi,
Until I dug into things I hadn't realised that pynmea2
isn't a straight fork of pynmea
--it appears there was some sort of refactoring of pynmea
done before it was imported into this repository as pynmea2
?
When the refactoring was done it appears the types that implement variable length sentences (RTE
and R00
) weren't converted to work correctly. Specifically, RTE
only ever stores one item in the waypoint_list
field and puts the rest in the data
field (I haven't looked closely at R00
).
Also, the RTE
class has a now unused parse
method (https://github.com/Knio/pynmea2/blob/master/pynmea2/types.py#L377) which is supposed to override another method (originally https://code.google.com/p/pynmea/source/browse/pynmea/nmea.py#39) but doesn't and never gets called. When the method is called manually it fails because it refers to self._parse()
which doesn't exist anymore (originally it was here: https://code.google.com/p/pynmea/source/browse/pynmea/nmea.py#14).
I discovered all this when looking for the "correct" way to implement XDR
which is another variable length sentence.
It seems the correct approach is probably to override the __init__
, render
& __repr__
methods of the variable length sentence classes. I'm going to attempt this with the XDR
class.
@Knio Hello,
I have some trouble parsing an RMC sentence (pynmea2 1.4.2 installed through pip):
p.parse('$GPRMC,114130,A,3809.1250,N,02415.8050,E,12195.6,341.5,280915,5,E,A_1\r\n')
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/pynmea2/nmea.py", line 106, in parse
raise ParseError('could not parse data: %r' % line)
pynmea2.nmea.ParseError: could not parse data: '$GPRMC,114130,A,3809.1250,N,02415.8050,E,12195.6,341.5,280915,5,E,A_1\r\n'
But if I try to parse:
p.parse('$GPRMC,114130,A,3809.1250,N,02415.8050,E,12195.6,341.5,280915,5,E\r\n')
That's the nmea sentence without the checksum field
I get (almost) the correct parsing:
<RMC(timestamp=datetime.time(11, 41, 30), status='A', lat='3809.1250', lat_dir='N', lon='02415.8050',
lon_dir='E', spd_over_grnd=12195.6, true_course=341.5, datestamp=datetime.date(2015, 9, 28), mag_variation='5', mag_var_dir='E\r\n')>
(notice the last field with \r\n characters)
anyway, parsing a GGA sentence both with checksum and newline chars is ok:
p.parse('$GPGGA,114130,3809.1250,N,02415.8050,E,1,04,5.6,1500.0,M,34.5,M,,*7E\r\n')
<GGA(timestamp=datetime.time(11, 41, 30), lat='3809.1250', lat_dir='N', lon='02415.8050', lon_dir='E', gps_qual=1, num_sats='04', horizontal_dil='5.6', altitude=1500.0, altitude_units='M', geo_sep='34.5', geo_sep_units='M', age_gps_data='', ref_station_id='')>
What could I do? Thanks
If I send a RMC to nmea that has lots of blank values and then I try to get the datatime back, an exception is thrown. The question I have, is should pynmea2 handle this, or is there code that I can call to check if it's valid before I call, p.datetime
where p is the RMC instance. Since, datetime
is a derived attribute, should it have checks in there to determine if the timestamp in the record is valid or not? and if so, I don't know what to return, None
? Or is there a way for a user to check this before calling datetime
?
This is what my gps returns when it's doesn't have any signal (like when I'm testing my code in a building)...
'$GPGGA,,,,,,0,00,,,M,0.0,M,,0000*48'
And I get this exception thrown:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/opt/fh/deployed/src/gps_sink.py", line 153, in run
c(s)
File "/opt/fh/deployed/src/gps_sink.py", line 50, in set_time
self.__gps_time = p.datetime
File "/opt/fh/env/local/lib/python2.7/site-packages/pynmea2/nmea_utils.py", line 98, in datetime
return datetime.datetime.combine(self.datestamp, self.timestamp)
TypeError: combine() argument 1 must be datetime.date, not None
Hello All,
I am interested to use this library in an embedded system, e.g. itsybitsy M4 Express. Any recommendation or cautions?
Thanks,
I'm trying to figure out the best way to parse through the fields in a talker.
type(pynmea2.parse("$GPGSV,..."))
produces <class 'pynmea2.types.talker.GSV'>
A bit of exploring didn't seem to come up with a good solution, without having to follow how the test code is setup where you have to know before you do.
>>> msg = pynmea2.parse("$GPGSV,...")
>>> msg.__dict__.keys()
dict_keys(['talker', 'sentence_type', 'data'])
>>> variables = [i for i in dir(msg) if not callable(i)]
>>> variables
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'checksum', 'data', 'fields', 'identifier', 'name_to_idx', 'parse', 'proprietary_re', 'query_re', 'render', 'sentence_re', 'sentence_type', 'sentence_types', 'talker', 'talker_re']
I was trying to target something like the following.
import sys
import os
import time
import pynmea2
def read(filename):
f = open(filename)
reader = pynmea2.NMEAStreamReader(f)
while 1:
for msg in reader.next():
decode_msg = pynmea2.parse(str(msg))
print(msg)
for key in decode_msg:
value = decode_msg[key]
print(key, " :: ", value)
def main():
read(sys.argv[1])
main()
However I get the following response.
Traceback (most recent call last):
File "convert.py", line 21, in <module>
main()
File "convert.py", line 19, in main
read(sys.argv[1])
File "convert.py", line 14, in read
for key in msg:
TypeError: 'GSV' object is not iterable
I also tried a variant with
for talker, sentence_type, data in decode_msg.items():
print(talker, " :: ", sentence_type , " :: ", data)
but got
Traceback (most recent call last):
File "/anaconda3/lib/python3.7/site-packages/pynmea2/nmea.py", line 153, in __getattr__
i = t.name_to_idx[name]
KeyError: 'items'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "convert.py", line 20, in <module>
main()
File "convert.py", line 18, in main
read(sys.argv[1])
File "convert.py", line 14, in read
for talker, sentence_type, data in decode_msg.items():
File "/anaconda3/lib/python3.7/site-packages/pynmea2/nmea.py", line 155, in __getattr__
raise AttributeError(name)
AttributeError: items
suggestions welcome!
<class 'bytes'> <class 'str'>
Traceback (most recent call last):
File "GPS_nmea.py", line 112, in
main()
File "GPS_nmea.py", line 106, in main
pos=nmeatty.getNMEAPosition()
File "GPS_nmea.py", line 69, in getNMEAPosition
for msg in self._reader.next():
File "/usr/local/lib/python3.4/dist-packages/pynmea2/stream.py", line 49, in next
lines = (self.buffer + data).split('\n')
TypeError: Can't convert 'bytes' object to str implicitly
Hey,
How can I parse multiple sentence? is that possible?
Eg:
I have the multiple sentences in a buffer, can I feed it directly to pynmea?
$GPRMC,041626.000,A,1009.9738,N,07618.6555,E,0.00,115.25,100517,,,A6F$GPVTG,115.25,T,,M,0.00,N,0.00,K,A3F$GPGGA,041626.000,1009.9738,N,07618.6555,E,1,6,1.24,10.6,M,-93.4,M,,48$GPGSA,A,3,27,16,23,03,09,08,,,,,,,1.56,1.24,0.9609$GPGSV,4,1,13,23,58,007,23,03,52,210,21,08,48,131,18,27,37,081,16*71$GPGSV,4,2,13,22,34,178,,09,30,335,25,16,23,029,30,07,22,308,*7E$GPGSV,4,3,13,11,19,171,,28,11,223,,01,11,186,,30,02,278,*78$GPGSV,4,4,13,193,,,*40$GLGSV,3,1,10,70,65,312,,69,49,167,,73,32,312,16,80,22,006,*6C$GLGSV,3,2,10,83,18,136,,71,15,331,,82,15,083,,74,08,258,61$GLGSV,3,3,10,68,01,157,,84,01,185,69$GPGLL,1009.9738,N,07618.6555,E,041626.000,A,A58$GPTXT,01,01,02,ANTSTATUS=OPEN2B
Hello,
I'm new to Python and
I couldn't import "pynmea". What can i do?
I'm using Raspberry Pi 3 B+ with noobs 3
for install i used
pi@raspberrypi:~ $ pip install pynmea2
Collecting pynmea2
Downloading https://files.pythonhosted.org/packages/7c/82/f734e75dbb0aecbd9ea20489f364fdac9f124f17c4d4e26d2ab160c8ff58/pynmea2-1.12.0.tar.gz
Building wheels for collected packages: pynmea2
Running setup.py bdist_wheel for pynmea2 ... done
Stored in directory: /home/pi/.cache/pip/wheels/4f/3f/c4/4748d48cbe607279db39640f9295a9eaf12f37c21716272066
Successfully built pynmea2
Installing collected packages: pynmea2
Successfully installed pynmea2-1.12.0
pi@raspberrypi:~ $
in python i used this
import pynmea
when i run it
Python 3.5.3 (/usr/bin/python3)
%Run screen7.py
Traceback (most recent call last):
File "/home/pi/Desktop/screen7.py", line 3, in
import pynmea
File "/usr/lib/python3/dist-packages/thonny/backend.py", line 317, in _custom_import
module = self._original_import(*args, **kw)
ImportError: No module named 'pynmea'
Hello
Will this work?
class RSD(TalkerSentence):
""" RADAR System Data
"""
fields = (("Origin 1 range", "origin_1_range"), # Origin 1 range, from own ship
("Origin 1 bearing", "origin_1_bearing", float), # Origin 1 bearing, degrees from 0
("Variable Range Marker 1", "VRM1"), # Variable Range Marker 1 (VRM1), range
("Bearing Line 1", "EBL1", float), # Bearing Line 1 (EBL1), degrees from 0
("Origin 2 range", "origin_2_range"), # Origin 2 range
("Origin 2 bearing", "origin_2_bearing", float), # Origin 2 bearing
("Variable Range Marker 2", "VRM2"), # VRM2, range
("Bearing Line 2", "EBL2"), # EBL2, degrees
("Cursor Range", "Cursor_range", Decimal), # Cursor Range From Own Ship
("Cursor Bearing Degrees", "cursor_bearing", float), # Cursor Bearing Degrees Clockwise From Zero
("Range Scale", "range_scale", Decimal), # Range Scale
("Range Unit", "dist_unit"), # Range Unit
("Display rotation", "display_rotation"), # Display rotation 1
)
Hi,
I have installed this library via pip, but have a problem accessing decimal lat and lon....
The below:
msg = pynmea2.parse(rcv)
print msg.gps_qual
print rcv
print msg.lat+" "+msg.lon
print msg.latitude+" "+msg.longitude
Gives the following output:
1
$GPGGA,185953.00,5123.94863,N,00009.08705,W,1,08,1.18,47.3,M,45.6,M,,*7E
5131.94862 00008.08693
In other words the un-converted lat/lon is printed, but not the decimal version. Any idea why...?
Scenario:
The user wishes to parse the entire file (that is, multiple sentences, same type), and have the data stored in a single object. After parsing the file and returning data to msg, one would get the, say, altitude data as:
>>>msg.altitude
( 100, 200, 300 )
msg.altitude returns a tuple
How to use my gps to get my location by python by my computer ?
My fix for issue #44 had the wrong indexes since I foolishly copied it directly from the ubx.py code.
the proper __init__
method should have been the following:
def __init__(self, manufacturer, data):
self.sentence_type = manufacturer + data[0]
super(GRM, self).__init__(manufacturer, data[1:])
This same method (with SRF) should be added to srf.py
Per the spec: https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_RMC.html the date time in the RMC message is UTC, however, pynmea2 parses it and creates a date time with no timezone, thus calling timestamp() on the returned date returns the wrong timestamp.
To reproduce:
msg = '$GPRMC,184446.000,A,3720.18653,N,12153.38874,W,0.0,0.0,130220,,,A*7E'
parsed = pynmea2.parse(msg)
assert parsed.datetime.timestamp() == 1581619486.0
The above assertion fails unless your computer is set to UTC timezone.
The workaround to the bug for anyone else bumping against this is to replace
the datetime with one that has the proper timezone:
msg = '$GPRMC,184446.000,A,3720.18653,N,12153.38874,W,0.0,0.0,130220,,,A*7E'
parsed = pynmea2.parse(msg)
assert parsed.datetime.replace(tzinfo=timezone.utc).timestamp() == 1581619486.0
please help me
My Garmin GPSMAP 78s outputs the following proprietary sentences:
$PGRME,27.5,M,46.0,M,53.6,M*1C
$PGRMZ,50,f,*1D
$PGRMM,WGS 84*06
These are not correctly parsed by pynmea2 because it puts the sentence subtype ('E', 'Z', or 'M', respectively) as the first data item. Thus I get the following output for the above messages, respectively:
<GRME(hpe='E', hpe_unit='27.5', vpe='M', vpe_unit='46.0', osepe='M', osepe_unit='53.6') data=['M']>
<GRMZ(altitude='Z', altitude_unit='50', pos_fix_dim='f') data=['']>
<GRMM(datum='M') data=['WGS 84']>
Can you add support for an optional comma in regex for proprietary message ids? Some proprietary messages such as Trimble (PTNL,AVR; PTNL,GGK, etc..) have a comma between manufacturer id and sentence type. (http://www.trimble.com/OEM_ReceiverHelp/v4.85/en/default.html#NMEA-0183messages_MessageOverview.html)
I get a failure trying to access a property on a bad input... Looks like checksum is checked only if it exists in string. If no checksum is in the string the package will still try to parse but fail when trying to access properties. For example attached file will fail when trying to access the properties.
Version 1.5.3
I have not found an information of how to enable microseconds in the .timestamp
, except when I changed the code within the module 'nmea.utils' to:
ms = (len(s) == 10) and 10000 * int(s[7:9]) or 0
Is it an error or a feature len(s) == 9
? s is i.e.: str: 204820.200
NMEA sends 10 characters as 'time', including the comma.
def timestamp(s):
'''
Converts a timestamp given in "hhmmss[.ss]" ASCII format to a
datetime.time object
'''
ms = (len(s) == 9) and 10000 * int(s[7:9]) or 0
a =int(s[7:9])
t = datetime.time(
>>> import pynmea2
>>> pynmea2.__version__
'1.3.3'
>>> msg = pynmea2.GGA('GP', 'GGA', '184353.07', '1929.045', 'S', '02410.506', 'E', '1', '04', '2.6', '100.00', 'M', '-33.9','M', '', '0000')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 4 arguments (17 given)
So there are certain instances where readline() is non optimal; however, a simple read() also causes issue because it attempts to read an unknown amount of the stream. This is problematic for instances where an end of file does not occur in the stream and/or the data is intermittently available. Specifically, utilizing stdin as the nmea stream object.
Using a read(size) with size set to some value slightly larger than largest expected string size is a viable solution; however, determining the size value is necessary.
The identifier
method returns sentence name with coma.
The script
import pynmea2
s = '$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75'
item = pynmea2.parse(s)
print(item.identifier())
outputs
GPGSV,
I would expect
GPGSV
I have a Seapath MRU. It outputs the following proprietary sentences:
$PSXN,20,horiz-qual,hgt-qual,head-qual,rp-qual*csum term
$PSXN,22,gyro-calib,gyro-offs*csum term
$PSXN,23,roll,pitch,head,heave*csum term
$PSXN,24,roll-rate,pitch-rate,yaw-rate,vertical-vel*csum term
$PSXN,21,event*csum term
where:
horiz-qual: Horizontal position and velocity quality: 0 = normal, 1 = reduced performance, 2= invalid data.
hgt-qual: Height and vertical velocity quality: 0 = normal, 1 = reduced performance, 2 =invalid data.
head-qual: Heading quality: 0 = normal, 1 = reduced performance, 2 = invalid data.
rp-qual: Roll and pitch quality: 0 = normal, 1 = reduced performance, 2 = invalid data.
gyro-calib: Gyro calibration value since system start-up in degrees on format d.dd.
gyro-offs: Short-term gyro offset in degrees on format d.dd.
roll: Roll in degrees on format d.dd. Positive with port side up.
pitch: Pitch in degrees on format d.dd. Positive with bow up.
heave: Heave in metres on format d.dd. Positive down.
roll-rate: Roll rate in degrees per second on format d.dd. Positive when port side is moving upwards.
pitch-rate: Pitch rate in degrees per second on format d.dd. Positive when bow is moving upwards.
yaw-rate: Yaw rate in degrees per second on format d.dd. Positive when bow is moving towards starboard.
vertical-vel: Vertical velocity in metres per second on format d.dd. Positive when moving downwards.
event: Event code: 1 = system restart.
csum: Checksum (exclusive or) of all characters between, but not including, the preceding $ and * , hexadecimal (00 - FF).
term: CR-LF (2 bytes, values 13 and 10).
with sample data:
'$PSXN,20,0,0,0,0*3B',
'$PSXN,23,0.30,-0.97,298.57,0.13*1B',
'$PSXN,26,0,44.5000,0.7800,-0.9000,NRP*6D',
So I created the following class:
class SXN(pynmea2.ProprietarySentence):
def __init__(self, manufacturer, data):
super(SXN, self).__init__(manufacturer, data)
self.sentence_type = data[1]
if self.sentence_type == '23':
SXN.fields = (
('Empty', '_'),
('sentence', 's'),
('roll', 'roll'),
('pitch', 'pitch'),
('head', 'head'),
('heave', 'heave')
)
SXN.name_to_idx = dict((f[1], i) for i, f in enumerate(SXN.fields))
This seems to work for the $PSXN,23 message, but as I think about supporting the others it seems kludgey. Is there a better approach?
The GNGST Sentence Type is unknown
I found that within the GRM.py file the number of fields was incorrect for the:
class GRME(GRM): """ GARMIN Estimated position error """ fields = ( ("Subtype", "subtype"), ("Estimated Horiz. Position Error", "hpe", Decimal), ("Estimated Horiz. Position Error Unit (M)", "hpe_unit"), ("Estimated Vert. Position Error", "vpe", Decimal), ("Estimated Vert. Position Error Unit (M)", "vpe_unit"), ("Estimated Horiz. Position Error", "osepe", Decimal), ("Overall Spherical Equiv. Position Error", "osepe_unit") )
Using the osepe_unit displaces the unit of horizontal position not the overal spherical eqv that is the next field over. I'm attempting to learn how to edit and recompile this so it works
I am getting lines like the following
$GPGGA,183800.0,3203.121,N,03446.075,E,1,03,4.90,00038,M,017,M,,*5A
$GPVTG,000.0,T,357.3,M,000.00,N,000.00,K*4C
from serial read of a trimble gps . I tried
streamreader = pynmea2.NMEAStreamReader()
while 1:
line = ser.readline().decode('ascii', errors='replace')
# print (line.strip())
print (line)
if line[0:6]=='$GPGGA':
msg = pynmea2.parse(line.strip())
print('msg1:'+str(msg))
for msg in streamreader.next(line.strip()):
print('msg:'+str(msg))
print('lat {} long {}'.format(msg.latitude,msg.longitude))
The pynmea2.parse spits back the input, while the streamreader.next does not get any msgs. Any clues?
Hi,
Would you be able to add an example of a script streaming and parsing a live feed from a pty or serial interface? I guess that is something many would use pynmea2 for. Excellent work by the way
when a file including some ascii data (likes GPGGA) and binarry data(maybe RANGEB),how the pynmea2 work?
In my try, pynmea2 match string at the beign,if I add any string, pynmea2 will match failed?
Have stumbled into several XDR sentences where the transducer name contains <space(s)>
i.e
$ERXDR,G,0,,SHD CANCEL*57
decoding this returns
{'units': '', 'type': 'G', 'id': 'SHD', 'value': '0'}
while the correct id should have been "SHD CANCEL"
The standard does not seem to specify (as far as i can see) if the space is an allowed character in the transducer name
XDR - Transducer Measurements
Measurement data from transducers that measure physical quantities such as temperature, force, pressure, frequency, angular or linear displacement, etc. Data from a variable number transducers measuring the same or different quantities can be mixed in the same sentence. This sentence is designed for use by integrated systems as well as transducers that may be connected in a 'chain' where each transducer receives the sentence as an input and adds its own data fields on before retransmitting the sentence.
$--XDR,a,x.x,a,c--c,...…………...a,x.x,a,c--c*hh
Transducer 'n'1 Data for variable # of transducers
Transducer #1 ID
Units of measure, Transducer #12
Measurement data, Transducer #1 Transducer type, Transducer #12
Notes:
Up to 'n' transducers may be included within the limits of allowed sentence length, null fields are not required except where portions of the 'Type-Data-Units-ID' combination are not available.
Transducer Type Field Units Field Comments temperature C C = degrees Celsius angular displacement A D = degrees "-" = anti-clockwise linear displacement D M = meters "-" = compression frequency F H = Hertz force N N = Newton "-" = compression pressure P B = Bars, P = Pascal "-" = vacuum flow rate R l = liters/second tachometer T R = RPM humidity H P = Percent volume V M = cubic meters generic G none (null) x.x = variable data current I A = Amperes voltage U V = Volts switch or valve S none (null) 1 = ON/ CLOSED, 0 = OFF/ OPEN salinity L S = ppt ppt = parts per thousand
class FSI(TalkerSentence):
""" Frequency Set Information
"""
fields = (
("Transmitting Frequency", "xmit_freq", Decimal),
("Receiving Frequency", "reciv_feq", Decimal),
("Communications Mode", "com_mode"),
("Power Level", "pwr_lvl"),
)
# FSI Frequency Set Information
# 1 2 3 4 5
# | | | | |
# $--FSI,xxxxxx,xxxxxx,c,x*hh
# 1) Transmitting Frequency
# 2) Receiving Frequency
# 3) Communications Mode (NMEA Syntax 2)
# 4) Power Level
# 5) Checksum
class GLC(TalkerSentence):
""" Geographic Position, Loran-C
"""
fields = (
("GRI Microseconds/10", "gri_ms", Decimal),
("Master TOA Microseconds", "toa_ms", float),
("Master TOA Signal Status", "toa_sig_stat"),
("Time Difference 1 Microseconds", "td_1_ms", float),
("Time Difference 1 Signal Status", "td_1_sig_stat"),
("Time Difference 2 Microseconds", "td_2_ms", float),
("Time Difference 2 Signal Status", "td_2_sig_stat"),
("Time Difference 3 Microseconds", "td_3_ms", float),
("Time Difference 3 Signal Status", "td_3_sig_stat"),
("Time Difference 4 Microseconds", "td_4_ms", float),
("Time Difference 4 Signal Status", "td_4_sig_stat"),
("Time Difference 5 Microseconds", "td_5_ms", float),
("Time Difference 5 Signal Status", "td_5_sig_stat"),
)
# GLC Geographic Position, Loran-C
# 12 14
# 1 2 3 4 5 6 7 8 9 10 11| 13|
# | | | | | | | | | | | | | |
# $--GLC,xxxx,x.x,a,x.x,a,x.x,a.x,x,a,x.x,a,x.x,a*hh
# 1) GRI Microseconds/10
# 2) Master TOA Microseconds
# 3) Master TOA Signal Status
# 4) Time Difference 1 Microseconds
# 5) Time Difference 1 Signal Status
# 6) Time Difference 2 Microseconds
# 7) Time Difference 2 Signal Status
# 8) Time Difference 3 Microseconds
# 9) Time Difference 3 Signal Status
# 10) Time Difference 4 Microseconds
# 11) Time Difference 4 Signal Status
# 12) Time Difference 5 Microseconds
# 13) Time Difference 5 Signal Status
# 14) Checksum
#
# GXA TRANSIT Position – Latitude/Longitude, Location and Time of TRANSIT Fix at Waypoint
# obsolete
class GXA(TalkerSentence):
""" TRANSIT Position
"""
fields = (
("UTC of position fix", 'timestamp', timestamp),
('Latitude', 'lat', float),
('Latitude Direction', 'lat_dir'),
('Longitude', 'lon', float),
('Longitude Direction', 'lon_dir'),
("Waypoint ID", ""),
("Satelite number", "sat_numb"),
)
# https://github.com/jcable/gpsd/www/NMEA.txt
# === GXA - TRANSIT Position - Latitude/Longitude ===
#
# Location and time of TRANSIT fix at waypoint
#
# ------------------------------------------------------------------------------
# 1 2 3 4 5 6 7 8
# | | | | | | | |
# $--GXA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,c--c,X*hh<CR><LF>
# ------------------------------------------------------------------------------
#
# Field Number:
#
# 1. UTC of position fix
# 2. Latitude
# 3. East or West
# 4. Longitude
# 5. North or South
# 6. Waypoint ID
# 7. Satelite number
# 8. Checksum
class LCD(TalkerSentence):
""" Loran-C Signal Data
"""
fields = (
("GRI Microseconds/10", "gri_ms", Decimal),
("Master Relative SNR", "snr", Decimal),
("Master Relative ECD", "ecd", Decimal),
("Time Difference 1 Microseconds", "td_1_ms", Decimal),
("Time Difference 1 Signal Status", "td_1_sig_stat", Decimal),
("Time Difference 2 Microseconds", "td_2_ms", Decimal),
("Time Difference 2 Signal Status", "td_2_sig_stat", Decimal),
("Time Difference 3 Microseconds", "td_3_ms", Decimal),
("Time Difference 3 Signal Status", "td_3_sig_stat", Decimal),
("Time Difference 4 Microseconds", "td_4_ms", Decimal),
("Time Difference 4 Signal Status", "td_4_sig_stat", Decimal),
("Time Difference 5 Microseconds", "td_5_ms", Decimal),
("Time Difference 5 Signal Status", "td_5_sig_stat", Decimal),
)
# LCD Loran-C Signal Data
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14
# | | | | | | | | | | | | | |
# $--LCD,xxxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx*hh
# 1) GRI Microseconds/10
# 2) Master Relative SNR
# 3) Master Relative ECD
# 4) Time Difference 1 Microseconds
# 5) Time Difference 1 Signal Status
# 6) Time Difference 2 Microseconds
# 7) Time Difference 2 Signal Status
# 8) Time Difference 3 Microseconds
# 9) Time Difference 3 Signal Status
# 10) Time Difference 4 Microseconds
# 11) Time Difference 4 Signal Status
# 12) Time Difference 5 Microseconds
# 13) Time Difference 5 Signal Status
# 14) Checksum
class MTA(TalkerSentence):
""" Air Temperature (to be phased out)
"""
fields = (
('Air temperature', 'temperature', float),
('Unit of measurement', 'units'),
)
# MTA Air Temperature (to be phased out) obsolete
# 1 2 3
# | | |
# $--MTW,x.x,C*hh
# 1) Degrees
# 2) Unit of Measurement, Celcius
# 3) Checksum
class OLN(TalkerSentence):
""" Omega Lane Numbers
"""
fields = (
("Omega Pair 1", "omg_pr_1"),
("Omega Pair 1 quontity", "omg_pr_1_qtu"),
("Omega Pair 1 total", "omg_pr_1_tot"),
("Omega Pair 2", "omg_pr_2"),
("Omega Pair 2 quontity", "omg_pr_2_qtu"),
("Omega Pair 2 total", "omg_pr_2_tot"),
("Omega Pair 3", "omg_pr_3"),
("Omega Pair 3 quontity", "omg_pr_3_qtu"),
("Omega Pair 3 total", "omg_pr_3_tot"),
)
# === OLN - Omega Lane Numbers ===
# (The OLN sentence is obsolete as of 2.30)
#
# ------------------------------------------------------------------------------
# 1 2 3 4
# |--------+ |--------+ |--------+ |
# $--OLN,aa,xxx,xxx,aa,xxx,xxx,aa,xxx,xxx*hh<CR><LF>
# ------------------------------------------------------------------------------
#
# Field Number:
#
# 1. Omega Pair 1
# 2. Omega Pair 1
# 3. Omega Pair 1
# 4. Checksum
class SFI(TalkerSentence):
""" Scanning Frequency Information
"""
fields = (
("Total number of messages", "total_num_msgs"),
("Message number", "msg_num"),
("Frequency 1", "freq"),
("Mode 1", "mode"),
)
# SFI Scanning Frequency Information
# 1 2 3 4 n
# | | | | |
# $--SFI,x.x,x.x,xxxxxx,c .......... xxxxxx,c*hh
# 1) Total Number Of Messages
# 2) Message Number
# 3) Frequency 1
# 4) Mode 1
# n) Checksum
class XTR(TalkerSentence):
""" Cross-Track Error, Dead Reckoning
"""
fields = (
("Magnitude of cross track error", "cross_track_error", float),
("Direction to steer, L or R", "l_r"), # L or R
("Units", "unit"), # N = Nautical Miles
)
# === XTR - Cross Track Error - Dead Reckoning ===
#
# ------------------------------------------------------------------------------
# 1 2 3 4
# | | | |
# $--XTR,x.x,a,N*hh<CR><LF>
# ------------------------------------------------------------------------------
#
# Field Number:
#
# 1. Magnitude of cross track error
# 2. Direction to steer, L or R
# 3. Units, N = Nautical Miles
# 4. Checksum
class ZFO(TalkerSentence):
""" UTC & Time from Origin Waypoint
"""
fields = (
("Time (UTC)", "timestamp", timestamp),
("Elapsed Time", "elap_time", timestamp),
("Origin Waypoint ID", "id"),
)
# ZFO UTC & Time from Origin Waypoint
# 1 2 3 4
# | | | |
# $--ZFO,hhmmss.ss,hhmmss.ss,c--c*hh
# 1) Time (UTC)
# 2) Elapsed Time
# 3) Origin Waypoint ID
# 4) Checksum
class ZTG(TalkerSentence):
""" UTC & Time to Destination Waypoint
"""
fields = (
("Time (UTC)", "timestamp", timestamp),
("Elapsed Time", "elap_time", timestamp),
("Destination Waypoint ID", "id"),
)
# ZTG UTC & Time to Destination Waypoint
# 1 2 3 4
# | | | |
# $--ZTG,hhmmss.ss,hhmmss.ss,c--c*hh
# 1) Time (UTC)
# 2) Time Remaining
# 3) Destination Waypoint ID
# 4) Checksum
Hi!
First of all thank you for your good work in this project, then...
msg = pynmea2.parse("$GPVTG,108.53,T,,M,0.04,N,0.07,K,A*31")
print msg.mag_track
File "./test.py", line 6, in <module>
print msg.mag_track
File "/usr/local/lib/python2.7/dist-packages/pynmea2/nmea.py", line 88, in __getattr__
return f[2](v)
File "/usr/lib/python2.7/decimal.py", line 548, in __new__
"Invalid literal for Decimal: %r" % value)
File "/usr/lib/python2.7/decimal.py", line 3866, in _raise_error
raise error(explanation)
decimal.InvalidOperation: Invalid literal for Decimal: ''
I think it would be better to check for empty data and return None or Decimal('NaN') rather that throwing and exception.
Thanks again.
I'm using a Dual XGPS160 and getting the following issue
Traceback (most recent call last):
File "./test.py", line 14, in <module>
msg = pynmea2.parse( data )
File "/Library/Python/2.7/site-packages/pynmea2/nmea.py", line 130, in parse
raise SentenceTypeError('Unknown sentence type %s' % sentence_type)
pynmea2.nmea.SentenceTypeError: Unknown sentence type GPPWR,
The sentence is:
$GPPWR,0922,1,0,0,0,00,0,S,97, 1 5 ,000*1F
Thanks,
Michael
I've tried ALOT already, but still nothing works or gives me the wanted results.
Currently I tried to read data usin the streamin docs, however, this throws
pynmea2.nmea.ParseError: ('could not parse data', u'*72\r')
I implemented it like this:
import serial
import pynmea2
ser = serial.Serial()
ser.port = "/dev/ttyS0"
ser.baudrate = 9600
ser.timeout = 1
ser.open()
reader = pynmea2.NMEAStreamReader()
while 1:
data = ser.readline()
for msg in reader.next(data):
print(msg)
Sometimes I get the sream to work, however, it's never ever instant.
I just want to have a continious stream of GPS data to be stored and displayed.
I need the latitude
, longitude
, speed
, time
, date
.
Someone please help me out here...
Hello, not sure if this is the correct way to share the problem I was having, but here goes. pip install pynmea2
seemed to work fine for installing pynmea2. But when I went to even import pynmea2
, I would get the error:
>>> import pynmea2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\WinPython-32bit-2.7.5.0\python-2.7.5\lib\site-packages\pynmea2\__init__.py", line 5, in <module>
from .types import *
ImportError: No module named types
Bizzare. It took me a bit of poking around the repo and looking at the install directory to find out that, lo and behold, I had no types
directory. I downloaded it and moved it into the right directory manually, and everything seems to work great. But pip didn't seem to get it right in the first place. This happened on both my Windows 8 install, and the install on my Beaglebone Black (vanilla Angstrom). I've got a workaround figured out, but it was a strange problem to come across.
It would be convenient to have default constructors for the NMEA types. When using pynmea2 for encoding NMEA messages we now have to provide constructor parameters which are already known to the NMEA types itself.
An example of how the default constructor would look like for the HDG type;
class HDG(TalkerSentence):
""" NOTE! This is a GUESS as I cannot find an actual spec
telling me the fields. Updates are welcome!
"""
fields = (
("Heading", "heading", Decimal),
("Deviation", "deviation", Decimal),
("Deviation Direction", "dev_dir"),
("Variation", "variation", Decimal),
("Variation Direction", "var_dir")
)
def __init__(self, talker=None, sentence_type=None, data=None):
if talker == None:
talker = 'HC'
if sentence_type == None:
sentence_type = 'HDG'
if data == None:
data = [''] * len(self.fields)
super(HDG, self).__init__(talker, sentence_type, data)
The usage would be as followed;
class NmeaTests(unittest.TestCase):
def testCreateHDG(self):
hdg = HDG()
hdg.heading = 180.0
hdg.deviation = 1.0
hdg.dev_dir = 'E'
hdg.variation = 90.0
hdg.var_dir = 'W'
msg = str(hdg)
self.assertEqual('$HCHDG,180.0,1.0,E,90.0,W*61', msg)
running pip install pynmea2
does not include the sub-packages in the install directory:
C:\Users\i7\Downloads\pynmea2>pip install pynmea2
Downloading/unpacking pynmea2
Downloading pynmea2-1.1.1.tar.gz
Running setup.py (path:c:\windows\temp\pip_build_i7\pynmea2\setup.py) egg_info for package pynmea2
Installing collected packages: pynmea2
Running setup.py install for pynmea2
Successfully installed pynmea2
Cleaning up...
C:\Users\i7\Downloads\pynmea2>ls -l C:\Python27\Lib\site-packages\pynmea2
total 27
-rw-r--r-- 1 i7 Administrators 203 Mar 21 10:39 __init__.py
-rw-r--r-- 1 i7 Administrators 419 Mar 21 10:39 __init__.pyc
-rw-r--r-- 1 i7 Administrators 23 Mar 21 10:39 _version.py
-rw-r--r-- 1 i7 Administrators 168 Mar 21 10:39 _version.pyc
-rw-r--r-- 1 i7 Administrators 6427 Mar 21 10:39 nmea.py
-rw-r--r-- 1 i7 Administrators 7826 Mar 21 10:39 nmea.pyc
-rw-r--r-- 1 i7 Administrators 1561 Mar 21 10:39 nmea_utils.py
-rw-r--r-- 1 i7 Administrators 2447 Mar 21 10:39 nmea_utils.pyc
-rw-r--r-- 1 i7 Administrators 989 Mar 21 10:39 stream.py
-rw-r--r-- 1 i7 Administrators 1504 Mar 21 10:39 stream.pyc
By accident I've found out that at least some instances of ProprietarySentences are picklable, but cannot be unpickled due to the way their constructor works (detected on Python 3.4.3 with Pickle Protocol 4 and SRF156 sentence).
Unfortunately I didn't have much opportunity to analyze further, but as the standard sentences are perfectly picklable, I think it could be considered as a bug.
I actually testing with a small usb device that give GPS, but didnt work the streamer with python 3.8, although with python2 works like a charm..
My code:
import serial
import pynmea2
ser = serial.Serial()
ser.port = "/dev/ttyUSB0"
ser.baudrate = 4800
ser.timeout = 1
ser.open()
reader = pynmea2.NMEAStreamReader()
while 1:
data = ser.readline()
for msg in reader.next(data):
print(msg)
With python3.8:
Traceback (most recent call last): File "gps_test1.py", line 14, in <module> for msg in reader.next(data): File "/usr/lib/python3.8/site-packages/pynmea2/stream.py", line 48, in next lines = (self.buffer + data).split('\n') TypeError: can only concatenate str (not "bytes") to str
With python2:
$GPGGA,182116.305,,,,,0,00,,,M,0.0,M,,0000*5D $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPGSV,3,1,12,12,79,291,30,15,61,117,,24,47,001,,18,38,260,*7A
Any idea or fix?
Currently, at least the GPRMC
message is parsed into both a datetime.datetime()
object that only contains the date, with a time of 0:0, and a datetime.time()
object that encapsulates the actual time.
This is confusing. If you really want to have separate objects for the date and the time (and if so, why?), the date should be a date()
object, rather then a datetime()
object.
While trying to install pynmea2
via anaconda 4.5.9 on Arch Linux I get the following error:
$ conda install -c knio pynmea2
Solving environment: failed
CondaHTTPError: HTTP 404 NOT FOUND for url <https://conda.anaconda.org/knio/noarch/repodata.json>
Elapsed: 00:00.093323
CF-RAY: 445b49fa0a385a62-BOS
The remote server could not find the noarch directory for the
requested channel with url: https://conda.anaconda.org/knio
As of conda 4.3, a valid channel must contain a `noarch/repodata.json` and
associated `noarch/repodata.json.bz2` file, even if `noarch/repodata.json` is
empty. please request that the channel administrator create
`noarch/repodata.json` and associated `noarch/repodata.json.bz2` files.
$ mkdir noarch
$ echo '{}' > noarch/repodata.json
$ bzip2 -k noarch/repodata.json
You will need to adjust your conda configuration to proceed.
Use `conda config --show channels` to view your configuration's current state.
Further configuration help can be found at <https://conda.io/docs/config.html>.
I will try pip install
but would prefer the conda method as it gives tighter environment control.
My NMEA stream contains AIS messages in the following format:
!AIVDM,1,1,,A,ENkb9ONaR@@@@@@@@@@@@@@@@@@;kaD09EE>`00003vP000,4*2C
When I try to parse this message I get a ParseError.
Any way to enable parsing AIS messages?
I'm using this library with an Airmar 200WX weather station. (Thank you!) It doesn't transmit proprietary data sentences, but does have set/query commands. For example:
I started writing the code for these sentences and think I've realized it will probably require new sentence classes. Also, the manufacturer code needs to go 3 -> 4 characters. What else should be considered?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.