Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterate through a Talker Sentence #85

Open
montge opened this issue Mar 4, 2019 · 3 comments
Open

Iterate through a Talker Sentence #85

montge opened this issue Mar 4, 2019 · 3 comments

Comments

@montge
Copy link

montge commented Mar 4, 2019

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!

@Knio
Copy link
Owner

Knio commented Mar 5, 2019

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.

@montge
Copy link
Author

montge commented Mar 5, 2019

Thanks! Might suggest just adding it to the example code.

@xOneca
Copy link
Contributor

xOneca commented Mar 19, 2019

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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants