Iterate through a Talker Sentence
montge opened this issue · comments
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!
Hi,
This was an unanticipated usage, and I realize there is no nice, documented API for it. Thanks for pointing this out.
Here is one way to do this today:
msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")
fields = {k: getattr(msg, k) for k in msg.name_to_idx}
print(fields)
Output:
{'timestamp': datetime.time(18, 43, 53, 70000), 'lat': '1929.045', 'lat_dir': 'S', 'lon': '02410.506', 'lon_dir': 'E', 'gps_qual': 1, 'num_sats': '04', 'horizontal_dil': '2.6', 'altitude': 100.0, 'altitude_units': 'M', 'geo_sep': '-33.9', 'geo_sep_units': 'M', 'age_gps_data': '', 'ref_station_id': '0000'}
Note that not all NMEA messages map cleanly to key-value pairs, and some types will have extra data that will not appear in fields
there. See nmea.py:180
(__repr__
) as a further example.
I will leave this ticket open for myself to create a better public facing API for this usage.
Thanks! Might suggest just adding it to the example code.
There are fields like latitude
, longitude
, datetime
, etc. (i.e. those on mixins) that are dynamic properties and don't show on name_to_idx
. It would be nice to consider them, if possible, in that future new API...